diff --git a/fileutil/tarball_compressor.go b/fileutil/tarball_compressor.go index 23e8857d..4a789f04 100644 --- a/fileutil/tarball_compressor.go +++ b/fileutil/tarball_compressor.go @@ -1,6 +1,7 @@ package fileutil import ( + "archive/tar" "fmt" "io" "io/fs" @@ -9,16 +10,16 @@ import ( "runtime" "strings" - "archive/tar" - "github.com/klauspost/pgzip" bosherr "github.com/cloudfoundry/bosh-utils/errors" boshsys "github.com/cloudfoundry/bosh-utils/system" ) +const forwardSlash string = "/" + type tarballCompressor struct { - fs boshsys.FileSystem + fs boshsys.FileSystem } func NewTarballCompressor( @@ -72,7 +73,7 @@ func (c tarballCompressor) CompressSpecificFilesInDir(dir string, files []string header.Name = relPath if runtime.GOOS == "windows" { - header.Name = strings.ReplaceAll(relPath, "\\", "/") + header.Name = strings.ReplaceAll(relPath, "\\", forwardSlash) } if err := tw.WriteHeader(header); err != nil { @@ -98,7 +99,7 @@ func (c tarballCompressor) CompressSpecificFilesInDir(dir string, files []string return "", bosherr.WrapError(err, "Creating tgz") } - if err = tw.Close(); err != nil { + if err = tw.Close(); err != nil { return "", bosherr.WrapError(err, "Closing tar writer") } @@ -140,13 +141,13 @@ func (c tarballCompressor) DecompressFileToDir(tarballPath string, dir string, o if options.PathInArchive != "" && !strings.HasPrefix( filepath.Clean(header.Name), filepath.Clean(options.PathInArchive)) { - continue + continue } fullName := filepath.Join(dir, filepath.FromSlash(header.Name)) if options.StripComponents > 0 { - components := strings.Split(filepath.Clean(header.Name), string(filepath.Separator)) + components := strings.Split(header.Name, forwardSlash) if len(components) <= options.StripComponents { continue } @@ -171,12 +172,12 @@ func (c tarballCompressor) DecompressFileToDir(tarballPath string, dir string, o } case tar.TypeLink: - if err := c.fs.Symlink(header.Linkname, fullName); err != nil { + if err := c.fs.Symlink(header.Linkname, fullName); err != nil { return bosherr.WrapError(err, "Decompressing link") } - case tar.TypeSymlink: - if err := c.fs.Symlink(header.Linkname, fullName); err != nil { + case tar.TypeSymlink: + if err := c.fs.Symlink(header.Linkname, fullName); err != nil { return bosherr.WrapError(err, "Decompressing symlink") } diff --git a/fileutil/tarball_compressor_test.go b/fileutil/tarball_compressor_test.go index d586f4d5..c7f59a5f 100644 --- a/fileutil/tarball_compressor_test.go +++ b/fileutil/tarball_compressor_test.go @@ -161,7 +161,6 @@ var _ = Describe("tarballCompressor", func() { "other_logs/more_logs/more.stdout.log", )) - content, err := fs.ReadFileString(filepath.FromSlash(dstDir + "/app.stdout.log")) Expect(err).ToNot(HaveOccurred()) Expect(content).To(ContainSubstring("this is app stdout")) @@ -250,7 +249,7 @@ var _ = Describe("tarballCompressor", func() { var ( tarballPath string - fs *fakesys.FakeFileSystem + fs *fakesys.FakeFileSystem ) BeforeEach(func() { @@ -267,7 +266,6 @@ var _ = Describe("tarballCompressor", func() { Expect(err).ToNot(HaveOccurred()) }) - It("uses no same owner option", func() { compressor := NewTarballCompressor(fs) err := compressor.DecompressFileToDir(tarballPath, dstDir, CompressorOptions{}) @@ -353,9 +351,15 @@ var _ = Describe("tarballCompressor", func() { dstElements, err := pathsInDir(dstDir) Expect(err).ToNot(HaveOccurred()) + // tar --strip-components treats a leading `./` in the file headers as its own component. + // So ./dir/some-file becomes dir/some-file with strip-components = 1. + // The example tar file in this test contains the leading ./ for each of its files. Expect(dstElements).To(Equal([]string{ "./", - "double-nested-file", + "empty-nested-dir/", + "nested-dir/", + "nested-dir/double-nested-file", + "nested-file", })) }) })