Skip to content

Commit

Permalink
Merge pull request #171 from prologic/fix_symlink_support
Browse files Browse the repository at this point in the history
Adds support for Symlinks in all Tar decompressors
  • Loading branch information
azr committed Mar 12, 2019
2 parents e1437d0 + f4fe50a commit d9c5f68
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 13 deletions.
2 changes: 2 additions & 0 deletions decompress_bzip2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestBzip2Decompressor(t *testing.T) {
false,
false,
nil,
nil,
"d3b07384d113edec49eaa6238ad5ff00",
nil,
},
Expand All @@ -21,6 +22,7 @@ func TestBzip2Decompressor(t *testing.T) {
true,
true,
nil,
nil,
"",
nil,
},
Expand Down
2 changes: 2 additions & 0 deletions decompress_gzip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestGzipDecompressor(t *testing.T) {
false,
false,
nil,
nil,
"d3b07384d113edec49eaa6238ad5ff00",
nil,
},
Expand All @@ -21,6 +22,7 @@ func TestGzipDecompressor(t *testing.T) {
true,
true,
nil,
nil,
"",
nil,
},
Expand Down
9 changes: 9 additions & 0 deletions decompress_tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ func untar(input io.Reader, dst, src string, dir bool) error {
path = filepath.Join(path, hdr.Name)
}

if hdr.Typeflag == tar.TypeSymlink {
// If the type is a symlink we re-write it and
// continue instead of attempting to copy the contents
if err := os.Symlink(hdr.Linkname, path); err != nil {
return fmt.Errorf("failed writing symbolic link: %s", err)
}
continue
}

