Fix copy API (`docker cp`, etc) uid/gid handling
Anusha Ragunathan authored on 2017/04/13 00:21:17... | ... |
@@ -27,7 +27,7 @@ type copyBackend interface { |
27 | 27 |
ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) |
28 | 28 |
ContainerCopy(name string, res string) (io.ReadCloser, error) |
29 | 29 |
ContainerExport(name string, out io.Writer) error |
30 |
- ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error |
|
30 |
+ ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error |
|
31 | 31 |
ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error) |
32 | 32 |
} |
33 | 33 |
|
... | ... |
@@ -112,5 +112,7 @@ func (s *containerRouter) putContainersArchive(ctx context.Context, w http.Respo |
112 | 112 |
} |
113 | 113 |
|
114 | 114 |
noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir") |
115 |
- return s.backend.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body) |
|
115 |
+ copyUIDGID := httputils.BoolValue(r, "copyUIDGID") |
|
116 |
+ |
|
117 |
+ return s.backend.ContainerExtractToDir(v.Name, v.Path, copyUIDGID, noOverwriteDirNonDir, r.Body) |
|
116 | 118 |
} |
... | ... |
@@ -20,6 +20,7 @@ type copyOptions struct { |
20 | 20 |
source string |
21 | 21 |
destination string |
22 | 22 |
followLink bool |
23 |
+ copyUIDGID bool |
|
23 | 24 |
} |
24 | 25 |
|
25 | 26 |
type copyDirection int |
... | ... |
@@ -66,6 +67,7 @@ func NewCopyCommand(dockerCli *command.DockerCli) *cobra.Command { |
66 | 66 |
flags := cmd.Flags() |
67 | 67 |
|
68 | 68 |
flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH") |
69 |
+ flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)") |
|
69 | 70 |
|
70 | 71 |
return cmd |
71 | 72 |
} |
... | ... |
@@ -92,7 +94,7 @@ func runCopy(dockerCli *command.DockerCli, opts copyOptions) error { |
92 | 92 |
case fromContainer: |
93 | 93 |
return copyFromContainer(ctx, dockerCli, srcContainer, srcPath, dstPath, cpParam) |
94 | 94 |
case toContainer: |
95 |
- return copyToContainer(ctx, dockerCli, srcPath, dstContainer, dstPath, cpParam) |
|
95 |
+ return copyToContainer(ctx, dockerCli, srcPath, dstContainer, dstPath, cpParam, opts.copyUIDGID) |
|
96 | 96 |
case acrossContainers: |
97 | 97 |
// Copying between containers isn't supported. |
98 | 98 |
return errors.New("copying between containers is not supported") |
... | ... |
@@ -175,7 +177,7 @@ func copyFromContainer(ctx context.Context, dockerCli *command.DockerCli, srcCon |
175 | 175 |
return archive.CopyTo(preArchive, srcInfo, dstPath) |
176 | 176 |
} |
177 | 177 |
|
178 |
-func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath, dstContainer, dstPath string, cpParam *cpConfig) (err error) { |
|
178 |
+func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath, dstContainer, dstPath string, cpParam *cpConfig, copyUIDGID bool) (err error) { |
|
179 | 179 |
if srcPath != "-" { |
180 | 180 |
// Get an absolute source path. |
181 | 181 |
srcPath, err = resolveLocalPath(srcPath) |
... | ... |
@@ -265,6 +267,7 @@ func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath, |
265 | 265 |
|
266 | 266 |
options := types.CopyToContainerOptions{ |
267 | 267 |
AllowOverwriteDirWithFile: false, |
268 |
+ CopyUIDGID: copyUIDGID, |
|
268 | 269 |
} |
269 | 270 |
|
270 | 271 |
return dockerCli.Client().CopyToContainer(ctx, dstContainer, resolvedDstPath, content, options) |
... | ... |
@@ -38,6 +38,10 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string, |
38 | 38 |
query.Set("noOverwriteDirNonDir", "true") |
39 | 39 |
} |
40 | 40 |
|
41 |
+ if options.CopyUIDGID { |
|
42 |
+ query.Set("copyUIDGID", "true") |
|
43 |
+ } |
|
44 |
+ |
|
41 | 45 |
apiPath := fmt.Sprintf("/containers/%s/archive", container) |
42 | 46 |
|
43 | 47 |
response, err := cli.putRaw(ctx, apiPath, query, content, nil) |
... | ... |
@@ -83,7 +83,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io |
83 | 83 |
// be ErrExtractPointNotDirectory. If noOverwriteDirNonDir is true then it will |
84 | 84 |
// be an error if unpacking the given content would cause an existing directory |
85 | 85 |
// to be replaced with a non-directory and vice versa. |
86 |
-func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error { |
|
86 |
+func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error { |
|
87 | 87 |
container, err := daemon.GetContainer(name) |
88 | 88 |
if err != nil { |
89 | 89 |
return err |
... | ... |
@@ -94,7 +94,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNon |
94 | 94 |
return err |
95 | 95 |
} |
96 | 96 |
|
97 |
- return daemon.containerExtractToDir(container, path, noOverwriteDirNonDir, content) |
|
97 |
+ return daemon.containerExtractToDir(container, path, copyUIDGID, noOverwriteDirNonDir, content) |
|
98 | 98 |
} |
99 | 99 |
|
100 | 100 |
// containerStatPath stats the filesystem resource at the specified path in this |
... | ... |
@@ -196,7 +196,7 @@ func (daemon *Daemon) containerArchivePath(container *container.Container, path |
196 | 196 |
// noOverwriteDirNonDir is true then it will be an error if unpacking the |
197 | 197 |
// given content would cause an existing directory to be replaced with a non- |
198 | 198 |
// directory and vice versa. |
199 |
-func (daemon *Daemon) containerExtractToDir(container *container.Container, path string, noOverwriteDirNonDir bool, content io.Reader) (err error) { |
|
199 |
+func (daemon *Daemon) containerExtractToDir(container *container.Container, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) (err error) { |
|
200 | 200 |
container.Lock() |
201 | 201 |
defer container.Unlock() |
202 | 202 |
|
... | ... |
@@ -279,13 +279,18 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path |
279 | 279 |
return ErrRootFSReadOnly |
280 | 280 |
} |
281 | 281 |
|
282 |
- uid, gid := daemon.GetRemappedUIDGID() |
|
283 |
- options := &archive.TarOptions{ |
|
284 |
- NoOverwriteDirNonDir: noOverwriteDirNonDir, |
|
285 |
- ChownOpts: &archive.TarChownOptions{ |
|
286 |
- UID: uid, GID: gid, // TODO: should all ownership be set to root (either real or remapped)? |
|
287 |
- }, |
|
282 |
+ options := daemon.defaultTarCopyOptions(noOverwriteDirNonDir) |
|
283 |
+ |
|
284 |
+ if copyUIDGID { |
|
285 |
+ var err error |
|
286 |
+ // tarCopyOptions will appropriately pull in the right uid/gid for the |
|
287 |
+ // user/group and will set the options. |
|
288 |
+ options, err = daemon.tarCopyOptions(container, noOverwriteDirNonDir) |
|
289 |
+ if err != nil { |
|
290 |
+ return err |
|
291 |
+ } |
|
288 | 292 |
} |
293 |
+ |
|
289 | 294 |
if err := chrootarchive.Untar(content, resolvedPath, options); err != nil { |
290 | 295 |
return err |
291 | 296 |
} |
292 | 297 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,16 @@ |
0 |
+package daemon |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "github.com/docker/docker/pkg/archive" |
|
4 |
+) |
|
5 |
+ |
|
6 |
+// defaultTarCopyOptions is the setting that is used when unpacking an archive |
|
7 |
+// for a copy API event. |
|
8 |
+func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions { |
|
9 |
+ uidMaps, gidMaps := daemon.GetUIDGIDMaps() |
|
10 |
+ return &archive.TarOptions{ |
|
11 |
+ NoOverwriteDirNonDir: noOverwriteDirNonDir, |
|
12 |
+ UIDMaps: uidMaps, |
|
13 |
+ GIDMaps: gidMaps, |
|
14 |
+ } |
|
15 |
+} |
0 | 16 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,28 @@ |
0 |
+// +build !windows |
|
1 |
+ |
|
2 |
+package daemon |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "github.com/docker/docker/container" |
|
6 |
+ "github.com/docker/docker/pkg/archive" |
|
7 |
+ "github.com/docker/docker/pkg/idtools" |
|
8 |
+) |
|
9 |
+ |
|
10 |
+func (daemon *Daemon) tarCopyOptions(container *container.Container, noOverwriteDirNonDir bool) (*archive.TarOptions, error) { |
|
11 |
+ if container.Config.User == "" { |
|
12 |
+ return daemon.defaultTarCopyOptions(noOverwriteDirNonDir), nil |
|
13 |
+ } |
|
14 |
+ |
|
15 |
+ user, err := idtools.LookupUser(container.Config.User) |
|
16 |
+ if err != nil { |
|
17 |
+ return nil, err |
|
18 |
+ } |
|
19 |
+ |
|
20 |
+ return &archive.TarOptions{ |
|
21 |
+ NoOverwriteDirNonDir: noOverwriteDirNonDir, |
|
22 |
+ ChownOpts: &archive.TarChownOptions{ |
|
23 |
+ UID: user.Uid, |
|
24 |
+ GID: user.Gid, |
|
25 |
+ }, |
|
26 |
+ }, nil |
|
27 |
+} |
0 | 28 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,12 @@ |
0 |
+// +build windows |
|
1 |
+ |
|
2 |
+package daemon |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "github.com/docker/docker/container" |
|
6 |
+ "github.com/docker/docker/pkg/archive" |
|
7 |
+) |
|
8 |
+ |
|
9 |
+func (daemon *Daemon) tarCopyOptions(container *container.Container, noOverwriteDirNonDir bool) (*archive.TarOptions, error) { |
|
10 |
+ return daemon.defaultTarCopyOptions(noOverwriteDirNonDir), nil |
|
11 |
+} |
... | ... |
@@ -29,7 +29,7 @@ func (s *DockerSuite) TestCpFromErrSrcNotExists(c *check.C) { |
29 | 29 |
tmpDir := getTestDir(c, "test-cp-from-err-src-not-exists") |
30 | 30 |
defer os.RemoveAll(tmpDir) |
31 | 31 |
|
32 |
- err := runDockerCp(c, containerCpPath(containerID, "file1"), tmpDir) |
|
32 |
+ err := runDockerCp(c, containerCpPath(containerID, "file1"), tmpDir, nil) |
|
33 | 33 |
c.Assert(err, checker.NotNil) |
34 | 34 |
|
35 | 35 |
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -44,7 +44,7 @@ func (s *DockerSuite) TestCpFromErrSrcNotDir(c *check.C) { |
44 | 44 |
tmpDir := getTestDir(c, "test-cp-from-err-src-not-dir") |
45 | 45 |
defer os.RemoveAll(tmpDir) |
46 | 46 |
|
47 |
- err := runDockerCp(c, containerCpPathTrailingSep(containerID, "file1"), tmpDir) |
|
47 |
+ err := runDockerCp(c, containerCpPathTrailingSep(containerID, "file1"), tmpDir, nil) |
|
48 | 48 |
c.Assert(err, checker.NotNil) |
49 | 49 |
|
50 | 50 |
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err)) |
... | ... |
@@ -65,7 +65,7 @@ func (s *DockerSuite) TestCpFromErrDstParentNotExists(c *check.C) { |
65 | 65 |
srcPath := containerCpPath(containerID, "/file1") |
66 | 66 |
dstPath := cpPath(tmpDir, "notExists", "file1") |
67 | 67 |
|
68 |
- err := runDockerCp(c, srcPath, dstPath) |
|
68 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
69 | 69 |
c.Assert(err, checker.NotNil) |
70 | 70 |
|
71 | 71 |
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -73,7 +73,7 @@ func (s *DockerSuite) TestCpFromErrDstParentNotExists(c *check.C) { |
73 | 73 |
// Try with a directory source. |
74 | 74 |
srcPath = containerCpPath(containerID, "/dir1") |
75 | 75 |
|
76 |
- err = runDockerCp(c, srcPath, dstPath) |
|
76 |
+ err = runDockerCp(c, srcPath, dstPath, nil) |
|
77 | 77 |
c.Assert(err, checker.NotNil) |
78 | 78 |
|
79 | 79 |
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -94,7 +94,7 @@ func (s *DockerSuite) TestCpFromErrDstNotDir(c *check.C) { |
94 | 94 |
srcPath := containerCpPath(containerID, "/file1") |
95 | 95 |
dstPath := cpPathTrailingSep(tmpDir, "file1") |
96 | 96 |
|
97 |
- err := runDockerCp(c, srcPath, dstPath) |
|
97 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
98 | 98 |
c.Assert(err, checker.NotNil) |
99 | 99 |
|
100 | 100 |
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err)) |
... | ... |
@@ -102,7 +102,7 @@ func (s *DockerSuite) TestCpFromErrDstNotDir(c *check.C) { |
102 | 102 |
// Try with a directory source. |
103 | 103 |
srcPath = containerCpPath(containerID, "/dir1") |
104 | 104 |
|
105 |
- err = runDockerCp(c, srcPath, dstPath) |
|
105 |
+ err = runDockerCp(c, srcPath, dstPath, nil) |
|
106 | 106 |
c.Assert(err, checker.NotNil) |
107 | 107 |
|
108 | 108 |
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err)) |
... | ... |
@@ -124,7 +124,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) { |
124 | 124 |
srcPath := containerCpPath(containerID, "/file2") |
125 | 125 |
dstPath := cpPath(tmpDir, "symlinkToFile1") |
126 | 126 |
|
127 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
127 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
128 | 128 |
|
129 | 129 |
// The symlink should not have been modified. |
130 | 130 |
c.Assert(symlinkTargetEquals(c, dstPath, "file1"), checker.IsNil) |
... | ... |
@@ -136,7 +136,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) { |
136 | 136 |
// should copy the file into the symlink target directory. |
137 | 137 |
dstPath = cpPath(tmpDir, "symlinkToDir1") |
138 | 138 |
|
139 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
139 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
140 | 140 |
|
141 | 141 |
// The symlink should not have been modified. |
142 | 142 |
c.Assert(symlinkTargetEquals(c, dstPath, "dir1"), checker.IsNil) |
... | ... |
@@ -149,7 +149,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) { |
149 | 149 |
// the contents of the source file. |
150 | 150 |
dstPath = cpPath(tmpDir, "brokenSymlinkToFileX") |
151 | 151 |
|
152 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
152 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
153 | 153 |
|
154 | 154 |
// The symlink should not have been modified. |
155 | 155 |
c.Assert(symlinkTargetEquals(c, dstPath, "fileX"), checker.IsNil) |
... | ... |
@@ -163,7 +163,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) { |
163 | 163 |
srcPath = containerCpPath(containerID, "/dir2") |
164 | 164 |
dstPath = cpPath(tmpDir, "symlinkToDir1") |
165 | 165 |
|
166 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
166 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
167 | 167 |
|
168 | 168 |
// The symlink should not have been modified. |
169 | 169 |
c.Assert(symlinkTargetEquals(c, dstPath, "dir1"), checker.IsNil) |
... | ... |
@@ -177,7 +177,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) { |
177 | 177 |
// should not modify the symlink. |
178 | 178 |
dstPath = cpPath(tmpDir, "brokenSymlinkToDirX") |
179 | 179 |
|
180 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
180 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
181 | 181 |
|
182 | 182 |
// The symlink should not have been modified. |
183 | 183 |
c.Assert(symlinkTargetEquals(c, dstPath, "dirX"), checker.IsNil) |
... | ... |
@@ -217,7 +217,7 @@ func (s *DockerSuite) TestCpFromCaseA(c *check.C) { |
217 | 217 |
srcPath := containerCpPath(containerID, "/root/file1") |
218 | 218 |
dstPath := cpPath(tmpDir, "itWorks.txt") |
219 | 219 |
|
220 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
220 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
221 | 221 |
|
222 | 222 |
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil) |
223 | 223 |
} |
... | ... |
@@ -235,7 +235,7 @@ func (s *DockerSuite) TestCpFromCaseB(c *check.C) { |
235 | 235 |
srcPath := containerCpPath(containerID, "/file1") |
236 | 236 |
dstDir := cpPathTrailingSep(tmpDir, "testDir") |
237 | 237 |
|
238 |
- err := runDockerCp(c, srcPath, dstDir) |
|
238 |
+ err := runDockerCp(c, srcPath, dstDir, nil) |
|
239 | 239 |
c.Assert(err, checker.NotNil) |
240 | 240 |
|
241 | 241 |
c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExists error, but got %T: %s", err, err)) |
... | ... |
@@ -260,7 +260,7 @@ func (s *DockerSuite) TestCpFromCaseC(c *check.C) { |
260 | 260 |
// Ensure the local file starts with different content. |
261 | 261 |
c.Assert(fileContentEquals(c, dstPath, "file2\n"), checker.IsNil) |
262 | 262 |
|
263 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
263 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
264 | 264 |
|
265 | 265 |
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil) |
266 | 266 |
} |
... | ... |
@@ -285,7 +285,7 @@ func (s *DockerSuite) TestCpFromCaseD(c *check.C) { |
285 | 285 |
_, err := os.Stat(dstPath) |
286 | 286 |
c.Assert(os.IsNotExist(err), checker.True, check.Commentf("did not expect dstPath %q to exist", dstPath)) |
287 | 287 |
|
288 |
- c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil) |
|
288 |
+ c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil) |
|
289 | 289 |
|
290 | 290 |
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil) |
291 | 291 |
|
... | ... |
@@ -299,7 +299,7 @@ func (s *DockerSuite) TestCpFromCaseD(c *check.C) { |
299 | 299 |
|
300 | 300 |
dstDir = cpPathTrailingSep(tmpDir, "dir1") |
301 | 301 |
|
302 |
- c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil) |
|
302 |
+ c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil) |
|
303 | 303 |
|
304 | 304 |
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil) |
305 | 305 |
} |
... | ... |
@@ -319,7 +319,7 @@ func (s *DockerSuite) TestCpFromCaseE(c *check.C) { |
319 | 319 |
dstDir := cpPath(tmpDir, "testDir") |
320 | 320 |
dstPath := filepath.Join(dstDir, "file1-1") |
321 | 321 |
|
322 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
322 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
323 | 323 |
|
324 | 324 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
325 | 325 |
|
... | ... |
@@ -330,7 +330,7 @@ func (s *DockerSuite) TestCpFromCaseE(c *check.C) { |
330 | 330 |
|
331 | 331 |
dstDir = cpPathTrailingSep(tmpDir, "testDir") |
332 | 332 |
|
333 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
333 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
334 | 334 |
|
335 | 335 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
336 | 336 |
} |
... | ... |
@@ -351,7 +351,7 @@ func (s *DockerSuite) TestCpFromCaseF(c *check.C) { |
351 | 351 |
srcDir := containerCpPath(containerID, "/root/dir1") |
352 | 352 |
dstFile := cpPath(tmpDir, "file1") |
353 | 353 |
|
354 |
- err := runDockerCp(c, srcDir, dstFile) |
|
354 |
+ err := runDockerCp(c, srcDir, dstFile, nil) |
|
355 | 355 |
c.Assert(err, checker.NotNil) |
356 | 356 |
|
357 | 357 |
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err)) |
... | ... |
@@ -376,7 +376,7 @@ func (s *DockerSuite) TestCpFromCaseG(c *check.C) { |
376 | 376 |
resultDir := filepath.Join(dstDir, "dir1") |
377 | 377 |
dstPath := filepath.Join(resultDir, "file1-1") |
378 | 378 |
|
379 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
379 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
380 | 380 |
|
381 | 381 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
382 | 382 |
|
... | ... |
@@ -390,7 +390,7 @@ func (s *DockerSuite) TestCpFromCaseG(c *check.C) { |
390 | 390 |
|
391 | 391 |
dstDir = cpPathTrailingSep(tmpDir, "dir2") |
392 | 392 |
|
393 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
393 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
394 | 394 |
|
395 | 395 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
396 | 396 |
} |
... | ... |
@@ -410,7 +410,7 @@ func (s *DockerSuite) TestCpFromCaseH(c *check.C) { |
410 | 410 |
dstDir := cpPath(tmpDir, "testDir") |
411 | 411 |
dstPath := filepath.Join(dstDir, "file1-1") |
412 | 412 |
|
413 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
413 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
414 | 414 |
|
415 | 415 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
416 | 416 |
|
... | ... |
@@ -421,7 +421,7 @@ func (s *DockerSuite) TestCpFromCaseH(c *check.C) { |
421 | 421 |
|
422 | 422 |
dstDir = cpPathTrailingSep(tmpDir, "testDir") |
423 | 423 |
|
424 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
424 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
425 | 425 |
|
426 | 426 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
427 | 427 |
} |
... | ... |
@@ -443,7 +443,7 @@ func (s *DockerSuite) TestCpFromCaseI(c *check.C) { |
443 | 443 |
srcDir := containerCpPathTrailingSep(containerID, "/root/dir1") + "." |
444 | 444 |
dstFile := cpPath(tmpDir, "file1") |
445 | 445 |
|
446 |
- err := runDockerCp(c, srcDir, dstFile) |
|
446 |
+ err := runDockerCp(c, srcDir, dstFile, nil) |
|
447 | 447 |
c.Assert(err, checker.NotNil) |
448 | 448 |
|
449 | 449 |
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err)) |
... | ... |
@@ -468,7 +468,7 @@ func (s *DockerSuite) TestCpFromCaseJ(c *check.C) { |
468 | 468 |
dstDir := cpPath(tmpDir, "dir2") |
469 | 469 |
dstPath := filepath.Join(dstDir, "file1-1") |
470 | 470 |
|
471 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
471 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
472 | 472 |
|
473 | 473 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
474 | 474 |
|
... | ... |
@@ -482,7 +482,7 @@ func (s *DockerSuite) TestCpFromCaseJ(c *check.C) { |
482 | 482 |
|
483 | 483 |
dstDir = cpPathTrailingSep(tmpDir, "dir2") |
484 | 484 |
|
485 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
485 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
486 | 486 |
|
487 | 487 |
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil) |
488 | 488 |
} |
... | ... |
@@ -28,7 +28,7 @@ const ( |
28 | 28 |
|
29 | 29 |
// Ensure that an all-local path case returns an error. |
30 | 30 |
func (s *DockerSuite) TestCpLocalOnly(c *check.C) { |
31 |
- err := runDockerCp(c, "foo", "bar") |
|
31 |
+ err := runDockerCp(c, "foo", "bar", nil) |
|
32 | 32 |
c.Assert(err, checker.NotNil) |
33 | 33 |
|
34 | 34 |
c.Assert(err.Error(), checker.Contains, "must specify at least one container source") |
... | ... |
@@ -31,7 +31,7 @@ func (s *DockerSuite) TestCpToErrSrcNotExists(c *check.C) { |
31 | 31 |
srcPath := cpPath(tmpDir, "file1") |
32 | 32 |
dstPath := containerCpPath(containerID, "file1") |
33 | 33 |
|
34 |
- err := runDockerCp(c, srcPath, dstPath) |
|
34 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
35 | 35 |
c.Assert(err, checker.NotNil) |
36 | 36 |
|
37 | 37 |
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -50,7 +50,7 @@ func (s *DockerSuite) TestCpToErrSrcNotDir(c *check.C) { |
50 | 50 |
srcPath := cpPathTrailingSep(tmpDir, "file1") |
51 | 51 |
dstPath := containerCpPath(containerID, "testDir") |
52 | 52 |
|
53 |
- err := runDockerCp(c, srcPath, dstPath) |
|
53 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
54 | 54 |
c.Assert(err, checker.NotNil) |
55 | 55 |
|
56 | 56 |
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err)) |
... | ... |
@@ -71,7 +71,7 @@ func (s *DockerSuite) TestCpToErrDstParentNotExists(c *check.C) { |
71 | 71 |
srcPath := cpPath(tmpDir, "file1") |
72 | 72 |
dstPath := containerCpPath(containerID, "/notExists", "file1") |
73 | 73 |
|
74 |
- err := runDockerCp(c, srcPath, dstPath) |
|
74 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
75 | 75 |
c.Assert(err, checker.NotNil) |
76 | 76 |
|
77 | 77 |
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -79,7 +79,7 @@ func (s *DockerSuite) TestCpToErrDstParentNotExists(c *check.C) { |
79 | 79 |
// Try with a directory source. |
80 | 80 |
srcPath = cpPath(tmpDir, "dir1") |
81 | 81 |
|
82 |
- err = runDockerCp(c, srcPath, dstPath) |
|
82 |
+ err = runDockerCp(c, srcPath, dstPath, nil) |
|
83 | 83 |
c.Assert(err, checker.NotNil) |
84 | 84 |
|
85 | 85 |
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -104,7 +104,7 @@ func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) { |
104 | 104 |
// The client should encounter an error trying to stat the destination |
105 | 105 |
// and then be unable to copy since the destination is asserted to be a |
106 | 106 |
// directory but does not exist. |
107 |
- err := runDockerCp(c, srcPath, dstPath) |
|
107 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
108 | 108 |
c.Assert(err, checker.NotNil) |
109 | 109 |
|
110 | 110 |
c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExist error, but got %T: %s", err, err)) |
... | ... |
@@ -116,7 +116,7 @@ func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) { |
116 | 116 |
// then decide to extract to the parent directory instead with a rebased |
117 | 117 |
// name in the source archive, but this directory would overwrite the |
118 | 118 |
// existing file with the same name. |
119 |
- err = runDockerCp(c, srcPath, dstPath) |
|
119 |
+ err = runDockerCp(c, srcPath, dstPath, nil) |
|
120 | 120 |
c.Assert(err, checker.NotNil) |
121 | 121 |
|
122 | 122 |
c.Assert(isCannotOverwriteNonDirWithDir(err), checker.True, check.Commentf("expected CannotOverwriteNonDirWithDir error, but got %T: %s", err, err)) |
... | ... |
@@ -144,7 +144,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) { |
144 | 144 |
srcPath := cpPath(testVol, "file2") |
145 | 145 |
dstPath := containerCpPath(containerID, "/vol2/symlinkToFile1") |
146 | 146 |
|
147 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
147 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
148 | 148 |
|
149 | 149 |
// The symlink should not have been modified. |
150 | 150 |
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToFile1"), "file1"), checker.IsNil) |
... | ... |
@@ -156,7 +156,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) { |
156 | 156 |
// This should copy the file into the symlink target directory. |
157 | 157 |
dstPath = containerCpPath(containerID, "/vol2/symlinkToDir1") |
158 | 158 |
|
159 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
159 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
160 | 160 |
|
161 | 161 |
// The symlink should not have been modified. |
162 | 162 |
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToDir1"), "dir1"), checker.IsNil) |
... | ... |
@@ -169,7 +169,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) { |
169 | 169 |
// contents of the source file. |
170 | 170 |
dstPath = containerCpPath(containerID, "/vol2/brokenSymlinkToFileX") |
171 | 171 |
|
172 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
172 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
173 | 173 |
|
174 | 174 |
// The symlink should not have been modified. |
175 | 175 |
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "brokenSymlinkToFileX"), "fileX"), checker.IsNil) |
... | ... |
@@ -183,7 +183,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) { |
183 | 183 |
srcPath = cpPath(testVol, "/dir2") |
184 | 184 |
dstPath = containerCpPath(containerID, "/vol2/symlinkToDir1") |
185 | 185 |
|
186 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
186 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
187 | 187 |
|
188 | 188 |
// The symlink should not have been modified. |
189 | 189 |
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToDir1"), "dir1"), checker.IsNil) |
... | ... |
@@ -197,7 +197,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) { |
197 | 197 |
// should not modify the symlink. |
198 | 198 |
dstPath = containerCpPath(containerID, "/vol2/brokenSymlinkToDirX") |
199 | 199 |
|
200 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
200 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
201 | 201 |
|
202 | 202 |
// The symlink should not have been modified. |
203 | 203 |
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "brokenSymlinkToDirX"), "dirX"), checker.IsNil) |
... | ... |
@@ -238,7 +238,7 @@ func (s *DockerSuite) TestCpToCaseA(c *check.C) { |
238 | 238 |
srcPath := cpPath(tmpDir, "file1") |
239 | 239 |
dstPath := containerCpPath(containerID, "/root/itWorks.txt") |
240 | 240 |
|
241 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
241 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
242 | 242 |
|
243 | 243 |
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil) |
244 | 244 |
} |
... | ... |
@@ -259,7 +259,7 @@ func (s *DockerSuite) TestCpToCaseB(c *check.C) { |
259 | 259 |
srcPath := cpPath(tmpDir, "file1") |
260 | 260 |
dstDir := containerCpPathTrailingSep(containerID, "testDir") |
261 | 261 |
|
262 |
- err := runDockerCp(c, srcPath, dstDir) |
|
262 |
+ err := runDockerCp(c, srcPath, dstDir, nil) |
|
263 | 263 |
c.Assert(err, checker.NotNil) |
264 | 264 |
|
265 | 265 |
c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExists error, but got %T: %s", err, err)) |
... | ... |
@@ -285,7 +285,7 @@ func (s *DockerSuite) TestCpToCaseC(c *check.C) { |
285 | 285 |
// Ensure the container's file starts with the original content. |
286 | 286 |
c.Assert(containerStartOutputEquals(c, containerID, "file2\n"), checker.IsNil) |
287 | 287 |
|
288 |
- c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil) |
|
288 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil) |
|
289 | 289 |
|
290 | 290 |
// Should now contain file1's contents. |
291 | 291 |
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil) |
... | ... |
@@ -312,7 +312,7 @@ func (s *DockerSuite) TestCpToCaseD(c *check.C) { |
312 | 312 |
// Ensure that dstPath doesn't exist. |
313 | 313 |
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil) |
314 | 314 |
|
315 |
- c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil) |
|
315 |
+ c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil) |
|
316 | 316 |
|
317 | 317 |
// Should now contain file1's contents. |
318 | 318 |
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil) |
... | ... |
@@ -330,7 +330,7 @@ func (s *DockerSuite) TestCpToCaseD(c *check.C) { |
330 | 330 |
// Ensure that dstPath doesn't exist. |
331 | 331 |
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil) |
332 | 332 |
|
333 |
- c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil) |
|
333 |
+ c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil) |
|
334 | 334 |
|
335 | 335 |
// Should now contain file1's contents. |
336 | 336 |
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil) |
... | ... |
@@ -353,7 +353,7 @@ func (s *DockerSuite) TestCpToCaseE(c *check.C) { |
353 | 353 |
srcDir := cpPath(tmpDir, "dir1") |
354 | 354 |
dstDir := containerCpPath(containerID, "testDir") |
355 | 355 |
|
356 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
356 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
357 | 357 |
|
358 | 358 |
// Should now contain file1-1's contents. |
359 | 359 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -367,7 +367,7 @@ func (s *DockerSuite) TestCpToCaseE(c *check.C) { |
367 | 367 |
|
368 | 368 |
dstDir = containerCpPathTrailingSep(containerID, "testDir") |
369 | 369 |
|
370 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
370 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
371 | 371 |
|
372 | 372 |
// Should now contain file1-1's contents. |
373 | 373 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -389,7 +389,7 @@ func (s *DockerSuite) TestCpToCaseF(c *check.C) { |
389 | 389 |
srcDir := cpPath(tmpDir, "dir1") |
390 | 390 |
dstFile := containerCpPath(containerID, "/root/file1") |
391 | 391 |
|
392 |
- err := runDockerCp(c, srcDir, dstFile) |
|
392 |
+ err := runDockerCp(c, srcDir, dstFile, nil) |
|
393 | 393 |
c.Assert(err, checker.NotNil) |
394 | 394 |
|
395 | 395 |
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err)) |
... | ... |
@@ -416,7 +416,7 @@ func (s *DockerSuite) TestCpToCaseG(c *check.C) { |
416 | 416 |
// Ensure that dstPath doesn't exist. |
417 | 417 |
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil) |
418 | 418 |
|
419 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
419 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
420 | 420 |
|
421 | 421 |
// Should now contain file1-1's contents. |
422 | 422 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -434,7 +434,7 @@ func (s *DockerSuite) TestCpToCaseG(c *check.C) { |
434 | 434 |
// Ensure that dstPath doesn't exist. |
435 | 435 |
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil) |
436 | 436 |
|
437 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
437 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
438 | 438 |
|
439 | 439 |
// Should now contain file1-1's contents. |
440 | 440 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -457,7 +457,7 @@ func (s *DockerSuite) TestCpToCaseH(c *check.C) { |
457 | 457 |
srcDir := cpPathTrailingSep(tmpDir, "dir1") + "." |
458 | 458 |
dstDir := containerCpPath(containerID, "testDir") |
459 | 459 |
|
460 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
460 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
461 | 461 |
|
462 | 462 |
// Should now contain file1-1's contents. |
463 | 463 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -471,7 +471,7 @@ func (s *DockerSuite) TestCpToCaseH(c *check.C) { |
471 | 471 |
|
472 | 472 |
dstDir = containerCpPathTrailingSep(containerID, "testDir") |
473 | 473 |
|
474 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
474 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
475 | 475 |
|
476 | 476 |
// Should now contain file1-1's contents. |
477 | 477 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -494,7 +494,7 @@ func (s *DockerSuite) TestCpToCaseI(c *check.C) { |
494 | 494 |
srcDir := cpPathTrailingSep(tmpDir, "dir1") + "." |
495 | 495 |
dstFile := containerCpPath(containerID, "/root/file1") |
496 | 496 |
|
497 |
- err := runDockerCp(c, srcDir, dstFile) |
|
497 |
+ err := runDockerCp(c, srcDir, dstFile, nil) |
|
498 | 498 |
c.Assert(err, checker.NotNil) |
499 | 499 |
|
500 | 500 |
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err)) |
... | ... |
@@ -522,7 +522,7 @@ func (s *DockerSuite) TestCpToCaseJ(c *check.C) { |
522 | 522 |
// Ensure that dstPath doesn't exist. |
523 | 523 |
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil) |
524 | 524 |
|
525 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
525 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
526 | 526 |
|
527 | 527 |
// Should now contain file1-1's contents. |
528 | 528 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -539,7 +539,7 @@ func (s *DockerSuite) TestCpToCaseJ(c *check.C) { |
539 | 539 |
// Ensure that dstPath doesn't exist. |
540 | 540 |
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil) |
541 | 541 |
|
542 |
- c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil) |
|
542 |
+ c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil) |
|
543 | 543 |
|
544 | 544 |
// Should now contain file1-1's contents. |
545 | 545 |
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil) |
... | ... |
@@ -563,7 +563,7 @@ func (s *DockerSuite) TestCpToErrReadOnlyRootfs(c *check.C) { |
563 | 563 |
srcPath := cpPath(tmpDir, "file1") |
564 | 564 |
dstPath := containerCpPath(containerID, "/root/shouldNotExist") |
565 | 565 |
|
566 |
- err := runDockerCp(c, srcPath, dstPath) |
|
566 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
567 | 567 |
c.Assert(err, checker.NotNil) |
568 | 568 |
|
569 | 569 |
c.Assert(isCpCannotCopyReadOnly(err), checker.True, check.Commentf("expected ErrContainerRootfsReadonly error, but got %T: %s", err, err)) |
... | ... |
@@ -590,7 +590,7 @@ func (s *DockerSuite) TestCpToErrReadOnlyVolume(c *check.C) { |
590 | 590 |
srcPath := cpPath(tmpDir, "file1") |
591 | 591 |
dstPath := containerCpPath(containerID, "/vol_ro/shouldNotExist") |
592 | 592 |
|
593 |
- err := runDockerCp(c, srcPath, dstPath) |
|
593 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
594 | 594 |
c.Assert(err, checker.NotNil) |
595 | 595 |
|
596 | 596 |
c.Assert(isCpCannotCopyReadOnly(err), checker.True, check.Commentf("expected ErrVolumeReadonly error, but got %T: %s", err, err)) |
... | ... |
@@ -14,6 +14,29 @@ import ( |
14 | 14 |
"github.com/go-check/check" |
15 | 15 |
) |
16 | 16 |
|
17 |
+func (s *DockerSuite) TestCpToContainerWithPermissions(c *check.C) { |
|
18 |
+ testRequires(c, SameHostDaemon, DaemonIsLinux) |
|
19 |
+ |
|
20 |
+ tmpDir := getTestDir(c, "test-cp-to-host-with-permissions") |
|
21 |
+ defer os.RemoveAll(tmpDir) |
|
22 |
+ |
|
23 |
+ makeTestContentInDir(c, tmpDir) |
|
24 |
+ |
|
25 |
+ containerName := "permtest" |
|
26 |
+ |
|
27 |
+ _, exc := dockerCmd(c, "create", "--name", containerName, "debian:jessie", "/bin/bash", "-c", "stat -c '%u %g %a' /permdirtest /permdirtest/permtest") |
|
28 |
+ c.Assert(exc, checker.Equals, 0) |
|
29 |
+ defer dockerCmd(c, "rm", "-f", containerName) |
|
30 |
+ |
|
31 |
+ srcPath := cpPath(tmpDir, "permdirtest") |
|
32 |
+ dstPath := containerCpPath(containerName, "/") |
|
33 |
+ c.Assert(runDockerCp(c, srcPath, dstPath, []string{"-a"}), checker.IsNil) |
|
34 |
+ |
|
35 |
+ out, err := startContainerGetOutput(c, containerName) |
|
36 |
+ c.Assert(err, checker.IsNil, check.Commentf("output: %v", out)) |
|
37 |
+ c.Assert(strings.TrimSpace(out), checker.Equals, "2 2 700\n65534 65534 400", check.Commentf("output: %v", out)) |
|
38 |
+} |
|
39 |
+ |
|
17 | 40 |
// Check ownership is root, both in non-userns and userns enabled modes |
18 | 41 |
func (s *DockerSuite) TestCpCheckDestOwnership(c *check.C) { |
19 | 42 |
testRequires(c, DaemonIsLinux, SameHostDaemon) |
... | ... |
@@ -29,7 +52,7 @@ func (s *DockerSuite) TestCpCheckDestOwnership(c *check.C) { |
29 | 29 |
srcPath := cpPath(tmpDir, "file1") |
30 | 30 |
dstPath := containerCpPath(containerID, "/tmpvol", "file1") |
31 | 31 |
|
32 |
- err := runDockerCp(c, srcPath, dstPath) |
|
32 |
+ err := runDockerCp(c, srcPath, dstPath, nil) |
|
33 | 33 |
c.Assert(err, checker.IsNil) |
34 | 34 |
|
35 | 35 |
stat, err := system.Stat(filepath.Join(tmpVolDir, "file1")) |
... | ... |
@@ -7,6 +7,7 @@ import ( |
7 | 7 |
"os" |
8 | 8 |
"os/exec" |
9 | 9 |
"path/filepath" |
10 |
+ "runtime" |
|
10 | 11 |
"strings" |
11 | 12 |
|
12 | 13 |
"github.com/docker/docker/integration-cli/checker" |
... | ... |
@@ -26,6 +27,9 @@ type fileData struct { |
26 | 26 |
filetype fileType |
27 | 27 |
path string |
28 | 28 |
contents string |
29 |
+ uid int |
|
30 |
+ gid int |
|
31 |
+ mode int |
|
29 | 32 |
} |
30 | 33 |
|
31 | 34 |
func (fd fileData) creationCommand() string { |
... | ... |
@@ -55,31 +59,33 @@ func mkFilesCommand(fds []fileData) string { |
55 | 55 |
} |
56 | 56 |
|
57 | 57 |
var defaultFileData = []fileData{ |
58 |
- {ftRegular, "file1", "file1"}, |
|
59 |
- {ftRegular, "file2", "file2"}, |
|
60 |
- {ftRegular, "file3", "file3"}, |
|
61 |
- {ftRegular, "file4", "file4"}, |
|
62 |
- {ftRegular, "file5", "file5"}, |
|
63 |
- {ftRegular, "file6", "file6"}, |
|
64 |
- {ftRegular, "file7", "file7"}, |
|
65 |
- {ftDir, "dir1", ""}, |
|
66 |
- {ftRegular, "dir1/file1-1", "file1-1"}, |
|
67 |
- {ftRegular, "dir1/file1-2", "file1-2"}, |
|
68 |
- {ftDir, "dir2", ""}, |
|
69 |
- {ftRegular, "dir2/file2-1", "file2-1"}, |
|
70 |
- {ftRegular, "dir2/file2-2", "file2-2"}, |
|
71 |
- {ftDir, "dir3", ""}, |
|
72 |
- {ftRegular, "dir3/file3-1", "file3-1"}, |
|
73 |
- {ftRegular, "dir3/file3-2", "file3-2"}, |
|
74 |
- {ftDir, "dir4", ""}, |
|
75 |
- {ftRegular, "dir4/file3-1", "file4-1"}, |
|
76 |
- {ftRegular, "dir4/file3-2", "file4-2"}, |
|
77 |
- {ftDir, "dir5", ""}, |
|
78 |
- {ftSymlink, "symlinkToFile1", "file1"}, |
|
79 |
- {ftSymlink, "symlinkToDir1", "dir1"}, |
|
80 |
- {ftSymlink, "brokenSymlinkToFileX", "fileX"}, |
|
81 |
- {ftSymlink, "brokenSymlinkToDirX", "dirX"}, |
|
82 |
- {ftSymlink, "symlinkToAbsDir", "/root"}, |
|
58 |
+ {ftRegular, "file1", "file1", 0, 0, 0666}, |
|
59 |
+ {ftRegular, "file2", "file2", 0, 0, 0666}, |
|
60 |
+ {ftRegular, "file3", "file3", 0, 0, 0666}, |
|
61 |
+ {ftRegular, "file4", "file4", 0, 0, 0666}, |
|
62 |
+ {ftRegular, "file5", "file5", 0, 0, 0666}, |
|
63 |
+ {ftRegular, "file6", "file6", 0, 0, 0666}, |
|
64 |
+ {ftRegular, "file7", "file7", 0, 0, 0666}, |
|
65 |
+ {ftDir, "dir1", "", 0, 0, 0777}, |
|
66 |
+ {ftRegular, "dir1/file1-1", "file1-1", 0, 0, 0666}, |
|
67 |
+ {ftRegular, "dir1/file1-2", "file1-2", 0, 0, 0666}, |
|
68 |
+ {ftDir, "dir2", "", 0, 0, 0666}, |
|
69 |
+ {ftRegular, "dir2/file2-1", "file2-1", 0, 0, 0666}, |
|
70 |
+ {ftRegular, "dir2/file2-2", "file2-2", 0, 0, 0666}, |
|
71 |
+ {ftDir, "dir3", "", 0, 0, 0666}, |
|
72 |
+ {ftRegular, "dir3/file3-1", "file3-1", 0, 0, 0666}, |
|
73 |
+ {ftRegular, "dir3/file3-2", "file3-2", 0, 0, 0666}, |
|
74 |
+ {ftDir, "dir4", "", 0, 0, 0666}, |
|
75 |
+ {ftRegular, "dir4/file3-1", "file4-1", 0, 0, 0666}, |
|
76 |
+ {ftRegular, "dir4/file3-2", "file4-2", 0, 0, 0666}, |
|
77 |
+ {ftDir, "dir5", "", 0, 0, 0666}, |
|
78 |
+ {ftSymlink, "symlinkToFile1", "file1", 0, 0, 0666}, |
|
79 |
+ {ftSymlink, "symlinkToDir1", "dir1", 0, 0, 0666}, |
|
80 |
+ {ftSymlink, "brokenSymlinkToFileX", "fileX", 0, 0, 0666}, |
|
81 |
+ {ftSymlink, "brokenSymlinkToDirX", "dirX", 0, 0, 0666}, |
|
82 |
+ {ftSymlink, "symlinkToAbsDir", "/root", 0, 0, 0666}, |
|
83 |
+ {ftDir, "permdirtest", "", 2, 2, 0700}, |
|
84 |
+ {ftRegular, "permdirtest/permtest", "perm_test", 65534, 65534, 0400}, |
|
83 | 85 |
} |
84 | 86 |
|
85 | 87 |
func defaultMkContentCommand() string { |
... | ... |
@@ -91,12 +97,16 @@ func makeTestContentInDir(c *check.C, dir string) { |
91 | 91 |
path := filepath.Join(dir, filepath.FromSlash(fd.path)) |
92 | 92 |
switch fd.filetype { |
93 | 93 |
case ftRegular: |
94 |
- c.Assert(ioutil.WriteFile(path, []byte(fd.contents+"\n"), os.FileMode(0666)), checker.IsNil) |
|
94 |
+ c.Assert(ioutil.WriteFile(path, []byte(fd.contents+"\n"), os.FileMode(fd.mode)), checker.IsNil) |
|
95 | 95 |
case ftDir: |
96 |
- c.Assert(os.Mkdir(path, os.FileMode(0777)), checker.IsNil) |
|
96 |
+ c.Assert(os.Mkdir(path, os.FileMode(fd.mode)), checker.IsNil) |
|
97 | 97 |
case ftSymlink: |
98 | 98 |
c.Assert(os.Symlink(fd.contents, path), checker.IsNil) |
99 | 99 |
} |
100 |
+ |
|
101 |
+ if fd.filetype != ftSymlink && runtime.GOOS != "windows" { |
|
102 |
+ c.Assert(os.Chown(path, fd.uid, fd.gid), checker.IsNil) |
|
103 |
+ } |
|
100 | 104 |
} |
101 | 105 |
} |
102 | 106 |
|
... | ... |
@@ -178,10 +188,16 @@ func containerCpPathTrailingSep(containerID string, pathElements ...string) stri |
178 | 178 |
return fmt.Sprintf("%s/", containerCpPath(containerID, pathElements...)) |
179 | 179 |
} |
180 | 180 |
|
181 |
-func runDockerCp(c *check.C, src, dst string) (err error) { |
|
182 |
- c.Logf("running `docker cp %s %s`", src, dst) |
|
181 |
+func runDockerCp(c *check.C, src, dst string, params []string) (err error) { |
|
182 |
+ c.Logf("running `docker cp %s %s %s`", strings.Join(params, " "), src, dst) |
|
183 |
+ |
|
184 |
+ args := []string{"cp"} |
|
185 |
+ |
|
186 |
+ for _, param := range params { |
|
187 |
+ args = append(args, param) |
|
188 |
+ } |
|
183 | 189 |
|
184 |
- args := []string{"cp", src, dst} |
|
190 |
+ args = append(args, src, dst) |
|
185 | 191 |
|
186 | 192 |
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, args...)) |
187 | 193 |
if err != nil { |