2014-10-29 15:06:51 -04:00
|
|
|
package chrootarchive
|
|
|
|
|
|
|
|
import (
|
2014-12-17 21:26:03 -05:00
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
2014-10-29 15:06:51 -04:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
2014-12-08 16:14:56 -05:00
|
|
|
"io"
|
2014-11-18 16:33:13 -05:00
|
|
|
"io/ioutil"
|
2014-10-29 15:06:51 -04:00
|
|
|
"os"
|
2014-12-08 16:14:56 -05:00
|
|
|
"path/filepath"
|
2014-10-29 15:06:51 -04:00
|
|
|
"runtime"
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
"github.com/docker/docker/pkg/archive"
|
|
|
|
"github.com/docker/docker/pkg/reexec"
|
|
|
|
)
|
|
|
|
|
2014-12-17 21:26:03 -05:00
|
|
|
type applyLayerResponse struct {
|
|
|
|
LayerSize int64 `json:"layerSize"`
|
|
|
|
}
|
|
|
|
|
2014-10-29 15:06:51 -04:00
|
|
|
func applyLayer() {
|
|
|
|
runtime.LockOSThread()
|
|
|
|
flag.Parse()
|
|
|
|
|
2014-12-08 16:14:56 -05:00
|
|
|
if err := chroot(flag.Arg(0)); err != nil {
|
2014-10-29 15:06:51 -04:00
|
|
|
fatal(err)
|
|
|
|
}
|
2014-12-17 21:26:03 -05:00
|
|
|
|
2014-12-08 16:14:56 -05:00
|
|
|
// We need to be able to set any perms
|
|
|
|
oldmask := syscall.Umask(0)
|
|
|
|
defer syscall.Umask(oldmask)
|
2014-11-18 16:33:13 -05:00
|
|
|
tmpDir, err := ioutil.TempDir("/", "temp-docker-extract")
|
|
|
|
if err != nil {
|
|
|
|
fatal(err)
|
|
|
|
}
|
2014-12-17 21:26:03 -05:00
|
|
|
|
2014-11-18 16:33:13 -05:00
|
|
|
os.Setenv("TMPDIR", tmpDir)
|
2014-12-17 21:26:03 -05:00
|
|
|
size, err := archive.UnpackLayer("/", os.Stdin)
|
2014-12-08 16:14:56 -05:00
|
|
|
os.RemoveAll(tmpDir)
|
|
|
|
if err != nil {
|
2014-10-29 15:06:51 -04:00
|
|
|
fatal(err)
|
|
|
|
}
|
2014-12-17 21:26:03 -05:00
|
|
|
|
|
|
|
encoder := json.NewEncoder(os.Stdout)
|
|
|
|
if err := encoder.Encode(applyLayerResponse{size}); err != nil {
|
|
|
|
fatal(fmt.Errorf("unable to encode layerSize JSON: %s", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
flush(os.Stdout)
|
2014-12-08 18:04:34 -05:00
|
|
|
flush(os.Stdin)
|
2014-10-29 15:06:51 -04:00
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2014-12-17 21:26:03 -05:00
|
|
|
func ApplyLayer(dest string, layer archive.ArchiveReader) (size int64, err error) {
|
2014-12-08 16:14:56 -05:00
|
|
|
dest = filepath.Clean(dest)
|
|
|
|
decompressed, err := archive.DecompressStream(layer)
|
|
|
|
if err != nil {
|
2014-12-17 21:26:03 -05:00
|
|
|
return 0, err
|
2014-12-08 16:14:56 -05:00
|
|
|
}
|
2014-12-17 21:26:03 -05:00
|
|
|
|
2014-12-08 16:14:56 -05:00
|
|
|
defer func() {
|
|
|
|
if c, ok := decompressed.(io.Closer); ok {
|
|
|
|
c.Close()
|
|
|
|
}
|
|
|
|
}()
|
2014-12-17 21:26:03 -05:00
|
|
|
|
2014-10-29 15:06:51 -04:00
|
|
|
cmd := reexec.Command("docker-applyLayer", dest)
|
2014-12-08 16:14:56 -05:00
|
|
|
cmd.Stdin = decompressed
|
2014-12-17 21:26:03 -05:00
|
|
|
|
|
|
|
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)
|
2014-10-29 15:06:51 -04:00
|
|
|
}
|
2014-12-17 21:26:03 -05:00
|
|
|
|
|
|
|
return response.LayerSize, nil
|
2014-10-29 15:06:51 -04:00
|
|
|
}
|