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.
17 #include <sys/types.h>
32 #include "got_compat.h"
34 #include "got_error.h"
35 #include "got_object.h"
38 #include "got_lib_delta.h"
39 #include "got_lib_delta_cache.h"
40 #include "got_lib_object.h"
41 #include "got_lib_object_cache.h"
42 #include "got_lib_object_parse.h"
43 #include "got_lib_privsep.h"
44 #include "got_lib_pack.h"
46 static volatile sig_atomic_t sigint_received
;
49 catch_sigint(int signo
)
54 static const struct got_error
*
55 open_object(struct got_object
**obj
, struct got_pack
*pack
,
56 struct got_packidx
*packidx
, int idx
, struct got_object_id
*id
,
57 struct got_object_cache
*objcache
)
59 const struct got_error
*err
;
61 err
= got_packfile_open_object(obj
, pack
, packidx
, idx
, id
);
66 err
= got_object_cache_add(objcache
, id
, *obj
);
68 if (err
->code
== GOT_ERR_OBJ_EXISTS
||
69 err
->code
== GOT_ERR_OBJ_TOO_LARGE
)
77 static const struct got_error
*
78 object_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
, struct got_pack
*pack
,
79 struct got_packidx
*packidx
, struct got_object_cache
*objcache
)
81 const struct got_error
*err
= NULL
;
82 struct got_imsg_packed_object iobj
;
83 struct got_object
*obj
;
84 struct got_object_id id
;
87 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
88 if (datalen
!= sizeof(iobj
))
89 return got_error(GOT_ERR_PRIVSEP_LEN
);
90 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
91 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
93 obj
= got_object_cache_get(objcache
, &id
);
97 err
= open_object(&obj
, pack
, packidx
, iobj
.idx
, &id
,
103 err
= got_privsep_send_obj(ibuf
, obj
);
105 got_object_close(obj
);
109 const struct got_error
*
110 open_commit(struct got_commit_object
**commit
, struct got_pack
*pack
,
111 struct got_packidx
*packidx
, int obj_idx
, struct got_object_id
*id
,
112 struct got_object_cache
*objcache
)
114 const struct got_error
*err
= NULL
;
115 struct got_object
*obj
= NULL
;
121 obj
= got_object_cache_get(objcache
, id
);
125 err
= open_object(&obj
, pack
, packidx
, obj_idx
, id
,
131 err
= got_packfile_extract_object_to_mem(&buf
, &len
, obj
, pack
);
137 err
= got_object_parse_commit(commit
, buf
, len
);
139 got_object_close(obj
);
144 static const struct got_error
*
145 commit_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
, struct got_pack
*pack
,
146 struct got_packidx
*packidx
, struct got_object_cache
*objcache
)
148 const struct got_error
*err
= NULL
;
149 struct got_imsg_packed_object iobj
;
150 struct got_commit_object
*commit
= NULL
;
151 struct got_object_id id
;
154 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
155 if (datalen
!= sizeof(iobj
))
156 return got_error(GOT_ERR_PRIVSEP_LEN
);
157 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
158 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
160 err
= open_commit(&commit
, pack
, packidx
, iobj
.idx
, &id
, objcache
);
164 err
= got_privsep_send_commit(ibuf
, commit
);
167 got_object_commit_close(commit
);
169 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
172 got_privsep_send_error(ibuf
, err
);
178 const struct got_error
*
179 open_tree(uint8_t **buf
, struct got_pathlist_head
*entries
, int *nentries
,
180 struct got_pack
*pack
, struct got_packidx
*packidx
, int obj_idx
,
181 struct got_object_id
*id
, struct got_object_cache
*objcache
)
183 const struct got_error
*err
= NULL
;
184 struct got_object
*obj
= NULL
;
190 obj
= got_object_cache_get(objcache
, id
);
194 err
= open_object(&obj
, pack
, packidx
, obj_idx
, id
,
200 err
= got_packfile_extract_object_to_mem(buf
, &len
, obj
, pack
);
206 err
= got_object_parse_tree(entries
, nentries
, *buf
, len
);
208 got_object_close(obj
);
216 static const struct got_error
*
217 tree_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
, struct got_pack
*pack
,
218 struct got_packidx
*packidx
, struct got_object_cache
*objcache
)
220 const struct got_error
*err
= NULL
;
221 struct got_imsg_packed_object iobj
;
222 struct got_pathlist_head entries
;
225 struct got_object_id id
;
228 TAILQ_INIT(&entries
);
230 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
231 if (datalen
!= sizeof(iobj
))
232 return got_error(GOT_ERR_PRIVSEP_LEN
);
233 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
234 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
236 err
= open_tree(&buf
, &entries
, &nentries
, pack
, packidx
, iobj
.idx
,
241 err
= got_privsep_send_tree(ibuf
, &entries
, nentries
);
242 got_object_parsed_tree_entries_free(&entries
);
245 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
248 got_privsep_send_error(ibuf
, err
);
254 static const struct got_error
*
255 receive_file(FILE **f
, struct imsgbuf
*ibuf
, int imsg_code
)
257 const struct got_error
*err
;
261 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
265 if (imsg
.hdr
.type
!= imsg_code
) {
266 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
270 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
272 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
276 err
= got_error(GOT_ERR_PRIVSEP_NO_FD
);
280 *f
= fdopen(imsg
.fd
, "w+");
282 err
= got_error_from_errno("fdopen");
291 static const struct got_error
*
292 blob_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
, struct got_pack
*pack
,
293 struct got_packidx
*packidx
, struct got_object_cache
*objcache
)
295 const struct got_error
*err
= NULL
;
296 struct got_imsg_packed_object iobj
;
297 struct got_object
*obj
= NULL
;
298 FILE *outfile
= NULL
, *basefile
= NULL
, *accumfile
= NULL
;
299 struct got_object_id id
;
304 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
305 if (datalen
!= sizeof(iobj
))
306 return got_error(GOT_ERR_PRIVSEP_LEN
);
307 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
308 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
310 obj
= got_object_cache_get(objcache
, &id
);
314 err
= open_object(&obj
, pack
, packidx
, iobj
.idx
, &id
,
320 err
= receive_file(&outfile
, ibuf
, GOT_IMSG_BLOB_OUTFD
);
323 err
= receive_file(&basefile
, ibuf
, GOT_IMSG_TMPFD
);
326 err
= receive_file(&accumfile
, ibuf
, GOT_IMSG_TMPFD
);
330 if (obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) {
331 err
= got_pack_get_max_delta_object_size(&blob_size
, obj
, pack
);
335 blob_size
= obj
->size
;
337 if (blob_size
<= GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
338 err
= got_packfile_extract_object_to_mem(&buf
, &obj
->size
,
341 err
= got_packfile_extract_object(pack
, obj
, outfile
, basefile
,
346 err
= got_privsep_send_blob(ibuf
, obj
->size
, obj
->hdrlen
, buf
);
349 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
350 err
= got_error_from_errno("fclose");
351 if (basefile
&& fclose(basefile
) == EOF
&& err
== NULL
)
352 err
= got_error_from_errno("fclose");
353 if (accumfile
&& fclose(accumfile
) == EOF
&& err
== NULL
)
354 err
= got_error_from_errno("fclose");
355 got_object_close(obj
);
356 if (err
&& err
->code
!= GOT_ERR_PRIVSEP_PIPE
)
357 got_privsep_send_error(ibuf
, err
);
362 static const struct got_error
*
363 tag_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
, struct got_pack
*pack
,
364 struct got_packidx
*packidx
, struct got_object_cache
*objcache
)
366 const struct got_error
*err
= NULL
;
367 struct got_imsg_packed_object iobj
;
368 struct got_object
*obj
= NULL
;
369 struct got_tag_object
*tag
= NULL
;
372 struct got_object_id id
;
375 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
376 if (datalen
!= sizeof(iobj
))
377 return got_error(GOT_ERR_PRIVSEP_LEN
);
378 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
379 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
381 obj
= got_object_cache_get(objcache
, &id
);
385 err
= open_object(&obj
, pack
, packidx
, iobj
.idx
, &id
,
391 err
= got_packfile_extract_object_to_mem(&buf
, &len
, obj
, pack
);
396 err
= got_object_parse_tag(&tag
, buf
, len
);
400 err
= got_privsep_send_tag(ibuf
, tag
);
403 got_object_close(obj
);
405 got_object_tag_close(tag
);
407 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
410 got_privsep_send_error(ibuf
, err
);
416 static struct got_parsed_tree_entry
*
417 find_entry_by_name(struct got_pathlist_head
*entries
, int nentries
,
418 const char *name
, size_t len
)
420 struct got_pathlist_entry
*pe
;
422 /* Note that tree entries are sorted in strncmp() order. */
423 TAILQ_FOREACH(pe
, entries
, entry
) {
424 int cmp
= strncmp(pe
->path
, name
, len
);
429 if (pe
->path
[len
] == '\0')
430 return (struct got_parsed_tree_entry
*)pe
->data
;
435 const struct got_error
*
436 tree_path_changed(int *changed
, uint8_t **buf1
, uint8_t **buf2
,
437 struct got_pathlist_head
*entries1
, int *nentries1
,
438 struct got_pathlist_head
*entries2
, int *nentries2
,
439 const char *path
, struct got_pack
*pack
, struct got_packidx
*packidx
,
440 struct imsgbuf
*ibuf
, struct got_object_cache
*objcache
)
442 const struct got_error
*err
= NULL
;
443 struct got_parsed_tree_entry
*pte1
= NULL
, *pte2
= NULL
;
449 /* We not do support comparing the root path. */
450 if (got_path_is_root_dir(path
))
451 return got_error_path(path
, GOT_ERR_BAD_PATH
);
466 pte1
= find_entry_by_name(entries1
, *nentries1
, seg
, seglen
);
468 err
= got_error(GOT_ERR_NO_OBJ
);
472 pte2
= find_entry_by_name(entries2
, *nentries2
, seg
, seglen
);
478 if (pte1
->mode
!= pte2
->mode
) {
483 if (memcmp(pte1
->id
, pte2
->id
, SHA1_DIGEST_LENGTH
) == 0) {
488 if (*s
== '\0') { /* final path element */
497 struct got_object_id id1
, id2
;
500 memcpy(id1
.sha1
, pte1
->id
, SHA1_DIGEST_LENGTH
);
501 idx
= got_packidx_get_object_idx(packidx
, &id1
);
503 err
= got_error_no_obj(&id1
);
506 got_object_parsed_tree_entries_free(entries1
);
510 err
= open_tree(buf1
, entries1
, nentries1
, pack
,
511 packidx
, idx
, &id1
, objcache
);
516 memcpy(id2
.sha1
, pte2
->id
, SHA1_DIGEST_LENGTH
);
517 idx
= got_packidx_get_object_idx(packidx
, &id2
);
519 err
= got_error_no_obj(&id2
);
522 got_object_parsed_tree_entries_free(entries2
);
526 err
= open_tree(buf2
, entries2
, nentries2
, pack
,
527 packidx
, idx
, &id2
, objcache
);
537 static const struct got_error
*
538 send_traversed_commits(struct got_object_id
*commit_ids
, size_t ncommits
,
539 struct imsgbuf
*ibuf
)
541 const struct got_error
*err
;
545 wbuf
= imsg_create(ibuf
, GOT_IMSG_TRAVERSED_COMMITS
, 0, 0,
546 sizeof(struct got_imsg_traversed_commits
) +
547 ncommits
* SHA1_DIGEST_LENGTH
);
549 return got_error_from_errno("imsg_create TRAVERSED_COMMITS");
551 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1) {
552 err
= got_error_from_errno("imsg_add TRAVERSED_COMMITS");
556 for (i
= 0; i
< ncommits
; i
++) {
557 struct got_object_id
*id
= &commit_ids
[i
];
558 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1) {
559 err
= got_error_from_errno(
560 "imsg_add TRAVERSED_COMMITS");
567 imsg_close(ibuf
, wbuf
);
569 return got_privsep_flush_imsg(ibuf
);
572 static const struct got_error
*
573 send_commit_traversal_done(struct imsgbuf
*ibuf
)
575 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_DONE
, 0, 0, -1,
577 return got_error_from_errno("imsg_compose TRAVERSAL_DONE");
579 return got_privsep_flush_imsg(ibuf
);
583 static const struct got_error
*
584 commit_traversal_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
585 struct got_pack
*pack
, struct got_packidx
*packidx
,
586 struct got_object_cache
*objcache
)
588 const struct got_error
*err
= NULL
;
589 struct got_imsg_packed_object iobj
;
590 struct got_object_qid
*pid
;
591 struct got_commit_object
*commit
= NULL
, *pcommit
= NULL
;
592 struct got_pathlist_head entries
, pentries
;
593 int nentries
= 0, pnentries
= 0;
594 struct got_object_id id
;
595 size_t datalen
, path_len
;
597 const int min_alloc
= 64;
598 int changed
= 0, ncommits
= 0, nallocated
= 0;
599 struct got_object_id
*commit_ids
= NULL
;
601 TAILQ_INIT(&entries
);
602 TAILQ_INIT(&pentries
);
604 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
605 if (datalen
< sizeof(iobj
))
606 return got_error(GOT_ERR_PRIVSEP_LEN
);
607 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
608 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
610 path_len
= datalen
- sizeof(iobj
) - 1;
612 return got_error(GOT_ERR_PRIVSEP_LEN
);
614 path
= imsg
->data
+ sizeof(iobj
);
615 if (path
[path_len
] != '\0')
616 return got_error(GOT_ERR_PRIVSEP_LEN
);
619 nallocated
= min_alloc
;
620 commit_ids
= reallocarray(NULL
, nallocated
, sizeof(*commit_ids
));
621 if (commit_ids
== NULL
)
622 return got_error_from_errno("reallocarray");
625 const size_t max_datalen
= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
;
628 if (sigint_received
) {
629 err
= got_error(GOT_ERR_CANCELLED
);
633 if (commit
== NULL
) {
634 idx
= got_packidx_get_object_idx(packidx
, &id
);
637 err
= open_commit(&commit
, pack
, packidx
,
640 if (err
->code
!= GOT_ERR_NO_OBJ
)
647 if (sizeof(struct got_imsg_traversed_commits
) +
648 ncommits
* SHA1_DIGEST_LENGTH
>= max_datalen
) {
649 err
= send_traversed_commits(commit_ids
, ncommits
,
656 if (ncommits
> nallocated
) {
657 struct got_object_id
*new;
658 nallocated
+= min_alloc
;
659 new = reallocarray(commit_ids
, nallocated
,
660 sizeof(*commit_ids
));
662 err
= got_error_from_errno("reallocarray");
667 memcpy(commit_ids
[ncommits
- 1].sha1
, id
.sha1
,
670 pid
= STAILQ_FIRST(&commit
->parent_ids
);
674 idx
= got_packidx_get_object_idx(packidx
, pid
->id
);
678 err
= open_commit(&pcommit
, pack
, packidx
, idx
, pid
->id
,
681 if (err
->code
!= GOT_ERR_NO_OBJ
)
687 if (path
[0] == '/' && path
[1] == '\0') {
688 if (got_object_id_cmp(pcommit
->tree_id
,
689 commit
->tree_id
) != 0) {
695 uint8_t *buf
= NULL
, *pbuf
= NULL
;
697 idx
= got_packidx_get_object_idx(packidx
,
701 pidx
= got_packidx_get_object_idx(packidx
,
706 err
= open_tree(&buf
, &entries
, &nentries
, pack
,
707 packidx
, idx
, commit
->tree_id
, objcache
);
710 err
= open_tree(&pbuf
, &pentries
, &pnentries
, pack
,
711 packidx
, pidx
, pcommit
->tree_id
, objcache
);
717 err
= tree_path_changed(&changed
, &buf
, &pbuf
,
718 &entries
, &nentries
, &pentries
, &pnentries
, path
,
719 pack
, packidx
, ibuf
, objcache
);
721 got_object_parsed_tree_entries_free(&entries
);
724 got_object_parsed_tree_entries_free(&pentries
);
728 if (err
->code
!= GOT_ERR_NO_OBJ
)
736 memcpy(id
.sha1
, pid
->id
->sha1
, SHA1_DIGEST_LENGTH
);
737 got_object_commit_close(commit
);
744 err
= send_traversed_commits(commit_ids
, ncommits
, ibuf
);
749 err
= got_privsep_send_commit(ibuf
, commit
);
754 err
= send_commit_traversal_done(ibuf
);
758 got_object_commit_close(commit
);
760 got_object_commit_close(pcommit
);
762 got_object_parsed_tree_entries_free(&entries
);
764 got_object_parsed_tree_entries_free(&pentries
);
766 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
769 got_privsep_send_error(ibuf
, err
);
775 static const struct got_error
*
776 raw_object_request(struct imsg
*imsg
, struct imsgbuf
*ibuf
, struct got_pack
*pack
,
777 struct got_packidx
*packidx
, struct got_object_cache
*objcache
)
779 const struct got_error
*err
= NULL
;
782 FILE *outfile
= NULL
, *basefile
= NULL
, *accumfile
= NULL
;
783 struct got_imsg_packed_object iobj
;
784 struct got_object
*obj
;
785 struct got_object_id id
;
788 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
789 if (datalen
!= sizeof(iobj
))
790 return got_error(GOT_ERR_PRIVSEP_LEN
);
791 memcpy(&iobj
, imsg
->data
, sizeof(iobj
));
792 memcpy(id
.sha1
, iobj
.id
, SHA1_DIGEST_LENGTH
);
794 obj
= got_object_cache_get(objcache
, &id
);
798 err
= open_object(&obj
, pack
, packidx
, iobj
.idx
, &id
,
804 err
= receive_file(&outfile
, ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
);
807 err
= receive_file(&basefile
, ibuf
, GOT_IMSG_TMPFD
);
810 err
= receive_file(&accumfile
, ibuf
, GOT_IMSG_TMPFD
);
814 if (obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) {
815 err
= got_pack_get_max_delta_object_size(&size
, obj
, pack
);
821 if (size
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
822 err
= got_packfile_extract_object_to_mem(&buf
, &obj
->size
,
825 err
= got_packfile_extract_object(pack
, obj
, outfile
, basefile
,
830 err
= got_privsep_send_raw_obj(ibuf
, obj
->size
, obj
->hdrlen
, buf
);
833 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
834 err
= got_error_from_errno("fclose");
835 if (basefile
&& fclose(basefile
) == EOF
&& err
== NULL
)
836 err
= got_error_from_errno("fclose");
837 if (accumfile
&& fclose(accumfile
) == EOF
&& err
== NULL
)
838 err
= got_error_from_errno("fclose");
839 got_object_close(obj
);
840 if (err
&& err
->code
!= GOT_ERR_PRIVSEP_PIPE
)
841 got_privsep_send_error(ibuf
, err
);
848 static const struct got_error
*
849 receive_packidx(struct got_packidx
**packidx
, struct imsgbuf
*ibuf
)
851 const struct got_error
*err
= NULL
;
853 struct got_imsg_packidx ipackidx
;
855 struct got_packidx
*p
;
859 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
863 p
= calloc(1, sizeof(*p
));
865 err
= got_error_from_errno("calloc");
869 if (imsg
.hdr
.type
!= GOT_IMSG_PACKIDX
) {
870 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
875 err
= got_error(GOT_ERR_PRIVSEP_NO_FD
);
879 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
880 if (datalen
!= sizeof(ipackidx
)) {
881 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
884 memcpy(&ipackidx
, imsg
.data
, sizeof(ipackidx
));
886 p
->len
= ipackidx
.len
;
887 p
->fd
= dup(imsg
.fd
);
889 err
= got_error_from_errno("dup");
892 if (lseek(p
->fd
, 0, SEEK_SET
) == -1) {
893 err
= got_error_from_errno("lseek");
897 #ifndef GOT_PACK_NO_MMAP
898 p
->map
= mmap(NULL
, p
->len
, PROT_READ
, MAP_PRIVATE
, p
->fd
, 0);
899 if (p
->map
== MAP_FAILED
)
900 p
->map
= NULL
; /* fall back to read(2) */
902 err
= got_packidx_init_hdr(p
, 1, ipackidx
.packfile_size
);
907 got_packidx_close(p
);
914 static const struct got_error
*
915 receive_pack(struct got_pack
**packp
, struct imsgbuf
*ibuf
)
917 const struct got_error
*err
= NULL
;
919 struct got_imsg_pack ipack
;
921 struct got_pack
*pack
;
925 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
929 pack
= calloc(1, sizeof(*pack
));
931 err
= got_error_from_errno("calloc");
935 if (imsg
.hdr
.type
!= GOT_IMSG_PACK
) {
936 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
941 err
= got_error(GOT_ERR_PRIVSEP_NO_FD
);
945 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
946 if (datalen
!= sizeof(ipack
)) {
947 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
950 memcpy(&ipack
, imsg
.data
, sizeof(ipack
));
952 pack
->filesize
= ipack
.filesize
;
953 pack
->fd
= dup(imsg
.fd
);
954 if (pack
->fd
== -1) {
955 err
= got_error_from_errno("dup");
958 if (lseek(pack
->fd
, 0, SEEK_SET
) == -1) {
959 err
= got_error_from_errno("lseek");
962 pack
->path_packfile
= strdup(ipack
.path_packfile
);
963 if (pack
->path_packfile
== NULL
) {
964 err
= got_error_from_errno("strdup");
968 pack
->delta_cache
= got_delta_cache_alloc(100,
969 GOT_DELTA_RESULT_SIZE_CACHED_MAX
);
970 if (pack
->delta_cache
== NULL
) {
971 err
= got_error_from_errno("got_delta_cache_alloc");
975 #ifndef GOT_PACK_NO_MMAP
976 pack
->map
= mmap(NULL
, pack
->filesize
, PROT_READ
, MAP_PRIVATE
,
978 if (pack
->map
== MAP_FAILED
)
979 pack
->map
= NULL
; /* fall back to read(2) */
993 main(int argc
, char *argv
[])
995 const struct got_error
*err
= NULL
;
998 struct got_packidx
*packidx
= NULL
;
999 struct got_pack
*pack
= NULL
;
1000 struct got_object_cache objcache
;
1002 //static int attached;
1003 //while (!attached) sleep(1);
1005 signal(SIGINT
, catch_sigint
);
1007 imsg_init(&ibuf
, GOT_IMSG_FD_CHILD
);
1009 err
= got_object_cache_init(&objcache
, GOT_OBJECT_CACHE_TYPE_OBJ
);
1011 err
= got_error_from_errno("got_object_cache_init");
1012 got_privsep_send_error(&ibuf
, err
);
1017 /* revoke access to most system calls */
1018 if (pledge("stdio recvfd", NULL
) == -1) {
1019 err
= got_error_from_errno("pledge");
1020 got_privsep_send_error(&ibuf
, err
);
1025 err
= receive_packidx(&packidx
, &ibuf
);
1027 got_privsep_send_error(&ibuf
, err
);
1031 err
= receive_pack(&pack
, &ibuf
);
1033 got_privsep_send_error(&ibuf
, err
);
1040 if (sigint_received
) {
1041 err
= got_error(GOT_ERR_CANCELLED
);
1045 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
1047 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
1052 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
1055 switch (imsg
.hdr
.type
) {
1056 case GOT_IMSG_PACKED_OBJECT_REQUEST
:
1057 err
= object_request(&imsg
, &ibuf
, pack
, packidx
,
1060 case GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
:
1061 err
= raw_object_request(&imsg
, &ibuf
, pack
, packidx
,
1064 case GOT_IMSG_COMMIT_REQUEST
:
1065 err
= commit_request(&imsg
, &ibuf
, pack
, packidx
,
1068 case GOT_IMSG_TREE_REQUEST
:
1069 err
= tree_request(&imsg
, &ibuf
, pack
, packidx
,
1072 case GOT_IMSG_BLOB_REQUEST
:
1073 err
= blob_request(&imsg
, &ibuf
, pack
, packidx
,
1076 case GOT_IMSG_TAG_REQUEST
:
1077 err
= tag_request(&imsg
, &ibuf
, pack
, packidx
,
1080 case GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
:
1081 err
= commit_traversal_request(&imsg
, &ibuf
, pack
,
1082 packidx
, &objcache
);
1085 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1089 if (imsg
.fd
!= -1 && close(imsg
.fd
) == -1 && err
== NULL
)
1090 err
= got_error_from_errno("close");
1097 got_packidx_close(packidx
);
1099 got_pack_close(pack
);
1100 got_object_cache_close(&objcache
);
1103 if (!sigint_received
&& err
->code
!= GOT_ERR_PRIVSEP_PIPE
) {
1104 fprintf(stderr
, "%s: %s\n", getprogname(), err
->msg
);
1105 got_privsep_send_error(&ibuf
, err
);
1108 if (close(GOT_IMSG_FD_CHILD
) == -1 && err
== NULL
)
1109 err
= got_error_from_errno("close");