github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/daemon/containerd/image_snapshot_unix.go (about)

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