| 702 | } |
| 703 | |
| 704 | unsigned char *use_pack(struct packed_git *p, |
| 705 | struct pack_window **w_cursor, |
| 706 | off_t offset, |
| 707 | unsigned long *left) |
| 708 | { |
| 709 | struct pack_window *win = *w_cursor; |
| 710 | |
| 711 | /* Since packfiles end in a hash of their content and it's |
| 712 | * pointless to ask for an offset into the middle of that |
| 713 | * hash, and the in_window function above wouldn't match |
| 714 | * don't allow an offset too close to the end of the file. |
| 715 | */ |
| 716 | if (!p->pack_size && p->pack_fd == -1 && open_packed_git(p)) |
| 717 | die("packfile %s cannot be accessed", p->pack_name); |
| 718 | if (offset > (p->pack_size - p->repo->hash_algo->rawsz)) |
| 719 | die("offset beyond end of packfile (truncated pack?)"); |
| 720 | if (offset < 0) |
| 721 | die(_("offset before end of packfile (broken .idx?)")); |
| 722 | |
| 723 | if (!win || !in_window(p->repo, win, offset)) { |
| 724 | if (win) |
| 725 | win->inuse_cnt--; |
| 726 | for (win = p->windows; win; win = win->next) { |
| 727 | if (in_window(p->repo, win, offset)) |
| 728 | break; |
| 729 | } |
| 730 | if (!win) { |
| 731 | size_t window_align; |
| 732 | off_t len; |
| 733 | struct repo_settings *settings; |
| 734 | |
| 735 | /* lazy load the settings in case it hasn't been setup */ |
| 736 | prepare_repo_settings(p->repo); |
| 737 | settings = &p->repo->settings; |
| 738 | |
| 739 | window_align = settings->packed_git_window_size / 2; |
| 740 | |
| 741 | if (p->pack_fd == -1 && open_packed_git(p)) |
| 742 | die("packfile %s cannot be accessed", p->pack_name); |
| 743 | |
| 744 | CALLOC_ARRAY(win, 1); |
| 745 | win->offset = (offset / window_align) * window_align; |
| 746 | len = p->pack_size - win->offset; |
| 747 | if (len > settings->packed_git_window_size) |
| 748 | len = settings->packed_git_window_size; |
| 749 | win->len = (size_t)len; |
| 750 | pack_mapped += win->len; |
| 751 | |
| 752 | while (settings->packed_git_limit < pack_mapped && |
| 753 | unuse_one_window(p->repo->objects)) |
| 754 | ; /* nothing */ |
| 755 | win->base = xmmap_gently(NULL, win->len, |
| 756 | PROT_READ, MAP_PRIVATE, |
| 757 | p->pack_fd, win->offset); |
| 758 | if (win->base == MAP_FAILED) |
| 759 | die_errno(_("packfile %s cannot be mapped%s"), |
| 760 | p->pack_name, mmap_os_err()); |
| 761 | if (!win->offset && win->len == p->pack_size |
no test coverage detected