github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/pkg/archive/archive_linux.go (about)

     1  //go:build !wasip1
     2  
     3  package archive // import "github.com/Prakhar-Agarwal-byte/moby/pkg/archive"
     4  
     5  import (
     6  	"archive/tar"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/Prakhar-Agarwal-byte/moby/pkg/system"
    12  	"github.com/pkg/errors"
    13  	"golang.org/x/sys/unix"
    14  )
    15  
    16  func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) (tarWhiteoutConverter, error) {
    17  	if format == OverlayWhiteoutFormat {
    18  		if inUserNS {
    19  			return nil, errors.New("specifying OverlayWhiteoutFormat is not allowed in userns")
    20  		}
    21  		return overlayWhiteoutConverter{}, nil
    22  	}
    23  	return nil, nil
    24  }
    25  
    26  type overlayWhiteoutConverter struct{}
    27  
    28  func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) {
    29  	// convert whiteouts to AUFS format
    30  	if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 {
    31  		// we just rename the file and make it normal
    32  		dir, filename := filepath.Split(hdr.Name)
    33  		hdr.Name = filepath.Join(dir, WhiteoutPrefix+filename)
    34  		hdr.Mode = 0o600
    35  		hdr.Typeflag = tar.TypeReg
    36  		hdr.Size = 0
    37  	}
    38  
    39  	if fi.Mode()&os.ModeDir != 0 {
    40  		// convert opaque dirs to AUFS format by writing an empty file with the prefix
    41  		opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
    42  		if err != nil {
    43  			return nil, err
    44  		}
    45  		if len(opaque) == 1 && opaque[0] == 'y' {
    46  			delete(hdr.PAXRecords, paxSchilyXattr+"trusted.overlay.opaque")
    47  
    48  			// create a header for the whiteout file
    49  			// it should inherit some properties from the parent, but be a regular file
    50  			wo = &tar.Header{
    51  				Typeflag:   tar.TypeReg,
    52  				Mode:       hdr.Mode & int64(os.ModePerm),
    53  				Name:       filepath.Join(hdr.Name, WhiteoutOpaqueDir),
    54  				Size:       0,
    55  				Uid:        hdr.Uid,
    56  				Uname:      hdr.Uname,
    57  				Gid:        hdr.Gid,
    58  				Gname:      hdr.Gname,
    59  				AccessTime: hdr.AccessTime,
    60  				ChangeTime: hdr.ChangeTime,
    61  			} //#nosec G305 -- An archive is being created, not extracted.
    62  		}
    63  	}
    64  
    65  	return
    66  }
    67  
    68  func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) {
    69  	base := filepath.Base(path)
    70  	dir := filepath.Dir(path)
    71  
    72  	// if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay
    73  	if base == WhiteoutOpaqueDir {
    74  		err := unix.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0)
    75  		if err != nil {
    76  			return false, errors.Wrapf(err, "setxattr(%q, trusted.overlay.opaque=y)", dir)
    77  		}
    78  		// don't write the file itself
    79  		return false, err
    80  	}
    81  
    82  	// if a file was deleted and we are using overlay, we need to create a character device
    83  	if strings.HasPrefix(base, WhiteoutPrefix) {
    84  		originalBase := base[len(WhiteoutPrefix):]
    85  		originalPath := filepath.Join(dir, originalBase)
    86  
    87  		if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil {
    88  			return false, errors.Wrapf(err, "failed to mknod(%q, S_IFCHR, 0)", originalPath)
    89  		}
    90  		if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil {
    91  			return false, err
    92  		}
    93  
    94  		// don't write the file itself
    95  		return false, nil
    96  	}
    97  
    98  	return true, nil
    99  }