func invokeUnpack(decompressedArchive io.ReadCloser, dest string, options *archive.TarOptions) error { // We can't pass a potentially large exclude list directly via cmd line // because we easily overrun the kernel's max argument/environment size // when the full image list is passed (e.g. when this is used by // `docker load`). We will marshall the options via a pipe to the // child r, w, err := os.Pipe() if err != nil { return fmt.Errorf("Untar pipe failure: %v", err) } cmd := reexec.Command("docker-untar", dest) cmd.Stdin = decompressedArchive cmd.ExtraFiles = append(cmd.ExtraFiles, r) output := bytes.NewBuffer(nil) cmd.Stdout = output cmd.Stderr = output if err := cmd.Start(); err != nil { return fmt.Errorf("Untar error on re-exec cmd: %v", err) } //write the options to the pipe for the untar exec to read if err := json.NewEncoder(w).Encode(options); err != nil { return fmt.Errorf("Untar json encode to pipe failed: %v", err) } w.Close() if err := cmd.Wait(); err != nil { return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output) } return nil }
func ApplyLayer(dest string, layer archive.ArchiveReader) (size int64, err error) { dest = filepath.Clean(dest) decompressed, err := archive.DecompressStream(layer) if err != nil { return 0, err } defer decompressed.Close() cmd := reexec.Command("docker-applyLayer", dest) cmd.Stdin = decompressed outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer) cmd.Stdout, cmd.Stderr = outBuf, errBuf if err = cmd.Run(); err != nil { return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf) } fmt.Printf("\n\nApplyLayer stdout: %s stderr: %s\n\n", outBuf, errBuf) // Stdout should be a valid JSON struct representing an applyLayerResponse. response := applyLayerResponse{} decoder := json.NewDecoder(outBuf) if err = decoder.Decode(&response); err != nil { return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err) } return response.LayerSize, nil }