image_snapshot_unix.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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/log"
  10. "github.com/containerd/containerd/mount"
  11. "github.com/containerd/containerd/snapshots"
  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. }