archive_windows.go 2.8 KB

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