Browse code

Only copy files and change permissions with non bindmount

Michael Crosby authored on 2013/09/20 05:09:19
Showing 2 changed files
... ...
@@ -665,9 +665,11 @@ func (container *Container) Start(hostConfig *HostConfig) error {
665 665
 			continue
666 666
 		}
667 667
 		var srcPath string
668
+		var isBindMount bool
668 669
 		srcRW := false
669 670
 		// If an external bind is defined for this volume, use that as a source
670 671
 		if bindMap, exists := binds[volPath]; exists {
672
+			isBindMount = true
671 673
 			srcPath = bindMap.SrcPath
672 674
 			if strings.ToLower(bindMap.Mode) == "rw" {
673 675
 				srcRW = true
... ...
@@ -691,7 +693,9 @@ func (container *Container) Start(hostConfig *HostConfig) error {
691 691
 		if err := os.MkdirAll(rootVolPath, 0755); err != nil {
692 692
 			return nil
693 693
 		}
694
-		if srcRW {
694
+
695
+		// Do not copy or change permissions if we are mounting from the host
696
+		if srcRW && !isBindMount {
695 697
 			volList, err := ioutil.ReadDir(rootVolPath)
696 698
 			if err != nil {
697 699
 				return err
... ...
@@ -702,22 +706,26 @@ func (container *Container) Start(hostConfig *HostConfig) error {
702 702
 					return err
703 703
 				}
704 704
 				if len(srcList) == 0 {
705
+					// If the source volume is empty copy files from the root into the volume
705 706
 					if err := CopyWithTar(rootVolPath, srcPath); err != nil {
706 707
 						return err
707 708
 					}
708
-				}
709
-			}
710
-			var stat syscall.Stat_t
711
-			if err := syscall.Stat(rootVolPath, &stat); err != nil {
712
-				return err
713
-			}
714
-			var srcStat syscall.Stat_t
715
-			if err := syscall.Stat(srcPath, &srcStat); err != nil {
716
-				return err
717
-			}
718
-			if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
719
-				if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
720
-					return err
709
+
710
+					var stat syscall.Stat_t
711
+					if err := syscall.Stat(rootVolPath, &stat); err != nil {
712
+						return err
713
+					}
714
+					var srcStat syscall.Stat_t
715
+					if err := syscall.Stat(srcPath, &srcStat); err != nil {
716
+						return err
717
+					}
718
+					// Change the source volume's ownership if it differs from the root
719
+					// files that where just copied
720
+					if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
721
+						if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
722
+							return err
723
+						}
724
+					}
721 725
 				}
722 726
 			}
723 727
 		}
... ...
@@ -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) {