Browse code

Merge pull request #1934 from dotcloud/host-permissions

Only copy files and change permissions with non bindmount

Michael Crosby authored on 2013/09/23 01:40:52
Showing 2 changed files
... ...
@@ -671,9 +671,11 @@ func (container *Container) Start(hostConfig *HostConfig) error {
671 671
 			continue
672 672
 		}
673 673
 		var srcPath string
674
+		var isBindMount bool
674 675
 		srcRW := false
675 676
 		// If an external bind is defined for this volume, use that as a source
676 677
 		if bindMap, exists := binds[volPath]; exists {
678
+			isBindMount = true
677 679
 			srcPath = bindMap.SrcPath
678 680
 			if strings.ToLower(bindMap.Mode) == "rw" {
679 681
 				srcRW = true
... ...
@@ -697,7 +699,9 @@ func (container *Container) Start(hostConfig *HostConfig) error {
697 697
 		if err := os.MkdirAll(rootVolPath, 0755); err != nil {
698 698
 			return nil
699 699
 		}
700
-		if srcRW {
700
+
701
+		// Do not copy or change permissions if we are mounting from the host
702
+		if srcRW && !isBindMount {
701 703
 			volList, err := ioutil.ReadDir(rootVolPath)
702 704
 			if err != nil {
703 705
 				return err
... ...
@@ -708,22 +712,26 @@ func (container *Container) Start(hostConfig *HostConfig) error {
708 708
 					return err
709 709
 				}
710 710
 				if len(srcList) == 0 {
711
+					// If the source volume is empty copy files from the root into the volume
711 712
 					if err := CopyWithTar(rootVolPath, srcPath); err != nil {
712 713
 						return err
713 714
 					}
714
-				}
715
-			}
716
-			var stat syscall.Stat_t
717
-			if err := syscall.Stat(rootVolPath, &stat); err != nil {
718
-				return err
719
-			}
720
-			var srcStat syscall.Stat_t
721
-			if err := syscall.Stat(srcPath, &srcStat); err != nil {
722
-				return err
723
-			}
724
-			if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
725
-				if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
726
-					return err
715
+
716
+					var stat syscall.Stat_t
717
+					if err := syscall.Stat(rootVolPath, &stat); err != nil {
718
+						return err
719
+					}
720
+					var srcStat syscall.Stat_t
721
+					if err := syscall.Stat(srcPath, &srcStat); err != nil {
722
+						return err
723
+					}
724
+					// Change the source volume's ownership if it differs from the root
725
+					// files that where just copied
726
+					if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
727
+						if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
728
+							return err
729
+						}
730
+					}
727 731
 				}
728 732
 			}
729 733
 		}
... ...
@@ -1202,7 +1202,7 @@ func TestCopyVolumeUidGid(t *testing.T) {
1202 1202
 	defer nuke(r)
1203 1203
 
1204 1204
 	// Add directory not owned by root
1205
-	container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && chown daemon.daemon /hello"}, t)
1205
+	container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && touch /hello/test.txt && chown daemon.daemon /hello"}, t)
1206 1206
 	defer r.Destroy(container1)
1207 1207
 
1208 1208
 	if container1.State.Running {
... ...
@@ -1227,18 +1227,10 @@ func TestCopyVolumeUidGid(t *testing.T) {
1227 1227
 	// Test that the uid and gid is copied from the image to the volume
1228 1228
 	tmpDir1 := tempDir(t)
1229 1229
 	defer os.RemoveAll(tmpDir1)
1230
-	stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "stat", "-c", "%U %G", "/hello"}, t)
1230
+	stdout1, _ := runContainer(r, []string{"-v", "/hello", img.ID, "stat", "-c", "%U %G", "/hello"}, t)
1231 1231
 	if !strings.Contains(stdout1, "daemon daemon") {
1232 1232
 		t.Fatal("Container failed to transfer uid and gid to volume")
1233 1233
 	}
1234
-
1235
-	// Test that the uid and gid is not copied from the image when the volume is read only
1236
-	tmpDir2 := tempDir(t)
1237
-	defer os.RemoveAll(tmpDir1)
1238
-	stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "stat", "-c", "%U %G", "/hello"}, t)
1239
-	if strings.Contains(stdout2, "daemon daemon") {
1240
-		t.Fatal("Container transfered uid and gid to volume")
1241
-	}
1242 1234
 }
1243 1235
 
1244 1236
 // Test for #1582
... ...
@@ -1272,27 +1264,10 @@ func TestCopyVolumeContent(t *testing.T) {
1272 1272
 	// Test that the content is copied from the image to the volume
1273 1273
 	tmpDir1 := tempDir(t)
1274 1274
 	defer os.RemoveAll(tmpDir1)
1275
-	stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "find", "/hello"}, t)
1275
+	stdout1, _ := runContainer(r, []string{"-v", "/hello", img.ID, "find", "/hello"}, t)
1276 1276
 	if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) {
1277 1277
 		t.Fatal("Container failed to transfer content to volume")
1278 1278
 	}
1279
-
1280
-	// Test that the content is not copied when the volume is readonly
1281
-	tmpDir2 := tempDir(t)
1282
-	defer os.RemoveAll(tmpDir2)
1283
-	stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "find", "/hello"}, t)
1284
-	if strings.Contains(stdout2, "/hello/local/world") || strings.Contains(stdout2, "/hello/local") {
1285
-		t.Fatal("Container transfered content to readonly volume")
1286
-	}
1287
-
1288
-	// Test that the content is not copied when the volume is non-empty
1289
-	tmpDir3 := tempDir(t)
1290
-	defer os.RemoveAll(tmpDir3)
1291
-	writeFile(path.Join(tmpDir3, "touch-me"), "", t)
1292
-	stdout3, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:rw", tmpDir3), img.ID, "find", "/hello"}, t)
1293
-	if strings.Contains(stdout3, "/hello/local/world") || strings.Contains(stdout3, "/hello/local") || !strings.Contains(stdout3, "/hello/touch-me") {
1294
-		t.Fatal("Container transfered content to non-empty volume")
1295
-	}
1296 1279
 }
1297 1280
 
1298 1281
 func TestBindMounts(t *testing.T) {