Signed-off-by: John Howard <jhoward@microsoft.com>
John Howard authored on 2015/05/28 10:46:13... | ... |
@@ -30,9 +30,15 @@ func untar() { |
30 | 30 |
|
31 | 31 |
var options *archive.TarOptions |
32 | 32 |
|
33 |
- //read the options from the pipe "ExtraFiles" |
|
34 |
- if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil { |
|
35 |
- fatal(err) |
|
33 |
+ if runtime.GOOS != "windows" { |
|
34 |
+ //read the options from the pipe "ExtraFiles" |
|
35 |
+ if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil { |
|
36 |
+ fatal(err) |
|
37 |
+ } |
|
38 |
+ } else { |
|
39 |
+ if err := json.Unmarshal([]byte(os.Getenv("OPT")), &options); err != nil { |
|
40 |
+ fatal(err) |
|
41 |
+ } |
|
36 | 42 |
} |
37 | 43 |
|
38 | 44 |
if err := chroot(flag.Arg(0)); err != nil { |
... | ... |
@@ -68,37 +74,68 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error |
68 | 68 |
if err != nil { |
69 | 69 |
return err |
70 | 70 |
} |
71 |
+ |
|
72 |
+ var data []byte |
|
73 |
+ var r, w *os.File |
|
71 | 74 |
defer decompressedArchive.Close() |
72 | 75 |
|
73 |
- // We can't pass a potentially large exclude list directly via cmd line |
|
74 |
- // because we easily overrun the kernel's max argument/environment size |
|
75 |
- // when the full image list is passed (e.g. when this is used by |
|
76 |
- // `docker load`). We will marshall the options via a pipe to the |
|
77 |
- // child |
|
78 |
- r, w, err := os.Pipe() |
|
79 |
- if err != nil { |
|
80 |
- return fmt.Errorf("Untar pipe failure: %v", err) |
|
76 |
+ if runtime.GOOS != "windows" { |
|
77 |
+ // We can't pass a potentially large exclude list directly via cmd line |
|
78 |
+ // because we easily overrun the kernel's max argument/environment size |
|
79 |
+ // when the full image list is passed (e.g. when this is used by |
|
80 |
+ // `docker load`). We will marshall the options via a pipe to the |
|
81 |
+ // child |
|
82 |
+ |
|
83 |
+ // This solution won't work on Windows as it will fail in golang |
|
84 |
+ // exec_windows.go as at the lowest layer because attr.Files > 3 |
|
85 |
+ r, w, err = os.Pipe() |
|
86 |
+ if err != nil { |
|
87 |
+ return fmt.Errorf("Untar pipe failure: %v", err) |
|
88 |
+ } |
|
89 |
+ } else { |
|
90 |
+ // We can't pass the exclude list directly via cmd line |
|
91 |
+ // because we easily overrun the shell max argument list length |
|
92 |
+ // when the full image list is passed (e.g. when this is used |
|
93 |
+ // by `docker load`). Instead we will add the JSON marshalled |
|
94 |
+ // and placed in the env, which has significantly larger |
|
95 |
+ // max size |
|
96 |
+ data, err = json.Marshal(options) |
|
97 |
+ if err != nil { |
|
98 |
+ return fmt.Errorf("Untar json encode: %v", err) |
|
99 |
+ } |
|
81 | 100 |
} |
101 |
+ |
|
82 | 102 |
cmd := reexec.Command("docker-untar", dest) |
83 | 103 |
cmd.Stdin = decompressedArchive |
84 |
- cmd.ExtraFiles = append(cmd.ExtraFiles, r) |
|
85 |
- output := bytes.NewBuffer(nil) |
|
86 |
- cmd.Stdout = output |
|
87 |
- cmd.Stderr = output |
|
88 | 104 |
|
89 |
- if err := cmd.Start(); err != nil { |
|
90 |
- return fmt.Errorf("Untar error on re-exec cmd: %v", err) |
|
91 |
- } |
|
92 |
- //write the options to the pipe for the untar exec to read |
|
93 |
- if err := json.NewEncoder(w).Encode(options); err != nil { |
|
94 |
- return fmt.Errorf("Untar json encode to pipe failed: %v", err) |
|
95 |
- } |
|
96 |
- w.Close() |
|
105 |
+ if runtime.GOOS != "windows" { |
|
106 |
+ cmd.ExtraFiles = append(cmd.ExtraFiles, r) |
|
107 |
+ output := bytes.NewBuffer(nil) |
|
108 |
+ cmd.Stdout = output |
|
109 |
+ cmd.Stderr = output |
|
110 |
+ |
|
111 |
+ if err := cmd.Start(); err != nil { |
|
112 |
+ return fmt.Errorf("Untar error on re-exec cmd: %v", err) |
|
113 |
+ } |
|
114 |
+ //write the options to the pipe for the untar exec to read |
|
115 |
+ if err := json.NewEncoder(w).Encode(options); err != nil { |
|
116 |
+ return fmt.Errorf("Untar json encode to pipe failed: %v", err) |
|
117 |
+ } |
|
118 |
+ w.Close() |
|
97 | 119 |
|
98 |
- if err := cmd.Wait(); err != nil { |
|
99 |
- return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output) |
|
120 |
+ if err := cmd.Wait(); err != nil { |
|
121 |
+ return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output) |
|
122 |
+ } |
|
123 |
+ return nil |
|
124 |
+ } else { |
|
125 |
+ cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data)) |
|
126 |
+ out, err := cmd.CombinedOutput() |
|
127 |
+ if err != nil { |
|
128 |
+ return fmt.Errorf("Untar %s %s", err, out) |
|
129 |
+ } |
|
130 |
+ return nil |
|
100 | 131 |
} |
101 |
- return nil |
|
132 |
+ |
|
102 | 133 |
} |
103 | 134 |
|
104 | 135 |
func TarUntar(src, dst string) error { |