File Coverage

deps/libgit2/src/pack.c
Criterion Covered Total %
statement 411 659 62.3
branch 163 414 39.3
condition n/a
subroutine n/a
pod n/a
total 574 1073 53.4


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
4             * This file is part of libgit2, distributed under the GNU GPL v2 with
5             * a Linking Exception. For full terms see the included COPYING file.
6             */
7              
8             #include "pack.h"
9              
10             #include "delta.h"
11             #include "futils.h"
12             #include "mwindow.h"
13             #include "odb.h"
14             #include "oid.h"
15              
16             /* Option to bypass checking existence of '.keep' files */
17             bool git_disable_pack_keep_file_checks = false;
18              
19             static int packfile_open(struct git_pack_file *p);
20             static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n);
21             static int packfile_unpack_compressed(
22             git_rawobj *obj,
23             struct git_pack_file *p,
24             git_mwindow **w_curs,
25             off64_t *curpos,
26             size_t size,
27             git_object_t type);
28              
29             /* Can find the offset of an object given
30             * a prefix of an identifier.
31             * Throws GIT_EAMBIGUOUSOIDPREFIX if short oid
32             * is ambiguous within the pack.
33             * This method assumes that len is between
34             * GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ.
35             */
36             static int pack_entry_find_offset(
37             off64_t *offset_out,
38             git_oid *found_oid,
39             struct git_pack_file *p,
40             const git_oid *short_oid,
41             size_t len);
42              
43 0           static int packfile_error(const char *message)
44             {
45 0           git_error_set(GIT_ERROR_ODB, "invalid pack file - %s", message);
46 0           return -1;
47             }
48              
49             /********************
50             * Delta base cache
51             ********************/
52              
53 2           static git_pack_cache_entry *new_cache_object(git_rawobj *source)
54             {
55 2           git_pack_cache_entry *e = git__calloc(1, sizeof(git_pack_cache_entry));
56 2 50         if (!e)
57 0           return NULL;
58              
59 2           git_atomic_inc(&e->refcount);
60 2           memcpy(&e->raw, source, sizeof(git_rawobj));
61              
62 2           return e;
63             }
64              
65 2           static void free_cache_object(void *o)
66             {
67 2           git_pack_cache_entry *e = (git_pack_cache_entry *)o;
68              
69 2 50         if (e != NULL) {
70 2 50         assert(e->refcount.val == 0);
71 2           git__free(e->raw.data);
72 2           git__free(e);
73             }
74 2           }
75              
76 8           static void cache_free(git_pack_cache *cache)
77             {
78             git_pack_cache_entry *entry;
79              
80 8 50         if (cache->entries) {
81 10 100         git_offmap_foreach_value(cache->entries, entry, {
82             free_cache_object(entry);
83             });
84              
85 8           git_offmap_free(cache->entries);
86 8           cache->entries = NULL;
87             }
88 8           }
89              
90 9           static int cache_init(git_pack_cache *cache)
91             {
92 9 50         if (git_offmap_new(&cache->entries) < 0)
93 0           return -1;
94              
95 9           cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT;
96              
97 9 50         if (git_mutex_init(&cache->lock)) {
98 0           git_error_set(GIT_ERROR_OS, "failed to initialize pack cache mutex");
99              
100 0           git__free(cache->entries);
101 0           cache->entries = NULL;
102              
103 0           return -1;
104             }
105              
106 9           return 0;
107             }
108              
109 5           static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset)
110             {
111             git_pack_cache_entry *entry;
112              
113 5 50         if (git_mutex_lock(&cache->lock) < 0)
114 0           return NULL;
115              
116 5 50         if ((entry = git_offmap_get(cache->entries, offset)) != NULL) {
117 0           git_atomic_inc(&entry->refcount);
118 0           entry->last_usage = cache->use_ctr++;
119             }
120             git_mutex_unlock(&cache->lock);
121              
122 5           return entry;
123             }
124              
125             /* Run with the cache lock held */
126 0           static void free_lowest_entry(git_pack_cache *cache)
127             {
128             off64_t offset;
129             git_pack_cache_entry *entry;
130              
131 0 0         git_offmap_foreach(cache->entries, offset, entry, {
    0          
    0          
132             if (entry && entry->refcount.val == 0) {
133             cache->memory_used -= entry->raw.len;
134             git_offmap_delete(cache->entries, offset);
135             free_cache_object(entry);
136             }
137             });
138 0           }
139              
140 2           static int cache_add(
141             git_pack_cache_entry **cached_out,
142             git_pack_cache *cache,
143             git_rawobj *base,
144             off64_t offset)
145             {
146             git_pack_cache_entry *entry;
147             int exists;
148              
149 2 50         if (base->len > GIT_PACK_CACHE_SIZE_LIMIT)
150 0           return -1;
151              
152 2           entry = new_cache_object(base);
153 2 50         if (entry) {
154 2 50         if (git_mutex_lock(&cache->lock) < 0) {
155 0           git_error_set(GIT_ERROR_OS, "failed to lock cache");
156 0           git__free(entry);
157 0           return -1;
158             }
159             /* Add it to the cache if nobody else has */
160 2           exists = git_offmap_exists(cache->entries, offset);
161 2 50         if (!exists) {
162 2 50         while (cache->memory_used + base->len > cache->memory_limit)
163 0           free_lowest_entry(cache);
164              
165 2           git_offmap_set(cache->entries, offset, entry);
166 2           cache->memory_used += entry->raw.len;
167              
168 2           *cached_out = entry;
169             }
170             git_mutex_unlock(&cache->lock);
171             /* Somebody beat us to adding it into the cache */
172 2 50         if (exists) {
173 0           git__free(entry);
174 0           return -1;
175             }
176             }
177              
178 2           return 0;
179             }
180              
181             /***********************************************************
182             *
183             * PACK INDEX METHODS
184             *
185             ***********************************************************/
186              
187 8           static void pack_index_free(struct git_pack_file *p)
188             {
189 8 50         if (p->oids) {
190 0           git__free(p->oids);
191 0           p->oids = NULL;
192             }
193 8 100         if (p->index_map.data) {
194 3           git_futils_mmap_free(&p->index_map);
195 3           p->index_map.data = NULL;
196             }
197 8           }
198              
199 3           static int pack_index_check(const char *path, struct git_pack_file *p)
200             {
201             struct git_pack_idx_header *hdr;
202             uint32_t version, nr, i, *index;
203             void *idx_map;
204             size_t idx_size;
205             struct stat st;
206             int error;
207             /* TODO: properly open the file without access time using O_NOATIME */
208 3           git_file fd = git_futils_open_ro(path);
209 3 50         if (fd < 0)
210 0           return fd;
211              
212 3 50         if (p_fstat(fd, &st) < 0) {
213 0           p_close(fd);
214 0           git_error_set(GIT_ERROR_OS, "unable to stat pack index '%s'", path);
215 0           return -1;
216             }
217              
218 6           if (!S_ISREG(st.st_mode) ||
219 6 50         !git__is_sizet(st.st_size) ||
220 3           (idx_size = (size_t)st.st_size) < 4 * 256 + 20 + 20)
221             {
222 0           p_close(fd);
223 0           git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path);
224 0           return -1;
225             }
226              
227 3           error = git_futils_mmap_ro(&p->index_map, fd, 0, idx_size);
228              
229 3           p_close(fd);
230              
231 3 50         if (error < 0)
232 0           return error;
233              
234 3           hdr = idx_map = p->index_map.data;
235              
236 3 50         if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
237 3           version = ntohl(hdr->idx_version);
238              
239 3 50         if (version < 2 || version > 2) {
    50          
240 0           git_futils_mmap_free(&p->index_map);
241 0           return packfile_error("unsupported index version");
242             }
243              
244             } else
245 0           version = 1;
246              
247 3           nr = 0;
248 3           index = idx_map;
249              
250 3 50         if (version > 1)
251 3           index += 2; /* skip index header */
252              
253 771 100         for (i = 0; i < 256; i++) {
254 768           uint32_t n = ntohl(index[i]);
255 768 50         if (n < nr) {
256 0           git_futils_mmap_free(&p->index_map);
257 0           return packfile_error("index is non-monotonic");
258             }
259 768           nr = n;
260             }
261              
262 3 50         if (version == 1) {
263             /*
264             * Total size:
265             * - 256 index entries 4 bytes each
266             * - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
267             * - 20-byte SHA1 of the packfile
268             * - 20-byte SHA1 file checksum
269             */
270 0 0         if (idx_size != 4*256 + nr * 24 + 20 + 20) {
271 0           git_futils_mmap_free(&p->index_map);
272 0           return packfile_error("index is corrupted");
273             }
274 3 50         } else if (version == 2) {
275             /*
276             * Minimum size:
277             * - 8 bytes of header
278             * - 256 index entries 4 bytes each
279             * - 20-byte sha1 entry * nr
280             * - 4-byte crc entry * nr
281             * - 4-byte offset entry * nr
282             * - 20-byte SHA1 of the packfile
283             * - 20-byte SHA1 file checksum
284             * And after the 4-byte offset table might be a
285             * variable sized table containing 8-byte entries
286             * for offsets larger than 2^31.
287             */
288 3           unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
289 3           unsigned long max_size = min_size;
290              
291 3 50         if (nr)
292 3           max_size += (nr - 1)*8;
293              
294 3 50         if (idx_size < min_size || idx_size > max_size) {
    50          
295 0           git_futils_mmap_free(&p->index_map);
296 0           return packfile_error("wrong index size");
297             }
298             }
299              
300 3           p->num_objects = nr;
301 3           p->index_version = version;
302 3           return 0;
303             }
304              
305 3           static int pack_index_open(struct git_pack_file *p)
306             {
307 3           int error = 0;
308             size_t name_len;
309             git_buf idx_name;
310              
311 3 50         if (p->index_version > -1)
312 0           return 0;
313              
314 3           name_len = strlen(p->pack_name);
315 3 50         assert(name_len > strlen(".pack")); /* checked by git_pack_file alloc */
316              
317 3 50         if (git_buf_init(&idx_name, name_len) < 0)
318 0           return -1;
319              
320 3           git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
321 3           git_buf_puts(&idx_name, ".idx");
322 3 50         if (git_buf_oom(&idx_name)) {
323 0           git_buf_dispose(&idx_name);
324 0           return -1;
325             }
326              
327 3 50         if ((error = git_mutex_lock(&p->lock)) < 0) {
328 0           git_buf_dispose(&idx_name);
329 0           return error;
330             }
331              
332 3 50         if (p->index_version == -1)
333 3           error = pack_index_check(idx_name.ptr, p);
334              
335 3           git_buf_dispose(&idx_name);
336              
337             git_mutex_unlock(&p->lock);
338              
339 3           return error;
340             }
341              
342 54           static unsigned char *pack_window_open(
343             struct git_pack_file *p,
344             git_mwindow **w_cursor,
345             off64_t offset,
346             unsigned int *left)
347             {
348 54 50         if (p->mwf.fd == -1 && packfile_open(p) < 0)
    0          
349 0           return NULL;
350              
351             /* Since packfiles end in a hash of their content and it's
352             * pointless to ask for an offset into the middle of that
353             * hash, and the pack_window_contains function above wouldn't match
354             * don't allow an offset too close to the end of the file.
355             *
356             * Don't allow a negative offset, as that means we've wrapped
357             * around.
358             */
359 54 100         if (offset > (p->mwf.size - 20))
360 2           return NULL;
361 52 50         if (offset < 0)
362 0           return NULL;
363              
364 52           return git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
365             }
366              
367             /*
368             * The per-object header is a pretty dense thing, which is
369             * - first byte: low four bits are "size",
370             * then three bits of "type",
371             * with the high bit being "size continues".
372             * - each byte afterwards: low seven bits are size continuation,
373             * with the high bit being "size continues"
374             */
375 53           size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_object_t type)
376             {
377             unsigned char *hdr_base;
378             unsigned char c;
379              
380 53 50         assert(type >= GIT_OBJECT_COMMIT && type <= GIT_OBJECT_REF_DELTA);
    50          
381              
382             /* TODO: add support for chunked objects; see git.git 6c0d19b1 */
383              
384 53           c = (unsigned char)((type << 4) | (size & 15));
385 53           size >>= 4;
386 53           hdr_base = hdr;
387              
388 98 100         while (size) {
389 45           *hdr++ = c | 0x80;
390 45           c = size & 0x7f;
391 45           size >>= 7;
392             }
393 53           *hdr++ = c;
394              
395 53           return (hdr - hdr_base);
396             }
397              
398              
399 52           static int packfile_unpack_header1(
400             unsigned long *usedp,
401             size_t *sizep,
402             git_object_t *type,
403             const unsigned char *buf,
404             unsigned long len)
405             {
406             unsigned shift;
407             unsigned long size, c;
408 52           unsigned long used = 0;
409              
410 52           c = buf[used++];
411 52           *type = (c >> 4) & 7;
412 52           size = c & 15;
413 52           shift = 4;
414 95 100         while (c & 0x80) {
415 43 50         if (len <= used) {
416 0           git_error_set(GIT_ERROR_ODB, "buffer too small");
417 0           return GIT_EBUFS;
418             }
419              
420 43 50         if (bitsizeof(long) <= shift) {
421 0           *usedp = 0;
422 0           git_error_set(GIT_ERROR_ODB, "packfile corrupted");
423 0           return -1;
424             }
425              
426 43           c = buf[used++];
427 43           size += (c & 0x7f) << shift;
428 43           shift += 7;
429             }
430              
431 52           *sizep = (size_t)size;
432 52           *usedp = used;
433 52           return 0;
434             }
435              
436 52           int git_packfile_unpack_header(
437             size_t *size_p,
438             git_object_t *type_p,
439             git_mwindow_file *mwf,
440             git_mwindow **w_curs,
441             off64_t *curpos)
442             {
443             unsigned char *base;
444             unsigned int left;
445             unsigned long used;
446             int ret;
447              
448             /* pack_window_open() assures us we have [base, base + 20) available
449             * as a range that we can look at at. (Its actually the hash
450             * size that is assured.) With our object header encoding
451             * the maximum deflated object size is 2^137, which is just
452             * insane, so we know won't exceed what we have been given.
453             */
454             /* base = pack_window_open(p, w_curs, *curpos, &left); */
455 52           base = git_mwindow_open(mwf, w_curs, *curpos, 20, &left);
456 52 50         if (base == NULL)
457 0           return GIT_EBUFS;
458              
459 52           ret = packfile_unpack_header1(&used, size_p, type_p, base, left);
460 52           git_mwindow_close(w_curs);
461 52 50         if (ret == GIT_EBUFS)
462 0           return ret;
463 52 50         else if (ret < 0)
464 0           return packfile_error("header length is zero");
465              
466 52           *curpos += used;
467 52           return 0;
468             }
469              
470 2           int git_packfile_resolve_header(
471             size_t *size_p,
472             git_object_t *type_p,
473             struct git_pack_file *p,
474             off64_t offset)
475             {
476 2           git_mwindow *w_curs = NULL;
477 2           off64_t curpos = offset;
478             size_t size;
479             git_object_t type;
480             off64_t base_offset;
481             int error;
482              
483 2           error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
484 2 50         if (error < 0)
485 0           return error;
486              
487 2 50         if (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
    50          
488             size_t base_size;
489             git_packfile_stream stream;
490              
491 0           error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, offset);
492 0           git_mwindow_close(&w_curs);
493              
494 0 0         if (error < 0)
495 0           return error;
496              
497 0 0         if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
498 0           return error;
499 0           error = git_delta_read_header_fromstream(&base_size, size_p, &stream);
500 0           git_packfile_stream_dispose(&stream);
501 0 0         if (error < 0)
502 0           return error;
503             } else {
504 2           *size_p = size;
505 2           base_offset = 0;
506             }
507              
508 2 50         while (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
    50          
509 0           curpos = base_offset;
510 0           error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
511 0 0         if (error < 0)
512 0           return error;
513 0 0         if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
    0          
514 0           break;
515              
516 0           error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, base_offset);
517 0           git_mwindow_close(&w_curs);
518              
519 0 0         if (error < 0)
520 0           return error;
521             }
522 2           *type_p = type;
523              
524 2           return error;
525             }
526              
527             #define SMALL_STACK_SIZE 64
528              
529             /**
530             * Generate the chain of dependencies which we need to get to the
531             * object at `off`. `chain` is used a stack, popping gives the right
532             * order to apply deltas on. If an object is found in the pack's base
533             * cache, we stop calculating there.
534             */
535 3           static int pack_dependency_chain(git_dependency_chain *chain_out,
536             git_pack_cache_entry **cached_out, off64_t *cached_off,
537             struct pack_chain_elem *small_stack, size_t *stack_sz,
538             struct git_pack_file *p, off64_t obj_offset)
539             {
540 3           git_dependency_chain chain = GIT_ARRAY_INIT;
541 3           git_mwindow *w_curs = NULL;
542 3           off64_t curpos = obj_offset, base_offset;
543 3           int error = 0, use_heap = 0;
544             size_t size, elem_pos;
545             git_object_t type;
546              
547 3           elem_pos = 0;
548             while (true) {
549             struct pack_chain_elem *elem;
550 5           git_pack_cache_entry *cached = NULL;
551              
552             /* if we have a base cached, we can stop here instead */
553 5 50         if ((cached = cache_get(&p->bases, obj_offset)) != NULL) {
554 0           *cached_out = cached;
555 0           *cached_off = obj_offset;
556 0           break;
557             }
558              
559             /* if we run out of space on the small stack, use the array */
560 5 50         if (elem_pos == SMALL_STACK_SIZE) {
561 0           git_array_init_to_size(chain, elem_pos);
562 0 0         GIT_ERROR_CHECK_ARRAY(chain);
563 0           memcpy(chain.ptr, small_stack, elem_pos * sizeof(struct pack_chain_elem));
564 0           chain.size = elem_pos;
565 0           use_heap = 1;
566             }
567              
568 5           curpos = obj_offset;
569 5 50         if (!use_heap) {
570 5           elem = &small_stack[elem_pos];
571             } else {
572 0 0         elem = git_array_alloc(chain);
    0          
573 0 0         if (!elem) {
574 0           error = -1;
575 0           goto on_error;
576             }
577             }
578              
579 5           elem->base_key = obj_offset;
580              
581 5           error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
582              
583 5 50         if (error < 0)
584 0           goto on_error;
585              
586 5           elem->offset = curpos;
587 5           elem->size = size;
588 5           elem->type = type;
589 5           elem->base_key = obj_offset;
590              
591 5 50         if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
    100          
592 3           break;
593              
594 2           error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, obj_offset);
595 2           git_mwindow_close(&w_curs);
596              
597 2 50         if (error < 0)
598 0           goto on_error;
599              
600             /* we need to pass the pos *after* the delta-base bit */
601 2           elem->offset = curpos;
602              
603             /* go through the loop again, but with the new object */
604 2           obj_offset = base_offset;
605 2           elem_pos++;
606 2           }
607              
608              
609 3           *stack_sz = elem_pos + 1;
610 3           *chain_out = chain;
611 3           return error;
612              
613             on_error:
614 0           git_array_clear(chain);
615 3           return error;
616             }
617              
618 3           int git_packfile_unpack(
619             git_rawobj *obj,
620             struct git_pack_file *p,
621             off64_t *obj_offset)
622             {
623 3           git_mwindow *w_curs = NULL;
624 3           off64_t curpos = *obj_offset;
625 3           int error, free_base = 0;
626 3           git_dependency_chain chain = GIT_ARRAY_INIT;
627 3           struct pack_chain_elem *elem = NULL, *stack;
628 3           git_pack_cache_entry *cached = NULL;
629             struct pack_chain_elem small_stack[SMALL_STACK_SIZE];
630 3           size_t stack_size = 0, elem_pos, alloclen;
631             git_object_t base_type;
632              
633             /*
634             * TODO: optionally check the CRC on the packfile
635             */
636              
637 3           error = pack_dependency_chain(&chain, &cached, obj_offset, small_stack, &stack_size, p, *obj_offset);
638 3 50         if (error < 0)
639 0           return error;
640              
641 3           obj->data = NULL;
642 3           obj->len = 0;
643 3           obj->type = GIT_OBJECT_INVALID;
644              
645             /* let's point to the right stack */
646 3 50         stack = chain.ptr ? chain.ptr : small_stack;
647              
648 3           elem_pos = stack_size;
649 3 50         if (cached) {
650 0           memcpy(obj, &cached->raw, sizeof(git_rawobj));
651 0           base_type = obj->type;
652 0           elem_pos--; /* stack_size includes the base, which isn't actually there */
653             } else {
654 3           elem = &stack[--elem_pos];
655 3           base_type = elem->type;
656             }
657              
658 3           switch (base_type) {
659             case GIT_OBJECT_COMMIT:
660             case GIT_OBJECT_TREE:
661             case GIT_OBJECT_BLOB:
662             case GIT_OBJECT_TAG:
663 3 50         if (!cached) {
664 3           curpos = elem->offset;
665 3           error = packfile_unpack_compressed(obj, p, &w_curs, &curpos, elem->size, elem->type);
666 3           git_mwindow_close(&w_curs);
667 3           base_type = elem->type;
668             }
669 3 50         if (error < 0)
670 0           goto cleanup;
671 3           break;
672             case GIT_OBJECT_OFS_DELTA:
673             case GIT_OBJECT_REF_DELTA:
674 0           error = packfile_error("dependency chain ends in a delta");
675 0           goto cleanup;
676             default:
677 0           error = packfile_error("invalid packfile type in header");
678 0           goto cleanup;
679             }
680              
681             /*
682             * Finding the object we want a cached base element is
683             * problematic, as we need to make sure we don't accidentally
684             * give the caller the cached object, which it would then feel
685             * free to free, so we need to copy the data.
686             */
687 3 50         if (cached && stack_size == 1) {
    0          
688 0           void *data = obj->data;
689              
690 0 0         GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, obj->len, 1);
    0          
691 0           obj->data = git__malloc(alloclen);
692 0 0         GIT_ERROR_CHECK_ALLOC(obj->data);
693              
694 0           memcpy(obj->data, data, obj->len + 1);
695 0           git_atomic_dec(&cached->refcount);
696 0           goto cleanup;
697             }
698              
699             /* we now apply each consecutive delta until we run out */
700 5 100         while (elem_pos > 0 && !error) {
    50          
701             git_rawobj base, delta;
702              
703             /*
704             * We can now try to add the base to the cache, as
705             * long as it's not already the cached one.
706             */
707 2 50         if (!cached)
708 2           free_base = !!cache_add(&cached, &p->bases, obj, elem->base_key);
709              
710 2           elem = &stack[elem_pos - 1];
711 2           curpos = elem->offset;
712 2           error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, elem->size, elem->type);
713 2           git_mwindow_close(&w_curs);
714              
715 2 50         if (error < 0) {
716             /* We have transferred ownership of the data to the cache. */
717 0           obj->data = NULL;
718 0           break;
719             }
720              
721             /* the current object becomes the new base, on which we apply the delta */
722 2           base = *obj;
723 2           obj->data = NULL;
724 2           obj->len = 0;
725 2           obj->type = GIT_OBJECT_INVALID;
726              
727 2           error = git_delta_apply(&obj->data, &obj->len, base.data, base.len, delta.data, delta.len);
728 2           obj->type = base_type;
729              
730             /*
731             * We usually don't want to free the base at this
732             * point, as we put it into the cache in the previous
733             * iteration. free_base lets us know that we got the
734             * base object directly from the packfile, so we can free it.
735             */
736 2           git__free(delta.data);
737 2 50         if (free_base) {
738 0           free_base = 0;
739 0           git__free(base.data);
740             }
741              
742 2 50         if (cached) {
743 2           git_atomic_dec(&cached->refcount);
744 2           cached = NULL;
745             }
746              
747 2 50         if (error < 0)
748 0           break;
749              
750 2           elem_pos--;
751             }
752              
753             cleanup:
754 3 50         if (error < 0) {
755 0           git__free(obj->data);
756 0 0         if (cached)
757 0           git_atomic_dec(&cached->refcount);
758             }
759              
760 3 50         if (elem)
761 3           *obj_offset = curpos;
762              
763 3           git_array_clear(chain);
764 3           return error;
765             }
766              
767 45           int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, off64_t curpos)
768             {
769 45           memset(obj, 0, sizeof(git_packfile_stream));
770 45           obj->curpos = curpos;
771 45           obj->p = p;
772              
773 45 50         if (git_zstream_init(&obj->zstream, GIT_ZSTREAM_INFLATE) < 0) {
774 0           git_error_set(GIT_ERROR_ZLIB, "failed to init packfile stream");
775 0           return -1;
776             }
777              
778 45           return 0;
779             }
780              
781 92           ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len)
782             {
783             unsigned int window_len;
784             unsigned char *in;
785             int error;
786              
787 92 100         if (obj->done)
788 45           return 0;
789              
790 47 100         if ((in = pack_window_open(obj->p, &obj->mw, obj->curpos, &window_len)) == NULL)
791 2           return GIT_EBUFS;
792              
793 45 50         if ((error = git_zstream_set_input(&obj->zstream, in, window_len)) < 0 ||
    50          
794 45           (error = git_zstream_get_output_chunk(buffer, &len, &obj->zstream)) < 0) {
795 0           git_mwindow_close(&obj->mw);
796 0           git_error_set(GIT_ERROR_ZLIB, "error reading from the zlib stream");
797 0           return -1;
798             }
799              
800 45           git_mwindow_close(&obj->mw);
801              
802 45           obj->curpos += window_len - obj->zstream.in_len;
803              
804 45 50         if (git_zstream_eos(&obj->zstream))
805 45           obj->done = 1;
806              
807             /* If we didn't write anything out but we're not done, we need more data */
808 45 50         if (!len && !git_zstream_eos(&obj->zstream))
    0          
809 0           return GIT_EBUFS;
810              
811 92           return len;
812              
813             }
814              
815 45           void git_packfile_stream_dispose(git_packfile_stream *obj)
816             {
817 45           git_zstream_free(&obj->zstream);
818 45           }
819              
820 5           static int packfile_unpack_compressed(
821             git_rawobj *obj,
822             struct git_pack_file *p,
823             git_mwindow **mwindow,
824             off64_t *position,
825             size_t size,
826             git_object_t type)
827             {
828 5           git_zstream zstream = GIT_ZSTREAM_INIT;
829 5           size_t buffer_len, total = 0;
830 5           char *data = NULL;
831             int error;
832              
833 5 50         GIT_ERROR_CHECK_ALLOC_ADD(&buffer_len, size, 1);
    50          
834 5           data = git__calloc(1, buffer_len);
835 5 50         GIT_ERROR_CHECK_ALLOC(data);
836              
837 5 50         if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0) {
838 0           git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack");
839 0           goto out;
840             }
841              
842             do {
843 5           size_t bytes = buffer_len - total;
844             unsigned int window_len;
845             unsigned char *in;
846              
847 5           in = pack_window_open(p, mwindow, *position, &window_len);
848              
849 5 50         if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 ||
    50          
850 5           (error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) {
851 0           git_mwindow_close(mwindow);
852 0           goto out;
853             }
854              
855 5           git_mwindow_close(mwindow);
856              
857 5           *position += window_len - zstream.in_len;
858 5           total += bytes;
859 5 50         } while (total < size);
860              
861 5 50         if (total != size || !git_zstream_eos(&zstream)) {
    50          
862 0           git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
863 0           error = -1;
864 0           goto out;
865             }
866              
867 5           obj->type = type;
868 5           obj->len = size;
869 5           obj->data = data;
870              
871             out:
872 5           git_zstream_free(&zstream);
873 5 50         if (error)
874 0           git__free(data);
875              
876 5           return error;
877             }
878              
879             /*
880             * curpos is where the data starts, delta_obj_offset is the where the
881             * header starts
882             */
883 2           int get_delta_base(
884             off64_t *delta_base_out,
885             struct git_pack_file *p,
886             git_mwindow **w_curs,
887             off64_t *curpos,
888             git_object_t type,
889             off64_t delta_obj_offset)
890             {
891 2           unsigned int left = 0;
892             unsigned char *base_info;
893             off64_t base_offset;
894             git_oid unused;
895              
896 2 50         assert(delta_base_out);
897              
898 2           base_info = pack_window_open(p, w_curs, *curpos, &left);
899             /* Assumption: the only reason this would fail is because the file is too small */
900 2 50         if (base_info == NULL)
901 0           return GIT_EBUFS;
902             /* pack_window_open() assured us we have [base_info, base_info + 20)
903             * as a range that we can look at without walking off the
904             * end of the mapped window. Its actually the hash size
905             * that is assured. An OFS_DELTA longer than the hash size
906             * is stupid, as then a REF_DELTA would be smaller to store.
907             */
908 2 50         if (type == GIT_OBJECT_OFS_DELTA) {
909 0           unsigned used = 0;
910 0           unsigned char c = base_info[used++];
911 0           size_t unsigned_base_offset = c & 127;
912 0 0         while (c & 128) {
913 0 0         if (left <= used)
914 0           return GIT_EBUFS;
915 0           unsigned_base_offset += 1;
916 0 0         if (!unsigned_base_offset || MSB(unsigned_base_offset, 7))
    0          
917 0           return packfile_error("overflow");
918 0           c = base_info[used++];
919 0           unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127);
920             }
921 0 0         if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset)
    0          
