2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #include "got_compat.h"
18 #include <sys/types.h>
20 #include <sys/queue.h>
23 #include <sys/resource.h>
24 #include <sys/socket.h>
36 #include "got_error.h"
37 #include "got_object.h"
40 #include "got_lib_hash.h"
41 #include "got_lib_delta.h"
42 #include "got_lib_delta_cache.h"
43 #include "got_lib_inflate.h"
44 #include "got_lib_object.h"
45 #include "got_lib_object_qid.h"
46 #include "got_lib_object_parse.h"
47 #include "got_lib_privsep.h"
48 #include "got_lib_pack.h"
51 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
55 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
58 static const struct got_error
*
59 verify_fanout_table(uint32_t *fanout_table
)
63 for (i
= 0; i
< 0xff - 1; i
++) {
64 if (be32toh(fanout_table
[i
]) > be32toh(fanout_table
[i
+ 1]))
65 return got_error(GOT_ERR_BAD_PACKIDX
);
71 const struct got_error
*
72 got_packidx_init_hdr(struct got_packidx
*p
, int verify
, off_t packfile_size
)
74 const struct got_error
*err
= NULL
;
75 enum got_hash_algorithm algo
= GOT_HASH_SHA1
;
76 struct got_packidx_v2_hdr
*h
;
78 uint8_t hash
[GOT_HASH_DIGEST_MAXLEN
];
79 size_t nobj
, len_fanout
, len_ids
, offset
, remain
;
83 got_hash_init(&ctx
, algo
);
89 if (remain
< sizeof(*h
->magic
)) {
90 err
= got_error(GOT_ERR_BAD_PACKIDX
);
94 h
->magic
= (uint32_t *)(p
->map
+ offset
);
96 h
->magic
= malloc(sizeof(*h
->magic
));
97 if (h
->magic
== NULL
) {
98 err
= got_error_from_errno("malloc");
101 n
= read(p
->fd
, h
->magic
, sizeof(*h
->magic
));
103 err
= got_error_from_errno("read");
105 } else if (n
!= sizeof(*h
->magic
)) {
106 err
= got_error(GOT_ERR_BAD_PACKIDX
);
110 if (*h
->magic
!= htobe32(GOT_PACKIDX_V2_MAGIC
)) {
111 err
= got_error(GOT_ERR_BAD_PACKIDX
);
114 offset
+= sizeof(*h
->magic
);
115 remain
-= sizeof(*h
->magic
);
118 got_hash_update(&ctx
, h
->magic
, sizeof(*h
->magic
));
120 if (remain
< sizeof(*h
->version
)) {
121 err
= got_error(GOT_ERR_BAD_PACKIDX
);
125 h
->version
= (uint32_t *)(p
->map
+ offset
);
127 h
->version
= malloc(sizeof(*h
->version
));
128 if (h
->version
== NULL
) {
129 err
= got_error_from_errno("malloc");
132 n
= read(p
->fd
, h
->version
, sizeof(*h
->version
));
134 err
= got_error_from_errno("read");
136 } else if (n
!= sizeof(*h
->version
)) {
137 err
= got_error(GOT_ERR_BAD_PACKIDX
);
141 if (*h
->version
!= htobe32(GOT_PACKIDX_VERSION
)) {
142 err
= got_error(GOT_ERR_BAD_PACKIDX
);
145 offset
+= sizeof(*h
->version
);
146 remain
-= sizeof(*h
->version
);
149 got_hash_update(&ctx
, h
->version
, sizeof(*h
->version
));
152 sizeof(*h
->fanout_table
) * GOT_PACKIDX_V2_FANOUT_TABLE_ITEMS
;
153 if (remain
< len_fanout
) {
154 err
= got_error(GOT_ERR_BAD_PACKIDX
);
158 h
->fanout_table
= (uint32_t *)(p
->map
+ offset
);
160 h
->fanout_table
= malloc(len_fanout
);
161 if (h
->fanout_table
== NULL
) {
162 err
= got_error_from_errno("malloc");
165 n
= read(p
->fd
, h
->fanout_table
, len_fanout
);
167 err
= got_error_from_errno("read");
169 } else if (n
!= len_fanout
) {
170 err
= got_error(GOT_ERR_BAD_PACKIDX
);
174 err
= verify_fanout_table(h
->fanout_table
);
178 got_hash_update(&ctx
, h
->fanout_table
, len_fanout
);
179 offset
+= len_fanout
;
180 remain
-= len_fanout
;
182 nobj
= be32toh(h
->fanout_table
[0xff]);
183 len_ids
= nobj
* sizeof(*h
->sorted_ids
);
184 if (len_ids
<= nobj
|| len_ids
> remain
) {
185 err
= got_error(GOT_ERR_BAD_PACKIDX
);
190 (struct got_packidx_object_id
*)((uint8_t*)(p
->map
+ offset
));
192 h
->sorted_ids
= malloc(len_ids
);
193 if (h
->sorted_ids
== NULL
) {
194 err
= got_error(GOT_ERR_BAD_PACKIDX
);
197 n
= read(p
->fd
, h
->sorted_ids
, len_ids
);
199 err
= got_error_from_errno("read");
200 else if (n
!= len_ids
) {
201 err
= got_error(GOT_ERR_BAD_PACKIDX
);
206 got_hash_update(&ctx
, h
->sorted_ids
, len_ids
);
210 if (remain
< nobj
* sizeof(*h
->crc32
)) {
211 err
= got_error(GOT_ERR_BAD_PACKIDX
);
215 h
->crc32
= (uint32_t *)((uint8_t*)(p
->map
+ offset
));
217 h
->crc32
= malloc(nobj
* sizeof(*h
->crc32
));
218 if (h
->crc32
== NULL
) {
219 err
= got_error_from_errno("malloc");
222 n
= read(p
->fd
, h
->crc32
, nobj
* sizeof(*h
->crc32
));
224 err
= got_error_from_errno("read");
225 else if (n
!= nobj
* sizeof(*h
->crc32
)) {
226 err
= got_error(GOT_ERR_BAD_PACKIDX
);
231 got_hash_update(&ctx
, h
->crc32
, nobj
* sizeof(*h
->crc32
));
232 remain
-= nobj
* sizeof(*h
->crc32
);
233 offset
+= nobj
* sizeof(*h
->crc32
);
235 if (remain
< nobj
* sizeof(*h
->offsets
)) {
236 err
= got_error(GOT_ERR_BAD_PACKIDX
);
240 h
->offsets
= (uint32_t *)((uint8_t*)(p
->map
+ offset
));
242 h
->offsets
= malloc(nobj
* sizeof(*h
->offsets
));
243 if (h
->offsets
== NULL
) {
244 err
= got_error_from_errno("malloc");
247 n
= read(p
->fd
, h
->offsets
, nobj
* sizeof(*h
->offsets
));
249 err
= got_error_from_errno("read");
250 else if (n
!= nobj
* sizeof(*h
->offsets
)) {
251 err
= got_error(GOT_ERR_BAD_PACKIDX
);
256 got_hash_update(&ctx
, h
->offsets
, nobj
* sizeof(*h
->offsets
));
257 remain
-= nobj
* sizeof(*h
->offsets
);
258 offset
+= nobj
* sizeof(*h
->offsets
);
260 /* Large file offsets are contained only in files > 2GB. */
261 if (verify
|| packfile_size
> 0x7fffffff) {
262 for (i
= 0; i
< nobj
; i
++) {
263 uint32_t o
= h
->offsets
[i
];
264 if (o
& htobe32(GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
))
268 if (p
->nlargeobj
== 0)
270 else if (packfile_size
<= 0x7fffffff) {
271 err
= got_error(GOT_ERR_BAD_PACKIDX
);
275 if (remain
< p
->nlargeobj
* sizeof(*h
->large_offsets
)) {
276 err
= got_error(GOT_ERR_BAD_PACKIDX
);
280 h
->large_offsets
= (uint64_t *)((uint8_t*)(p
->map
+ offset
));
282 h
->large_offsets
= malloc(p
->nlargeobj
*
283 sizeof(*h
->large_offsets
));
284 if (h
->large_offsets
== NULL
) {
285 err
= got_error_from_errno("malloc");
288 n
= read(p
->fd
, h
->large_offsets
,
289 p
->nlargeobj
* sizeof(*h
->large_offsets
));
291 err
= got_error_from_errno("read");
292 else if (n
!= p
->nlargeobj
* sizeof(*h
->large_offsets
)) {
293 err
= got_error(GOT_ERR_BAD_PACKIDX
);
298 got_hash_update(&ctx
, h
->large_offsets
,
299 p
->nlargeobj
* sizeof(*h
->large_offsets
));
300 remain
-= p
->nlargeobj
* sizeof(*h
->large_offsets
);
301 offset
+= p
->nlargeobj
* sizeof(*h
->large_offsets
);
304 if (remain
< sizeof(*h
->trailer
)) {
305 err
= got_error(GOT_ERR_BAD_PACKIDX
);
310 (struct got_packidx_trailer
*)((uint8_t*)(p
->map
+ offset
));
312 h
->trailer
= malloc(sizeof(*h
->trailer
));
313 if (h
->trailer
== NULL
) {
314 err
= got_error_from_errno("malloc");
317 n
= read(p
->fd
, h
->trailer
, sizeof(*h
->trailer
));
319 err
= got_error_from_errno("read");
320 else if (n
!= sizeof(*h
->trailer
)) {
321 err
= got_error(GOT_ERR_BAD_PACKIDX
);
326 got_hash_update(&ctx
, h
->trailer
->packfile_sha1
,
328 got_hash_final(&ctx
, hash
);
329 if (got_hash_cmp(ctx
.algo
, hash
, h
->trailer
->packidx_sha1
) != 0)
330 err
= got_error(GOT_ERR_PACKIDX_CSUM
);
336 const struct got_error
*
337 got_packidx_open(struct got_packidx
**packidx
,
338 int dir_fd
, const char *relpath
, int verify
)
340 const struct got_error
*err
= NULL
;
341 struct got_packidx
*p
= NULL
;
343 struct stat idx_sb
, pack_sb
;
347 err
= got_packidx_get_packfile_path(&pack_relpath
, relpath
);
352 * Ensure that a corresponding pack file exists.
353 * Some Git repositories have this problem. Git seems to ignore
354 * the existence of lonely pack index files but we do not.
356 if (fstatat(dir_fd
, pack_relpath
, &pack_sb
, 0) == -1) {
357 if (errno
== ENOENT
) {
358 err
= got_error_fmt(GOT_ERR_LONELY_PACKIDX
,
361 err
= got_error_from_errno2("fstatat", pack_relpath
);
365 p
= calloc(1, sizeof(*p
));
367 err
= got_error_from_errno("calloc");
371 p
->fd
= openat(dir_fd
, relpath
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
373 err
= got_error_from_errno2("openat", relpath
);
377 if (fstat(p
->fd
, &idx_sb
) != 0) {
378 err
= got_error_from_errno2("fstat", relpath
);
381 p
->len
= idx_sb
.st_size
;
382 if (p
->len
< sizeof(p
->hdr
)) {
383 err
= got_error(GOT_ERR_BAD_PACKIDX
);
387 p
->path_packidx
= strdup(relpath
);
388 if (p
->path_packidx
== NULL
) {
389 err
= got_error_from_errno("strdup");
393 #ifndef GOT_PACK_NO_MMAP
394 if (p
->len
> 0 && p
->len
<= SIZE_MAX
) {
395 p
->map
= mmap(NULL
, p
->len
, PROT_READ
, MAP_PRIVATE
, p
->fd
, 0);
396 if (p
->map
== MAP_FAILED
) {
397 if (errno
!= ENOMEM
) {
398 err
= got_error_from_errno("mmap");
401 p
->map
= NULL
; /* fall back to read(2) */
406 err
= got_packidx_init_hdr(p
, verify
, pack_sb
.st_size
);
410 got_packidx_close(p
);
417 const struct got_error
*
418 got_packidx_close(struct got_packidx
*packidx
)
420 const struct got_error
*err
= NULL
;
422 free(packidx
->path_packidx
);
424 if (munmap(packidx
->map
, packidx
->len
) == -1)
425 err
= got_error_from_errno("munmap");
427 free(packidx
->hdr
.magic
);
428 free(packidx
->hdr
.version
);
429 free(packidx
->hdr
.fanout_table
);
430 free(packidx
->hdr
.sorted_ids
);
431 free(packidx
->hdr
.crc32
);
432 free(packidx
->hdr
.offsets
);
433 free(packidx
->hdr
.large_offsets
);
434 free(packidx
->hdr
.trailer
);
436 if (close(packidx
->fd
) == -1 && err
== NULL
)
437 err
= got_error_from_errno("close");
438 free(packidx
->sorted_offsets
);
439 free(packidx
->sorted_large_offsets
);
445 const struct got_error
*
446 got_packidx_get_packfile_path(char **path_packfile
, const char *path_packidx
)
450 /* Packfile path contains ".pack" instead of ".idx", so add one byte. */
451 size
= strlen(path_packidx
) + 2;
452 if (size
< GOT_PACKFILE_NAMELEN
+ 1)
453 return got_error_path(path_packidx
, GOT_ERR_BAD_PATH
);
455 *path_packfile
= malloc(size
);
456 if (*path_packfile
== NULL
)
457 return got_error_from_errno("malloc");
459 /* Copy up to and excluding ".idx". */
460 if (strlcpy(*path_packfile
, path_packidx
,
461 size
- strlen(GOT_PACKIDX_SUFFIX
) - 1) >= size
)
462 return got_error(GOT_ERR_NO_SPACE
);
464 if (strlcat(*path_packfile
, GOT_PACKFILE_SUFFIX
, size
) >= size
)
465 return got_error(GOT_ERR_NO_SPACE
);
471 got_packidx_get_object_offset(struct got_packidx
*packidx
, int idx
)
473 uint32_t offset
= be32toh(packidx
->hdr
.offsets
[idx
]);
474 if (offset
& GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
) {
476 idx
= offset
& GOT_PACKIDX_OFFSET_VAL_MASK
;
477 if (idx
< 0 || idx
>= packidx
->nlargeobj
||
478 packidx
->hdr
.large_offsets
== NULL
)
480 loffset
= be64toh(packidx
->hdr
.large_offsets
[idx
]);
481 return (loffset
> INT64_MAX
? -1 : (off_t
)loffset
);
483 return (off_t
)(offset
& GOT_PACKIDX_OFFSET_VAL_MASK
);
487 got_packidx_get_object_idx(struct got_packidx
*packidx
,
488 struct got_object_id
*id
)
490 u_int8_t id0
= id
->sha1
[0];
491 uint32_t totobj
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
492 int left
= 0, right
= totobj
- 1;
495 left
= be32toh(packidx
->hdr
.fanout_table
[id0
- 1]);
497 while (left
<= right
) {
498 struct got_packidx_object_id
*oid
;
501 i
= ((left
+ right
) / 2);
502 oid
= &packidx
->hdr
.sorted_ids
[i
];
503 cmp
= memcmp(id
->sha1
, oid
->sha1
, SHA1_DIGEST_LENGTH
);
516 offset_cmp(const void *pa
, const void *pb
)
518 const struct got_pack_offset_index
*a
, *b
;
520 a
= (const struct got_pack_offset_index
*)pa
;
521 b
= (const struct got_pack_offset_index
*)pb
;
523 if (a
->offset
< b
->offset
)
525 else if (a
->offset
> b
->offset
)
532 large_offset_cmp(const void *pa
, const void *pb
)
534 const struct got_pack_large_offset_index
*a
, *b
;
536 a
= (const struct got_pack_large_offset_index
*)pa
;
537 b
= (const struct got_pack_large_offset_index
*)pb
;
539 if (a
->offset
< b
->offset
)
541 else if (a
->offset
> b
->offset
)
547 static const struct got_error
*
548 build_offset_index(struct got_packidx
*p
)
550 uint32_t nobj
= be32toh(p
->hdr
.fanout_table
[0xff]);
551 unsigned int i
, j
, k
;
553 p
->sorted_offsets
= calloc(nobj
- p
->nlargeobj
,
554 sizeof(p
->sorted_offsets
[0]));
555 if (p
->sorted_offsets
== NULL
)
556 return got_error_from_errno("calloc");
558 if (p
->nlargeobj
> 0) {
559 p
->sorted_large_offsets
= calloc(p
->nlargeobj
,
560 sizeof(p
->sorted_large_offsets
[0]));
561 if (p
->sorted_large_offsets
== NULL
)
562 return got_error_from_errno("calloc");
567 for (i
= 0; i
< nobj
; i
++) {
568 uint32_t offset
= be32toh(p
->hdr
.offsets
[i
]);
569 if (offset
& GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX
) {
572 idx
= offset
& GOT_PACKIDX_OFFSET_VAL_MASK
;
573 if (idx
>= p
->nlargeobj
||
575 p
->hdr
.large_offsets
== NULL
)
576 return got_error(GOT_ERR_BAD_PACKIDX
);
577 loffset
= be64toh(p
->hdr
.large_offsets
[idx
]);
578 p
->sorted_large_offsets
[j
].offset
= loffset
;
579 p
->sorted_large_offsets
[j
].idx
= i
;
582 p
->sorted_offsets
[k
].offset
= offset
;
583 p
->sorted_offsets
[k
].idx
= i
;
587 if (j
!= p
->nlargeobj
|| k
!= nobj
- p
->nlargeobj
)
588 return got_error(GOT_ERR_BAD_PACKIDX
);
590 qsort(p
->sorted_offsets
, nobj
- p
->nlargeobj
,
591 sizeof(p
->sorted_offsets
[0]), offset_cmp
);
593 if (p
->sorted_large_offsets
)
594 qsort(p
->sorted_large_offsets
, p
->nlargeobj
,
595 sizeof(p
->sorted_large_offsets
[0]), large_offset_cmp
);
600 const struct got_error
*
601 got_packidx_get_offset_idx(int *idx
, struct got_packidx
*packidx
, off_t offset
)
603 const struct got_error
*err
;
604 uint32_t totobj
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
609 if (packidx
->sorted_offsets
== NULL
) {
610 err
= build_offset_index(packidx
);
615 if (offset
>= 0x7fffffff) {
617 left
= 0, right
= packidx
->nlargeobj
- 1;
618 while (left
<= right
) {
619 i
= ((left
+ right
) / 2);
620 lo
= packidx
->sorted_large_offsets
[i
].offset
;
622 *idx
= packidx
->sorted_large_offsets
[i
].idx
;
624 } else if (offset
> lo
)
626 else if (offset
< lo
)
631 left
= 0, right
= totobj
- packidx
->nlargeobj
- 1;
632 while (left
<= right
) {
633 i
= ((left
+ right
) / 2);
634 o
= packidx
->sorted_offsets
[i
].offset
;
636 *idx
= packidx
->sorted_offsets
[i
].idx
;
638 } else if (offset
> o
)
648 const struct got_error
*
649 got_packidx_get_object_id(struct got_object_id
*id
,
650 struct got_packidx
*packidx
, int idx
)
652 uint32_t totobj
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
653 struct got_packidx_object_id
*oid
;
655 if (idx
< 0 || idx
>= totobj
)
656 return got_error(GOT_ERR_NO_OBJ
);
658 oid
= &packidx
->hdr
.sorted_ids
[idx
];
659 memcpy(id
->sha1
, oid
->sha1
, SHA1_DIGEST_LENGTH
);
663 const struct got_error
*
664 got_packidx_match_id_str_prefix(struct got_object_id_queue
*matched_ids
,
665 struct got_packidx
*packidx
, const char *id_str_prefix
)
667 const struct got_error
*err
= NULL
;
669 uint32_t totobj
= be32toh(packidx
->hdr
.fanout_table
[0xff]);
671 size_t prefix_len
= strlen(id_str_prefix
);
672 struct got_packidx_object_id
*oid
;
676 return got_error_path(id_str_prefix
, GOT_ERR_BAD_OBJ_ID_STR
);
678 hex
[0] = id_str_prefix
[0];
679 hex
[1] = id_str_prefix
[1];
681 if (!got_parse_xdigit(&id0
, hex
))
682 return got_error_path(id_str_prefix
, GOT_ERR_BAD_OBJ_ID_STR
);
685 i
= be32toh(packidx
->hdr
.fanout_table
[id0
- 1]);
686 oid
= &packidx
->hdr
.sorted_ids
[i
];
687 while (i
< totobj
&& oid
->sha1
[0] == id0
) {
688 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
689 struct got_object_qid
*qid
;
692 if (!got_sha1_digest_to_str(oid
->sha1
, id_str
, sizeof(id_str
)))
693 return got_error(GOT_ERR_NO_SPACE
);
695 cmp
= strncmp(id_str
, id_str_prefix
, prefix_len
);
697 oid
= &packidx
->hdr
.sorted_ids
[++i
];
702 err
= got_object_qid_alloc_partial(&qid
);
705 memcpy(qid
->id
.sha1
, oid
->sha1
, SHA1_DIGEST_LENGTH
);
706 STAILQ_INSERT_TAIL(matched_ids
, qid
, entry
);
708 oid
= &packidx
->hdr
.sorted_ids
[++i
];
715 set_max_datasize(void)
719 if (getrlimit(RLIMIT_DATA
, &rl
) != 0)
722 rl
.rlim_cur
= rl
.rlim_max
;
723 setrlimit(RLIMIT_DATA
, &rl
);
726 const struct got_error
*
727 got_pack_start_privsep_child(struct got_pack
*pack
, struct got_packidx
*packidx
)
729 const struct got_error
*err
= NULL
;
732 struct imsgbuf
*ibuf
;
734 ibuf
= calloc(1, sizeof(*ibuf
));
736 return got_error_from_errno("calloc");
738 pack
->privsep_child
= calloc(1, sizeof(*pack
->privsep_child
));
739 if (pack
->privsep_child
== NULL
) {
740 err
= got_error_from_errno("calloc");
744 pack
->child_has_tempfiles
= 0;
745 pack
->child_has_delta_outfd
= 0;
747 if (socketpair(AF_UNIX
, SOCK_STREAM
, PF_UNSPEC
, imsg_fds
) == -1) {
748 err
= got_error_from_errno("socketpair");
754 err
= got_error_from_errno("fork");
756 } else if (pid
== 0) {
758 got_privsep_exec_child(imsg_fds
, GOT_PATH_PROG_READ_PACK
,
759 pack
->path_packfile
);
763 if (close(imsg_fds
[1]) == -1)
764 return got_error_from_errno("close");
765 pack
->privsep_child
->imsg_fd
= imsg_fds
[0];
766 pack
->privsep_child
->pid
= pid
;
767 imsg_init(ibuf
, imsg_fds
[0]);
768 pack
->privsep_child
->ibuf
= ibuf
;
770 err
= got_privsep_init_pack_child(ibuf
, pack
, packidx
);
772 const struct got_error
*child_err
;
773 err
= got_privsep_send_stop(pack
->privsep_child
->imsg_fd
);
774 child_err
= got_privsep_wait_for_child(
775 pack
->privsep_child
->pid
);
776 if (child_err
&& err
== NULL
)
782 free(pack
->privsep_child
);
783 pack
->privsep_child
= NULL
;
788 static const struct got_error
*
789 pack_stop_privsep_child(struct got_pack
*pack
)
791 const struct got_error
*err
= NULL
, *close_err
= NULL
;
793 if (pack
->privsep_child
== NULL
)
796 err
= got_privsep_send_stop(pack
->privsep_child
->imsg_fd
);
799 if (close(pack
->privsep_child
->imsg_fd
) == -1)
800 close_err
= got_error_from_errno("close");
801 err
= got_privsep_wait_for_child(pack
->privsep_child
->pid
);
802 if (close_err
&& err
== NULL
)
804 imsg_clear(pack
->privsep_child
->ibuf
);
805 free(pack
->privsep_child
->ibuf
);
806 free(pack
->privsep_child
);
807 pack
->privsep_child
= NULL
;
811 const struct got_error
*
812 got_pack_close(struct got_pack
*pack
)
814 const struct got_error
*err
= NULL
;
816 err
= pack_stop_privsep_child(pack
);
817 if (pack
->map
&& munmap(pack
->map
, pack
->filesize
) == -1 && !err
)
818 err
= got_error_from_errno("munmap");
819 if (pack
->fd
!= -1 && close(pack
->fd
) == -1 && err
== NULL
)
820 err
= got_error_from_errno("close");
822 free(pack
->path_packfile
);
823 pack
->path_packfile
= NULL
;
825 if (pack
->delta_cache
) {
826 got_delta_cache_free(pack
->delta_cache
);
827 pack
->delta_cache
= NULL
;
831 * Leave accumfd and basefd alone. They are managed by the
832 * repository layer and can be reused.
838 const struct got_error
*
839 got_pack_parse_object_type_and_size(uint8_t *type
, uint64_t *size
, size_t *len
,
840 struct got_pack
*pack
, off_t offset
)
850 if (offset
>= pack
->filesize
)
851 return got_error(GOT_ERR_PACK_OFFSET
);
854 if (offset
> SIZE_MAX
) {
855 return got_error_fmt(GOT_ERR_PACK_OFFSET
,
856 "offset %lld overflows size_t",
860 mapoff
= (size_t)offset
;
862 if (lseek(pack
->fd
, offset
, SEEK_SET
) == -1)
863 return got_error_from_errno("lseek");
867 /* We do not support size values which don't fit in 64 bit. */
869 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
870 "packfile offset %lld", (long long)offset
);
873 if (mapoff
+ sizeof(sizeN
) >= pack
->filesize
)
874 return got_error(GOT_ERR_BAD_PACKFILE
);
875 sizeN
= *(pack
->map
+ mapoff
);
876 mapoff
+= sizeof(sizeN
);
878 ssize_t n
= read(pack
->fd
, &sizeN
, sizeof(sizeN
));
880 return got_error_from_errno("read");
881 if (n
!= sizeof(sizeN
))
882 return got_error(GOT_ERR_BAD_PACKFILE
);
884 *len
+= sizeof(sizeN
);
887 t
= (sizeN
& GOT_PACK_OBJ_SIZE0_TYPE_MASK
) >>
888 GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT
;
889 s
= (sizeN
& GOT_PACK_OBJ_SIZE0_VAL_MASK
);
891 size_t shift
= 4 + 7 * (i
- 1);
892 s
|= ((sizeN
& GOT_PACK_OBJ_SIZE_VAL_MASK
) << shift
);
895 } while (sizeN
& GOT_PACK_OBJ_SIZE_MORE
);
902 static const struct got_error
*
903 open_plain_object(struct got_object
**obj
, struct got_object_id
*id
,
904 uint8_t type
, off_t offset
, size_t size
, int idx
)
906 *obj
= calloc(1, sizeof(**obj
));
908 return got_error_from_errno("calloc");
911 (*obj
)->flags
= GOT_OBJ_FLAG_PACKED
;
912 (*obj
)->pack_idx
= idx
;
915 memcpy(&(*obj
)->id
, id
, sizeof((*obj
)->id
));
916 (*obj
)->pack_offset
= offset
;
921 static const struct got_error
*
922 parse_negative_offset(int64_t *offset
, size_t *len
, struct got_pack
*pack
,
933 /* We do not support offset values which don't fit in 64 bit. */
935 return got_error(GOT_ERR_NO_SPACE
);
940 if (delta_offset
+ *len
> SIZE_MAX
) {
941 return got_error_fmt(GOT_ERR_PACK_OFFSET
,
942 "mapoff %lld would overflow size_t",
943 (long long)delta_offset
+ *len
);
946 mapoff
= (size_t)delta_offset
+ *len
;
947 if (mapoff
+ sizeof(offN
) >= pack
->filesize
)
948 return got_error(GOT_ERR_PACK_OFFSET
);
949 offN
= *(pack
->map
+ mapoff
);
952 n
= read(pack
->fd
, &offN
, sizeof(offN
));
954 return got_error_from_errno("read");
955 if (n
!= sizeof(offN
))
956 return got_error(GOT_ERR_BAD_PACKFILE
);
958 *len
+= sizeof(offN
);
961 o
= (offN
& GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
965 o
+= (offN
& GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
968 } while (offN
& GOT_PACK_OBJ_DELTA_OFF_MORE
);
974 const struct got_error
*
975 got_pack_parse_offset_delta(off_t
*base_offset
, size_t *len
,
976 struct got_pack
*pack
, off_t offset
, size_t tslen
)
978 const struct got_error
*err
;
984 err
= parse_negative_offset(&negoffset
, &negofflen
, pack
,
989 /* Compute the base object's offset (must be in the same pack file). */
990 *base_offset
= (offset
- negoffset
);
991 if (*base_offset
<= 0)
992 return got_error(GOT_ERR_BAD_PACKFILE
);
998 static const struct got_error
*
999 read_delta_data(uint8_t **delta_buf
, size_t *delta_len
,
1000 size_t *delta_compressed_len
, size_t delta_data_offset
,
1001 struct got_pack
*pack
)
1003 const struct got_error
*err
= NULL
;
1004 size_t consumed
= 0;
1007 if (delta_data_offset
>= pack
->filesize
)
1008 return got_error(GOT_ERR_PACK_OFFSET
);
1009 err
= got_inflate_to_mem_mmap(delta_buf
, delta_len
,
1010 &consumed
, NULL
, pack
->map
, delta_data_offset
,
1011 pack
->filesize
- delta_data_offset
);
1015 if (lseek(pack
->fd
, delta_data_offset
, SEEK_SET
) == -1)
1016 return got_error_from_errno("lseek");
1017 err
= got_inflate_to_mem_fd(delta_buf
, delta_len
,
1018 &consumed
, NULL
, 0, pack
->fd
);
1023 if (delta_compressed_len
)
1024 *delta_compressed_len
= consumed
;
1029 static const struct got_error
*
1030 add_delta(struct got_delta_chain
*deltas
, off_t delta_offset
, size_t tslen
,
1031 int delta_type
, size_t delta_size
, off_t delta_data_offset
)
1033 struct got_delta
*delta
;
1035 delta
= got_delta_open(delta_offset
, tslen
, delta_type
, delta_size
,
1038 return got_error_from_errno("got_delta_open");
1039 /* delta is freed in got_object_close() */
1041 STAILQ_INSERT_HEAD(&deltas
->entries
, delta
, entry
);
1045 static const struct got_error
*
1046 resolve_offset_delta(struct got_delta_chain
*deltas
,
1047 struct got_packidx
*packidx
, struct got_pack
*pack
, off_t delta_offset
,
1048 size_t tslen
, int delta_type
, size_t delta_size
, unsigned int recursion
)
1050 const struct got_error
*err
;
1055 off_t delta_data_offset
;
1058 err
= got_pack_parse_offset_delta(&base_offset
, &consumed
, pack
,
1059 delta_offset
, tslen
);
1063 delta_data_offset
= delta_offset
+ tslen
+ consumed
;
1064 if (delta_data_offset
>= pack
->filesize
)
1065 return got_error(GOT_ERR_PACK_OFFSET
);
1067 if (pack
->map
== NULL
) {
1068 delta_data_offset
= lseek(pack
->fd
, 0, SEEK_CUR
);
1069 if (delta_data_offset
== -1)
1070 return got_error_from_errno("lseek");
1073 err
= add_delta(deltas
, delta_offset
, tslen
, delta_type
, delta_size
,
1078 /* An offset delta must be in the same packfile. */
1079 if (base_offset
>= pack
->filesize
)
1080 return got_error(GOT_ERR_PACK_OFFSET
);
1082 err
= got_pack_parse_object_type_and_size(&base_type
, &base_size
,
1083 &base_tslen
, pack
, base_offset
);
1087 return got_pack_resolve_delta_chain(deltas
, packidx
, pack
, base_offset
,
1088 base_tslen
, base_type
, base_size
, recursion
- 1);
1091 const struct got_error
*
1092 got_pack_parse_ref_delta(struct got_object_id
*id
,
1093 struct got_pack
*pack
, off_t delta_offset
, int tslen
)
1098 if (delta_offset
+ tslen
> SIZE_MAX
) {
1099 return got_error_fmt(GOT_ERR_PACK_OFFSET
,
1100 "mapoff %lld would overflow size_t",
1101 (long long)delta_offset
+ tslen
);
1104 mapoff
= delta_offset
+ tslen
;
1105 if (mapoff
+ sizeof(*id
) >= pack
->filesize
)
1106 return got_error(GOT_ERR_PACK_OFFSET
);
1107 memcpy(id
, pack
->map
+ mapoff
, sizeof(*id
));
1110 n
= read(pack
->fd
, id
, sizeof(*id
));
1112 return got_error_from_errno("read");
1113 if (n
!= sizeof(*id
))
1114 return got_error(GOT_ERR_BAD_PACKFILE
);
1120 static const struct got_error
*
1121 resolve_ref_delta(struct got_delta_chain
*deltas
, struct got_packidx
*packidx
,
1122 struct got_pack
*pack
, off_t delta_offset
, size_t tslen
, int delta_type
,
1123 size_t delta_size
, unsigned int recursion
)
1125 const struct got_error
*err
;
1126 struct got_object_id id
;
1132 off_t delta_data_offset
;
1134 if (delta_offset
+ tslen
>= pack
->filesize
)
1135 return got_error(GOT_ERR_PACK_OFFSET
);
1137 err
= got_pack_parse_ref_delta(&id
, pack
, delta_offset
, tslen
);
1141 delta_data_offset
= delta_offset
+ tslen
+ SHA1_DIGEST_LENGTH
;
1143 delta_data_offset
= lseek(pack
->fd
, 0, SEEK_CUR
);
1144 if (delta_data_offset
== -1)
1145 return got_error_from_errno("lseek");
1148 err
= add_delta(deltas
, delta_offset
, tslen
, delta_type
, delta_size
,
1153 /* Delta base must be in the same pack file. */
1154 idx
= got_packidx_get_object_idx(packidx
, &id
);
1156 return got_error(GOT_ERR_NO_OBJ
);
1158 base_offset
= got_packidx_get_object_offset(packidx
, idx
);
1159 if (base_offset
== -1)
1160 return got_error(GOT_ERR_BAD_PACKIDX
);
1162 if (base_offset
>= pack
->filesize
)
1163 return got_error(GOT_ERR_PACK_OFFSET
);
1165 err
= got_pack_parse_object_type_and_size(&base_type
, &base_size
,
1166 &base_tslen
, pack
, base_offset
);
1170 return got_pack_resolve_delta_chain(deltas
, packidx
, pack
, base_offset
,
1171 base_tslen
, base_type
, base_size
, recursion
- 1);
1174 const struct got_error
*
1175 got_pack_resolve_delta_chain(struct got_delta_chain
*deltas
,
1176 struct got_packidx
*packidx
, struct got_pack
*pack
, off_t delta_offset
,
1177 size_t tslen
, int delta_type
, size_t delta_size
, unsigned int recursion
)
1179 const struct got_error
*err
= NULL
;
1181 if (--recursion
== 0)
1182 return got_error(GOT_ERR_RECURSION
);
1184 switch (delta_type
) {
1185 case GOT_OBJ_TYPE_COMMIT
:
1186 case GOT_OBJ_TYPE_TREE
:
1187 case GOT_OBJ_TYPE_BLOB
:
1188 case GOT_OBJ_TYPE_TAG
:
1189 /* Plain types are the final delta base. Recursion ends. */
1190 err
= add_delta(deltas
, delta_offset
, tslen
, delta_type
,
1193 case GOT_OBJ_TYPE_OFFSET_DELTA
:
1194 err
= resolve_offset_delta(deltas
, packidx
, pack
,
1195 delta_offset
, tslen
, delta_type
, delta_size
, recursion
- 1);
1197 case GOT_OBJ_TYPE_REF_DELTA
:
1198 err
= resolve_ref_delta(deltas
, packidx
, pack
,
1199 delta_offset
, tslen
, delta_type
, delta_size
, recursion
- 1);
1202 return got_error(GOT_ERR_OBJ_TYPE
);
1208 static const struct got_error
*
1209 open_delta_object(struct got_object
**obj
, struct got_packidx
*packidx
,
1210 struct got_pack
*pack
, struct got_object_id
*id
, off_t offset
,
1211 size_t tslen
, int delta_type
, size_t delta_size
, int idx
)
1213 const struct got_error
*err
= NULL
;
1216 *obj
= calloc(1, sizeof(**obj
));
1218 return got_error_from_errno("calloc");
1222 (*obj
)->size
= 0; /* Not known because deltas aren't applied yet. */
1223 memcpy(&(*obj
)->id
, id
, sizeof((*obj
)->id
));
1224 (*obj
)->pack_offset
= offset
+ tslen
;
1226 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1227 (*obj
)->flags
|= GOT_OBJ_FLAG_DELTIFIED
;
1228 (*obj
)->flags
|= GOT_OBJ_FLAG_PACKED
;
1229 (*obj
)->pack_idx
= idx
;
1231 err
= got_pack_resolve_delta_chain(&(*obj
)->deltas
, packidx
, pack
,
1232 offset
, tslen
, delta_type
, delta_size
,
1233 GOT_DELTA_CHAIN_RECURSION_MAX
);
1237 err
= got_delta_chain_get_base_type(&resolved_type
, &(*obj
)->deltas
);
1240 (*obj
)->type
= resolved_type
;
1243 got_object_close(*obj
);
1249 const struct got_error
*
1250 got_packfile_open_object(struct got_object
**obj
, struct got_pack
*pack
,
1251 struct got_packidx
*packidx
, int idx
, struct got_object_id
*id
)
1253 const struct got_error
*err
= NULL
;
1261 offset
= got_packidx_get_object_offset(packidx
, idx
);
1263 return got_error(GOT_ERR_BAD_PACKIDX
);
1265 err
= got_pack_parse_object_type_and_size(&type
, &size
, &tslen
,
1271 case GOT_OBJ_TYPE_COMMIT
:
1272 case GOT_OBJ_TYPE_TREE
:
1273 case GOT_OBJ_TYPE_BLOB
:
1274 case GOT_OBJ_TYPE_TAG
:
1275 err
= open_plain_object(obj
, id
, type
, offset
+ tslen
,
1278 case GOT_OBJ_TYPE_OFFSET_DELTA
:
1279 case GOT_OBJ_TYPE_REF_DELTA
:
1280 err
= open_delta_object(obj
, packidx
, pack
, id
, offset
,
1281 tslen
, type
, size
, idx
);
1284 err
= got_error(GOT_ERR_OBJ_TYPE
);
1291 const struct got_error
*
1292 got_pack_get_delta_chain_max_size(uint64_t *max_size
,
1293 struct got_delta_chain
*deltas
, struct got_pack
*pack
)
1295 struct got_delta
*delta
;
1296 uint64_t base_size
= 0, result_size
= 0;
1299 STAILQ_FOREACH(delta
, &deltas
->entries
, entry
) {
1300 /* Plain object types are the delta base. */
1301 if (delta
->type
!= GOT_OBJ_TYPE_COMMIT
&&
1302 delta
->type
!= GOT_OBJ_TYPE_TREE
&&
1303 delta
->type
!= GOT_OBJ_TYPE_BLOB
&&
1304 delta
->type
!= GOT_OBJ_TYPE_TAG
) {
1305 const struct got_error
*err
;
1306 uint8_t *delta_buf
= NULL
;
1310 if (pack
->delta_cache
) {
1311 got_delta_cache_get(&delta_buf
, &delta_len
,
1312 NULL
, NULL
, pack
->delta_cache
,
1313 delta
->data_offset
);
1315 if (delta_buf
== NULL
) {
1317 err
= read_delta_data(&delta_buf
, &delta_len
,
1318 NULL
, delta
->data_offset
, pack
);
1322 if (pack
->delta_cache
&& !cached
) {
1323 err
= got_delta_cache_add(pack
->delta_cache
,
1324 delta
->data_offset
, delta_buf
, delta_len
);
1327 else if (err
->code
!= GOT_ERR_NO_SPACE
) {
1332 err
= got_delta_get_sizes(&base_size
, &result_size
,
1333 delta_buf
, delta_len
);
1339 base_size
= delta
->size
;
1340 if (base_size
> *max_size
)
1341 *max_size
= base_size
;
1342 if (result_size
> *max_size
)
1343 *max_size
= result_size
;
1349 const struct got_error
*
1350 got_pack_get_max_delta_object_size(uint64_t *size
, struct got_object
*obj
,
1351 struct got_pack
*pack
)
1353 if ((obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) == 0)
1354 return got_error(GOT_ERR_OBJ_TYPE
);
1356 return got_pack_get_delta_chain_max_size(size
, &obj
->deltas
, pack
);
1359 const struct got_error
*
1360 got_pack_dump_delta_chain_to_file(size_t *result_size
,
1361 struct got_delta_chain
*deltas
, struct got_pack
*pack
, FILE *outfile
,
1362 FILE *base_file
, FILE *accum_file
)
1364 const struct got_error
*err
= NULL
;
1365 struct got_delta
*delta
;
1366 uint8_t *base_buf
= NULL
, *accum_buf
= NULL
;
1367 size_t base_bufsz
= 0, accum_bufsz
= 0, accum_size
= 0;
1368 /* We process small enough files entirely in memory for speed. */
1369 const size_t max_bufsize
= GOT_DELTA_RESULT_SIZE_CACHED_MAX
;
1370 uint64_t max_size
= 0;
1375 if (STAILQ_EMPTY(&deltas
->entries
))
1376 return got_error(GOT_ERR_BAD_DELTA_CHAIN
);
1378 if (pack
->delta_cache
) {
1379 uint8_t *delta_buf
= NULL
, *fulltext
= NULL
;
1380 size_t delta_len
, fulltext_len
;
1382 delta
= STAILQ_LAST(&deltas
->entries
, got_delta
, entry
);
1383 got_delta_cache_get(&delta_buf
, &delta_len
,
1384 &fulltext
, &fulltext_len
,
1385 pack
->delta_cache
, delta
->data_offset
);
1389 w
= fwrite(fulltext
, 1, fulltext_len
, outfile
);
1390 if (w
!= fulltext_len
)
1391 return got_ferror(outfile
, GOT_ERR_IO
);
1392 if (fflush(outfile
) != 0)
1393 return got_error_from_errno("fflush");
1394 *result_size
= fulltext_len
;
1399 if (fseeko(base_file
, 0L, SEEK_SET
) == -1)
1400 return got_error_from_errno("fseeko");
1401 if (fseeko(accum_file
, 0L, SEEK_SET
) == -1)
1402 return got_error_from_errno("fseeko");
1404 /* Deltas are ordered in ascending order. */
1405 STAILQ_FOREACH(delta
, &deltas
->entries
, entry
) {
1406 uint8_t *delta_buf
= NULL
, *fulltext
= NULL
;
1407 size_t delta_len
, fulltext_len
;
1408 uint64_t base_size
, result_size
= 0;
1412 off_t delta_data_offset
;
1414 /* Plain object types are the delta base. */
1415 if (delta
->type
!= GOT_OBJ_TYPE_COMMIT
&&
1416 delta
->type
!= GOT_OBJ_TYPE_TREE
&&
1417 delta
->type
!= GOT_OBJ_TYPE_BLOB
&&
1418 delta
->type
!= GOT_OBJ_TYPE_TAG
) {
1419 err
= got_error(GOT_ERR_BAD_DELTA_CHAIN
);
1423 delta_data_offset
= delta
->offset
+ delta
->tslen
;
1424 if (delta_data_offset
>= pack
->filesize
) {
1425 err
= got_error(GOT_ERR_PACK_OFFSET
);
1428 if (pack
->map
== NULL
) {
1429 if (lseek(pack
->fd
, delta_data_offset
, SEEK_SET
)
1431 err
= got_error_from_errno("lseek");
1435 if (delta
->size
> max_size
)
1436 max_size
= delta
->size
;
1437 if (max_size
> max_bufsize
) {
1439 if (delta_data_offset
> SIZE_MAX
) {
1440 return got_error_fmt(
1442 "delta offset %lld "
1448 mapoff
= delta_data_offset
;
1449 err
= got_inflate_to_file_mmap(
1450 &base_bufsz
, NULL
, NULL
, pack
->map
,
1451 mapoff
, pack
->filesize
- mapoff
,
1454 err
= got_inflate_to_file_fd(
1455 &base_bufsz
, NULL
, NULL
, pack
->fd
,
1458 accum_buf
= malloc(max_size
);
1459 if (accum_buf
== NULL
) {
1460 err
= got_error_from_errno("malloc");
1463 accum_bufsz
= max_size
;
1465 if (delta_data_offset
> SIZE_MAX
) {
1466 err
= got_error_fmt(
1468 "delta offset %lld "
1475 mapoff
= delta_data_offset
;
1476 err
= got_inflate_to_mem_mmap(&base_buf
,
1477 &base_bufsz
, NULL
, NULL
,
1479 pack
->filesize
- mapoff
);
1481 err
= got_inflate_to_mem_fd(&base_buf
,
1482 &base_bufsz
, NULL
, NULL
, max_size
,
1488 if (base_buf
== NULL
)
1490 else if (pack
->delta_cache
&& fulltext
== NULL
) {
1491 err
= got_delta_cache_add(pack
->delta_cache
,
1492 delta_data_offset
, NULL
, 0);
1494 if (err
->code
!= GOT_ERR_NO_SPACE
)
1498 err
= got_delta_cache_add_fulltext(
1501 base_buf
, base_bufsz
);
1503 err
->code
!= GOT_ERR_NO_SPACE
)
1511 if (pack
->delta_cache
) {
1512 got_delta_cache_get(&delta_buf
, &delta_len
,
1513 &fulltext
, &fulltext_len
,
1514 pack
->delta_cache
, delta
->data_offset
);
1516 if (delta_buf
== NULL
) {
1518 err
= read_delta_data(&delta_buf
, &delta_len
, NULL
,
1519 delta
->data_offset
, pack
);
1523 if (pack
->delta_cache
&& !cached
) {
1524 err
= got_delta_cache_add(pack
->delta_cache
,
1525 delta
->data_offset
, delta_buf
, delta_len
);
1528 else if (err
->code
!= GOT_ERR_NO_SPACE
) {
1534 err
= got_delta_get_sizes(&base_size
, &result_size
,
1535 delta_buf
, delta_len
);
1541 if (base_size
> max_size
)
1542 max_size
= base_size
;
1543 if (result_size
> max_size
)
1544 max_size
= result_size
;
1545 if (fulltext_len
> max_size
)
1546 max_size
= fulltext_len
;
1548 if (base_buf
&& max_size
> max_bufsize
) {
1549 /* Switch from buffers to temporary files. */
1550 size_t w
= fwrite(base_buf
, 1, base_bufsz
,
1552 if (w
!= base_bufsz
) {
1553 err
= got_ferror(outfile
, GOT_ERR_IO
);
1564 if (base_buf
&& max_size
> base_bufsz
) {
1565 uint8_t *p
= realloc(base_buf
, max_size
);
1567 err
= got_error_from_errno("realloc");
1573 base_bufsz
= max_size
;
1576 if (accum_buf
&& max_size
> accum_bufsz
) {
1577 uint8_t *p
= realloc(accum_buf
, max_size
);
1579 err
= got_error_from_errno("realloc");
1585 accum_bufsz
= max_size
;
1590 memcpy(accum_buf
, fulltext
, fulltext_len
);
1591 accum_size
= fulltext_len
;
1594 err
= got_delta_apply_in_mem(base_buf
,
1595 base_bufsz
, delta_buf
, delta_len
,
1596 accum_buf
, &accum_size
, max_size
);
1603 if (fulltext
== NULL
) {
1604 err
= got_delta_cache_add_fulltext(
1605 pack
->delta_cache
, delta
->data_offset
,
1606 accum_buf
, accum_size
);
1608 if (err
->code
!= GOT_ERR_NO_SPACE
)
1614 err
= got_delta_apply(base_file
, delta_buf
,
1616 /* Final delta application writes to output file. */
1617 ++n
< deltas
->nentries
? accum_file
: outfile
,
1625 if (n
< deltas
->nentries
) {
1626 /* Accumulated delta becomes the new base. */
1628 uint8_t *tmp
= accum_buf
;
1629 size_t tmp_size
= accum_bufsz
;
1630 accum_buf
= base_buf
;
1631 accum_bufsz
= base_bufsz
;
1633 base_bufsz
= tmp_size
;
1635 FILE *tmp
= accum_file
;
1636 accum_file
= base_file
;
1651 size_t len
= fwrite(accum_buf
, 1, accum_size
, outfile
);
1653 if (len
!= accum_size
)
1654 err
= got_ferror(outfile
, GOT_ERR_IO
);
1658 *result_size
= accum_size
;
1662 const struct got_error
*
1663 got_pack_dump_delta_chain_to_mem(uint8_t **outbuf
, size_t *outlen
,
1664 struct got_delta_chain
*deltas
, struct got_pack
*pack
)
1666 const struct got_error
*err
= NULL
;
1667 struct got_delta
*delta
;
1668 uint8_t *base_buf
= NULL
, *accum_buf
= NULL
;
1669 size_t base_bufsz
= 0, accum_bufsz
= 0, accum_size
= 0;
1670 uint64_t max_size
= 0;
1676 if (STAILQ_EMPTY(&deltas
->entries
))
1677 return got_error(GOT_ERR_BAD_DELTA_CHAIN
);
1679 if (pack
->delta_cache
) {
1680 uint8_t *delta_buf
= NULL
, *fulltext
= NULL
;
1681 size_t delta_len
, fulltext_len
;
1683 delta
= STAILQ_LAST(&deltas
->entries
, got_delta
, entry
);
1684 got_delta_cache_get(&delta_buf
, &delta_len
,
1685 &fulltext
, &fulltext_len
,
1686 pack
->delta_cache
, delta
->data_offset
);
1688 *outbuf
= malloc(fulltext_len
);
1689 if (*outbuf
== NULL
)
1690 return got_error_from_errno("malloc");
1691 memcpy(*outbuf
, fulltext
, fulltext_len
);
1692 *outlen
= fulltext_len
;
1697 /* Deltas are ordered in ascending order. */
1698 STAILQ_FOREACH(delta
, &deltas
->entries
, entry
) {
1699 uint8_t *delta_buf
= NULL
, *fulltext
= NULL
;
1700 size_t delta_len
, fulltext_len
= 0;
1701 uint64_t base_size
, result_size
= 0;
1704 off_t delta_data_offset
;
1706 /* Plain object types are the delta base. */
1707 if (delta
->type
!= GOT_OBJ_TYPE_COMMIT
&&
1708 delta
->type
!= GOT_OBJ_TYPE_TREE
&&
1709 delta
->type
!= GOT_OBJ_TYPE_BLOB
&&
1710 delta
->type
!= GOT_OBJ_TYPE_TAG
) {
1711 err
= got_error(GOT_ERR_BAD_DELTA_CHAIN
);
1715 delta_data_offset
= delta
->offset
+ delta
->tslen
;
1716 if (delta_data_offset
>= pack
->filesize
) {
1717 err
= got_error(GOT_ERR_PACK_OFFSET
);
1721 if (pack
->delta_cache
) {
1722 got_delta_cache_get(&delta_buf
, &delta_len
,
1723 &fulltext
, &fulltext_len
,
1724 pack
->delta_cache
, delta_data_offset
);
1727 if (delta
->size
> max_size
)
1728 max_size
= delta
->size
;
1729 if (delta
->size
> fulltext_len
)
1730 max_size
= fulltext_len
;
1733 base_buf
= malloc(fulltext_len
);
1734 if (base_buf
== NULL
) {
1735 err
= got_error_from_errno("malloc");
1738 memcpy(base_buf
, fulltext
, fulltext_len
);
1739 base_bufsz
= fulltext_len
;
1740 } else if (pack
->map
) {
1743 if (delta_data_offset
> SIZE_MAX
) {
1744 return got_error_fmt(GOT_ERR_RANGE
,
1745 "delta %lld offset would "
1747 (long long)delta_data_offset
);
1750 mapoff
= delta_data_offset
;
1751 err
= got_inflate_to_mem_mmap(&base_buf
,
1752 &base_bufsz
, NULL
, NULL
, pack
->map
,
1753 mapoff
, pack
->filesize
- mapoff
);
1755 if (lseek(pack
->fd
, delta_data_offset
, SEEK_SET
)
1757 err
= got_error_from_errno("lseek");
1760 err
= got_inflate_to_mem_fd(&base_buf
,
1761 &base_bufsz
, NULL
, NULL
, max_size
,
1768 if (pack
->delta_cache
&& fulltext
== NULL
) {
1769 err
= got_delta_cache_add(pack
->delta_cache
,
1770 delta_data_offset
, NULL
, 0);
1772 if (err
->code
!= GOT_ERR_NO_SPACE
)
1776 err
= got_delta_cache_add_fulltext(
1779 base_buf
, base_bufsz
);
1781 err
->code
!= GOT_ERR_NO_SPACE
)
1789 if (pack
->delta_cache
) {
1790 got_delta_cache_get(&delta_buf
, &delta_len
,
1791 &fulltext
, &fulltext_len
,
1792 pack
->delta_cache
, delta
->data_offset
);
1794 if (delta_buf
== NULL
) {
1796 err
= read_delta_data(&delta_buf
, &delta_len
, NULL
,
1797 delta
->data_offset
, pack
);
1801 if (pack
->delta_cache
&& !cached
) {
1802 err
= got_delta_cache_add(pack
->delta_cache
,
1803 delta
->data_offset
, delta_buf
, delta_len
);
1806 else if (err
->code
!= GOT_ERR_NO_SPACE
) {
1812 err
= got_delta_get_sizes(&base_size
, &result_size
,
1813 delta_buf
, delta_len
);
1819 if (base_size
> max_size
)
1820 max_size
= base_size
;
1821 if (result_size
> max_size
)
1822 max_size
= result_size
;
1823 if (fulltext_len
> max_size
)
1824 max_size
= fulltext_len
;
1826 if (max_size
> base_bufsz
) {
1827 uint8_t *p
= realloc(base_buf
, max_size
);
1829 err
= got_error_from_errno("realloc");
1835 base_bufsz
= max_size
;
1838 if (max_size
> accum_bufsz
) {
1839 uint8_t *p
= realloc(accum_buf
, max_size
);
1841 err
= got_error_from_errno("realloc");
1847 accum_bufsz
= max_size
;
1851 memcpy(accum_buf
, fulltext
, fulltext_len
);
1852 accum_size
= fulltext_len
;
1855 err
= got_delta_apply_in_mem(base_buf
, base_bufsz
,
1856 delta_buf
, delta_len
, accum_buf
,
1857 &accum_size
, max_size
);
1865 if (fulltext
== NULL
) {
1866 err
= got_delta_cache_add_fulltext(pack
->delta_cache
,
1867 delta
->data_offset
, accum_buf
, accum_size
);
1869 if (err
->code
!= GOT_ERR_NO_SPACE
)
1875 if (n
< deltas
->nentries
) {
1876 /* Accumulated delta becomes the new base. */
1877 uint8_t *tmp
= accum_buf
;
1878 size_t tmp_size
= accum_bufsz
;
1879 accum_buf
= base_buf
;
1880 accum_bufsz
= base_bufsz
;
1882 base_bufsz
= tmp_size
;
1893 *outbuf
= accum_buf
;
1894 *outlen
= accum_size
;
1899 const struct got_error
*
1900 got_packfile_extract_object(struct got_pack
*pack
, struct got_object
*obj
,
1901 FILE *outfile
, FILE *base_file
, FILE *accum_file
)
1903 const struct got_error
*err
= NULL
;
1905 if ((obj
->flags
& GOT_OBJ_FLAG_PACKED
) == 0)
1906 return got_error(GOT_ERR_OBJ_NOT_PACKED
);
1908 if ((obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) == 0) {
1909 if (obj
->pack_offset
>= pack
->filesize
)
1910 return got_error(GOT_ERR_PACK_OFFSET
);
1915 if (obj
->pack_offset
> SIZE_MAX
) {
1916 return got_error_fmt(GOT_ERR_RANGE
,
1917 "pack offset %lld would overflow size_t",
1918 (long long)obj
->pack_offset
);
1921 mapoff
= obj
->pack_offset
;
1922 err
= got_inflate_to_file_mmap(&obj
->size
, NULL
, NULL
,
1923 pack
->map
, mapoff
, pack
->filesize
- mapoff
,
1926 if (lseek(pack
->fd
, obj
->pack_offset
, SEEK_SET
) == -1)
1927 return got_error_from_errno("lseek");
1928 err
= got_inflate_to_file_fd(&obj
->size
, NULL
, NULL
,
1932 err
= got_pack_dump_delta_chain_to_file(&obj
->size
,
1933 &obj
->deltas
, pack
, outfile
, base_file
, accum_file
);
1938 const struct got_error
*
1939 got_packfile_extract_object_to_mem(uint8_t **buf
, size_t *len
,
1940 struct got_object
*obj
, struct got_pack
*pack
)
1942 const struct got_error
*err
= NULL
;
1944 if ((obj
->flags
& GOT_OBJ_FLAG_PACKED
) == 0)
1945 return got_error(GOT_ERR_OBJ_NOT_PACKED
);
1947 if ((obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) == 0) {
1948 if (obj
->pack_offset
>= pack
->filesize
)
1949 return got_error(GOT_ERR_PACK_OFFSET
);
1953 if (obj
->pack_offset
> SIZE_MAX
) {
1954 return got_error_fmt(GOT_ERR_RANGE
,
1955 "pack offset %lld would overflow size_t",
1956 (long long)obj
->pack_offset
);
1959 mapoff
= obj
->pack_offset
;
1960 err
= got_inflate_to_mem_mmap(buf
, len
, NULL
, NULL
,
1961 pack
->map
, mapoff
, pack
->filesize
- mapoff
);
1963 if (lseek(pack
->fd
, obj
->pack_offset
, SEEK_SET
) == -1)
1964 return got_error_from_errno("lseek");
1965 err
= got_inflate_to_mem_fd(buf
, len
, NULL
, NULL
,
1966 obj
->size
, pack
->fd
);
1969 err
= got_pack_dump_delta_chain_to_mem(buf
, len
, &obj
->deltas
,
1975 static const struct got_error
*
1976 read_raw_delta_data(uint8_t **delta_buf
, size_t *delta_len
,
1977 size_t *delta_len_compressed
, uint64_t *base_size
, uint64_t *result_size
,
1978 off_t delta_data_offset
, struct got_pack
*pack
, struct got_packidx
*packidx
)
1980 const struct got_error
*err
= NULL
;
1982 /* Validate decompression and obtain the decompressed size. */
1983 err
= read_delta_data(delta_buf
, delta_len
, delta_len_compressed
,
1984 delta_data_offset
, pack
);
1988 /* Read delta base/result sizes from head of delta stream. */
1989 err
= got_delta_get_sizes(base_size
, result_size
,
1990 *delta_buf
, *delta_len
);
1994 /* Discard decompressed delta and read it again in compressed form. */
1996 *delta_buf
= malloc(*delta_len_compressed
);
1997 if (*delta_buf
== NULL
) {
1998 err
= got_error_from_errno("malloc");
2002 if (delta_data_offset
>= pack
->filesize
) {
2003 err
= got_error(GOT_ERR_PACK_OFFSET
);
2006 memcpy(*delta_buf
, pack
->map
+ delta_data_offset
,
2007 *delta_len_compressed
);
2010 if (lseek(pack
->fd
, delta_data_offset
, SEEK_SET
) == -1) {
2011 err
= got_error_from_errno("lseek");
2014 n
= read(pack
->fd
, *delta_buf
, *delta_len_compressed
);
2016 err
= got_error_from_errno("read");
2018 } else if (n
!= *delta_len_compressed
) {
2019 err
= got_error(GOT_ERR_IO
);
2028 *delta_len_compressed
= 0;
2035 const struct got_error
*
2036 got_packfile_extract_raw_delta(uint8_t **delta_buf
, size_t *delta_size
,
2037 size_t *delta_compressed_size
, off_t
*delta_offset
,
2038 off_t
*delta_data_offset
, off_t
*base_offset
,
2039 struct got_object_id
*base_id
, uint64_t *base_size
, uint64_t *result_size
,
2040 struct got_pack
*pack
, struct got_packidx
*packidx
, int idx
)
2042 const struct got_error
*err
= NULL
;
2046 size_t tslen
, delta_hdrlen
;
2050 *delta_compressed_size
= 0;
2052 *delta_data_offset
= 0;
2057 offset
= got_packidx_get_object_offset(packidx
, idx
);
2059 return got_error(GOT_ERR_BAD_PACKIDX
);
2061 if (offset
>= pack
->filesize
)
2062 return got_error(GOT_ERR_PACK_OFFSET
);
2064 err
= got_pack_parse_object_type_and_size(&type
, &size
, &tslen
,
2069 if (tslen
+ size
< tslen
|| offset
+ size
< size
||
2070 tslen
+ offset
< tslen
)
2071 return got_error(GOT_ERR_PACK_OFFSET
);
2074 case GOT_OBJ_TYPE_OFFSET_DELTA
:
2075 err
= got_pack_parse_offset_delta(base_offset
, &delta_hdrlen
,
2076 pack
, offset
, tslen
);
2080 case GOT_OBJ_TYPE_REF_DELTA
:
2081 err
= got_pack_parse_ref_delta(base_id
, pack
, offset
, tslen
);
2084 delta_hdrlen
= SHA1_DIGEST_LENGTH
;
2087 return got_error_fmt(GOT_ERR_OBJ_TYPE
,
2088 "non-delta object type %d found at offset %lld",
2089 type
, (long long)offset
);
2092 if (tslen
+ delta_hdrlen
< delta_hdrlen
||
2093 offset
+ delta_hdrlen
< delta_hdrlen
)
2094 return got_error(GOT_ERR_BAD_DELTA
);
2096 *delta_data_offset
= offset
+ tslen
+ delta_hdrlen
;
2097 err
= read_raw_delta_data(delta_buf
, delta_size
, delta_compressed_size
,
2098 base_size
, result_size
, *delta_data_offset
, pack
, packidx
);
2102 if (*delta_size
!= size
) {
2103 err
= got_error(GOT_ERR_BAD_DELTA
);
2107 *delta_offset
= offset
;
2113 *delta_compressed_size
= 0;