From e9a42a45bfe296850a72ba6ee5e7c0c04534ea34 Mon Sep 17 00:00:00 2001 From: Tibor Vass Date: Thu, 24 Apr 2014 18:22:22 -0700 Subject: [PATCH] Fixes #5152 : symlink in volume path Docker-DCO-1.1-Signed-off-by: Tibor Vass (github: tiborvass) --- daemon/volumes.go | 21 ++++++--- integration-cli/docker_cli_run_test.go | 43 +++++++++++++++++++ .../TestVolumeWithSymlink/Dockerfile | 3 ++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 integration-cli/run_tests/TestVolumeWithSymlink/Dockerfile diff --git a/daemon/volumes.go b/daemon/volumes.go index 4a5c4475b7..66266ef061 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -217,15 +217,26 @@ func createVolumes(container *Container) error { srcPath = p } - container.Volumes[volPath] = srcPath - container.VolumesRW[volPath] = srcRW - // Create the mountpoint - volPath = filepath.Join(container.basefs, volPath) - rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.basefs) + rootVolPath, err := utils.FollowSymlinkInScope(filepath.Join(container.basefs, volPath), container.basefs) if err != nil { return err } + + newVolPath, err := filepath.Rel(container.basefs, rootVolPath) + if err != nil { + return err + } + newVolPath = "/" + newVolPath + + if volPath != newVolPath { + delete(container.Volumes, volPath) + delete(container.VolumesRW, volPath) + } + + container.Volumes[newVolPath] = srcPath + container.VolumesRW[newVolPath] = srcRW + if err := createIfNotExists(rootVolPath, volIsDir); err != nil { return err } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 5973f2fe1b..4a770bef1e 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/exec" + "path/filepath" "regexp" "sort" "strings" @@ -424,6 +425,48 @@ func TestCreateVolume(t *testing.T) { logDone("run - create docker mangaed volume") } +// Test that creating a volume with a symlink in its path works correctly. Test for #5152. +// Note that this bug happens only with symlinks with a target that starts with '/'. +func TestVolumeWithSymlink(t *testing.T) { + buildDirectory := filepath.Join(workingDirectory, "run_tests", "TestVolumeWithSymlink") + buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-volumewithsymlink", ".") + buildCmd.Dir = buildDirectory + err := buildCmd.Run() + if err != nil { + t.Fatal("could not build 'docker-test-volumewithsymlink': %v", err) + } + + cmd := exec.Command(dockerBinary, "run", "-v", "/bar/foo", "--name", "test-volumewithsymlink", "docker-test-volumewithsymlink", "sh", "-c", "mount | grep -q /foo/foo") + exitCode, err := runCommand(cmd) + if err != nil || exitCode != 0 { + t.Fatal("[run] err: %v, exitcode: %d", err, exitCode) + } + + var volPath string + cmd = exec.Command(dockerBinary, "inspect", "-f", "{{range .Volumes}}{{.}}{{end}}", "test-volumewithsymlink") + volPath, exitCode, err = runCommandWithOutput(cmd) + if err != nil || exitCode != 0 { + t.Fatal("[inspect] err: %v, exitcode: %d", err, exitCode) + } + + cmd = exec.Command(dockerBinary, "rm", "-v", "test-volumewithsymlink") + exitCode, err = runCommand(cmd) + if err != nil || exitCode != 0 { + t.Fatal("[rm] err: %v, exitcode: %d", err, exitCode) + } + + f, err := os.Open(volPath) + defer f.Close() + if !os.IsNotExist(err) { + t.Fatal("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath) + } + + deleteImages("docker-test-volumewithsymlink") + deleteAllContainers() + + logDone("run - volume with symlink") +} + func TestExitCode(t *testing.T) { cmd := exec.Command(dockerBinary, "run", "busybox", "/bin/sh", "-c", "exit 72") diff --git a/integration-cli/run_tests/TestVolumeWithSymlink/Dockerfile b/integration-cli/run_tests/TestVolumeWithSymlink/Dockerfile new file mode 100644 index 0000000000..46bed8540b --- /dev/null +++ b/integration-cli/run_tests/TestVolumeWithSymlink/Dockerfile @@ -0,0 +1,3 @@ +FROM busybox + +RUN mkdir /foo && ln -s /foo /bar