922 0           return packfile_error("out of bounds");
923 0           base_offset = delta_obj_offset - unsigned_base_offset;
924 0           *curpos += used;
925 2 50         } else if (type == GIT_OBJECT_REF_DELTA) {
926             /* If we have the cooperative cache, search in it first */
927 2 50         if (p->has_cache) {
928             struct git_pack_entry *entry;
929             git_oid oid;
930              
931 2           git_oid_fromraw(&oid, base_info);
932 2 50         if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
933 2 50         if (entry->offset == 0)
934 0           return packfile_error("delta offset is zero");
935              
936 2           *curpos += 20;
937 2           *delta_base_out = entry->offset;
938 2           return 0;
939             } else {
940             /* If we're building an index, don't try to find the pack
941             * entry; we just haven't seen it yet. We'll make
942             * progress again in the next loop.
943             */
944 2           return GIT_PASSTHROUGH;
945             }
946             }
947              
948             /* The base entry _must_ be in the same pack */
949 0 0         if (pack_entry_find_offset(&base_offset, &unused, p, (git_oid *)base_info, GIT_OID_HEXSZ) < 0)
950 0           return packfile_error("base entry delta is not in the same pack");
951 0           *curpos += 20;
952             } else
953 0           return packfile_error("unknown object type");
954              
955 0 0         if (base_offset == 0)
956 0           return packfile_error("delta offset is zero");
957              
958 0           *delta_base_out = base_offset;
959 2           return 0;
960             }
961              
962             /***********************************************************
963             *
964             * PACKFILE METHODS
965             *
966             ***********************************************************/
967              
968 8           void git_packfile_close(struct git_pack_file *p, bool unlink_packfile)
969             {
970 8 100         if (p->mwf.fd >= 0) {
971 3           git_mwindow_free_all_locked(&p->mwf);
972 3           p_close(p->mwf.fd);
973 3           p->mwf.fd = -1;
974             }
975              
976 8 50         if (unlink_packfile)
977 0           p_unlink(p->pack_name);
978 8           }
979              
980 8           void git_packfile_free(struct git_pack_file *p)
981             {
982 8 50         if (!p)
983 0           return;
984              
985 8           cache_free(&p->bases);
986              
987 8           git_packfile_close(p, false);
988              
989 8           pack_index_free(p);
990              
991 8           git__free(p->bad_object_sha1);
992              
993             git_mutex_free(&p->lock);
994             git_mutex_free(&p->bases.lock);
995 8           git__free(p);
996             }
997              
998 3           static int packfile_open(struct git_pack_file *p)
999             {
1000             struct stat st;
1001             struct git_pack_header hdr;
1002             git_oid sha1;
1003             unsigned char *idx_sha1;
1004              
1005 3 50         if (p->index_version == -1 && pack_index_open(p) < 0)
    0          
1006 0           return git_odb__error_notfound("failed to open packfile", NULL, 0);
1007              
1008             /* if mwf opened by another thread, return now */
1009 3 50         if (git_mutex_lock(&p->lock) < 0)
1010 0           return packfile_error("failed to get lock for open");
1011              
1012 3 50         if (p->mwf.fd >= 0) {
1013             git_mutex_unlock(&p->lock);
1014 0           return 0;
1015             }
1016              
1017             /* TODO: open with noatime */
1018 3           p->mwf.fd = git_futils_open_ro(p->pack_name);
1019 3 50         if (p->mwf.fd < 0)
1020 0           goto cleanup;
1021              
1022 6           if (p_fstat(p->mwf.fd, &st) < 0 ||
1023 3           git_mwindow_file_register(&p->mwf) < 0)
1024             goto cleanup;
1025              
1026             /* If we created the struct before we had the pack we lack size. */
1027 3 50         if (!p->mwf.size) {
1028 0 0         if (!S_ISREG(st.st_mode))
1029 0           goto cleanup;
1030 0           p->mwf.size = (off64_t)st.st_size;
1031 3 50         } else if (p->mwf.size != st.st_size)
1032 0           goto cleanup;
1033              
1034             #if 0
1035             /* We leave these file descriptors open with sliding mmap;
1036             * there is no point keeping them open across exec(), though.
1037             */
1038             fd_flag = fcntl(p->mwf.fd, F_GETFD, 0);
1039             if (fd_flag < 0)
1040             goto cleanup;
1041              
1042             fd_flag |= FD_CLOEXEC;
1043             if (fcntl(p->pack_fd, F_SETFD, fd_flag) == -1)
1044             goto cleanup;
1045             #endif
1046              
1047             /* Verify we recognize this pack file format. */
1048 6           if (p_read(p->mwf.fd, &hdr, sizeof(hdr)) < 0 ||
1049 6 50         hdr.hdr_signature != htonl(PACK_SIGNATURE) ||
1050 3 0         !pack_version_ok(hdr.hdr_version))
1051             goto cleanup;
1052              
1053             /* Verify the pack matches its index. */
1054 6           if (p->num_objects != ntohl(hdr.hdr_entries) ||
1055 6 50         p_lseek(p->mwf.fd, p->mwf.size - GIT_OID_RAWSZ, SEEK_SET) == -1 ||
1056 3           p_read(p->mwf.fd, sha1.id, GIT_OID_RAWSZ) < 0)
1057             goto cleanup;
1058              
1059 3           idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
1060              
1061 3 50         if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
1062 0           goto cleanup;
1063              
1064             git_mutex_unlock(&p->lock);
1065 3           return 0;
1066              
1067             cleanup:
1068 0           git_error_set(GIT_ERROR_OS, "invalid packfile '%s'", p->pack_name);
1069              
1070 0 0         if (p->mwf.fd >= 0)
1071 0           p_close(p->mwf.fd);
1072 0           p->mwf.fd = -1;
1073              
1074             git_mutex_unlock(&p->lock);
1075              
1076 3           return -1;
1077             }
1078              
1079 4           int git_packfile__name(char **out, const char *path)
1080             {
1081             size_t path_len;
1082 4           git_buf buf = GIT_BUF_INIT;
1083              
1084 4           path_len = strlen(path);
1085              
1086 4 50         if (path_len < strlen(".idx"))
1087 0           return git_odb__error_notfound("invalid packfile path", NULL, 0);
1088              
1089 4 50         if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
1090 0           return -1;
1091              
1092 4           *out = git_buf_detach(&buf);
1093 4           return 0;
1094             }
1095              
1096 9           int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1097             {
1098             struct stat st;
1099             struct git_pack_file *p;
1100 9 50         size_t path_len = path ? strlen(path) : 0, alloc_len;
1101              
1102 9           *pack_out = NULL;
1103              
1104 9 50         if (path_len < strlen(".idx"))
1105 0           return git_odb__error_notfound("invalid packfile path", NULL, 0);
1106              
1107 9 50         GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*p), path_len);
    50          
