@@ -18,6 +18,7 @@ import (
1818 "github.com/containers/podman/v5/utils"
1919 "github.com/containers/storage/pkg/archive"
2020 crcOs "github.com/crc-org/crc/v2/pkg/os"
21+ "github.com/klauspost/compress/zstd"
2122 "github.com/sirupsen/logrus"
2223 "github.com/ulikunitz/xz"
2324)
@@ -59,12 +60,22 @@ func Decompress(localPath *define.VMFile, uncompressedPath string) error {
5960 if err != nil {
6061 return err
6162 }
63+ // darwin really struggles with sparse files. being diligent here
6264 fmt .Printf ("Copying uncompressed file %q to %q/n" , localPath .GetPath (), dstFile .Name ())
65+
66+ // Keeping CRC implementation for now, but ideally this could be pruned and
67+ // sparsewriter could be used. in that case, this area needs rework or
68+ // sparsewriter be made to honor the *file interface
6369 _ , err = crcOs .CopySparse (uncompressedFileWriter , dstFile )
6470 return err
6571 case archive .Gzip :
6672 if runtime .GOOS == "darwin" {
67- return decompressGzWithSparse (prefix , localPath , uncompressedPath )
73+ return decompressGzWithSparse (prefix , localPath , uncompressedFileWriter )
74+ }
75+ fallthrough
76+ case archive .Zstd :
77+ if runtime .GOOS == "darwin" {
78+ return decompressZstdWithSparse (prefix , localPath , uncompressedFileWriter )
6879 }
6980 fallthrough
7081 default :
@@ -225,22 +236,31 @@ func decompressZip(prefix string, src string, output io.WriteCloser) error {
225236 return err
226237}
227238
228- func decompressGzWithSparse (prefix string , compressedPath * define.VMFile , uncompressedPath string ) error {
229- stat , err := os .Stat (compressedPath .GetPath ())
230- if err != nil {
231- return err
232- }
233-
234- dstFile , err := os .OpenFile (uncompressedPath , os .O_CREATE | os .O_TRUNC | os .O_WRONLY , stat .Mode ())
235- if err != nil {
236- return err
237- }
239+ func decompressWithSparse (prefix string , compressedReader io.Reader , uncompressedFile * os.File ) error {
240+ dstFile := NewSparseWriter (uncompressedFile )
238241 defer func () {
239242 if err := dstFile .Close (); err != nil {
240- logrus .Errorf ("unable to close uncompressed file %s: %q" , uncompressedPath , err )
243+ logrus .Errorf ("unable to close uncompressed file %s: %q" , uncompressedFile . Name () , err )
241244 }
242245 }()
243246
247+ // TODO remove the following line when progress bars work
248+ _ = prefix
249+ // p, bar := utils.ProgressBar(prefix, stat.Size(), prefix+": done")
250+ // proxyReader := bar.ProxyReader(f)
251+ // defer func() {
252+ // if err := proxyReader.Close(); err != nil {
253+ // logrus.Error(err)
254+ // }
255+ // }()
256+
257+ // p.Wait()
258+ _ , err := io .Copy (dstFile , compressedReader )
259+ return err
260+ }
261+
262+ func decompressGzWithSparse (prefix string , compressedPath * define.VMFile , uncompressedFileWriter * os.File ) error {
263+ logrus .Debugf ("decompressing %s" , compressedPath .GetPath ())
244264 f , err := os .Open (compressedPath .GetPath ())
245265 if err != nil {
246266 return err
@@ -260,20 +280,34 @@ func decompressGzWithSparse(prefix string, compressedPath *define.VMFile, uncomp
260280 logrus .Errorf ("unable to close gzreader: %q" , err )
261281 }
262282 }()
283+ // This way we get something to look at in debug mode
284+ defer func () {
285+ logrus .Debug ("decompression complete" )
286+ }()
287+ return decompressWithSparse (prefix , gzReader , uncompressedFileWriter )
288+ }
263289
264- // TODO remove the following line when progress bars work
265- _ = prefix
266- // p, bar := utils.ProgressBar(prefix, stat.Size(), prefix+": done")
267- // proxyReader := bar.ProxyReader(f)
268- // defer func() {
269- // if err := proxyReader.Close(); err != nil {
270- // logrus.Error(err)
271- // }
272- // }()
273-
290+ func decompressZstdWithSparse (prefix string , compressedPath * define.VMFile , uncompressedFileWriter * os.File ) error {
274291 logrus .Debugf ("decompressing %s" , compressedPath .GetPath ())
275- _ , err = crcOs .CopySparse (dstFile , gzReader )
276- logrus .Debug ("decompression complete" )
277- // p.Wait()
278- return err
292+ f , err := os .Open (compressedPath .GetPath ())
293+ if err != nil {
294+ return err
295+ }
296+ defer func () {
297+ if err := f .Close (); err != nil {
298+ logrus .Errorf ("unable to close on compressed file %s: %q" , compressedPath .GetPath (), err )
299+ }
300+ }()
301+
302+ zstdReader , err := zstd .NewReader (f )
303+ if err != nil {
304+ return err
305+ }
306+ defer zstdReader .Close ()
307+
308+ // This way we get something to look at in debug mode
309+ defer func () {
310+ logrus .Debug ("decompression complete" )
311+ }()
312+ return decompressWithSparse (prefix , zstdReader , uncompressedFileWriter )
279313}
0 commit comments