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
Этот коммит содержится в:
Jesse Hallam
2021-05-25 22:00:57 -03:00
коммит произвёл GitHub
родитель a5a22cdd12
Коммит 4f0f038e0b
2 изменённых файлов: 31 добавлений и 5 удалений

Просмотреть файл

@@ -68,12 +68,20 @@ func extractTarGz(gzipStream io.Reader, dst string) error {
return err
}
outFile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode))
if err != nil {
return err
copyFile := func() error {
outFile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode))
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
}
}

Просмотреть файл

@@ -72,6 +72,24 @@ func TestExtractTarGz(t *testing.T) {
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 {
Files []*tar.Header
ExpectedError bool