MCPcopy Index your code
hub / github.com/docker/cli / copyToContainer

Function copyToContainer

cli/command/container/cp.go:355–484  ·  view source on GitHub ↗

In order to get the copy behavior right, we need to know information about both the source and destination. The API is a simple tar archive/extract API but we can use the stat info header about the destination to be more informed about exactly what the destination is.

(ctx context.Context, dockerCLI command.Cli, copyConfig cpConfig)

Source from the content-addressed store, hash-verified

353// archive/extract API but we can use the stat info header about the
354// destination to be more informed about exactly what the destination is.
355func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpConfig) error {
356 srcPath := copyConfig.sourcePath
357 dstPath := copyConfig.destPath
358
359 if srcPath != "-" {
360 // Get an absolute source path.
361 p, err := resolveLocalPath(srcPath)
362 if err != nil {
363 return err
364 }
365 srcPath = p
366 }
367
368 apiClient := dockerCLI.Client()
369 // Prepare destination copy info by stat-ing the container path.
370 dstInfo := archive.CopyInfo{Path: dstPath}
371 if dst, err := apiClient.ContainerStatPath(ctx, copyConfig.container, client.ContainerStatPathOptions{Path: dstPath}); err == nil {
372 // If the destination is a symbolic link, we should evaluate it.
373 if dst.Stat.Mode&os.ModeSymlink != 0 {
374 linkTarget := dst.Stat.LinkTarget
375 if !isAbs(linkTarget) {
376 // Join with the parent directory.
377 dstParent, _ := archive.SplitPathDirEntry(dstPath)
378 linkTarget = filepath.Join(dstParent, linkTarget)
379 }
380
381 dstInfo.Path = linkTarget
382 dst, err = apiClient.ContainerStatPath(ctx, copyConfig.container, client.ContainerStatPathOptions{Path: linkTarget})
383 }
384 // Validate the destination path
385 if err == nil {
386 if err := command.ValidateOutputPathFileMode(dst.Stat.Mode); err != nil {
387 return fmt.Errorf(`destination "%s:%s" must be a directory or a regular file: %w`, copyConfig.container, dstPath, err)
388 }
389 dstInfo.Exists, dstInfo.IsDir = true, dst.Stat.Mode.IsDir()
390 }
391
392 // Ignore any error and assume that the parent directory of the destination
393 // path exists, in which case the copy may still succeed. If there is any
394 // type of conflict (e.g., non-directory overwriting an existing directory
395 // or vice versa) the extraction will fail. If the destination simply did
396 // not exist, but the parent directory does, the extraction will still
397 // succeed.
398 _ = err // Intentionally ignore stat errors (see above)
399 }
400
401 var (
402 content io.ReadCloser
403 resolvedDstPath string
404 copiedSize int64
405 contentSize int64
406 sizeErr error
407 )
408
409 if srcPath == "-" {
410 content = os.Stdin
411 resolvedDstPath = dstInfo.Path
412 sizeErr = errors.New("content size not available for stdin")

Callers 1

runCopyFunction · 0.85

Calls 10

resolveLocalPathFunction · 0.85
localContentSizeFunction · 0.85
copyProgressFunction · 0.85
copySummaryFunction · 0.85
ContainerStatPathMethod · 0.80
CopyToContainerMethod · 0.80
isAbsFunction · 0.70
ClientMethod · 0.65
ErrMethod · 0.65
CloseMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…