github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/tarutil/tar_test.go (about) 1 // Copyright 2019-2021 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tarutil 6 7 import ( 8 "os" 9 "os/exec" 10 "path/filepath" 11 "runtime" 12 "testing" 13 ) 14 15 func extractAndCompare(t *testing.T, tarFile string, files []struct{ name, body string }) { 16 tmpDir := t.TempDir() 17 18 // Extract tar to tmpDir. 19 f, err := os.Open(tarFile) 20 if err != nil { 21 t.Fatal(err) 22 } 23 defer f.Close() 24 if err := ExtractDir(f, tmpDir, &Opts{Filters: []Filter{SafeFilter}}); err != nil { 25 t.Fatal(err) 26 } 27 28 for _, f := range files { 29 body, err := os.ReadFile(filepath.Join(tmpDir, f.name)) 30 if err != nil { 31 t.Errorf("could not read %s: %v", f.name, err) 32 continue 33 } 34 if string(body) != f.body { 35 t.Errorf("for file %s, got %q, want %q", 36 f.name, string(body), f.body) 37 } 38 } 39 } 40 41 func TestExtractDir(t *testing.T) { 42 files := []struct { 43 name, body string 44 }{ 45 {"a.txt", "hello\n"}, 46 {"dir/b.txt", "world\n"}, 47 } 48 extractAndCompare(t, "test.tar", files) 49 } 50 51 func TestCreateTarSingleFile(t *testing.T) { 52 tmpDir := t.TempDir() 53 54 // Create the tar file. 55 filename := filepath.Join(tmpDir, "test.tar") 56 f, err := os.Create(filename) 57 if err != nil { 58 t.Fatal(err) 59 } 60 if err := CreateTar(f, []string{"test0"}, nil); err != nil { 61 f.Close() 62 t.Fatal(err) 63 } 64 if err := f.Close(); err != nil { 65 t.Fatal(err) 66 } 67 68 out, err := exec.Command("tar", "-tf", filename).CombinedOutput() 69 if err != nil { 70 t.Fatalf("system tar could not parse the file: %v", err) 71 } 72 expected := `test0 73 test0/a.txt 74 test0/dir 75 test0/dir/b.txt 76 ` 77 if string(out) != expected { 78 t.Fatalf("got %q, want %q", string(out), expected) 79 } 80 } 81 82 func TestCreateTarMultFiles(t *testing.T) { 83 tmpDir := t.TempDir() 84 85 // Create the tar file. 86 filename := filepath.Join(tmpDir, "test.tar") 87 f, err := os.Create(filename) 88 if err != nil { 89 t.Fatal(err) 90 } 91 files := []string{"test0", "test1", "test2.txt"} 92 if err := CreateTar(f, files, nil); err != nil { 93 f.Close() 94 t.Fatal(err) 95 } 96 if err := f.Close(); err != nil { 97 t.Fatal(err) 98 } 99 100 out, err := exec.Command("tar", "-tf", filename).CombinedOutput() 101 if err != nil { 102 t.Fatalf("system tar could not parse the file: %v", err) 103 } 104 expected := `test0 105 test0/a.txt 106 test0/dir 107 test0/dir/b.txt 108 test1 109 test1/a1.txt 110 test2.txt 111 ` 112 if string(out) != expected { 113 t.Fatalf("got %q, want %q", string(out), expected) 114 } 115 } 116 117 // TestCreateTarProcfsFile exercises the special case where stat on the file 118 // reports a size of 0, but the file actually has contents. For example, most 119 // of the files in /proc and /sys. 120 func TestCreateTarProcfsFile(t *testing.T) { 121 if runtime.GOOS != "linux" { 122 t.Skipf("/proc/version is only on linux, but GOOS=%s", runtime.GOOS) 123 } 124 125 tmpDir := t.TempDir() 126 127 // /proc/version won't change during the test. The size according to 128 // stat should also be 0. 129 procfsFile := "/proc/version" 130 contents, err := os.ReadFile(procfsFile) 131 if err != nil { 132 t.Fatal(err) 133 } 134 if fi, err := os.Stat(procfsFile); err != nil { 135 t.Fatal(err) 136 } else if fi.Size() != 0 { 137 t.Fatalf("Expected the size of %q to be 0, got %d", procfsFile, fi.Size()) 138 } 139 140 // Create the tar file containing /proc/version. 141 filename := filepath.Join(tmpDir, "test.tar") 142 f, err := os.Create(filename) 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 opts := &Opts{ 148 NoRecursion: true, 149 // We want the path names in the tar archive to be relative to 150 // root. We cannot store absolute paths in the tar file because 151 // it will fail the zipslip check on extraction. 152 ChangeDirectory: "/", 153 } 154 if err := CreateTar(f, []string{"proc", "proc/version"}, opts); err != nil { 155 f.Close() 156 t.Fatal(err) 157 } 158 if err := f.Close(); err != nil { 159 t.Fatal(err) 160 } 161 162 expected := []struct { 163 name, body string 164 }{ 165 {procfsFile, string(contents)}, 166 } 167 extractAndCompare(t, filename, expected) 168 } 169 170 func TestListArchive(t *testing.T) { 171 f, err := os.Open("test.tar") 172 if err != nil { 173 t.Fatal(err) 174 } 175 defer f.Close() 176 177 if err := ListArchive(f); err != nil { 178 t.Fatal(err) 179 } 180 }