(packagePath, targetDir string)
| 429 | } |
| 430 | |
| 431 | func unzipLocalSkillPackage(packagePath, targetDir string) error { |
| 432 | reader, err := zip.OpenReader(packagePath) |
| 433 | if err != nil { |
| 434 | return err |
| 435 | } |
| 436 | defer reader.Close() |
| 437 | root, err := filepath.Abs(targetDir) |
| 438 | if err != nil { |
| 439 | return err |
| 440 | } |
| 441 | for _, file := range reader.File { |
| 442 | name, err := safeLocalSkillZipEntryName(file.Name) |
| 443 | if err != nil { |
| 444 | return err |
| 445 | } |
| 446 | targetPath := filepath.Join(root, name) |
| 447 | rel, err := filepath.Rel(root, targetPath) |
| 448 | if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { |
| 449 | return fmt.Errorf("invalid zip entry: %s", file.Name) |
| 450 | } |
| 451 | if file.FileInfo().IsDir() { |
| 452 | if err := os.MkdirAll(targetPath, file.Mode()); err != nil { |
| 453 | return err |
| 454 | } |
| 455 | continue |
| 456 | } |
| 457 | if file.Mode()&os.ModeSymlink != 0 { |
| 458 | return fmt.Errorf("unsupported zip entry: %s", file.Name) |
| 459 | } |
| 460 | if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil { |
| 461 | return err |
| 462 | } |
| 463 | rc, err := file.Open() |
| 464 | if err != nil { |
| 465 | return err |
| 466 | } |
| 467 | dst, err := os.OpenFile(targetPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, file.Mode()) |
| 468 | if err != nil { |
| 469 | _ = rc.Close() |
| 470 | return err |
| 471 | } |
| 472 | _, copyErr := io.Copy(dst, rc) |
| 473 | closeErr := dst.Close() |
| 474 | _ = rc.Close() |
| 475 | if copyErr != nil { |
| 476 | return copyErr |
| 477 | } |
| 478 | if closeErr != nil { |
| 479 | return closeErr |
| 480 | } |
| 481 | } |
| 482 | return nil |
| 483 | } |
| 484 | |
| 485 | func untarLocalSkillPackage(packagePath, targetDir string, gzipped bool) error { |
| 486 | src, err := os.Open(packagePath) |
no test coverage detected