Windows: chrootarchive refactor
Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
parent
24fd826fc0
commit
d025345cdd
5 changed files with 77 additions and 34 deletions
|
@ -9,21 +9,14 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
"github.com/docker/docker/pkg/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
var chrootArchiver = &archive.Archiver{Untar: Untar}
|
var chrootArchiver = &archive.Archiver{Untar: Untar}
|
||||||
|
|
||||||
func chroot(path string) error {
|
|
||||||
if err := syscall.Chroot(path); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return syscall.Chdir("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
func untar() {
|
func untar() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -38,7 +31,20 @@ func untar() {
|
||||||
if err := chroot(flag.Arg(0)); err != nil {
|
if err := chroot(flag.Arg(0)); err != nil {
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
if err := archive.Unpack(os.Stdin, "/", options); err != nil {
|
|
||||||
|
// Explanation of Windows difference. Windows does not support chroot.
|
||||||
|
// untar() is a helper function for the command line in the format
|
||||||
|
// "docker docker-untar directory input". In Windows, directory will be
|
||||||
|
// something like <pathto>\docker-buildnnnnnnnnn. So, just use that directory
|
||||||
|
// directly instead.
|
||||||
|
//
|
||||||
|
// One example of where this is used is in the docker build command where the
|
||||||
|
// dockerfile will be unpacked to the machine on which the daemon runs.
|
||||||
|
rootPath := "/"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
rootPath = flag.Arg(0)
|
||||||
|
}
|
||||||
|
if err := archive.Unpack(os.Stdin, rootPath, options); err != nil {
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
// fully consume stdin in case it is zero padded
|
// fully consume stdin in case it is zero padded
|
||||||
|
@ -59,7 +65,7 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error
|
||||||
|
|
||||||
dest = filepath.Clean(dest)
|
dest = filepath.Clean(dest)
|
||||||
if _, err := os.Stat(dest); os.IsNotExist(err) {
|
if _, err := os.Stat(dest); os.IsNotExist(err) {
|
||||||
if err := os.MkdirAll(dest, 0777); err != nil {
|
if err := system.MkdirAll(dest, 0777); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -15,6 +14,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
"github.com/docker/docker/pkg/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -28,7 +28,7 @@ func TestChrootTarUntar(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil {
|
||||||
|
@ -42,7 +42,7 @@ func TestChrootTarUntar(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dest := filepath.Join(tmpdir, "src")
|
dest := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
if err := system.MkdirAll(dest, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := Untar(stream, dest, &archive.TarOptions{ExcludePatterns: []string{"lolo"}}); err != nil {
|
if err := Untar(stream, dest, &archive.TarOptions{ExcludePatterns: []string{"lolo"}}); err != nil {
|
||||||
|
@ -59,7 +59,7 @@ func TestChrootUntarWithHugeExcludesList(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil {
|
||||||
|
@ -70,7 +70,7 @@ func TestChrootUntarWithHugeExcludesList(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dest := filepath.Join(tmpdir, "dest")
|
dest := filepath.Join(tmpdir, "dest")
|
||||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
if err := system.MkdirAll(dest, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
options := &archive.TarOptions{}
|
options := &archive.TarOptions{}
|
||||||
|
@ -101,11 +101,11 @@ func prepareSourceDirectory(numberOfFiles int, targetPath string, makeSymLinks b
|
||||||
fileData := []byte("fooo")
|
fileData := []byte("fooo")
|
||||||
for n := 0; n < numberOfFiles; n++ {
|
for n := 0; n < numberOfFiles; n++ {
|
||||||
fileName := fmt.Sprintf("file-%d", n)
|
fileName := fmt.Sprintf("file-%d", n)
|
||||||
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(targetPath, fileName), fileData, 0700); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if makeSymLinks {
|
if makeSymLinks {
|
||||||
if err := os.Symlink(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
|
if err := os.Symlink(filepath.Join(targetPath, fileName), filepath.Join(targetPath, fileName+"-link")); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func TestChrootTarUntarWithSymlink(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
||||||
|
@ -179,7 +179,7 @@ func TestChrootCopyWithTar(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
||||||
|
@ -225,7 +225,7 @@ func TestChrootCopyFileWithTar(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
||||||
|
@ -268,7 +268,7 @@ func TestChrootUntarPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
||||||
|
@ -329,7 +329,7 @@ func TestChrootUntarEmptyArchiveFromSlowReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
dest := filepath.Join(tmpdir, "dest")
|
dest := filepath.Join(tmpdir, "dest")
|
||||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
if err := system.MkdirAll(dest, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
|
stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
|
||||||
|
@ -345,7 +345,7 @@ func TestChrootApplyEmptyArchiveFromSlowReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
dest := filepath.Join(tmpdir, "dest")
|
dest := filepath.Join(tmpdir, "dest")
|
||||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
if err := system.MkdirAll(dest, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
|
stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
|
||||||
|
@ -361,7 +361,7 @@ func TestChrootApplyDotDotFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
src := filepath.Join(tmpdir, "src")
|
src := filepath.Join(tmpdir, "src")
|
||||||
if err := os.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(src, "..gitme"), []byte(""), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(src, "..gitme"), []byte(""), 0644); err != nil {
|
||||||
|
@ -372,7 +372,7 @@ func TestChrootApplyDotDotFile(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dest := filepath.Join(tmpdir, "dest")
|
dest := filepath.Join(tmpdir, "dest")
|
||||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
if err := system.MkdirAll(dest, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := ApplyLayer(dest, stream); err != nil {
|
if _, err := ApplyLayer(dest, stream); err != nil {
|
||||||
|
|
14
chrootarchive/archive_unix.go
Normal file
14
chrootarchive/archive_unix.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package chrootarchive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func chroot(path string) error {
|
||||||
|
if err := syscall.Chroot(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Chdir("/")
|
||||||
|
}
|
6
chrootarchive/archive_windows.go
Normal file
6
chrootarchive/archive_windows.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package chrootarchive
|
||||||
|
|
||||||
|
// chroot is not supported by Windows
|
||||||
|
func chroot(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -9,10 +9,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
"github.com/docker/docker/pkg/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
type applyLayerResponse struct {
|
type applyLayerResponse struct {
|
||||||
|
@ -20,23 +20,40 @@ type applyLayerResponse struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyLayer() {
|
func applyLayer() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
root = "/"
|
||||||
|
tmpDir = ""
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if err := chroot(flag.Arg(0)); err != nil {
|
if runtime.GOOS != "windows" {
|
||||||
fatal(err)
|
if err := chroot(flag.Arg(0)); err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to be able to set any perms
|
||||||
|
oldmask, err := system.Umask(0)
|
||||||
|
defer system.Umask(oldmask)
|
||||||
|
if err != nil {
|
||||||
|
fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// As Windows does not support chroot or umask, we use the directory
|
||||||
|
// passed in which will be <pathto>\docker-buildnnnnnnnn instead of
|
||||||
|
// the 'chroot-root', "/"
|
||||||
|
root = flag.Arg(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to be able to set any perms
|
if tmpDir, err = ioutil.TempDir(root, "temp-docker-extract"); err != nil {
|
||||||
oldmask := syscall.Umask(0)
|
|
||||||
defer syscall.Umask(oldmask)
|
|
||||||
tmpDir, err := ioutil.TempDir("/", "temp-docker-extract")
|
|
||||||
if err != nil {
|
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Setenv("TMPDIR", tmpDir)
|
os.Setenv("TMPDIR", tmpDir)
|
||||||
size, err := archive.UnpackLayer("/", os.Stdin)
|
size, err := archive.UnpackLayer(root, os.Stdin)
|
||||||
os.RemoveAll(tmpDir)
|
os.RemoveAll(tmpDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err)
|
fatal(err)
|
||||||
|
|
Loading…
Reference in a new issue