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 blob_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
292 struct got_packidx *packidx, struct got_object_cache *objcache)
294 const struct got_error *err = NULL;
295 struct got_imsg_packed_object iobj;
296 struct got_object *obj = NULL;
297 FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
298 struct got_object_id id;
303 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
304 if (datalen != sizeof(iobj))
305 return got_error(GOT_ERR_PRIVSEP_LEN);
306 memcpy(&iobj, imsg->data, sizeof(iobj));
307 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
309 obj = got_object_cache_get(objcache, &id);
313 err = open_object(&obj, pack, packidx, iobj.idx, &id,
319 err = receive_file(&outfile, ibuf, GOT_IMSG_BLOB_OUTFD);
322 err = receive_file(&basefile, ibuf, GOT_IMSG_TMPFD);
325 err = receive_file(&accumfile, ibuf, GOT_IMSG_TMPFD);
329 if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
330 err = got_pack_get_max_delta_object_size(&blob_size, obj, pack);
334 blob_size = obj->size;
336 if (blob_size <= GOT_PRIVSEP_INLINE_BLOB_DATA_MAX)
337 err = got_packfile_extract_object_to_mem(&buf, &obj->size,
340 err = got_packfile_extract_object(pack, obj, outfile, basefile,
345 err = got_privsep_send_blob(ibuf, obj->size, obj->hdrlen, buf);
348 if (outfile && fclose(outfile) == EOF && err == NULL)
349 err = got_error_from_errno("fclose");
350 if (basefile && fclose(basefile) == EOF && err == NULL)
351 err = got_error_from_errno("fclose");
352 if (accumfile && fclose(accumfile) == EOF && err == NULL)
353 err = got_error_from_errno("fclose");
354 got_object_close(obj);
355 if (err && err->code != GOT_ERR_PRIVSEP_PIPE)
356 got_privsep_send_error(ibuf, err);
361 static const struct got_error *
362 tag_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
363 struct got_packidx *packidx, struct got_object_cache *objcache)
365 const struct got_error *err = NULL;
366 struct got_imsg_packed_object iobj;
367 struct got_object *obj = NULL;
368 struct got_tag_object *tag = NULL;
371 struct got_object_id id;
374 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
375 if (datalen != sizeof(iobj))
376 return got_error(GOT_ERR_PRIVSEP_LEN);
377 memcpy(&iobj, imsg->data, sizeof(iobj));
378 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
380 obj = got_object_cache_get(objcache, &id);
384 err = open_object(&obj, pack, packidx, iobj.idx, &id,
390 err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack);
395 err = got_object_parse_tag(&tag, buf, len);
399 err = got_privsep_send_tag(ibuf, tag);
402 got_object_close(obj);
404 got_object_tag_close(tag);
406 if (err->code == GOT_ERR_PRIVSEP_PIPE)
409 got_privsep_send_error(ibuf, err);
415 static struct got_parsed_tree_entry *
416 find_entry_by_name(struct got_pathlist_head *entries, int nentries,
417 const char *name, size_t len)
419 struct got_pathlist_entry *pe;
421 /* Note that tree entries are sorted in strncmp() order. */
422 TAILQ_FOREACH(pe, entries, entry) {
423 int cmp = strncmp(pe->path, name, len);
428 if (pe->path[len] == '\0')
429 return (struct got_parsed_tree_entry *)pe->data;
434 static const struct got_error *
435 tree_path_changed(int *changed, uint8_t **buf1, uint8_t **buf2,
436 struct got_pathlist_head *entries1, int *nentries1,
437 struct got_pathlist_head *entries2, int *nentries2,
438 const char *path, struct got_pack *pack, struct got_packidx *packidx,
439 struct imsgbuf *ibuf, struct got_object_cache *objcache)
441 const struct got_error *err = NULL;
442 struct got_parsed_tree_entry *pte1 = NULL, *pte2 = NULL;
448 /* We not do support comparing the root path. */
449 if (got_path_is_root_dir(path))
450 return got_error_path(path, GOT_ERR_BAD_PATH);
465 pte1 = find_entry_by_name(entries1, *nentries1, seg, seglen);
467 err = got_error(GOT_ERR_NO_OBJ);
471 pte2 = find_entry_by_name(entries2, *nentries2, seg, seglen);
477 if (pte1->mode != pte2->mode) {
482 if (memcmp(pte1->id, pte2->id, SHA1_DIGEST_LENGTH) == 0) {
487 if (*s == '\0') { /* final path element */
496 struct got_object_id id1, id2;
499 memcpy(id1.sha1, pte1->id, SHA1_DIGEST_LENGTH);
500 idx = got_packidx_get_object_idx(packidx, &id1);
502 err = got_error_no_obj(&id1);
505 got_object_parsed_tree_entries_free(entries1);
509 err = open_tree(buf1, entries1, nentries1, pack,
510 packidx, idx, &id1, objcache);
515 memcpy(id2.sha1, pte2->id, SHA1_DIGEST_LENGTH);
516 idx = got_packidx_get_object_idx(packidx, &id2);
518 err = got_error_no_obj(&id2);
521 got_object_parsed_tree_entries_free(entries2);
525 err = open_tree(buf2, entries2, nentries2, pack,
526 packidx, idx, &id2, objcache);
536 static const struct got_error *
537 send_traversed_commits(struct got_object_id *commit_ids, size_t ncommits,
538 struct imsgbuf *ibuf)
540 const struct got_error *err;
544 wbuf = imsg_create(ibuf, GOT_IMSG_TRAVERSED_COMMITS, 0, 0,
545 sizeof(struct got_imsg_traversed_commits) +
546 ncommits * SHA1_DIGEST_LENGTH);
548 return got_error_from_errno("imsg_create TRAVERSED_COMMITS");
550 if (imsg_add(wbuf, &ncommits, sizeof(ncommits)) == -1) {
551 err = got_error_from_errno("imsg_add TRAVERSED_COMMITS");
555 for (i = 0; i < ncommits; i++) {
556 struct got_object_id *id = &commit_ids[i];
557 if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1) {
558 err = got_error_from_errno(
559 "imsg_add TRAVERSED_COMMITS");
566 imsg_close(ibuf, wbuf);
568 return got_privsep_flush_imsg(ibuf);
571 static const struct got_error *
572 send_commit_traversal_done(struct imsgbuf *ibuf)
574 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_TRAVERSAL_DONE, 0, 0, -1,
576 return got_error_from_errno("imsg_compose TRAVERSAL_DONE");
578 return got_privsep_flush_imsg(ibuf);
582 static const struct got_error *
583 commit_traversal_request(struct imsg *imsg, struct imsgbuf *ibuf,
584 struct got_pack *pack, struct got_packidx *packidx,
585 struct got_object_cache *objcache)
587 const struct got_error *err = NULL;
588 struct got_imsg_packed_object iobj;
589 struct got_object_qid *pid;
590 struct got_commit_object *commit = NULL, *pcommit = NULL;
591 struct got_pathlist_head entries, pentries;
592 int nentries = 0, pnentries = 0;
593 struct got_object_id id;
594 size_t datalen, path_len;
596 const int min_alloc = 64;
597 int changed = 0, ncommits = 0, nallocated = 0;
598 struct got_object_id *commit_ids = NULL;
600 TAILQ_INIT(&entries);
601 TAILQ_INIT(&pentries);
603 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
604 if (datalen < sizeof(iobj))
605 return got_error(GOT_ERR_PRIVSEP_LEN);
606 memcpy(&iobj, imsg->data, sizeof(iobj));
607 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
609 path_len = datalen - sizeof(iobj) - 1;
611 return got_error(GOT_ERR_PRIVSEP_LEN);
613 path = imsg->data + sizeof(iobj);
614 if (path[path_len] != '\0')
615 return got_error(GOT_ERR_PRIVSEP_LEN);
618 nallocated = min_alloc;
619 commit_ids = reallocarray(NULL, nallocated, sizeof(*commit_ids));
620 if (commit_ids == NULL)
621 return got_error_from_errno("reallocarray");
624 const size_t max_datalen = MAX_IMSGSIZE - IMSG_HEADER_SIZE;
627 if (sigint_received) {
628 err = got_error(GOT_ERR_CANCELLED);
632 if (commit == NULL) {
633 idx = got_packidx_get_object_idx(packidx, &id);
636 err = open_commit(&commit, pack, packidx,
639 if (err->code != GOT_ERR_NO_OBJ)
646 if (sizeof(struct got_imsg_traversed_commits) +
647 ncommits * SHA1_DIGEST_LENGTH >= max_datalen) {
648 err = send_traversed_commits(commit_ids, ncommits,
655 if (ncommits > nallocated) {
656 struct got_object_id *new;
657 nallocated += min_alloc;
658 new = reallocarray(commit_ids, nallocated,
659 sizeof(*commit_ids));
661 err = got_error_from_errno("reallocarray");
666 memcpy(commit_ids[ncommits - 1].sha1, id.sha1,
669 pid = STAILQ_FIRST(&commit->parent_ids);
673 idx = got_packidx_get_object_idx(packidx, pid->id);
677 err = open_commit(&pcommit, pack, packidx, idx, pid->id,
680 if (err->code != GOT_ERR_NO_OBJ)
686 if (path[0] == '/' && path[1] == '\0') {
687 if (got_object_id_cmp(pcommit->tree_id,
688 commit->tree_id) != 0) {
694 uint8_t *buf = NULL, *pbuf = NULL;
696 idx = got_packidx_get_object_idx(packidx,
700 pidx = got_packidx_get_object_idx(packidx,
705 err = open_tree(&buf, &entries, &nentries, pack,
706 packidx, idx, commit->tree_id, objcache);
709 err = open_tree(&pbuf, &pentries, &pnentries, pack,
710 packidx, pidx, pcommit->tree_id, objcache);
716 err = tree_path_changed(&changed, &buf, &pbuf,
717 &entries, &nentries, &pentries, &pnentries, path,
718 pack, packidx, ibuf, objcache);
720 got_object_parsed_tree_entries_free(&entries);
723 got_object_parsed_tree_entries_free(&pentries);
727 if (err->code != GOT_ERR_NO_OBJ)
735 memcpy(id.sha1, pid->id->sha1, SHA1_DIGEST_LENGTH);
736 got_object_commit_close(commit);
743 err = send_traversed_commits(commit_ids, ncommits, ibuf);
748 err = got_privsep_send_commit(ibuf, commit);
753 err = send_commit_traversal_done(ibuf);
757 got_object_commit_close(commit);
759 got_object_commit_close(pcommit);
761 got_object_parsed_tree_entries_free(&entries);
763 got_object_parsed_tree_entries_free(&pentries);
765 if (err->code == GOT_ERR_PRIVSEP_PIPE)
768 got_privsep_send_error(ibuf, err);
774 static const struct got_error *
775 raw_object_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
776 struct got_packidx *packidx, struct got_object_cache *objcache)
778 const struct got_error *err = NULL;
781 FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
782 struct got_imsg_packed_object iobj;
783 struct got_object *obj;
784 struct got_object_id id;
787 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
788 if (datalen != sizeof(iobj))
789 return got_error(GOT_ERR_PRIVSEP_LEN);
790 memcpy(&iobj, imsg->data, sizeof(iobj));
791 memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
793 obj = got_object_cache_get(objcache, &id);
797 err = open_object(&obj, pack, packidx, iobj.idx, &id,
803 err = receive_file(&outfile, ibuf, GOT_IMSG_RAW_OBJECT_OUTFD);
806 err = receive_file(&basefile, ibuf, GOT_IMSG_TMPFD);
809 err = receive_file(&accumfile, ibuf, GOT_IMSG_TMPFD);
813 if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
814 err = got_pack_get_max_delta_object_size(&size, obj, pack);
820 if (size <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX)
821 err = got_packfile_extract_object_to_mem(&buf, &obj->size,
824 err = got_packfile_extract_object(pack, obj, outfile, basefile,
829 err = got_privsep_send_raw_obj(ibuf, obj->size, obj->hdrlen, buf);
832 if (outfile && fclose(outfile) == EOF && err == NULL)
833 err = got_error_from_errno("fclose");
834 if (basefile && fclose(basefile) == EOF && err == NULL)
835 err = got_error_from_errno("fclose");
836 if (accumfile && fclose(accumfile) == EOF && err == NULL)
837 err = got_error_from_errno("fclose");
838 got_object_close(obj);
839 if (err && err->code != GOT_ERR_PRIVSEP_PIPE)
840 got_privsep_send_error(ibuf, err);
847 static const struct got_error *
848 receive_packidx(struct got_packidx **packidx, struct imsgbuf *ibuf)
850 const struct got_error *err = NULL;
852 struct got_imsg_packidx ipackidx;
854 struct got_packidx *p;
858 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
862 p = calloc(1, sizeof(*p));
864 err = got_error_from_errno("calloc");
868 if (imsg.hdr.type != GOT_IMSG_PACKIDX) {
869 err = got_error(GOT_ERR_PRIVSEP_MSG);
874 err = got_error(GOT_ERR_PRIVSEP_NO_FD);
878 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
879 if (datalen != sizeof(ipackidx)) {
880 err = got_error(GOT_ERR_PRIVSEP_LEN);
883 memcpy(&ipackidx, imsg.data, sizeof(ipackidx));
885 p->len = ipackidx.len;
886 p->fd = dup(imsg.fd);
888 err = got_error_from_errno("dup");
891 if (lseek(p->fd, 0, SEEK_SET) == -1) {
892 err = got_error_from_errno("lseek");
896 #ifndef GOT_PACK_NO_MMAP
897 p->map = mmap(NULL, p->len, PROT_READ, MAP_PRIVATE, p->fd, 0);
898 if (p->map == MAP_FAILED)
899 p->map = NULL; /* fall back to read(2) */
901 err = got_packidx_init_hdr(p, 1, ipackidx.packfile_size);
906 got_packidx_close(p);
913 static const struct got_error *
914 receive_pack(struct got_pack **packp, struct imsgbuf *ibuf)
916 const struct got_error *err = NULL;
918 struct got_imsg_pack ipack;
920 struct got_pack *pack;
924 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
928 pack = calloc(1, sizeof(*pack));
930 err = got_error_from_errno("calloc");
934 if (imsg.hdr.type != GOT_IMSG_PACK) {
935 err = got_error(GOT_ERR_PRIVSEP_MSG);
940 err = got_error(GOT_ERR_PRIVSEP_NO_FD);
944 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
945 if (datalen != sizeof(ipack)) {
946 err = got_error(GOT_ERR_PRIVSEP_LEN);
949 memcpy(&ipack, imsg.data, sizeof(ipack));
951 pack->filesize = ipack.filesize;
952 pack->fd = dup(imsg.fd);
953 if (pack->fd == -1) {
954 err = got_error_from_errno("dup");
957 if (lseek(pack->fd, 0, SEEK_SET) == -1) {
958 err = got_error_from_errno("lseek");
961 pack->path_packfile = strdup(ipack.path_packfile);
962 if (pack->path_packfile == NULL) {
963 err = got_error_from_errno("strdup");
967 pack->delta_cache = got_delta_cache_alloc(100,
968 GOT_DELTA_RESULT_SIZE_CACHED_MAX);
969 if (pack->delta_cache == NULL) {
970 err = got_error_from_errno("got_delta_cache_alloc");
974 #ifndef GOT_PACK_NO_MMAP
975 pack->map = mmap(NULL, pack->filesize, PROT_READ, MAP_PRIVATE,
977 if (pack->map == MAP_FAILED)
978 pack->map = NULL; /* fall back to read(2) */
992 main(int argc, char *argv[])
994 const struct got_error *err = NULL;
997 struct got_packidx *packidx = NULL;
998 struct got_pack *pack = NULL;
999 struct got_object_cache objcache;
1001 //static int attached;
1002 //while (!attached) sleep(1);
1004 signal(SIGINT, catch_sigint);
1006 imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
1008 err = got_object_cache_init(&objcache, GOT_OBJECT_CACHE_TYPE_OBJ);
1010 err = got_error_from_errno("got_object_cache_init");
1011 got_privsep_send_error(&ibuf, err);
1016 /* revoke access to most system calls */
1017 if (pledge("stdio recvfd", NULL) == -1) {
1018 err = got_error_from_errno("pledge");
1019 got_privsep_send_error(&ibuf, err);
1024 err = receive_packidx(&packidx, &ibuf);
1026 got_privsep_send_error(&ibuf, err);
1030 err = receive_pack(&pack, &ibuf);
1032 got_privsep_send_error(&ibuf, err);
1039 if (sigint_received) {
1040 err = got_error(GOT_ERR_CANCELLED);
1044 err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
1046 if (err->code == GOT_ERR_PRIVSEP_PIPE)
1051 if (imsg.hdr.type == GOT_IMSG_STOP)
1054 switch (imsg.hdr.type) {
1055 case GOT_IMSG_PACKED_OBJECT_REQUEST:
1056 err = object_request(&imsg, &ibuf, pack, packidx,
1059 case GOT_IMSG_PACKED_RAW_OBJECT_REQUEST:
1060 err = raw_object_request(&imsg, &ibuf, pack, packidx,
1063 case GOT_IMSG_COMMIT_REQUEST:
1064 err = commit_request(&imsg, &ibuf, pack, packidx,
1067 case GOT_IMSG_TREE_REQUEST:
1068 err = tree_request(&imsg, &ibuf, pack, packidx,
1071 case GOT_IMSG_BLOB_REQUEST:
1072 err = blob_request(&imsg, &ibuf, pack, packidx,
1075 case GOT_IMSG_TAG_REQUEST:
1076 err = tag_request(&imsg, &ibuf, pack, packidx,
1079 case GOT_IMSG_COMMIT_TRAVERSAL_REQUEST:
1080 err = commit_traversal_request(&imsg, &ibuf, pack,
1081 packidx, &objcache);
1084 err = got_error(GOT_ERR_PRIVSEP_MSG);
1088 if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
1089 err = got_error_from_errno("close");
1096 got_packidx_close(packidx);
1098 got_pack_close(pack);
1099 got_object_cache_close(&objcache);
1102 if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE) {
1103 fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
1104 got_privsep_send_error(&ibuf, err);
1107 if (close(GOT_IMSG_FD_CHILD) == -1 && err == NULL)
1108 err = got_error_from_errno("close");