Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions chrootarchive/archive.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package chrootarchive

import (
"errors"
"io"
"os"
"path/filepath"

"github.com/moby/sys/user"

"github.com/moby/go-archive"
"github.com/moby/go-archive/compression"
)

// NewArchiver returns a new Archiver which uses chrootarchive.Untar
Expand Down Expand Up @@ -51,41 +47,6 @@ func UntarUncompressed(tarArchive io.Reader, dest string, options *archive.TarOp
return untarHandler(tarArchive, dest, options, false, dest)
}

// Handler for teasing out the automatic decompression
func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool, root string) error {
if tarArchive == nil {
return errors.New("empty archive")
}
if options == nil {
options = &archive.TarOptions{}
}

// If dest is inside a root then directory is created within chroot by extractor.
// This case is only currently used by cp.
if dest == root {
uid, gid := options.IDMap.RootPair()

dest = filepath.Clean(dest)
if _, err := os.Stat(dest); os.IsNotExist(err) {
if err := user.MkdirAllAndChown(dest, 0o755, uid, gid, user.WithOnlyNew); err != nil {
return err
}
}
}

r := io.NopCloser(tarArchive)
if decompress {
decompressedArchive, err := compression.DecompressStream(tarArchive)
if err != nil {
return err
}
defer decompressedArchive.Close()
r = decompressedArchive
}

return invokeUnpack(r, dest, options, root)
}

// Tar tars the requested path while chrooted to the specified root.
func Tar(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
if options == nil {
Expand Down
39 changes: 39 additions & 0 deletions chrootarchive/archive_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,51 @@ package chrootarchive
import (
"errors"
"io"
"os"
"path/filepath"
"strings"

"github.com/moby/go-archive"
"github.com/moby/go-archive/compression"
"github.com/moby/sys/user"
)

// Handler for teasing out the automatic decompression
func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool, root string) error {
if tarArchive == nil {
return errors.New("empty archive")
}
if options == nil {
options = &archive.TarOptions{}
}

// Create dest here only if it is the root itself; paths below the root are
// created by the extractor after entering the chroot.
// This case is only currently used by cp.
if dest == root {
uid, gid := options.IDMap.RootPair()

dest = filepath.Clean(dest)
if _, err := os.Stat(dest); os.IsNotExist(err) {
if err := user.MkdirAllAndChown(dest, 0o755, uid, gid, user.WithOnlyNew); err != nil {
return err
}
}
}

r := io.NopCloser(tarArchive)
if decompress {
decompressedArchive, err := compression.DecompressStream(tarArchive)
if err != nil {
return err
}
defer decompressedArchive.Close()
r = decompressedArchive
}

return invokeUnpack(r, dest, options, root)
}

func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
relDest, err := resolvePathInChroot(root, dest)
if err != nil {
Expand Down
29 changes: 26 additions & 3 deletions chrootarchive/archive_windows.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package chrootarchive

import (
"errors"
"io"
"os"
"path/filepath"
"strings"

"github.com/moby/go-archive"
Expand All @@ -25,14 +28,34 @@ func addLongPathPrefix(srcPath string) string {
return longPathPrefix + srcPath
}

func invokeUnpack(decompressedArchive io.ReadCloser, dest string, options *archive.TarOptions, root string) error {
// Handler for teasing out the automatic decompression
func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool, root string) error {
if tarArchive == nil {
return errors.New("empty archive")
}

// Create dest here only if it is the root itself; paths below the root are
// created by the extractor after entering the chroot.
// This case is only currently used by cp.
if dest == root {
dest = filepath.Clean(dest)
if _, err := os.Stat(dest); os.IsNotExist(err) {
if err := os.MkdirAll(dest, 0); err != nil {
return err
}
}
}

// Windows is different to Linux here because Windows does not support
// chroot. Hence there is no point sandboxing a chrooted process to
// do the unpack. We call inline instead within the daemon process.
return archive.Unpack(decompressedArchive, addLongPathPrefix(dest), options)
if decompress {
return archive.Untar(tarArchive, addLongPathPrefix(dest), options)
}
return archive.UntarUncompressed(tarArchive, addLongPathPrefix(dest), options)
}

func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
func invokePack(srcPath string, options *archive.TarOptions, _ string) (io.ReadCloser, error) {
// Windows is different to Linux here because Windows does not support
// chroot. Hence there is no point sandboxing a chrooted process to
// do the pack. We call inline instead within the daemon process.
Expand Down
Loading