add pkg/chrootarchive and use it on the daemon
Docker-DCO-1.1-Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com> (github: unclejack) Conflicts: builder/internals.go daemon/graphdriver/aufs/aufs.go daemon/volumes.go fixed conflicts in imports
This commit is contained in:
parent
2746675b42
commit
e19f49915f
6 changed files with 161 additions and 3 deletions
76
chrootarchive/archive.go
Normal file
76
chrootarchive/archive.go
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
package chrootarchive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/archive"
|
||||||
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func untar() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if err := syscall.Chroot(flag.Arg(0)); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
if err := syscall.Chdir("/"); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
if err := archive.Untar(os.Stdin, "/", nil); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
chrootArchiver = &archive.Archiver{Untar}
|
||||||
|
)
|
||||||
|
|
||||||
|
func Untar(archive io.Reader, dest string, options *archive.TarOptions) error {
|
||||||
|
if _, err := os.Stat(dest); os.IsNotExist(err) {
|
||||||
|
if err := os.MkdirAll(dest, 0777); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd := reexec.Command("docker-untar", dest)
|
||||||
|
cmd.Stdin = archive
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Untar %s %s", err, out)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TarUntar(src, dst string) error {
|
||||||
|
return chrootArchiver.TarUntar(src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyWithTar creates a tar archive of filesystem path `src`, and
|
||||||
|
// unpacks it at filesystem path `dst`.
|
||||||
|
// The archive is streamed directly with fixed buffering and no
|
||||||
|
// intermediary disk IO.
|
||||||
|
func CopyWithTar(src, dst string) error {
|
||||||
|
return chrootArchiver.CopyWithTar(src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyFileWithTar emulates the behavior of the 'cp' command-line
|
||||||
|
// for a single file. It copies a regular file from path `src` to
|
||||||
|
// path `dst`, and preserves all its metadata.
|
||||||
|
//
|
||||||
|
// If `dst` ends with a trailing slash '/', the final destination path
|
||||||
|
// will be `dst/base(src)`.
|
||||||
|
func CopyFileWithTar(src, dst string) (err error) {
|
||||||
|
return chrootArchiver.CopyFileWithTar(src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UntarPath is a convenience function which looks for an archive
|
||||||
|
// at filesystem path `src`, and unpacks it at `dst`.
|
||||||
|
func UntarPath(src, dst string) error {
|
||||||
|
return chrootArchiver.UntarPath(src, dst)
|
||||||
|
}
|
38
chrootarchive/diff.go
Normal file
38
chrootarchive/diff.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package chrootarchive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/archive"
|
||||||
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func applyLayer() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if err := syscall.Chroot(flag.Arg(0)); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
if err := syscall.Chdir("/"); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
if err := archive.ApplyLayer("/", os.Stdin); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
18
chrootarchive/init.go
Normal file
18
chrootarchive/init.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package chrootarchive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
reexec.Register("docker-untar", untar)
|
||||||
|
reexec.Register("docker-applyLayer", applyLayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatal(err error) {
|
||||||
|
fmt.Fprint(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
18
reexec/command_linux.go
Normal file
18
reexec/command_linux.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package reexec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Command(args ...string) *exec.Cmd {
|
||||||
|
return &exec.Cmd{
|
||||||
|
Path: Self(),
|
||||||
|
Args: args,
|
||||||
|
SysProcAttr: &syscall.SysProcAttr{
|
||||||
|
Pdeathsig: syscall.SIGTERM,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
11
reexec/command_unsupported.go
Normal file
11
reexec/command_unsupported.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package reexec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Command(args ...string) *exec.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -27,19 +27,16 @@ func Init() bool {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Self returns the path to the current processes binary
|
// Self returns the path to the current processes binary
|
||||||
func Self() string {
|
func Self() string {
|
||||||
name := os.Args[0]
|
name := os.Args[0]
|
||||||
|
|
||||||
if filepath.Base(name) == name {
|
if filepath.Base(name) == name {
|
||||||
if lp, err := exec.LookPath(name); err == nil {
|
if lp, err := exec.LookPath(name); err == nil {
|
||||||
name = lp
|
name = lp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue