2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
3 * Copyright (c) 2020 Ori Bernstein <ori@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/types.h>
19 #include <sys/queue.h>
38 #include "got_compat.h"
40 #include "got_object.h"
41 #include "got_error.h"
43 #include "got_repository.h"
45 #include "got_lib_sha1.h"
46 #include "got_lib_delta.h"
47 #include "got_lib_inflate.h"
48 #include "got_lib_object.h"
49 #include "got_lib_object_parse.h"
50 #include "got_lib_privsep.h"
51 #include "got_lib_pack.h"
52 #include "got_lib_poll.h"
54 #include "got_privsep.h"
57 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
61 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
64 static const struct got_error *
65 read_imsg(struct imsgbuf *ibuf)
67 const struct got_error *err;
70 err = got_poll_fd(ibuf->fd, POLLIN, INFTIM);
72 if (err->code == GOT_ERR_EOF)
73 return got_error(GOT_ERR_PRIVSEP_PIPE);
79 if (errno == EAGAIN) /* Could be a file-descriptor leak. */
80 return got_error(GOT_ERR_PRIVSEP_NO_FD);
81 return got_error(GOT_ERR_PRIVSEP_READ);
84 return got_error(GOT_ERR_PRIVSEP_PIPE);
89 const struct got_error *
90 got_privsep_wait_for_child(pid_t pid)
94 if (waitpid(pid, &child_status, 0) == -1)
95 return got_error_from_errno("waitpid");
97 if (!WIFEXITED(child_status))
98 return got_error(GOT_ERR_PRIVSEP_DIED);
100 if (WEXITSTATUS(child_status) != 0)
101 return got_error(GOT_ERR_PRIVSEP_EXIT);
106 static const struct got_error *
107 recv_imsg_error(struct imsg *imsg, size_t datalen)
109 struct got_imsg_error *ierr;
111 if (datalen != sizeof(*ierr))
112 return got_error(GOT_ERR_PRIVSEP_LEN);
115 if (ierr->code == GOT_ERR_ERRNO) {
116 static struct got_error serr;
117 serr.code = GOT_ERR_ERRNO;
118 serr.msg = strerror(ierr->errno_code);
122 return got_error(ierr->code);
125 const struct got_error *
126 got_privsep_recv_imsg(struct imsg *imsg, struct imsgbuf *ibuf,
129 const struct got_error *err;
132 n = imsg_get(ibuf, imsg);
134 return got_error_from_errno("imsg_get");
137 err = read_imsg(ibuf);
140 n = imsg_get(ibuf, imsg);
142 return got_error_from_errno("imsg_get");
145 if (imsg->hdr.len < IMSG_HEADER_SIZE + min_datalen)
146 return got_error(GOT_ERR_PRIVSEP_LEN);
148 if (imsg->hdr.type == GOT_IMSG_ERROR) {
149 size_t datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
150 return recv_imsg_error(imsg, datalen);
156 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
158 got_privsep_send_error(struct imsgbuf *ibuf, const struct got_error *err)
160 const struct got_error *poll_err;
161 struct got_imsg_error ierr;
164 ierr.code = err->code;
165 if (err->code == GOT_ERR_ERRNO)
166 ierr.errno_code = errno;
169 ret = imsg_compose(ibuf, GOT_IMSG_ERROR, 0, 0, -1, &ierr, sizeof(ierr));
171 fprintf(stderr, "%s: error %d \"%s\": imsg_compose: %s\n",
172 getprogname(), err->code, err->msg, strerror(errno));
176 poll_err = got_poll_fd(ibuf->fd, POLLOUT, INFTIM);
178 fprintf(stderr, "%s: error %d \"%s\": poll: %s\n",
179 getprogname(), err->code, err->msg, poll_err->msg);
183 ret = imsg_flush(ibuf);
185 fprintf(stderr, "%s: error %d \"%s\": imsg_flush: %s\n",
186 getprogname(), err->code, err->msg, strerror(errno));
192 static const struct got_error *
193 flush_imsg(struct imsgbuf *ibuf)
195 const struct got_error *err;
197 err = got_poll_fd(ibuf->fd, POLLOUT, INFTIM);
201 if (imsg_flush(ibuf) == -1) {
203 return got_error_from_errno("imsg_flush");
209 const struct got_error *
210 got_privsep_flush_imsg(struct imsgbuf *ibuf)
212 return flush_imsg(ibuf);
215 const struct got_error *
216 got_privsep_send_stop(int fd)
218 const struct got_error *err = NULL;
221 imsg_init(&ibuf, fd);
223 if (imsg_compose(&ibuf, GOT_IMSG_STOP, 0, 0, -1, NULL, 0) == -1)
224 return got_error_from_errno("imsg_compose STOP");
226 err = flush_imsg(&ibuf);
230 const struct got_error *
231 got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd,
232 struct got_object_id *id)
234 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_REQUEST, 0, 0, fd,
235 id, sizeof(*id)) == -1)
236 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
238 return flush_imsg(ibuf);
241 const struct got_error *
242 got_privsep_send_raw_obj_req(struct imsgbuf *ibuf, int fd,
243 struct got_object_id *id)
245 if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_REQUEST, 0, 0, fd,
246 id, sizeof(*id)) == -1)
247 return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
249 return flush_imsg(ibuf);
252 const struct got_error *
253 got_privsep_send_raw_obj_outfd(struct imsgbuf *ibuf, int outfd)
255 const struct got_error *err = NULL;
257 if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_OUTFD, 0, 0, outfd, NULL, 0)
259 err = got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
264 return flush_imsg(ibuf);
267 const struct got_error *
268 got_privsep_send_raw_obj(struct imsgbuf *ibuf, off_t size, size_t hdrlen,
271 const struct got_error *err = NULL;
272 struct got_imsg_raw_obj iobj;
273 size_t len = sizeof(iobj);
276 memset(&iobj, 0, sizeof(iobj));
277 iobj.hdrlen = hdrlen;
280 if (data && size + hdrlen <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX)
281 len += (size_t)size + hdrlen;
283 wbuf = imsg_create(ibuf, GOT_IMSG_RAW_OBJECT, 0, 0, len);
285 err = got_error_from_errno("imsg_create RAW_OBJECT");
289 if (imsg_add(wbuf, &iobj, sizeof(iobj)) == -1)
290 return got_error_from_errno("imsg_add RAW_OBJECT");
292 if (data && size + hdrlen <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX) {
293 if (imsg_add(wbuf, data, size + hdrlen) == -1)
294 return got_error_from_errno("imsg_add RAW_OBJECT");
298 imsg_close(ibuf, wbuf);
300 return flush_imsg(ibuf);
303 const struct got_error *
304 got_privsep_recv_raw_obj(uint8_t **outbuf, off_t *size, size_t *hdrlen,
305 struct imsgbuf *ibuf)
307 const struct got_error *err = NULL;
309 struct got_imsg_raw_obj *iobj;
314 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
318 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
320 switch (imsg.hdr.type) {
321 case GOT_IMSG_RAW_OBJECT:
322 if (datalen < sizeof(*iobj)) {
323 err = got_error(GOT_ERR_PRIVSEP_LEN);
328 *hdrlen = iobj->hdrlen;
330 if (datalen == sizeof(*iobj)) {
331 /* Data has been written to file descriptor. */
336 *size + *hdrlen > GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX) {
337 err = got_error(GOT_ERR_PRIVSEP_LEN);
341 *outbuf = malloc(*size + *hdrlen);
342 if (*outbuf == NULL) {
343 err = got_error_from_errno("malloc");
346 memcpy(*outbuf, imsg.data + sizeof(*iobj), *size + *hdrlen);
349 err = got_error(GOT_ERR_PRIVSEP_MSG);
358 const struct got_error *
359 got_privsep_send_commit_req(struct imsgbuf *ibuf, int fd,
360 struct got_object_id *id, int pack_idx)
362 const struct got_error *err = NULL;
363 struct got_imsg_packed_object iobj;
367 memset(&iobj, 0, sizeof(iobj));
368 if (pack_idx != -1) { /* commit is packed */
370 memcpy(&iobj.id, id, sizeof(iobj.id));
378 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, data, len)
380 err = got_error_from_errno("imsg_compose COMMIT_REQUEST");
385 return flush_imsg(ibuf);
388 const struct got_error *
389 got_privsep_send_tree_req(struct imsgbuf *ibuf, int fd,
390 struct got_object_id *id, int pack_idx)
396 len = sizeof(struct got_imsg_packed_object);
400 wbuf = imsg_create(ibuf, GOT_IMSG_TREE_REQUEST, 0, 0, len);
402 return got_error_from_errno("imsg_create TREE_REQUEST");
404 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
405 return got_error_from_errno("imsg_add TREE_REQUEST");
407 if (pack_idx != -1) { /* tree is packed */
408 if (imsg_add(wbuf, &pack_idx, sizeof(pack_idx)) == -1)
409 return got_error_from_errno("imsg_add TREE_REQUEST");
413 imsg_close(ibuf, wbuf);
415 return flush_imsg(ibuf);
418 const struct got_error *
419 got_privsep_send_tag_req(struct imsgbuf *ibuf, int fd,
420 struct got_object_id *id, int pack_idx)
422 struct got_imsg_packed_object iobj;
426 memset(&iobj, 0, sizeof(iobj));
427 if (pack_idx != -1) { /* tag is packed */
429 memcpy(&iobj.id, id, sizeof(iobj.id));
437 if (imsg_compose(ibuf, GOT_IMSG_TAG_REQUEST, 0, 0, fd, data, len)
439 return got_error_from_errno("imsg_compose TAG_REQUEST");
441 return flush_imsg(ibuf);
444 const struct got_error *
445 got_privsep_send_blob_req(struct imsgbuf *ibuf, int infd,
446 struct got_object_id *id, int pack_idx)
448 const struct got_error *err = NULL;
449 struct got_imsg_packed_object iobj;
453 memset(&iobj, 0, sizeof(iobj));
454 if (pack_idx != -1) { /* blob is packed */
456 memcpy(&iobj.id, id, sizeof(iobj.id));
464 if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, data, len)
466 err = got_error_from_errno("imsg_compose BLOB_REQUEST");
471 return flush_imsg(ibuf);
474 const struct got_error *
475 got_privsep_send_blob_outfd(struct imsgbuf *ibuf, int outfd)
477 const struct got_error *err = NULL;
479 if (imsg_compose(ibuf, GOT_IMSG_BLOB_OUTFD, 0, 0, outfd, NULL, 0)
481 err = got_error_from_errno("imsg_compose BLOB_OUTFD");
486 return flush_imsg(ibuf);
489 static const struct got_error *
490 send_fd(struct imsgbuf *ibuf, int imsg_code, int fd)
492 const struct got_error *err = NULL;
494 if (imsg_compose(ibuf, imsg_code, 0, 0, fd, NULL, 0) == -1) {
495 err = got_error_from_errno("imsg_compose TMPFD");
500 return flush_imsg(ibuf);
503 const struct got_error *
504 got_privsep_send_tmpfd(struct imsgbuf *ibuf, int fd)
506 return send_fd(ibuf, GOT_IMSG_TMPFD, fd);
509 const struct got_error *
510 got_privsep_send_obj(struct imsgbuf *ibuf, struct got_object *obj)
512 struct got_imsg_object iobj;
514 memset(&iobj, 0, sizeof(iobj));
516 memcpy(&iobj.id, &obj->id, sizeof(iobj.id));
517 iobj.type = obj->type;
518 iobj.flags = obj->flags;
519 iobj.hdrlen = obj->hdrlen;
520 iobj.size = obj->size;
521 if (iobj.flags & GOT_OBJ_FLAG_PACKED) {
522 iobj.pack_offset = obj->pack_offset;
523 iobj.pack_idx = obj->pack_idx;
526 if (imsg_compose(ibuf, GOT_IMSG_OBJECT, 0, 0, -1, &iobj, sizeof(iobj))
528 return got_error_from_errno("imsg_compose OBJECT");
530 return flush_imsg(ibuf);
533 const struct got_error *
534 got_privsep_send_fetch_req(struct imsgbuf *ibuf, int fd,
535 struct got_pathlist_head *have_refs, int fetch_all_branches,
536 struct got_pathlist_head *wanted_branches,
537 struct got_pathlist_head *wanted_refs, int list_refs_only,
538 const char *worktree_branch, const char *remote_head,
539 int no_head, int verbosity)
541 const struct got_error *err = NULL;
543 struct got_pathlist_entry *pe;
544 struct got_imsg_fetch_request fetchreq;
545 size_t remote_head_len, worktree_branch_len, len = sizeof(fetchreq);
547 if (worktree_branch) {
548 worktree_branch_len = strlen(worktree_branch);
549 len += worktree_branch_len;
552 remote_head_len = strlen(remote_head);
553 len += remote_head_len;
556 if (len >= MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
558 return got_error(GOT_ERR_NO_SPACE);
561 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_REQUEST, 0, 0, len);
563 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
565 memset(&fetchreq, 0, sizeof(fetchreq));
566 fetchreq.no_head = no_head;
567 fetchreq.fetch_all_branches = fetch_all_branches;
568 fetchreq.list_refs_only = list_refs_only;
569 fetchreq.verbosity = verbosity;
570 if (worktree_branch != NULL)
571 fetchreq.worktree_branch_len = worktree_branch_len;
572 if (remote_head != NULL)
573 fetchreq.remote_head_len = remote_head_len;
574 TAILQ_FOREACH(pe, have_refs, entry)
575 fetchreq.n_have_refs++;
576 TAILQ_FOREACH(pe, wanted_branches, entry)
577 fetchreq.n_wanted_branches++;
578 TAILQ_FOREACH(pe, wanted_refs, entry)
579 fetchreq.n_wanted_refs++;
580 if (imsg_add(wbuf, &fetchreq, sizeof(fetchreq)) == -1)
581 return got_error_from_errno("imsg_add FETCH_REQUEST");
582 if (worktree_branch) {
583 if (imsg_add(wbuf, worktree_branch, worktree_branch_len) == -1)
584 return got_error_from_errno("imsg_add FETCH_REQUEST");
587 if (imsg_add(wbuf, remote_head, remote_head_len) == -1)
588 return got_error_from_errno("imsg_add FETCH_REQUEST");
591 imsg_close(ibuf, wbuf);
593 err = flush_imsg(ibuf);
600 TAILQ_FOREACH(pe, have_refs, entry) {
601 const char *name = pe->path;
602 size_t name_len = pe->path_len;
603 struct got_object_id *id = pe->data;
605 len = sizeof(struct got_imsg_fetch_have_ref) + name_len;
606 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_HAVE_REF, 0, 0, len);
608 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
610 /* Keep in sync with struct got_imsg_fetch_have_ref! */
611 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
612 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
613 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
614 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
615 if (imsg_add(wbuf, name, name_len) == -1)
616 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
619 imsg_close(ibuf, wbuf);
620 err = flush_imsg(ibuf);
625 TAILQ_FOREACH(pe, wanted_branches, entry) {
626 const char *name = pe->path;
627 size_t name_len = pe->path_len;
629 len = sizeof(struct got_imsg_fetch_wanted_branch) + name_len;
630 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_WANTED_BRANCH, 0, 0,
633 return got_error_from_errno(
634 "imsg_create FETCH_WANTED_BRANCH");
636 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
637 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
638 return got_error_from_errno(
639 "imsg_add FETCH_WANTED_BRANCH");
640 if (imsg_add(wbuf, name, name_len) == -1)
641 return got_error_from_errno(
642 "imsg_add FETCH_WANTED_BRANCH");
645 imsg_close(ibuf, wbuf);
646 err = flush_imsg(ibuf);
651 TAILQ_FOREACH(pe, wanted_refs, entry) {
652 const char *name = pe->path;
653 size_t name_len = pe->path_len;
655 len = sizeof(struct got_imsg_fetch_wanted_ref) + name_len;
656 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_WANTED_REF, 0, 0,
659 return got_error_from_errno(
660 "imsg_create FETCH_WANTED_REF");
662 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
663 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
664 return got_error_from_errno(
665 "imsg_add FETCH_WANTED_REF");
666 if (imsg_add(wbuf, name, name_len) == -1)
667 return got_error_from_errno(
668 "imsg_add FETCH_WANTED_REF");
671 imsg_close(ibuf, wbuf);
672 err = flush_imsg(ibuf);
682 const struct got_error *
683 got_privsep_send_fetch_outfd(struct imsgbuf *ibuf, int fd)
685 return send_fd(ibuf, GOT_IMSG_FETCH_OUTFD, fd);
688 const struct got_error *
689 got_privsep_recv_fetch_progress(int *done, struct got_object_id **id,
690 char **refname, struct got_pathlist_head *symrefs, char **server_progress,
691 off_t *packfile_size, uint8_t *pack_sha1, struct imsgbuf *ibuf)
693 const struct got_error *err = NULL;
696 struct got_imsg_fetch_symrefs *isymrefs = NULL;
704 *server_progress = NULL;
706 memset(pack_sha1, 0, SHA1_DIGEST_LENGTH);
708 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
712 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
713 switch (imsg.hdr.type) {
714 case GOT_IMSG_FETCH_SYMREFS:
715 if (datalen < sizeof(*isymrefs)) {
716 err = got_error(GOT_ERR_PRIVSEP_LEN);
719 if (isymrefs != NULL) {
720 err = got_error(GOT_ERR_PRIVSEP_MSG);
723 isymrefs = (struct got_imsg_fetch_symrefs *)imsg.data;
724 off = sizeof(*isymrefs);
725 remain = datalen - off;
726 for (n = 0; n < isymrefs->nsymrefs; n++) {
727 struct got_imsg_fetch_symref *s;
729 if (remain < sizeof(struct got_imsg_fetch_symref)) {
730 err = got_error(GOT_ERR_PRIVSEP_LEN);
733 s = (struct got_imsg_fetch_symref *)(imsg.data + off);
735 remain -= sizeof(*s);
736 if (remain < s->name_len) {
737 err = got_error(GOT_ERR_PRIVSEP_LEN);
740 name = strndup(imsg.data + off, s->name_len);
742 err = got_error_from_errno("strndup");
746 remain -= s->name_len;
747 if (remain < s->target_len) {
748 err = got_error(GOT_ERR_PRIVSEP_LEN);
752 target = strndup(imsg.data + off, s->target_len);
753 if (target == NULL) {
754 err = got_error_from_errno("strndup");
758 off += s->target_len;
759 remain -= s->target_len;
760 err = got_pathlist_append(symrefs, name, target);
768 case GOT_IMSG_FETCH_REF:
769 if (datalen <= sizeof(**id)) {
770 err = got_error(GOT_ERR_PRIVSEP_MSG);
773 *id = malloc(sizeof(**id));
775 err = got_error_from_errno("malloc");
778 memcpy(*id, imsg.data, sizeof(**id));
779 *refname = strndup(imsg.data + sizeof(**id),
780 datalen - sizeof(**id));
781 if (*refname == NULL) {
782 err = got_error_from_errno("strndup");
786 case GOT_IMSG_FETCH_SERVER_PROGRESS:
788 err = got_error(GOT_ERR_PRIVSEP_LEN);
791 *server_progress = strndup(imsg.data, datalen);
792 if (*server_progress == NULL) {
793 err = got_error_from_errno("strndup");
796 for (i = 0; i < datalen; i++) {
797 if (!isprint((unsigned char)(*server_progress)[i]) &&
798 !isspace((unsigned char)(*server_progress)[i])) {
799 err = got_error(GOT_ERR_PRIVSEP_MSG);
800 free(*server_progress);
801 *server_progress = NULL;
806 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS:
807 if (datalen < sizeof(*packfile_size)) {
808 err = got_error(GOT_ERR_PRIVSEP_MSG);
811 memcpy(packfile_size, imsg.data, sizeof(*packfile_size));
813 case GOT_IMSG_FETCH_DONE:
814 if (datalen != SHA1_DIGEST_LENGTH) {
815 err = got_error(GOT_ERR_PRIVSEP_MSG);
818 memcpy(pack_sha1, imsg.data, SHA1_DIGEST_LENGTH);
822 err = got_error(GOT_ERR_PRIVSEP_MSG);
836 static const struct got_error *
837 send_send_ref(const char *name, size_t name_len, struct got_object_id *id,
838 int delete, struct imsgbuf *ibuf)
843 len = sizeof(struct got_imsg_send_ref) + name_len;
844 wbuf = imsg_create(ibuf, GOT_IMSG_SEND_REF, 0, 0, len);
846 return got_error_from_errno("imsg_create SEND_REF");
848 /* Keep in sync with struct got_imsg_send_ref! */
849 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
850 return got_error_from_errno("imsg_add SEND_REF");
851 if (imsg_add(wbuf, &delete, sizeof(delete)) == -1)
852 return got_error_from_errno("imsg_add SEND_REF");
853 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
854 return got_error_from_errno("imsg_add SEND_REF");
855 if (imsg_add(wbuf, name, name_len) == -1)
856 return got_error_from_errno("imsg_add SEND_REF");
859 imsg_close(ibuf, wbuf);
860 return flush_imsg(ibuf);
863 const struct got_error *
864 got_privsep_send_send_req(struct imsgbuf *ibuf, int fd,
865 struct got_pathlist_head *have_refs,
866 struct got_pathlist_head *delete_refs,
869 const struct got_error *err = NULL;
870 struct got_pathlist_entry *pe;
871 struct got_imsg_send_request sendreq;
872 struct got_object_id zero_id;
874 memset(&zero_id, 0, sizeof(zero_id));
875 memset(&sendreq, 0, sizeof(sendreq));
876 sendreq.verbosity = verbosity;
877 TAILQ_FOREACH(pe, have_refs, entry)
879 TAILQ_FOREACH(pe, delete_refs, entry)
881 if (imsg_compose(ibuf, GOT_IMSG_SEND_REQUEST, 0, 0, fd,
882 &sendreq, sizeof(sendreq)) == -1) {
883 err = got_error_from_errno(
884 "imsg_compose FETCH_SERVER_PROGRESS");
888 err = flush_imsg(ibuf);
893 TAILQ_FOREACH(pe, have_refs, entry) {
894 const char *name = pe->path;
895 size_t name_len = pe->path_len;
896 struct got_object_id *id = pe->data;
897 err = send_send_ref(name, name_len, id, 0, ibuf);
902 TAILQ_FOREACH(pe, delete_refs, entry) {
903 const char *name = pe->path;
904 size_t name_len = pe->path_len;
905 err = send_send_ref(name, name_len, &zero_id, 1, ibuf);
910 if (fd != -1 && close(fd) == -1 && err == NULL)
911 err = got_error_from_errno("close");
916 const struct got_error *
917 got_privsep_recv_send_remote_refs(struct got_pathlist_head *remote_refs,
918 struct imsgbuf *ibuf)
920 const struct got_error *err = NULL;
924 struct got_imsg_send_remote_ref iremote_ref;
925 struct got_object_id *id = NULL;
926 char *refname = NULL;
927 struct got_pathlist_entry *new;
930 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
933 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
934 switch (imsg.hdr.type) {
935 case GOT_IMSG_SEND_REMOTE_REF:
936 if (datalen < sizeof(iremote_ref)) {
937 err = got_error(GOT_ERR_PRIVSEP_MSG);
940 memcpy(&iremote_ref, imsg.data, sizeof(iremote_ref));
941 if (datalen != sizeof(iremote_ref) +
942 iremote_ref.name_len) {
943 err = got_error(GOT_ERR_PRIVSEP_MSG);
946 id = malloc(sizeof(*id));
948 err = got_error_from_errno("malloc");
951 memcpy(id, &iremote_ref.id, sizeof(*id));
952 refname = strndup(imsg.data + sizeof(iremote_ref),
953 datalen - sizeof(iremote_ref));
954 if (refname == NULL) {
955 err = got_error_from_errno("strndup");
958 err = got_pathlist_insert(&new, remote_refs,
962 if (new == NULL) { /* duplicate which wasn't inserted */
969 case GOT_IMSG_SEND_PACK_REQUEST:
971 err = got_error(GOT_ERR_PRIVSEP_MSG);
974 /* got-send-pack is now waiting for a pack file. */
978 err = got_error(GOT_ERR_PRIVSEP_MSG);
989 const struct got_error *
990 got_privsep_send_packfd(struct imsgbuf *ibuf, int fd)
992 return send_fd(ibuf, GOT_IMSG_SEND_PACKFD, fd);
995 const struct got_error *
996 got_privsep_recv_send_progress(int *done, off_t *bytes_sent,
997 int *success, char **refname, char **errmsg, struct imsgbuf *ibuf)
999 const struct got_error *err = NULL;
1002 struct got_imsg_send_ref_status iref_status;
1004 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1010 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
1014 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1015 switch (imsg.hdr.type) {
1016 case GOT_IMSG_SEND_UPLOAD_PROGRESS:
1017 if (datalen < sizeof(*bytes_sent)) {
1018 err = got_error(GOT_ERR_PRIVSEP_MSG);
1021 memcpy(bytes_sent, imsg.data, sizeof(*bytes_sent));
1023 case GOT_IMSG_SEND_REF_STATUS:
1024 if (datalen < sizeof(iref_status)) {
1025 err = got_error(GOT_ERR_PRIVSEP_MSG);
1028 memcpy(&iref_status, imsg.data, sizeof(iref_status));
1029 if (datalen != sizeof(iref_status) + iref_status.name_len +
1030 iref_status.errmsg_len) {
1031 err = got_error(GOT_ERR_PRIVSEP_MSG);
1034 *success = iref_status.success;
1035 *refname = strndup(imsg.data + sizeof(iref_status),
1036 iref_status.name_len);
1038 if (iref_status.errmsg_len != 0)
1039 *errmsg = strndup(imsg.data + sizeof(iref_status) +
1040 iref_status.name_len, iref_status.errmsg_len);
1042 case GOT_IMSG_SEND_DONE:
1044 err = got_error(GOT_ERR_PRIVSEP_MSG);
1050 err = got_error(GOT_ERR_PRIVSEP_MSG);
1058 const struct got_error *
1059 got_privsep_send_index_pack_req(struct imsgbuf *ibuf, uint8_t *pack_sha1,
1062 const struct got_error *err = NULL;
1064 /* Keep in sync with struct got_imsg_index_pack_request */
1065 if (imsg_compose(ibuf, GOT_IMSG_IDXPACK_REQUEST, 0, 0, fd,
1066 pack_sha1, SHA1_DIGEST_LENGTH) == -1) {
1067 err = got_error_from_errno("imsg_compose INDEX_REQUEST");
1071 return flush_imsg(ibuf);
1074 const struct got_error *
1075 got_privsep_send_index_pack_outfd(struct imsgbuf *ibuf, int fd)
1077 return send_fd(ibuf, GOT_IMSG_IDXPACK_OUTFD, fd);
1080 const struct got_error *
1081 got_privsep_recv_index_progress(int *done, int *nobj_total,
1082 int *nobj_indexed, int *nobj_loose, int *nobj_resolved,
1083 struct imsgbuf *ibuf)
1085 const struct got_error *err = NULL;
1087 struct got_imsg_index_pack_progress *iprogress;
1095 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
1099 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1100 switch (imsg.hdr.type) {
1101 case GOT_IMSG_IDXPACK_PROGRESS:
1102 if (datalen < sizeof(*iprogress)) {
1103 err = got_error(GOT_ERR_PRIVSEP_LEN);
1106 iprogress = (struct got_imsg_index_pack_progress *)imsg.data;
1107 if (iprogress->nobj_total < 0 || iprogress->nobj_indexed < 0 ||
1108 iprogress->nobj_loose < 0 || iprogress->nobj_resolved < 0) {
1109 err = got_error(GOT_ERR_RANGE);
1112 *nobj_total = iprogress->nobj_total;
1113 *nobj_indexed = iprogress->nobj_indexed;
1114 *nobj_loose = iprogress->nobj_loose;
1115 *nobj_resolved = iprogress->nobj_resolved;
1117 case GOT_IMSG_IDXPACK_DONE:
1119 err = got_error(GOT_ERR_PRIVSEP_LEN);
1125 err = got_error(GOT_ERR_PRIVSEP_MSG);
1133 const struct got_error *
1134 got_privsep_get_imsg_obj(struct got_object **obj, struct imsg *imsg,
1135 struct imsgbuf *ibuf)
1137 struct got_imsg_object *iobj;
1138 size_t datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1140 if (datalen != sizeof(*iobj))
1141 return got_error(GOT_ERR_PRIVSEP_LEN);
1144 if (iobj->pack_offset < 0)
1145 return got_error(GOT_ERR_PACK_OFFSET);
1147 *obj = calloc(1, sizeof(**obj));
1149 return got_error_from_errno("calloc");
1151 memcpy(&(*obj)->id, &iobj->id, sizeof(iobj->id));
1152 (*obj)->type = iobj->type;
1153 (*obj)->flags = iobj->flags;
1154 (*obj)->hdrlen = iobj->hdrlen;
1155 (*obj)->size = iobj->size;
1156 /* path_packfile is handled by caller */
1157 if (iobj->flags & GOT_OBJ_FLAG_PACKED) {
1158 (*obj)->pack_offset = iobj->pack_offset;
1159 (*obj)->pack_idx = iobj->pack_idx;
1161 STAILQ_INIT(&(*obj)->deltas.entries);
1165 const struct got_error *
1166 got_privsep_recv_obj(struct got_object **obj, struct imsgbuf *ibuf)
1168 const struct got_error *err = NULL;
1170 const size_t min_datalen =
1171 MIN(sizeof(struct got_imsg_error), sizeof(struct got_imsg_object));
1175 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1179 switch (imsg.hdr.type) {
1180 case GOT_IMSG_OBJECT:
1181 err = got_privsep_get_imsg_obj(obj, &imsg, ibuf);
1184 err = got_error(GOT_ERR_PRIVSEP_MSG);
1193 static const struct got_error *
1194 send_commit_logmsg(struct imsgbuf *ibuf, struct got_commit_object *commit,
1197 const struct got_error *err = NULL;
1198 size_t offset, remain;
1201 remain = logmsg_len;
1202 while (remain > 0) {
1203 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
1205 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_LOGMSG, 0, 0, -1,
1206 commit->logmsg + offset, n) == -1) {
1207 err = got_error_from_errno("imsg_compose "
1212 err = flush_imsg(ibuf);
1223 const struct got_error *
1224 got_privsep_send_commit(struct imsgbuf *ibuf, struct got_commit_object *commit)
1226 const struct got_error *err = NULL;
1227 struct got_imsg_commit_object *icommit;
1230 struct got_object_qid *qid;
1231 size_t author_len = strlen(commit->author);
1232 size_t committer_len = strlen(commit->committer);
1233 size_t logmsg_len = strlen(commit->logmsg);
1235 total = sizeof(*icommit) + author_len + committer_len +
1236 commit->nparents * sizeof(struct got_object_id);
1238 buf = malloc(total);
1240 return got_error_from_errno("malloc");
1242 icommit = (struct got_imsg_commit_object *)buf;
1243 memcpy(&icommit->tree_id, commit->tree_id, sizeof(icommit->tree_id));
1244 icommit->author_len = author_len;
1245 icommit->author_time = commit->author_time;
1246 icommit->author_gmtoff = commit->author_gmtoff;
1247 icommit->committer_len = committer_len;
1248 icommit->committer_time = commit->committer_time;
1249 icommit->committer_gmtoff = commit->committer_gmtoff;
1250 icommit->logmsg_len = logmsg_len;
1251 icommit->nparents = commit->nparents;
1253 len = sizeof(*icommit);
1254 memcpy(buf + len, commit->author, author_len);
1256 memcpy(buf + len, commit->committer, committer_len);
1257 len += committer_len;
1258 STAILQ_FOREACH(qid, &commit->parent_ids, entry) {
1259 memcpy(buf + len, &qid->id, sizeof(qid->id));
1260 len += sizeof(qid->id);
1263 if (imsg_compose(ibuf, GOT_IMSG_COMMIT, 0, 0, -1, buf, len) == -1) {
1264 err = got_error_from_errno("imsg_compose COMMIT");
1268 if (logmsg_len == 0 ||
1269 logmsg_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
1270 err = flush_imsg(ibuf);
1274 err = send_commit_logmsg(ibuf, commit, logmsg_len);
1280 static const struct got_error *
1281 get_commit_from_imsg(struct got_commit_object **commit,
1282 struct imsg *imsg, size_t datalen, struct imsgbuf *ibuf)
1284 const struct got_error *err = NULL;
1285 struct got_imsg_commit_object *icommit;
1289 if (datalen < sizeof(*icommit))
1290 return got_error(GOT_ERR_PRIVSEP_LEN);
1292 icommit = imsg->data;
1293 if (datalen != sizeof(*icommit) + icommit->author_len +
1294 icommit->committer_len +
1295 icommit->nparents * sizeof(struct got_object_id))
1296 return got_error(GOT_ERR_PRIVSEP_LEN);
1298 if (icommit->nparents < 0)
1299 return got_error(GOT_ERR_PRIVSEP_LEN);
1301 len += sizeof(*icommit);
1303 *commit = got_object_commit_alloc_partial();
1304 if (*commit == NULL)
1305 return got_error_from_errno(
1306 "got_object_commit_alloc_partial");
1308 memcpy((*commit)->tree_id, &icommit->tree_id,
1309 sizeof(icommit->tree_id));
1310 (*commit)->author_time = icommit->author_time;
1311 (*commit)->author_gmtoff = icommit->author_gmtoff;
1312 (*commit)->committer_time = icommit->committer_time;
1313 (*commit)->committer_gmtoff = icommit->committer_gmtoff;
1315 (*commit)->author = strndup(imsg->data + len, icommit->author_len);
1316 if ((*commit)->author == NULL) {
1317 err = got_error_from_errno("strndup");
1320 len += icommit->author_len;
1322 (*commit)->committer = strndup(imsg->data + len,
1323 icommit->committer_len);
1324 if ((*commit)->committer == NULL) {
1325 err = got_error_from_errno("strndup");
1328 len += icommit->committer_len;
1330 if (icommit->logmsg_len == 0) {
1331 (*commit)->logmsg = strdup("");
1332 if ((*commit)->logmsg == NULL) {
1333 err = got_error_from_errno("strdup");
1337 size_t offset = 0, remain = icommit->logmsg_len;
1339 (*commit)->logmsg = malloc(icommit->logmsg_len + 1);
1340 if ((*commit)->logmsg == NULL) {
1341 err = got_error_from_errno("malloc");
1344 while (remain > 0) {
1345 struct imsg imsg_log;
1346 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE,
1349 err = got_privsep_recv_imsg(&imsg_log, ibuf, n);
1353 if (imsg_log.hdr.type != GOT_IMSG_COMMIT_LOGMSG) {
1354 err = got_error(GOT_ERR_PRIVSEP_MSG);
1358 memcpy((*commit)->logmsg + offset,
1360 imsg_free(&imsg_log);
1364 (*commit)->logmsg[icommit->logmsg_len] = '\0';
1367 for (i = 0; i < icommit->nparents; i++) {
1368 struct got_object_qid *qid;
1370 err = got_object_qid_alloc_partial(&qid);
1373 memcpy(&qid->id, imsg->data + len +
1374 i * sizeof(qid->id), sizeof(qid->id));
1375 STAILQ_INSERT_TAIL(&(*commit)->parent_ids, qid, entry);
1376 (*commit)->nparents++;
1380 got_object_commit_close(*commit);
1386 const struct got_error *
1387 got_privsep_recv_commit(struct got_commit_object **commit, struct imsgbuf *ibuf)
1389 const struct got_error *err = NULL;
1392 const size_t min_datalen =
1393 MIN(sizeof(struct got_imsg_error),
1394 sizeof(struct got_imsg_commit_object));
1398 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1402 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1404 switch (imsg.hdr.type) {
1405 case GOT_IMSG_COMMIT:
1406 err = get_commit_from_imsg(commit, &imsg, datalen, ibuf);
1409 err = got_error(GOT_ERR_PRIVSEP_MSG);
1418 static const struct got_error *
1419 send_tree_entries_batch(struct imsgbuf *ibuf,
1420 struct got_parsed_tree_entry *entries, int idx0, int idxN, size_t len)
1423 struct got_imsg_tree_entries ientries;
1426 memset(&ientries, 0, sizeof(ientries));
1428 wbuf = imsg_create(ibuf, GOT_IMSG_TREE_ENTRIES, 0, 0, len);
1430 return got_error_from_errno("imsg_create TREE_ENTRY");
1432 ientries.nentries = idxN - idx0 + 1;
1433 if (imsg_add(wbuf, &ientries, sizeof(ientries)) == -1)
1434 return got_error_from_errno("imsg_add TREE_ENTRY");
1436 for (i = idx0; i <= idxN; i++) {
1437 struct got_parsed_tree_entry *pte = &entries[i];
1439 /* Keep in sync with struct got_imsg_tree_entry definition! */
1440 if (imsg_add(wbuf, pte->id, SHA1_DIGEST_LENGTH) == -1)
1441 return got_error_from_errno("imsg_add TREE_ENTRY");
1442 if (imsg_add(wbuf, &pte->mode, sizeof(pte->mode)) == -1)
1443 return got_error_from_errno("imsg_add TREE_ENTRY");
1444 if (imsg_add(wbuf, &pte->namelen, sizeof(pte->namelen)) == -1)
1445 return got_error_from_errno("imsg_add TREE_ENTRY");
1447 /* Remaining bytes are the entry's name. */
1448 if (imsg_add(wbuf, pte->name, pte->namelen) == -1)
1449 return got_error_from_errno("imsg_add TREE_ENTRY");
1453 imsg_close(ibuf, wbuf);
1457 static const struct got_error *
1458 send_tree_entries(struct imsgbuf *ibuf, struct got_parsed_tree_entry *entries,
1461 const struct got_error *err = NULL;
1463 size_t entries_len = sizeof(struct got_imsg_tree_entries);
1466 for (j = 0; j < nentries; j++) {
1467 struct got_parsed_tree_entry *pte = &entries[j];
1468 size_t len = sizeof(struct got_imsg_tree_entry) + pte->namelen;
1471 entries_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
1472 err = send_tree_entries_batch(ibuf, entries,
1473 i, j - 1, entries_len);
1477 entries_len = sizeof(struct got_imsg_tree_entries);
1484 err = send_tree_entries_batch(ibuf, entries, i, j - 1,
1493 const struct got_error *
1494 got_privsep_send_tree(struct imsgbuf *ibuf,
1495 struct got_parsed_tree_entry *entries, int nentries)
1497 const struct got_error *err = NULL;
1498 struct got_imsg_tree_object itree;
1500 memset(&itree, 0, sizeof(itree));
1501 itree.nentries = nentries;
1502 if (imsg_compose(ibuf, GOT_IMSG_TREE, 0, 0, -1, &itree, sizeof(itree))
1504 return got_error_from_errno("imsg_compose TREE");
1506 err = send_tree_entries(ibuf, entries, nentries);
1510 return flush_imsg(ibuf);
1514 static const struct got_error *
1515 recv_tree_entries(void *data, size_t datalen, struct got_tree_object *tree,
1518 const struct got_error *err = NULL;
1519 struct got_imsg_tree_entries *ientries;
1520 struct got_tree_entry *te;
1524 if (datalen <= sizeof(*ientries) ||
1525 datalen > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
1526 return got_error(GOT_ERR_PRIVSEP_LEN);
1528 ientries = (struct got_imsg_tree_entries *)data;
1529 if (ientries->nentries > INT_MAX) {
1530 return got_error_msg(GOT_ERR_NO_SPACE,
1531 "too many tree entries");
1534 te_offset = sizeof(*ientries);
1535 for (i = 0; i < ientries->nentries; i++) {
1536 struct got_imsg_tree_entry ite;
1537 const char *te_name;
1538 uint8_t *buf = (uint8_t *)data + te_offset;
1540 if (te_offset >= datalen) {
1541 err = got_error(GOT_ERR_PRIVSEP_LEN);
1545 /* Might not be aligned, size is ~32 bytes. */
1546 memcpy(&ite, buf, sizeof(ite));
1548 if (ite.namelen >= sizeof(te->name)) {
1549 err = got_error(GOT_ERR_PRIVSEP_LEN);
1552 if (te_offset + sizeof(ite) + ite.namelen > datalen) {
1553 err = got_error(GOT_ERR_PRIVSEP_LEN);
1557 if (*nentries >= tree->nentries) {
1558 err = got_error(GOT_ERR_PRIVSEP_LEN);
1561 te = &tree->entries[*nentries];
1562 te_name = buf + sizeof(ite);
1563 memcpy(te->name, te_name, ite.namelen);
1564 te->name[ite.namelen] = '\0';
1565 memcpy(te->id.sha1, ite.id, SHA1_DIGEST_LENGTH);
1566 te->mode = ite.mode;
1567 te->idx = *nentries;
1570 te_offset += sizeof(ite) + ite.namelen;
1576 const struct got_error *
1577 got_privsep_recv_tree(struct got_tree_object **tree, struct imsgbuf *ibuf)
1579 const struct got_error *err = NULL;
1580 const size_t min_datalen =
1581 MIN(sizeof(struct got_imsg_error),
1582 sizeof(struct got_imsg_tree_object));
1583 struct got_imsg_tree_object *itree;
1588 while (*tree == NULL || nentries < (*tree)->nentries) {
1592 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1596 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1598 switch (imsg.hdr.type) {
1600 /* This message should only appear once. */
1601 if (*tree != NULL) {
1602 err = got_error(GOT_ERR_PRIVSEP_MSG);
1605 if (datalen != sizeof(*itree)) {
1606 err = got_error(GOT_ERR_PRIVSEP_LEN);
1610 if (itree->nentries < 0) {
1611 err = got_error(GOT_ERR_PRIVSEP_LEN);
1614 *tree = malloc(sizeof(**tree));
1615 if (*tree == NULL) {
1616 err = got_error_from_errno("malloc");
1619 (*tree)->entries = calloc(itree->nentries,
1620 sizeof(struct got_tree_entry));
1621 if ((*tree)->entries == NULL) {
1622 err = got_error_from_errno("malloc");
1627 (*tree)->nentries = itree->nentries;
1628 (*tree)->refcnt = 0;
1630 case GOT_IMSG_TREE_ENTRIES:
1631 /* This message should be preceeded by GOT_IMSG_TREE. */
1632 if (*tree == NULL) {
1633 err = got_error(GOT_ERR_PRIVSEP_MSG);
1636 err = recv_tree_entries(imsg.data, datalen,
1640 err = got_error(GOT_ERR_PRIVSEP_MSG);
1649 if (*tree && (*tree)->nentries != nentries) {
1651 err = got_error(GOT_ERR_PRIVSEP_LEN);
1652 got_object_tree_close(*tree);
1659 const struct got_error *
1660 got_privsep_send_blob(struct imsgbuf *ibuf, size_t size, size_t hdrlen,
1661 const uint8_t *data)
1663 struct got_imsg_blob iblob;
1665 memset(&iblob, 0, sizeof(iblob));
1667 iblob.hdrlen = hdrlen;
1672 if (size > GOT_PRIVSEP_INLINE_BLOB_DATA_MAX)
1673 return got_error(GOT_ERR_NO_SPACE);
1675 buf = malloc(sizeof(iblob) + size);
1677 return got_error_from_errno("malloc");
1679 memcpy(buf, &iblob, sizeof(iblob));
1680 memcpy(buf + sizeof(iblob), data, size);
1681 if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, buf,
1682 sizeof(iblob) + size) == -1) {
1684 return got_error_from_errno("imsg_compose BLOB");
1688 /* Data has already been written to file descriptor. */
1689 if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, &iblob,
1690 sizeof(iblob)) == -1)
1691 return got_error_from_errno("imsg_compose BLOB");
1695 return flush_imsg(ibuf);
1698 const struct got_error *
1699 got_privsep_recv_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen,
1700 struct imsgbuf *ibuf)
1702 const struct got_error *err = NULL;
1704 struct got_imsg_blob *iblob;
1709 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
1713 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1715 switch (imsg.hdr.type) {
1717 if (datalen < sizeof(*iblob)) {
1718 err = got_error(GOT_ERR_PRIVSEP_LEN);
1722 *size = iblob->size;
1723 *hdrlen = iblob->hdrlen;
1725 if (datalen == sizeof(*iblob)) {
1726 /* Data has been written to file descriptor. */
1730 if (*size > GOT_PRIVSEP_INLINE_BLOB_DATA_MAX ||
1731 *size > datalen + sizeof(*iblob)) {
1732 err = got_error(GOT_ERR_PRIVSEP_LEN);
1736 *outbuf = malloc(*size);
1737 if (*outbuf == NULL) {
1738 err = got_error_from_errno("malloc");
1741 memcpy(*outbuf, imsg.data + sizeof(*iblob), *size);
1744 err = got_error(GOT_ERR_PRIVSEP_MSG);
1753 static const struct got_error *
1754 send_tagmsg(struct imsgbuf *ibuf, struct got_tag_object *tag, size_t tagmsg_len)
1756 const struct got_error *err = NULL;
1757 size_t offset, remain;
1760 remain = tagmsg_len;
1761 while (remain > 0) {
1762 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
1764 if (imsg_compose(ibuf, GOT_IMSG_TAG_TAGMSG, 0, 0, -1,
1765 tag->tagmsg + offset, n) == -1) {
1766 err = got_error_from_errno("imsg_compose TAG_TAGMSG");
1770 err = flush_imsg(ibuf);
1781 const struct got_error *
1782 got_privsep_send_tag(struct imsgbuf *ibuf, struct got_tag_object *tag)
1784 const struct got_error *err = NULL;
1785 struct got_imsg_tag_object *itag;
1788 size_t tag_len = strlen(tag->tag);
1789 size_t tagger_len = strlen(tag->tagger);
1790 size_t tagmsg_len = strlen(tag->tagmsg);
1792 total = sizeof(*itag) + tag_len + tagger_len + tagmsg_len;
1794 buf = malloc(total);
1796 return got_error_from_errno("malloc");
1798 itag = (struct got_imsg_tag_object *)buf;
1799 memcpy(&itag->id, &tag->id, sizeof(itag->id));
1800 itag->obj_type = tag->obj_type;
1801 itag->tag_len = tag_len;
1802 itag->tagger_len = tagger_len;
1803 itag->tagger_time = tag->tagger_time;
1804 itag->tagger_gmtoff = tag->tagger_gmtoff;
1805 itag->tagmsg_len = tagmsg_len;
1807 len = sizeof(*itag);
1808 memcpy(buf + len, tag->tag, tag_len);
1810 memcpy(buf + len, tag->tagger, tagger_len);
1813 if (imsg_compose(ibuf, GOT_IMSG_TAG, 0, 0, -1, buf, len) == -1) {
1814 err = got_error_from_errno("imsg_compose TAG");
1818 if (tagmsg_len == 0 ||
1819 tagmsg_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
1820 err = flush_imsg(ibuf);
1824 err = send_tagmsg(ibuf, tag, tagmsg_len);
1830 const struct got_error *
1831 got_privsep_recv_tag(struct got_tag_object **tag, struct imsgbuf *ibuf)
1833 const struct got_error *err = NULL;
1835 struct got_imsg_tag_object *itag;
1836 size_t len, datalen;
1837 const size_t min_datalen =
1838 MIN(sizeof(struct got_imsg_error),
1839 sizeof(struct got_imsg_tag_object));
1843 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1847 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1850 switch (imsg.hdr.type) {
1852 if (datalen < sizeof(*itag)) {
1853 err = got_error(GOT_ERR_PRIVSEP_LEN);
1857 if (datalen != sizeof(*itag) + itag->tag_len +
1859 err = got_error(GOT_ERR_PRIVSEP_LEN);
1862 len += sizeof(*itag);
1864 *tag = calloc(1, sizeof(**tag));
1866 err = got_error_from_errno("calloc");
1870 memcpy(&(*tag)->id, &itag->id, sizeof(itag->id));
1872 (*tag)->tag = strndup(imsg.data + len, itag->tag_len);
1873 if ((*tag)->tag == NULL) {
1874 err = got_error_from_errno("strndup");
1877 len += itag->tag_len;
1879 (*tag)->obj_type = itag->obj_type;
1880 (*tag)->tagger_time = itag->tagger_time;
1881 (*tag)->tagger_gmtoff = itag->tagger_gmtoff;
1883 (*tag)->tagger = strndup(imsg.data + len, itag->tagger_len);
1884 if ((*tag)->tagger == NULL) {
1885 err = got_error_from_errno("strndup");
1888 len += itag->tagger_len;
1890 if (itag->tagmsg_len == 0) {
1891 (*tag)->tagmsg = strdup("");
1892 if ((*tag)->tagmsg == NULL) {
1893 err = got_error_from_errno("strdup");
1897 size_t offset = 0, remain = itag->tagmsg_len;
1899 (*tag)->tagmsg = malloc(itag->tagmsg_len + 1);
1900 if ((*tag)->tagmsg == NULL) {
1901 err = got_error_from_errno("malloc");
1904 while (remain > 0) {
1905 struct imsg imsg_log;
1906 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE,
1909 err = got_privsep_recv_imsg(&imsg_log, ibuf, n);
1913 if (imsg_log.hdr.type != GOT_IMSG_TAG_TAGMSG)
1914 return got_error(GOT_ERR_PRIVSEP_MSG);
1916 memcpy((*tag)->tagmsg + offset, imsg_log.data,
1918 imsg_free(&imsg_log);
1922 (*tag)->tagmsg[itag->tagmsg_len] = '\0';
1927 err = got_error(GOT_ERR_PRIVSEP_MSG);
1936 const struct got_error *
1937 got_privsep_init_pack_child(struct imsgbuf *ibuf, struct got_pack *pack,
1938 struct got_packidx *packidx)
1940 const struct got_error *err = NULL;
1941 struct got_imsg_packidx ipackidx;
1942 struct got_imsg_pack ipack;
1945 memset(&ipackidx, 0, sizeof(ipackidx));
1946 memset(&ipack, 0, sizeof(ipack));
1948 ipackidx.len = packidx->len;
1949 ipackidx.packfile_size = pack->filesize;
1950 fd = dup(packidx->fd);
1952 return got_error_from_errno("dup");
1954 if (imsg_compose(ibuf, GOT_IMSG_PACKIDX, 0, 0, fd, &ipackidx,
1955 sizeof(ipackidx)) == -1) {
1956 err = got_error_from_errno("imsg_compose PACKIDX");
1961 if (strlcpy(ipack.path_packfile, pack->path_packfile,
1962 sizeof(ipack.path_packfile)) >= sizeof(ipack.path_packfile))
1963 return got_error(GOT_ERR_NO_SPACE);
1964 ipack.filesize = pack->filesize;
1968 return got_error_from_errno("dup");
1970 if (imsg_compose(ibuf, GOT_IMSG_PACK, 0, 0, fd, &ipack, sizeof(ipack))
1972 err = got_error_from_errno("imsg_compose PACK");
1977 return flush_imsg(ibuf);
1980 const struct got_error *
1981 got_privsep_send_packed_obj_req(struct imsgbuf *ibuf, int idx,
1982 struct got_object_id *id)
1984 struct got_imsg_packed_object iobj;
1986 memset(&iobj, 0, sizeof(iobj));
1988 memcpy(&iobj.id, id, sizeof(iobj.id));
1990 if (imsg_compose(ibuf, GOT_IMSG_PACKED_OBJECT_REQUEST, 0, 0, -1,
1991 &iobj, sizeof(iobj)) == -1)
1992 return got_error_from_errno("imsg_compose "
1993 "PACKED_OBJECT_REQUEST");
1995 return flush_imsg(ibuf);
1998 const struct got_error *
1999 got_privsep_send_packed_raw_obj_req(struct imsgbuf *ibuf, int idx,
2000 struct got_object_id *id)
2002 struct got_imsg_packed_object iobj;
2004 memset(&iobj, 0, sizeof(iobj));
2006 memcpy(&iobj.id, id, sizeof(iobj.id));
2008 if (imsg_compose(ibuf, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST, 0, 0, -1,
2009 &iobj, sizeof(iobj)) == -1)
2010 return got_error_from_errno("imsg_compose "
2011 "PACKED_OBJECT_REQUEST");
2013 return flush_imsg(ibuf);
2016 const struct got_error *
2017 got_privsep_send_gitconfig_parse_req(struct imsgbuf *ibuf, int fd)
2019 const struct got_error *err = NULL;
2021 if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_PARSE_REQUEST, 0, 0, fd,
2023 err = got_error_from_errno("imsg_compose "
2024 "GITCONFIG_PARSE_REQUEST");
2029 return flush_imsg(ibuf);
2032 const struct got_error *
2033 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf *ibuf)
2035 if (imsg_compose(ibuf,
2036 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST, 0, 0, -1,
2038 return got_error_from_errno("imsg_compose "
2039 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2041 return flush_imsg(ibuf);
2044 const struct got_error *
2045 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf *ibuf)
2047 if (imsg_compose(ibuf,
2048 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST, 0, 0, -1,
2050 return got_error_from_errno("imsg_compose "
2051 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2053 return flush_imsg(ibuf);
2057 const struct got_error *
2058 got_privsep_send_gitconfig_author_name_req(struct imsgbuf *ibuf)
2060 if (imsg_compose(ibuf,
2061 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST, 0, 0, -1, NULL, 0) == -1)
2062 return got_error_from_errno("imsg_compose "
2063 "GITCONFIG_AUTHOR_NAME_REQUEST");
2065 return flush_imsg(ibuf);
2068 const struct got_error *
2069 got_privsep_send_gitconfig_author_email_req(struct imsgbuf *ibuf)
2071 if (imsg_compose(ibuf,
2072 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST, 0, 0, -1, NULL, 0) == -1)
2073 return got_error_from_errno("imsg_compose "
2074 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2076 return flush_imsg(ibuf);
2079 const struct got_error *
2080 got_privsep_send_gitconfig_remotes_req(struct imsgbuf *ibuf)
2082 if (imsg_compose(ibuf,
2083 GOT_IMSG_GITCONFIG_REMOTES_REQUEST, 0, 0, -1, NULL, 0) == -1)
2084 return got_error_from_errno("imsg_compose "
2085 "GITCONFIG_REMOTE_REQUEST");
2087 return flush_imsg(ibuf);
2090 const struct got_error *
2091 got_privsep_send_gitconfig_owner_req(struct imsgbuf *ibuf)
2093 if (imsg_compose(ibuf,
2094 GOT_IMSG_GITCONFIG_OWNER_REQUEST, 0, 0, -1, NULL, 0) == -1)
2095 return got_error_from_errno("imsg_compose "
2096 "GITCONFIG_OWNER_REQUEST");
2098 return flush_imsg(ibuf);
2101 const struct got_error *
2102 got_privsep_recv_gitconfig_str(char **str, struct imsgbuf *ibuf)
2104 const struct got_error *err = NULL;
2110 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2113 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2115 switch (imsg.hdr.type) {
2116 case GOT_IMSG_GITCONFIG_STR_VAL:
2119 *str = strndup(imsg.data, datalen);
2121 err = got_error_from_errno("strndup");
2126 err = got_error(GOT_ERR_PRIVSEP_MSG);
2134 const struct got_error *
2135 got_privsep_recv_gitconfig_pair(char **key, char **val, struct imsgbuf *ibuf)
2137 const struct got_error *err = NULL;
2138 struct got_imsg_gitconfig_pair p;
2145 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2150 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2152 if (imsg.hdr.type != GOT_IMSG_GITCONFIG_PAIR) {
2153 err = got_error(GOT_ERR_PRIVSEP_MSG);
2157 if (datalen < sizeof(p)) {
2158 err = got_error(GOT_ERR_PRIVSEP_LEN);
2162 memcpy(&p, data, sizeof(p));
2165 if (datalen != sizeof(p) + p.klen + p.vlen) {
2166 err = got_error(GOT_ERR_PRIVSEP_LEN);
2170 *key = strndup(data, p.klen);
2172 err = got_error_from_errno("strndup");
2177 *val = strndup(data, p.vlen);
2179 err = got_error_from_errno("strndup");
2188 const struct got_error *
2189 got_privsep_recv_gitconfig_int(int *val, struct imsgbuf *ibuf)
2191 const struct got_error *err = NULL;
2194 const size_t min_datalen =
2195 MIN(sizeof(struct got_imsg_error), sizeof(int));
2199 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
2202 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2204 switch (imsg.hdr.type) {
2205 case GOT_IMSG_GITCONFIG_INT_VAL:
2206 if (datalen != sizeof(*val)) {
2207 err = got_error(GOT_ERR_PRIVSEP_LEN);
2210 memcpy(val, imsg.data, sizeof(*val));
2213 err = got_error(GOT_ERR_PRIVSEP_MSG);
2222 free_remote_data(struct got_remote_repo *remote)
2227 free(remote->fetch_url);
2228 free(remote->send_url);
2229 for (i = 0; i < remote->nfetch_branches; i++)
2230 free(remote->fetch_branches[i]);
2231 free(remote->fetch_branches);
2232 for (i = 0; i < remote->nsend_branches; i++)
2233 free(remote->send_branches[i]);
2234 free(remote->send_branches);
2235 for (i = 0; i < remote->nfetch_refs; i++)
2236 free(remote->fetch_refs[i]);
2237 free(remote->fetch_refs);
2240 const struct got_error *
2241 got_privsep_recv_gitconfig_remotes(struct got_remote_repo **remotes,
2242 int *nremotes, struct imsgbuf *ibuf)
2244 const struct got_error *err = NULL;
2247 struct got_imsg_remotes iremotes;
2248 struct got_imsg_remote iremote;
2252 iremotes.nremotes = 0;
2254 err = got_privsep_recv_imsg(&imsg, ibuf, sizeof(iremotes));
2257 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2259 switch (imsg.hdr.type) {
2260 case GOT_IMSG_GITCONFIG_REMOTES:
2261 if (datalen != sizeof(iremotes)) {
2262 err = got_error(GOT_ERR_PRIVSEP_LEN);
2265 memcpy(&iremotes, imsg.data, sizeof(iremotes));
2266 if (iremotes.nremotes == 0) {
2273 return got_error(GOT_ERR_PRIVSEP_MSG);
2278 *remotes = recallocarray(NULL, 0, iremotes.nremotes, sizeof(**remotes));
2279 if (*remotes == NULL)
2280 return got_error_from_errno("recallocarray");
2282 while (*nremotes < iremotes.nremotes) {
2283 struct got_remote_repo *remote;
2285 err = got_privsep_recv_imsg(&imsg, ibuf, sizeof(iremote));
2288 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2290 switch (imsg.hdr.type) {
2291 case GOT_IMSG_GITCONFIG_REMOTE:
2292 remote = &(*remotes)[*nremotes];
2293 memset(remote, 0, sizeof(*remote));
2294 if (datalen < sizeof(iremote)) {
2295 err = got_error(GOT_ERR_PRIVSEP_LEN);
2298 memcpy(&iremote, imsg.data, sizeof(iremote));
2299 if (iremote.name_len == 0 ||
2300 iremote.fetch_url_len == 0 ||
2301 iremote.send_url_len == 0 ||
2302 (sizeof(iremote) + iremote.name_len +
2303 iremote.fetch_url_len + iremote.send_url_len) > datalen) {
2304 err = got_error(GOT_ERR_PRIVSEP_LEN);
2307 remote->name = strndup(imsg.data + sizeof(iremote),
2309 if (remote->name == NULL) {
2310 err = got_error_from_errno("strndup");
2313 remote->fetch_url = strndup(imsg.data + sizeof(iremote) +
2314 iremote.name_len, iremote.fetch_url_len);
2315 if (remote->fetch_url == NULL) {
2316 err = got_error_from_errno("strndup");
2317 free_remote_data(remote);
2320 remote->send_url = strndup(imsg.data + sizeof(iremote) +
2321 iremote.name_len + iremote.fetch_url_len,
2322 iremote.send_url_len);
2323 if (remote->send_url == NULL) {
2324 err = got_error_from_errno("strndup");
2325 free_remote_data(remote);
2328 remote->mirror_references = iremote.mirror_references;
2329 remote->fetch_all_branches = iremote.fetch_all_branches;
2330 remote->nfetch_branches = 0;
2331 remote->fetch_branches = NULL;
2332 remote->nsend_branches = 0;
2333 remote->send_branches = NULL;
2334 remote->nfetch_refs = 0;
2335 remote->fetch_refs = NULL;
2339 err = got_error(GOT_ERR_PRIVSEP_MSG);
2350 for (i = 0; i < *nremotes; i++)
2351 free_remote_data(&(*remotes)[i]);
2359 const struct got_error *
2360 got_privsep_send_gotconfig_parse_req(struct imsgbuf *ibuf, int fd)
2362 const struct got_error *err = NULL;
2364 if (imsg_compose(ibuf, GOT_IMSG_GOTCONFIG_PARSE_REQUEST, 0, 0, fd,
2366 err = got_error_from_errno("imsg_compose "
2367 "GOTCONFIG_PARSE_REQUEST");
2372 return flush_imsg(ibuf);
2375 const struct got_error *
2376 got_privsep_send_gotconfig_author_req(struct imsgbuf *ibuf)
2378 if (imsg_compose(ibuf,
2379 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST, 0, 0, -1, NULL, 0) == -1)
2380 return got_error_from_errno("imsg_compose "
2381 "GOTCONFIG_AUTHOR_REQUEST");
2383 return flush_imsg(ibuf);
2386 const struct got_error *
2387 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf *ibuf)
2389 if (imsg_compose(ibuf,
2390 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST, 0, 0, -1, NULL, 0) == -1)
2391 return got_error_from_errno("imsg_compose "
2392 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2394 return flush_imsg(ibuf);
2397 const struct got_error *
2398 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf *ibuf)
2400 if (imsg_compose(ibuf,
2401 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST, 0, 0, -1, NULL, 0) == -1)
2402 return got_error_from_errno("imsg_compose "
2403 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2405 return flush_imsg(ibuf);
2408 const struct got_error *
2409 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf *ibuf)
2411 if (imsg_compose(ibuf,
2412 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST, 0, 0, -1, NULL, 0) == -1)
2413 return got_error_from_errno("imsg_compose "
2414 "GOTCONFIG_SIGNERID_REQUEST");
2416 return flush_imsg(ibuf);
2419 const struct got_error *
2420 got_privsep_send_gotconfig_remotes_req(struct imsgbuf *ibuf)
2422 if (imsg_compose(ibuf,
2423 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST, 0, 0, -1, NULL, 0) == -1)
2424 return got_error_from_errno("imsg_compose "
2425 "GOTCONFIG_REMOTE_REQUEST");
2427 return flush_imsg(ibuf);
2430 const struct got_error *
2431 got_privsep_recv_gotconfig_str(char **str, struct imsgbuf *ibuf)
2433 const struct got_error *err = NULL;
2439 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2442 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2444 switch (imsg.hdr.type) {
2445 case GOT_IMSG_GOTCONFIG_STR_VAL:
2448 *str = strndup(imsg.data, datalen);
2450 err = got_error_from_errno("strndup");
2455 err = got_error(GOT_ERR_PRIVSEP_MSG);
2463 const struct got_error *
2464 got_privsep_recv_gotconfig_remotes(struct got_remote_repo **remotes,
2465 int *nremotes, struct imsgbuf *ibuf)
2467 const struct got_error *err = NULL;
2470 struct got_imsg_remotes iremotes;
2471 struct got_imsg_remote iremote;
2472 const size_t min_datalen =
2473 MIN(sizeof(struct got_imsg_error), sizeof(iremotes));
2477 iremotes.nremotes = 0;
2479 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
2482 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2484 switch (imsg.hdr.type) {
2485 case GOT_IMSG_GOTCONFIG_REMOTES:
2486 if (datalen != sizeof(iremotes)) {
2487 err = got_error(GOT_ERR_PRIVSEP_LEN);
2490 memcpy(&iremotes, imsg.data, sizeof(iremotes));
2491 if (iremotes.nremotes < 0) {
2492 err = got_error(GOT_ERR_PRIVSEP_LEN);
2495 if (iremotes.nremotes == 0) {
2502 return got_error(GOT_ERR_PRIVSEP_MSG);
2507 *remotes = recallocarray(NULL, 0, iremotes.nremotes, sizeof(**remotes));
2508 if (*remotes == NULL)
2509 return got_error_from_errno("recallocarray");
2511 while (*nremotes < iremotes.nremotes) {
2512 struct got_remote_repo *remote;
2513 const size_t min_datalen =
2514 MIN(sizeof(struct got_imsg_error), sizeof(iremote));
2517 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
2520 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2522 switch (imsg.hdr.type) {
2523 case GOT_IMSG_GOTCONFIG_REMOTE:
2524 remote = &(*remotes)[*nremotes];
2525 memset(remote, 0, sizeof(*remote));
2526 if (datalen < sizeof(iremote)) {
2527 err = got_error(GOT_ERR_PRIVSEP_LEN);
2530 memcpy(&iremote, imsg.data, sizeof(iremote));
2531 if (iremote.name_len == 0 ||
2532 (iremote.fetch_url_len == 0 &&
2533 iremote.send_url_len == 0) ||
2534 (sizeof(iremote) + iremote.name_len +
2535 iremote.fetch_url_len + iremote.send_url_len) >
2537 err = got_error(GOT_ERR_PRIVSEP_LEN);
2540 remote->name = strndup(imsg.data + sizeof(iremote),
2542 if (remote->name == NULL) {
2543 err = got_error_from_errno("strndup");
2546 remote->fetch_url = strndup(imsg.data +
2547 sizeof(iremote) + iremote.name_len,
2548 iremote.fetch_url_len);
2549 if (remote->fetch_url == NULL) {
2550 err = got_error_from_errno("strndup");
2551 free_remote_data(remote);
2554 remote->send_url = strndup(imsg.data +
2555 sizeof(iremote) + iremote.name_len +
2556 iremote.fetch_url_len, iremote.send_url_len);
2557 if (remote->send_url == NULL) {
2558 err = got_error_from_errno("strndup");
2559 free_remote_data(remote);
2562 remote->mirror_references = iremote.mirror_references;
2563 remote->fetch_all_branches = iremote.fetch_all_branches;
2564 if (iremote.nfetch_branches > 0) {
2565 remote->fetch_branches = recallocarray(NULL, 0,
2566 iremote.nfetch_branches, sizeof(char *));
2567 if (remote->fetch_branches == NULL) {
2568 err = got_error_from_errno("calloc");
2569 free_remote_data(remote);
2573 remote->nfetch_branches = 0;
2574 for (i = 0; i < iremote.nfetch_branches; i++) {
2576 err = got_privsep_recv_gotconfig_str(&branch,
2579 free_remote_data(remote);
2582 remote->fetch_branches[i] = branch;
2583 remote->nfetch_branches++;
2585 if (iremote.nsend_branches > 0) {
2586 remote->send_branches = recallocarray(NULL, 0,
2587 iremote.nsend_branches, sizeof(char *));
2588 if (remote->send_branches == NULL) {
2589 err = got_error_from_errno("calloc");
2590 free_remote_data(remote);
2594 remote->nsend_branches = 0;
2595 for (i = 0; i < iremote.nsend_branches; i++) {
2597 err = got_privsep_recv_gotconfig_str(&branch,
2600 free_remote_data(remote);
2603 remote->send_branches[i] = branch;
2604 remote->nsend_branches++;
2606 if (iremote.nfetch_refs > 0) {
2607 remote->fetch_refs = recallocarray(NULL, 0,
2608 iremote.nfetch_refs, sizeof(char *));
2609 if (remote->fetch_refs == NULL) {
2610 err = got_error_from_errno("calloc");
2611 free_remote_data(remote);
2615 remote->nfetch_refs = 0;
2616 for (i = 0; i < iremote.nfetch_refs; i++) {
2618 err = got_privsep_recv_gotconfig_str(&ref,
2621 free_remote_data(remote);
2624 remote->fetch_refs[i] = ref;
2625 remote->nfetch_refs++;
2630 err = got_error(GOT_ERR_PRIVSEP_MSG);
2641 for (i = 0; i < *nremotes; i++)
2642 free_remote_data(&(*remotes)[i]);
2650 const struct got_error *
2651 got_privsep_send_commit_traversal_request(struct imsgbuf *ibuf,
2652 struct got_object_id *id, int idx, const char *path)
2655 size_t path_len = strlen(path) + 1;
2657 wbuf = imsg_create(ibuf, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST, 0, 0,
2658 sizeof(struct got_imsg_commit_traversal_request) + path_len);
2660 return got_error_from_errno(
2661 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2662 if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1)
2663 return got_error_from_errno("imsg_add "
2664 "COMMIT_TRAVERSAL_REQUEST");
2665 if (imsg_add(wbuf, &idx, sizeof(idx)) == -1)
2666 return got_error_from_errno("imsg_add "
2667 "COMMIT_TRAVERSAL_REQUEST");
2668 if (imsg_add(wbuf, path, path_len) == -1)
2669 return got_error_from_errno("imsg_add "
2670 "COMMIT_TRAVERSAL_REQUEST");
2673 imsg_close(ibuf, wbuf);
2675 return flush_imsg(ibuf);
2678 const struct got_error *
2679 got_privsep_recv_traversed_commits(struct got_commit_object **changed_commit,
2680 struct got_object_id **changed_commit_id,
2681 struct got_object_id_queue *commit_ids, struct imsgbuf *ibuf)
2683 const struct got_error *err = NULL;
2685 struct got_imsg_traversed_commits *icommits;
2686 struct got_object_id *ids;
2690 *changed_commit = NULL;
2691 *changed_commit_id = NULL;
2694 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2698 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2699 switch (imsg.hdr.type) {
2700 case GOT_IMSG_TRAVERSED_COMMITS:
2701 icommits = imsg.data;
2702 if (datalen != sizeof(*icommits) +
2703 icommits->ncommits * sizeof(*ids)) {
2704 err = got_error(GOT_ERR_PRIVSEP_LEN);
2707 ids = imsg.data + sizeof(*icommits);
2708 for (i = 0; i < icommits->ncommits; i++) {
2709 struct got_object_qid *qid;
2711 err = got_object_qid_alloc_partial(&qid);
2714 memcpy(&qid->id, &ids[i], sizeof(ids[i]));
2715 STAILQ_INSERT_TAIL(commit_ids, qid, entry);
2717 /* The last commit may contain a change. */
2718 if (i == icommits->ncommits - 1) {
2719 *changed_commit_id =
2720 got_object_id_dup(&qid->id);
2721 if (*changed_commit_id == NULL) {
2722 err = got_error_from_errno(
2723 "got_object_id_dup");
2729 case GOT_IMSG_COMMIT:
2730 if (*changed_commit_id == NULL) {
2731 err = got_error(GOT_ERR_PRIVSEP_MSG);
2734 err = get_commit_from_imsg(changed_commit, &imsg,
2737 case GOT_IMSG_COMMIT_TRAVERSAL_DONE:
2741 err = got_error(GOT_ERR_PRIVSEP_MSG);
2751 got_object_id_queue_free(commit_ids);
2755 const struct got_error *
2756 got_privsep_send_enumerated_tree(size_t *totlen, struct imsgbuf *ibuf,
2757 struct got_object_id *tree_id, const char *path,
2758 struct got_parsed_tree_entry *entries, int nentries)
2760 const struct got_error *err = NULL;
2762 size_t path_len = strlen(path);
2765 msglen = sizeof(struct got_imsg_enumerated_tree) + path_len;
2766 wbuf = imsg_create(ibuf, GOT_IMSG_ENUMERATED_TREE, 0, 0, msglen);
2768 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2770 if (imsg_add(wbuf, tree_id->sha1, SHA1_DIGEST_LENGTH) == -1)
2771 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2772 if (imsg_add(wbuf, &nentries, sizeof(nentries)) == -1)
2773 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2774 if (imsg_add(wbuf, path, path_len) == -1)
2775 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2778 imsg_close(ibuf, wbuf);
2781 err = send_tree_entries(ibuf, entries, nentries);
2786 return flush_imsg(ibuf);
2789 const struct got_error *
2790 got_privsep_send_object_enumeration_request(struct imsgbuf *ibuf)
2792 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_ENUMERATION_REQUEST,
2793 0, 0, -1, NULL, 0) == -1)
2794 return got_error_from_errno("imsg_compose "
2795 "OBJECT_ENUMERATION_REQUEST");
2797 return flush_imsg(ibuf);
2800 const struct got_error *
2801 got_privsep_send_object_enumeration_done(struct imsgbuf *ibuf)
2803 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_ENUMERATION_DONE,
2804 0, 0, -1, NULL, 0) == -1)
2805 return got_error_from_errno("imsg_compose "
2806 "OBJECT_ENUMERATION_DONE");
2808 return flush_imsg(ibuf);
2811 const struct got_error *
2812 got_privsep_send_object_enumeration_incomplete(struct imsgbuf *ibuf)
2814 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE,
2815 0, 0, -1, NULL, 0) == -1)
2816 return got_error_from_errno("imsg_compose "
2817 "OBJECT_ENUMERATION_INCOMPLETE");
2819 return flush_imsg(ibuf);
2822 const struct got_error *
2823 got_privsep_send_enumerated_commit(struct imsgbuf *ibuf,
2824 struct got_object_id *id, time_t mtime)
2828 wbuf = imsg_create(ibuf, GOT_IMSG_ENUMERATED_COMMIT, 0, 0,
2829 sizeof(struct got_imsg_enumerated_commit) + SHA1_DIGEST_LENGTH);
2831 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2833 /* Keep in sync with struct got_imsg_enumerated_commit! */
2834 if (imsg_add(wbuf, id, SHA1_DIGEST_LENGTH) == -1)
2835 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2836 if (imsg_add(wbuf, &mtime, sizeof(mtime)) == -1)
2837 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2840 imsg_close(ibuf, wbuf);
2841 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2845 const struct got_error *
2846 got_privsep_recv_enumerated_objects(int *found_all_objects,
2847 struct imsgbuf *ibuf,
2848 got_object_enumerate_commit_cb cb_commit,
2849 got_object_enumerate_tree_cb cb_tree, void *cb_arg,
2850 struct got_repository *repo)
2852 const struct got_error *err = NULL;
2854 struct got_imsg_enumerated_commit *icommit = NULL;
2855 struct got_object_id commit_id;
2856 int have_commit = 0;
2858 struct got_tree_object tree;
2859 struct got_imsg_enumerated_tree *itree;
2860 struct got_object_id tree_id;
2861 char *path = NULL, *canon_path = NULL;
2862 size_t datalen, path_len;
2866 *found_all_objects = 0;
2867 memset(&tree, 0, sizeof(tree));
2870 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2874 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2875 switch (imsg.hdr.type) {
2876 case GOT_IMSG_ENUMERATED_COMMIT:
2877 if (have_commit && nentries != -1) {
2878 err = got_error(GOT_ERR_PRIVSEP_MSG);
2881 if (datalen != sizeof(*icommit)) {
2882 err = got_error(GOT_ERR_PRIVSEP_LEN);
2885 icommit = (struct got_imsg_enumerated_commit *)imsg.data;
2886 memcpy(commit_id.sha1, icommit->id, SHA1_DIGEST_LENGTH);
2887 mtime = icommit->mtime;
2890 case GOT_IMSG_ENUMERATED_TREE:
2891 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2893 err = got_error(GOT_ERR_PRIVSEP_MSG);
2896 if (datalen < sizeof(*itree)) {
2897 err = got_error(GOT_ERR_PRIVSEP_LEN);
2901 path_len = datalen - sizeof(*itree);
2902 if (path_len == 0) {
2903 err = got_error(GOT_ERR_PRIVSEP_LEN);
2906 memcpy(tree_id.sha1, itree->id, sizeof(tree_id.sha1));
2908 path = strndup(imsg.data + sizeof(*itree), path_len);
2910 err = got_error_from_errno("strndup");
2914 canon_path = malloc(path_len + 1);
2915 if (canon_path == NULL) {
2916 err = got_error_from_errno("malloc");
2919 if (!got_path_is_absolute(path)) {
2920 err = got_error(GOT_ERR_BAD_PATH);
2923 if (got_path_is_root_dir(path)) {
2924 /* XXX check what got_canonpath() does wrong */
2925 canon_path[0] = '/';
2926 canon_path[1] = '\0';
2928 err = got_canonpath(path, canon_path,
2933 if (strcmp(path, canon_path) != 0) {
2934 err = got_error(GOT_ERR_BAD_PATH);
2937 if (nentries != -1) {
2938 err = got_error(GOT_ERR_PRIVSEP_MSG);
2941 if (itree->nentries < -1) {
2942 err = got_error(GOT_ERR_PRIVSEP_MSG);
2945 if (itree->nentries == -1) {
2946 /* Tree was not found in pack file. */
2947 err = cb_tree(cb_arg, NULL, mtime, &tree_id,
2951 if (itree->nentries > INT_MAX) {
2952 err = got_error(GOT_ERR_PRIVSEP_LEN);
2955 tree.entries = calloc(itree->nentries,
2956 sizeof(struct got_tree_entry));
2957 if (tree.entries == NULL) {
2958 err = got_error_from_errno("calloc");
2961 if (itree->nentries == 0) {
2962 err = cb_tree(cb_arg, &tree, mtime, &tree_id,
2967 /* Prepare for next tree. */
2969 memset(&tree, 0, sizeof(tree));
2972 tree.nentries = itree->nentries;
2976 case GOT_IMSG_TREE_ENTRIES:
2977 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2978 if (nentries <= -1) {
2979 err = got_error(GOT_ERR_PRIVSEP_MSG);
2982 err = recv_tree_entries(imsg.data, datalen,
2986 if (tree.nentries == nentries) {
2987 err = cb_tree(cb_arg, &tree, mtime, &tree_id,
2992 /* Prepare for next tree. */
2994 memset(&tree, 0, sizeof(tree));
2998 case GOT_IMSG_TREE_ENUMERATION_DONE:
2999 /* All trees have been found and traversed. */
3000 if (!have_commit || path == NULL || nentries != -1) {
3001 err = got_error(GOT_ERR_PRIVSEP_MSG);
3004 err = cb_commit(cb_arg, mtime, &commit_id, repo);
3009 case GOT_IMSG_OBJECT_ENUMERATION_DONE:
3010 *found_all_objects = 1;
3013 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE:
3017 err = got_error(GOT_ERR_PRIVSEP_MSG);
3032 const struct got_error *
3033 got_privsep_send_raw_delta_req(struct imsgbuf *ibuf, int idx,
3034 struct got_object_id *id)
3036 struct got_imsg_raw_delta_request dreq;
3038 memset(&dreq, 0, sizeof(dreq));
3040 memcpy(&dreq.id, id, sizeof(dreq.id));
3042 if (imsg_compose(ibuf, GOT_IMSG_RAW_DELTA_REQUEST, 0, 0, -1,
3043 &dreq, sizeof(dreq)) == -1)
3044 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
3046 return flush_imsg(ibuf);
3049 const struct got_error *
3050 got_privsep_send_raw_delta_outfd(struct imsgbuf *ibuf, int fd)
3052 return send_fd(ibuf, GOT_IMSG_RAW_DELTA_OUTFD, fd);
3055 const struct got_error *
3056 got_privsep_send_raw_delta(struct imsgbuf *ibuf, uint64_t base_size,
3057 uint64_t result_size, off_t delta_size, off_t delta_compressed_size,
3058 off_t delta_offset, off_t delta_out_offset, struct got_object_id *base_id)
3060 struct got_imsg_raw_delta idelta;
3063 memset(&idelta, 0, sizeof(idelta));
3064 idelta.base_size = base_size;
3065 idelta.result_size = result_size;
3066 idelta.delta_size = delta_size;
3067 idelta.delta_compressed_size = delta_compressed_size;
3068 idelta.delta_offset = delta_offset;
3069 idelta.delta_out_offset = delta_out_offset;
3070 memcpy(&idelta.base_id, &base_id, sizeof(idelta.base_id));
3072 ret = imsg_compose(ibuf, GOT_IMSG_RAW_DELTA, 0, 0, -1,
3073 &idelta, sizeof(idelta));
3075 return got_error_from_errno("imsg_compose RAW_DELTA");
3077 return flush_imsg(ibuf);
3080 const struct got_error *
3081 got_privsep_recv_raw_delta(uint64_t *base_size, uint64_t *result_size,
3082 off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
3083 off_t *delta_out_offset, struct got_object_id **base_id,
3084 struct imsgbuf *ibuf)
3086 const struct got_error *err = NULL;
3088 struct got_imsg_raw_delta *delta;
3094 *delta_compressed_size = 0;
3096 *delta_out_offset = 0;
3099 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3103 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3105 switch (imsg.hdr.type) {
3106 case GOT_IMSG_RAW_DELTA:
3107 if (datalen != sizeof(*delta)) {
3108 err = got_error(GOT_ERR_PRIVSEP_LEN);
3112 *base_size = delta->base_size;
3113 *result_size = delta->result_size;
3114 *delta_size = delta->delta_size;
3115 *delta_compressed_size = delta->delta_compressed_size;
3116 *delta_offset = delta->delta_offset;
3117 *delta_out_offset = delta->delta_out_offset;
3118 *base_id = calloc(1, sizeof(**base_id));
3119 if (*base_id == NULL) {
3120 err = got_error_from_errno("malloc");
3123 memcpy(*base_id, &delta->base_id, sizeof(**base_id));
3126 err = got_error(GOT_ERR_PRIVSEP_MSG);
3139 static const struct got_error *
3140 send_idlist(struct imsgbuf *ibuf, struct got_object_id **ids, size_t nids)
3142 const struct got_error *err = NULL;
3143 struct got_imsg_object_idlist idlist;
3147 memset(&idlist, 0, sizeof(idlist));
3149 if (nids > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS)
3150 return got_error(GOT_ERR_NO_SPACE);
3152 wbuf = imsg_create(ibuf, GOT_IMSG_OBJ_ID_LIST, 0, 0,
3153 sizeof(idlist) + nids * sizeof(**ids));
3155 err = got_error_from_errno("imsg_create OBJ_ID_LIST");
3160 if (imsg_add(wbuf, &idlist, sizeof(idlist)) == -1)
3161 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3163 for (i = 0; i < nids; i++) {
3164 struct got_object_id *id = ids[i];
3165 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
3166 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3170 imsg_close(ibuf, wbuf);
3172 return flush_imsg(ibuf);
3175 const struct got_error *
3176 got_privsep_send_object_idlist(struct imsgbuf *ibuf,
3177 struct got_object_id **ids, size_t nids)
3179 const struct got_error *err = NULL;
3180 struct got_object_id *idlist[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS];
3183 for (i = 0; i < nids; i++) {
3184 idlist[i % nitems(idlist)] = ids[i];
3186 if (queued >= nitems(idlist)) {
3187 err = send_idlist(ibuf, idlist, queued);
3195 err = send_idlist(ibuf, idlist, queued);
3203 const struct got_error *
3204 got_privsep_send_object_idlist_done(struct imsgbuf *ibuf)
3206 if (imsg_compose(ibuf, GOT_IMSG_OBJ_ID_LIST_DONE, 0, 0, -1, NULL, 0)
3208 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3210 return flush_imsg(ibuf);
3213 const struct got_error *
3214 got_privsep_recv_object_idlist(int *done, struct got_object_id **ids,
3215 size_t *nids, struct imsgbuf *ibuf)
3217 const struct got_error *err = NULL;
3219 struct got_imsg_object_idlist *idlist;
3226 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3230 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3231 switch (imsg.hdr.type) {
3232 case GOT_IMSG_OBJ_ID_LIST:
3233 if (datalen < sizeof(*idlist)) {
3234 err = got_error(GOT_ERR_PRIVSEP_LEN);
3238 if (idlist->nids > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS ||
3239 idlist->nids * sizeof(**ids) > datalen - sizeof(*idlist)) {
3240 err = got_error(GOT_ERR_PRIVSEP_LEN);
3243 *nids = idlist->nids;
3244 *ids = calloc(*nids, sizeof(**ids));
3246 err = got_error_from_errno("calloc");
3249 memcpy(*ids, (uint8_t *)imsg.data + sizeof(*idlist),
3250 *nids * sizeof(**ids));
3252 case GOT_IMSG_OBJ_ID_LIST_DONE:
3256 err = got_error(GOT_ERR_PRIVSEP_MSG);
3265 const struct got_error *
3266 got_privsep_send_delta_reuse_req(struct imsgbuf *ibuf)
3268 if (imsg_compose(ibuf, GOT_IMSG_DELTA_REUSE_REQUEST, 0, 0, -1, NULL, 0)
3270 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3272 return flush_imsg(ibuf);
3275 const struct got_error *
3276 got_privsep_send_reused_deltas(struct imsgbuf *ibuf,
3277 struct got_imsg_reused_delta *deltas, size_t ndeltas)
3279 const struct got_error *err = NULL;
3281 struct got_imsg_reused_deltas ideltas;
3284 memset(&ideltas, 0, sizeof(ideltas));
3286 if (ndeltas > GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS)
3287 return got_error(GOT_ERR_NO_SPACE);
3289 wbuf = imsg_create(ibuf, GOT_IMSG_REUSED_DELTAS, 0, 0,
3290 sizeof(ideltas) + ndeltas * sizeof(*deltas));
3292 err = got_error_from_errno("imsg_create REUSED_DELTAS");
3296 ideltas.ndeltas = ndeltas;
3297 if (imsg_add(wbuf, &ideltas, sizeof(ideltas)) == -1)
3298 return got_error_from_errno("imsg_add REUSED_DELTAS");
3300 for (i = 0; i < ndeltas; i++) {
3301 struct got_imsg_reused_delta *delta = &deltas[i];
3302 if (imsg_add(wbuf, delta, sizeof(*delta)) == -1)
3303 return got_error_from_errno("imsg_add REUSED_DELTAS");
3307 imsg_close(ibuf, wbuf);
3309 return flush_imsg(ibuf);
3312 const struct got_error *
3313 got_privsep_send_reused_deltas_done(struct imsgbuf *ibuf)
3315 if (imsg_compose(ibuf, GOT_IMSG_DELTA_REUSE_DONE, 0, 0, -1, NULL, 0)
3317 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3319 return flush_imsg(ibuf);
3322 const struct got_error *
3323 got_privsep_recv_reused_deltas(int *done, struct got_imsg_reused_delta *deltas,
3324 size_t *ndeltas, struct imsgbuf *ibuf)
3326 const struct got_error *err = NULL;
3328 struct got_imsg_reused_deltas *ideltas;
3334 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3338 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3339 switch (imsg.hdr.type) {
3340 case GOT_IMSG_REUSED_DELTAS:
3341 if (datalen < sizeof(*ideltas)) {
3342 err = got_error(GOT_ERR_PRIVSEP_LEN);
3345 ideltas = imsg.data;
3346 if (ideltas->ndeltas > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS ||
3347 ideltas->ndeltas * sizeof(*deltas) >
3348 datalen - sizeof(*ideltas)) {
3349 err = got_error(GOT_ERR_PRIVSEP_LEN);
3352 *ndeltas = ideltas->ndeltas;
3353 memcpy(deltas, (uint8_t *)imsg.data + sizeof(*ideltas),
3354 *ndeltas * sizeof(*deltas));
3356 case GOT_IMSG_DELTA_REUSE_DONE:
3360 err = got_error(GOT_ERR_PRIVSEP_MSG);
3369 const struct got_error *
3370 got_privsep_init_commit_painting(struct imsgbuf *ibuf)
3372 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_PAINTING_INIT,
3375 return got_error_from_errno("imsg_compose "
3376 "COMMIT_PAINTING_INIT");
3378 return flush_imsg(ibuf);
3381 const struct got_error *
3382 got_privsep_send_painting_request(struct imsgbuf *ibuf, int idx,
3383 struct got_object_id *id, intptr_t color)
3385 struct got_imsg_commit_painting_request ireq;
3387 memset(&ireq, 0, sizeof(ireq));
3388 memcpy(&ireq.id, id, sizeof(ireq.id));
3392 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_PAINTING_REQUEST, 0, 0, -1,
3393 &ireq, sizeof(ireq)) == -1)
3394 return got_error_from_errno("imsg_compose "
3395 "COMMIT_PAINTING_REQUEST");
3397 return flush_imsg(ibuf);
3400 static const struct got_error *
3401 send_painted_commits(struct got_object_id_queue *ids, int *nids,
3402 size_t remain, int present_in_pack, struct imsgbuf *ibuf)
3404 const struct got_error *err = NULL;
3405 struct ibuf *wbuf = NULL;
3406 struct got_object_qid *qid;
3411 msglen = MIN(remain, MAX_IMSGSIZE - IMSG_HEADER_SIZE);
3412 ncommits = (msglen - sizeof(struct got_imsg_painted_commits)) /
3413 sizeof(struct got_imsg_painted_commit);
3415 wbuf = imsg_create(ibuf, GOT_IMSG_PAINTED_COMMITS, 0, 0, msglen);
3417 err = got_error_from_errno("imsg_create PAINTED_COMMITS");
3421 /* Keep in sync with struct got_imsg_painted_commits! */
3422 if (imsg_add(wbuf, &ncommits, sizeof(ncommits)) == -1)
3423 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3424 if (imsg_add(wbuf, &present_in_pack, sizeof(present_in_pack)) == -1)
3425 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3427 while (ncommits > 0) {
3428 qid = STAILQ_FIRST(ids);
3429 STAILQ_REMOVE_HEAD(ids, entry);
3432 color = (intptr_t)qid->data;
3434 /* Keep in sync with struct got_imsg_painted_commit! */
3435 if (imsg_add(wbuf, qid->id.sha1, SHA1_DIGEST_LENGTH) == -1)
3436 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3437 if (imsg_add(wbuf, &color, sizeof(color)) == -1)
3438 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3440 got_object_qid_free(qid);
3444 imsg_close(ibuf, wbuf);
3446 return flush_imsg(ibuf);
3449 const struct got_error *
3450 got_privsep_send_painted_commits(struct imsgbuf *ibuf,
3451 struct got_object_id_queue *ids, int *nids,
3452 int present_in_pack, int flush)
3454 const struct got_error *err;
3461 remain = (sizeof(struct got_imsg_painted_commits)) +
3462 *nids * sizeof(struct got_imsg_painted_commit);
3463 if (flush || remain >= MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
3464 err = send_painted_commits(ids, nids, remain,
3465 present_in_pack, ibuf);
3469 } while (flush && *nids > 0);
3474 const struct got_error *
3475 got_privsep_send_painting_commits_done(struct imsgbuf *ibuf)
3477 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_PAINTING_DONE,
3480 return got_error_from_errno("imsg_compose "
3481 "COMMIT_PAINTING_DONE");
3483 return flush_imsg(ibuf);
3486 const struct got_error *
3487 got_privsep_recv_painted_commits(struct got_object_id_queue *new_ids,
3488 got_privsep_recv_painted_commit_cb cb, void *cb_arg, struct imsgbuf *ibuf)
3490 const struct got_error *err = NULL;
3492 struct got_imsg_painted_commits icommits;
3493 struct got_imsg_painted_commit icommit;
3498 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3502 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3503 if (imsg.hdr.type == GOT_IMSG_COMMIT_PAINTING_DONE)
3505 if (imsg.hdr.type != GOT_IMSG_PAINTED_COMMITS)
3506 return got_error(GOT_ERR_PRIVSEP_MSG);
3508 if (datalen < sizeof(icommits))
3509 return got_error(GOT_ERR_PRIVSEP_LEN);
3510 memcpy(&icommits, imsg.data, sizeof(icommits));
3511 if (icommits.ncommits * sizeof(icommit) < icommits.ncommits ||
3512 datalen < sizeof(icommits) +
3513 icommits.ncommits * sizeof(icommit))
3514 return got_error(GOT_ERR_PRIVSEP_LEN);
3516 for (i = 0; i < icommits.ncommits; i++) {
3518 (uint8_t *)imsg.data + sizeof(icommits) + i * sizeof(icommit),
3521 if (icommits.present_in_pack) {
3522 struct got_object_id id;
3523 memcpy(id.sha1, icommit.id, SHA1_DIGEST_LENGTH);
3524 err = cb(cb_arg, &id, icommit.color);
3528 struct got_object_qid *qid;
3529 err = got_object_qid_alloc_partial(&qid);
3532 memcpy(qid->id.sha1, icommit.id,
3533 SHA1_DIGEST_LENGTH);
3534 qid->data = (void *)icommit.color;
3535 STAILQ_INSERT_TAIL(new_ids, qid, entry);
3545 const struct got_error *
3546 got_privsep_unveil_exec_helpers(void)
3548 const char *helpers[] = {
3549 GOT_PATH_PROG_READ_PACK,
3550 GOT_PATH_PROG_READ_OBJECT,
3551 GOT_PATH_PROG_READ_COMMIT,
3552 GOT_PATH_PROG_READ_TREE,
3553 GOT_PATH_PROG_READ_BLOB,
3554 GOT_PATH_PROG_READ_TAG,
3555 GOT_PATH_PROG_READ_GITCONFIG,
3556 GOT_PATH_PROG_READ_GOTCONFIG,
3557 GOT_PATH_PROG_READ_PATCH,
3558 GOT_PATH_PROG_FETCH_PACK,
3559 GOT_PATH_PROG_INDEX_PACK,
3560 GOT_PATH_PROG_SEND_PACK,
3564 for (i = 0; i < nitems(helpers); i++) {
3565 if (unveil(helpers[i], "x") == 0)
3567 return got_error_from_errno2("unveil", helpers[i]);
3574 got_privsep_exec_child(int imsg_fds[2], const char *path, const char *repo_path)
3576 if (close(imsg_fds[0]) == -1) {
3577 fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
3581 if (dup2(imsg_fds[1], GOT_IMSG_FD_CHILD) == -1) {
3582 fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
3586 closefrom(GOT_IMSG_FD_CHILD + 1);
3588 if (execl(path, path, repo_path, (char *)NULL) == -1) {
3589 fprintf(stderr, "%s: %s: %s\n", getprogname(), path,