archive.go 2.6 KB

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