github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/container_cp_linux.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 22 "github.com/containerd/nerdctl/pkg/api/types" 23 "github.com/containerd/nerdctl/pkg/clientutil" 24 "github.com/containerd/nerdctl/pkg/cmd/container" 25 "github.com/containerd/nerdctl/pkg/rootlessutil" 26 "github.com/spf13/cobra" 27 ) 28 29 func newCpCommand() *cobra.Command { 30 shortHelp := "Copy files/folders between a running container and the local filesystem." 31 32 longHelp := shortHelp + ` 33 This command requires 'tar' to be installed on the host (not in the container). 34 Using GNU tar is recommended. 35 The path of the 'tar' binary can be specified with an environment variable '$TAR'. 36 37 WARNING: 'nerdctl cp' is designed only for use with trusted, cooperating containers. 38 Using 'nerdctl cp' with untrusted or malicious containers is unsupported and may not provide protection against unexpected behavior. 39 ` 40 41 usage := `cp [flags] CONTAINER:SRC_PATH DEST_PATH|- 42 nerdctl cp [flags] SRC_PATH|- CONTAINER:DEST_PATH` 43 var cpCommand = &cobra.Command{ 44 Use: usage, 45 Args: IsExactArgs(2), 46 Short: shortHelp, 47 Long: longHelp, 48 RunE: cpAction, 49 ValidArgsFunction: cpShellComplete, 50 SilenceUsage: true, 51 SilenceErrors: true, 52 } 53 54 cpCommand.Flags().BoolP("follow-link", "L", false, "Always follow symbolic link in SRC_PATH.") 55 56 return cpCommand 57 } 58 59 func cpAction(cmd *cobra.Command, args []string) error { 60 options, err := processCpOptions(cmd, args) 61 if err != nil { 62 return err 63 } 64 if rootlessutil.IsRootless() { 65 options.GOptions.Address, err = rootlessutil.RootlessContainredSockAddress() 66 if err != nil { 67 return err 68 } 69 } 70 client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) 71 if err != nil { 72 return err 73 } 74 defer cancel() 75 76 return container.Cp(ctx, client, options) 77 } 78 79 func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptions, error) { 80 globalOptions, err := processRootCmdFlags(cmd) 81 if err != nil { 82 return types.ContainerCpOptions{}, err 83 } 84 flagL, err := cmd.Flags().GetBool("follow-link") 85 if err != nil { 86 return types.ContainerCpOptions{}, err 87 } 88 89 srcSpec, err := parseCpFileSpec(args[0]) 90 if err != nil { 91 return types.ContainerCpOptions{}, err 92 } 93 94 destSpec, err := parseCpFileSpec(args[1]) 95 if err != nil { 96 return types.ContainerCpOptions{}, err 97 } 98 99 if (srcSpec.Container != nil && destSpec.Container != nil) || (len(srcSpec.Path) == 0 && len(destSpec.Path) == 0) { 100 return types.ContainerCpOptions{}, fmt.Errorf("one of src or dest must be a local file specification") 101 } 102 if srcSpec.Container == nil && destSpec.Container == nil { 103 return types.ContainerCpOptions{}, fmt.Errorf("one of src or dest must be a container file specification") 104 } 105 if srcSpec.Path == "-" { 106 return types.ContainerCpOptions{}, fmt.Errorf("support for reading a tar archive from stdin is not implemented yet") 107 } 108 if destSpec.Path == "-" { 109 return types.ContainerCpOptions{}, fmt.Errorf("support for writing a tar archive to stdout is not implemented yet") 110 } 111 112 container2host := srcSpec.Container != nil 113 var container string 114 if container2host { 115 container = *srcSpec.Container 116 } else { 117 container = *destSpec.Container 118 } 119 return types.ContainerCpOptions{ 120 GOptions: globalOptions, 121 Container2Host: container2host, 122 ContainerReq: container, 123 DestPath: destSpec.Path, 124 SrcPath: srcSpec.Path, 125 FollowSymLink: flagL, 126 }, nil 127 }