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