diff --git a/decompress_tgz.go b/decompress_tgz.go index e8b1c31ca..7084e48d9 100644 --- a/decompress_tgz.go +++ b/decompress_tgz.go @@ -80,6 +80,26 @@ func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool) error { // Mark that we're done so future in single file mode errors done = true + 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.Typeflag == tar.TypeLink) { + // If the type is a link ("hardlink") we re-write it and + // continue instead of attempting to copy the contents + if err := os.Link(hdr.Linkname, path); err != nil { + return fmt.Errorf("failed writing link: %s", err) + } + + continue + } + // Open the file for writing dstF, err := os.Create(path) if err != nil { diff --git a/decompress_tgz_test.go b/decompress_tgz_test.go index f3261d3df..9a468be15 100644 --- a/decompress_tgz_test.go +++ b/decompress_tgz_test.go @@ -61,6 +61,22 @@ func TestTarGzipDecompressor(t *testing.T) { multiplePaths, "", }, + + { + "with-symlinks.tar.gz", + true, + false, + []string{"bar", "baz", "foo"}, + "", + }, + + { + "with-links.tar.gz", + true, + false, + []string{"foo", "bar"}, + "", + }, } for i, tc := range cases { diff --git a/test-fixtures/decompress-tgz/with-links.tar.gz b/test-fixtures/decompress-tgz/with-links.tar.gz new file mode 100644 index 000000000..a08f2f471 Binary files /dev/null and b/test-fixtures/decompress-tgz/with-links.tar.gz differ diff --git a/test-fixtures/decompress-tgz/with-symlinks.tar.gz b/test-fixtures/decompress-tgz/with-symlinks.tar.gz new file mode 100644 index 000000000..f92504a96 Binary files /dev/null and b/test-fixtures/decompress-tgz/with-symlinks.tar.gz differ