123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- package archive // import "github.com/docker/docker/pkg/archive"
- import (
- "io/ioutil"
- "os"
- "path/filepath"
- "syscall"
- "testing"
- "github.com/docker/docker/pkg/system"
- rsystem "github.com/opencontainers/runc/libcontainer/system"
- "golang.org/x/sys/unix"
- "gotest.tools/assert"
- "gotest.tools/skip"
- )
- // setupOverlayTestDir creates files in a directory with overlay whiteouts
- // Tree layout
- // .
- // ├── d1 # opaque, 0700
- // │ └── f1 # empty file, 0600
- // ├── d2 # opaque, 0750
- // │ └── f1 # empty file, 0660
- // └── d3 # 0700
- // └── f1 # whiteout, 0644
- func setupOverlayTestDir(t *testing.T, src string) {
- skip.If(t, os.Getuid() != 0, "skipping test that requires root")
- skip.If(t, rsystem.RunningInUserNS(), "skipping test that requires initial userns (trusted.overlay.opaque xattr cannot be set in userns, even with Ubuntu kernel)")
- // Create opaque directory containing single file and permission 0700
- err := os.Mkdir(filepath.Join(src, "d1"), 0700)
- assert.NilError(t, err)
- err = system.Lsetxattr(filepath.Join(src, "d1"), "trusted.overlay.opaque", []byte("y"), 0)
- assert.NilError(t, err)
- err = ioutil.WriteFile(filepath.Join(src, "d1", "f1"), []byte{}, 0600)
- assert.NilError(t, err)
- // Create another opaque directory containing single file but with permission 0750
- err = os.Mkdir(filepath.Join(src, "d2"), 0750)
- assert.NilError(t, err)
- err = system.Lsetxattr(filepath.Join(src, "d2"), "trusted.overlay.opaque", []byte("y"), 0)
- assert.NilError(t, err)
- err = ioutil.WriteFile(filepath.Join(src, "d2", "f1"), []byte{}, 0660)
- assert.NilError(t, err)
- // Create regular directory with deleted file
- err = os.Mkdir(filepath.Join(src, "d3"), 0700)
- assert.NilError(t, err)
- err = system.Mknod(filepath.Join(src, "d3", "f1"), unix.S_IFCHR, 0)
- assert.NilError(t, err)
- }
- func checkOpaqueness(t *testing.T, path string, opaque string) {
- xattrOpaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
- assert.NilError(t, err)
- if string(xattrOpaque) != opaque {
- t.Fatalf("Unexpected opaque value: %q, expected %q", string(xattrOpaque), opaque)
- }
- }
- func checkOverlayWhiteout(t *testing.T, path string) {
- stat, err := os.Stat(path)
- assert.NilError(t, err)
- statT, ok := stat.Sys().(*syscall.Stat_t)
- if !ok {
- t.Fatalf("Unexpected type: %t, expected *syscall.Stat_t", stat.Sys())
- }
- if statT.Rdev != 0 {
- t.Fatalf("Non-zero device number for whiteout")
- }
- }
- func checkFileMode(t *testing.T, path string, perm os.FileMode) {
- stat, err := os.Stat(path)
- assert.NilError(t, err)
- if stat.Mode() != perm {
- t.Fatalf("Unexpected file mode for %s: %o, expected %o", path, stat.Mode(), perm)
- }
- }
- func TestOverlayTarUntar(t *testing.T) {
- oldmask, err := system.Umask(0)
- assert.NilError(t, err)
- defer system.Umask(oldmask)
- src, err := ioutil.TempDir("", "docker-test-overlay-tar-src")
- assert.NilError(t, err)
- defer os.RemoveAll(src)
- setupOverlayTestDir(t, src)
- dst, err := ioutil.TempDir("", "docker-test-overlay-tar-dst")
- assert.NilError(t, err)
- defer os.RemoveAll(dst)
- options := &TarOptions{
- Compression: Uncompressed,
- WhiteoutFormat: OverlayWhiteoutFormat,
- }
- archive, err := TarWithOptions(src, options)
- assert.NilError(t, err)
- defer archive.Close()
- err = Untar(archive, dst, options)
- assert.NilError(t, err)
- checkFileMode(t, filepath.Join(dst, "d1"), 0700|os.ModeDir)
- checkFileMode(t, filepath.Join(dst, "d2"), 0750|os.ModeDir)
- checkFileMode(t, filepath.Join(dst, "d3"), 0700|os.ModeDir)
- checkFileMode(t, filepath.Join(dst, "d1", "f1"), 0600)
- checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660)
- checkFileMode(t, filepath.Join(dst, "d3", "f1"), os.ModeCharDevice|os.ModeDevice)
- checkOpaqueness(t, filepath.Join(dst, "d1"), "y")
- checkOpaqueness(t, filepath.Join(dst, "d2"), "y")
- checkOpaqueness(t, filepath.Join(dst, "d3"), "")
- checkOverlayWhiteout(t, filepath.Join(dst, "d3", "f1"))
- }
- func TestOverlayTarAUFSUntar(t *testing.T) {
- oldmask, err := system.Umask(0)
- assert.NilError(t, err)
- defer system.Umask(oldmask)
- src, err := ioutil.TempDir("", "docker-test-overlay-tar-src")
- assert.NilError(t, err)
- defer os.RemoveAll(src)
- setupOverlayTestDir(t, src)
- dst, err := ioutil.TempDir("", "docker-test-overlay-tar-dst")
- assert.NilError(t, err)
- defer os.RemoveAll(dst)
- archive, err := TarWithOptions(src, &TarOptions{
- Compression: Uncompressed,
- WhiteoutFormat: OverlayWhiteoutFormat,
- })
- assert.NilError(t, err)
- defer archive.Close()
- err = Untar(archive, dst, &TarOptions{
- Compression: Uncompressed,
- WhiteoutFormat: AUFSWhiteoutFormat,
- })
- assert.NilError(t, err)
- checkFileMode(t, filepath.Join(dst, "d1"), 0700|os.ModeDir)
- checkFileMode(t, filepath.Join(dst, "d1", WhiteoutOpaqueDir), 0700)
- checkFileMode(t, filepath.Join(dst, "d2"), 0750|os.ModeDir)
- checkFileMode(t, filepath.Join(dst, "d2", WhiteoutOpaqueDir), 0750)
- checkFileMode(t, filepath.Join(dst, "d3"), 0700|os.ModeDir)
- checkFileMode(t, filepath.Join(dst, "d1", "f1"), 0600)
- checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660)
- checkFileMode(t, filepath.Join(dst, "d3", WhiteoutPrefix+"f1"), 0600)
- }
|