* Do not call this directly as this leaks p->pack_fd on error return; * call open_packed_git() instead. */
| 611 | * call open_packed_git() instead. |
| 612 | */ |
| 613 | static int open_packed_git_1(struct packed_git *p) |
| 614 | { |
| 615 | struct stat st; |
| 616 | struct pack_header hdr; |
| 617 | unsigned char hash[GIT_MAX_RAWSZ]; |
| 618 | unsigned char *idx_hash; |
| 619 | ssize_t read_result; |
| 620 | const unsigned hashsz = p->repo->hash_algo->rawsz; |
| 621 | |
| 622 | if (open_pack_index(p)) |
| 623 | return error("packfile %s index unavailable", p->pack_name); |
| 624 | |
| 625 | if (!pack_max_fds) { |
| 626 | unsigned int max_fds = get_max_fd_limit(); |
| 627 | |
| 628 | /* Save 3 for stdin/stdout/stderr, 22 for work */ |
| 629 | if (25 < max_fds) |
| 630 | pack_max_fds = max_fds - 25; |
| 631 | else |
| 632 | pack_max_fds = 1; |
| 633 | } |
| 634 | |
| 635 | while (pack_max_fds <= pack_open_fds && close_one_pack(p->repo)) |
| 636 | ; /* nothing */ |
| 637 | |
| 638 | p->pack_fd = git_open(p->pack_name); |
| 639 | if (p->pack_fd < 0 || fstat(p->pack_fd, &st)) |
| 640 | return -1; |
| 641 | pack_open_fds++; |
| 642 | |
| 643 | /* If we created the struct before we had the pack we lack size. */ |
| 644 | if (!p->pack_size) { |
| 645 | if (!S_ISREG(st.st_mode)) |
| 646 | return error("packfile %s not a regular file", p->pack_name); |
| 647 | p->pack_size = st.st_size; |
| 648 | } else if (p->pack_size != st.st_size) |
| 649 | return error("packfile %s size changed", p->pack_name); |
| 650 | |
| 651 | /* Verify we recognize this pack file format. */ |
| 652 | read_result = read_in_full(p->pack_fd, &hdr, sizeof(hdr)); |
| 653 | if (read_result < 0) |
| 654 | return error_errno("error reading from %s", p->pack_name); |
| 655 | if (read_result != sizeof(hdr)) |
| 656 | return error("file %s is far too short to be a packfile", p->pack_name); |
| 657 | if (hdr.hdr_signature != htonl(PACK_SIGNATURE)) |
| 658 | return error("file %s is not a GIT packfile", p->pack_name); |
| 659 | if (!pack_version_ok(hdr.hdr_version)) |
| 660 | return error("packfile %s is version %"PRIu32" and not" |
| 661 | " supported (try upgrading GIT to a newer version)", |
| 662 | p->pack_name, ntohl(hdr.hdr_version)); |
| 663 | |
| 664 | /* Verify the pack matches its index. */ |
| 665 | if (p->num_objects != ntohl(hdr.hdr_entries)) |
| 666 | return error("packfile %s claims to have %"PRIu32" objects" |
| 667 | " while index indicates %"PRIu32" objects", |
| 668 | p->pack_name, ntohl(hdr.hdr_entries), |
| 669 | p->num_objects); |
| 670 | read_result = pread_in_full(p->pack_fd, hash, hashsz, |
no test coverage detected