github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/pkg/archive/archive_linux_test.go (about) 1 package archive // import "github.com/docker/docker/pkg/archive" 2 3 import ( 4 "os" 5 "path/filepath" 6 "syscall" 7 "testing" 8 9 "github.com/containerd/containerd/pkg/userns" 10 "github.com/docker/docker/pkg/system" 11 "golang.org/x/sys/unix" 12 "gotest.tools/v3/assert" 13 "gotest.tools/v3/skip" 14 ) 15 16 // setupOverlayTestDir creates files in a directory with overlay whiteouts 17 // Tree layout 18 // . 19 // ├── d1 # opaque, 0700 20 // │ └── f1 # empty file, 0600 21 // ├── d2 # opaque, 0750 22 // │ └── f1 # empty file, 0660 23 // └── d3 # 0700 24 // └── f1 # whiteout, 0644 25 func setupOverlayTestDir(t *testing.T, src string) { 26 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 27 skip.If(t, userns.RunningInUserNS(), "skipping test that requires initial userns (trusted.overlay.opaque xattr cannot be set in userns, even with Ubuntu kernel)") 28 // Create opaque directory containing single file and permission 0700 29 err := os.Mkdir(filepath.Join(src, "d1"), 0700) 30 assert.NilError(t, err) 31 32 err = system.Lsetxattr(filepath.Join(src, "d1"), "trusted.overlay.opaque", []byte("y"), 0) 33 assert.NilError(t, err) 34 35 err = os.WriteFile(filepath.Join(src, "d1", "f1"), []byte{}, 0600) 36 assert.NilError(t, err) 37 38 // Create another opaque directory containing single file but with permission 0750 39 err = os.Mkdir(filepath.Join(src, "d2"), 0750) 40 assert.NilError(t, err) 41 42 err = system.Lsetxattr(filepath.Join(src, "d2"), "trusted.overlay.opaque", []byte("y"), 0) 43 assert.NilError(t, err) 44 45 err = os.WriteFile(filepath.Join(src, "d2", "f1"), []byte{}, 0660) 46 assert.NilError(t, err) 47 48 // Create regular directory with deleted file 49 err = os.Mkdir(filepath.Join(src, "d3"), 0700) 50 assert.NilError(t, err) 51 52 err = system.Mknod(filepath.Join(src, "d3", "f1"), unix.S_IFCHR, 0) 53 assert.NilError(t, err) 54 } 55 56 func checkOpaqueness(t *testing.T, path string, opaque string) { 57 xattrOpaque, err := system.Lgetxattr(path, "trusted.overlay.opaque") 58 assert.NilError(t, err) 59 60 if string(xattrOpaque) != opaque { 61 t.Fatalf("Unexpected opaque value: %q, expected %q", string(xattrOpaque), opaque) 62 } 63 64 } 65 66 func checkOverlayWhiteout(t *testing.T, path string) { 67 stat, err := os.Stat(path) 68 assert.NilError(t, err) 69 70 statT, ok := stat.Sys().(*syscall.Stat_t) 71 if !ok { 72 t.Fatalf("Unexpected type: %t, expected *syscall.Stat_t", stat.Sys()) 73 } 74 if statT.Rdev != 0 { 75 t.Fatalf("Non-zero device number for whiteout") 76 } 77 } 78 79 func checkFileMode(t *testing.T, path string, perm os.FileMode) { 80 stat, err := os.Stat(path) 81 assert.NilError(t, err) 82 83 if stat.Mode() != perm { 84 t.Fatalf("Unexpected file mode for %s: %o, expected %o", path, stat.Mode(), perm) 85 } 86 } 87 88 func TestOverlayTarUntar(t *testing.T) { 89 oldmask, err := system.Umask(0) 90 assert.NilError(t, err) 91 defer system.Umask(oldmask) 92 93 src, err := os.MkdirTemp("", "docker-test-overlay-tar-src") 94 assert.NilError(t, err) 95 defer os.RemoveAll(src) 96 97 setupOverlayTestDir(t, src) 98 99 dst, err := os.MkdirTemp("", "docker-test-overlay-tar-dst") 100 assert.NilError(t, err) 101 defer os.RemoveAll(dst) 102 103 options := &TarOptions{ 104 Compression: Uncompressed, 105 WhiteoutFormat: OverlayWhiteoutFormat, 106 } 107 archive, err := TarWithOptions(src, options) 108 assert.NilError(t, err) 109 defer archive.Close() 110 111 err = Untar(archive, dst, options) 112 assert.NilError(t, err) 113 114 checkFileMode(t, filepath.Join(dst, "d1"), 0700|os.ModeDir) 115 checkFileMode(t, filepath.Join(dst, "d2"), 0750|os.ModeDir) 116 checkFileMode(t, filepath.Join(dst, "d3"), 0700|os.ModeDir) 117 checkFileMode(t, filepath.Join(dst, "d1", "f1"), 0600) 118 checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660) 119 checkFileMode(t, filepath.Join(dst, "d3", "f1"), os.ModeCharDevice|os.ModeDevice) 120 121 checkOpaqueness(t, filepath.Join(dst, "d1"), "y") 122 checkOpaqueness(t, filepath.Join(dst, "d2"), "y") 123 checkOpaqueness(t, filepath.Join(dst, "d3"), "") 124 checkOverlayWhiteout(t, filepath.Join(dst, "d3", "f1")) 125 } 126 127 func TestOverlayTarAUFSUntar(t *testing.T) { 128 oldmask, err := system.Umask(0) 129 assert.NilError(t, err) 130 defer system.Umask(oldmask) 131 132 src, err := os.MkdirTemp("", "docker-test-overlay-tar-src") 133 assert.NilError(t, err) 134 defer os.RemoveAll(src) 135 136 setupOverlayTestDir(t, src) 137 138 dst, err := os.MkdirTemp("", "docker-test-overlay-tar-dst") 139 assert.NilError(t, err) 140 defer os.RemoveAll(dst) 141 142 archive, err := TarWithOptions(src, &TarOptions{ 143 Compression: Uncompressed, 144 WhiteoutFormat: OverlayWhiteoutFormat, 145 }) 146 assert.NilError(t, err) 147 defer archive.Close() 148 149 err = Untar(archive, dst, &TarOptions{ 150 Compression: Uncompressed, 151 WhiteoutFormat: AUFSWhiteoutFormat, 152 }) 153 assert.NilError(t, err) 154 155 checkFileMode(t, filepath.Join(dst, "d1"), 0700|os.ModeDir) 156 checkFileMode(t, filepath.Join(dst, "d1", WhiteoutOpaqueDir), 0700) 157 checkFileMode(t, filepath.Join(dst, "d2"), 0750|os.ModeDir) 158 checkFileMode(t, filepath.Join(dst, "d2", WhiteoutOpaqueDir), 0750) 159 checkFileMode(t, filepath.Join(dst, "d3"), 0700|os.ModeDir) 160 checkFileMode(t, filepath.Join(dst, "d1", "f1"), 0600) 161 checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660) 162 checkFileMode(t, filepath.Join(dst, "d3", WhiteoutPrefix+"f1"), 0600) 163 }