if hdr.FileInfo().IsDir() {
if !dir {
return fmt.Errorf("expected a single file: %s", src)
Expand Down
12 changes: 12 additions & 0 deletions decompress_tar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func TestTar(t *testing.T) {
true,
false,
[]string{"directory/", "directory/a", "directory/b"},
nil,
"",
nil,
},
Expand All @@ -22,6 +23,7 @@ func TestTar(t *testing.T) {
true,
false,
[]string{"directory/", "directory/sub/", "directory/sub/a", "directory/sub/b"},
nil,
"",
nil,
},
Expand All @@ -30,6 +32,16 @@ func TestTar(t *testing.T) {
true,
false,
[]string{"directory/", "directory/sub/", "directory/sub/a", "directory/sub/b"},
nil,
"",
&mtime,
},
{
"with-symlinks.tar",
true,
false,
[]string{"baz", "foo"},
map[string]string{"bar": "baz"},
"",
&mtime,
},
Expand Down
6 changes: 6 additions & 0 deletions decompress_tbz2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func TestTarBzip2Decompressor(t *testing.T) {
false,
true,
nil,
nil,
"",
nil,
},
Expand All @@ -23,6 +24,7 @@ func TestTarBzip2Decompressor(t *testing.T) {
false,
false,
nil,
nil,
"d3b07384d113edec49eaa6238ad5ff00",
nil,
},
Expand All @@ -32,6 +34,7 @@ func TestTarBzip2Decompressor(t *testing.T) {
true,
false,
[]string{"file"},
nil,
"",
nil,
},
Expand All @@ -41,6 +44,7 @@ func TestTarBzip2Decompressor(t *testing.T) {
true,
false,
[]string{"file1", "file2"},
nil,
"",
nil,
},
Expand All @@ -50,6 +54,7 @@ func TestTarBzip2Decompressor(t *testing.T) {
false,
true,
nil,
nil,
"",
nil,
},
Expand All @@ -60,6 +65,7 @@ func TestTarBzip2Decompressor(t *testing.T) {
true,
false,
orderingPaths,
nil,
"",
nil,
},
Expand Down
65 changes: 52 additions & 13 deletions decompress_testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import (

// TestDecompressCase is a single test case for testing decompressors
type TestDecompressCase struct {
Input string // Input is the complete path to the input file
Dir bool // Dir is whether or not we're testing directory mode
Err bool // Err is whether we expect an error or not
DirList []string // DirList is the list of files for Dir mode
FileMD5 string // FileMD5 is the expected MD5 for a single file
Mtime *time.Time // Mtime is the optionally expected mtime for a single file (or all files if in Dir mode)
Input string // Input is the complete path to the input file
Dir bool // Dir is whether or not we're testing directory mode
Err bool // Err is whether we expect an error or not
DirList []string // DirList is the list of files for Dir mode
Symlinks map[string]string // Optional map of symlinks to test
FileMD5 string // FileMD5 is the expected MD5 for a single file
Mtime *time.Time // Mtime is the optionally expected mtime for a single file (or all files if in Dir mode)
}

// TestDecompressor is a helper function for testing generic decompressors.
Expand Down Expand Up @@ -97,11 +98,17 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {

// Directory, check for the correct contents
actual := testListDir(t, dst)
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
if !reflect.DeepEqual(actual.files, expected) {
t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual.files, expected)
}

// Symlinks, check that symlinks match
if tc.Symlinks != nil && !reflect.DeepEqual(actual.symlinks, tc.Symlinks) {
t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual.symlinks, tc.Symlinks)
}

// Check for correct atime/mtime
for _, dir := range actual {
for _, dir := range actual.files {
path := filepath.Join(dst, dir)
if tc.Mtime != nil {
fi, err := os.Stat(path)
Expand All @@ -124,8 +131,32 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {
}
}

func testListDir(t testing.T, path string) []string {
var result []string
type testResult struct {
files []string
symlinks map[string]string
}

func (tr *testResult) AddFile(name string) {
tr.files = append(tr.files, name)
}

func (tr *testResult) AddSymlink(name, link string) {
tr.symlinks[name] = link
}

func (tr *testResult) SortFiles() {
sort.Strings(tr.files)
}

func newTestResult() *testResult {
return &testResult{
files: make([]string, 0),
symlinks: make(map[string]string),
}
}

func testListDir(t testing.T, path string) *testResult {
result := newTestResult()
err := filepath.Walk(path, func(sub string, info os.FileInfo, err error) error {
if err != nil {
return err
Expand All @@ -140,16 +171,24 @@ func testListDir(t testing.T, path string) []string {
// If it is a dir, add trailing sep
if info.IsDir() {
sub += string(os.PathSeparator)
result.AddFile(sub)
} else if info.Mode()&os.ModeSymlink != 0 {
link, err := os.Readlink(filepath.Join(path, info.Name()))
if err != nil {
return err
}
result.AddSymlink(sub, link)
} else {
result.AddFile(sub)
}

result = append(result, sub)
return nil
})
if err != nil {
t.Fatalf("err: %s", err)
}

sort.Strings(result)
result.SortFiles()
return result
}

Expand Down
8 changes: 8 additions & 0 deletions decompress_tgz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func TestTarGzipDecompressor(t *testing.T) {
false,
true,
nil,
nil,
"",
nil,
},
Expand All @@ -25,6 +26,7 @@ func TestTarGzipDecompressor(t *testing.T) {
false,
false,
nil,
nil,
"d3b07384d113edec49eaa6238ad5ff00",
nil,
},
Expand All @@ -34,6 +36,7 @@ func TestTarGzipDecompressor(t *testing.T) {
true,
false,
[]string{"file"},
nil,
"",
nil,
},
Expand All @@ -43,6 +46,7 @@ func TestTarGzipDecompressor(t *testing.T) {
true,
false,
[]string{"file1", "file2"},
nil,
"",
nil,
},
Expand All @@ -52,6 +56,7 @@ func TestTarGzipDecompressor(t *testing.T) {
false,
true,
nil,
nil,
"",
nil,
},
Expand All @@ -61,6 +66,7 @@ func TestTarGzipDecompressor(t *testing.T) {
true,
false,
multiplePaths,
nil,
"",
nil,
},
Expand All @@ -71,6 +77,7 @@ func TestTarGzipDecompressor(t *testing.T) {
true,
false,
orderingPaths,
nil,
"",
nil,
},
Expand All @@ -82,6 +89,7 @@ func TestTarGzipDecompressor(t *testing.T) {
true,
true,
nil,
nil,
"",
nil,
},
Expand Down
7 changes: 7 additions & 0 deletions decompress_txz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func TestTarXzDecompressor(t *testing.T) {
false,
true,
nil,
nil,
"",
nil,
},
Expand All @@ -25,6 +26,7 @@ func TestTarXzDecompressor(t *testing.T) {
false,
false,
nil,
nil,
"d3b07384d113edec49eaa6238ad5ff00",
nil,
},
Expand All @@ -34,6 +36,7 @@ func TestTarXzDecompressor(t *testing.T) {
true,
false,
[]string{"file"},
nil,
"",
nil,
},
Expand All @@ -43,6 +46,7 @@ func TestTarXzDecompressor(t *testing.T) {
true,
false,
[]string{"file1", "file2"},
nil,
"",
nil,
},
Expand All @@ -52,6 +56,7 @@ func TestTarXzDecompressor(t *testing.T) {
false,
true,
nil,
nil,
"",
nil,
},
Expand All @@ -61,6 +66,7 @@ func TestTarXzDecompressor(t *testing.T) {
true,
false,
multiplePaths,
nil,
"",
nil,
},
Expand All @@ -71,6 +77,7 @@ func TestTarXzDecompressor(t *testing.T) {
true,
false,
orderingPaths,
nil,
"",
nil,
},
Expand Down
2 changes: 2 additions & 0 deletions decompress_xz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestXzDecompressor(t *testing.T) {
false,
false,
nil,
nil,
"d3b07384d113edec49eaa6238ad5ff00",
nil,
},
Expand All @@ -21,6 +22,7 @@ func TestXzDecompressor(t *testing.T) {
true,
true,
nil,
nil,
"",
nil,
},
Expand Down
Loading

0 comments on commit d9c5f68

Please sign in to comment.