Browse code

Combine SetupWorkingDirectory for Linux and Windows

Signed-off-by: Darren Stahl <darst@microsoft.com>

Darren Stahl authored on 2016/01/28 06:03:09
Showing 5 changed files
... ...
@@ -22,6 +22,7 @@ import (
22 22
 	"github.com/docker/docker/pkg/promise"
23 23
 	"github.com/docker/docker/pkg/signal"
24 24
 	"github.com/docker/docker/pkg/symlink"
25
+	"github.com/docker/docker/pkg/system"
25 26
 	"github.com/docker/docker/runconfig"
26 27
 	"github.com/docker/docker/volume"
27 28
 	containertypes "github.com/docker/engine-api/types/container"
... ...
@@ -183,6 +184,30 @@ func (container *Container) WriteHostConfig() error {
183 183
 	return json.NewEncoder(f).Encode(&container.HostConfig)
184 184
 }
185 185
 
186
+// SetupWorkingDirectory sets up the container's working directory as set in container.Config.WorkingDir
187
+func (container *Container) SetupWorkingDirectory() error {
188
+	if container.Config.WorkingDir == "" {
189
+		return nil
190
+	}
191
+	container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir)
192
+
193
+	pth, err := container.GetResourcePath(container.Config.WorkingDir)
194
+	if err != nil {
195
+		return err
196
+	}
197
+
198
+	if err := system.MkdirAll(pth, 0755); err != nil {
199
+		pthInfo, err2 := os.Stat(pth)
200
+		if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
201
+			return derr.ErrorCodeNotADir.WithArgs(container.Config.WorkingDir)
202
+		}
203
+
204
+		return err
205
+	}
206
+
207
+	return nil
208
+}
209
+
186 210
 // GetResourcePath evaluates `path` in the scope of the container's BaseFS, with proper path
187 211
 // sanitisation. Symlinks are all scoped to the BaseFS of the container, as
188 212
 // though the container's BaseFS was `/`.
... ...
@@ -199,7 +224,8 @@ func (container *Container) WriteHostConfig() error {
199 199
 func (container *Container) GetResourcePath(path string) (string, error) {
200 200
 	// IMPORTANT - These are paths on the OS where the daemon is running, hence
201 201
 	// any filepath operations must be done in an OS agnostic way.
202
-	cleanPath := filepath.Join(string(os.PathSeparator), path)
202
+
203
+	cleanPath := cleanResourcePath(path)
203 204
 	r, e := symlink.FollowSymlinkInScope(filepath.Join(container.BaseFS, cleanPath), container.BaseFS)
204 205
 	return r, e
205 206
 }
... ...
@@ -398,34 +398,6 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
398 398
 	return createOptions, nil
399 399
 }
400 400
 
401
-// SetupWorkingDirectory sets up the container's working directory as set in container.Config.WorkingDir
402
-func (container *Container) SetupWorkingDirectory() error {
403
-	if container.Config.WorkingDir == "" {
404
-		return nil
405
-	}
406
-	container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir)
407
-
408
-	pth, err := container.GetResourcePath(container.Config.WorkingDir)
409
-	if err != nil {
410
-		return err
411
-	}
412
-
413
-	pthInfo, err := os.Stat(pth)
414
-	if err != nil {
415
-		if !os.IsNotExist(err) {
416
-			return err
417
-		}
418
-
419
-		if err := system.MkdirAll(pth, 0755); err != nil {
420
-			return err
421
-		}
422
-	}
423
-	if pthInfo != nil && !pthInfo.IsDir() {
424
-		return derr.ErrorCodeNotADir.WithArgs(container.Config.WorkingDir)
425
-	}
426
-	return nil
427
-}
428
-
429 401
 // appendNetworkMounts appends any network mounts to the array of mount points passed in
430 402
 func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) {
431 403
 	for _, mnt := range container.NetworkMounts() {
... ...
@@ -768,3 +740,8 @@ func (container *Container) TmpfsMounts() []execdriver.Mount {
768 768
 	}
769 769
 	return mounts
770 770
 }
771
+
772
+// cleanResourcePath cleans a resource path and prepares to combine with mnt path
773
+func cleanResourcePath(path string) string {
774
+	return filepath.Join(string(os.PathSeparator), path)
775
+}
... ...
@@ -3,6 +3,9 @@
3 3
 package container
4 4
 
5 5
 import (
6
+	"os"
7
+	"path/filepath"
8
+
6 9
 	"github.com/docker/docker/daemon/execdriver"
7 10
 	"github.com/docker/docker/volume"
8 11
 	"github.com/docker/engine-api/types/container"
... ...
@@ -22,12 +25,6 @@ func (container *Container) CreateDaemonEnvironment(linkedEnv []string) []string
22 22
 	return container.Config.Env
23 23
 }
24 24
 
25
-// SetupWorkingDirectory initializes the container working directory.
26
-// This is a NOOP In windows.
27
-func (container *Container) SetupWorkingDirectory() error {
28
-	return nil
29
-}
30
-
31 25
 // UnmountIpcMounts unmount Ipc related mounts.
32 26
 // This is a NOOP on windows.
33 27
 func (container *Container) UnmountIpcMounts(unmount func(pth string) error) {
... ...
@@ -59,3 +56,15 @@ func (container *Container) UpdateContainer(hostConfig *container.HostConfig) er
59 59
 func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) {
60 60
 	return volumeMounts, nil
61 61
 }
62
+
63
+// cleanResourcePath cleans a resource path by removing C:\ syntax, and prepares
64
+// to combine with a volume path
65
+func cleanResourcePath(path string) string {
66
+	if len(path) >= 2 {
67
+		c := path[0]
68
+		if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
69
+			path = path[2:]
70
+		}
71
+	}
72
+	return filepath.Join(string(os.PathSeparator), path)
73
+}
... ...
@@ -6568,3 +6568,20 @@ func (s *DockerSuite) TestBuildFailsGitNotCallable(c *check.C) {
6568 6568
 	c.Assert(err, checker.NotNil)
6569 6569
 	c.Assert(out, checker.Contains, "unable to prepare context: unable to find 'git': ")
6570 6570
 }
6571
+
6572
+// TestBuildWorkdirWindowsPath tests that a Windows style path works as a workdir
6573
+func (s *DockerSuite) TestBuildWorkdirWindowsPath(c *check.C) {
6574
+	testRequires(c, DaemonIsWindows)
6575
+	name := "testbuildworkdirwindowspath"
6576
+
6577
+	_, err := buildImage(name, `
6578
+	FROM windowsservercore
6579
+	RUN mkdir C:\\work
6580
+	WORKDIR C:\\work
6581
+	RUN if "%CD%" NEQ "C:\work" exit -1
6582
+	`, true)
6583
+
6584
+	if err != nil {
6585
+		c.Fatal(err)
6586
+	}
6587
+}
... ...
@@ -1723,7 +1723,7 @@ func (s *DockerSuite) TestRunWorkdirExistsAndIsFile(c *check.C) {
1723 1723
 	expected := "Cannot mkdir: /bin/cat is not a directory"
1724 1724
 	if daemonPlatform == "windows" {
1725 1725
 		existingFile = `\windows\system32\ntdll.dll`
1726
-		expected = "The directory name is invalid"
1726
+		expected = `Cannot mkdir: \windows\system32\ntdll.dll is not a directory.`
1727 1727
 	}
1728 1728
 
1729 1729
 	out, exitCode, err := dockerCmdWithError("run", "-w", existingFile, "busybox")