2018-02-05 21:05:59 +00:00
|
|
|
package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
|
2014-11-08 15:38:42 +00:00
|
|
|
|
|
|
|
import (
|
2015-03-25 01:20:20 +00:00
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2015-04-12 05:12:40 +00:00
|
|
|
"hash/crc32"
|
2014-12-06 02:30:03 +00:00
|
|
|
"io"
|
2014-11-08 15:38:42 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2016-03-01 22:28:29 +00:00
|
|
|
"runtime"
|
2015-04-10 18:23:09 +00:00
|
|
|
"strings"
|
2014-11-08 15:38:42 +00:00
|
|
|
"testing"
|
2014-12-06 02:30:03 +00:00
|
|
|
"time"
|
2014-11-08 15:38:42 +00:00
|
|
|
|
|
|
|
"github.com/docker/docker/pkg/archive"
|
2022-03-14 19:24:29 +00:00
|
|
|
"github.com/docker/docker/pkg/idtools"
|
2014-11-11 11:02:14 +00:00
|
|
|
"github.com/docker/docker/pkg/reexec"
|
2020-02-07 13:39:24 +00:00
|
|
|
"gotest.tools/v3/skip"
|
2014-11-08 15:38:42 +00:00
|
|
|
)
|
|
|
|
|
2014-11-11 11:02:14 +00:00
|
|
|
func init() {
|
|
|
|
reexec.Init()
|
|
|
|
}
|
|
|
|
|
2022-03-14 19:24:29 +00:00
|
|
|
var chrootArchiver = NewArchiver(idtools.IdentityMapping{})
|
2017-05-24 15:53:41 +00:00
|
|
|
|
|
|
|
func TarUntar(src, dst string) error {
|
|
|
|
return chrootArchiver.TarUntar(src, dst)
|
|
|
|
}
|
|
|
|
|
|
|
|
func CopyFileWithTar(src, dst string) (err error) {
|
|
|
|
return chrootArchiver.CopyFileWithTar(src, dst)
|
|
|
|
}
|
|
|
|
|
|
|
|
func UntarPath(src, dst string) error {
|
|
|
|
return chrootArchiver.UntarPath(src, dst)
|
|
|
|
}
|
|
|
|
|
|
|
|
func CopyWithTar(src, dst string) error {
|
|
|
|
return chrootArchiver.CopyWithTar(src, dst)
|
|
|
|
}
|
|
|
|
|
2014-11-08 15:38:42 +00:00
|
|
|
func TestChrootTarUntar(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2014-11-08 15:38:42 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2014-11-08 15:38:42 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2022-10-16 12:09:06 +00:00
|
|
|
if err := os.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0o644); err != nil {
|
2014-11-08 15:38:42 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2022-10-16 12:09:06 +00:00
|
|
|
if err := os.WriteFile(filepath.Join(src, "lolo"), []byte("hello lolo"), 0o644); err != nil {
|
2014-11-08 15:38:42 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
stream, err := archive.Tar(src, archive.Uncompressed)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2022-10-16 11:15:23 +00:00
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(dest, 0o700); err != nil {
|
2014-11-08 15:38:42 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-10-23 21:30:11 +00:00
|
|
|
if err := Untar(stream, dest, &archive.TarOptions{ExcludePatterns: []string{"lolo"}}); err != nil {
|
2014-11-08 15:38:42 +00:00
|
|
|
t.Fatal(err)
|
2015-03-25 01:20:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-10 18:23:09 +00:00
|
|
|
// gh#10426: Verify the fix for having a huge excludes list (like on `docker load` with large # of
|
|
|
|
// local images)
|
|
|
|
func TestChrootUntarWithHugeExcludesList(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2015-04-10 18:23:09 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2015-04-10 18:23:09 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2022-10-16 12:09:06 +00:00
|
|
|
if err := os.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0o644); err != nil {
|
2015-04-10 18:23:09 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
stream, err := archive.Tar(src, archive.Uncompressed)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(dest, 0o700); err != nil {
|
2015-04-10 18:23:09 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
options := &archive.TarOptions{}
|
2019-11-27 14:39:12 +00:00
|
|
|
// 65534 entries of 64-byte strings ~= 4MB of environment space which should overflow
|
|
|
|
// on most systems when passed via environment or command line arguments
|
2017-03-30 09:04:42 +00:00
|
|
|
excludes := make([]string, 65534)
|
2020-06-25 08:29:34 +00:00
|
|
|
var i rune
|
|
|
|
for i = 0; i < 65534; i++ {
|
2015-04-10 18:23:09 +00:00
|
|
|
excludes[i] = strings.Repeat(string(i), 64)
|
|
|
|
}
|
|
|
|
options.ExcludePatterns = excludes
|
|
|
|
if err := Untar(stream, dest, options); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
func TestChrootUntarEmptyArchive(t *testing.T) {
|
2022-10-16 10:59:14 +00:00
|
|
|
if err := Untar(nil, t.TempDir(), nil); err == nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal("expected error on empty archive")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:58:08 +00:00
|
|
|
func prepareSourceDirectory(numberOfFiles int, targetPath string, makeSymLinks bool) (int, error) {
|
2015-03-25 01:20:20 +00:00
|
|
|
fileData := []byte("fooo")
|
|
|
|
for n := 0; n < numberOfFiles; n++ {
|
|
|
|
fileName := fmt.Sprintf("file-%d", n)
|
2022-10-16 12:09:06 +00:00
|
|
|
if err := os.WriteFile(filepath.Join(targetPath, fileName), fileData, 0o700); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
return 0, err
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
if makeSymLinks {
|
2015-05-14 22:08:00 +00:00
|
|
|
if err := os.Symlink(filepath.Join(targetPath, fileName), filepath.Join(targetPath, fileName+"-link")); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
totalSize := numberOfFiles * len(fileData)
|
|
|
|
return totalSize, nil
|
|
|
|
}
|
|
|
|
|
2015-04-12 05:12:40 +00:00
|
|
|
func getHash(filename string) (uint32, error) {
|
2021-08-24 10:10:50 +00:00
|
|
|
stream, err := os.ReadFile(filename)
|
2015-04-12 05:12:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
hash := crc32.NewIEEE()
|
|
|
|
hash.Write(stream)
|
|
|
|
return hash.Sum32(), nil
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:58:08 +00:00
|
|
|
func compareDirectories(src string, dest string) error {
|
|
|
|
changes, err := archive.ChangesDirs(dest, src)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(changes) > 0 {
|
|
|
|
return fmt.Errorf("Unexpected differences after untar: %v", changes)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-04-12 05:12:40 +00:00
|
|
|
func compareFiles(src string, dest string) error {
|
|
|
|
srcHash, err := getHash(src)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
destHash, err := getHash(dest)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if srcHash != destHash {
|
|
|
|
return fmt.Errorf("%s is different from %s", src, dest)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:58:08 +00:00
|
|
|
func TestChrootTarUntarWithSymlink(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, runtime.GOOS == "windows", "FIXME: figure out why this is failing")
|
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2015-03-25 01:20:20 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-06-07 07:45:21 +00:00
|
|
|
if _, err := prepareSourceDirectory(10, src, false); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
|
|
|
if err := TarUntar(src, dest); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
if err := compareDirectories(src, dest); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-03-25 01:20:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestChrootCopyWithTar(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, runtime.GOOS == "windows", "FIXME: figure out why this is failing")
|
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2015-03-25 01:20:20 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
// Copy directory
|
2015-04-08 20:58:08 +00:00
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
2015-03-25 01:20:20 +00:00
|
|
|
if err := CopyWithTar(src, dest); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
if err := compareDirectories(src, dest); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
// Copy file
|
|
|
|
srcfile := filepath.Join(src, "file-1")
|
2015-04-08 20:58:08 +00:00
|
|
|
dest = filepath.Join(tmpdir, "destFile")
|
|
|
|
destfile := filepath.Join(dest, "file-1")
|
|
|
|
if err := CopyWithTar(srcfile, destfile); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-12 05:12:40 +00:00
|
|
|
if err := compareFiles(srcfile, destfile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
// Copy symbolic link
|
2015-04-08 20:58:08 +00:00
|
|
|
srcLinkfile := filepath.Join(src, "file-1-link")
|
|
|
|
dest = filepath.Join(tmpdir, "destSymlink")
|
|
|
|
destLinkfile := filepath.Join(dest, "file-1-link")
|
|
|
|
if err := CopyWithTar(srcLinkfile, destLinkfile); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-12 05:12:40 +00:00
|
|
|
if err := compareFiles(srcLinkfile, destLinkfile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-03-25 01:20:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestChrootCopyFileWithTar(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2015-03-25 01:20:20 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
// Copy directory
|
2015-04-08 20:58:08 +00:00
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
2015-03-25 01:20:20 +00:00
|
|
|
if err := CopyFileWithTar(src, dest); err == nil {
|
|
|
|
t.Fatal("Expected error on copying directory")
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
// Copy file
|
|
|
|
srcfile := filepath.Join(src, "file-1")
|
2015-04-08 20:58:08 +00:00
|
|
|
dest = filepath.Join(tmpdir, "destFile")
|
|
|
|
destfile := filepath.Join(dest, "file-1")
|
|
|
|
if err := CopyFileWithTar(srcfile, destfile); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-12 05:12:40 +00:00
|
|
|
if err := compareFiles(srcfile, destfile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-08 20:58:08 +00:00
|
|
|
|
2015-03-25 01:20:20 +00:00
|
|
|
// Copy symbolic link
|
2015-04-08 20:58:08 +00:00
|
|
|
srcLinkfile := filepath.Join(src, "file-1-link")
|
|
|
|
dest = filepath.Join(tmpdir, "destSymlink")
|
|
|
|
destLinkfile := filepath.Join(dest, "file-1-link")
|
|
|
|
if err := CopyFileWithTar(srcLinkfile, destLinkfile); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-12 05:12:40 +00:00
|
|
|
if err := compareFiles(srcLinkfile, destLinkfile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-03-25 01:20:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestChrootUntarPath(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, runtime.GOOS == "windows", "FIXME: figure out why this is failing")
|
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2015-03-25 01:20:20 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-06-07 07:45:21 +00:00
|
|
|
if _, err := prepareSourceDirectory(10, src, false); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
|
|
|
// Untar a directory
|
|
|
|
if err := UntarPath(src, dest); err == nil {
|
|
|
|
t.Fatal("Expected error on untaring a directory")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Untar a tar file
|
|
|
|
stream, err := archive.Tar(src, archive.Uncompressed)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
buf.ReadFrom(stream)
|
|
|
|
tarfile := filepath.Join(tmpdir, "src.tar")
|
2022-10-16 12:09:06 +00:00
|
|
|
if err := os.WriteFile(tarfile, buf.Bytes(), 0o644); err != nil {
|
2015-03-25 01:20:20 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := UntarPath(tarfile, dest); err != nil {
|
|
|
|
t.Fatal(err)
|
2015-04-08 20:58:08 +00:00
|
|
|
}
|
|
|
|
if err := compareDirectories(src, dest); err != nil {
|
|
|
|
t.Fatal(err)
|
2014-11-08 15:38:42 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-06 02:30:03 +00:00
|
|
|
|
|
|
|
type slowEmptyTarReader struct {
|
|
|
|
size int
|
|
|
|
offset int
|
|
|
|
chunkSize int
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read is a slow reader of an empty tar (like the output of "tar c --files-from /dev/null")
|
|
|
|
func (s *slowEmptyTarReader) Read(p []byte) (int, error) {
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
count := s.chunkSize
|
|
|
|
if len(p) < s.chunkSize {
|
|
|
|
count = len(p)
|
|
|
|
}
|
|
|
|
for i := 0; i < count; i++ {
|
|
|
|
p[i] = 0
|
|
|
|
}
|
|
|
|
s.offset += count
|
|
|
|
if s.offset > s.size {
|
|
|
|
return count, io.EOF
|
|
|
|
}
|
|
|
|
return count, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestChrootUntarEmptyArchiveFromSlowReader(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2014-12-06 02:30:03 +00:00
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(dest, 0o700); err != nil {
|
2014-12-06 02:30:03 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
|
|
|
|
if err := Untar(stream, dest, nil); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2014-12-08 23:04:34 +00:00
|
|
|
|
|
|
|
func TestChrootApplyEmptyArchiveFromSlowReader(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2014-12-08 23:04:34 +00:00
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(dest, 0o700); err != nil {
|
2014-12-08 23:04:34 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
stream := &slowEmptyTarReader{size: 10240, chunkSize: 1024}
|
2014-12-18 02:26:03 +00:00
|
|
|
if _, err := ApplyLayer(dest, stream); err != nil {
|
2014-12-08 23:04:34 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2015-02-17 02:38:52 +00:00
|
|
|
|
|
|
|
func TestChrootApplyDotDotFile(t *testing.T) {
|
2018-04-20 09:59:08 +00:00
|
|
|
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
2022-10-16 10:59:14 +00:00
|
|
|
tmpdir := t.TempDir()
|
2015-02-17 02:38:52 +00:00
|
|
|
src := filepath.Join(tmpdir, "src")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(src, 0o700); err != nil {
|
2015-02-17 02:38:52 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2022-10-16 12:09:06 +00:00
|
|
|
if err := os.WriteFile(filepath.Join(src, "..gitme"), []byte(""), 0o644); err != nil {
|
2015-02-17 02:38:52 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
stream, err := archive.Tar(src, archive.Uncompressed)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
dest := filepath.Join(tmpdir, "dest")
|
pkg/chrootarchive: replace system.MkdirAll for os.Mkdir
system.MkdirAll is a special version of os.Mkdir to handle creating directories
using Windows volume paths ("\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}").
This may be important when MkdirAll is used, which traverses all parent paths to
create them if missing (ultimately landing on the "volume" path).
Commit 62f648b06137a7e21b800f63ac403f7bb4d4f5b4 introduced the system.MkdirAll
calls, as a change was made in applyLayer() for Windows to use Windows volume
paths as an alternative for chroot (which is not supported on Windows). Later
iteractions changed this to regular Windows long-paths (`\\?\<path>`) in
230cfc6ed21e9398b9b3df765e6c02e90031d728, and 9b648dfac6453de5944ee4bb749115d85a253a05.
Such paths are handled by the `os` package.
However, in these tests, the parent path already exists (all paths created are
a direct subdirectory within `tmpDir`). It looks like `MkdirAll` here is used
out of convenience to not have to handle `os.ErrExist` errors. As all these
tests are running in a fresh temporary directory, there should be no need to
handle those, and it's actually desirable to produce an error in that case, as
the directory already existing would be unexpected.
Because of the above, this test changes `system.MkdirAll` to `os.Mkdir`. As we
are changing these lines, this patch also changes the legacy octal notation
(`0700`) to the now preferred `0o700`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-16 11:53:58 +00:00
|
|
|
if err := os.Mkdir(dest, 0o700); err != nil {
|
2015-02-17 02:38:52 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if _, err := ApplyLayer(dest, stream); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|