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
| ... | ... |
@@ -24,6 +24,7 @@ import ( |
| 24 | 24 |
"github.com/docker/docker/daemon" |
| 25 | 25 |
imagepkg "github.com/docker/docker/image" |
| 26 | 26 |
"github.com/docker/docker/pkg/archive" |
| 27 |
+ "github.com/docker/docker/pkg/chrootarchive" |
|
| 27 | 28 |
"github.com/docker/docker/pkg/parsers" |
| 28 | 29 |
"github.com/docker/docker/pkg/symlink" |
| 29 | 30 |
"github.com/docker/docker/pkg/system" |
| ... | ... |
@@ -46,7 +47,9 @@ func (b *Builder) readContext(context io.Reader) error {
|
| 46 | 46 |
if b.context, err = tarsum.NewTarSum(decompressedStream, true, tarsum.Version0); err != nil {
|
| 47 | 47 |
return err |
| 48 | 48 |
} |
| 49 |
- if err := archive.Untar(b.context, tmpdirPath, nil); err != nil {
|
|
| 49 |
+ |
|
| 50 |
+ os.MkdirAll(tmpdirPath, 0700) |
|
| 51 |
+ if err := chrootarchive.Untar(b.context, tmpdirPath, nil); err != nil {
|
|
| 50 | 52 |
return err |
| 51 | 53 |
} |
| 52 | 54 |
|
| ... | ... |
@@ -627,7 +630,7 @@ func (b *Builder) addContext(container *daemon.Container, orig, dest string, dec |
| 627 | 627 |
} |
| 628 | 628 |
|
| 629 | 629 |
// try to successfully untar the orig |
| 630 |
- if err := archive.UntarPath(origPath, tarDest); err == nil {
|
|
| 630 |
+ if err := chrootarchive.UntarPath(origPath, tarDest); err == nil {
|
|
| 631 | 631 |
return nil |
| 632 | 632 |
} else if err != io.EOF {
|
| 633 | 633 |
log.Debugf("Couldn't untar %s to %s: %s", origPath, tarDest, err)
|
| ... | ... |
@@ -637,7 +640,7 @@ func (b *Builder) addContext(container *daemon.Container, orig, dest string, dec |
| 637 | 637 |
if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
|
| 638 | 638 |
return err |
| 639 | 639 |
} |
| 640 |
- if err := archive.CopyWithTar(origPath, destPath); err != nil {
|
|
| 640 |
+ if err := chrootarchive.CopyWithTar(origPath, destPath); err != nil {
|
|
| 641 | 641 |
return err |
| 642 | 642 |
} |
| 643 | 643 |
|
| ... | ... |
@@ -650,7 +653,7 @@ func (b *Builder) addContext(container *daemon.Container, orig, dest string, dec |
| 650 | 650 |
} |
| 651 | 651 |
|
| 652 | 652 |
func copyAsDirectory(source, destination string, destinationExists bool) error {
|
| 653 |
- if err := archive.CopyWithTar(source, destination); err != nil {
|
|
| 653 |
+ if err := chrootarchive.CopyWithTar(source, destination); err != nil {
|
|
| 654 | 654 |
return err |
| 655 | 655 |
} |
| 656 | 656 |
|
| ... | ... |
@@ -33,6 +33,7 @@ import ( |
| 33 | 33 |
log "github.com/Sirupsen/logrus" |
| 34 | 34 |
"github.com/docker/docker/daemon/graphdriver" |
| 35 | 35 |
"github.com/docker/docker/pkg/archive" |
| 36 |
+ "github.com/docker/docker/pkg/chrootarchive" |
|
| 36 | 37 |
mountpk "github.com/docker/docker/pkg/mount" |
| 37 | 38 |
"github.com/docker/docker/utils" |
| 38 | 39 |
"github.com/docker/libcontainer/label" |
| ... | ... |
@@ -305,7 +306,7 @@ func (a *Driver) Diff(id, parent string) (archive.Archive, error) {
|
| 305 | 305 |
} |
| 306 | 306 |
|
| 307 | 307 |
func (a *Driver) applyDiff(id string, diff archive.ArchiveReader) error {
|
| 308 |
- return archive.Untar(diff, path.Join(a.rootPath(), "diff", id), nil) |
|
| 308 |
+ return chrootarchive.Untar(diff, path.Join(a.rootPath(), "diff", id), nil) |
|
| 309 | 309 |
} |
| 310 | 310 |
|
| 311 | 311 |
// DiffSize calculates the changes between the specified id |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
log "github.com/Sirupsen/logrus" |
| 10 | 10 |
"github.com/docker/docker/pkg/archive" |
| 11 |
+ "github.com/docker/docker/pkg/chrootarchive" |
|
| 11 | 12 |
"github.com/docker/docker/pkg/ioutils" |
| 12 | 13 |
"github.com/docker/docker/utils" |
| 13 | 14 |
) |
| ... | ... |
@@ -122,7 +123,7 @@ func (gdw *naiveDiffDriver) ApplyDiff(id, parent string, diff archive.ArchiveRea |
| 122 | 122 |
|
| 123 | 123 |
start := time.Now().UTC() |
| 124 | 124 |
log.Debugf("Start untar layer")
|
| 125 |
- if err = archive.ApplyLayer(layerFs, diff); err != nil {
|
|
| 125 |
+ if err = chrootarchive.ApplyLayer(layerFs, diff); err != nil {
|
|
| 126 | 126 |
return |
| 127 | 127 |
} |
| 128 | 128 |
log.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
|
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"path" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/daemon/graphdriver" |
| 11 |
- "github.com/docker/docker/pkg/archive" |
|
| 11 |
+ "github.com/docker/docker/pkg/chrootarchive" |
|
| 12 | 12 |
"github.com/docker/libcontainer/label" |
| 13 | 13 |
) |
| 14 | 14 |
|
| ... | ... |
@@ -66,7 +66,7 @@ func (d *Driver) Create(id, parent string) error {
|
| 66 | 66 |
if err != nil {
|
| 67 | 67 |
return fmt.Errorf("%s: %s", parent, err)
|
| 68 | 68 |
} |
| 69 |
- if err := archive.CopyWithTar(parentDir, dir); err != nil {
|
|
| 69 |
+ if err := chrootarchive.CopyWithTar(parentDir, dir); err != nil {
|
|
| 70 | 70 |
return err |
| 71 | 71 |
} |
| 72 | 72 |
return nil |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
log "github.com/Sirupsen/logrus" |
| 14 | 14 |
"github.com/docker/docker/daemon/execdriver" |
| 15 |
- "github.com/docker/docker/pkg/archive" |
|
| 15 |
+ "github.com/docker/docker/pkg/chrootarchive" |
|
| 16 | 16 |
"github.com/docker/docker/pkg/symlink" |
| 17 | 17 |
"github.com/docker/docker/volumes" |
| 18 | 18 |
) |
| ... | ... |
@@ -320,7 +320,7 @@ func copyExistingContents(source, destination string) error {
|
| 320 | 320 |
|
| 321 | 321 |
if len(srcList) == 0 {
|
| 322 | 322 |
// If the source volume is empty copy files from the root into the volume |
| 323 |
- if err := archive.CopyWithTar(source, destination); err != nil {
|
|
| 323 |
+ if err := chrootarchive.CopyWithTar(source, destination); err != nil {
|
|
| 324 | 324 |
return err |
| 325 | 325 |
} |
| 326 | 326 |
} |
| 327 | 327 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,76 @@ |
| 0 |
+package chrootarchive |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "flag" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io" |
|
| 6 |
+ "os" |
|
| 7 |
+ "runtime" |
|
| 8 |
+ "syscall" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/docker/docker/pkg/archive" |
|
| 11 |
+ "github.com/docker/docker/pkg/reexec" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func untar() {
|
|
| 15 |
+ runtime.LockOSThread() |
|
| 16 |
+ flag.Parse() |
|
| 17 |
+ |
|
| 18 |
+ if err := syscall.Chroot(flag.Arg(0)); err != nil {
|
|
| 19 |
+ fatal(err) |
|
| 20 |
+ } |
|
| 21 |
+ if err := syscall.Chdir("/"); err != nil {
|
|
| 22 |
+ fatal(err) |
|
| 23 |
+ } |
|
| 24 |
+ if err := archive.Untar(os.Stdin, "/", nil); err != nil {
|
|
| 25 |
+ fatal(err) |
|
| 26 |
+ } |
|
| 27 |
+ os.Exit(0) |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+var ( |
|
| 31 |
+ chrootArchiver = &archive.Archiver{Untar}
|
|
| 32 |
+) |
|
| 33 |
+ |
|
| 34 |
+func Untar(archive io.Reader, dest string, options *archive.TarOptions) error {
|
|
| 35 |
+ if _, err := os.Stat(dest); os.IsNotExist(err) {
|
|
| 36 |
+ if err := os.MkdirAll(dest, 0777); err != nil {
|
|
| 37 |
+ return err |
|
| 38 |
+ } |
|
| 39 |
+ } |
|
| 40 |
+ cmd := reexec.Command("docker-untar", dest)
|
|
| 41 |
+ cmd.Stdin = archive |
|
| 42 |
+ out, err := cmd.CombinedOutput() |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return fmt.Errorf("Untar %s %s", err, out)
|
|
| 45 |
+ } |
|
| 46 |
+ return nil |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+func TarUntar(src, dst string) error {
|
|
| 50 |
+ return chrootArchiver.TarUntar(src, dst) |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+// CopyWithTar creates a tar archive of filesystem path `src`, and |
|
| 54 |
+// unpacks it at filesystem path `dst`. |
|
| 55 |
+// The archive is streamed directly with fixed buffering and no |
|
| 56 |
+// intermediary disk IO. |
|
| 57 |
+func CopyWithTar(src, dst string) error {
|
|
| 58 |
+ return chrootArchiver.CopyWithTar(src, dst) |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// CopyFileWithTar emulates the behavior of the 'cp' command-line |
|
| 62 |
+// for a single file. It copies a regular file from path `src` to |
|
| 63 |
+// path `dst`, and preserves all its metadata. |
|
| 64 |
+// |
|
| 65 |
+// If `dst` ends with a trailing slash '/', the final destination path |
|
| 66 |
+// will be `dst/base(src)`. |
|
| 67 |
+func CopyFileWithTar(src, dst string) (err error) {
|
|
| 68 |
+ return chrootArchiver.CopyFileWithTar(src, dst) |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+// UntarPath is a convenience function which looks for an archive |
|
| 72 |
+// at filesystem path `src`, and unpacks it at `dst`. |
|
| 73 |
+func UntarPath(src, dst string) error {
|
|
| 74 |
+ return chrootArchiver.UntarPath(src, dst) |
|
| 75 |
+} |
| 0 | 76 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 0 |
+package chrootarchive |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "flag" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "os" |
|
| 6 |
+ "runtime" |
|
| 7 |
+ "syscall" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/pkg/archive" |
|
| 10 |
+ "github.com/docker/docker/pkg/reexec" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func applyLayer() {
|
|
| 14 |
+ runtime.LockOSThread() |
|
| 15 |
+ flag.Parse() |
|
| 16 |
+ |
|
| 17 |
+ if err := syscall.Chroot(flag.Arg(0)); err != nil {
|
|
| 18 |
+ fatal(err) |
|
| 19 |
+ } |
|
| 20 |
+ if err := syscall.Chdir("/"); err != nil {
|
|
| 21 |
+ fatal(err) |
|
| 22 |
+ } |
|
| 23 |
+ if err := archive.ApplyLayer("/", os.Stdin); err != nil {
|
|
| 24 |
+ fatal(err) |
|
| 25 |
+ } |
|
| 26 |
+ os.Exit(0) |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func ApplyLayer(dest string, layer archive.ArchiveReader) error {
|
|
| 30 |
+ cmd := reexec.Command("docker-applyLayer", dest)
|
|
| 31 |
+ cmd.Stdin = layer |
|
| 32 |
+ out, err := cmd.CombinedOutput() |
|
| 33 |
+ if err != nil {
|
|
| 34 |
+ return fmt.Errorf("ApplyLayer %s %s", err, out)
|
|
| 35 |
+ } |
|
| 36 |
+ return nil |
|
| 37 |
+} |
| 0 | 38 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+package chrootarchive |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "os" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/docker/pkg/reexec" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func init() {
|
|
| 10 |
+ reexec.Register("docker-untar", untar)
|
|
| 11 |
+ reexec.Register("docker-applyLayer", applyLayer)
|
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+func fatal(err error) {
|
|
| 15 |
+ fmt.Fprint(os.Stderr, err) |
|
| 16 |
+ os.Exit(1) |
|
| 17 |
+} |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+// +build linux |
|
| 1 |
+ |
|
| 2 |
+package reexec |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "os/exec" |
|
| 6 |
+ "syscall" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func Command(args ...string) *exec.Cmd {
|
|
| 10 |
+ return &exec.Cmd{
|
|
| 11 |
+ Path: Self(), |
|
| 12 |
+ Args: args, |
|
| 13 |
+ SysProcAttr: &syscall.SysProcAttr{
|
|
| 14 |
+ Pdeathsig: syscall.SIGTERM, |
|
| 15 |
+ }, |
|
| 16 |
+ } |
|
| 17 |
+} |
| ... | ... |
@@ -27,19 +27,16 @@ func Init() bool {
|
| 27 | 27 |
|
| 28 | 28 |
return true |
| 29 | 29 |
} |
| 30 |
- |
|
| 31 | 30 |
return false |
| 32 | 31 |
} |
| 33 | 32 |
|
| 34 | 33 |
// Self returns the path to the current processes binary |
| 35 | 34 |
func Self() string {
|
| 36 | 35 |
name := os.Args[0] |
| 37 |
- |
|
| 38 | 36 |
if filepath.Base(name) == name {
|
| 39 | 37 |
if lp, err := exec.LookPath(name); err == nil {
|
| 40 | 38 |
name = lp |
| 41 | 39 |
} |
| 42 | 40 |
} |
| 43 |
- |
|
| 44 | 41 |
return name |
| 45 | 42 |
} |