2 * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
3 * Copyright (c) 2020, 2022 Stefan Sperling <stsp@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/queue.h>
21 #include <sys/types.h>
41 #include "got_error.h"
42 #include "got_object.h"
44 #include "got_lib_sha1.h"
45 #include "got_lib_delta.h"
46 #include "got_lib_inflate.h"
47 #include "got_lib_object.h"
48 #include "got_lib_object_parse.h"
49 #include "got_lib_object_idset.h"
50 #include "got_lib_privsep.h"
51 #include "got_lib_pack.h"
52 #include "got_lib_ratelimit.h"
53 #include "got_lib_pack_index.h"
54 #include "got_lib_delta_cache.h"
56 struct got_indexed_object
{
57 struct got_object_id id
;
60 * Has this object been fully resolved?
61 * If so, we know its ID, otherwise we don't and 'id' is invalid.
65 /* Offset of type+size field for this object in pack file. */
68 /* Type+size values parsed from pack file. */
72 /* Length of on-disk type+size data. */
75 /* Length of object data following type+size. */
83 struct got_object_id ref_id
;
86 /* For offset deltas. */
88 size_t base_offsetlen
;
94 putbe32(char *b
, uint32_t n
)
102 static const struct got_error
*
103 get_obj_type_label(const char **label
, int obj_type
)
105 const struct got_error
*err
= NULL
;
108 case GOT_OBJ_TYPE_BLOB
:
109 *label
= GOT_OBJ_LABEL_BLOB
;
111 case GOT_OBJ_TYPE_TREE
:
112 *label
= GOT_OBJ_LABEL_TREE
;
114 case GOT_OBJ_TYPE_COMMIT
:
115 *label
= GOT_OBJ_LABEL_COMMIT
;
117 case GOT_OBJ_TYPE_TAG
:
118 *label
= GOT_OBJ_LABEL_TAG
;
122 err
= got_error(GOT_ERR_OBJ_TYPE
);
129 static const struct got_error
*
130 read_checksum(uint32_t *crc
, SHA1_CTX
*sha1_ctx
, int fd
, size_t len
)
136 for (n
= len
; n
> 0; n
-= r
){
137 r
= read(fd
, buf
, n
> sizeof(buf
) ? sizeof(buf
) : n
);
139 return got_error_from_errno("read");
143 *crc
= crc32(*crc
, buf
, r
);
145 SHA1Update(sha1_ctx
, buf
, r
);
151 static const struct got_error
*
152 read_file_sha1(SHA1_CTX
*ctx
, FILE *f
, size_t len
)
157 for (n
= len
; n
> 0; n
-= r
) {
158 r
= fread(buf
, 1, n
> sizeof(buf
) ? sizeof(buf
) : n
, f
);
162 return got_ferror(f
, GOT_ERR_IO
);
164 SHA1Update(ctx
, buf
, r
);
170 static const struct got_error
*
171 read_packed_object(struct got_pack
*pack
, struct got_indexed_object
*obj
,
172 FILE *tmpfile
, SHA1_CTX
*pack_sha1_ctx
)
174 const struct got_error
*err
= NULL
;
176 uint8_t *data
= NULL
;
181 const char *obj_label
;
182 size_t mapoff
= obj
->off
;
183 struct got_inflate_checksum csum
;
185 memset(&csum
, 0, sizeof(csum
));
186 csum
.input_sha1
= pack_sha1_ctx
;
187 csum
.input_crc
= &obj
->crc
;
189 err
= got_pack_parse_object_type_and_size(&obj
->type
, &obj
->size
,
190 &obj
->tslen
, pack
, obj
->off
);
195 obj
->crc
= crc32(obj
->crc
, pack
->map
+ mapoff
, obj
->tslen
);
196 SHA1Update(pack_sha1_ctx
, pack
->map
+ mapoff
, obj
->tslen
);
197 mapoff
+= obj
->tslen
;
199 /* XXX Seek back and get the CRC of on-disk type+size bytes. */
200 if (lseek(pack
->fd
, obj
->off
, SEEK_SET
) == -1)
201 return got_error_from_errno("lseek");
202 err
= read_checksum(&obj
->crc
, pack_sha1_ctx
,
203 pack
->fd
, obj
->tslen
);
209 case GOT_OBJ_TYPE_BLOB
:
210 case GOT_OBJ_TYPE_COMMIT
:
211 case GOT_OBJ_TYPE_TREE
:
212 case GOT_OBJ_TYPE_TAG
:
213 if (obj
->size
> GOT_DELTA_RESULT_SIZE_CACHED_MAX
) {
214 if (fseek(tmpfile
, 0L, SEEK_SET
) == -1) {
215 err
= got_error_from_errno("fseek");
219 err
= got_inflate_to_file_mmap(&datalen
,
220 &obj
->len
, &csum
, pack
->map
, mapoff
,
221 pack
->filesize
- mapoff
, tmpfile
);
223 err
= got_inflate_to_file_fd(&datalen
,
224 &obj
->len
, &csum
, pack
->fd
, tmpfile
);
228 err
= got_inflate_to_mem_mmap(&data
, &datalen
,
229 &obj
->len
, &csum
, pack
->map
, mapoff
,
230 pack
->filesize
- mapoff
);
232 err
= got_inflate_to_mem_fd(&data
, &datalen
,
233 &obj
->len
, &csum
, obj
->size
, pack
->fd
);
239 err
= get_obj_type_label(&obj_label
, obj
->type
);
244 if (asprintf(&header
, "%s %lld", obj_label
,
245 (long long)obj
->size
) == -1) {
246 err
= got_error_from_errno("asprintf");
250 headerlen
= strlen(header
) + 1;
251 SHA1Update(&ctx
, header
, headerlen
);
252 if (obj
->size
> GOT_DELTA_RESULT_SIZE_CACHED_MAX
) {
253 err
= read_file_sha1(&ctx
, tmpfile
, datalen
);
260 SHA1Update(&ctx
, data
, datalen
);
261 SHA1Final(obj
->id
.sha1
, &ctx
);
265 case GOT_OBJ_TYPE_REF_DELTA
:
266 memset(obj
->id
.sha1
, 0xff, SHA1_DIGEST_LENGTH
);
268 if (mapoff
+ SHA1_DIGEST_LENGTH
>= pack
->filesize
) {
269 err
= got_error(GOT_ERR_BAD_PACKFILE
);
272 if (mapoff
+ SHA1_DIGEST_LENGTH
> SIZE_MAX
) {
273 err
= got_error_fmt(GOT_ERR_RANGE
,
274 "mapoff %lld would overflow size_t",
275 (long long)mapoff
+ SHA1_DIGEST_LENGTH
);
278 memcpy(obj
->delta
.ref
.ref_id
.sha1
, pack
->map
+ mapoff
,
280 obj
->crc
= crc32(obj
->crc
, pack
->map
+ mapoff
,
282 SHA1Update(pack_sha1_ctx
, pack
->map
+ mapoff
,
284 mapoff
+= SHA1_DIGEST_LENGTH
;
285 err
= got_inflate_to_mem_mmap(NULL
, &datalen
,
286 &obj
->len
, &csum
, pack
->map
, mapoff
,
287 pack
->filesize
- mapoff
);
291 n
= read(pack
->fd
, obj
->delta
.ref
.ref_id
.sha1
,
294 err
= got_error_from_errno("read");
297 if (n
< sizeof(obj
->id
)) {
298 err
= got_error(GOT_ERR_BAD_PACKFILE
);
301 obj
->crc
= crc32(obj
->crc
, obj
->delta
.ref
.ref_id
.sha1
,
303 SHA1Update(pack_sha1_ctx
, obj
->delta
.ref
.ref_id
.sha1
,
305 err
= got_inflate_to_mem_fd(NULL
, &datalen
, &obj
->len
,
306 &csum
, obj
->size
, pack
->fd
);
310 obj
->len
+= SHA1_DIGEST_LENGTH
;
312 case GOT_OBJ_TYPE_OFFSET_DELTA
:
313 memset(obj
->id
.sha1
, 0xff, SHA1_DIGEST_LENGTH
);
314 err
= got_pack_parse_offset_delta(&obj
->delta
.ofs
.base_offset
,
315 &obj
->delta
.ofs
.base_offsetlen
, pack
, obj
->off
,
321 if (mapoff
+ obj
->delta
.ofs
.base_offsetlen
>=
323 err
= got_error(GOT_ERR_BAD_PACKFILE
);
327 if (mapoff
+ obj
->delta
.ofs
.base_offsetlen
>
329 err
= got_error_fmt(GOT_ERR_RANGE
,
330 "mapoff %lld would overflow size_t",
332 + obj
->delta
.ofs
.base_offsetlen
);
335 obj
->crc
= crc32(obj
->crc
, pack
->map
+ mapoff
,
336 obj
->delta
.ofs
.base_offsetlen
);
337 SHA1Update(pack_sha1_ctx
, pack
->map
+ mapoff
,
338 obj
->delta
.ofs
.base_offsetlen
);
339 mapoff
+= obj
->delta
.ofs
.base_offsetlen
;
340 err
= got_inflate_to_mem_mmap(NULL
, &datalen
,
341 &obj
->len
, &csum
, pack
->map
, mapoff
,
342 pack
->filesize
- mapoff
);
347 * XXX Seek back and get CRC and SHA1 of on-disk
350 if (lseek(pack
->fd
, obj
->off
+ obj
->tslen
, SEEK_SET
)
352 err
= got_error_from_errno("lseek");
355 err
= read_checksum(&obj
->crc
, pack_sha1_ctx
,
356 pack
->fd
, obj
->delta
.ofs
.base_offsetlen
);
360 err
= got_inflate_to_mem_fd(NULL
, &datalen
, &obj
->len
,
361 &csum
, obj
->size
, pack
->fd
);
365 obj
->len
+= obj
->delta
.ofs
.base_offsetlen
;
368 err
= got_error(GOT_ERR_OBJ_TYPE
);
375 const struct got_error
*
376 got_pack_hwrite(int fd
, void *buf
, int len
, SHA1_CTX
*ctx
)
380 SHA1Update(ctx
, buf
, len
);
382 w
= write(fd
, buf
, len
);
384 return got_error_from_errno("write");
386 return got_error(GOT_ERR_IO
);
391 static const struct got_error
*
392 resolve_deltified_object(struct got_pack
*pack
, struct got_packidx
*packidx
,
393 struct got_indexed_object
*obj
, FILE *tmpfile
, FILE *delta_base_file
,
394 FILE *delta_accum_file
)
396 const struct got_error
*err
= NULL
;
397 struct got_delta_chain deltas
;
398 struct got_delta
*delta
;
406 const char *obj_label
;
409 STAILQ_INIT(&deltas
.entries
);
411 err
= got_pack_resolve_delta_chain(&deltas
, packidx
, pack
,
412 obj
->off
, obj
->tslen
, obj
->type
, obj
->size
,
413 GOT_DELTA_CHAIN_RECURSION_MAX
);
417 err
= got_pack_get_delta_chain_max_size(&max_size
, &deltas
, pack
);
420 if (max_size
> GOT_DELTA_RESULT_SIZE_CACHED_MAX
) {
422 rewind(delta_base_file
);
423 rewind(delta_accum_file
);
424 err
= got_pack_dump_delta_chain_to_file(&len
, &deltas
,
425 pack
, tmpfile
, delta_base_file
, delta_accum_file
);
429 err
= got_pack_dump_delta_chain_to_mem(&buf
, &len
,
435 err
= got_delta_chain_get_base_type(&base_obj_type
, &deltas
);
438 err
= get_obj_type_label(&obj_label
, base_obj_type
);
441 if (asprintf(&header
, "%s %zd", obj_label
, len
) == -1) {
442 err
= got_error_from_errno("asprintf");
445 headerlen
= strlen(header
) + 1;
447 SHA1Update(&ctx
, header
, headerlen
);
448 if (max_size
> GOT_DELTA_RESULT_SIZE_CACHED_MAX
) {
449 err
= read_file_sha1(&ctx
, tmpfile
, len
);
453 SHA1Update(&ctx
, buf
, len
);
454 SHA1Final(obj
->id
.sha1
, &ctx
);
458 while (!STAILQ_EMPTY(&deltas
.entries
)) {
459 delta
= STAILQ_FIRST(&deltas
.entries
);
460 STAILQ_REMOVE_HEAD(&deltas
.entries
, entry
);
466 /* Determine the slot in the pack index a given object ID should use. */
468 find_object_idx(struct got_packidx
*packidx
, uint8_t *sha1
)
470 u_int8_t id0
= sha1
[0];
471 uint32_t nindexed
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
472 int left
= 0, right
= nindexed
- 1;
476 left
= be32toh(packidx
->hdr
.fanout_table
[id0
- 1]);
478 while (left
<= right
) {
479 struct got_packidx_object_id
*oid
;
481 i
= ((left
+ right
) / 2);
482 oid
= &packidx
->hdr
.sorted_ids
[i
];
484 cmp
= memcmp(sha1
, oid
->sha1
, SHA1_DIGEST_LENGTH
);
486 return -1; /* object already indexed */
498 print_packidx(struct got_packidx
*packidx
)
500 uint32_t nindexed
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
503 fprintf(stderr
, "object IDs:\n");
504 for (i
= 0; i
< nindexed
; i
++) {
505 char hex
[SHA1_DIGEST_STRING_LENGTH
];
506 got_sha1_digest_to_str(packidx
->hdr
.sorted_ids
[i
].sha1
,
508 fprintf(stderr
, "%s\n", hex
);
510 fprintf(stderr
, "\n");
512 fprintf(stderr
, "object offsets:\n");
513 for (i
= 0; i
< nindexed
; i
++) {
514 uint32_t offset
= be32toh(packidx
->hdr
.offsets
[i
]);
515 if (offset
& GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
) {
516 int j
= offset
& GOT_PACKIDX_OFFSET_VAL_MASK
;
517 fprintf(stderr
, "%u -> %llu\n", offset
,
518 be64toh(packidx
->hdr
.large_offsets
[j
]));
520 fprintf(stderr
, "%u\n", offset
);
522 fprintf(stderr
, "\n");
524 fprintf(stderr
, "fanout table:");
525 for (i
= 0; i
<= 0xff; i
++)
526 fprintf(stderr
, " %u", be32toh(packidx
->hdr
.fanout_table
[i
]));
527 fprintf(stderr
, "\n");
532 add_indexed_object(struct got_packidx
*packidx
, uint32_t idx
,
533 struct got_indexed_object
*obj
)
537 memcpy(packidx
->hdr
.sorted_ids
[idx
].sha1
, obj
->id
.sha1
,
539 packidx
->hdr
.crc32
[idx
] = htobe32(obj
->crc
);
540 if (obj
->off
< GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
)
541 packidx
->hdr
.offsets
[idx
] = htobe32(obj
->off
);
543 packidx
->hdr
.offsets
[idx
] = htobe32(packidx
->nlargeobj
|
544 GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
);
545 packidx
->hdr
.large_offsets
[packidx
->nlargeobj
] =
547 packidx
->nlargeobj
++;
550 for (i
= obj
->id
.sha1
[0]; i
<= 0xff; i
++) {
551 uint32_t n
= be32toh(packidx
->hdr
.fanout_table
[i
]);
552 packidx
->hdr
.fanout_table
[i
] = htobe32(n
+ 1);
557 indexed_obj_cmp(const void *pa
, const void *pb
)
559 struct got_indexed_object
*a
, *b
;
561 a
= (struct got_indexed_object
*)pa
;
562 b
= (struct got_indexed_object
*)pb
;
563 return got_object_id_cmp(&a
->id
, &b
->id
);
567 make_packidx(struct got_packidx
*packidx
, uint32_t nobj
,
568 struct got_indexed_object
*objects
)
570 struct got_indexed_object
*obj
;
574 qsort(objects
, nobj
, sizeof(struct got_indexed_object
),
577 memset(packidx
->hdr
.fanout_table
, 0,
578 GOT_PACKIDX_V2_FANOUT_TABLE_ITEMS
* sizeof(uint32_t));
579 packidx
->nlargeobj
= 0;
581 for (i
= 0; i
< nobj
; i
++) {
584 add_indexed_object(packidx
, idx
++, obj
);
589 update_packidx(struct got_packidx
*packidx
, uint32_t nobj
,
590 struct got_indexed_object
*obj
)
593 uint32_t nindexed
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
595 idx
= find_object_idx(packidx
, obj
->id
.sha1
);
597 char hex
[SHA1_DIGEST_STRING_LENGTH
];
598 got_sha1_digest_to_str(obj
->id
.sha1
, hex
, sizeof(hex
));
599 return; /* object already indexed */
602 memmove(&packidx
->hdr
.sorted_ids
[idx
+ 1],
603 &packidx
->hdr
.sorted_ids
[idx
],
604 sizeof(struct got_packidx_object_id
) * (nindexed
- idx
));
605 memmove(&packidx
->hdr
.offsets
[idx
+ 1], &packidx
->hdr
.offsets
[idx
],
606 sizeof(uint32_t) * (nindexed
- idx
));
608 add_indexed_object(packidx
, idx
, obj
);
611 static const struct got_error
*
612 report_progress(uint32_t nobj_total
, uint32_t nobj_indexed
, uint32_t nobj_loose
,
613 uint32_t nobj_resolved
, struct got_ratelimit
*rl
,
614 got_pack_index_progress_cb progress_cb
, void *progress_arg
)
616 const struct got_error
*err
;
620 err
= got_ratelimit_check(&elapsed
, rl
);
625 return progress_cb(progress_arg
, nobj_total
, nobj_indexed
, nobj_loose
,
629 const struct got_error
*
630 got_pack_index(struct got_pack
*pack
, int idxfd
, FILE *tmpfile
,
631 FILE *delta_base_file
, FILE *delta_accum_file
, uint8_t *pack_sha1_expected
,
632 got_pack_index_progress_cb progress_cb
, void *progress_arg
,
633 struct got_ratelimit
*rl
)
635 const struct got_error
*err
;
636 struct got_packfile_hdr hdr
;
637 struct got_packidx packidx
;
639 char pack_sha1
[SHA1_DIGEST_LENGTH
];
640 uint32_t nobj
, nvalid
, nloose
, nresolved
= 0, i
;
641 struct got_indexed_object
*objects
= NULL
, *obj
;
643 uint8_t packidx_hash
[SHA1_DIGEST_LENGTH
];
645 int pass
, have_ref_deltas
= 0, first_delta_idx
= -1;
647 int p_indexed
= 0, last_p_indexed
= -1;
648 int p_resolved
= 0, last_p_resolved
= -1;
650 /* Require that pack file header and SHA1 trailer are present. */
651 if (pack
->filesize
< sizeof(hdr
) + SHA1_DIGEST_LENGTH
)
652 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
656 memcpy(&hdr
, pack
->map
, sizeof(hdr
));
657 mapoff
+= sizeof(hdr
);
659 r
= read(pack
->fd
, &hdr
, sizeof(hdr
));
661 return got_error_from_errno("read");
663 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
667 if (hdr
.signature
!= htobe32(GOT_PACKFILE_SIGNATURE
))
668 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
669 "bad packfile signature");
670 if (hdr
.version
!= htobe32(GOT_PACKFILE_VERSION
))
671 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
672 "bad packfile version");
673 nobj
= be32toh(hdr
.nobjects
);
675 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
676 "bad packfile with zero objects");
678 /* We compute the SHA1 of pack file contents and verify later on. */
680 SHA1Update(&ctx
, (void *)&hdr
, sizeof(hdr
));
683 * Create an in-memory pack index which will grow as objects
684 * IDs in the pack file are discovered. Only fields used to
685 * read deltified objects will be needed by the pack.c library
686 * code, so setting up just a pack index header is sufficient.
688 memset(&packidx
, 0, sizeof(packidx
));
689 packidx
.hdr
.magic
= malloc(sizeof(uint32_t));
690 if (packidx
.hdr
.magic
== NULL
)
691 return got_error_from_errno("malloc");
692 *packidx
.hdr
.magic
= htobe32(GOT_PACKIDX_V2_MAGIC
);
693 packidx
.hdr
.version
= malloc(sizeof(uint32_t));
694 if (packidx
.hdr
.version
== NULL
) {
695 err
= got_error_from_errno("malloc");
698 *packidx
.hdr
.version
= htobe32(GOT_PACKIDX_VERSION
);
699 packidx
.hdr
.fanout_table
= calloc(GOT_PACKIDX_V2_FANOUT_TABLE_ITEMS
,
701 if (packidx
.hdr
.fanout_table
== NULL
) {
702 err
= got_error_from_errno("calloc");
705 packidx
.hdr
.sorted_ids
= calloc(nobj
,
706 sizeof(struct got_packidx_object_id
));
707 if (packidx
.hdr
.sorted_ids
== NULL
) {
708 err
= got_error_from_errno("calloc");
711 packidx
.hdr
.crc32
= calloc(nobj
, sizeof(uint32_t));
712 if (packidx
.hdr
.crc32
== NULL
) {
713 err
= got_error_from_errno("calloc");
716 packidx
.hdr
.offsets
= calloc(nobj
, sizeof(uint32_t));
717 if (packidx
.hdr
.offsets
== NULL
) {
718 err
= got_error_from_errno("calloc");
721 /* Large offsets table is empty for pack files < 2 GB. */
722 if (pack
->filesize
>= GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
) {
723 packidx
.hdr
.large_offsets
= calloc(nobj
, sizeof(uint64_t));
724 if (packidx
.hdr
.large_offsets
== NULL
) {
725 err
= got_error_from_errno("calloc");
732 objects
= calloc(nobj
, sizeof(struct got_indexed_object
));
734 return got_error_from_errno("calloc");
737 * First pass: locate all objects and identify un-deltified objects.
739 * When this pass has completed we will know offset, type, size, and
740 * CRC information for all objects in this pack file. We won't know
741 * any of the actual object IDs of deltified objects yet since we
742 * will not yet attempt to combine deltas.
745 for (i
= 0; i
< nobj
; i
++) {
746 /* Don't send too many progress privsep messages. */
747 p_indexed
= ((i
+ 1) * 100) / nobj
;
748 if (p_indexed
!= last_p_indexed
) {
749 err
= report_progress(nobj
, i
+ 1, nloose
, 0,
750 rl
, progress_cb
, progress_arg
);
753 last_p_indexed
= p_indexed
;
757 obj
->crc
= crc32(0L, NULL
, 0);
759 /* Store offset to type+size information for this object. */
763 obj
->off
= lseek(pack
->fd
, 0, SEEK_CUR
);
764 if (obj
->off
== -1) {
765 err
= got_error_from_errno("lseek");
770 err
= read_packed_object(pack
, obj
, tmpfile
, &ctx
);
775 mapoff
+= obj
->tslen
+ obj
->len
;
777 if (lseek(pack
->fd
, obj
->off
+ obj
->tslen
+ obj
->len
,
779 err
= got_error_from_errno("lseek");
784 if (obj
->type
== GOT_OBJ_TYPE_BLOB
||
785 obj
->type
== GOT_OBJ_TYPE_TREE
||
786 obj
->type
== GOT_OBJ_TYPE_COMMIT
||
787 obj
->type
== GOT_OBJ_TYPE_TAG
) {
791 if (first_delta_idx
== -1)
793 if (obj
->type
== GOT_OBJ_TYPE_REF_DELTA
)
800 * Having done a full pass over the pack file and can now
801 * verify its checksum.
803 SHA1Final(pack_sha1
, &ctx
);
805 if (memcmp(pack_sha1_expected
, pack_sha1
, SHA1_DIGEST_LENGTH
) != 0) {
806 err
= got_error(GOT_ERR_PACKFILE_CSUM
);
810 /* Verify the SHA1 checksum stored at the end of the pack file. */
812 if (pack
->filesize
> SIZE_MAX
) {
813 err
= got_error_fmt(GOT_ERR_RANGE
,
814 "filesize %lld overflows size_t",
815 (long long)pack
->filesize
);
819 memcpy(pack_sha1_expected
, pack
->map
+
820 pack
->filesize
- SHA1_DIGEST_LENGTH
,
824 if (lseek(pack
->fd
, -SHA1_DIGEST_LENGTH
, SEEK_END
) == -1) {
825 err
= got_error_from_errno("lseek");
828 n
= read(pack
->fd
, pack_sha1_expected
, SHA1_DIGEST_LENGTH
);
830 err
= got_error_from_errno("read");
833 if (n
!= SHA1_DIGEST_LENGTH
) {
834 err
= got_error(GOT_ERR_IO
);
838 if (memcmp(pack_sha1
, pack_sha1_expected
, SHA1_DIGEST_LENGTH
) != 0) {
839 err
= got_error_msg(GOT_ERR_BAD_PACKFILE
,
840 "bad checksum in pack file trailer");
844 if (first_delta_idx
== -1)
847 /* In order to resolve ref deltas we need an in-progress pack index. */
849 make_packidx(&packidx
, nobj
, objects
);
852 * Second pass: We can now resolve deltas to compute the IDs of
853 * objects which appear in deltified form. Because deltas can be
854 * chained this pass may require a couple of iterations until all
855 * IDs of deltified objects have been discovered.
858 while (nvalid
!= nobj
) {
861 * This loop will only run once unless the pack file
862 * contains ref deltas which refer to objects located
863 * later in the pack file, which is unusual.
864 * Offset deltas can always be resolved in one pass
865 * unless the packfile is corrupt.
867 for (i
= first_delta_idx
; i
< nobj
; i
++) {
869 if (obj
->type
!= GOT_OBJ_TYPE_REF_DELTA
&&
870 obj
->type
!= GOT_OBJ_TYPE_OFFSET_DELTA
)
876 if (pack
->map
== NULL
&& lseek(pack
->fd
,
877 obj
->off
+ obj
->tslen
, SEEK_SET
) == -1) {
878 err
= got_error_from_errno("lseek");
882 err
= resolve_deltified_object(pack
, &packidx
, obj
,
883 tmpfile
, delta_base_file
, delta_accum_file
);
885 if (err
->code
!= GOT_ERR_NO_OBJ
)
888 * We cannot resolve this object yet because
889 * a delta base is unknown. Try again later.
897 update_packidx(&packidx
, nobj
, obj
);
898 /* Don't send too many progress privsep messages. */
899 p_resolved
= ((nresolved
+ n
) * 100) / nobj
;
900 if (p_resolved
!= last_p_resolved
) {
901 err
= report_progress(nobj
, nobj
,
902 nloose
, nresolved
+ n
, rl
,
903 progress_cb
, progress_arg
);
906 last_p_resolved
= p_resolved
;
910 if (pass
++ > 3 && n
== 0) {
911 err
= got_error_msg(GOT_ERR_BAD_PACKFILE
,
912 "could not resolve any of deltas; packfile could "
920 if (nloose
+ nresolved
!= nobj
) {
922 snprintf(msg
, sizeof(msg
), "discovered only %d of %d objects",
923 nloose
+ nresolved
, nobj
);
924 err
= got_error_msg(GOT_ERR_BAD_PACKFILE
, msg
);
928 err
= report_progress(nobj
, nobj
, nloose
, nresolved
, NULL
,
929 progress_cb
, progress_arg
);
933 make_packidx(&packidx
, nobj
, objects
);
939 putbe32(buf
, GOT_PACKIDX_V2_MAGIC
);
940 putbe32(buf
+ 4, GOT_PACKIDX_VERSION
);
941 err
= got_pack_hwrite(idxfd
, buf
, 8, &ctx
);
944 err
= got_pack_hwrite(idxfd
, packidx
.hdr
.fanout_table
,
945 GOT_PACKIDX_V2_FANOUT_TABLE_ITEMS
* sizeof(uint32_t), &ctx
);
948 err
= got_pack_hwrite(idxfd
, packidx
.hdr
.sorted_ids
,
949 nobj
* SHA1_DIGEST_LENGTH
, &ctx
);
952 err
= got_pack_hwrite(idxfd
, packidx
.hdr
.crc32
,
953 nobj
* sizeof(uint32_t), &ctx
);
956 err
= got_pack_hwrite(idxfd
, packidx
.hdr
.offsets
,
957 nobj
* sizeof(uint32_t), &ctx
);
960 if (packidx
.nlargeobj
> 0) {
961 err
= got_pack_hwrite(idxfd
, packidx
.hdr
.large_offsets
,
962 packidx
.nlargeobj
* sizeof(uint64_t), &ctx
);
966 err
= got_pack_hwrite(idxfd
, pack_sha1
, SHA1_DIGEST_LENGTH
, &ctx
);
970 SHA1Final(packidx_hash
, &ctx
);
971 w
= write(idxfd
, packidx_hash
, sizeof(packidx_hash
));
973 err
= got_error_from_errno("write");
976 if (w
!= sizeof(packidx_hash
)) {
977 err
= got_error(GOT_ERR_IO
);
982 free(packidx
.hdr
.magic
);
983 free(packidx
.hdr
.version
);
984 free(packidx
.hdr
.fanout_table
);
985 free(packidx
.hdr
.sorted_ids
);
986 free(packidx
.hdr
.offsets
);
987 free(packidx
.hdr
.large_offsets
);