Browse code

Fixes #5152 : symlink in volume path

Docker-DCO-1.1-Signed-off-by: Tibor Vass <teabee89@gmail.com> (github: tiborvass)

Tibor Vass authored on 2014/04/25 10:22:22
Showing 3 changed files
... ...
@@ -217,15 +217,26 @@ func createVolumes(container *Container) error {
217 217
 			srcPath = p
218 218
 		}
219 219
 
220
-		container.Volumes[volPath] = srcPath
221
-		container.VolumesRW[volPath] = srcRW
222
-
223 220
 		// Create the mountpoint
224
-		volPath = filepath.Join(container.basefs, volPath)
225
-		rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.basefs)
221
+		rootVolPath, err := utils.FollowSymlinkInScope(filepath.Join(container.basefs, volPath), container.basefs)
222
+		if err != nil {
223
+			return err
224
+		}
225
+
226
+		newVolPath, err := filepath.Rel(container.basefs, rootVolPath)
226 227
 		if err != nil {
227 228
 			return err
228 229
 		}
230
+		newVolPath = "/" + newVolPath
231
+
232
+		if volPath != newVolPath {
233
+			delete(container.Volumes, volPath)
234
+			delete(container.VolumesRW, volPath)
235
+		}
236
+
237
+		container.Volumes[newVolPath] = srcPath
238
+		container.VolumesRW[newVolPath] = srcRW
239
+
229 240
 		if err := createIfNotExists(rootVolPath, volIsDir); err != nil {
230 241
 			return err
231 242
 		}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"os"
6 6
 	"os/exec"
7
+	"path/filepath"
7 8
 	"regexp"
8 9
 	"sort"
9 10
 	"strings"
... ...
@@ -424,6 +425,48 @@ func TestCreateVolume(t *testing.T) {
424 424
 	logDone("run - create docker mangaed volume")
425 425
 }
426 426
 
427
+// Test that creating a volume with a symlink in its path works correctly. Test for #5152.
428
+// Note that this bug happens only with symlinks with a target that starts with '/'.
429
+func TestVolumeWithSymlink(t *testing.T) {
430
+	buildDirectory := filepath.Join(workingDirectory, "run_tests", "TestVolumeWithSymlink")
431
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-volumewithsymlink", ".")
432
+	buildCmd.Dir = buildDirectory
433
+	err := buildCmd.Run()
434
+	if err != nil {
435
+		t.Fatal("could not build 'docker-test-volumewithsymlink': %v", err)
436
+	}
437
+
438
+	cmd := exec.Command(dockerBinary, "run", "-v", "/bar/foo", "--name", "test-volumewithsymlink", "docker-test-volumewithsymlink", "sh", "-c", "mount | grep -q /foo/foo")
439
+	exitCode, err := runCommand(cmd)
440
+	if err != nil || exitCode != 0 {
441
+		t.Fatal("[run] err: %v, exitcode: %d", err, exitCode)
442
+	}
443
+
444
+	var volPath string
445
+	cmd = exec.Command(dockerBinary, "inspect", "-f", "{{range .Volumes}}{{.}}{{end}}", "test-volumewithsymlink")
446
+	volPath, exitCode, err = runCommandWithOutput(cmd)
447
+	if err != nil || exitCode != 0 {
448
+		t.Fatal("[inspect] err: %v, exitcode: %d", err, exitCode)
449
+	}
450
+
451
+	cmd = exec.Command(dockerBinary, "rm", "-v", "test-volumewithsymlink")
452
+	exitCode, err = runCommand(cmd)
453
+	if err != nil || exitCode != 0 {
454
+		t.Fatal("[rm] err: %v, exitcode: %d", err, exitCode)
455
+	}
456
+
457
+	f, err := os.Open(volPath)
458
+	defer f.Close()
459
+	if !os.IsNotExist(err) {
460
+		t.Fatal("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath)
461
+	}
462
+
463
+	deleteImages("docker-test-volumewithsymlink")
464
+	deleteAllContainers()
465
+
466
+	logDone("run - volume with symlink")
467
+}
468
+
427 469
 func TestExitCode(t *testing.T) {
428 470
 	cmd := exec.Command(dockerBinary, "run", "busybox", "/bin/sh", "-c", "exit 72")
429 471
 
430 472
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+FROM busybox
1
+
2
+RUN mkdir /foo && ln -s /foo /bar