copy_unix.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package dockerfile
  2. import (
  3. "os"
  4. "path/filepath"
  5. "github.com/docker/docker/pkg/idtools"
  6. )
  7. func pathExists(path string) (bool, error) {
  8. _, err := os.Stat(path)
  9. switch {
  10. case err == nil:
  11. return true, nil
  12. case os.IsNotExist(err):
  13. return false, nil
  14. }
  15. return false, err
  16. }
  17. // TODO: review this
  18. func fixPermissions(source, destination string, rootIDs idtools.IDPair) error {
  19. doChownDestination, err := chownDestinationRoot(destination)
  20. if err != nil {
  21. return err
  22. }
  23. // We Walk on the source rather than on the destination because we don't
  24. // want to change permissions on things we haven't created or modified.
  25. return filepath.Walk(source, func(fullpath string, info os.FileInfo, err error) error {
  26. // Do not alter the walk root iff. it existed before, as it doesn't fall under
  27. // the domain of "things we should chown".
  28. if !doChownDestination && (source == fullpath) {
  29. return nil
  30. }
  31. // Path is prefixed by source: substitute with destination instead.
  32. cleaned, err := filepath.Rel(source, fullpath)
  33. if err != nil {
  34. return err
  35. }
  36. fullpath = filepath.Join(destination, cleaned)
  37. return os.Lchown(fullpath, rootIDs.UID, rootIDs.GID)
  38. })
  39. }
  40. // If the destination didn't already exist, or the destination isn't a
  41. // directory, then we should Lchown the destination. Otherwise, we shouldn't
  42. // Lchown the destination.
  43. func chownDestinationRoot(destination string) (bool, error) {
  44. destExists, err := pathExists(destination)
  45. if err != nil {
  46. return false, err
  47. }
  48. destStat, err := os.Stat(destination)
  49. if err != nil {
  50. // This should *never* be reached, because the destination must've already
  51. // been created while untar-ing the context.
  52. return false, err
  53. }
  54. return !destExists || !destStat.IsDir(), nil
  55. }