in internal/utils/file/file.go [77:139]
func UnpackTargzFile(src, dest string) error {
if err := os.MkdirAll(dest, 0755); err != nil {
return fmt.Errorf("failed to create directory %q: %w", dest, err)
}
srcFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("failed to open file %q: %w", src, err)
}
defer srcFile.Close()
gr, err := gzip.NewReader(srcFile)
if err != nil {
return fmt.Errorf("failed to create gzip reader for file %q: %w", src, err)
}
defer gr.Close()
tr := tar.NewReader(gr)
for {
hdr, err := tr.Next()
// No more entries in the archive.
if err == io.EOF {
return nil
}
if err != nil {
return fmt.Errorf("failed to read next tar entry: %w", err)
}
name := filepath.Clean(hdr.Name)
entryPath := filepath.Join(dest, name)
switch hdr.Typeflag {
case tar.TypeDir:
if err := os.MkdirAll(entryPath, os.FileMode(hdr.Mode)); err != nil {
return fmt.Errorf("failed to create directory %q: %w", entryPath, err)
}
case tar.TypeSymlink:
if err := os.Symlink(hdr.Linkname, entryPath); err != nil {
return fmt.Errorf("failed to create symlink %q: %w", entryPath, err)
}
// Treat it as regular file and simply copy it to the destination.
default:
if err := os.MkdirAll(filepath.Dir(entryPath), os.FileMode(hdr.Mode)); err != nil {
return fmt.Errorf("failed to create directory %q: %w", filepath.Dir(entryPath), err)
}
f, err := os.OpenFile(entryPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(hdr.Mode))
if err != nil {
return fmt.Errorf("failed to open file %q: %w", entryPath, err)
}
if _, err = io.Copy(f, tr); err != nil {
f.Close()
// Return original error.
return fmt.Errorf("failed to copy contents to the file %q: %w", entryPath, err)
}
// Close file immediately to avoid too many open files.
if err := f.Close(); err != nil {
return fmt.Errorf("failed to close file %q: %w", entryPath, err)
}
}
}
}