Ensure adding a broken tar doesn't silently fail
Signed-off-by: Aidan Hobson Sayers <aidanhs@cantab.net>
This commit is contained in:
parent
688bb55544
commit
12fc11efd0
2 changed files with 64 additions and 5 deletions
|
@ -77,6 +77,11 @@ var (
|
||||||
defaultArchiver = &Archiver{Untar: Untar, UIDMaps: nil, GIDMaps: nil}
|
defaultArchiver = &Archiver{Untar: Untar, UIDMaps: nil, GIDMaps: nil}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// HeaderSize is the size in bytes of a tar header
|
||||||
|
HeaderSize = 512
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Uncompressed represents the uncompressed.
|
// Uncompressed represents the uncompressed.
|
||||||
Uncompressed Compression = iota
|
Uncompressed Compression = iota
|
||||||
|
@ -88,7 +93,8 @@ const (
|
||||||
Xz
|
Xz
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsArchive checks if it is a archive by the header.
|
// IsArchive checks for the magic bytes of a tar or any supported compression
|
||||||
|
// algorithm.
|
||||||
func IsArchive(header []byte) bool {
|
func IsArchive(header []byte) bool {
|
||||||
compression := DetectCompression(header)
|
compression := DetectCompression(header)
|
||||||
if compression != Uncompressed {
|
if compression != Uncompressed {
|
||||||
|
@ -99,6 +105,23 @@ func IsArchive(header []byte) bool {
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsArchivePath checks if the (possibly compressed) file at the given path
|
||||||
|
// starts with a tar file header.
|
||||||
|
func IsArchivePath(path string) bool {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
rdr, err := DecompressStream(file)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
r := tar.NewReader(rdr)
|
||||||
|
_, err = r.Next()
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
// DetectCompression detects the compression algorithm of the source.
|
// DetectCompression detects the compression algorithm of the source.
|
||||||
func DetectCompression(source []byte) Compression {
|
func DetectCompression(source []byte) Compression {
|
||||||
for compression, m := range map[Compression][]byte{
|
for compression, m := range map[Compression][]byte{
|
||||||
|
@ -800,10 +823,7 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
|
||||||
GIDMaps: archiver.GIDMaps,
|
GIDMaps: archiver.GIDMaps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := archiver.Untar(archive, dst, options); err != nil {
|
return archiver.Untar(archive, dst, options)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UntarPath is a convenience function which looks for an archive
|
// UntarPath is a convenience function which looks for an archive
|
||||||
|
|
|
@ -49,6 +49,45 @@ func TestIsArchive7zip(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsArchivePathDir(t *testing.T) {
|
||||||
|
cmd := exec.Command("/bin/sh", "-c", "mkdir -p /tmp/archivedir")
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Fail to create an archive file for test : %s.", output)
|
||||||
|
}
|
||||||
|
if IsArchivePath("/tmp/archivedir") {
|
||||||
|
t.Fatalf("Incorrectly recognised directory as an archive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsArchivePathInvalidFile(t *testing.T) {
|
||||||
|
cmd := exec.Command("/bin/sh", "-c", "dd if=/dev/zero bs=1K count=1 of=/tmp/archive && gzip --stdout /tmp/archive > /tmp/archive.gz")
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Fail to create an archive file for test : %s.", output)
|
||||||
|
}
|
||||||
|
if IsArchivePath("/tmp/archive") {
|
||||||
|
t.Fatalf("Incorrectly recognised invalid tar path as archive")
|
||||||
|
}
|
||||||
|
if IsArchivePath("/tmp/archive.gz") {
|
||||||
|
t.Fatalf("Incorrectly recognised invalid compressed tar path as archive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsArchivePathTar(t *testing.T) {
|
||||||
|
cmd := exec.Command("/bin/sh", "-c", "touch /tmp/archivedata && tar -cf /tmp/archive /tmp/archivedata && gzip --stdout /tmp/archive > /tmp/archive.gz")
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Fail to create an archive file for test : %s.", output)
|
||||||
|
}
|
||||||
|
if !IsArchivePath("/tmp/archive") {
|
||||||
|
t.Fatalf("Did not recognise valid tar path as archive")
|
||||||
|
}
|
||||||
|
if !IsArchivePath("/tmp/archive.gz") {
|
||||||
|
t.Fatalf("Did not recognise valid compressed tar path as archive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDecompressStreamGzip(t *testing.T) {
|
func TestDecompressStreamGzip(t *testing.T) {
|
||||||
cmd := exec.Command("/bin/sh", "-c", "touch /tmp/archive && gzip -f /tmp/archive")
|
cmd := exec.Command("/bin/sh", "-c", "touch /tmp/archive && gzip -f /tmp/archive")
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
|
|
Loading…
Reference in a new issue