github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/pkg/archive/archive_linux.go (about) 1 package archive 2 3 import ( 4 "archive/tar" 5 "os" 6 "path/filepath" 7 "strings" 8 "syscall" 9 10 "github.com/docker/docker/pkg/system" 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) 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 err 38 } 39 if opaque != nil && len(opaque) == 1 && opaque[0] == 'y' { 40 // create a header for the whiteout file 41 // it should inherit some properties from the parent, but be a regular file 42 *hdr = tar.Header{ 43 Typeflag: tar.TypeReg, 44 Mode: hdr.Mode & int64(os.ModePerm), 45 Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir), 46 Size: 0, 47 Uid: hdr.Uid, 48 Uname: hdr.Uname, 49 Gid: hdr.Gid, 50 Gname: hdr.Gname, 51 AccessTime: hdr.AccessTime, 52 ChangeTime: hdr.ChangeTime, 53 } 54 } 55 } 56 57 return nil 58 } 59 60 func (overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) { 61 base := filepath.Base(path) 62 dir := filepath.Dir(path) 63 64 // if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay 65 if base == WhiteoutOpaqueDir { 66 if err := syscall.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0); err != nil { 67 return false, err 68 } 69 70 // don't write the file itself 71 return false, nil 72 } 73 74 // if a file was deleted and we are using overlay, we need to create a character device 75 if strings.HasPrefix(base, WhiteoutPrefix) { 76 originalBase := base[len(WhiteoutPrefix):] 77 originalPath := filepath.Join(dir, originalBase) 78 79 if err := syscall.Mknod(originalPath, syscall.S_IFCHR, 0); err != nil { 80 return false, err 81 } 82 if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil { 83 return false, err 84 } 85 86 // don't write the file itself 87 return false, nil 88 } 89 90 return true, nil 91 }