MCPcopy Create free account
hub / github.com/containerd/nerdctl / CopyFiles

Function CopyFiles

pkg/containerutil/cp_linux.go:88–361  ·  view source on GitHub ↗

CopyFiles implements `nerdctl cp` It currently depends on the following assumptions: - linux only - tar binary exists on the system - nsenter binary exists on the system - if rootless, the container is running (aka: /proc/pid/root)

(ctx context.Context, client *containerd.Client, container containerd.Container, options types.ContainerCpOptions)

Source from the content-addressed store, hash-verified

86// - nsenter binary exists on the system
87// - if rootless, the container is running (aka: /proc/pid/root)
88func CopyFiles(ctx context.Context, client *containerd.Client, container containerd.Container, options types.ContainerCpOptions) (err error) {
89 // We do rely on the tar binary as a shortcut - could also be replaced by archive/tar, though that would mean
90 // we need to replace nsenter calls with re-exec
91 tarBinary, isGNUTar, err := tarutil.FindTarBinary()
92 if err != nil {
93 return err
94 }
95
96 log.G(ctx).Debugf("Detected tar binary %q (GNU=%v)", tarBinary, isGNUTar)
97
98 // This can happen if the container being passed has been deleted since in a racy way
99 conSpec, err := container.Spec(ctx)
100 if err != nil {
101 return errors.Join(ErrContainerVanished, err)
102 }
103
104 // Try to get a running container root
105 root, pid, err := getRoot(ctx, container)
106 // If the task is "not found" (for example, if the container stopped), we will try to mount the snapshot
107 // Any other type of error from Task() is fatal here.
108 if err != nil && !errdefs.IsNotFound(err) {
109 return errors.Join(ErrContainerVanished, err)
110 }
111
112 log.G(ctx).Debugf("We have root %s and pid %d", root, pid)
113
114 // If we have no root:
115 // - bail out for rootless
116 // - mount the snapshot for rootful
117 if root == "" {
118 // FIXME: Rootless does not support copying into/out of stopped/created containers as we need to nsenter into
119 // the user namespace of the pid of the running container with --preserve-credentials to preserve uid/gid
120 // mapping and copy files into the container.
121 if rootlessutil.IsRootless() {
122 return ErrRootlessCannotCp
123 }
124
125 // See similar situation above. This may happen if we are racing against container deletion
126 var conInfo containers.Container
127 conInfo, err = container.Info(ctx)
128 if err != nil {
129 return errors.Join(ErrContainerVanished, err)
130 }
131
132 var cleanup func() error
133 root, cleanup, err = mountSnapshotForContainer(ctx, client, conInfo, options.GOptions.Snapshotter)
134 if cleanup != nil {
135 defer func() {
136 err = errors.Join(err, cleanup())
137 }()
138 }
139
140 if err != nil {
141 return errors.Join(ErrFailedMountingSnapshot, err)
142 }
143
144 log.G(ctx).Debugf("Got new root %s", root)
145 }

Callers 1

CpFunction · 0.92

Calls 12

FindTarBinaryFunction · 0.92
IsRootlessFunction · 0.92
getRootFunction · 0.85
getPathSpecFromContainerFunction · 0.85
getPathSpecFromHostFunction · 0.85
InfoMethod · 0.80
StartMethod · 0.80
DirMethod · 0.65
ErrorMethod · 0.45
StringMethod · 0.45
WaitMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…