container/archive.go
4f0d95fa
 package container // import "github.com/docker/docker/container"
6bb0d181
 
 import (
 	"os"
 
91e197d6
 	"github.com/docker/docker/api/types"
6bb0d181
 	"github.com/docker/docker/pkg/archive"
7f665985
 	"github.com/docker/docker/pkg/system"
d6ea46ce
 	"github.com/pkg/errors"
6bb0d181
 )
 
 // ResolvePath resolves the given path in the container to a resource on the
 // host. Returns a resolved path (absolute path to the resource on the host),
 // the absolute path to the resource relative to the container's rootfs, and
6983f05b
 // an error if the path points to outside the container's rootfs.
6bb0d181
 func (container *Container) ResolvePath(path string) (resolvedPath, absPath string, err error) {
d6ea46ce
 	if container.BaseFS == nil {
 		return "", "", errors.New("ResolvePath: BaseFS of container " + container.ID + " is unexpectedly nil")
 	}
7f665985
 	// Check if a drive letter supplied, it must be the system drive. No-op except on Windows
7a7357da
 	path, err = system.CheckSystemDriveAndRemoveDriveLetter(path, container.BaseFS)
7f665985
 	if err != nil {
 		return "", "", err
 	}
 
6bb0d181
 	// Consider the given path as an absolute path in the container.
7a7357da
 	absPath = archive.PreserveTrailingDotOrSeparator(
 		container.BaseFS.Join(string(container.BaseFS.Separator()), path),
 		path,
 		container.BaseFS.Separator())
6bb0d181
 
 	// Split the absPath into its Directory and Base components. We will
 	// resolve the dir in the scope of the container then append the base.
7a7357da
 	dirPath, basePath := container.BaseFS.Split(absPath)
6bb0d181
 
 	resolvedDirPath, err := container.GetResourcePath(dirPath)
 	if err != nil {
 		return "", "", err
 	}
 
 	// resolvedDirPath will have been cleaned (no trailing path separators) so
 	// we can manually join it with the base path element.
7a7357da
 	resolvedPath = resolvedDirPath + string(container.BaseFS.Separator()) + basePath
6bb0d181
 	return resolvedPath, absPath, nil
 }
 
 // StatPath is the unexported version of StatPath. Locks and mounts should
 // be acquired before calling this method and the given path should be fully
 // resolved to a path on the host corresponding to the given absolute path
 // inside the container.
 func (container *Container) StatPath(resolvedPath, absPath string) (stat *types.ContainerPathStat, err error) {
d6ea46ce
 	if container.BaseFS == nil {
 		return nil, errors.New("StatPath: BaseFS of container " + container.ID + " is unexpectedly nil")
 	}
7a7357da
 	driver := container.BaseFS
 
 	lstat, err := driver.Lstat(resolvedPath)
6bb0d181
 	if err != nil {
 		return nil, err
 	}
 
 	var linkTarget string
 	if lstat.Mode()&os.ModeSymlink != 0 {
 		// Fully evaluate the symlink in the scope of the container rootfs.
 		hostPath, err := container.GetResourcePath(absPath)
 		if err != nil {
 			return nil, err
 		}
 
7a7357da
 		linkTarget, err = driver.Rel(driver.Path(), hostPath)
6bb0d181
 		if err != nil {
 			return nil, err
 		}
 
 		// Make it an absolute path.
7a7357da
 		linkTarget = driver.Join(string(driver.Separator()), linkTarget)
6bb0d181
 	}
 
 	return &types.ContainerPathStat{
7a7357da
 		Name:       driver.Base(absPath),
6bb0d181
 		Size:       lstat.Size(),
 		Mode:       lstat.Mode(),
 		Mtime:      lstat.ModTime(),
 		LinkTarget: linkTarget,
 	}, nil
 }