github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_cp_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path" 10 "path/filepath" 11 "strings" 12 13 "github.com/docker/docker/integration-cli/checker" 14 "github.com/docker/docker/pkg/testutil" 15 icmd "github.com/docker/docker/pkg/testutil/cmd" 16 "github.com/go-check/check" 17 ) 18 19 const ( 20 cpTestPathParent = "/some" 21 cpTestPath = "/some/path" 22 cpTestName = "test" 23 cpFullPath = "/some/path/test" 24 25 cpContainerContents = "holla, i am the container" 26 cpHostContents = "hello, i am the host" 27 ) 28 29 // Ensure that an all-local path case returns an error. 30 func (s *DockerSuite) TestCpLocalOnly(c *check.C) { 31 err := runDockerCp(c, "foo", "bar", nil) 32 c.Assert(err, checker.NotNil) 33 34 c.Assert(err.Error(), checker.Contains, "must specify at least one container source") 35 } 36 37 // Test for #5656 38 // Check that garbage paths don't escape the container's rootfs 39 func (s *DockerSuite) TestCpGarbagePath(c *check.C) { 40 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath) 41 42 containerID := strings.TrimSpace(out) 43 44 out, _ = dockerCmd(c, "wait", containerID) 45 // failed to set up container 46 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 47 48 c.Assert(os.MkdirAll(cpTestPath, os.ModeDir), checker.IsNil) 49 50 hostFile, err := os.Create(cpFullPath) 51 c.Assert(err, checker.IsNil) 52 defer hostFile.Close() 53 defer os.RemoveAll(cpTestPathParent) 54 55 fmt.Fprintf(hostFile, "%s", cpHostContents) 56 57 tmpdir, err := ioutil.TempDir("", "docker-integration") 58 c.Assert(err, checker.IsNil) 59 60 tmpname := filepath.Join(tmpdir, cpTestName) 61 defer os.RemoveAll(tmpdir) 62 63 path := path.Join("../../../../../../../../../../../../", cpFullPath) 64 65 dockerCmd(c, "cp", containerID+":"+path, tmpdir) 66 67 file, _ := os.Open(tmpname) 68 defer file.Close() 69 70 test, err := ioutil.ReadAll(file) 71 c.Assert(err, checker.IsNil) 72 73 // output matched host file -- garbage path can escape container rootfs 74 c.Assert(string(test), checker.Not(checker.Equals), cpHostContents) 75 76 // output doesn't match the input for garbage path 77 c.Assert(string(test), checker.Equals, cpContainerContents) 78 } 79 80 // Check that relative paths are relative to the container's rootfs 81 func (s *DockerSuite) TestCpRelativePath(c *check.C) { 82 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath) 83 84 containerID := strings.TrimSpace(out) 85 86 out, _ = dockerCmd(c, "wait", containerID) 87 // failed to set up container 88 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 89 90 c.Assert(os.MkdirAll(cpTestPath, os.ModeDir), checker.IsNil) 91 92 hostFile, err := os.Create(cpFullPath) 93 c.Assert(err, checker.IsNil) 94 defer hostFile.Close() 95 defer os.RemoveAll(cpTestPathParent) 96 97 fmt.Fprintf(hostFile, "%s", cpHostContents) 98 99 tmpdir, err := ioutil.TempDir("", "docker-integration") 100 c.Assert(err, checker.IsNil) 101 102 tmpname := filepath.Join(tmpdir, cpTestName) 103 defer os.RemoveAll(tmpdir) 104 105 var relPath string 106 if path.IsAbs(cpFullPath) { 107 // normally this is `filepath.Rel("/", cpFullPath)` but we cannot 108 // get this unix-path manipulation on windows with filepath. 109 relPath = cpFullPath[1:] 110 } 111 c.Assert(path.IsAbs(cpFullPath), checker.True, check.Commentf("path %s was assumed to be an absolute path", cpFullPath)) 112 113 dockerCmd(c, "cp", containerID+":"+relPath, tmpdir) 114 115 file, _ := os.Open(tmpname) 116 defer file.Close() 117 118 test, err := ioutil.ReadAll(file) 119 c.Assert(err, checker.IsNil) 120 121 // output matched host file -- relative path can escape container rootfs 122 c.Assert(string(test), checker.Not(checker.Equals), cpHostContents) 123 124 // output doesn't match the input for relative path 125 c.Assert(string(test), checker.Equals, cpContainerContents) 126 } 127 128 // Check that absolute paths are relative to the container's rootfs 129 func (s *DockerSuite) TestCpAbsolutePath(c *check.C) { 130 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath) 131 132 containerID := strings.TrimSpace(out) 133 134 out, _ = dockerCmd(c, "wait", containerID) 135 // failed to set up container 136 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 137 138 c.Assert(os.MkdirAll(cpTestPath, os.ModeDir), checker.IsNil) 139 140 hostFile, err := os.Create(cpFullPath) 141 c.Assert(err, checker.IsNil) 142 defer hostFile.Close() 143 defer os.RemoveAll(cpTestPathParent) 144 145 fmt.Fprintf(hostFile, "%s", cpHostContents) 146 147 tmpdir, err := ioutil.TempDir("", "docker-integration") 148 c.Assert(err, checker.IsNil) 149 150 tmpname := filepath.Join(tmpdir, cpTestName) 151 defer os.RemoveAll(tmpdir) 152 153 path := cpFullPath 154 155 dockerCmd(c, "cp", containerID+":"+path, tmpdir) 156 157 file, _ := os.Open(tmpname) 158 defer file.Close() 159 160 test, err := ioutil.ReadAll(file) 161 c.Assert(err, checker.IsNil) 162 163 // output matched host file -- absolute path can escape container rootfs 164 c.Assert(string(test), checker.Not(checker.Equals), cpHostContents) 165 166 // output doesn't match the input for absolute path 167 c.Assert(string(test), checker.Equals, cpContainerContents) 168 } 169 170 // Test for #5619 171 // Check that absolute symlinks are still relative to the container's rootfs 172 func (s *DockerSuite) TestCpAbsoluteSymlink(c *check.C) { 173 testRequires(c, DaemonIsLinux) 174 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpFullPath+" container_path") 175 176 containerID := strings.TrimSpace(out) 177 178 out, _ = dockerCmd(c, "wait", containerID) 179 // failed to set up container 180 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 181 182 c.Assert(os.MkdirAll(cpTestPath, os.ModeDir), checker.IsNil) 183 184 hostFile, err := os.Create(cpFullPath) 185 c.Assert(err, checker.IsNil) 186 defer hostFile.Close() 187 defer os.RemoveAll(cpTestPathParent) 188 189 fmt.Fprintf(hostFile, "%s", cpHostContents) 190 191 tmpdir, err := ioutil.TempDir("", "docker-integration") 192 c.Assert(err, checker.IsNil) 193 194 tmpname := filepath.Join(tmpdir, "container_path") 195 defer os.RemoveAll(tmpdir) 196 197 path := path.Join("/", "container_path") 198 199 dockerCmd(c, "cp", containerID+":"+path, tmpdir) 200 201 // We should have copied a symlink *NOT* the file itself! 202 linkTarget, err := os.Readlink(tmpname) 203 c.Assert(err, checker.IsNil) 204 205 c.Assert(linkTarget, checker.Equals, filepath.FromSlash(cpFullPath)) 206 } 207 208 // Check that symlinks to a directory behave as expected when copying one from 209 // a container. 210 func (s *DockerSuite) TestCpFromSymlinkToDirectory(c *check.C) { 211 testRequires(c, DaemonIsLinux) 212 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpTestPathParent+" /dir_link") 213 214 containerID := strings.TrimSpace(out) 215 216 out, _ = dockerCmd(c, "wait", containerID) 217 // failed to set up container 218 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 219 220 testDir, err := ioutil.TempDir("", "test-cp-from-symlink-to-dir-") 221 c.Assert(err, checker.IsNil) 222 defer os.RemoveAll(testDir) 223 224 // This copy command should copy the symlink, not the target, into the 225 // temporary directory. 226 dockerCmd(c, "cp", containerID+":"+"/dir_link", testDir) 227 228 expectedPath := filepath.Join(testDir, "dir_link") 229 linkTarget, err := os.Readlink(expectedPath) 230 c.Assert(err, checker.IsNil) 231 232 c.Assert(linkTarget, checker.Equals, filepath.FromSlash(cpTestPathParent)) 233 234 os.Remove(expectedPath) 235 236 // This copy command should resolve the symlink (note the trailing 237 // separator), copying the target into the temporary directory. 238 dockerCmd(c, "cp", containerID+":"+"/dir_link/", testDir) 239 240 // It *should not* have copied the directory using the target's name, but 241 // used the given name instead. 242 unexpectedPath := filepath.Join(testDir, cpTestPathParent) 243 stat, err := os.Lstat(unexpectedPath) 244 if err == nil { 245 out = fmt.Sprintf("target name was copied: %q - %q", stat.Mode(), stat.Name()) 246 } 247 c.Assert(err, checker.NotNil, check.Commentf(out)) 248 249 // It *should* have copied the directory using the asked name "dir_link". 250 stat, err = os.Lstat(expectedPath) 251 c.Assert(err, checker.IsNil, check.Commentf("unable to stat resource at %q", expectedPath)) 252 253 c.Assert(stat.IsDir(), checker.True, check.Commentf("should have copied a directory but got %q instead", stat.Mode())) 254 } 255 256 // Check that symlinks to a directory behave as expected when copying one to a 257 // container. 258 func (s *DockerSuite) TestCpToSymlinkToDirectory(c *check.C) { 259 testRequires(c, DaemonIsLinux) 260 testRequires(c, SameHostDaemon) // Requires local volume mount bind. 261 262 testVol, err := ioutil.TempDir("", "test-cp-to-symlink-to-dir-") 263 c.Assert(err, checker.IsNil) 264 defer os.RemoveAll(testVol) 265 266 // Create a test container with a local volume. We will test by copying 267 // to the volume path in the container which we can then verify locally. 268 out, _ := dockerCmd(c, "create", "-v", testVol+":/testVol", "busybox") 269 270 containerID := strings.TrimSpace(out) 271 272 // Create a temp directory to hold a test file nested in a directory. 273 testDir, err := ioutil.TempDir("", "test-cp-to-symlink-to-dir-") 274 c.Assert(err, checker.IsNil) 275 defer os.RemoveAll(testDir) 276 277 // This file will be at "/testDir/some/path/test" and will be copied into 278 // the test volume later. 279 hostTestFilename := filepath.Join(testDir, cpFullPath) 280 c.Assert(os.MkdirAll(filepath.Dir(hostTestFilename), os.FileMode(0700)), checker.IsNil) 281 c.Assert(ioutil.WriteFile(hostTestFilename, []byte(cpHostContents), os.FileMode(0600)), checker.IsNil) 282 283 // Now create another temp directory to hold a symlink to the 284 // "/testDir/some" directory. 285 linkDir, err := ioutil.TempDir("", "test-cp-to-symlink-to-dir-") 286 c.Assert(err, checker.IsNil) 287 defer os.RemoveAll(linkDir) 288 289 // Then symlink "/linkDir/dir_link" to "/testdir/some". 290 linkTarget := filepath.Join(testDir, cpTestPathParent) 291 localLink := filepath.Join(linkDir, "dir_link") 292 c.Assert(os.Symlink(linkTarget, localLink), checker.IsNil) 293 294 // Now copy that symlink into the test volume in the container. 295 dockerCmd(c, "cp", localLink, containerID+":/testVol") 296 297 // This copy command should have copied the symlink *not* the target. 298 expectedPath := filepath.Join(testVol, "dir_link") 299 actualLinkTarget, err := os.Readlink(expectedPath) 300 c.Assert(err, checker.IsNil, check.Commentf("unable to read symlink at %q", expectedPath)) 301 302 c.Assert(actualLinkTarget, checker.Equals, linkTarget) 303 304 // Good, now remove that copied link for the next test. 305 os.Remove(expectedPath) 306 307 // This copy command should resolve the symlink (note the trailing 308 // separator), copying the target into the test volume directory in the 309 // container. 310 dockerCmd(c, "cp", localLink+"/", containerID+":/testVol") 311 312 // It *should not* have copied the directory using the target's name, but 313 // used the given name instead. 314 unexpectedPath := filepath.Join(testVol, cpTestPathParent) 315 stat, err := os.Lstat(unexpectedPath) 316 if err == nil { 317 out = fmt.Sprintf("target name was copied: %q - %q", stat.Mode(), stat.Name()) 318 } 319 c.Assert(err, checker.NotNil, check.Commentf(out)) 320 321 // It *should* have copied the directory using the asked name "dir_link". 322 stat, err = os.Lstat(expectedPath) 323 c.Assert(err, checker.IsNil, check.Commentf("unable to stat resource at %q", expectedPath)) 324 325 c.Assert(stat.IsDir(), checker.True, check.Commentf("should have copied a directory but got %q instead", stat.Mode())) 326 327 // And this directory should contain the file copied from the host at the 328 // expected location: "/testVol/dir_link/path/test" 329 expectedFilepath := filepath.Join(testVol, "dir_link/path/test") 330 fileContents, err := ioutil.ReadFile(expectedFilepath) 331 c.Assert(err, checker.IsNil) 332 333 c.Assert(string(fileContents), checker.Equals, cpHostContents) 334 } 335 336 // Test for #5619 337 // Check that symlinks which are part of the resource path are still relative to the container's rootfs 338 func (s *DockerSuite) TestCpSymlinkComponent(c *check.C) { 339 testRequires(c, DaemonIsLinux) 340 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpTestPath+" container_path") 341 342 containerID := strings.TrimSpace(out) 343 344 out, _ = dockerCmd(c, "wait", containerID) 345 // failed to set up container 346 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 347 348 c.Assert(os.MkdirAll(cpTestPath, os.ModeDir), checker.IsNil) 349 350 hostFile, err := os.Create(cpFullPath) 351 c.Assert(err, checker.IsNil) 352 defer hostFile.Close() 353 defer os.RemoveAll(cpTestPathParent) 354 355 fmt.Fprintf(hostFile, "%s", cpHostContents) 356 357 tmpdir, err := ioutil.TempDir("", "docker-integration") 358 359 c.Assert(err, checker.IsNil) 360 361 tmpname := filepath.Join(tmpdir, cpTestName) 362 defer os.RemoveAll(tmpdir) 363 364 path := path.Join("/", "container_path", cpTestName) 365 366 dockerCmd(c, "cp", containerID+":"+path, tmpdir) 367 368 file, _ := os.Open(tmpname) 369 defer file.Close() 370 371 test, err := ioutil.ReadAll(file) 372 c.Assert(err, checker.IsNil) 373 374 // output matched host file -- symlink path component can escape container rootfs 375 c.Assert(string(test), checker.Not(checker.Equals), cpHostContents) 376 377 // output doesn't match the input for symlink path component 378 c.Assert(string(test), checker.Equals, cpContainerContents) 379 } 380 381 // Check that cp with unprivileged user doesn't return any error 382 func (s *DockerSuite) TestCpUnprivilegedUser(c *check.C) { 383 testRequires(c, DaemonIsLinux) 384 testRequires(c, UnixCli) // uses chmod/su: not available on windows 385 386 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "touch "+cpTestName) 387 388 containerID := strings.TrimSpace(out) 389 390 out, _ = dockerCmd(c, "wait", containerID) 391 // failed to set up container 392 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 393 394 tmpdir, err := ioutil.TempDir("", "docker-integration") 395 c.Assert(err, checker.IsNil) 396 397 defer os.RemoveAll(tmpdir) 398 399 c.Assert(os.Chmod(tmpdir, 0777), checker.IsNil) 400 401 result := icmd.RunCommand("su", "unprivilegeduser", "-c", 402 fmt.Sprintf("%s cp %s:%s %s", dockerBinary, containerID, cpTestName, tmpdir)) 403 result.Assert(c, icmd.Expected{}) 404 } 405 406 func (s *DockerSuite) TestCpSpecialFiles(c *check.C) { 407 testRequires(c, DaemonIsLinux) 408 testRequires(c, SameHostDaemon) 409 410 outDir, err := ioutil.TempDir("", "cp-test-special-files") 411 c.Assert(err, checker.IsNil) 412 defer os.RemoveAll(outDir) 413 414 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "touch /foo") 415 416 containerID := strings.TrimSpace(out) 417 418 out, _ = dockerCmd(c, "wait", containerID) 419 // failed to set up container 420 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 421 422 // Copy actual /etc/resolv.conf 423 dockerCmd(c, "cp", containerID+":/etc/resolv.conf", outDir) 424 425 expected := readContainerFile(c, containerID, "resolv.conf") 426 actual, err := ioutil.ReadFile(outDir + "/resolv.conf") 427 428 // Expected copied file to be duplicate of the container resolvconf 429 c.Assert(bytes.Equal(actual, expected), checker.True) 430 431 // Copy actual /etc/hosts 432 dockerCmd(c, "cp", containerID+":/etc/hosts", outDir) 433 434 expected = readContainerFile(c, containerID, "hosts") 435 actual, err = ioutil.ReadFile(outDir + "/hosts") 436 437 // Expected copied file to be duplicate of the container hosts 438 c.Assert(bytes.Equal(actual, expected), checker.True) 439 440 // Copy actual /etc/resolv.conf 441 dockerCmd(c, "cp", containerID+":/etc/hostname", outDir) 442 443 expected = readContainerFile(c, containerID, "hostname") 444 actual, err = ioutil.ReadFile(outDir + "/hostname") 445 c.Assert(err, checker.IsNil) 446 447 // Expected copied file to be duplicate of the container resolvconf 448 c.Assert(bytes.Equal(actual, expected), checker.True) 449 } 450 451 func (s *DockerSuite) TestCpVolumePath(c *check.C) { 452 // stat /tmp/cp-test-volumepath851508420/test gets permission denied for the user 453 testRequires(c, NotUserNamespace) 454 testRequires(c, DaemonIsLinux) 455 testRequires(c, SameHostDaemon) 456 457 tmpDir, err := ioutil.TempDir("", "cp-test-volumepath") 458 c.Assert(err, checker.IsNil) 459 defer os.RemoveAll(tmpDir) 460 outDir, err := ioutil.TempDir("", "cp-test-volumepath-out") 461 c.Assert(err, checker.IsNil) 462 defer os.RemoveAll(outDir) 463 _, err = os.Create(tmpDir + "/test") 464 c.Assert(err, checker.IsNil) 465 466 out, _ := dockerCmd(c, "run", "-d", "-v", "/foo", "-v", tmpDir+"/test:/test", "-v", tmpDir+":/baz", "busybox", "/bin/sh", "-c", "touch /foo/bar") 467 468 containerID := strings.TrimSpace(out) 469 470 out, _ = dockerCmd(c, "wait", containerID) 471 // failed to set up container 472 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 473 474 // Copy actual volume path 475 dockerCmd(c, "cp", containerID+":/foo", outDir) 476 477 stat, err := os.Stat(outDir + "/foo") 478 c.Assert(err, checker.IsNil) 479 // expected copied content to be dir 480 c.Assert(stat.IsDir(), checker.True) 481 stat, err = os.Stat(outDir + "/foo/bar") 482 c.Assert(err, checker.IsNil) 483 // Expected file `bar` to be a file 484 c.Assert(stat.IsDir(), checker.False) 485 486 // Copy file nested in volume 487 dockerCmd(c, "cp", containerID+":/foo/bar", outDir) 488 489 stat, err = os.Stat(outDir + "/bar") 490 c.Assert(err, checker.IsNil) 491 // Expected file `bar` to be a file 492 c.Assert(stat.IsDir(), checker.False) 493 494 // Copy Bind-mounted dir 495 dockerCmd(c, "cp", containerID+":/baz", outDir) 496 stat, err = os.Stat(outDir + "/baz") 497 c.Assert(err, checker.IsNil) 498 // Expected `baz` to be a dir 499 c.Assert(stat.IsDir(), checker.True) 500 501 // Copy file nested in bind-mounted dir 502 dockerCmd(c, "cp", containerID+":/baz/test", outDir) 503 fb, err := ioutil.ReadFile(outDir + "/baz/test") 504 c.Assert(err, checker.IsNil) 505 fb2, err := ioutil.ReadFile(tmpDir + "/test") 506 c.Assert(err, checker.IsNil) 507 // Expected copied file to be duplicate of bind-mounted file 508 c.Assert(bytes.Equal(fb, fb2), checker.True) 509 510 // Copy bind-mounted file 511 dockerCmd(c, "cp", containerID+":/test", outDir) 512 fb, err = ioutil.ReadFile(outDir + "/test") 513 c.Assert(err, checker.IsNil) 514 fb2, err = ioutil.ReadFile(tmpDir + "/test") 515 c.Assert(err, checker.IsNil) 516 // Expected copied file to be duplicate of bind-mounted file 517 c.Assert(bytes.Equal(fb, fb2), checker.True) 518 } 519 520 func (s *DockerSuite) TestCpToDot(c *check.C) { 521 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test") 522 523 containerID := strings.TrimSpace(out) 524 525 out, _ = dockerCmd(c, "wait", containerID) 526 // failed to set up container 527 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 528 529 tmpdir, err := ioutil.TempDir("", "docker-integration") 530 c.Assert(err, checker.IsNil) 531 defer os.RemoveAll(tmpdir) 532 cwd, err := os.Getwd() 533 c.Assert(err, checker.IsNil) 534 defer os.Chdir(cwd) 535 c.Assert(os.Chdir(tmpdir), checker.IsNil) 536 dockerCmd(c, "cp", containerID+":/test", ".") 537 content, err := ioutil.ReadFile("./test") 538 c.Assert(err, checker.IsNil) 539 c.Assert(string(content), checker.Equals, "lololol\n") 540 } 541 542 func (s *DockerSuite) TestCpToStdout(c *check.C) { 543 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test") 544 545 containerID := strings.TrimSpace(out) 546 547 out, _ = dockerCmd(c, "wait", containerID) 548 // failed to set up container 549 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 550 551 out, _, err := testutil.RunCommandPipelineWithOutput( 552 exec.Command(dockerBinary, "cp", containerID+":/test", "-"), 553 exec.Command("tar", "-vtf", "-")) 554 555 c.Assert(err, checker.IsNil) 556 557 c.Assert(out, checker.Contains, "test") 558 c.Assert(out, checker.Contains, "-rw") 559 } 560 561 func (s *DockerSuite) TestCpNameHasColon(c *check.C) { 562 testRequires(c, SameHostDaemon, DaemonIsLinux) 563 564 out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /te:s:t") 565 566 containerID := strings.TrimSpace(out) 567 568 out, _ = dockerCmd(c, "wait", containerID) 569 // failed to set up container 570 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 571 572 tmpdir, err := ioutil.TempDir("", "docker-integration") 573 c.Assert(err, checker.IsNil) 574 defer os.RemoveAll(tmpdir) 575 dockerCmd(c, "cp", containerID+":/te:s:t", tmpdir) 576 content, err := ioutil.ReadFile(tmpdir + "/te:s:t") 577 c.Assert(err, checker.IsNil) 578 c.Assert(string(content), checker.Equals, "lololol\n") 579 } 580 581 func (s *DockerSuite) TestCopyAndRestart(c *check.C) { 582 testRequires(c, DaemonIsLinux) 583 expectedMsg := "hello" 584 out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", expectedMsg) 585 containerID := strings.TrimSpace(out) 586 587 out, _ = dockerCmd(c, "wait", containerID) 588 // failed to set up container 589 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 590 591 tmpDir, err := ioutil.TempDir("", "test-docker-restart-after-copy-") 592 c.Assert(err, checker.IsNil) 593 defer os.RemoveAll(tmpDir) 594 595 dockerCmd(c, "cp", fmt.Sprintf("%s:/etc/group", containerID), tmpDir) 596 597 out, _ = dockerCmd(c, "start", "-a", containerID) 598 599 c.Assert(strings.TrimSpace(out), checker.Equals, expectedMsg) 600 } 601 602 func (s *DockerSuite) TestCopyCreatedContainer(c *check.C) { 603 testRequires(c, DaemonIsLinux) 604 dockerCmd(c, "create", "--name", "test_cp", "-v", "/test", "busybox") 605 606 tmpDir, err := ioutil.TempDir("", "test") 607 c.Assert(err, checker.IsNil) 608 defer os.RemoveAll(tmpDir) 609 dockerCmd(c, "cp", "test_cp:/bin/sh", tmpDir) 610 } 611 612 // test copy with option `-L`: following symbol link 613 // Check that symlinks to a file behave as expected when copying one from 614 // a container to host following symbol link 615 func (s *DockerSuite) TestCpSymlinkFromConToHostFollowSymlink(c *check.C) { 616 testRequires(c, DaemonIsLinux) 617 out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpFullPath+" /dir_link") 618 if exitCode != 0 { 619 c.Fatal("failed to create a container", out) 620 } 621 622 cleanedContainerID := strings.TrimSpace(out) 623 624 out, _ = dockerCmd(c, "wait", cleanedContainerID) 625 if strings.TrimSpace(out) != "0" { 626 c.Fatal("failed to set up container", out) 627 } 628 629 testDir, err := ioutil.TempDir("", "test-cp-symlink-container-to-host-follow-symlink") 630 if err != nil { 631 c.Fatal(err) 632 } 633 defer os.RemoveAll(testDir) 634 635 // This copy command should copy the symlink, not the target, into the 636 // temporary directory. 637 dockerCmd(c, "cp", "-L", cleanedContainerID+":"+"/dir_link", testDir) 638 639 expectedPath := filepath.Join(testDir, "dir_link") 640 641 expected := []byte(cpContainerContents) 642 actual, err := ioutil.ReadFile(expectedPath) 643 644 if !bytes.Equal(actual, expected) { 645 c.Fatalf("Expected copied file to be duplicate of the container symbol link target") 646 } 647 os.Remove(expectedPath) 648 649 // now test copy symbol link to a non-existing file in host 650 expectedPath = filepath.Join(testDir, "somefile_host") 651 // expectedPath shouldn't exist, if exists, remove it 652 if _, err := os.Lstat(expectedPath); err == nil { 653 os.Remove(expectedPath) 654 } 655 656 dockerCmd(c, "cp", "-L", cleanedContainerID+":"+"/dir_link", expectedPath) 657 658 actual, err = ioutil.ReadFile(expectedPath) 659 c.Assert(err, checker.IsNil) 660 661 if !bytes.Equal(actual, expected) { 662 c.Fatalf("Expected copied file to be duplicate of the container symbol link target") 663 } 664 defer os.Remove(expectedPath) 665 }