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