1108 9 50         GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
    50          
1109              
1110 9           p = git__calloc(1, alloc_len);
1111 9 50         GIT_ERROR_CHECK_ALLOC(p);
1112              
1113 9           memcpy(p->pack_name, path, path_len + 1);
1114              
1115             /*
1116             * Make sure a corresponding .pack file exists and that
1117             * the index looks sane.
1118             */
1119 9 100         if (git__suffixcmp(path, ".idx") == 0) {
1120 3           size_t root_len = path_len - strlen(".idx");
1121              
1122 3 50         if (!git_disable_pack_keep_file_checks) {
1123 3           memcpy(p->pack_name + root_len, ".keep", sizeof(".keep"));
1124 3 50         if (git_path_exists(p->pack_name) == true)
1125 0           p->pack_keep = 1;
1126             }
1127              
1128 3           memcpy(p->pack_name + root_len, ".pack", sizeof(".pack"));
1129             }
1130              
1131 9 50         if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
    50          
1132 0           git__free(p);
1133 0           return git_odb__error_notfound("packfile not found", NULL, 0);
1134             }
1135              
1136             /* ok, it looks sane as far as we can check without
1137             * actually mapping the pack file.
1138             */
1139 9           p->mwf.fd = -1;
1140 9           p->mwf.size = st.st_size;
1141 9           p->pack_local = 1;
1142 9           p->mtime = (git_time_t)st.st_mtime;
1143 9           p->index_version = -1;
1144              
1145 9 50         if (git_mutex_init(&p->lock)) {
1146 0           git_error_set(GIT_ERROR_OS, "failed to initialize packfile mutex");
1147 0           git__free(p);
1148 0           return -1;
1149             }
1150              
1151 9 50         if (cache_init(&p->bases) < 0) {
1152 0           git__free(p);
1153 0           return -1;
1154             }
1155              
1156 9           *pack_out = p;
1157              
1158 9           return 0;
1159             }
1160              
1161             /***********************************************************
1162             *
1163             * PACKFILE ENTRY SEARCH INTERNALS
1164             *
1165             ***********************************************************/
1166              
1167 3           static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n)
1168             {
1169 3           const unsigned char *index = p->index_map.data;
1170 3           const unsigned char *end = index + p->index_map.len;
1171 3           index += 4 * 256;
1172 3 50         if (p->index_version == 1) {
1173 0           return ntohl(*((uint32_t *)(index + 24 * n)));
1174             } else {
1175             uint32_t off;
1176 3           index += 8 + p->num_objects * (20 + 4);
1177 3           off = ntohl(*((uint32_t *)(index + 4 * n)));
1178 3 50         if (!(off & 0x80000000))
1179 3           return off;
1180 0           index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
1181              
1182             /* Make sure we're not being sent out of bounds */
1183 0 0         if (index >= end - 8)
1184 0           return -1;
1185              
1186 0           return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
1187 0           ntohl(*((uint32_t *)(index + 4)));
1188             }
1189             }
1190              
1191 0           static int git__memcmp4(const void *a, const void *b) {
1192 0           return memcmp(a, b, 4);
1193             }
1194              
1195 0           int git_pack_foreach_entry(
1196             struct git_pack_file *p,
1197             git_odb_foreach_cb cb,
1198             void *data)
1199             {
1200 0           const unsigned char *index = p->index_map.data, *current;
1201             uint32_t i;
1202 0           int error = 0;
1203              
1204 0 0         if (index == NULL) {
1205 0 0         if ((error = pack_index_open(p)) < 0)
1206 0           return error;
1207              
1208 0 0         assert(p->index_map.data);
1209              
1210 0           index = p->index_map.data;
1211             }
1212              
1213 0 0         if (p->index_version > 1) {
1214 0           index += 8;
1215             }
1216              
1217 0           index += 4 * 256;
1218              
1219 0 0         if (p->oids == NULL) {
1220             git_vector offsets, oids;
1221              
1222 0 0         if ((error = git_vector_init(&oids, p->num_objects, NULL)))
1223 0           return error;
1224              
1225 0 0         if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4)))
1226 0           return error;
1227              
1228 0 0         if (p->index_version > 1) {
1229 0           const unsigned char *off = index + 24 * p->num_objects;
1230 0 0         for (i = 0; i < p->num_objects; i++)
1231 0           git_vector_insert(&offsets, (void*)&off[4 * i]);
1232 0           git_vector_sort(&offsets);
1233 0 0         git_vector_foreach(&offsets, i, current)
1234 0           git_vector_insert(&oids, (void*)&index[5 * (current - off)]);
1235             } else {
1236 0 0         for (i = 0; i < p->num_objects; i++)
1237 0           git_vector_insert(&offsets, (void*)&index[24 * i]);
1238 0           git_vector_sort(&offsets);
1239 0 0         git_vector_foreach(&offsets, i, current)
1240 0           git_vector_insert(&oids, (void*)¤t[4]);
1241             }
1242              
1243 0           git_vector_free(&offsets);
1244 0           p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
1245             }
1246              
1247 0 0         for (i = 0; i < p->num_objects; i++)
1248 0 0         if ((error = cb(p->oids[i], data)) != 0)
1249 0           return git_error_set_after_callback(error);
1250              
1251 0           return error;
1252             }
1253              
1254 3           static int sha1_position(const void *table, size_t stride, unsigned lo,
1255             unsigned hi, const unsigned char *key)
1256             {
1257 3           const unsigned char *base = table;
1258              
1259 3 50         while (lo < hi) {
1260 3           unsigned mi = (lo + hi) / 2;
1261 3           int cmp = git_oid__hashcmp(base + mi * stride, key);
1262              
1263 3 50         if (!cmp)
1264 3           return mi;
1265              
1266 0 0         if (cmp > 0)
1267 0           hi = mi;
1268             else
1269 0           lo = mi+1;
1270             }
1271              
1272 0           return -((int)lo)-1;
1273             }
1274              
1275 3           static int pack_entry_find_offset(
1276             off64_t *offset_out,
1277             git_oid *found_oid,
1278             struct git_pack_file *p,
1279             const git_oid *short_oid,
1280             size_t len)
1281             {
1282             const uint32_t *level1_ofs;
1283             const unsigned char *index;
1284             unsigned hi, lo, stride;
1285 3           int pos, found = 0;
1286             off64_t offset;
1287 3           const unsigned char *current = 0;
1288              
1289 3           *offset_out = 0;
1290              
1291 3 50         if (p->index_version == -1) {
1292             int error;
1293              
1294 3 50         if ((error = pack_index_open(p)) < 0)
1295 0           return error;
1296 3 50         assert(p->index_map.data);
1297             }
1298              
1299 3           index = p->index_map.data;
1300 3           level1_ofs = p->index_map.data;
1301              
1302 3 50         if (p->index_version > 1) {
1303 3           level1_ofs += 2;
1304 3           index += 8;
1305             }
1306              
1307 3           index += 4 * 256;
1308 3           hi = ntohl(level1_ofs[(int)short_oid->id[0]]);
1309 3 50         lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(level1_ofs[(int)short_oid->id[0] - 1]));
1310              
1311 3 50         if (p->index_version > 1) {
1312 3           stride = 20;
1313             } else {
1314 0           stride = 24;
1315 0           index += 4;
1316             }
1317              
1318             #ifdef INDEX_DEBUG_LOOKUP
1319             printf("%02x%02x%02x... lo %u hi %u nr %d\n",
1320             short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects);
1321             #endif
1322              
1323 3           pos = sha1_position(index, stride, lo, hi, short_oid->id);
1324              
1325 3 50         if (pos >= 0) {
1326             /* An object matching exactly the oid was found */
1327 3           found = 1;
1328 3           current = index + pos * stride;
1329             } else {
1330             /* No object was found */
1331             /* pos refers to the object with the "closest" oid to short_oid */
1332 0           pos = - 1 - pos;
1333 0 0         if (pos < (int)p->num_objects) {
1334 0           current = index + pos * stride;
1335              
1336 0 0         if (!git_oid_ncmp(short_oid, (const git_oid *)current, len))
1337 0           found = 1;
1338             }
1339             }
1340              
1341 3 50         if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)p->num_objects) {
    50          
    0          
1342             /* Check for ambiguousity */
1343 0           const unsigned char *next = current + stride;
1344              
1345 0 0         if (!git_oid_ncmp(short_oid, (const git_oid *)next, len)) {
1346 0           found = 2;
1347             }
1348             }
1349              
1350 3 50         if (!found)
1351 0           return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
1352 3 50         if (found > 1)
1353 0           return git_odb__error_ambiguous("found multiple offsets for pack entry");
1354              
1355 3 50         if ((offset = nth_packed_object_offset(p, pos)) < 0) {
1356 0           git_error_set(GIT_ERROR_ODB, "packfile index is corrupt");
1357 0           return -1;
1358             }
1359              
1360 3           *offset_out = offset;
1361 3           git_oid_fromraw(found_oid, current);
1362              
1363             #ifdef INDEX_DEBUG_LOOKUP
1364             {
1365             unsigned char hex_sha1[GIT_OID_HEXSZ + 1];
1366             git_oid_fmt(hex_sha1, found_oid);
1367             hex_sha1[GIT_OID_HEXSZ] = '\0';
1368             printf("found lo=%d %s\n", lo, hex_sha1);
1369             }
1370             #endif
1371              
1372 3           return 0;
1373             }
1374              
1375 3           int git_pack_entry_find(
1376             struct git_pack_entry *e,
1377             struct git_pack_file *p,
1378             const git_oid *short_oid,
1379             size_t len)
1380             {
1381             off64_t offset;
1382             git_oid found_oid;
1383             int error;
1384              
1385 3 50         assert(p);
1386              
1387 3 50         if (len == GIT_OID_HEXSZ && p->num_bad_objects) {
    50          
1388             unsigned i;
1389 0 0         for (i = 0; i < p->num_bad_objects; i++)
1390 0 0         if (git_oid__cmp(short_oid, &p->bad_object_sha1[i]) == 0)
1391 0           return packfile_error("bad object found in packfile");
1392             }
1393              
1394 3           error = pack_entry_find_offset(&offset, &found_oid, p, short_oid, len);
1395 3 50         if (error < 0)
1396 0           return error;
1397              
1398             /* we found a unique entry in the index;
1399             * make sure the packfile backing the index
1400             * still exists on disk */
1401 3 50         if (p->mwf.fd == -1 && (error = packfile_open(p)) < 0)
    50          
1402 0           return error;
1403              
1404 3           e->offset = offset;
1405 3           e->p = p;
1406              
1407 3           git_oid_cpy(&e->sha1, &found_oid);
1408 3           return 0;
1409             }