// applyLayerHandler parses a diff in the standard layer format from `layer`, and // applies it to the directory `dest`. Returns the size in bytes of the // contents of the layer. func applyLayerHandler(dest string, layer archive.ArchiveReader, decompress bool) (size int64, err error) { dest = filepath.Clean(dest) if decompress { decompressed, err := archive.DecompressStream(layer) if err != nil { return 0, err } defer decompressed.Close() layer = decompressed } cmd := reexec.Command("docker-applyLayer", dest) cmd.Stdin = layer 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) } // 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 }
func mountFrom(dir, device, target, mType string, flags uintptr, label string) error { options := &mountOptions{ Device: device, Target: target, Type: mType, Flag: uint32(flags), Label: label, } cmd := reexec.Command("docker-mountfrom", dir) w, err := cmd.StdinPipe() if err != nil { return fmt.Errorf("mountfrom error on pipe creation: %v", err) } output := bytes.NewBuffer(nil) cmd.Stdout = output cmd.Stderr = output if err := cmd.Start(); err != nil { return fmt.Errorf("mountfrom 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("mountfrom json encode to pipe failed: %v", err) } w.Close() if err := cmd.Wait(); err != nil { return fmt.Errorf("mountfrom re-exec error: %v: output: %s", err, output) } return nil }
func (r *RootfsWriter) WriteFile(log lager.Logger, filePath string, contents []byte, rootfsPath string, rootUid, rootGid int) error { cmd := reexec.Command("chrootwrite", "-rootfs", rootfsPath, "-path", filePath, "-uid", strconv.Itoa(rootUid), "-gid", strconv.Itoa(rootGid), ) stdin, err := cmd.StdinPipe() if err != nil { return err } if err = cmd.Start(); err != nil { return err } if _, err = stdin.Write(contents); err != nil { return err } if err = stdin.Close(); err != nil { return err } return cmd.Wait() }
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) error { cmd := reexec.Command("docker-applyLayer", dest) cmd.Stdin = layer out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("ApplyLayer %s %s", err, out) } return nil }
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error { if tarArchive == nil { return fmt.Errorf("Empty archive") } if options == nil { options = &archive.TarOptions{} } if options.ExcludePatterns == nil { options.ExcludePatterns = []string{} } dest = filepath.Clean(dest) if _, err := os.Stat(dest); os.IsNotExist(err) { if err := os.MkdirAll(dest, 0777); err != nil { return err } } decompressedArchive, err := archive.DecompressStream(tarArchive) if err != nil { return err } defer decompressedArchive.Close() // 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) var output bytes.Buffer 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 reexecInNamespace(args ...string) { reexecArgs := append([]string{"namespaced"}, args...) cmd := reexec.Command(reexecArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWNS, } if err := cmd.Run(); err != nil { fmt.Printf("secret garden exec failed: %s\n", err) os.Exit(1) } }
func Command(rootfsPath string, uid, gid int, mode os.FileMode, recreate bool, paths ...string) *exec.Cmd { flags := []string{ name, "-rootfsPath", rootfsPath, "-uid", strconv.Itoa(uid), "-gid", strconv.Itoa(gid), "-perm", strconv.Itoa(int(mode.Perm())), } if recreate { flags = append(flags, "-recreate=true") } return reexec.Command(append(flags, paths...)...) }
func runEnqueue(t *testing.T, filename, from, to string) { cmd := reexec.Command("enqueue", filename, from, to) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { t.Fatal(err) } go func() { if err := cmd.Wait(); err != nil { t.Fatal(err) } }() }
func runAllocate(t *testing.T, wg *sync.WaitGroup, memoryRegion, size, qty string) { cmd := reexec.Command("allocate", memoryRegion, size, qty) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { t.Fatal(err) } go func() { defer wg.Done() if err := cmd.Wait(); err != nil { t.Fatal(err) } }() }
// importLayer adds a new layer to the tag and graph store based on the given data. func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPaths []string) (size int64, err error) { cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...) output := bytes.NewBuffer(nil) cmd.Stdin = layerData cmd.Stdout = output cmd.Stderr = output if err = cmd.Start(); err != nil { return } if err = cmd.Wait(); err != nil { return 0, fmt.Errorf("re-exec error: %v: output: %s", err, output) } return strconv.ParseInt(output.String(), 10, 64) }
func (c *Container) Apply(log lager.Logger, cfg kawasaki.NetworkConfig, pid int) error { netns, err := c.FileOpener.Open(fmt.Sprintf("/proc/%d/ns/net", pid)) if err != nil { return err } defer netns.Close() log = log.Session("configure-container-netns", lager.Data{ "networkConfig": cfg, "netNsPath": netns.Name(), }) cmd := reexec.Command("configure-container-netns", "-netNsPath", netns.Name(), "-containerIntf", cfg.ContainerIntf, "-containerIP", cfg.ContainerIP.String(), "-bridgeIP", cfg.BridgeIP.String(), "-subnet", cfg.Subnet.String(), "-mtu", strconv.FormatInt(int64(cfg.Mtu), 10), ) errBuf := bytes.NewBuffer([]byte{}) cmd.Stderr = errBuf if err := cmd.Start(); err != nil { log.Error("starting-command", errors.New(errBuf.String())) return err } if err := cmd.Wait(); err != nil { status, err := exitStatus(err) if err != nil { log.Error("waiting-for-command", errors.New(errBuf.String())) return err } if status == 1 { return errors.New(errBuf.String()) } log.Error("unexpected-error", errors.New(errBuf.String())) return errors.New("unexpected error") } return nil }
// applyLayerHandler parses a diff in the standard layer format from `layer`, and // applies it to the directory `dest`. Returns the size in bytes of the // contents of the layer. func applyLayerHandler(dest string, layer io.Reader, options *archive.TarOptions, decompress bool) (size int64, err error) { dest = filepath.Clean(dest) if decompress { decompressed, err := archive.DecompressStream(layer) if err != nil { return 0, err } defer decompressed.Close() layer = decompressed } if options == nil { options = &archive.TarOptions{} if rsystem.RunningInUserNS() { options.InUserNS = true } } if options.ExcludePatterns == nil { options.ExcludePatterns = []string{} } data, err := json.Marshal(options) if err != nil { return 0, fmt.Errorf("ApplyLayer json encode: %v", err) } cmd := reexec.Command("docker-applyLayer", dest) cmd.Stdin = layer cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data)) 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) } // 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 }
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error { if tarArchive == nil { return fmt.Errorf("Empty archive") } if options == nil { options = &archive.TarOptions{} } if options.ExcludePatterns == nil { options.ExcludePatterns = []string{} } dest = filepath.Clean(dest) if _, err := os.Stat(dest); os.IsNotExist(err) { if err := os.MkdirAll(dest, 0777); err != nil { return err } } // We can't pass the exclude list directly via cmd line // because we easily overrun the shell max argument list length // when the full image list is passed (e.g. when this is used // by `docker load`). Instead we will add the JSON marshalled // and placed in the env, which has significantly larger // max size data, err := json.Marshal(options) if err != nil { return fmt.Errorf("Untar json encode: %v", err) } decompressedArchive, err := archive.DecompressStream(tarArchive) if err != nil { return err } defer decompressedArchive.Close() cmd := reexec.Command("docker-untar", dest) cmd.Stdin = decompressedArchive cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data)) out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("Untar %s %s", err, out) } return nil }
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error { if tarArchive == nil { return fmt.Errorf("Empty archive") } if options == nil { options = &archive.TarOptions{} } if options.ExcludePatterns == nil { options.ExcludePatterns = []string{} } var ( buf bytes.Buffer enc = json.NewEncoder(&buf) ) if err := enc.Encode(options); err != nil { return fmt.Errorf("Untar json encode: %v", err) } if _, err := os.Stat(dest); os.IsNotExist(err) { if err := os.MkdirAll(dest, 0777); err != nil { return err } } dest = filepath.Clean(dest) decompressedArchive, err := archive.DecompressStream(tarArchive) if err != nil { return err } defer decompressedArchive.Close() cmd := reexec.Command("docker-untar", dest, buf.String()) cmd.Stdin = decompressedArchive out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("Untar %s %s", err, out) } return nil }
"io" _ "github.com/cloudfoundry-incubator/garden-linux/container_daemon/proc_starter" "github.com/docker/docker/pkg/reexec" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" ) var _ = Describe("proc_starter", func() { It("runs the process in the specified working directory", func() { testWorkDir, err := ioutil.TempDir("", "") Expect(err).ToNot(HaveOccurred()) cmd := reexec.Command("proc_starter", "-uid=0", "-gid=0", fmt.Sprintf("-workDir=%s", testWorkDir), "--", "/bin/sh", "-c", "echo $PWD") op, err := cmd.CombinedOutput() Expect(err).ToNot(HaveOccurred()) Expect(string(op)).To(Equal(testWorkDir + "\n")) }) It("runs a program from the PATH", func() { cmd := reexec.Command("proc_starter", "-uid=0", "-gid=0", "-workDir=/tmp", "--", "ls", "/") Expect(cmd.Run()).To(Succeed()) }) It("sets rlimits", func() { cmd := reexec.Command("proc_starter", "-uid=0", "-gid=0", "-workDir=/tmp", "-rlimits=RLIMIT_NOFILE=2099,RLIMIT_CPU=3", "--", "sh", "-c", "ulimit -a") out := gbytes.NewBuffer() cmd.Stdout = io.MultiWriter(GinkgoWriter, out) cmd.Stderr = GinkgoWriter
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error { if tarArchive == nil { return fmt.Errorf("Empty archive") } if options == nil { options = &archive.TarOptions{} } if options.ExcludePatterns == nil { options.ExcludePatterns = []string{} } dest = filepath.Clean(dest) if _, err := os.Stat(dest); os.IsNotExist(err) { if err := system.MkdirAll(dest, 0777); err != nil { return err } } decompressedArchive, err := archive.DecompressStream(tarArchive) if err != nil { return err } var data []byte var r, w *os.File defer decompressedArchive.Close() if runtime.GOOS != "windows" { // 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 // This solution won't work on Windows as it will fail in golang // exec_windows.go as at the lowest layer because attr.Files > 3 r, w, err = os.Pipe() if err != nil { return fmt.Errorf("Untar pipe failure: %v", err) } } else { // We can't pass the exclude list directly via cmd line // because we easily overrun the shell max argument list length // when the full image list is passed (e.g. when this is used // by `docker load`). Instead we will add the JSON marshalled // and placed in the env, which has significantly larger // max size data, err = json.Marshal(options) if err != nil { return fmt.Errorf("Untar json encode: %v", err) } } cmd := reexec.Command("docker-untar", dest) cmd.Stdin = decompressedArchive if runtime.GOOS != "windows" { 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 } else { cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data)) out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("Untar %s %s", err, out) } return nil } }