2015-03-24 23:57:23 -04:00
package client
import (
"fmt"
"io"
"strings"
2015-04-09 16:05:31 -04:00
"github.com/docker/docker/api/types"
2015-03-24 23:57:23 -04:00
"github.com/docker/docker/pkg/archive"
flag "github.com/docker/docker/pkg/mflag"
)
2015-03-25 13:34:41 -04:00
// CmdCp copies files/folders from a path on the container to a directory on the host running the command.
//
// If HOSTDIR is '-', the data is written as a tar file to STDOUT.
//
// Usage: docker cp CONTAINER:PATH HOSTDIR
2015-03-24 23:57:23 -04:00
func ( cli * DockerCli ) CmdCp ( args ... string ) error {
2015-04-30 17:43:14 -04:00
cmd := cli . Subcmd ( "cp" , "CONTAINER:PATH HOSTDIR|-" , "Copy files/folders from a PATH on the container to a HOSTDIR on the host\nrunning the command. Use '-' to write the data as a tar file to STDOUT." , true )
2015-03-24 23:57:23 -04:00
cmd . Require ( flag . Exact , 2 )
2015-03-28 21:22:46 -04:00
cmd . ParseFlags ( args , true )
2015-03-24 23:57:23 -04:00
2015-04-10 00:08:05 -04:00
// deal with path name with `:`
info := strings . SplitN ( cmd . Arg ( 0 ) , ":" , 2 )
2015-03-24 23:57:23 -04:00
if len ( info ) != 2 {
return fmt . Errorf ( "Error: Path not specified" )
}
2015-04-09 16:05:31 -04:00
cfg := & types . CopyConfig {
Resource : info [ 1 ] ,
}
stream , statusCode , err := cli . call ( "POST" , "/containers/" + info [ 0 ] + "/copy" , cfg , nil )
2015-03-24 23:57:23 -04:00
if stream != nil {
defer stream . Close ( )
}
if statusCode == 404 {
return fmt . Errorf ( "No such container: %v" , info [ 0 ] )
}
if err != nil {
return err
}
2015-04-09 16:05:31 -04:00
hostPath := cmd . Arg ( 1 )
2015-03-24 23:57:23 -04:00
if statusCode == 200 {
2015-04-09 16:05:31 -04:00
if hostPath == "-" {
2015-03-24 23:57:23 -04:00
_ , err = io . Copy ( cli . out , stream )
} else {
2015-04-09 16:05:31 -04:00
err = archive . Untar ( stream , hostPath , & archive . TarOptions { NoLchown : true } )
2015-03-24 23:57:23 -04:00
}
if err != nil {
return err
}
}
return nil
}