Skip to content

Commit 3e6fb61

Browse files
committed
untar: call defer file.Close() after each file
deferred calls are only called when the current function ends, which means untar() is currently holding all files open until it has finished processing the whole archive. By introducing `untarFile()` and `unzipFile()` helpers, we can ensure each file is closed as soon as it's fully uncompressed.
1 parent 4dda6fa commit 3e6fb61

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

pkg/extract/extract.go

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -99,25 +99,30 @@ func untar(reader io.Reader, targetDir string, fileFilter func(string) bool) ([]
9999
// if it's a file create it
100100
case tar.TypeReg, tar.TypeGNUSparse:
101101
// tar.Next() will externally only iterate files, so we might have to create intermediate directories here
102-
if err = os.MkdirAll(filepath.Dir(path), 0750); err != nil {
103-
return nil, err
104-
}
105-
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, header.FileInfo().Mode())
106-
if err != nil {
107-
return nil, err
108-
}
109-
defer file.Close()
110-
111-
// copy over contents
112-
// #nosec G110
113-
if _, err := io.Copy(file, tarReader); err != nil {
102+
if err := untarFile(tarReader, header, path); err != nil {
114103
return nil, err
115104
}
116105
extractedFiles = append(extractedFiles, path)
117106
}
118107
}
119108
}
120109

110+
func untarFile(tarReader *tar.Reader, header *tar.Header, path string) error {
111+
if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
112+
return err
113+
}
114+
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, header.FileInfo().Mode())
115+
if err != nil {
116+
return err
117+
}
118+
defer file.Close()
119+
120+
// copy over contents
121+
// #nosec G110
122+
_, err = io.Copy(file, tarReader)
123+
return err
124+
}
125+
121126
func Unzip(archive, target string) ([]string, error) {
122127
return unzip(archive, target, nil)
123128
}
@@ -153,29 +158,34 @@ func unzip(archive, target string, fileFilter func(string) bool) ([]string, erro
153158
continue
154159
}
155160

156-
// with a file filter, we may have skipped the intermediate directories, make sure they exist
157-
if err = os.MkdirAll(filepath.Dir(path), 0750); err != nil {
161+
if err := unzipFile(path, file); err != nil {
158162
return nil, err
159163
}
164+
extractedFiles = append(extractedFiles, path)
165+
}
160166

161-
fileReader, err := file.Open()
162-
if err != nil {
163-
return nil, err
164-
}
165-
defer fileReader.Close()
167+
return extractedFiles, nil
168+
}
166169

167-
targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
168-
if err != nil {
169-
return nil, err
170-
}
171-
defer targetFile.Close()
170+
func unzipFile(path string, file *zip.File) error {
171+
// with a file filter, we may have skipped the intermediate directories, make sure they exist
172+
if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
173+
return err
174+
}
172175

173-
// #nosec G110
174-
if _, err := io.Copy(targetFile, fileReader); err != nil {
175-
return nil, err
176-
}
177-
extractedFiles = append(extractedFiles, path)
176+
fileReader, err := file.Open()
177+
if err != nil {
178+
return err
178179
}
180+
defer fileReader.Close()
179181

180-
return extractedFiles, nil
182+
targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
183+
if err != nil {
184+
return err
185+
}
186+
defer targetFile.Close()
187+
188+
// #nosec G110
189+
_, err = io.Copy(targetFile, fileReader)
190+
return err
181191
}

0 commit comments

Comments
 (0)