image_snapshot_unix.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. //go:build !windows
  2. package containerd
  3. import (
  4. "context"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "syscall"
  9. "github.com/containerd/containerd/mount"
  10. "github.com/containerd/containerd/snapshots"
  11. "github.com/containerd/log"
  12. "github.com/docker/docker/pkg/idtools"
  13. )
  14. func (i *ImageService) remapSnapshot(ctx context.Context, snapshotter snapshots.Snapshotter, id string, parentSnapshot string) error {
  15. rootPair := i.idMapping.RootPair()
  16. usernsID := fmt.Sprintf("%s-%d-%d", parentSnapshot, rootPair.UID, rootPair.GID)
  17. remappedID := usernsID + remapSuffix
  18. // If the remapped snapshot already exist we only need to prepare the new snapshot
  19. if _, err := snapshotter.Stat(ctx, usernsID); err == nil {
  20. _, err = snapshotter.Prepare(ctx, id, usernsID)
  21. return err
  22. }
  23. mounts, err := snapshotter.Prepare(ctx, remappedID, parentSnapshot)
  24. if err != nil {
  25. return err
  26. }
  27. if err := i.remapRootFS(ctx, mounts); err != nil {
  28. if rmErr := snapshotter.Remove(ctx, usernsID); rmErr != nil {
  29. log.G(ctx).WithError(rmErr).Warn("failed to remove snapshot after remap error")
  30. }
  31. return err
  32. }
  33. if err := snapshotter.Commit(ctx, usernsID, remappedID); err != nil {
  34. return err
  35. }
  36. _, err = snapshotter.Prepare(ctx, id, usernsID)
  37. return err
  38. }
  39. func (i *ImageService) remapRootFS(ctx context.Context, mounts []mount.Mount) error {
  40. return mount.WithTempMount(ctx, mounts, func(root string) error {
  41. return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
  42. if err != nil {
  43. return err
  44. }
  45. stat := info.Sys().(*syscall.Stat_t)
  46. if stat == nil {
  47. return fmt.Errorf("cannot get underlying data for %s", path)
  48. }
  49. ids, err := i.idMapping.ToHost(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
  50. if err != nil {
  51. return err
  52. }
  53. return os.Lchown(path, ids.UID, ids.GID)
  54. })
  55. })
  56. }
  57. func (i *ImageService) unremapRootFS(ctx context.Context, mounts []mount.Mount) error {
  58. return mount.WithTempMount(ctx, mounts, func(root string) error {
  59. return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
  60. if err != nil {
  61. return err
  62. }
  63. stat := info.Sys().(*syscall.Stat_t)
  64. if stat == nil {
  65. return fmt.Errorf("cannot get underlying data for %s", path)
  66. }
  67. uid, gid, err := i.idMapping.ToContainer(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
  68. if err != nil {
  69. return err
  70. }
  71. return os.Lchown(path, uid, gid)
  72. })
  73. })
  74. }