github.com/rumpl/bof@v23.0.0-rc.2+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 // . 20 // ├── d1 # opaque, 0700 21 // │ └── f1 # empty file, 0600 22 // ├── d2 # opaque, 0750 23 // │ └── f1 # empty file, 0660 24 // └── d3 # 0700 25 // └── f1 # whiteout, 0644 26 func setupOverlayTestDir(t *testing.T, src string) { 27 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 28 skip.If(t, userns.RunningInUserNS(), "skipping test that requires initial userns (trusted.overlay.opaque xattr cannot be set in userns, even with Ubuntu kernel)") 29 // Create opaque directory containing single file and permission 0700 30 err := os.Mkdir(filepath.Join(src, "d1"), 0700) 31 assert.NilError(t, err) 32 33 err = system.Lsetxattr(filepath.Join(src, "d1"), "trusted.overlay.opaque", []byte("y"), 0) 34 assert.NilError(t, err) 35 36 err = os.WriteFile(filepath.Join(src, "d1", "f1"), []byte{}, 0600) 37 assert.NilError(t, err) 38 39 // Create another opaque directory containing single file but with permission 0750 40 err = os.Mkdir(filepath.Join(src, "d2"), 0750) 41 assert.NilError(t, err) 42 43 err = system.Lsetxattr(filepath.Join(src, "d2"), "trusted.overlay.opaque", []byte("y"), 0) 44 assert.NilError(t, err) 45 46 err = os.WriteFile(filepath.Join(src, "d2", "f1"), []byte{}, 0660) 47 assert.NilError(t, err) 48 49 // Create regular directory with deleted file 50 err = os.Mkdir(filepath.Join(src, "d3"), 0700) 51 assert.NilError(t, err) 52 53 err = system.Mknod(filepath.Join(src, "d3", "f1"), unix.S_IFCHR, 0) 54 assert.NilError(t, err) 55 } 56 57 func checkOpaqueness(t *testing.T, path string, opaque string) { 58 xattrOpaque, err := system.Lgetxattr(path, "trusted.overlay.opaque") 59 assert.NilError(t, err) 60 61 if string(xattrOpaque) != opaque { 62 t.Fatalf("Unexpected opaque value: %q, expected %q", string(xattrOpaque), opaque) 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 restore := overrideUmask(0) 90 defer restore() 91 92 src, err := os.MkdirTemp("", "docker-test-overlay-tar-src") 93 assert.NilError(t, err) 94 defer os.RemoveAll(src) 95 96 setupOverlayTestDir(t, src) 97 98 dst, err := os.MkdirTemp("", "docker-test-overlay-tar-dst") 99 assert.NilError(t, err) 100 defer os.RemoveAll(dst) 101 102 options := &TarOptions{ 103 Compression: Uncompressed, 104 WhiteoutFormat: OverlayWhiteoutFormat, 105 } 106 archive, err := TarWithOptions(src, options) 107 assert.NilError(t, err) 108 defer archive.Close() 109 110 err = Untar(archive, dst, options) 111 assert.NilError(t, err) 112 113 checkFileMode(t, filepath.Join(dst, "d1"), 0700|os.ModeDir) 114 checkFileMode(t, filepath.Join(dst, "d2"), 0750|os.ModeDir) 115 checkFileMode(t, filepath.Join(dst, "d3"), 0700|os.ModeDir) 116 checkFileMode(t, filepath.Join(dst, "d1", "f1"), 0600) 117 checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660) 118 checkFileMode(t, filepath.Join(dst, "d3", "f1"), os.ModeCharDevice|os.ModeDevice) 119 120 checkOpaqueness(t, filepath.Join(dst, "d1"), "y") 121 checkOpaqueness(t, filepath.Join(dst, "d2"), "y") 122 checkOpaqueness(t, filepath.Join(dst, "d3"), "") 123 checkOverlayWhiteout(t, filepath.Join(dst, "d3", "f1")) 124 } 125 126 func TestOverlayTarAUFSUntar(t *testing.T) { 127 restore := overrideUmask(0) 128 defer restore() 129 130 src, err := os.MkdirTemp("", "docker-test-overlay-tar-src") 131 assert.NilError(t, err) 132 defer os.RemoveAll(src) 133 134 setupOverlayTestDir(t, src) 135 136 dst, err := os.MkdirTemp("", "docker-test-overlay-tar-dst") 137 assert.NilError(t, err) 138 defer os.RemoveAll(dst) 139 140 archive, err := TarWithOptions(src, &TarOptions{ 141 Compression: Uncompressed, 142 WhiteoutFormat: OverlayWhiteoutFormat, 143 }) 144 assert.NilError(t, err) 145 defer archive.Close() 146 147 err = Untar(archive, dst, &TarOptions{ 148 Compression: Uncompressed, 149 WhiteoutFormat: AUFSWhiteoutFormat, 150 }) 151 assert.NilError(t, err) 152 153 checkFileMode(t, filepath.Join(dst, "d1"), 0700|os.ModeDir) 154 checkFileMode(t, filepath.Join(dst, "d1", WhiteoutOpaqueDir), 0700) 155 checkFileMode(t, filepath.Join(dst, "d2"), 0750|os.ModeDir) 156 checkFileMode(t, filepath.Join(dst, "d2", WhiteoutOpaqueDir), 0750) 157 checkFileMode(t, filepath.Join(dst, "d3"), 0700|os.ModeDir) 158 checkFileMode(t, filepath.Join(dst, "d1", "f1"), 0600) 159 checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660) 160 checkFileMode(t, filepath.Join(dst, "d3", WhiteoutPrefix+"f1"), 0600) 161 }