Browse code

Windows: chrootarchive refactor

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2015/05/15 07:08:00
Showing 5 changed files
... ...
@@ -9,21 +9,14 @@ import (
9 9
 	"os"
10 10
 	"path/filepath"
11 11
 	"runtime"
12
-	"syscall"
13 12
 
14 13
 	"github.com/docker/docker/pkg/archive"
15 14
 	"github.com/docker/docker/pkg/reexec"
15
+	"github.com/docker/docker/pkg/system"
16 16
 )
17 17
 
18 18
 var chrootArchiver = &archive.Archiver{Untar: Untar}
19 19
 
20
-func chroot(path string) error {
21
-	if err := syscall.Chroot(path); err != nil {
22
-		return err
23
-	}
24
-	return syscall.Chdir("/")
25
-}
26
-
27 20
 func untar() {
28 21
 	runtime.LockOSThread()
29 22
 	flag.Parse()
... ...
@@ -38,7 +31,20 @@ func untar() {
38 38
 	if err := chroot(flag.Arg(0)); err != nil {
39 39
 		fatal(err)
40 40
 	}
41
-	if err := archive.Unpack(os.Stdin, "/", options); err != nil {
41
+
42
+	// Explanation of Windows difference. Windows does not support chroot.
43
+	// untar() is a helper function for the command line in the format
44
+	// "docker docker-untar directory input". In Windows, directory will be
45
+	// something like <pathto>\docker-buildnnnnnnnnn. So, just use that directory
46
+	// directly instead.
47
+	//
48
+	// One example of where this is used is in the docker build command where the
49
+	// dockerfile will be unpacked to the machine on which the daemon runs.
50
+	rootPath := "/"
51
+	if runtime.GOOS == "windows" {
52
+		rootPath = flag.Arg(0)
53
+	}
54
+	if err := archive.Unpack(os.Stdin, rootPath, options); err != nil {
42 55
 		fatal(err)
43 56
 	}
44 57
 	// fully consume stdin in case it is zero padded
... ...
@@ -59,7 +65,7 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error
59 59
 
60 60
 	dest = filepath.Clean(dest)
61 61
 	if _, err := os.Stat(dest); os.IsNotExist(err) {
62
-		if err := os.MkdirAll(dest, 0777); err != nil {
62
+		if err := system.MkdirAll(dest, 0777); err != nil {
63 63
 			return err
64 64
 		}
65 65
 	}
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"io"
8 8
 	"io/ioutil"
9 9
 	"os"
10
-	"path"
11 10
 	"path/filepath"
12 11
 	"strings"
13 12
 	"testing"
... ...
@@ -15,6 +14,7 @@ import (
15 15
 
16 16
 	"github.com/docker/docker/pkg/archive"
17 17
 	"github.com/docker/docker/pkg/reexec"
18
+	"github.com/docker/docker/pkg/system"
18 19
 )
19 20
 
20 21
 func init() {
... ...
@@ -28,7 +28,7 @@ func TestChrootTarUntar(t *testing.T) {
28 28
 	}
29 29
 	defer os.RemoveAll(tmpdir)
30 30
 	src := filepath.Join(tmpdir, "src")
31
-	if err := os.MkdirAll(src, 0700); err != nil {
31
+	if err := system.MkdirAll(src, 0700); err != nil {
32 32
 		t.Fatal(err)
33 33
 	}
34 34
 	if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil {
... ...
@@ -42,7 +42,7 @@ func TestChrootTarUntar(t *testing.T) {
42 42
 		t.Fatal(err)
43 43
 	}
44 44
 	dest := filepath.Join(tmpdir, "src")
45
-	if err := os.MkdirAll(dest, 0700); err != nil {
45
+	if err := system.MkdirAll(dest, 0700); err != nil {
46 46
 		t.Fatal(err)
47 47
 	}
48 48
 	if err := Untar(stream, dest, &archive.TarOptions{ExcludePatterns: []string{"lolo"}}); err != nil {
... ...
@@ -59,7 +59,7 @@ func TestChrootUntarWithHugeExcludesList(t *testing.T) {
59 59
 	}
60 60
 	defer os.RemoveAll(tmpdir)
61 61
 	src := filepath.Join(tmpdir, "src")
62
-	if err := os.MkdirAll(src, 0700); err != nil {
62
+	if err := system.MkdirAll(src, 0700); err != nil {
63 63
 		t.Fatal(err)
64 64
 	}
65 65
 	if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil {
... ...
@@ -70,7 +70,7 @@ func TestChrootUntarWithHugeExcludesList(t *testing.T) {
70 70
 		t.Fatal(err)
71 71
 	}
72 72
 	dest := filepath.Join(tmpdir, "dest")
73
-	if err := os.MkdirAll(dest, 0700); err != nil {
73
+	if err := system.MkdirAll(dest, 0700); err != nil {
74 74
 		t.Fatal(err)
75 75
 	}
76 76
 	options := &archive.TarOptions{}
... ...
@@ -101,11 +101,11 @@ func prepareSourceDirectory(numberOfFiles int, targetPath string, makeSymLinks b
101 101
 	fileData := []byte("fooo")
102 102
 	for n := 0; n < numberOfFiles; n++ {
103 103
 		fileName := fmt.Sprintf("file-%d", n)
104
-		if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
104
+		if err := ioutil.WriteFile(filepath.Join(targetPath, fileName), fileData, 0700); err != nil {
105 105
 			return 0, err
106 106
 		}
107 107
 		if makeSymLinks {
108
-			if err := os.Symlink(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
108
+			if err := os.Symlink(filepath.Join(targetPath, fileName), filepath.Join(targetPath, fileName+"-link")); err != nil {
109 109
 				return 0, err
110 110
 			}
111 111
 		}
... ...
@@ -157,7 +157,7 @@ func TestChrootTarUntarWithSymlink(t *testing.T) {
157 157
 	}
158 158
 	defer os.RemoveAll(tmpdir)
159 159
 	src := filepath.Join(tmpdir, "src")
160
-	if err := os.MkdirAll(src, 0700); err != nil {
160
+	if err := system.MkdirAll(src, 0700); err != nil {
161 161
 		t.Fatal(err)
162 162
 	}
163 163
 	if _, err := prepareSourceDirectory(10, src, true); err != nil {
... ...
@@ -179,7 +179,7 @@ func TestChrootCopyWithTar(t *testing.T) {
179 179
 	}
180 180
 	defer os.RemoveAll(tmpdir)
181 181
 	src := filepath.Join(tmpdir, "src")
182
-	if err := os.MkdirAll(src, 0700); err != nil {
182
+	if err := system.MkdirAll(src, 0700); err != nil {
183 183
 		t.Fatal(err)
184 184
 	}
185 185
 	if _, err := prepareSourceDirectory(10, src, true); err != nil {
... ...
@@ -225,7 +225,7 @@ func TestChrootCopyFileWithTar(t *testing.T) {
225 225
 	}
226 226
 	defer os.RemoveAll(tmpdir)
227 227
 	src := filepath.Join(tmpdir, "src")
228
-	if err := os.MkdirAll(src, 0700); err != nil {
228
+	if err := system.MkdirAll(src, 0700); err != nil {
229 229
 		t.Fatal(err)
230 230
 	}
231 231
 	if _, err := prepareSourceDirectory(10, src, true); err != nil {
... ...
@@ -268,7 +268,7 @@ func TestChrootUntarPath(t *testing.T) {
268 268
 	}
269 269
 	defer os.RemoveAll(tmpdir)
270 270
 	src := filepath.Join(tmpdir, "src")
271
-	if err := os.MkdirAll(src, 0700); err != nil {
271
+	if err := system.MkdirAll(src, 0700); err != nil {
272 272
 		t.Fatal(err)
273 273
 	}
274 274
 	if _, err := prepareSourceDirectory(10, src, true); err != nil {
... ...
@@ -329,7 +329,7 @@ func TestChrootUntarEmptyArchiveFromSlowReader(t *testing.T) {
329 329
 	}
330 330
 	defer os.RemoveAll(tmpdir)
331 331
 	dest := filepath.Join(tmpdir, "dest")
332
-	if err := os.MkdirAll(dest, 0700); err != nil {
332
+	if err := system.MkdirAll(dest, 0700); err != nil {
333 333
 		t.Fatal(err)
334 334
 	}
335 335
 	stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
... ...
@@ -345,7 +345,7 @@ func TestChrootApplyEmptyArchiveFromSlowReader(t *testing.T) {
345 345
 	}
346 346
 	defer os.RemoveAll(tmpdir)
347 347
 	dest := filepath.Join(tmpdir, "dest")
348
-	if err := os.MkdirAll(dest, 0700); err != nil {
348
+	if err := system.MkdirAll(dest, 0700); err != nil {
349 349
 		t.Fatal(err)
350 350
 	}
351 351
 	stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
... ...
@@ -361,7 +361,7 @@ func TestChrootApplyDotDotFile(t *testing.T) {
361 361
 	}
362 362
 	defer os.RemoveAll(tmpdir)
363 363
 	src := filepath.Join(tmpdir, "src")
364
-	if err := os.MkdirAll(src, 0700); err != nil {
364
+	if err := system.MkdirAll(src, 0700); err != nil {
365 365
 		t.Fatal(err)
366 366
 	}
367 367
 	if err := ioutil.WriteFile(filepath.Join(src, "..gitme"), []byte(""), 0644); err != nil {
... ...
@@ -372,7 +372,7 @@ func TestChrootApplyDotDotFile(t *testing.T) {
372 372
 		t.Fatal(err)
373 373
 	}
374 374
 	dest := filepath.Join(tmpdir, "dest")
375
-	if err := os.MkdirAll(dest, 0700); err != nil {
375
+	if err := system.MkdirAll(dest, 0700); err != nil {
376 376
 		t.Fatal(err)
377 377
 	}
378 378
 	if _, err := ApplyLayer(dest, stream); err != nil {
379 379
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+// +build !windows
1
+
2
+package chrootarchive
3
+
4
+import (
5
+	"syscall"
6
+)
7
+
8
+func chroot(path string) error {
9
+	if err := syscall.Chroot(path); err != nil {
10
+		return err
11
+	}
12
+	return syscall.Chdir("/")
13
+}
0 14
new file mode 100644
... ...
@@ -0,0 +1,6 @@
0
+package chrootarchive
1
+
2
+// chroot is not supported by Windows
3
+func chroot(path string) error {
4
+	return nil
5
+}
... ...
@@ -9,10 +9,10 @@ import (
9 9
 	"os"
10 10
 	"path/filepath"
11 11
 	"runtime"
12
-	"syscall"
13 12
 
14 13
 	"github.com/docker/docker/pkg/archive"
15 14
 	"github.com/docker/docker/pkg/reexec"
15
+	"github.com/docker/docker/pkg/system"
16 16
 )
17 17
 
18 18
 type applyLayerResponse struct {
... ...
@@ -20,23 +20,40 @@ type applyLayerResponse struct {
20 20
 }
21 21
 
22 22
 func applyLayer() {
23
+
24
+	var (
25
+		root   = "/"
26
+		tmpDir = ""
27
+		err    error
28
+	)
29
+
23 30
 	runtime.LockOSThread()
24 31
 	flag.Parse()
25 32
 
26
-	if err := chroot(flag.Arg(0)); err != nil {
27
-		fatal(err)
33
+	if runtime.GOOS != "windows" {
34
+		if err := chroot(flag.Arg(0)); err != nil {
35
+			fatal(err)
36
+		}
37
+
38
+		// We need to be able to set any perms
39
+		oldmask, err := system.Umask(0)
40
+		defer system.Umask(oldmask)
41
+		if err != nil {
42
+			fatal(err)
43
+		}
44
+	} else {
45
+		// As Windows does not support chroot or umask, we use the directory
46
+		// passed in which will be <pathto>\docker-buildnnnnnnnn instead of
47
+		// the 'chroot-root', "/"
48
+		root = flag.Arg(0)
28 49
 	}
29 50
 
30
-	// We need to be able to set any perms
31
-	oldmask := syscall.Umask(0)
32
-	defer syscall.Umask(oldmask)
33
-	tmpDir, err := ioutil.TempDir("/", "temp-docker-extract")
34
-	if err != nil {
51
+	if tmpDir, err = ioutil.TempDir(root, "temp-docker-extract"); err != nil {
35 52
 		fatal(err)
36 53
 	}
37 54
 
38 55
 	os.Setenv("TMPDIR", tmpDir)
39
-	size, err := archive.UnpackLayer("/", os.Stdin)
56
+	size, err := archive.UnpackLayer(root, os.Stdin)
40 57
 	os.RemoveAll(tmpDir)
41 58
 	if err != nil {
42 59
 		fatal(err)