Line Flow Count Block(s) Source
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 ##### 2 static int packfile_error(const char *message)
44 - {
45 ##### 2 git_error_set(GIT_ERROR_ODB, "invalid pack file - %s", message);
46 ##### 3 return -1;
47 - }
48 -
49 - /********************
50 - * Delta base cache
51 - ********************/
52 -
53 5265 2 static git_pack_cache_entry *new_cache_object(git_rawobj *source)
54 - {
55 5265 2 git_pack_cache_entry *e = git__calloc(1, sizeof(git_pack_cache_entry));
56 5265 3 if (!e)
57 ##### 4 return NULL;
58 -
59 5265 5 git_atomic_inc(&e->refcount);
60 5265 6 memcpy(&e->raw, source, sizeof(git_rawobj));
61 -
62 5265 6 return e;
63 - }
64 -
65 5265 2 static void free_cache_object(void *o)
66 - {
67 5265 2 git_pack_cache_entry *e = (git_pack_cache_entry *)o;
68 -
69 5265 2 if (e != NULL) {
70 5265 3,4 assert(e->refcount.val == 0);
71 5265 5 git__free(e->raw.data);
72 5265 6 git__free(e);
73 - }
74 5265 7 }
75 -
76 2601 2 static void cache_free(git_pack_cache *cache)
77 - {
78 - git_pack_cache_entry *entry;
79 -
80 2601 2 if (cache->entries) {
81 7866 3-6 git_offmap_foreach_value(cache->entries, entry, {
82 - free_cache_object(entry);
83 - });
84 -
85 2601 7 git_offmap_free(cache->entries);
86 2601 8 cache->entries = NULL;
87 - }
88 2601 9 }
89 -
90 2601 2 static int cache_init(git_pack_cache *cache)
91 - {
92 2601 2,3 if (git_offmap_new(&cache->entries) < 0)
93 ##### 4 return -1;
94 -
95 2601 5 cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT;
96 -
97 2601 5,6 if (git_mutex_init(&cache->lock)) {
98 ##### 7 git_error_set(GIT_ERROR_OS, "failed to initialize pack cache mutex");
99 -
100 ##### 8 git__free(cache->entries);
101 ##### 9 cache->entries = NULL;
102 -
103 ##### 9 return -1;
104 - }
105 -
106 2601 10 return 0;
107 - }
108 -
109 44966 2 static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset)
110 - {
111 - git_pack_cache_entry *entry;
112 -
113 44969 2,3 if (git_mutex_lock(&cache->lock) < 0)
114 ##### 4 return NULL;
115 -
116 44969 5,6 if ((entry = git_offmap_get(cache->entries, offset)) != NULL) {
117 10277 7 git_atomic_inc(&entry->refcount);
118 10277 8 entry->last_usage = cache->use_ctr++;
119 - }
120 44969 9 git_mutex_unlock(&cache->lock);
121 -
122 44969 10 return entry;
123 - }
124 -
125 - /* Run with the cache lock held */
126 ##### 2 static void free_lowest_entry(git_pack_cache *cache)
127 - {
128 - off64_t offset;
129 - git_pack_cache_entry *entry;
130 -
131 ##### 2-8 git_offmap_foreach(cache->entries, offset, entry, {
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 ##### 9 }
139 -
140 5265 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 5265 2 if (base->len > GIT_PACK_CACHE_SIZE_LIMIT)
150 ##### 3 return -1;
151 -
152 5265 4 entry = new_cache_object(base);
153 5265 5 if (entry) {
154 5265 6,7 if (git_mutex_lock(&cache->lock) < 0) {
155 ##### 8 git_error_set(GIT_ERROR_OS, "failed to lock cache");
156 ##### 9 git__free(entry);
157 ##### 10 return -1;
158 - }
159 - /* Add it to the cache if nobody else has */
160 5265 11 exists = git_offmap_exists(cache->entries, offset);
161 5265 12 if (!exists) {
162 5265 13,15 while (cache->memory_used + base->len > cache->memory_limit)
163 ##### 14 free_lowest_entry(cache);
164 -
165 5265 16 git_offmap_set(cache->entries, offset, entry);
166 5265 17 cache->memory_used += entry->raw.len;
167 -
168 5265 17 *cached_out = entry;
169 - }
170 5265 18 git_mutex_unlock(&cache->lock);
171 - /* Somebody beat us to adding it into the cache */
172 5265 19 if (exists) {
173 ##### 20 git__free(entry);
174 ##### 21 return -1;
175 - }
176 - }
177 -
178 5265 22 return 0;
179 - }
180 -
181 - /***********************************************************
182 - *
183 - * PACK INDEX METHODS
184 - *
185 - ***********************************************************/
186 -
187 2601 2 static void pack_index_free(struct git_pack_file *p)
188 - {
189 2601 2 if (p->oids) {
190 10 3 git__free(p->oids);
191 10 4 p->oids = NULL;
192 - }
193 2601 5 if (p->index_map.data) {
194 2364 6 git_futils_mmap_free(&p->index_map);
195 2364 7 p->index_map.data = NULL;
196 - }
197 2601 8 }
198 -
199 2364 2 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 2364 2 git_file fd = git_futils_open_ro(path);
209 2364 3 if (fd < 0)
210 ##### 4 return fd;
211 -
212 2364 5,6 if (p_fstat(fd, &st) < 0) {
213 ##### 7 p_close(fd);
214 ##### 8 git_error_set(GIT_ERROR_OS, "unable to stat pack index '%s'", path);
215 ##### 9 return -1;
216 - }
217 -
218 2364 10,12 if (!S_ISREG(st.st_mode) ||
219 2364 11,13 !git__is_sizet(st.st_size) ||
220 2364 13 (idx_size = (size_t)st.st_size) < 4 * 256 + 20 + 20)
221 - {
222 ##### 14 p_close(fd);
223 ##### 15 git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path);
224 ##### 16 return -1;
225 - }
226 -
227 2364 17 error = git_futils_mmap_ro(&p->index_map, fd, 0, idx_size);
228 -
229 2364 18 p_close(fd);
230 -
231 2364 19 if (error < 0)
232 ##### 20 return error;
233 -
234 2364 21 hdr = idx_map = p->index_map.data;
235 -
236 2364 21,22 if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
237 2364 23 version = ntohl(hdr->idx_version);
238 -
239 2364 24,25 if (version < 2 || version > 2) {
240 ##### 26 git_futils_mmap_free(&p->index_map);
241 ##### 27 return packfile_error("unsupported index version");
242 - }
243 -
244 - } else
245 ##### 28 version = 1;
246 -
247 2364 29 nr = 0;
248 2364 29 index = idx_map;
249 -
250 2364 29 if (version > 1)
251 2364 30 index += 2; /* skip index header */
252 -
253 607548 31,36,37 for (i = 0; i < 256; i++) {
254 605184 32 uint32_t n = ntohl(index[i]);
255 605184 33 if (n < nr) {
256 ##### 34 git_futils_mmap_free(&p->index_map);
257 ##### 35 return packfile_error("index is non-monotonic");
258 - }
259 605184 36 nr = n;
260 - }
261 -
262 2364 38 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 ##### 39 if (idx_size != 4*256 + nr * 24 + 20 + 20) {
271 ##### 40 git_futils_mmap_free(&p->index_map);
272 ##### 41 return packfile_error("index is corrupted");
273 - }
274 2364 42 } 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 2364 43 unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
289 2364 43 unsigned long max_size = min_size;
290 -
291 2364 43 if (nr)
292 2363 44 max_size += (nr - 1)*8;
293 -
294 2364 45,46 if (idx_size < min_size || idx_size > max_size) {
295 ##### 47 git_futils_mmap_free(&p->index_map);
296 ##### 48 return packfile_error("wrong index size");
297 - }
298 - }
299 -
300 2364 49 p->num_objects = nr;
301 2364 49 p->index_version = version;
302 2364 49 return 0;
303 - }
304 -
305 5696 2 static int pack_index_open(struct git_pack_file *p)
306 - {
307 5696 2 int error = 0;
308 - size_t name_len;
309 - git_buf idx_name;
310 -
311 5696 2 if (p->index_version > -1)
312 3 3 return 0;
313 -
314 5693 4 name_len = strlen(p->pack_name);
315 5693 4,5 assert(name_len > strlen(".pack")); /* checked by git_pack_file alloc */
316 -
317 5741 6,7 if (git_buf_init(&idx_name, name_len) < 0)
318 ##### 8 return -1;
319 -
320 5741 9 git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
321 5718 10 git_buf_puts(&idx_name, ".idx");
322 5712 11,12 if (git_buf_oom(&idx_name)) {
323 ##### 13 git_buf_dispose(&idx_name);
324 ##### 14 return -1;
325 - }
326 -
327 5774 15,16 if ((error = git_mutex_lock(&p->lock)) < 0) {
328 ##### 17 git_buf_dispose(&idx_name);
329 ##### 18 return error;
330 - }
331 -
332 5774 19 if (p->index_version == -1)
333 2364 20 error = pack_index_check(idx_name.ptr, p);
334 -
335 5774 21 git_buf_dispose(&idx_name);
336 -
337 5769 22 git_mutex_unlock(&p->lock);
338 -
339 5778 23 return error;
340 - }
341 -
342 54287 2 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 54287 2-4 if (p->mwf.fd == -1 && packfile_open(p) < 0)
349 ##### 5 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 54287 6 if (offset > (p->mwf.size - 20))
360 133 7 return NULL;
361 54154 8 if (offset < 0)
362 ##### 9 return NULL;
363 -
364 54154 10 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 2224 2 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 2224 2-4 assert(type >= GIT_OBJECT_COMMIT && type <= GIT_OBJECT_REF_DELTA);
381 -
382 - /* TODO: add support for chunked objects; see git.git 6c0d19b1 */
383 -
384 2224 5 c = (unsigned char)((type << 4) | (size & 15));
385 2224 5 size >>= 4;
386 2224 5 hdr_base = hdr;
387 -
388 3934 5,7 while (size) {
389 1710 6 *hdr++ = c | 0x80;
390 1710 6 c = size & 0x7f;
391 1710 6 size >>= 7;
392 - }
393 2224 8 *hdr++ = c;
394 -
395 2224 8 return (hdr - hdr_base);
396 - }
397 -
398 -
399 43926 2 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 43926 2 unsigned long used = 0;
409 -
410 43926 2 c = buf[used++];
411 43926 2 *type = (c >> 4) & 7;
412 43926 2 size = c & 15;
413 43926 2 shift = 4;
414 86667 2,10 while (c & 0x80) {
415 42741 3 if (len <= used) {
416 ##### 4 git_error_set(GIT_ERROR_ODB, "buffer too small");
417 ##### 5 return GIT_EBUFS;
418 - }
419 -
420 42741 6 if (bitsizeof(long) <= shift) {
421 ##### 7 *usedp = 0;
422 ##### 7 git_error_set(GIT_ERROR_ODB, "packfile corrupted");
423 ##### 8 return -1;
424 - }
425 -
426 42741 9 c = buf[used++];
427 42741 9 size += (c & 0x7f) << shift;
428 42741 9 shift += 7;
429 - }
430 -
431 43926 11 *sizep = (size_t)size;
432 43926 11 *usedp = used;
433 43926 11 return 0;
434 - }
435 -
436 43926 2 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 43926 2 base = git_mwindow_open(mwf, w_curs, *curpos, 20, &left);
456 43926 3 if (base == NULL)
457 ##### 4 return GIT_EBUFS;
458 -
459 43926 5 ret = packfile_unpack_header1(&used, size_p, type_p, base, left);
460 43926 6 git_mwindow_close(w_curs);
461 43926 7 if (ret == GIT_EBUFS)
462 ##### 8 return ret;
463 43926 9 else if (ret < 0)
464 ##### 10 return packfile_error("header length is zero");
465 -
466 43926 11 *curpos += used;
467 43926 11 return 0;
468 - }
469 -
470 2995 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 2995 2 git_mwindow *w_curs = NULL;
477 2995 2 off64_t curpos = offset;
478 - size_t size;
479 - git_object_t type;
480 - off64_t base_offset;
481 - int error;
482 -
483 2995 2 error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
484 2995 3 if (error < 0)
485 ##### 4 return error;
486 -
487 2995 5,6,18 if (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
488 - size_t base_size;
489 - git_packfile_stream stream;
490 -
491 474 7 error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, offset);
492 474 8 git_mwindow_close(&w_curs);
493 -
494 474 9 if (error < 0)
495 ##### 10,19 return error;
496 -
497 474 11,12 if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
498 ##### 13 return error;
499 474 14 error = git_delta_read_header_fromstream(&base_size, size_p, &stream);
500 474 15 git_packfile_stream_dispose(&stream);
501 474 16 if (error < 0)
502 ##### 17 return error;
503 - } else {
504 2521 20 *size_p = size;
505 2521 20 base_offset = 0;
506 - }
507 -
508 3476 21,32,33 while (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
509 955 22 curpos = base_offset;
510 955 22 error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
511 955 23 if (error < 0)
512 ##### 24 return error;
513 955 25,26 if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
514 474 27 break;
515 -
516 481 28 error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, base_offset);
517 481 29 git_mwindow_close(&w_curs);
518 -
519 481 30 if (error < 0)
520 ##### 31 return error;
521 - }
522 2995 34 *type_p = type;
523 -
524 2995 34 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 32837 2 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 32837 2 git_dependency_chain chain = GIT_ARRAY_INIT;
541 32837 2 git_mwindow *w_curs = NULL;
542 32837 2 off64_t curpos = obj_offset, base_offset;
543 32837 2 int error = 0, use_heap = 0;
544 - size_t size, elem_pos;
545 - git_object_t type;
546 -
547 32837 2 elem_pos = 0;
548 - while (true) {
549 - struct pack_chain_elem *elem;
550 44966 3 git_pack_cache_entry *cached = NULL;
551 -
552 - /* if we have a base cached, we can stop here instead */
553 44969 3,4 if ((cached = cache_get(&p->bases, obj_offset)) != NULL) {
554 10277 5 *cached_out = cached;
555 10277 5 *cached_off = obj_offset;
556 10277 5 break;
557 - }
558 -
559 - /* if we run out of space on the small stack, use the array */
560 34692 6 if (elem_pos == SMALL_STACK_SIZE) {
561 ##### 7 git_array_init_to_size(chain, elem_pos);
562 ##### 8,9 GIT_ERROR_CHECK_ARRAY(chain);
563 ##### 10 memcpy(chain.ptr, small_stack, elem_pos * sizeof(struct pack_chain_elem));
564 ##### 10 chain.size = elem_pos;
565 ##### 10 use_heap = 1;
566 - }
567 -
568 34692 11 curpos = obj_offset;
569 34692 11 if (!use_heap) {
570 34692 12 elem = &small_stack[elem_pos];
571 - } else {
572 ##### 13-18 elem = git_array_alloc(chain);
573 ##### 19 if (!elem) {
574 ##### 20 error = -1;
575 ##### 20 goto on_error;
576 - }
577 - }
578 -
579 34692 21 elem->base_key = obj_offset;
580 -
581 34692 21 error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
582 -
583 34690 22 if (error < 0)
584 ##### 23 goto on_error;
585 -
586 34690 24 elem->offset = curpos;
587 34690 24 elem->size = size;
588 34690 24 elem->type = type;
589 34690 24 elem->base_key = obj_offset;
590 -
591 34690 24,25 if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
592 22559 26 break;
593 -
594 12131 27 error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, obj_offset);
595 12133 28 git_mwindow_close(&w_curs);
596 -
597 12133 29 if (error < 0)
598 4 30 goto on_error;
599 -
600 - /* we need to pass the pos *after* the delta-base bit */
601 12129 31 elem->offset = curpos;
602 -
603 - /* go through the loop again, but with the new object */
604 12129 31 obj_offset = base_offset;
605 12129 31 elem_pos++;
606 12129 31 }
607 -
608 -
609 32836 32 *stack_sz = elem_pos + 1;
610 32836 32 *chain_out = chain;
611 32836 32 return error;
612 -
613 - on_error:
614 4 33 git_array_clear(chain);
615 4 34 return error;
616 - }
617 -
618 32838 2 int git_packfile_unpack(
619 - git_rawobj *obj,
620 - struct git_pack_file *p,
621 - off64_t *obj_offset)
622 - {
623 32838 2 git_mwindow *w_curs = NULL;
624 32838 2 off64_t curpos = *obj_offset;
625 32838 2 int error, free_base = 0;
626 32838 2 git_dependency_chain chain = GIT_ARRAY_INIT;
627 32838 2 struct pack_chain_elem *elem = NULL, *stack;
628 32838 2 git_pack_cache_entry *cached = NULL;
629 - struct pack_chain_elem small_stack[SMALL_STACK_SIZE];
630 32838 2 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 32838 2 error = pack_dependency_chain(&chain, &cached, obj_offset, small_stack, &stack_size, p, *obj_offset);
638 32840 3 if (error < 0)
639 4 4 return error;
640 -
641 32836 5 obj->data = NULL;
642 32836 5 obj->len = 0;
643 32836 5 obj->type = GIT_OBJECT_INVALID;
644 -
645 - /* let's point to the right stack */
646 32836 5-7 stack = chain.ptr ? chain.ptr : small_stack;
647 -
648 32836 8 elem_pos = stack_size;
649 32836 8 if (cached) {
650 10277 9 memcpy(obj, &cached->raw, sizeof(git_rawobj));
651 10277 9 base_type = obj->type;
652 10277 9 elem_pos--; /* stack_size includes the base, which isn't actually there */
653 - } else {
654 22559 10 elem = &stack[--elem_pos];
655 22559 10 base_type = elem->type;
656 - }
657 -
658 32836 11 switch (base_type) {
659 - case GIT_OBJECT_COMMIT:
660 - case GIT_OBJECT_TREE:
661 - case GIT_OBJECT_BLOB:
662 - case GIT_OBJECT_TAG:
663 32836 12 if (!cached) {
664 22559 13 curpos = elem->offset;
665 22559 13 error = packfile_unpack_compressed(obj, p, &w_curs, &curpos, elem->size, elem->type);
666 22558 14 git_mwindow_close(&w_curs);
667 22558 15 base_type = elem->type;
668 - }
669 32835 16 if (error < 0)
670 ##### 17 goto cleanup;
671 32835 18 break;
672 - case GIT_OBJECT_OFS_DELTA:
673 - case GIT_OBJECT_REF_DELTA:
674 ##### 19 error = packfile_error("dependency chain ends in a delta");
675 ##### 20 goto cleanup;
676 - default:
677 ##### 21 error = packfile_error("invalid packfile type in header");
678 ##### 22 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 32835 23,24 if (cached && stack_size == 1) {
688 3413 25 void *data = obj->data;
689 -
690 3413 25-31 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, obj->len, 1);
691 3413 32 obj->data = git__malloc(alloclen);
692 3413 33,34 GIT_ERROR_CHECK_ALLOC(obj->data);
693 -
694 3413 35 memcpy(obj->data, data, obj->len + 1);
695 3413 35 git_atomic_dec(&cached->refcount);
696 3413 36 goto cleanup;
697 - }
698 -
699 - /* we now apply each consecutive delta until we run out */
700 41550 37,56,57 while (elem_pos > 0 && !error) {
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 12129 38 if (!cached)
708 5265 39,40 free_base = !!cache_add(&cached, &p->bases, obj, elem->base_key);
709 -
710 12129 41 elem = &stack[elem_pos - 1];
711 12129 41 curpos = elem->offset;
712 12129 41 error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, elem->size, elem->type);
713 12129 42 git_mwindow_close(&w_curs);
714 -
715 12129 43 if (error < 0) {
716 - /* We have transferred ownership of the data to the cache. */
717 1 44 obj->data = NULL;
718 1 44,55 break;
719 - }
720 -
721 - /* the current object becomes the new base, on which we apply the delta */
722 12128 45 base = *obj;
723 12128 45 obj->data = NULL;
724 12128 45 obj->len = 0;
725 12128 45 obj->type = GIT_OBJECT_INVALID;
726 -
727 12128 45 error = git_delta_apply(&obj->data, &obj->len, base.data, base.len, delta.data, delta.len);
728 12128 46 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 12128 46 git__free(delta.data);
737 12128 47 if (free_base) {
738 ##### 48 free_base = 0;
739 ##### 48 git__free(base.data);
740 - }
741 -
742 12128 49 if (cached) {
743 12128 50 git_atomic_dec(&cached->refcount);
744 12128 51 cached = NULL;
745 - }
746 -
747 12128 52 if (error < 0)
748 ##### 53 break;
749 -
750 12128 54 elem_pos--;
751 - }
752 -
753 - cleanup:
754 32835 58 if (error < 0) {
755 1 59 git__free(obj->data);
756 1 60 if (cached)
757 1 61 git_atomic_dec(&cached->refcount);
758 - }
759 -
760 32835 62 if (elem)
761 29422 63 *obj_offset = curpos;
762 -
763 32835 64 git_array_clear(chain);
764 32835 65 return error;
765 - }
766 -
767 5756 2 int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, off64_t curpos)
768 - {
769 5756 2 memset(obj, 0, sizeof(git_packfile_stream));
770 5756 2 obj->curpos = curpos;
771 5756 2 obj->p = p;
772 -
773 5756 2,3 if (git_zstream_init(&obj->zstream, GIT_ZSTREAM_INFLATE) < 0) {
774 ##### 4 git_error_set(GIT_ERROR_ZLIB, "failed to init packfile stream");
775 ##### 5 return -1;
776 - }
777 -
778 5756 6 return 0;
779 - }
780 -
781 11307 2 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 11307 2 if (obj->done)
788 5351 3 return 0;
789 -
790 5956 4,5 if ((in = pack_window_open(obj->p, &obj->mw, obj->curpos, &window_len)) == NULL)
791 133 6 return GIT_EBUFS;
792 -
793 5823 7-10 if ((error = git_zstream_set_input(&obj->zstream, in, window_len)) < 0 ||
794 5823 9 (error = git_zstream_get_output_chunk(buffer, &len, &obj->zstream)) < 0) {
795 ##### 11 git_mwindow_close(&obj->mw);
796 ##### 12 git_error_set(GIT_ERROR_ZLIB, "error reading from the zlib stream");
797 ##### 13 return -1;
798 - }
799 -
800 5823 14 git_mwindow_close(&obj->mw);
801 -
802 5823 15 obj->curpos += window_len - obj->zstream.in_len;
803 -
804 5823 15,16 if (git_zstream_eos(&obj->zstream))
805 5364 17 obj->done = 1;
806 -
807 - /* If we didn't write anything out but we're not done, we need more data */
808 5823 18-20 if (!len && !git_zstream_eos(&obj->zstream))
809 ##### 21 return GIT_EBUFS;
810 -
811 5823 22 return len;
812 -
813 - }
814 -
815 5756 2 void git_packfile_stream_dispose(git_packfile_stream *obj)
816 - {
817 5756 2 git_zstream_free(&obj->zstream);
818 5756 3 }
819 -
820 - 2 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files)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 - 2 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git_zstream zstream = GIT_ZSTREAM_INIT;
829 - 2 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) size_t buffer_len, total = 0;
830 - 2 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) char *data = NULL;
831 - int error;
832 -
833 - 2-8 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC_ADD(&buffer_len, size, 1);
834 - 9 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) data = git__calloc(1, buffer_len);
835 - 10,11 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC(data);
836 -
837 - 12,13 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0) {
838 - 14 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack");
839 - 15 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) goto out;
840 - }
841 -
842 - do {
843 - 16 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) size_t bytes = buffer_len - total;
844 - unsigned int window_len;
845 - unsigned char *in;
846 -
847 - 16 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) in = pack_window_open(p, mwindow, *position, &window_len);
848 -
849 - 17-20 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 ||
850 - 19 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) (error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) {
851 - 21 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git_mwindow_close(mwindow);
852 - 22 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) goto out;
853 - }
854 -
855 - 23 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git_mwindow_close(mwindow);
856 -
857 - 24 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) *position += window_len - zstream.in_len;
858 - 24 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) total += bytes;
859 - 24 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) } while (total < size);
860 -
861 - 25-27 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) if (total != size || !git_zstream_eos(&zstream)) {
862 - 28 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
863 - 29 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) error = -1;
864 - 29 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) goto out;
865 - }
866 -
867 - 30 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) obj->type = type;
868 - 30 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) obj->len = size;
869 - 30 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) obj->data = data;
870 -
871 - out:
872 - 31 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git_zstream_free(&zstream);
873 - 32 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) if (error)
874 - 33 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) git__free(data);
875 -
876 - 34 suppressed: function cannot be solved packfile_unpack_compressed (automatic due to inconsistent arc counts in .gcda files) return error;
877 - }
878 -
879 - /*
880 - * curpos is where the data starts, delta_obj_offset is the where the
881 - * header starts
882 - */
883 13647 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 13647 2 unsigned int left = 0;
892 - unsigned char *base_info;
893 - off64_t base_offset;
894 - git_oid unused;
895 -
896 13647 2,3 assert(delta_base_out);
897 -
898 13647 4 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 13647 5 if (base_info == NULL)
901 ##### 6 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 13647 7 if (type == GIT_OBJECT_OFS_DELTA) {
909 13449 8 unsigned used = 0;
910 13449 8 unsigned char c = base_info[used++];
911 13449 8 size_t unsigned_base_offset = c & 127;
912 26891 8,15 while (c & 128) {
913 13442 9 if (left <= used)
914 ##### 10 return GIT_EBUFS;
915 13442 11 unsigned_base_offset += 1;
916 13442 11,12 if (!unsigned_base_offset || MSB(unsigned_base_offset, 7))
917 ##### 13 return packfile_error("overflow");
918 13442 14 c = base_info[used++];
919 13442 14 unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127);
920 - }
921 13449 16,17 if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset)
922 ##### 18 return packfile_error("out of bounds");
923 13449 19 base_offset = delta_obj_offset - unsigned_base_offset;
924 13449 19 *curpos += used;
925 198 20 } else if (type == GIT_OBJECT_REF_DELTA) {
926 - /* If we have the cooperative cache, search in it first */
927 198 21 if (p->has_cache) {
928 - struct git_pack_entry *entry;
929 - git_oid oid;
930 -
931 145 22 git_oid_fromraw(&oid, base_info);
932 145 23,24 if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
933 141 25 if (entry->offset == 0)
934 ##### 26 return packfile_error("delta offset is zero");
935 -
936 141 27 *curpos += 20;
937 141 27 *delta_base_out = entry->offset;
938 141 27 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 145 28,29 return GIT_PASSTHROUGH;
945 - }
946 - }
947 -
948 - /* The base entry _must_ be in the same pack */
949 53 30,31 if (pack_entry_find_offset(&base_offset, &unused, p, (git_oid *)base_info, GIT_OID_HEXSZ) < 0)
950 ##### 32 return packfile_error("base entry delta is not in the same pack");
951 53 33 *curpos += 20;
952 - } else
953 ##### 34 return packfile_error("unknown object type");
954 -
955 13502 35 if (base_offset == 0)
956 ##### 36 return packfile_error("delta offset is zero");
957 -
958 13502 37 *delta_base_out = base_offset;
959 13502 37 return 0;
960 - }
961 -
962 - /***********************************************************
963 - *
964 - * PACKFILE METHODS
965 - *
966 - ***********************************************************/
967 -
968 2610 2 void git_packfile_close(struct git_pack_file *p, bool unlink_packfile)
969 - {
970 2610 2 if (p->mwf.fd >= 0) {
971 445 3 git_mwindow_free_all_locked(&p->mwf);
972 445 4 p_close(p->mwf.fd);
973 445 5 p->mwf.fd = -1;
974 - }
975 -
976 2610 6 if (unlink_packfile)
977 9 7 p_unlink(p->pack_name);
978 2610 8 }
979 -
980 2601 2 void git_packfile_free(struct git_pack_file *p)
981 - {
982 2601 2 if (!p)
983 2601 3,11 return;
984 -
985 2601 4 cache_free(&p->bases);
986 -
987 2601 5 git_packfile_close(p, false);
988 -
989 2601 6 pack_index_free(p);
990 -
991 2601 7 git__free(p->bad_object_sha1);
992 -
993 2601 8 git_mutex_free(&p->lock);
994 2601 9 git_mutex_free(&p->bases.lock);
995 2601 10 git__free(p);
996 - }
997 -
998 519 2 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 519 2-4 if (p->index_version == -1 && pack_index_open(p) < 0)
1006 ##### 5 return git_odb__error_notfound("failed to open packfile", NULL, 0);
1007 -
1008 - /* if mwf opened by another thread, return now */
1009 520 6,7 if (git_mutex_lock(&p->lock) < 0)
1010 ##### 8 return packfile_error("failed to get lock for open");
1011 -
1012 520 9 if (p->mwf.fd >= 0) {
1013 84 10 git_mutex_unlock(&p->lock);
1014 84 11 return 0;
1015 - }
1016 -
1017 - /* TODO: open with noatime */
1018 436 12 p->mwf.fd = git_futils_open_ro(p->pack_name);
1019 436 13 if (p->mwf.fd < 0)
1020 ##### 14 goto cleanup;
1021 -
1022 436 15,16,18 if (p_fstat(p->mwf.fd, &st) < 0 ||
1023 436 17 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 436 19 if (!p->mwf.size) {
1028 ##### 20 if (!S_ISREG(st.st_mode))
1029 ##### 21 goto cleanup;
1030 ##### 22 p->mwf.size = (off64_t)st.st_size;
1031 436 23 } else if (p->mwf.size != st.st_size)
1032 ##### 24 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 436 25,26,28 if (p_read(p->mwf.fd, &hdr, sizeof(hdr)) < 0 ||
1049 436 27,30 hdr.hdr_signature != htonl(PACK_SIGNATURE) ||
1050 436 29,31,32 !pack_version_ok(hdr.hdr_version))
1051 - goto cleanup;
1052 -
1053 - /* Verify the pack matches its index. */
1054 436 33,34,36 if (p->num_objects != ntohl(hdr.hdr_entries) ||
1055 436 35,38 p_lseek(p->mwf.fd, p->mwf.size - GIT_OID_RAWSZ, SEEK_SET) == -1 ||
1056 436 37 p_read(p->mwf.fd, sha1.id, GIT_OID_RAWSZ) < 0)
1057 - goto cleanup;
1058 -
1059 436 39 idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
1060 -
1061 436 39,40 if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
1062 ##### 41 goto cleanup;
1063 -
1064 436 42 git_mutex_unlock(&p->lock);
1065 436 43 return 0;
1066 -
1067 - cleanup:
1068 ##### 44 git_error_set(GIT_ERROR_OS, "invalid packfile '%s'", p->pack_name);
1069 -
1070 ##### 45 if (p->mwf.fd >= 0)
1071 ##### 46 p_close(p->mwf.fd);
1072 ##### 47 p->mwf.fd = -1;
1073 -
1074 ##### 47 git_mutex_unlock(&p->lock);
1075 -
1076 ##### 48 return -1;
1077 - }
1078 -
1079 - 2 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files)int git_packfile__name(char **out, const char *path)
1080 - {
1081 - size_t path_len;
1082 - 2 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) git_buf buf = GIT_BUF_INIT;
1083 -
1084 - 2 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) path_len = strlen(path);
1085 -
1086 - 2 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) if (path_len < strlen(".idx"))
1087 - 3 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) return git_odb__error_notfound("invalid packfile path", NULL, 0);
1088 -
1089 - 4,5 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
1090 - 6 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) return -1;
1091 -
1092 - 7 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) *out = git_buf_detach(&buf);
1093 - 8 suppressed: function cannot be solved git_packfile__name (automatic due to inconsistent arc counts in .gcda files) return 0;
1094 - }
1095 -
1096 2601 2 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 2601 2-4 size_t path_len = path ? strlen(path) : 0, alloc_len;
1101 -
1102 2601 5 *pack_out = NULL;
1103 -
1104 2601 5 if (path_len < strlen(".idx"))
1105 ##### 6 return git_odb__error_notfound("invalid packfile path", NULL, 0);
1106 -
1107 2601 7-13 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*p), path_len);
1108 2601 14-20 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
1109 -
1110 2601 21 p = git__calloc(1, alloc_len);
1111 2601 22,23 GIT_ERROR_CHECK_ALLOC(p);
1112 -
1113 2601 24 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 2601 24,25 if (git__suffixcmp(path, ".idx") == 0) {
1120 2502 26 size_t root_len = path_len - strlen(".idx");
1121 -
1122 2502 26 if (!git_disable_pack_keep_file_checks) {
1123 2502 27 memcpy(p->pack_name + root_len, ".keep", sizeof(".keep"));
1124 2502 27,28 if (git_path_exists(p->pack_name) == true)
1125 ##### 29 p->pack_keep = 1;
1126 - }
1127 -
1128 2502 30 memcpy(p->pack_name + root_len, ".pack", sizeof(".pack"));
1129 - }
1130 -
1131 2601 31-33 if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
1132 ##### 34 git__free(p);
1133 ##### 35 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 2601 36 p->mwf.fd = -1;
1140 2601 36 p->mwf.size = st.st_size;
1141 2601 36 p->pack_local = 1;
1142 2601 36 p->mtime = (git_time_t)st.st_mtime;
1143 2601 36 p->index_version = -1;
1144 -
1145 2601 36,37 if (git_mutex_init(&p->lock)) {
1146 ##### 38 git_error_set(GIT_ERROR_OS, "failed to initialize packfile mutex");
1147 ##### 39 git__free(p);
1148 ##### 40 return -1;
1149 - }
1150 -
1151 2601 41,42 if (cache_init(&p->bases) < 0) {
1152 ##### 43 git__free(p);
1153 ##### 44 return -1;
1154 - }
1155 -
1156 2601 45 *pack_out = p;
1157 -
1158 2601 45 return 0;
1159 - }
1160 -
1161 - /***********************************************************
1162 - *
1163 - * PACKFILE ENTRY SEARCH INTERNALS
1164 - *
1165 - ***********************************************************/
1166 -
1167 35876 2 static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n)
1168 - {
1169 35876 2 const unsigned char *index = p->index_map.data;
1170 35876 2 const unsigned char *end = index + p->index_map.len;
1171 35876 2 index += 4 * 256;
1172 35876 2 if (p->index_version == 1) {
1173 ##### 3,4 return ntohl(*((uint32_t *)(index + 24 * n)));
1174 - } else {
1175 - uint32_t off;
1176 35876 5 index += 8 + p->num_objects * (20 + 4);
1177 35876 5 off = ntohl(*((uint32_t *)(index + 4 * n)));
1178 35877 6 if (!(off & 0x80000000))
1179 35877 7 return off;
1180 ##### 8 index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
1181 -
1182 - /* Make sure we're not being sent out of bounds */
1183 ##### 8 if (index >= end - 8)
1184 ##### 9 return -1;
1185 -
1186 ##### 10 return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
1187 ##### 11 ntohl(*((uint32_t *)(index + 4)));
1188 - }
1189 - }
1190 -
1191 76988 2 static int git__memcmp4(const void *a, const void *b) {
1192 76988 2 return memcmp(a, b, 4);
1193 - }
1194 -
1195 13 2 int git_pack_foreach_entry(
1196 - struct git_pack_file *p,
1197 - git_odb_foreach_cb cb,
1198 - void *data)
1199 - {
1200 13 2 const unsigned char *index = p->index_map.data, *current;
1201 - uint32_t i;
1202 13 2 int error = 0;
1203 -
1204 13 2 if (index == NULL) {
1205 10 3,4 if ((error = pack_index_open(p)) < 0)
1206 ##### 5 return error;
1207 -
1208 10 6,7 assert(p->index_map.data);
1209 -
1210 10 8 index = p->index_map.data;
1211 - }
1212 -
1213 13 9 if (p->index_version > 1) {
1214 13 10 index += 8;
1215 - }
1216 -
1217 13 11 index += 4 * 256;
1218 -
1219 13 11 if (p->oids == NULL) {
1220 - git_vector offsets, oids;
1221 -
1222 10 12,13 if ((error = git_vector_init(&oids, p->num_objects, NULL)))
1223 ##### 14,43 return error;
1224 -
1225 10 15,16 if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4)))
1226 ##### 17 return error;
1227 -
1228 10 18 if (p->index_version > 1) {
1229 10 19 const unsigned char *off = index + 24 * p->num_objects;
1230 6558 19,21,22 for (i = 0; i < p->num_objects; i++)
1231 6548 20 git_vector_insert(&offsets, (void*)&off[4 * i]);
1232 10 23 git_vector_sort(&offsets);
1233 6558 24,26-29 git_vector_foreach(&offsets, i, current)
1234 6548 25 git_vector_insert(&oids, (void*)&index[5 * (current - off)]);
1235 - } else {
1236 ##### 30,32,33 for (i = 0; i < p->num_objects; i++)
1237 ##### 31 git_vector_insert(&offsets, (void*)&index[24 * i]);
1238 ##### 34 git_vector_sort(&offsets);
1239 ##### 35,37-39 git_vector_foreach(&offsets, i, current)
1240 ##### 36 git_vector_insert(&oids, (void*)&current[4]);
1241 - }
1242 -
1243 10 40 git_vector_free(&offsets);
1244 10 41,42 p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
1245 - }
1246 -
1247 6919 44,48,49 for (i = 0; i < p->num_objects; i++)
1248 6908 45,46 if ((error = cb(p->oids[i], data)) != 0)
1249 2 47 return git_error_set_after_callback(error);
1250 -
1251 11 50 return error;
1252 - }
1253 -
1254 172683 2 static int sha1_position(const void *table, size_t stride, unsigned lo,
1255 - unsigned hi, const unsigned char *key)
1256 - {
1257 172683 2 const unsigned char *base = table;
1258 -
1259 472832 2,9 while (lo < hi) {
1260 335178 3 unsigned mi = (lo + hi) / 2;
1261 335178 3 int cmp = git_oid__hashcmp(base + mi * stride, key);
1262 -
1263 335812 4 if (!cmp)
1264 35663 5 return mi;
1265 -
1266 300149 6 if (cmp > 0)
1267 189828 7 hi = mi;
1268 - else
1269 110321 8 lo = mi+1;
1270 - }
1271 -
1272 137654 10 return -((int)lo)-1;
1273 - }
1274 -
1275 - 2 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files)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 - 2 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) int pos, found = 0;
1286 - off64_t offset;
1287 - 2 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) const unsigned char *current = 0;
1288 -
1289 - 2 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) *offset_out = 0;
1290 -
1291 - 2 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (p->index_version == -1) {
1292 - int error;
1293 -
1294 - 3,4 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if ((error = pack_index_open(p)) < 0)
1295 - 5 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) return error;
1296 - 6,7 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) assert(p->index_map.data);
1297 - }
1298 -
1299 - 8 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) index = p->index_map.data;
1300 - 8 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) level1_ofs = p->index_map.data;
1301 -
1302 - 8 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (p->index_version > 1) {
1303 - 9 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) level1_ofs += 2;
1304 - 9 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) index += 8;
1305 - }
1306 -
1307 - 10 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) index += 4 * 256;
1308 - 10 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) hi = ntohl(level1_ofs[(int)short_oid->id[0]]);
1309 - 11-13 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(level1_ofs[(int)short_oid->id[0] - 1]));
1310 -
1311 - 14 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (p->index_version > 1) {
1312 - 15 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) stride = 20;
1313 - } else {
1314 - 16 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) stride = 24;
1315 - 16 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) 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 - 17 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) pos = sha1_position(index, stride, lo, hi, short_oid->id);
1324 -
1325 - 18 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (pos >= 0) {
1326 - /* An object matching exactly the oid was found */
1327 - 19 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) found = 1;
1328 - 19 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) 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 - 20 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) pos = - 1 - pos;
1333 - 20 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (pos < (int)p->num_objects) {
1334 - 21 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) current = index + pos * stride;
1335 -
1336 - 21,22 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (!git_oid_ncmp(short_oid, (const git_oid *)current, len))
1337 - 23 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) found = 1;
1338 - }
1339 - }
1340 -
1341 - 24-26 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)p->num_objects) {
1342 - /* Check for ambiguousity */
1343 - 27 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) const unsigned char *next = current + stride;
1344 -
1345 - 27,28 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (!git_oid_ncmp(short_oid, (const git_oid *)next, len)) {
1346 - 29 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) found = 2;
1347 - }
1348 - }
1349 -
1350 - 30 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (!found)
1351 - 31 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
1352 - 32 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if (found > 1)
1353 - 33 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) return git_odb__error_ambiguous("found multiple offsets for pack entry");
1354 -
1355 - 34,35 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) if ((offset = nth_packed_object_offset(p, pos)) < 0) {
1356 - 36 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_ODB, "packfile index is corrupt");
1357 - 37 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) return -1;
1358 - }
1359 -
1360 - 38 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) *offset_out = offset;
1361 - 38 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) 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 - 39 suppressed: function cannot be solved pack_entry_find_offset (automatic due to inconsistent arc counts in .gcda files) return 0;
1373 - }
1374 -
1375 - 2 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files)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 - 2,3 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) assert(p);
1386 -
1387 - 4,5 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) if (len == GIT_OID_HEXSZ && p->num_bad_objects) {
1388 - unsigned i;
1389 - 6,10,11 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) for (i = 0; i < p->num_bad_objects; i++)
1390 - 7,8 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) if (git_oid__cmp(short_oid, &p->bad_object_sha1[i]) == 0)
1391 - 9 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) return packfile_error("bad object found in packfile");
1392 - }
1393 -
1394 - 12 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) error = pack_entry_find_offset(&offset, &found_oid, p, short_oid, len);
1395 - 13 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) if (error < 0)
1396 - 14 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) 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 - 15-17 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) if (p->mwf.fd == -1 && (error = packfile_open(p)) < 0)
1402 - 18 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) return error;
1403 -
1404 - 19 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) e->offset = offset;
1405 - 19 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) e->p = p;
1406 -
1407 - 19 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) git_oid_cpy(&e->sha1, &found_oid);
1408 - 20 suppressed: function cannot be solved git_pack_entry_find (automatic due to inconsistent arc counts in .gcda files) return 0;
1409 - }