github.com/lacework-dev/go-moby@v20.10.12+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 27 func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) { 28 // convert whiteouts to AUFS format 29 if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 { 30 // we just rename the file and make it normal 31 dir, filename := filepath.Split(hdr.Name) 32 hdr.Name = filepath.Join(dir, WhiteoutPrefix+filename) 33 hdr.Mode = 0600 34 hdr.Typeflag = tar.TypeReg 35 hdr.Size = 0 36 } 37 38 if fi.Mode()&os.ModeDir != 0 { 39 // convert opaque dirs to AUFS format by writing an empty file with the prefix 40 opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque") 41 if err != nil { 42 return nil, err 43 } 44 if len(opaque) == 1 && opaque[0] == 'y' { 45 if hdr.Xattrs != nil { 46 delete(hdr.Xattrs, "trusted.overlay.opaque") 47 } 48 49 // create a header for the whiteout file 50 // it should inherit some properties from the parent, but be a regular file 51 wo = &tar.Header{ 52 Typeflag: tar.TypeReg, 53 Mode: hdr.Mode & int64(os.ModePerm), 54 Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir), 55 Size: 0, 56 Uid: hdr.Uid, 57 Uname: hdr.Uname, 58 Gid: hdr.Gid, 59 Gname: hdr.Gname, 60 AccessTime: hdr.AccessTime, 61 ChangeTime: hdr.ChangeTime, 62 } 63 } 64 } 65 66 return 67 } 68 69 func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) { 70 base := filepath.Base(path) 71 dir := filepath.Dir(path) 72 73 // if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay 74 if base == WhiteoutOpaqueDir { 75 err := unix.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0) 76 if err != nil { 77 return false, errors.Wrapf(err, "setxattr(%q, trusted.overlay.opaque=y)", dir) 78 } 79 // don't write the file itself 80 return false, err 81 } 82 83 // if a file was deleted and we are using overlay, we need to create a character device 84 if strings.HasPrefix(base, WhiteoutPrefix) { 85 originalBase := base[len(WhiteoutPrefix):] 86 originalPath := filepath.Join(dir, originalBase) 87 88 if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil { 89 return false, errors.Wrapf(err, "failed to mknod(%q, S_IFCHR, 0)", originalPath) 90 } 91 if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil { 92 return false, err 93 } 94 95 // don't write the file itself 96 return false, nil 97 } 98 99 return true, nil 100 }