extractTarGz reads a TAR.GZ archive from r and extracts its contents into destDir. It returns an error if the archive cannot be read, or if any file or directory within the archive cannot be created or written.
(r io.Reader, destDir string)
| 405 | // It returns an error if the archive cannot be read, |
| 406 | // or if any file or directory within the archive cannot be created or written. |
| 407 | func extractTarGz(r io.Reader, destDir string) error { |
| 408 | gzr, err := gzip.NewReader(r) |
| 409 | if err != nil { |
| 410 | return fmt.Errorf("failed to create gzip reader: %w", err) |
| 411 | } |
| 412 | defer gzr.Close() |
| 413 | |
| 414 | absDestDirPath, err := safepaths.ParseAbsolute(destDir) |
| 415 | if err != nil { |
| 416 | return err |
| 417 | } |
| 418 | |
| 419 | tr := tar.NewReader(gzr) |
| 420 | for { |
| 421 | header, err := tr.Next() |
| 422 | if err == io.EOF { |
| 423 | break |
| 424 | } |
| 425 | if err != nil { |
| 426 | return fmt.Errorf("failed to read tar: %w", err) |
| 427 | } |
| 428 | |
| 429 | absFilePath, err := absDestDirPath.Join(header.Name) |
| 430 | if err != nil { |
| 431 | return err |
| 432 | } |
| 433 | target := absFilePath.String() |
| 434 | |
| 435 | if header.Typeflag == tar.TypeReg { |
| 436 | if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { |
| 437 | return fmt.Errorf("failed to create parent directory: %w", err) |
| 438 | } |
| 439 | if err := extractFile(target, os.FileMode(header.Mode)&0777, tr); err != nil { |
| 440 | return err |
| 441 | } |
| 442 | } |
| 443 | } |
| 444 | return nil |
| 445 | } |
| 446 | |
| 447 | // extractFile creates a file at target with the given mode and copies content from r. |
| 448 | func extractFile(target string, mode os.FileMode, r io.Reader) (err error) { |