github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/container/archive_windows.go (about)

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