github.com/kunnos/engine@v1.13.1/pkg/archive/archive_unix_test.go (about) 1 // +build !windows 2 3 package archive 4 5 import ( 6 "bytes" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "runtime" 12 "syscall" 13 "testing" 14 15 "github.com/docker/docker/pkg/system" 16 ) 17 18 func TestCanonicalTarNameForPath(t *testing.T) { 19 cases := []struct{ in, expected string }{ 20 {"foo", "foo"}, 21 {"foo/bar", "foo/bar"}, 22 {"foo/dir/", "foo/dir/"}, 23 } 24 for _, v := range cases { 25 if out, err := CanonicalTarNameForPath(v.in); err != nil { 26 t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err) 27 } else if out != v.expected { 28 t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out) 29 } 30 } 31 } 32 33 func TestCanonicalTarName(t *testing.T) { 34 cases := []struct { 35 in string 36 isDir bool 37 expected string 38 }{ 39 {"foo", false, "foo"}, 40 {"foo", true, "foo/"}, 41 {"foo/bar", false, "foo/bar"}, 42 {"foo/bar", true, "foo/bar/"}, 43 } 44 for _, v := range cases { 45 if out, err := canonicalTarName(v.in, v.isDir); err != nil { 46 t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err) 47 } else if out != v.expected { 48 t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out) 49 } 50 } 51 } 52 53 func TestChmodTarEntry(t *testing.T) { 54 cases := []struct { 55 in, expected os.FileMode 56 }{ 57 {0000, 0000}, 58 {0777, 0777}, 59 {0644, 0644}, 60 {0755, 0755}, 61 {0444, 0444}, 62 } 63 for _, v := range cases { 64 if out := chmodTarEntry(v.in); out != v.expected { 65 t.Fatalf("wrong chmod. expected:%v got:%v", v.expected, out) 66 } 67 } 68 } 69 70 func TestTarWithHardLink(t *testing.T) { 71 origin, err := ioutil.TempDir("", "docker-test-tar-hardlink") 72 if err != nil { 73 t.Fatal(err) 74 } 75 defer os.RemoveAll(origin) 76 if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil { 77 t.Fatal(err) 78 } 79 if err := os.Link(filepath.Join(origin, "1"), filepath.Join(origin, "2")); err != nil { 80 t.Fatal(err) 81 } 82 83 var i1, i2 uint64 84 if i1, err = getNlink(filepath.Join(origin, "1")); err != nil { 85 t.Fatal(err) 86 } 87 // sanity check that we can hardlink 88 if i1 != 2 { 89 t.Skipf("skipping since hardlinks don't work here; expected 2 links, got %d", i1) 90 } 91 92 dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest") 93 if err != nil { 94 t.Fatal(err) 95 } 96 defer os.RemoveAll(dest) 97 98 // we'll do this in two steps to separate failure 99 fh, err := Tar(origin, Uncompressed) 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 // ensure we can read the whole thing with no error, before writing back out 105 buf, err := ioutil.ReadAll(fh) 106 if err != nil { 107 t.Fatal(err) 108 } 109 110 bRdr := bytes.NewReader(buf) 111 err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed}) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 if i1, err = getInode(filepath.Join(dest, "1")); err != nil { 117 t.Fatal(err) 118 } 119 if i2, err = getInode(filepath.Join(dest, "2")); err != nil { 120 t.Fatal(err) 121 } 122 123 if i1 != i2 { 124 t.Errorf("expected matching inodes, but got %d and %d", i1, i2) 125 } 126 } 127 128 func getNlink(path string) (uint64, error) { 129 stat, err := os.Stat(path) 130 if err != nil { 131 return 0, err 132 } 133 statT, ok := stat.Sys().(*syscall.Stat_t) 134 if !ok { 135 return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys()) 136 } 137 // We need this conversion on ARM64 138 return uint64(statT.Nlink), nil 139 } 140 141 func getInode(path string) (uint64, error) { 142 stat, err := os.Stat(path) 143 if err != nil { 144 return 0, err 145 } 146 statT, ok := stat.Sys().(*syscall.Stat_t) 147 if !ok { 148 return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys()) 149 } 150 return statT.Ino, nil 151 } 152 153 func TestTarWithBlockCharFifo(t *testing.T) { 154 origin, err := ioutil.TempDir("", "docker-test-tar-hardlink") 155 if err != nil { 156 t.Fatal(err) 157 } 158 defer os.RemoveAll(origin) 159 if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil { 160 t.Fatal(err) 161 } 162 if err := system.Mknod(filepath.Join(origin, "2"), syscall.S_IFBLK, int(system.Mkdev(int64(12), int64(5)))); err != nil { 163 t.Fatal(err) 164 } 165 if err := system.Mknod(filepath.Join(origin, "3"), syscall.S_IFCHR, int(system.Mkdev(int64(12), int64(5)))); err != nil { 166 t.Fatal(err) 167 } 168 if err := system.Mknod(filepath.Join(origin, "4"), syscall.S_IFIFO, int(system.Mkdev(int64(12), int64(5)))); err != nil { 169 t.Fatal(err) 170 } 171 172 dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest") 173 if err != nil { 174 t.Fatal(err) 175 } 176 defer os.RemoveAll(dest) 177 178 // we'll do this in two steps to separate failure 179 fh, err := Tar(origin, Uncompressed) 180 if err != nil { 181 t.Fatal(err) 182 } 183 184 // ensure we can read the whole thing with no error, before writing back out 185 buf, err := ioutil.ReadAll(fh) 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 bRdr := bytes.NewReader(buf) 191 err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed}) 192 if err != nil { 193 t.Fatal(err) 194 } 195 196 changes, err := ChangesDirs(origin, dest) 197 if err != nil { 198 t.Fatal(err) 199 } 200 if len(changes) > 0 { 201 t.Fatalf("Tar with special device (block, char, fifo) should keep them (recreate them when untar) : %v", changes) 202 } 203 } 204 205 // TestTarUntarWithXattr is Unix as Lsetxattr is not supported on Windows 206 func TestTarUntarWithXattr(t *testing.T) { 207 if runtime.GOOS == "solaris" { 208 t.Skip() 209 } 210 origin, err := ioutil.TempDir("", "docker-test-untar-origin") 211 if err != nil { 212 t.Fatal(err) 213 } 214 defer os.RemoveAll(origin) 215 if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil { 216 t.Fatal(err) 217 } 218 if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil { 219 t.Fatal(err) 220 } 221 if err := ioutil.WriteFile(filepath.Join(origin, "3"), []byte("will be ignored"), 0700); err != nil { 222 t.Fatal(err) 223 } 224 if err := system.Lsetxattr(filepath.Join(origin, "2"), "security.capability", []byte{0x00}, 0); err != nil { 225 t.Fatal(err) 226 } 227 228 for _, c := range []Compression{ 229 Uncompressed, 230 Gzip, 231 } { 232 changes, err := tarUntar(t, origin, &TarOptions{ 233 Compression: c, 234 ExcludePatterns: []string{"3"}, 235 }) 236 237 if err != nil { 238 t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err) 239 } 240 241 if len(changes) != 1 || changes[0].Path != "/3" { 242 t.Fatalf("Unexpected differences after tarUntar: %v", changes) 243 } 244 capability, _ := system.Lgetxattr(filepath.Join(origin, "2"), "security.capability") 245 if capability == nil && capability[0] != 0x00 { 246 t.Fatalf("Untar should have kept the 'security.capability' xattr.") 247 } 248 } 249 }