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>
31 #include "got_compat.h"
33 #include "got_error.h"
34 #include "got_object.h"
37 #include "got_lib_delta.h"
38 #include "got_lib_delta_cache.h"
39 #include "got_lib_object.h"
40 #include "got_lib_object_cache.h"
41 #include "got_lib_object_parse.h"
42 #include "got_lib_privsep.h"
43 #include "got_lib_pack.h"
45 static volatile sig_atomic_t sigint_received;
48 catch_sigint(int signo)
53 static const struct got_error *
54 open_object(struct got_object **obj, struct got_pack *pack,
55 struct got_packidx *packidx, int idx, struct got_object_id *id,
56 struct got_object_cache *objcache)
58 const struct got_error *err;
60 err = got_packfile_open_object(obj, pack, packidx, idx, id);
65 err = got_object_cache_add(objcache, id, *obj);
67 if (err->code == GOT_ERR_OBJ_EXISTS ||
68 err->code == GOT_ERR_OBJ_TOO_LARGE)
76 static const struct got_error *
77 object_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
78 struct got_packidx *packidx, struct got_object_cache *objcache)
80 const struct got_error *err = NULL;
81 struct got_imsg_packed_object iobj;
82 struct got_object *obj;
83 struct got_object_id id;
86 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
87 if (datalen != sizeof(iobj))
88 return got_error(GOT_ERR_PRIVSEP_LEN);
89 memcpy(&iobj, imsg->data, sizeof(iobj));
90 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
92 obj = got_object_cache_get(objcache, &id);
96 err = open_object(&obj, pack, packidx, iobj.idx, &id,
102 err = got_privsep_send_obj(ibuf, obj);
104 got_object_close(obj);
108 static const struct got_error *
109 open_commit(struct got_commit_object **commit, struct got_pack *pack,
110 struct got_packidx *packidx, int obj_idx, struct got_object_id *id,
111 struct got_object_cache *objcache)
113 const struct got_error *err = NULL;
114 struct got_object *obj = NULL;
120 obj = got_object_cache_get(objcache, id);
124 err = open_object(&obj, pack, packidx, obj_idx, id,
130 err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack);
136 err = got_object_parse_commit(commit, buf, len);
138 got_object_close(obj);
143 static const struct got_error *
144 commit_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
145 struct got_packidx *packidx, struct got_object_cache *objcache)
147 const struct got_error *err = NULL;
148 struct got_imsg_packed_object iobj;
149 struct got_commit_object *commit = NULL;
150 struct got_object_id id;
153 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
154 if (datalen != sizeof(iobj))
155 return got_error(GOT_ERR_PRIVSEP_LEN);
156 memcpy(&iobj, imsg->data, sizeof(iobj));
157 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
159 err = open_commit(&commit, pack, packidx, iobj.idx, &id, objcache);
163 err = got_privsep_send_commit(ibuf, commit);
166 got_object_commit_close(commit);
168 if (err->code == GOT_ERR_PRIVSEP_PIPE)
171 got_privsep_send_error(ibuf, err);
177 static const struct got_error *
178 open_tree(uint8_t **buf, struct got_pathlist_head *entries, int *nentries,
179 struct got_pack *pack, struct got_packidx *packidx, int obj_idx,
180 struct got_object_id *id, struct got_object_cache *objcache)
182 const struct got_error *err = NULL;
183 struct got_object *obj = NULL;
189 obj = got_object_cache_get(objcache, id);
193 err = open_object(&obj, pack, packidx, obj_idx, id,
199 err = got_packfile_extract_object_to_mem(buf, &len, obj, pack);
205 err = got_object_parse_tree(entries, nentries, *buf, len);
207 got_object_close(obj);
215 static const struct got_error *
216 tree_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
217 struct got_packidx *packidx, struct got_object_cache *objcache)
219 const struct got_error *err = NULL;
220 struct got_imsg_packed_object iobj;
221 struct got_pathlist_head entries;
224 struct got_object_id id;
227 TAILQ_INIT(&entries);
229 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
230 if (datalen != sizeof(iobj))
231 return got_error(GOT_ERR_PRIVSEP_LEN);
232 memcpy(&iobj, imsg->data, sizeof(iobj));
233 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
235 err = open_tree(&buf, &entries, &nentries, pack, packidx, iobj.idx,
240 err = got_privsep_send_tree(ibuf, &entries, nentries);
241 got_object_parsed_tree_entries_free(&entries);
244 if (err->code == GOT_ERR_PRIVSEP_PIPE)
247 got_privsep_send_error(ibuf, err);
253 static const struct got_error *
254 receive_file(FILE **f, struct imsgbuf *ibuf, uint32_t imsg_code)
256 const struct got_error *err;
260 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
264 if (imsg.hdr.type != imsg_code) {
265 err = got_error(GOT_ERR_PRIVSEP_MSG);
269 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
271 err = got_error(GOT_ERR_PRIVSEP_LEN);
275 err = got_error(GOT_ERR_PRIVSEP_NO_FD);
279 *f = fdopen(imsg.fd, "w+");
281 err = got_error_from_errno("fdopen");
290 static const struct got_error *
291 receive_tempfile(FILE **basefile, FILE **accumfile, struct imsg *imsg,
292 struct imsgbuf *ibuf)
297 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
299 return got_error(GOT_ERR_PRIVSEP_LEN);
302 return got_error(GOT_ERR_PRIVSEP_NO_FD);
304 if (*basefile == NULL)
306 else if (*accumfile == NULL)
309 return got_error(GOT_ERR_PRIVSEP_MSG);
311 *f = fdopen(imsg->fd, "w+");
313 return got_error_from_errno("fdopen");
319 static const struct got_error *
320 blob_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
321 struct got_packidx *packidx, struct got_object_cache *objcache,
322 FILE *basefile, FILE *accumfile)
324 const struct got_error *err = NULL;
325 struct got_imsg_packed_object iobj;
326 struct got_object *obj = NULL;
327 FILE *outfile = NULL;
328 struct got_object_id id;
333 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
334 if (datalen != sizeof(iobj))
335 return got_error(GOT_ERR_PRIVSEP_LEN);
336 memcpy(&iobj, imsg->data, sizeof(iobj));
337 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
339 obj = got_object_cache_get(objcache, &id);
343 err = open_object(&obj, pack, packidx, iobj.idx, &id,
349 err = receive_file(&outfile, ibuf, GOT_IMSG_BLOB_OUTFD);
353 if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
354 err = got_pack_get_max_delta_object_size(&blob_size, obj, pack);
358 blob_size = obj->size;
360 if (blob_size <= GOT_PRIVSEP_INLINE_BLOB_DATA_MAX)
361 err = got_packfile_extract_object_to_mem(&buf, &obj->size,
364 err = got_packfile_extract_object(pack, obj, outfile, basefile,
369 err = got_privsep_send_blob(ibuf, obj->size, obj->hdrlen, buf);
372 if (outfile && fclose(outfile) == EOF && err == NULL)
373 err = got_error_from_errno("fclose");
374 got_object_close(obj);
375 if (err && err->code != GOT_ERR_PRIVSEP_PIPE)
376 got_privsep_send_error(ibuf, err);
381 static const struct got_error *
382 tag_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
383 struct got_packidx *packidx, struct got_object_cache *objcache)
385 const struct got_error *err = NULL;
386 struct got_imsg_packed_object iobj;
387 struct got_object *obj = NULL;
388 struct got_tag_object *tag = NULL;
391 struct got_object_id id;
394 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
395 if (datalen != sizeof(iobj))
396 return got_error(GOT_ERR_PRIVSEP_LEN);
397 memcpy(&iobj, imsg->data, sizeof(iobj));
398 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
400 obj = got_object_cache_get(objcache, &id);
404 err = open_object(&obj, pack, packidx, iobj.idx, &id,
410 err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack);
415 err = got_object_parse_tag(&tag, buf, len);
419 err = got_privsep_send_tag(ibuf, tag);
422 got_object_close(obj);
424 got_object_tag_close(tag);
426 if (err->code == GOT_ERR_PRIVSEP_PIPE)
429 got_privsep_send_error(ibuf, err);
435 static struct got_parsed_tree_entry *
436 find_entry_by_name(struct got_pathlist_head *entries, int nentries,
437 const char *name, size_t len)
439 struct got_pathlist_entry *pe;
441 /* Note that tree entries are sorted in strncmp() order. */
442 TAILQ_FOREACH(pe, entries, entry) {
443 int cmp = strncmp(pe->path, name, len);
448 if (pe->path[len] == '\0')
449 return (struct got_parsed_tree_entry *)pe->data;
454 static const struct got_error *
455 tree_path_changed(int *changed, uint8_t **buf1, uint8_t **buf2,
456 struct got_pathlist_head *entries1, int *nentries1,
457 struct got_pathlist_head *entries2, int *nentries2,
458 const char *path, struct got_pack *pack, struct got_packidx *packidx,
459 struct imsgbuf *ibuf, struct got_object_cache *objcache)
461 const struct got_error *err = NULL;
462 struct got_parsed_tree_entry *pte1 = NULL, *pte2 = NULL;
468 /* We not do support comparing the root path. */
469 if (got_path_is_root_dir(path))
470 return got_error_path(path, GOT_ERR_BAD_PATH);
485 pte1 = find_entry_by_name(entries1, *nentries1, seg, seglen);
487 err = got_error(GOT_ERR_NO_OBJ);
491 pte2 = find_entry_by_name(entries2, *nentries2, seg, seglen);
497 if (pte1->mode != pte2->mode) {
502 if (memcmp(pte1->id, pte2->id, SHA1_DIGEST_LENGTH) == 0) {
507 if (*s == '\0') { /* final path element */
516 struct got_object_id id1, id2;
519 memcpy(id1.sha1, pte1->id, SHA1_DIGEST_LENGTH);
520 idx = got_packidx_get_object_idx(packidx, &id1);
522 err = got_error_no_obj(&id1);
525 got_object_parsed_tree_entries_free(entries1);
529 err = open_tree(buf1, entries1, nentries1, pack,
530 packidx, idx, &id1, objcache);
535 memcpy(id2.sha1, pte2->id, SHA1_DIGEST_LENGTH);
536 idx = got_packidx_get_object_idx(packidx, &id2);
538 err = got_error_no_obj(&id2);
541 got_object_parsed_tree_entries_free(entries2);
545 err = open_tree(buf2, entries2, nentries2, pack,
546 packidx, idx, &id2, objcache);
556 static const struct got_error *
557 send_traversed_commits(struct got_object_id *commit_ids, size_t ncommits,
558 struct imsgbuf *ibuf)
560 const struct got_error *err;
564 wbuf = imsg_create(ibuf, GOT_IMSG_TRAVERSED_COMMITS, 0, 0,
565 sizeof(struct got_imsg_traversed_commits) +
566 ncommits * SHA1_DIGEST_LENGTH);
568 return got_error_from_errno("imsg_create TRAVERSED_COMMITS");
570 if (imsg_add(wbuf, &ncommits, sizeof(ncommits)) == -1) {
571 err = got_error_from_errno("imsg_add TRAVERSED_COMMITS");
575 for (i = 0; i < ncommits; i++) {
576 struct got_object_id *id = &commit_ids[i];
577 if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1) {
578 err = got_error_from_errno(
579 "imsg_add TRAVERSED_COMMITS");
586 imsg_close(ibuf, wbuf);
588 return got_privsep_flush_imsg(ibuf);
591 static const struct got_error *
592 send_commit_traversal_done(struct imsgbuf *ibuf)
594 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_TRAVERSAL_DONE, 0, 0, -1,
596 return got_error_from_errno("imsg_compose TRAVERSAL_DONE");
598 return got_privsep_flush_imsg(ibuf);
602 static const struct got_error *
603 commit_traversal_request(struct imsg *imsg, struct imsgbuf *ibuf,
604 struct got_pack *pack, struct got_packidx *packidx,
605 struct got_object_cache *objcache)
607 const struct got_error *err = NULL;
608 struct got_imsg_packed_object iobj;
609 struct got_object_qid *pid;
610 struct got_commit_object *commit = NULL, *pcommit = NULL;
611 struct got_pathlist_head entries, pentries;
612 int nentries = 0, pnentries = 0;
613 struct got_object_id id;
614 size_t datalen, path_len;
616 const int min_alloc = 64;
617 int changed = 0, ncommits = 0, nallocated = 0;
618 struct got_object_id *commit_ids = NULL;
620 TAILQ_INIT(&entries);
621 TAILQ_INIT(&pentries);
623 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
624 if (datalen < sizeof(iobj))
625 return got_error(GOT_ERR_PRIVSEP_LEN);
626 memcpy(&iobj, imsg->data, sizeof(iobj));
627 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
629 path_len = datalen - sizeof(iobj) - 1;
631 return got_error(GOT_ERR_PRIVSEP_LEN);
633 path = imsg->data + sizeof(iobj);
634 if (path[path_len] != '\0')
635 return got_error(GOT_ERR_PRIVSEP_LEN);
638 nallocated = min_alloc;
639 commit_ids = reallocarray(NULL, nallocated, sizeof(*commit_ids));
640 if (commit_ids == NULL)
641 return got_error_from_errno("reallocarray");
644 const size_t max_datalen = MAX_IMSGSIZE - IMSG_HEADER_SIZE;
647 if (sigint_received) {
648 err = got_error(GOT_ERR_CANCELLED);
652 if (commit == NULL) {
653 idx = got_packidx_get_object_idx(packidx, &id);
656 err = open_commit(&commit, pack, packidx,
659 if (err->code != GOT_ERR_NO_OBJ)
666 if (sizeof(struct got_imsg_traversed_commits) +
667 ncommits * SHA1_DIGEST_LENGTH >= max_datalen) {
668 err = send_traversed_commits(commit_ids, ncommits,
675 if (ncommits > nallocated) {
676 struct got_object_id *new;
677 nallocated += min_alloc;
678 new = reallocarray(commit_ids, nallocated,
679 sizeof(*commit_ids));
681 err = got_error_from_errno("reallocarray");
686 memcpy(commit_ids[ncommits - 1].sha1, id.sha1,
689 pid = STAILQ_FIRST(&commit->parent_ids);
693 idx = got_packidx_get_object_idx(packidx, pid->id);
697 err = open_commit(&pcommit, pack, packidx, idx, pid->id,
700 if (err->code != GOT_ERR_NO_OBJ)
706 if (path[0] == '/' && path[1] == '\0') {
707 if (got_object_id_cmp(pcommit->tree_id,
708 commit->tree_id) != 0) {
714 uint8_t *buf = NULL, *pbuf = NULL;
716 idx = got_packidx_get_object_idx(packidx,
720 pidx = got_packidx_get_object_idx(packidx,
725 err = open_tree(&buf, &entries, &nentries, pack,
726 packidx, idx, commit->tree_id, objcache);
729 err = open_tree(&pbuf, &pentries, &pnentries, pack,
730 packidx, pidx, pcommit->tree_id, objcache);
736 err = tree_path_changed(&changed, &buf, &pbuf,
737 &entries, &nentries, &pentries, &pnentries, path,
738 pack, packidx, ibuf, objcache);
740 got_object_parsed_tree_entries_free(&entries);
743 got_object_parsed_tree_entries_free(&pentries);
747 if (err->code != GOT_ERR_NO_OBJ)
755 memcpy(id.sha1, pid->id->sha1, SHA1_DIGEST_LENGTH);
756 got_object_commit_close(commit);
763 err = send_traversed_commits(commit_ids, ncommits, ibuf);
768 err = got_privsep_send_commit(ibuf, commit);
773 err = send_commit_traversal_done(ibuf);
777 got_object_commit_close(commit);
779 got_object_commit_close(pcommit);
781 got_object_parsed_tree_entries_free(&entries);
783 got_object_parsed_tree_entries_free(&pentries);
785 if (err->code == GOT_ERR_PRIVSEP_PIPE)
788 got_privsep_send_error(ibuf, err);
794 static const struct got_error *
795 raw_object_request(struct imsg *imsg, struct imsgbuf *ibuf,
796 struct got_pack *pack, struct got_packidx *packidx,
797 struct got_object_cache *objcache, FILE *basefile, FILE *accumfile)
799 const struct got_error *err = NULL;
802 FILE *outfile = NULL;
803 struct got_imsg_packed_object iobj;
804 struct got_object *obj;
805 struct got_object_id id;
808 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
809 if (datalen != sizeof(iobj))
810 return got_error(GOT_ERR_PRIVSEP_LEN);
811 memcpy(&iobj, imsg->data, sizeof(iobj));
812 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
814 obj = got_object_cache_get(objcache, &id);
818 err = open_object(&obj, pack, packidx, iobj.idx, &id,
824 err = receive_file(&outfile, ibuf, GOT_IMSG_RAW_OBJECT_OUTFD);
828 if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
829 err = got_pack_get_max_delta_object_size(&size, obj, pack);
835 if (size <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX)
836 err = got_packfile_extract_object_to_mem(&buf, &obj->size,
839 err = got_packfile_extract_object(pack, obj, outfile, basefile,
844 err = got_privsep_send_raw_obj(ibuf, obj->size, obj->hdrlen, buf);
847 if (outfile && fclose(outfile) == EOF && err == NULL)
848 err = got_error_from_errno("fclose");
849 got_object_close(obj);
850 if (err && err->code != GOT_ERR_PRIVSEP_PIPE)
851 got_privsep_send_error(ibuf, err);
858 static const struct got_error *
859 receive_packidx(struct got_packidx **packidx, struct imsgbuf *ibuf)
861 const struct got_error *err = NULL;
863 struct got_imsg_packidx ipackidx;
865 struct got_packidx *p;
869 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
873 p = calloc(1, sizeof(*p));
875 err = got_error_from_errno("calloc");
879 if (imsg.hdr.type != GOT_IMSG_PACKIDX) {
880 err = got_error(GOT_ERR_PRIVSEP_MSG);
885 err = got_error(GOT_ERR_PRIVSEP_NO_FD);
889 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
890 if (datalen != sizeof(ipackidx)) {
891 err = got_error(GOT_ERR_PRIVSEP_LEN);
894 memcpy(&ipackidx, imsg.data, sizeof(ipackidx));
896 p->len = ipackidx.len;
897 p->fd = dup(imsg.fd);
899 err = got_error_from_errno("dup");
902 if (lseek(p->fd, 0, SEEK_SET) == -1) {
903 err = got_error_from_errno("lseek");
907 #ifndef GOT_PACK_NO_MMAP
908 p->map = mmap(NULL, p->len, PROT_READ, MAP_PRIVATE, p->fd, 0);
909 if (p->map == MAP_FAILED)
910 p->map = NULL; /* fall back to read(2) */
912 err = got_packidx_init_hdr(p, 1, ipackidx.packfile_size);
917 got_packidx_close(p);
924 static const struct got_error *
925 receive_pack(struct got_pack **packp, struct imsgbuf *ibuf)
927 const struct got_error *err = NULL;
929 struct got_imsg_pack ipack;
931 struct got_pack *pack;
935 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
939 pack = calloc(1, sizeof(*pack));
941 err = got_error_from_errno("calloc");
945 if (imsg.hdr.type != GOT_IMSG_PACK) {
946 err = got_error(GOT_ERR_PRIVSEP_MSG);
951 err = got_error(GOT_ERR_PRIVSEP_NO_FD);
955 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
956 if (datalen != sizeof(ipack)) {
957 err = got_error(GOT_ERR_PRIVSEP_LEN);
960 memcpy(&ipack, imsg.data, sizeof(ipack));
962 pack->filesize = ipack.filesize;
963 pack->fd = dup(imsg.fd);
964 if (pack->fd == -1) {
965 err = got_error_from_errno("dup");
968 if (lseek(pack->fd, 0, SEEK_SET) == -1) {
969 err = got_error_from_errno("lseek");
972 pack->path_packfile = strdup(ipack.path_packfile);
973 if (pack->path_packfile == NULL) {
974 err = got_error_from_errno("strdup");
978 pack->delta_cache = got_delta_cache_alloc(100,
979 GOT_DELTA_RESULT_SIZE_CACHED_MAX);
980 if (pack->delta_cache == NULL) {
981 err = got_error_from_errno("got_delta_cache_alloc");
985 #ifndef GOT_PACK_NO_MMAP
986 pack->map = mmap(NULL, pack->filesize, PROT_READ, MAP_PRIVATE,
988 if (pack->map == MAP_FAILED)
989 pack->map = NULL; /* fall back to read(2) */
1003 main(int argc, char *argv[])
1005 const struct got_error *err = NULL;
1006 struct imsgbuf ibuf;
1008 struct got_packidx *packidx = NULL;
1009 struct got_pack *pack = NULL;
1010 struct got_object_cache objcache;
1011 FILE *basefile = NULL, *accumfile = NULL;
1013 //static int attached;
1014 //while (!attached) sleep(1);
1016 signal(SIGINT, catch_sigint);
1018 imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
1020 err = got_object_cache_init(&objcache, GOT_OBJECT_CACHE_TYPE_OBJ);
1022 err = got_error_from_errno("got_object_cache_init");
1023 got_privsep_send_error(&ibuf, err);
1028 /* revoke access to most system calls */
1029 if (pledge("stdio recvfd", NULL) == -1) {
1030 err = got_error_from_errno("pledge");
1031 got_privsep_send_error(&ibuf, err);
1036 err = receive_packidx(&packidx, &ibuf);
1038 got_privsep_send_error(&ibuf, err);
1042 err = receive_pack(&pack, &ibuf);
1044 got_privsep_send_error(&ibuf, err);
1051 if (sigint_received) {
1052 err = got_error(GOT_ERR_CANCELLED);
1056 err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
1058 if (err->code == GOT_ERR_PRIVSEP_PIPE)
1063 if (imsg.hdr.type == GOT_IMSG_STOP)
1066 switch (imsg.hdr.type) {
1067 case GOT_IMSG_TMPFD:
1068 err = receive_tempfile(&basefile, &accumfile,
1071 case GOT_IMSG_PACKED_OBJECT_REQUEST:
1072 err = object_request(&imsg, &ibuf, pack, packidx,
1075 case GOT_IMSG_PACKED_RAW_OBJECT_REQUEST:
1076 if (basefile == NULL || accumfile == NULL) {
1077 err = got_error(GOT_ERR_PRIVSEP_MSG);
1080 err = raw_object_request(&imsg, &ibuf, pack, packidx,
1081 &objcache, basefile, accumfile);
1083 case GOT_IMSG_COMMIT_REQUEST:
1084 err = commit_request(&imsg, &ibuf, pack, packidx,
1087 case GOT_IMSG_TREE_REQUEST:
1088 err = tree_request(&imsg, &ibuf, pack, packidx,
1091 case GOT_IMSG_BLOB_REQUEST:
1092 if (basefile == NULL || accumfile == NULL) {
1093 err = got_error(GOT_ERR_PRIVSEP_MSG);
1096 err = blob_request(&imsg, &ibuf, pack, packidx,
1097 &objcache, basefile, accumfile);
1099 case GOT_IMSG_TAG_REQUEST:
1100 err = tag_request(&imsg, &ibuf, pack, packidx,
1103 case GOT_IMSG_COMMIT_TRAVERSAL_REQUEST:
1104 err = commit_traversal_request(&imsg, &ibuf, pack,
1105 packidx, &objcache);
1108 err = got_error(GOT_ERR_PRIVSEP_MSG);
1112 if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
1113 err = got_error_from_errno("close");
1120 got_packidx_close(packidx);
1122 got_pack_close(pack);
1123 got_object_cache_close(&objcache);
1125 if (basefile && fclose(basefile) == EOF && err == NULL)
1126 err = got_error_from_errno("fclose");
1127 if (accumfile && fclose(accumfile) == EOF && err == NULL)
1128 err = got_error_from_errno("fclose");
1130 if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE) {
1131 fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
1132 got_privsep_send_error(&ibuf, err);
1135 if (close(GOT_IMSG_FD_CHILD) == -1 && err == NULL)
1136 err = got_error_from_errno("close");