MM-35945: handle lots of files in ExtractTarGz (#17669)
* MM-35945: handle lots of files in ExtractTarGz `ExtractTarGz` can fail on archives with a largish number or files, complaining about too many open file handles. Clean up as we go to avoid this. Fixes: https://mattermost.atlassian.net/browse/MM-35945 * use closure to allow defer
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
a5a22cdd12
Коммит
4f0f038e0b
@@ -68,12 +68,20 @@ func extractTarGz(gzipStream io.Reader, dst string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode))
|
copyFile := func() error {
|
||||||
if err != nil {
|
outFile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode))
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
if _, err := io.Copy(outFile, tarReader); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
defer outFile.Close()
|
|
||||||
if _, err := io.Copy(outFile, tarReader); err != nil {
|
if err := copyFile(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,24 @@ func TestExtractTarGz(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("huge tar", func(t *testing.T) {
|
||||||
|
files := make([]*tar.Header, 0, 10000)
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
files = append(files, &tar.Header{
|
||||||
|
Name: fmt.Sprintf("%d.txt", i),
|
||||||
|
Typeflag: tar.TypeReg,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
dst, err := ioutil.TempDir("", "TestExtractTarGz")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(dst)
|
||||||
|
|
||||||
|
archive := makeArchive(t, files)
|
||||||
|
err = extractTarGz(&archive, dst)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Files []*tar.Header
|
Files []*tar.Header
|
||||||
ExpectedError bool
|
ExpectedError bool
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user