zip creation: avoid stat if not strictly required

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino
2025-01-02 18:05:47 +01:00
parent a0f781aeef
commit b02b79fe6d
4 changed files with 29 additions and 23 deletions

View File

@@ -999,7 +999,7 @@ func getFileWriter(conn *BaseConnection, virtualPath string, expectedSize int64)
return w, numFiles, truncatedSize, cancelFn, nil return w, numFiles, truncatedSize, cancelFn, nil
} }
func addZipEntry(wr *zipWriterWrapper, conn *BaseConnection, entryPath, baseDir string, recursion int) error { func addZipEntry(wr *zipWriterWrapper, conn *BaseConnection, entryPath, baseDir string, info os.FileInfo, recursion int) error { //nolint:gocyclo
if entryPath == wr.Name { if entryPath == wr.Name {
// skip the archive itself // skip the archive itself
return nil return nil
@@ -1009,10 +1009,13 @@ func addZipEntry(wr *zipWriterWrapper, conn *BaseConnection, entryPath, baseDir
return util.ErrRecursionTooDeep return util.ErrRecursionTooDeep
} }
recursion++ recursion++
info, err := conn.DoStat(entryPath, 1, false) var err error
if err != nil { if info == nil {
eventManagerLog(logger.LevelError, "unable to add zip entry %q, stat error: %v", entryPath, err) info, err = conn.DoStat(entryPath, 1, false)
return err if err != nil {
eventManagerLog(logger.LevelError, "unable to add zip entry %q, stat error: %v", entryPath, err)
return err
}
} }
entryName, err := getZipEntryName(entryPath, baseDir) entryName, err := getZipEntryName(entryPath, baseDir)
if err != nil { if err != nil {
@@ -1050,7 +1053,7 @@ func addZipEntry(wr *zipWriterWrapper, conn *BaseConnection, entryPath, baseDir
} }
for _, info := range contents { for _, info := range contents {
fullPath := util.CleanPath(path.Join(entryPath, info.Name())) fullPath := util.CleanPath(path.Join(entryPath, info.Name()))
if err := addZipEntry(wr, conn, fullPath, baseDir, recursion); err != nil { if err := addZipEntry(wr, conn, fullPath, baseDir, info, recursion); err != nil {
eventManagerLog(logger.LevelError, "unable to add zip entry: %v", err) eventManagerLog(logger.LevelError, "unable to add zip entry: %v", err)
return err return err
} }
@@ -2042,7 +2045,7 @@ func executeCompressFsActionForUser(c dataprovider.EventActionFsCompress, replac
} }
startTime := time.Now() startTime := time.Now()
for _, item := range paths { for _, item := range paths {
if err := addZipEntry(zipWriter, conn, item, baseDir, 0); err != nil { if err := addZipEntry(zipWriter, conn, item, baseDir, nil, 0); err != nil {
closeWriterAndUpdateQuota(writer, conn, name, "", numFiles, truncatedSize, err, operationUpload, startTime) //nolint:errcheck closeWriterAndUpdateQuota(writer, conn, name, "", numFiles, truncatedSize, err, operationUpload, startTime) //nolint:errcheck
return err return err
} }

View File

@@ -1823,7 +1823,7 @@ func TestFilesystemActionErrors(t *testing.T) {
Writer: zip.NewWriter(bytes.NewBuffer(nil)), Writer: zip.NewWriter(bytes.NewBuffer(nil)),
Entries: map[string]bool{}, Entries: map[string]bool{},
} }
err = addZipEntry(wr, conn, "/adir/sub/f.dat", "/adir/sub/sub", 0) err = addZipEntry(wr, conn, "/adir/sub/f.dat", "/adir/sub/sub", nil, 0)
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, getErrorString(err), "is outside base dir") assert.Contains(t, getErrorString(err), "is outside base dir")
} }
@@ -1833,7 +1833,7 @@ func TestFilesystemActionErrors(t *testing.T) {
Writer: zip.NewWriter(bytes.NewBuffer(nil)), Writer: zip.NewWriter(bytes.NewBuffer(nil)),
Entries: map[string]bool{}, Entries: map[string]bool{},
} }
err = addZipEntry(wr, conn, "/p1", "/", 2000) err = addZipEntry(wr, conn, "/p1", "/", nil, 2000)
assert.ErrorIs(t, err, util.ErrRecursionTooDeep) assert.ErrorIs(t, err, util.ErrRecursionTooDeep)
err = dataprovider.DeleteUser(username, "", "", "") err = dataprovider.DeleteUser(username, "", "", "")

View File

@@ -384,7 +384,7 @@ func renderCompressedFiles(w http.ResponseWriter, conn *Connection, baseDir stri
for _, file := range files { for _, file := range files {
fullPath := util.CleanPath(path.Join(baseDir, file)) fullPath := util.CleanPath(path.Join(baseDir, file))
if err := addZipEntry(wr, conn, fullPath, baseDir, 0); err != nil { if err := addZipEntry(wr, conn, fullPath, baseDir, nil, 0); err != nil {
if share != nil { if share != nil {
dataprovider.UpdateShareLastUse(share, -1) //nolint:errcheck dataprovider.UpdateShareLastUse(share, -1) //nolint:errcheck
} }
@@ -400,16 +400,19 @@ func renderCompressedFiles(w http.ResponseWriter, conn *Connection, baseDir stri
} }
} }
func addZipEntry(wr *zip.Writer, conn *Connection, entryPath, baseDir string, recursion int) error { func addZipEntry(wr *zip.Writer, conn *Connection, entryPath, baseDir string, info os.FileInfo, recursion int) error {
if recursion >= util.MaxRecursion { if recursion >= util.MaxRecursion {
conn.Log(logger.LevelDebug, "unable to add zip entry %q, recursion too depth: %d", entryPath, recursion) conn.Log(logger.LevelDebug, "unable to add zip entry %q, recursion too depth: %d", entryPath, recursion)
return util.ErrRecursionTooDeep return util.ErrRecursionTooDeep
} }
recursion++ recursion++
info, err := conn.Stat(entryPath, 1) var err error
if err != nil { if info == nil {
conn.Log(logger.LevelDebug, "unable to add zip entry %q, stat error: %v", entryPath, err) info, err = conn.Stat(entryPath, 1)
return err if err != nil {
conn.Log(logger.LevelDebug, "unable to add zip entry %q, stat error: %v", entryPath, err)
return err
}
} }
entryName, err := getZipEntryName(entryPath, baseDir) entryName, err := getZipEntryName(entryPath, baseDir)
if err != nil { if err != nil {
@@ -441,7 +444,7 @@ func addZipEntry(wr *zip.Writer, conn *Connection, entryPath, baseDir string, re
} }
for _, info := range contents { for _, info := range contents {
fullPath := util.CleanPath(path.Join(entryPath, info.Name())) fullPath := util.CleanPath(path.Join(entryPath, info.Name()))
if err := addZipEntry(wr, conn, fullPath, baseDir, recursion); err != nil { if err := addZipEntry(wr, conn, fullPath, baseDir, info, recursion); err != nil {
return err return err
} }
} }

View File

@@ -2291,14 +2291,14 @@ func TestZipErrors(t *testing.T) {
assert.Contains(t, err.Error(), "write error") assert.Contains(t, err.Error(), "write error")
} }
err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), "/", 0) err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), "/", nil, 0)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "write error") assert.Contains(t, err.Error(), "write error")
} }
err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), "/", 2000) err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), "/", nil, 2000)
assert.ErrorIs(t, err, util.ErrRecursionTooDeep) assert.ErrorIs(t, err, util.ErrRecursionTooDeep)
err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), path.Join("/", filepath.Base(testDir), "dir"), 0) err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), path.Join("/", filepath.Base(testDir), "dir"), nil, 0)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "is outside base dir") assert.Contains(t, err.Error(), "is outside base dir")
} }
@@ -2307,14 +2307,14 @@ func TestZipErrors(t *testing.T) {
err = os.WriteFile(testFilePath, util.GenerateRandomBytes(65535), os.ModePerm) err = os.WriteFile(testFilePath, util.GenerateRandomBytes(65535), os.ModePerm)
assert.NoError(t, err) assert.NoError(t, err)
err = addZipEntry(wr, connection, path.Join("/", filepath.Base(testDir), filepath.Base(testFilePath)), err = addZipEntry(wr, connection, path.Join("/", filepath.Base(testDir), filepath.Base(testFilePath)),
"/"+filepath.Base(testDir), 0) "/"+filepath.Base(testDir), nil, 0)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "write error") assert.Contains(t, err.Error(), "write error")
} }
connection.User.Permissions["/"] = []string{dataprovider.PermListItems} connection.User.Permissions["/"] = []string{dataprovider.PermListItems}
err = addZipEntry(wr, connection, path.Join("/", filepath.Base(testDir), filepath.Base(testFilePath)), err = addZipEntry(wr, connection, path.Join("/", filepath.Base(testDir), filepath.Base(testFilePath)),
"/"+filepath.Base(testDir), 0) "/"+filepath.Base(testDir), nil, 0)
assert.ErrorIs(t, err, os.ErrPermission) assert.ErrorIs(t, err, os.ErrPermission)
// creating a virtual folder to a missing path stat is ok but readdir fails // creating a virtual folder to a missing path stat is ok but readdir fails
@@ -2326,14 +2326,14 @@ func TestZipErrors(t *testing.T) {
}) })
connection.User = user connection.User = user
wr = zip.NewWriter(bytes.NewBuffer(make([]byte, 0))) wr = zip.NewWriter(bytes.NewBuffer(make([]byte, 0)))
err = addZipEntry(wr, connection, user.VirtualFolders[0].VirtualPath, "/", 0) err = addZipEntry(wr, connection, user.VirtualFolders[0].VirtualPath, "/", nil, 0)
assert.Error(t, err) assert.Error(t, err)
user.Filters.FilePatterns = append(user.Filters.FilePatterns, sdk.PatternsFilter{ user.Filters.FilePatterns = append(user.Filters.FilePatterns, sdk.PatternsFilter{
Path: "/", Path: "/",
DeniedPatterns: []string{"*.zip"}, DeniedPatterns: []string{"*.zip"},
}) })
err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), "/", 0) err = addZipEntry(wr, connection, "/"+filepath.Base(testDir), "/", nil, 0)
assert.ErrorIs(t, err, os.ErrPermission) assert.ErrorIs(t, err, os.ErrPermission)
err = os.RemoveAll(testDir) err = os.RemoveAll(testDir)