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