From d1fd0465e4567060beef6834acf38996cedd6ead Mon Sep 17 00:00:00 2001 From: Daniel Barton Date: Wed, 18 Oct 2023 10:47:36 +0800 Subject: [PATCH] server(filesystem): fix file names when extracting archives (#165) --- server/backup/backup_local.go | 2 +- server/backup/backup_s3.go | 2 +- server/filesystem/compress.go | 53 +---------------------------------- 3 files changed, 3 insertions(+), 54 deletions(-) diff --git a/server/backup/backup_local.go b/server/backup/backup_local.go index a6a1d72..1d520e1 100644 --- a/server/backup/backup_local.go +++ b/server/backup/backup_local.go @@ -100,7 +100,7 @@ func (b *LocalBackup) Restore(ctx context.Context, _ io.Reader, callback Restore } defer r.Close() - return callback(filesystem.ExtractNameFromArchive(f), f.FileInfo, r) + return callback(f.NameInArchive, f.FileInfo, r) }); err != nil { return err } diff --git a/server/backup/backup_s3.go b/server/backup/backup_s3.go index ede235a..5d3ae96 100644 --- a/server/backup/backup_s3.go +++ b/server/backup/backup_s3.go @@ -100,7 +100,7 @@ func (s *S3Backup) Restore(ctx context.Context, r io.Reader, callback RestoreCal } defer r.Close() - return callback(filesystem.ExtractNameFromArchive(f), f.FileInfo, r) + return callback(f.NameInArchive, f.FileInfo, r) }); err != nil { return err } diff --git a/server/filesystem/compress.go b/server/filesystem/compress.go index 0e52972..ed2810d 100644 --- a/server/filesystem/compress.go +++ b/server/filesystem/compress.go @@ -1,9 +1,6 @@ package filesystem import ( - "archive/tar" - "archive/zip" - "compress/gzip" "context" "fmt" "io" @@ -11,14 +8,11 @@ import ( "os" "path" "path/filepath" - "reflect" "strings" "sync/atomic" "time" "emperror.dev/errors" - gzip2 "github.com/klauspost/compress/gzip" - zip2 "github.com/klauspost/compress/zip" "github.com/mholt/archiver/v4" ) @@ -201,7 +195,7 @@ func (fs *Filesystem) extractStream(ctx context.Context, opts extractStreamOptio if f.IsDir() { return nil } - p := filepath.Join(opts.Directory, ExtractNameFromArchive(f)) + p := filepath.Join(opts.Directory, f.NameInArchive) // If it is ignored, just don't do anything with the file and skip over it. if err := fs.IsIgnored(p); err != nil { return nil @@ -227,48 +221,3 @@ func (fs *Filesystem) extractStream(ctx context.Context, opts extractStreamOptio } return nil } - -// ExtractNameFromArchive looks at an archive file to try and determine the name -// for a given element in an archive. Because of... who knows why, each file type -// uses different methods to determine the file name. -// -// If there is a archiver.File#Sys() value present we will try to use the name -// present in there, otherwise falling back to archiver.File#Name() if all else -// fails. Without this logic present, some archive types such as zip/tars/etc. -// will write all of the files to the base directory, rather than the nested -// directory that is expected. -// -// For files like ".rar" types, there is no f.Sys() value present, and the value -// of archiver.File#Name() will be what you need. -func ExtractNameFromArchive(f archiver.File) string { - sys := f.Sys() - // Some archive types won't have a value returned when you call f.Sys() on them, - // such as ".rar" archives for example. In those cases the only thing you can do - // is hope that "f.Name()" is actually correct for them. - if sys == nil { - return f.Name() - } - switch s := sys.(type) { - case *zip.FileHeader: - return s.Name - case *zip2.FileHeader: - return s.Name - case *tar.Header: - return s.Name - case *gzip.Header: - return s.Name - case *gzip2.Header: - return s.Name - default: - // At this point we cannot figure out what type of archive this might be so - // just try to find the name field in the struct. If it is found return it. - field := reflect.Indirect(reflect.ValueOf(sys)).FieldByName("Name") - if field.IsValid() { - return field.String() - } - // Fallback to the basename of the file at this point. There is nothing we can really - // do to try and figure out what the underlying directory of the file is supposed to - // be since it didn't implement a name field. - return f.Name() - } -}