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)
| 411 | // It returns an error if the archive cannot be read, |
| 412 | // or if any file or directory within the archive cannot be created or written. |
| 413 | func extractTarGz(r io.Reader, destDir string) error { |
| 414 | gzr, err := gzip.NewReader(r) |
| 415 | if err != nil { |
| 416 | return fmt.Errorf("failed to create gzip reader: %w", err) |
| 417 | } |
| 418 | defer gzr.Close() |
| 419 | |
| 420 | root, err := safepaths.OpenRoot(destDir) |
| 421 | if err != nil { |
| 422 | return err |
| 423 | } |
| 424 | defer root.Close() |
| 425 | |
| 426 | tr := tar.NewReader(gzr) |
| 427 | for { |
| 428 | header, err := tr.Next() |
| 429 | if err == io.EOF { |
| 430 | break |
| 431 | } |
| 432 | if err != nil { |
| 433 | return fmt.Errorf("failed to read tar: %w", err) |
| 434 | } |
| 435 | if err := safepaths.ValidateChild(header.Name); err != nil { |
| 436 | return err |
| 437 | } |
| 438 | |
| 439 | if header.Typeflag == tar.TypeReg { |
| 440 | if err := root.CopyFile(header.Name, tr, os.FileMode(header.Mode)&0o777, 0o755, true); err != nil { |
| 441 | return fmt.Errorf("failed to extract file: %w", err) |
| 442 | } |
| 443 | } |
| 444 | } |
| 445 | return nil |
| 446 | } |
| 447 | |
| 448 | func removeCopilot(installDir string) error { |
| 449 | if _, err := os.Stat(installDir); os.IsNotExist(err) { |