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