archive.go 2.5 KB

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