github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/pkg/archive/archive_unix.go (about) 1 // +build !windows 2 3 package archive // import "github.com/demonoid81/moby/pkg/archive" 4 5 import ( 6 "archive/tar" 7 "errors" 8 "os" 9 "path/filepath" 10 "strings" 11 "syscall" 12 13 "github.com/demonoid81/moby/pkg/idtools" 14 "github.com/demonoid81/moby/pkg/system" 15 rsystem "github.com/opencontainers/runc/libcontainer/system" 16 "golang.org/x/sys/unix" 17 ) 18 19 // fixVolumePathPrefix does platform specific processing to ensure that if 20 // the path being passed in is not in a volume path format, convert it to one. 21 func fixVolumePathPrefix(srcPath string) string { 22 return srcPath 23 } 24 25 // getWalkRoot calculates the root path when performing a TarWithOptions. 26 // We use a separate function as this is platform specific. On Linux, we 27 // can't use filepath.Join(srcPath,include) because this will clean away 28 // a trailing "." or "/" which may be important. 29 func getWalkRoot(srcPath string, include string) string { 30 return strings.TrimSuffix(srcPath, string(filepath.Separator)) + string(filepath.Separator) + include 31 } 32 33 // CanonicalTarNameForPath returns platform-specific filepath 34 // to canonical posix-style path for tar archival. p is relative 35 // path. 36 func CanonicalTarNameForPath(p string) string { 37 return p // already unix-style 38 } 39 40 // chmodTarEntry is used to adjust the file permissions used in tar header based 41 // on the platform the archival is done. 42 43 func chmodTarEntry(perm os.FileMode) os.FileMode { 44 return perm // noop for unix as golang APIs provide perm bits correctly 45 } 46 47 func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) (err error) { 48 s, ok := stat.(*syscall.Stat_t) 49 50 if ok { 51 // Currently go does not fill in the major/minors 52 if s.Mode&unix.S_IFBLK != 0 || 53 s.Mode&unix.S_IFCHR != 0 { 54 hdr.Devmajor = int64(unix.Major(uint64(s.Rdev))) // nolint: unconvert 55 hdr.Devminor = int64(unix.Minor(uint64(s.Rdev))) // nolint: unconvert 56 } 57 } 58 59 return 60 } 61 62 func getInodeFromStat(stat interface{}) (inode uint64, err error) { 63 s, ok := stat.(*syscall.Stat_t) 64 65 if ok { 66 inode = s.Ino 67 } 68 69 return 70 } 71 72 func getFileUIDGID(stat interface{}) (idtools.Identity, error) { 73 s, ok := stat.(*syscall.Stat_t) 74 75 if !ok { 76 return idtools.Identity{}, errors.New("cannot convert stat value to syscall.Stat_t") 77 } 78 return idtools.Identity{UID: int(s.Uid), GID: int(s.Gid)}, nil 79 } 80 81 // handleTarTypeBlockCharFifo is an OS-specific helper function used by 82 // createTarFile to handle the following types of header: Block; Char; Fifo 83 func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { 84 if rsystem.RunningInUserNS() { 85 // cannot create a device if running in user namespace 86 return nil 87 } 88 89 mode := uint32(hdr.Mode & 07777) 90 switch hdr.Typeflag { 91 case tar.TypeBlock: 92 mode |= unix.S_IFBLK 93 case tar.TypeChar: 94 mode |= unix.S_IFCHR 95 case tar.TypeFifo: 96 mode |= unix.S_IFIFO 97 } 98 99 return system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))) 100 } 101 102 func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { 103 if hdr.Typeflag == tar.TypeLink { 104 if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { 105 if err := os.Chmod(path, hdrInfo.Mode()); err != nil { 106 return err 107 } 108 } 109 } else if hdr.Typeflag != tar.TypeSymlink { 110 if err := os.Chmod(path, hdrInfo.Mode()); err != nil { 111 return err 112 } 113 } 114 return nil 115 }