github.com/docker/docker-ce@v17.12.1-ce-rc2+incompatible/components/engine/container/archive.go (about)

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