github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/container/archive.go (about) 1 package container // import "github.com/demonoid81/moby/container" 2 3 import ( 4 "os" 5 6 "github.com/demonoid81/moby/api/types" 7 "github.com/demonoid81/moby/pkg/archive" 8 "github.com/demonoid81/moby/pkg/system" 9 "github.com/pkg/errors" 10 ) 11 12 // ResolvePath resolves the given path in the container to a resource on the 13 // host. Returns a resolved path (absolute path to the resource on the host), 14 // the absolute path to the resource relative to the container's rootfs, and 15 // an error if the path points to outside the container's rootfs. 16 func (container *Container) ResolvePath(path string) (resolvedPath, absPath string, err error) { 17 if container.BaseFS == nil { 18 return "", "", errors.New("ResolvePath: BaseFS of container " + container.ID + " is unexpectedly nil") 19 } 20 // Check if a drive letter supplied, it must be the system drive. No-op except on Windows 21 path, err = system.CheckSystemDriveAndRemoveDriveLetter(path, container.BaseFS) 22 if err != nil { 23 return "", "", err 24 } 25 26 // Consider the given path as an absolute path in the container. 27 absPath = archive.PreserveTrailingDotOrSeparator( 28 container.BaseFS.Join(string(container.BaseFS.Separator()), path), 29 path, 30 container.BaseFS.Separator()) 31 32 // Split the absPath into its Directory and Base components. We will 33 // resolve the dir in the scope of the container then append the base. 34 dirPath, basePath := container.BaseFS.Split(absPath) 35 36 resolvedDirPath, err := container.GetResourcePath(dirPath) 37 if err != nil { 38 return "", "", err 39 } 40 41 // resolvedDirPath will have been cleaned (no trailing path separators) so 42 // we can manually join it with the base path element. 43 resolvedPath = resolvedDirPath + string(container.BaseFS.Separator()) + basePath 44 return resolvedPath, absPath, nil 45 } 46 47 // StatPath is the unexported version of StatPath. Locks and mounts should 48 // be acquired before calling this method and the given path should be fully 49 // resolved to a path on the host corresponding to the given absolute path 50 // inside the container. 51 func (container *Container) StatPath(resolvedPath, absPath string) (stat *types.ContainerPathStat, err error) { 52 if container.BaseFS == nil { 53 return nil, errors.New("StatPath: BaseFS of container " + container.ID + " is unexpectedly nil") 54 } 55 driver := container.BaseFS 56 57 lstat, err := driver.Lstat(resolvedPath) 58 if err != nil { 59 return nil, err 60 } 61 62 var linkTarget string 63 if lstat.Mode()&os.ModeSymlink != 0 { 64 // Fully evaluate the symlink in the scope of the container rootfs. 65 hostPath, err := container.GetResourcePath(absPath) 66 if err != nil { 67 return nil, err 68 } 69 70 linkTarget, err = driver.Rel(driver.Path(), hostPath) 71 if err != nil { 72 return nil, err 73 } 74 75 // Make it an absolute path. 76 linkTarget = driver.Join(string(driver.Separator()), linkTarget) 77 } 78 79 return &types.ContainerPathStat{ 80 Name: driver.Base(absPath), 81 Size: lstat.Size(), 82 Mode: lstat.Mode(), 83 Mtime: lstat.ModTime(), 84 LinkTarget: linkTarget, 85 }, nil 86 }