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