Skip to content

Commit 232b93e

Browse files
committed
Implements the IsNonCompressedTarball directly in go instead of relying on file
1 parent f54397f commit 232b93e

File tree

3 files changed

+100
-90
lines changed

3 files changed

+100
-90
lines changed

fileutil/fakes/fake_compressor.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ type FakeCompressor struct {
2626

2727
CleanUpTarballPath string
2828
CleanUpErr error
29+
30+
IsNonCompressedResult bool
31+
IsNonCompressedErr error
2932
}
3033

3134
func NewFakeCompressor() *FakeCompressor {
@@ -66,7 +69,7 @@ func (fc *FakeCompressor) DecompressFileToDir(tarballPath string, dir string, op
6669
}
6770

6871
func (fc *FakeCompressor) IsNonCompressedTarball(path string) (bool, error) {
69-
return false, nil
72+
return fc.IsNonCompressedResult, fc.IsNonCompressedErr
7073
}
7174

7275
func (fc *FakeCompressor) CleanUp(tarballPath string) error {

fileutil/tarball_compressor.go

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
package fileutil
22

33
import (
4+
"bytes"
45
"fmt"
6+
"os"
57
"runtime"
6-
"strings"
78

89
bosherr "github.com/cloudfoundry/bosh-utils/errors"
910
boshsys "github.com/cloudfoundry/bosh-utils/system"
1011
)
1112

13+
var (
14+
gzipMagic = []byte{0x1f, 0x8b}
15+
bzip2Magic = []byte{0x42, 0x5a, 0x68} // "BZh"
16+
xzMagic = []byte{0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00}
17+
zstdMagic = []byte{0x28, 0xb5, 0x2f, 0xfd}
18+
ustarMagic = []byte("ustar")
19+
ustarOffset = 257 // Offset of the TAR magic string in the file
20+
)
21+
1222
type tarballCompressor struct {
1323
cmdRunner boshsys.CmdRunner
1424
fs boshsys.FileSystem
@@ -82,13 +92,35 @@ func (c tarballCompressor) DecompressFileToDir(tarballPath string, dir string, o
8292
}
8393

8494
func (c tarballCompressor) IsNonCompressedTarball(path string) (bool, error) {
85-
stdout, _, exitStatus, err := c.cmdRunner.RunCommand("file", path)
86-
if err != nil || exitStatus != 0 {
87-
return false, err
95+
f, err := c.fs.OpenFile(path, os.O_RDONLY, 0644)
96+
if err != nil {
97+
return false, fmt.Errorf("could not open file: %w", err)
98+
}
99+
defer f.Close()
100+
101+
// Read the first 512 bytes to check both compression headers and the TAR header.
102+
// Ignore the error from reading a partial buffer, which is fine for short files.
103+
buffer := make([]byte, 512)
104+
_, _ = f.Read(buffer)
105+
106+
// 1. Check for compression first.
107+
if bytes.HasPrefix(buffer, gzipMagic) ||
108+
bytes.HasPrefix(buffer, bzip2Magic) ||
109+
bytes.HasPrefix(buffer, xzMagic) ||
110+
bytes.HasPrefix(buffer, zstdMagic) {
111+
return false, nil
112+
}
113+
114+
// 2. If NOT compressed, check for the TAR magic string at its specific offset.
115+
// Ensure the buffer is long enough to contain the TAR header magic string.
116+
if len(buffer) > ustarOffset+len(ustarMagic) {
117+
magicBytes := buffer[ustarOffset : ustarOffset+len(ustarMagic)]
118+
if bytes.Equal(magicBytes, ustarMagic) {
119+
return true, nil
120+
}
88121
}
89122

90-
fileOutputStr := strings.TrimSpace(stdout)
91-
return strings.Contains(fileOutputStr, "POSIX tar archive"), nil
123+
return false, nil
92124
}
93125

94126
func (c tarballCompressor) CleanUp(tarballPath string) error {

fileutil/tarball_compressor_test.go

Lines changed: 58 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -274,119 +274,94 @@ var _ = Describe("tarballCompressor", func() {
274274
})
275275

276276
Describe("IsNonCompressedTarball", func() {
277-
It("returns true for non-compressed tarball files", func() {
278-
cmdRunner := fakesys.NewFakeCmdRunner()
279-
compressor := NewTarballCompressor(cmdRunner, fs)
280-
281-
// Mock the file command output for a non-compressed tarball
282-
cmdRunner.AddCmdResult("file /test/file.tar", fakesys.FakeCmdResult{
283-
Stdout: "/test/file.tar: POSIX tar archive\n",
284-
Stderr: "",
285-
ExitStatus: 0,
286-
})
277+
It("returns true for non-compressed tarball created with NoCompression=true", func() {
278+
// Create a non-compressed tarball using CompressFilesInDir with NoCompression=true
279+
tgzName, err := compressor.CompressFilesInDir(testAssetsFixtureDir, CompressorOptions{NoCompression: true})
280+
Expect(err).ToNot(HaveOccurred())
281+
defer os.Remove(tgzName)
287282

288-
result, err := compressor.IsNonCompressedTarball("/test/file.tar")
283+
// Test that IsNonCompressedTarball correctly identifies it as non-compressed
284+
result, err := compressor.IsNonCompressedTarball(tgzName)
289285
Expect(err).ToNot(HaveOccurred())
290286
Expect(result).To(BeTrue())
291-
292-
Expect(1).To(Equal(len(cmdRunner.RunCommands)))
293-
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tar"}))
294287
})
295288

296-
It("returns false for compressed tarball files", func() {
297-
cmdRunner := fakesys.NewFakeCmdRunner()
298-
compressor := NewTarballCompressor(cmdRunner, fs)
299-
300-
// Mock the file command output for a compressed tarball
301-
cmdRunner.AddCmdResult("file /test/file.tgz", fakesys.FakeCmdResult{
302-
Stdout: "/test/file.tgz: gzip compressed data, from Unix, original size modulo 2^32 1024\n",
303-
Stderr: "",
304-
ExitStatus: 0,
305-
})
289+
It("returns false for compressed tarball created with NoCompression=false", func() {
290+
// Create a compressed tarball using CompressFilesInDir with NoCompression=false
291+
tgzName, err := compressor.CompressFilesInDir(testAssetsFixtureDir, CompressorOptions{NoCompression: false})
292+
Expect(err).ToNot(HaveOccurred())
293+
defer os.Remove(tgzName)
306294

307-
result, err := compressor.IsNonCompressedTarball("/test/file.tgz")
295+
// Test that IsNonCompressedTarball correctly identifies it as compressed
296+
result, err := compressor.IsNonCompressedTarball(tgzName)
308297
Expect(err).ToNot(HaveOccurred())
309298
Expect(result).To(BeFalse())
310-
311-
Expect(1).To(Equal(len(cmdRunner.RunCommands)))
312-
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tgz"}))
313299
})
314300

315-
It("returns false for non-tarball files", func() {
316-
cmdRunner := fakesys.NewFakeCmdRunner()
317-
compressor := NewTarballCompressor(cmdRunner, fs)
318-
319-
// Mock the file command output for a regular text file
320-
cmdRunner.AddCmdResult("file /test/file.txt", fakesys.FakeCmdResult{
321-
Stdout: "/test/file.txt: ASCII text\n",
322-
Stderr: "",
323-
ExitStatus: 0,
324-
})
301+
It("returns false for compressed tarball created with default options", func() {
302+
// Create a compressed tarball using CompressFilesInDir with default options (NoCompression=false)
303+
tgzName, err := compressor.CompressFilesInDir(testAssetsFixtureDir, CompressorOptions{})
304+
Expect(err).ToNot(HaveOccurred())
305+
defer os.Remove(tgzName)
325306

326-
result, err := compressor.IsNonCompressedTarball("/test/file.txt")
307+
// Test that IsNonCompressedTarball correctly identifies it as compressed
308+
result, err := compressor.IsNonCompressedTarball(tgzName)
327309
Expect(err).ToNot(HaveOccurred())
328310
Expect(result).To(BeFalse())
311+
})
329312

330-
Expect(1).To(Equal(len(cmdRunner.RunCommands)))
331-
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.txt"}))
313+
It("returns error for non-existent file", func() {
314+
result, err := compressor.IsNonCompressedTarball("/nonexistent/file.tar")
315+
Expect(err).To(HaveOccurred())
316+
Expect(result).To(BeFalse())
332317
})
333318

334-
It("returns error when file command fails", func() {
335-
cmdRunner := fakesys.NewFakeCmdRunner()
336-
compressor := NewTarballCompressor(cmdRunner, fs)
319+
It("returns error for non-tarball file", func() {
320+
// Create a temporary text file
321+
tempFile, err := fs.TempFile("test-non-tarball")
322+
Expect(err).ToNot(HaveOccurred())
323+
defer os.Remove(tempFile.Name())
337324

338-
// Mock the file command to return an error
339-
cmdRunner.AddCmdResult("file /test/nonexistent.tar", fakesys.FakeCmdResult{
340-
Stdout: "",
341-
Stderr: "file: cannot open `/test/nonexistent.tar' (No such file or directory)\n",
342-
ExitStatus: 1,
343-
})
325+
err = fs.WriteFileString(tempFile.Name(), "This is not a tar file")
326+
Expect(err).ToNot(HaveOccurred())
344327

345-
result, _ := compressor.IsNonCompressedTarball("/test/nonexistent.tar")
328+
result, err := compressor.IsNonCompressedTarball(tempFile.Name())
329+
Expect(err).ToNot(HaveOccurred())
346330
Expect(result).To(BeFalse())
347-
348-
Expect(1).To(Equal(len(cmdRunner.RunCommands)))
349-
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/nonexistent.tar"}))
350331
})
351332

352-
It("returns error when file command execution fails", func() {
353-
cmdRunner := fakesys.NewFakeCmdRunner()
354-
compressor := NewTarballCompressor(cmdRunner, fs)
355-
356-
// Mock the file command to return an execution error
357-
cmdRunner.AddCmdResult("file /test/file.tar", fakesys.FakeCmdResult{
358-
Stdout: "",
359-
Stderr: "",
360-
ExitStatus: 0,
361-
Error: errors.New("command execution failed"),
362-
})
333+
It("returns error for empty file", func() {
334+
// Create an empty temporary file
335+
tempFile, err := fs.TempFile("test-empty-file")
336+
Expect(err).ToNot(HaveOccurred())
337+
defer os.Remove(tempFile.Name())
338+
tempFile.Close()
363339

364-
result, err := compressor.IsNonCompressedTarball("/test/file.tar")
365-
Expect(err).To(HaveOccurred())
366-
Expect(err.Error()).To(ContainSubstring("command execution failed"))
340+
result, err := compressor.IsNonCompressedTarball(tempFile.Name())
341+
Expect(err).ToNot(HaveOccurred())
367342
Expect(result).To(BeFalse())
368-
369-
Expect(1).To(Equal(len(cmdRunner.RunCommands)))
370-
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tar"}))
371343
})
372344

373-
It("handles file command output with extra whitespace", func() {
374-
cmdRunner := fakesys.NewFakeCmdRunner()
375-
compressor := NewTarballCompressor(cmdRunner, fs)
345+
It("correctly identifies tarballs created with CompressSpecificFilesInDir", func() {
346+
files := []string{"app.stdout.log", "app.stderr.log"}
376347

377-
// Mock the file command output with extra whitespace
378-
cmdRunner.AddCmdResult("file /test/file.tar", fakesys.FakeCmdResult{
379-
Stdout: " /test/file.tar: POSIX tar archive \n",
380-
Stderr: "",
381-
ExitStatus: 0,
382-
})
348+
// Test non-compressed tarball
349+
tgzName, err := compressor.CompressSpecificFilesInDir(testAssetsFixtureDir, files, CompressorOptions{NoCompression: true})
350+
Expect(err).ToNot(HaveOccurred())
351+
defer os.Remove(tgzName)
383352

384-
result, err := compressor.IsNonCompressedTarball("/test/file.tar")
353+
result, err := compressor.IsNonCompressedTarball(tgzName)
385354
Expect(err).ToNot(HaveOccurred())
386355
Expect(result).To(BeTrue())
387356

388-
Expect(1).To(Equal(len(cmdRunner.RunCommands)))
389-
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tar"}))
357+
// Test compressed tarball
358+
tgzName2, err := compressor.CompressSpecificFilesInDir(testAssetsFixtureDir, files, CompressorOptions{NoCompression: false})
359+
Expect(err).ToNot(HaveOccurred())
360+
defer os.Remove(tgzName2)
361+
362+
result2, err := compressor.IsNonCompressedTarball(tgzName2)
363+
Expect(err).ToNot(HaveOccurred())
364+
Expect(result2).To(BeFalse())
390365
})
391366
})
392367

0 commit comments

Comments
 (0)