github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/integration-cli/docker_cli_cp_to_container_test.go (about)

     1  package main
     2  
     3  import (
     4  	"os"
     5  
     6  	"github.com/docker/docker/integration-cli/checker"
     7  	"github.com/go-check/check"
     8  )
     9  
    10  // docker cp LOCALPATH CONTAINER:PATH
    11  
    12  // Try all of the test cases from the archive package which implements the
    13  // internals of `docker cp` and ensure that the behavior matches when actually
    14  // copying to and from containers.
    15  
    16  // Basic assumptions about SRC and DST:
    17  // 1. SRC must exist.
    18  // 2. If SRC ends with a trailing separator, it must be a directory.
    19  // 3. DST parent directory must exist.
    20  // 4. If DST exists as a file, it must not end with a trailing separator.
    21  
    22  // First get these easy error cases out of the way.
    23  
    24  // Test for error when SRC does not exist.
    25  func (s *DockerSuite) TestCpToErrSrcNotExists(c *check.C) {
    26  	containerID := makeTestContainer(c, testContainerOptions{})
    27  
    28  	tmpDir := getTestDir(c, "test-cp-to-err-src-not-exists")
    29  	defer os.RemoveAll(tmpDir)
    30  
    31  	srcPath := cpPath(tmpDir, "file1")
    32  	dstPath := containerCpPath(containerID, "file1")
    33  
    34  	err := runDockerCp(c, srcPath, dstPath)
    35  	c.Assert(err, checker.NotNil)
    36  
    37  	c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
    38  }
    39  
    40  // Test for error when SRC ends in a trailing
    41  // path separator but it exists as a file.
    42  func (s *DockerSuite) TestCpToErrSrcNotDir(c *check.C) {
    43  	containerID := makeTestContainer(c, testContainerOptions{})
    44  
    45  	tmpDir := getTestDir(c, "test-cp-to-err-src-not-dir")
    46  	defer os.RemoveAll(tmpDir)
    47  
    48  	makeTestContentInDir(c, tmpDir)
    49  
    50  	srcPath := cpPathTrailingSep(tmpDir, "file1")
    51  	dstPath := containerCpPath(containerID, "testDir")
    52  
    53  	err := runDockerCp(c, srcPath, dstPath)
    54  	c.Assert(err, checker.NotNil)
    55  
    56  	c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
    57  }
    58  
    59  // Test for error when SRC is a valid file or directory,
    60  // but the DST parent directory does not exist.
    61  func (s *DockerSuite) TestCpToErrDstParentNotExists(c *check.C) {
    62  	testRequires(c, DaemonIsLinux)
    63  	containerID := makeTestContainer(c, testContainerOptions{addContent: true})
    64  
    65  	tmpDir := getTestDir(c, "test-cp-to-err-dst-parent-not-exists")
    66  	defer os.RemoveAll(tmpDir)
    67  
    68  	makeTestContentInDir(c, tmpDir)
    69  
    70  	// Try with a file source.
    71  	srcPath := cpPath(tmpDir, "file1")
    72  	dstPath := containerCpPath(containerID, "/notExists", "file1")
    73  
    74  	err := runDockerCp(c, srcPath, dstPath)
    75  	c.Assert(err, checker.NotNil)
    76  
    77  	c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
    78  
    79  	// Try with a directory source.
    80  	srcPath = cpPath(tmpDir, "dir1")
    81  
    82  	err = runDockerCp(c, srcPath, dstPath)
    83  	c.Assert(err, checker.NotNil)
    84  
    85  	c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
    86  }
    87  
    88  // Test for error when DST ends in a trailing path separator but exists as a
    89  // file. Also test that we cannot overwrite an existing directory with a
    90  // non-directory and cannot overwrite an existing
    91  func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) {
    92  	testRequires(c, DaemonIsLinux)
    93  	containerID := makeTestContainer(c, testContainerOptions{addContent: true})
    94  
    95  	tmpDir := getTestDir(c, "test-cp-to-err-dst-not-dir")
    96  	defer os.RemoveAll(tmpDir)
    97  
    98  	makeTestContentInDir(c, tmpDir)
    99  
   100  	// Try with a file source.
   101  	srcPath := cpPath(tmpDir, "dir1/file1-1")
   102  	dstPath := containerCpPathTrailingSep(containerID, "file1")
   103  
   104  	// The client should encounter an error trying to stat the destination
   105  	// and then be unable to copy since the destination is asserted to be a
   106  	// directory but does not exist.
   107  	err := runDockerCp(c, srcPath, dstPath)
   108  	c.Assert(err, checker.NotNil)
   109  
   110  	c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExist error, but got %T: %s", err, err))
   111  
   112  	// Try with a directory source.
   113  	srcPath = cpPath(tmpDir, "dir1")
   114  
   115  	// The client should encounter an error trying to stat the destination and
   116  	// then decide to extract to the parent directory instead with a rebased
   117  	// name in the source archive, but this directory would overwrite the
   118  	// existing file with the same name.
   119  	err = runDockerCp(c, srcPath, dstPath)
   120  	c.Assert(err, checker.NotNil)
   121  
   122  	c.Assert(isCannotOverwriteNonDirWithDir(err), checker.True, check.Commentf("expected CannotOverwriteNonDirWithDir error, but got %T: %s", err, err))
   123  }
   124  
   125  // Check that copying from a local path to a symlink in a container copies to
   126  // the symlink target and does not overwrite the container symlink itself.
   127  func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
   128  	//  stat /tmp/test-cp-to-symlink-destination-262430901/vol3 gets permission denied for the user
   129  	testRequires(c, NotUserNamespace)
   130  	testRequires(c, DaemonIsLinux)
   131  	testRequires(c, SameHostDaemon) // Requires local volume mount bind.
   132  
   133  	testVol := getTestDir(c, "test-cp-to-symlink-destination-")
   134  	defer os.RemoveAll(testVol)
   135  
   136  	makeTestContentInDir(c, testVol)
   137  
   138  	containerID := makeTestContainer(c, testContainerOptions{
   139  		volumes: defaultVolumes(testVol), // Our bind mount is at /vol2
   140  	})
   141  
   142  	// First, copy a local file to a symlink to a file in the container. This
   143  	// should overwrite the symlink target contents with the source contents.
   144  	srcPath := cpPath(testVol, "file2")
   145  	dstPath := containerCpPath(containerID, "/vol2/symlinkToFile1")
   146  
   147  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   148  
   149  	// The symlink should not have been modified.
   150  	c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToFile1"), "file1"), checker.IsNil)
   151  
   152  	// The file should have the contents of "file2" now.
   153  	c.Assert(fileContentEquals(c, cpPath(testVol, "file1"), "file2\n"), checker.IsNil)
   154  
   155  	// Next, copy a local file to a symlink to a directory in the container.
   156  	// This should copy the file into the symlink target directory.
   157  	dstPath = containerCpPath(containerID, "/vol2/symlinkToDir1")
   158  
   159  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   160  
   161  	// The symlink should not have been modified.
   162  	c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToDir1"), "dir1"), checker.IsNil)
   163  
   164  	// The file should have the contents of "file2" now.
   165  	c.Assert(fileContentEquals(c, cpPath(testVol, "file2"), "file2\n"), checker.IsNil)
   166  
   167  	// Next, copy a file to a symlink to a file that does not exist (a broken
   168  	// symlink) in the container. This should create the target file with the
   169  	// contents of the source file.
   170  	dstPath = containerCpPath(containerID, "/vol2/brokenSymlinkToFileX")
   171  
   172  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   173  
   174  	// The symlink should not have been modified.
   175  	c.Assert(symlinkTargetEquals(c, cpPath(testVol, "brokenSymlinkToFileX"), "fileX"), checker.IsNil)
   176  
   177  	// The file should have the contents of "file2" now.
   178  	c.Assert(fileContentEquals(c, cpPath(testVol, "fileX"), "file2\n"), checker.IsNil)
   179  
   180  	// Next, copy a local directory to a symlink to a directory in the
   181  	// container. This should copy the directory into the symlink target
   182  	// directory and not modify the symlink.
   183  	srcPath = cpPath(testVol, "/dir2")
   184  	dstPath = containerCpPath(containerID, "/vol2/symlinkToDir1")
   185  
   186  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   187  
   188  	// The symlink should not have been modified.
   189  	c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToDir1"), "dir1"), checker.IsNil)
   190  
   191  	// The directory should now contain a copy of "dir2".
   192  	c.Assert(fileContentEquals(c, cpPath(testVol, "dir1/dir2/file2-1"), "file2-1\n"), checker.IsNil)
   193  
   194  	// Next, copy a local directory to a symlink to a local directory that does
   195  	// not exist (a broken symlink) in the container. This should create the
   196  	// target as a directory with the contents of the source directory. It
   197  	// should not modify the symlink.
   198  	dstPath = containerCpPath(containerID, "/vol2/brokenSymlinkToDirX")
   199  
   200  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   201  
   202  	// The symlink should not have been modified.
   203  	c.Assert(symlinkTargetEquals(c, cpPath(testVol, "brokenSymlinkToDirX"), "dirX"), checker.IsNil)
   204  
   205  	// The "dirX" directory should now be a copy of "dir2".
   206  	c.Assert(fileContentEquals(c, cpPath(testVol, "dirX/file2-1"), "file2-1\n"), checker.IsNil)
   207  }
   208  
   209  // Possibilities are reduced to the remaining 10 cases:
   210  //
   211  //  case | srcIsDir | onlyDirContents | dstExists | dstIsDir | dstTrSep | action
   212  // ===================================================================================================
   213  //   A   |  no      |  -              |  no       |  -       |  no      |  create file
   214  //   B   |  no      |  -              |  no       |  -       |  yes     |  error
   215  //   C   |  no      |  -              |  yes      |  no      |  -       |  overwrite file
   216  //   D   |  no      |  -              |  yes      |  yes     |  -       |  create file in dst dir
   217  //   E   |  yes     |  no             |  no       |  -       |  -       |  create dir, copy contents
   218  //   F   |  yes     |  no             |  yes      |  no      |  -       |  error
   219  //   G   |  yes     |  no             |  yes      |  yes     |  -       |  copy dir and contents
   220  //   H   |  yes     |  yes            |  no       |  -       |  -       |  create dir, copy contents
   221  //   I   |  yes     |  yes            |  yes      |  no      |  -       |  error
   222  //   J   |  yes     |  yes            |  yes      |  yes     |  -       |  copy dir contents
   223  //
   224  
   225  // A. SRC specifies a file and DST (no trailing path separator) doesn't
   226  //    exist. This should create a file with the name DST and copy the
   227  //    contents of the source file into it.
   228  func (s *DockerSuite) TestCpToCaseA(c *check.C) {
   229  	containerID := makeTestContainer(c, testContainerOptions{
   230  		workDir: "/root", command: makeCatFileCommand("itWorks.txt"),
   231  	})
   232  
   233  	tmpDir := getTestDir(c, "test-cp-to-case-a")
   234  	defer os.RemoveAll(tmpDir)
   235  
   236  	makeTestContentInDir(c, tmpDir)
   237  
   238  	srcPath := cpPath(tmpDir, "file1")
   239  	dstPath := containerCpPath(containerID, "/root/itWorks.txt")
   240  
   241  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   242  
   243  	c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
   244  }
   245  
   246  // B. SRC specifies a file and DST (with trailing path separator) doesn't
   247  //    exist. This should cause an error because the copy operation cannot
   248  //    create a directory when copying a single file.
   249  func (s *DockerSuite) TestCpToCaseB(c *check.C) {
   250  	containerID := makeTestContainer(c, testContainerOptions{
   251  		command: makeCatFileCommand("testDir/file1"),
   252  	})
   253  
   254  	tmpDir := getTestDir(c, "test-cp-to-case-b")
   255  	defer os.RemoveAll(tmpDir)
   256  
   257  	makeTestContentInDir(c, tmpDir)
   258  
   259  	srcPath := cpPath(tmpDir, "file1")
   260  	dstDir := containerCpPathTrailingSep(containerID, "testDir")
   261  
   262  	err := runDockerCp(c, srcPath, dstDir)
   263  	c.Assert(err, checker.NotNil)
   264  
   265  	c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExists error, but got %T: %s", err, err))
   266  }
   267  
   268  // C. SRC specifies a file and DST exists as a file. This should overwrite
   269  //    the file at DST with the contents of the source file.
   270  func (s *DockerSuite) TestCpToCaseC(c *check.C) {
   271  	testRequires(c, DaemonIsLinux)
   272  	containerID := makeTestContainer(c, testContainerOptions{
   273  		addContent: true, workDir: "/root",
   274  		command: makeCatFileCommand("file2"),
   275  	})
   276  
   277  	tmpDir := getTestDir(c, "test-cp-to-case-c")
   278  	defer os.RemoveAll(tmpDir)
   279  
   280  	makeTestContentInDir(c, tmpDir)
   281  
   282  	srcPath := cpPath(tmpDir, "file1")
   283  	dstPath := containerCpPath(containerID, "/root/file2")
   284  
   285  	// Ensure the container's file starts with the original content.
   286  	c.Assert(containerStartOutputEquals(c, containerID, "file2\n"), checker.IsNil)
   287  
   288  	c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
   289  
   290  	// Should now contain file1's contents.
   291  	c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
   292  }
   293  
   294  // D. SRC specifies a file and DST exists as a directory. This should place
   295  //    a copy of the source file inside it using the basename from SRC. Ensure
   296  //    this works whether DST has a trailing path separator or not.
   297  func (s *DockerSuite) TestCpToCaseD(c *check.C) {
   298  	testRequires(c, DaemonIsLinux)
   299  	containerID := makeTestContainer(c, testContainerOptions{
   300  		addContent: true,
   301  		command:    makeCatFileCommand("/dir1/file1"),
   302  	})
   303  
   304  	tmpDir := getTestDir(c, "test-cp-to-case-d")
   305  	defer os.RemoveAll(tmpDir)
   306  
   307  	makeTestContentInDir(c, tmpDir)
   308  
   309  	srcPath := cpPath(tmpDir, "file1")
   310  	dstDir := containerCpPath(containerID, "dir1")
   311  
   312  	// Ensure that dstPath doesn't exist.
   313  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   314  
   315  	c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil)
   316  
   317  	// Should now contain file1's contents.
   318  	c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
   319  
   320  	// Now try again but using a trailing path separator for dstDir.
   321  
   322  	// Make new destination container.
   323  	containerID = makeTestContainer(c, testContainerOptions{
   324  		addContent: true,
   325  		command:    makeCatFileCommand("/dir1/file1"),
   326  	})
   327  
   328  	dstDir = containerCpPathTrailingSep(containerID, "dir1")
   329  
   330  	// Ensure that dstPath doesn't exist.
   331  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   332  
   333  	c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil)
   334  
   335  	// Should now contain file1's contents.
   336  	c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
   337  }
   338  
   339  // E. SRC specifies a directory and DST does not exist. This should create a
   340  //    directory at DST and copy the contents of the SRC directory into the DST
   341  //    directory. Ensure this works whether DST has a trailing path separator or
   342  //    not.
   343  func (s *DockerSuite) TestCpToCaseE(c *check.C) {
   344  	containerID := makeTestContainer(c, testContainerOptions{
   345  		command: makeCatFileCommand("/testDir/file1-1"),
   346  	})
   347  
   348  	tmpDir := getTestDir(c, "test-cp-to-case-e")
   349  	defer os.RemoveAll(tmpDir)
   350  
   351  	makeTestContentInDir(c, tmpDir)
   352  
   353  	srcDir := cpPath(tmpDir, "dir1")
   354  	dstDir := containerCpPath(containerID, "testDir")
   355  
   356  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   357  
   358  	// Should now contain file1-1's contents.
   359  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   360  
   361  	// Now try again but using a trailing path separator for dstDir.
   362  
   363  	// Make new destination container.
   364  	containerID = makeTestContainer(c, testContainerOptions{
   365  		command: makeCatFileCommand("/testDir/file1-1"),
   366  	})
   367  
   368  	dstDir = containerCpPathTrailingSep(containerID, "testDir")
   369  
   370  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   371  
   372  	// Should now contain file1-1's contents.
   373  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   374  }
   375  
   376  // F. SRC specifies a directory and DST exists as a file. This should cause an
   377  //    error as it is not possible to overwrite a file with a directory.
   378  func (s *DockerSuite) TestCpToCaseF(c *check.C) {
   379  	testRequires(c, DaemonIsLinux)
   380  	containerID := makeTestContainer(c, testContainerOptions{
   381  		addContent: true, workDir: "/root",
   382  	})
   383  
   384  	tmpDir := getTestDir(c, "test-cp-to-case-f")
   385  	defer os.RemoveAll(tmpDir)
   386  
   387  	makeTestContentInDir(c, tmpDir)
   388  
   389  	srcDir := cpPath(tmpDir, "dir1")
   390  	dstFile := containerCpPath(containerID, "/root/file1")
   391  
   392  	err := runDockerCp(c, srcDir, dstFile)
   393  	c.Assert(err, checker.NotNil)
   394  
   395  	c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err))
   396  }
   397  
   398  // G. SRC specifies a directory and DST exists as a directory. This should copy
   399  //    the SRC directory and all its contents to the DST directory. Ensure this
   400  //    works whether DST has a trailing path separator or not.
   401  func (s *DockerSuite) TestCpToCaseG(c *check.C) {
   402  	testRequires(c, DaemonIsLinux)
   403  	containerID := makeTestContainer(c, testContainerOptions{
   404  		addContent: true, workDir: "/root",
   405  		command: makeCatFileCommand("dir2/dir1/file1-1"),
   406  	})
   407  
   408  	tmpDir := getTestDir(c, "test-cp-to-case-g")
   409  	defer os.RemoveAll(tmpDir)
   410  
   411  	makeTestContentInDir(c, tmpDir)
   412  
   413  	srcDir := cpPath(tmpDir, "dir1")
   414  	dstDir := containerCpPath(containerID, "/root/dir2")
   415  
   416  	// Ensure that dstPath doesn't exist.
   417  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   418  
   419  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   420  
   421  	// Should now contain file1-1's contents.
   422  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   423  
   424  	// Now try again but using a trailing path separator for dstDir.
   425  
   426  	// Make new destination container.
   427  	containerID = makeTestContainer(c, testContainerOptions{
   428  		addContent: true,
   429  		command:    makeCatFileCommand("/dir2/dir1/file1-1"),
   430  	})
   431  
   432  	dstDir = containerCpPathTrailingSep(containerID, "/dir2")
   433  
   434  	// Ensure that dstPath doesn't exist.
   435  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   436  
   437  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   438  
   439  	// Should now contain file1-1's contents.
   440  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   441  }
   442  
   443  // H. SRC specifies a directory's contents only and DST does not exist. This
   444  //    should create a directory at DST and copy the contents of the SRC
   445  //    directory (but not the directory itself) into the DST directory. Ensure
   446  //    this works whether DST has a trailing path separator or not.
   447  func (s *DockerSuite) TestCpToCaseH(c *check.C) {
   448  	containerID := makeTestContainer(c, testContainerOptions{
   449  		command: makeCatFileCommand("/testDir/file1-1"),
   450  	})
   451  
   452  	tmpDir := getTestDir(c, "test-cp-to-case-h")
   453  	defer os.RemoveAll(tmpDir)
   454  
   455  	makeTestContentInDir(c, tmpDir)
   456  
   457  	srcDir := cpPathTrailingSep(tmpDir, "dir1") + "."
   458  	dstDir := containerCpPath(containerID, "testDir")
   459  
   460  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   461  
   462  	// Should now contain file1-1's contents.
   463  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   464  
   465  	// Now try again but using a trailing path separator for dstDir.
   466  
   467  	// Make new destination container.
   468  	containerID = makeTestContainer(c, testContainerOptions{
   469  		command: makeCatFileCommand("/testDir/file1-1"),
   470  	})
   471  
   472  	dstDir = containerCpPathTrailingSep(containerID, "testDir")
   473  
   474  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   475  
   476  	// Should now contain file1-1's contents.
   477  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   478  }
   479  
   480  // I. SRC specifies a directory's contents only and DST exists as a file. This
   481  //    should cause an error as it is not possible to overwrite a file with a
   482  //    directory.
   483  func (s *DockerSuite) TestCpToCaseI(c *check.C) {
   484  	testRequires(c, DaemonIsLinux)
   485  	containerID := makeTestContainer(c, testContainerOptions{
   486  		addContent: true, workDir: "/root",
   487  	})
   488  
   489  	tmpDir := getTestDir(c, "test-cp-to-case-i")
   490  	defer os.RemoveAll(tmpDir)
   491  
   492  	makeTestContentInDir(c, tmpDir)
   493  
   494  	srcDir := cpPathTrailingSep(tmpDir, "dir1") + "."
   495  	dstFile := containerCpPath(containerID, "/root/file1")
   496  
   497  	err := runDockerCp(c, srcDir, dstFile)
   498  	c.Assert(err, checker.NotNil)
   499  
   500  	c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err))
   501  }
   502  
   503  // J. SRC specifies a directory's contents only and DST exists as a directory.
   504  //    This should copy the contents of the SRC directory (but not the directory
   505  //    itself) into the DST directory. Ensure this works whether DST has a
   506  //    trailing path separator or not.
   507  func (s *DockerSuite) TestCpToCaseJ(c *check.C) {
   508  	testRequires(c, DaemonIsLinux)
   509  	containerID := makeTestContainer(c, testContainerOptions{
   510  		addContent: true, workDir: "/root",
   511  		command: makeCatFileCommand("/dir2/file1-1"),
   512  	})
   513  
   514  	tmpDir := getTestDir(c, "test-cp-to-case-j")
   515  	defer os.RemoveAll(tmpDir)
   516  
   517  	makeTestContentInDir(c, tmpDir)
   518  
   519  	srcDir := cpPathTrailingSep(tmpDir, "dir1") + "."
   520  	dstDir := containerCpPath(containerID, "/dir2")
   521  
   522  	// Ensure that dstPath doesn't exist.
   523  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   524  
   525  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   526  
   527  	// Should now contain file1-1's contents.
   528  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   529  
   530  	// Now try again but using a trailing path separator for dstDir.
   531  
   532  	// Make new destination container.
   533  	containerID = makeTestContainer(c, testContainerOptions{
   534  		command: makeCatFileCommand("/dir2/file1-1"),
   535  	})
   536  
   537  	dstDir = containerCpPathTrailingSep(containerID, "/dir2")
   538  
   539  	// Ensure that dstPath doesn't exist.
   540  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   541  
   542  	c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
   543  
   544  	// Should now contain file1-1's contents.
   545  	c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
   546  }
   547  
   548  // The `docker cp` command should also ensure that you cannot
   549  // write to a container rootfs that is marked as read-only.
   550  func (s *DockerSuite) TestCpToErrReadOnlyRootfs(c *check.C) {
   551  	// --read-only + userns has remount issues
   552  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   553  	tmpDir := getTestDir(c, "test-cp-to-err-read-only-rootfs")
   554  	defer os.RemoveAll(tmpDir)
   555  
   556  	makeTestContentInDir(c, tmpDir)
   557  
   558  	containerID := makeTestContainer(c, testContainerOptions{
   559  		readOnly: true, workDir: "/root",
   560  		command: makeCatFileCommand("shouldNotExist"),
   561  	})
   562  
   563  	srcPath := cpPath(tmpDir, "file1")
   564  	dstPath := containerCpPath(containerID, "/root/shouldNotExist")
   565  
   566  	err := runDockerCp(c, srcPath, dstPath)
   567  	c.Assert(err, checker.NotNil)
   568  
   569  	c.Assert(isCpCannotCopyReadOnly(err), checker.True, check.Commentf("expected ErrContainerRootfsReadonly error, but got %T: %s", err, err))
   570  
   571  	// Ensure that dstPath doesn't exist.
   572  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   573  }
   574  
   575  // The `docker cp` command should also ensure that you
   576  // cannot write to a volume that is mounted as read-only.
   577  func (s *DockerSuite) TestCpToErrReadOnlyVolume(c *check.C) {
   578  	// --read-only + userns has remount issues
   579  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   580  	tmpDir := getTestDir(c, "test-cp-to-err-read-only-volume")
   581  	defer os.RemoveAll(tmpDir)
   582  
   583  	makeTestContentInDir(c, tmpDir)
   584  
   585  	containerID := makeTestContainer(c, testContainerOptions{
   586  		volumes: defaultVolumes(tmpDir), workDir: "/root",
   587  		command: makeCatFileCommand("/vol_ro/shouldNotExist"),
   588  	})
   589  
   590  	srcPath := cpPath(tmpDir, "file1")
   591  	dstPath := containerCpPath(containerID, "/vol_ro/shouldNotExist")
   592  
   593  	err := runDockerCp(c, srcPath, dstPath)
   594  	c.Assert(err, checker.NotNil)
   595  
   596  	c.Assert(isCpCannotCopyReadOnly(err), checker.True, check.Commentf("expected ErrVolumeReadonly error, but got %T: %s", err, err))
   597  
   598  	// Ensure that dstPath doesn't exist.
   599  	c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
   600  }