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_object.h"
39 #include "got_error.h"
41 #include "got_repository.h"
43 #include "got_lib_hash.h"
44 #include "got_lib_delta.h"
45 #include "got_lib_inflate.h"
46 #include "got_lib_object.h"
47 #include "got_lib_object_parse.h"
48 #include "got_lib_object_qid.h"
49 #include "got_lib_privsep.h"
50 #include "got_lib_pack.h"
51 #include "got_lib_poll.h"
53 #include "got_privsep.h"
56 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
60 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
63 static const struct got_error *
64 read_imsg(struct imsgbuf *ibuf)
66 const struct got_error *err;
69 err = got_poll_fd(ibuf->fd, POLLIN, INFTIM);
71 if (err->code == GOT_ERR_EOF)
72 return got_error(GOT_ERR_PRIVSEP_PIPE);
78 if (errno == EAGAIN) /* Could be a file-descriptor leak. */
79 return got_error(GOT_ERR_PRIVSEP_NO_FD);
80 return got_error(GOT_ERR_PRIVSEP_READ);
83 return got_error(GOT_ERR_PRIVSEP_PIPE);
88 const struct got_error *
89 got_privsep_wait_for_child(pid_t pid)
93 if (waitpid(pid, &child_status, 0) == -1)
94 return got_error_from_errno("waitpid");
96 if (!WIFEXITED(child_status))
97 return got_error(GOT_ERR_PRIVSEP_DIED);
99 if (WEXITSTATUS(child_status) != 0)
100 return got_error(GOT_ERR_PRIVSEP_EXIT);
105 static const struct got_error *
106 recv_imsg_error(struct imsg *imsg, size_t datalen)
108 struct got_imsg_error *ierr;
110 if (datalen != sizeof(*ierr))
111 return got_error(GOT_ERR_PRIVSEP_LEN);
114 if (ierr->code == GOT_ERR_ERRNO) {
115 static struct got_error serr;
116 serr.code = GOT_ERR_ERRNO;
117 serr.msg = strerror(ierr->errno_code);
121 return got_error(ierr->code);
124 const struct got_error *
125 got_privsep_recv_imsg(struct imsg *imsg, struct imsgbuf *ibuf,
128 const struct got_error *err;
131 n = imsg_get(ibuf, imsg);
133 return got_error_from_errno("imsg_get");
136 err = read_imsg(ibuf);
139 n = imsg_get(ibuf, imsg);
141 return got_error_from_errno("imsg_get");
144 if (imsg->hdr.len < IMSG_HEADER_SIZE + min_datalen)
145 return got_error(GOT_ERR_PRIVSEP_LEN);
147 if (imsg->hdr.type == GOT_IMSG_ERROR) {
148 size_t datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
149 return recv_imsg_error(imsg, datalen);
155 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
157 got_privsep_send_error(struct imsgbuf *ibuf, const struct got_error *err)
159 const struct got_error *poll_err;
160 struct got_imsg_error ierr;
163 ierr.code = err->code;
164 if (err->code == GOT_ERR_ERRNO)
165 ierr.errno_code = errno;
168 ret = imsg_compose(ibuf, GOT_IMSG_ERROR, 0, 0, -1, &ierr, sizeof(ierr));
170 fprintf(stderr, "%s: error %d \"%s\": imsg_compose: %s\n",
171 getprogname(), err->code, err->msg, strerror(errno));
175 poll_err = got_poll_fd(ibuf->fd, POLLOUT, INFTIM);
177 fprintf(stderr, "%s: error %d \"%s\": poll: %s\n",
178 getprogname(), err->code, err->msg, poll_err->msg);
182 ret = imsg_flush(ibuf);
184 fprintf(stderr, "%s: error %d \"%s\": imsg_flush: %s\n",
185 getprogname(), err->code, err->msg, strerror(errno));
191 static const struct got_error *
192 flush_imsg(struct imsgbuf *ibuf)
194 const struct got_error *err;
196 err = got_poll_fd(ibuf->fd, POLLOUT, INFTIM);
200 if (imsg_flush(ibuf) == -1) {
202 return got_error_from_errno("imsg_flush");
208 const struct got_error *
209 got_privsep_flush_imsg(struct imsgbuf *ibuf)
211 return flush_imsg(ibuf);
214 const struct got_error *
215 got_privsep_send_stop(int fd)
219 imsg_init(&ibuf, fd);
221 if (imsg_compose(&ibuf, GOT_IMSG_STOP, 0, 0, -1, NULL, 0) == -1)
222 return got_error_from_errno("imsg_compose STOP");
224 return flush_imsg(&ibuf);
227 const struct got_error *
228 got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd,
229 struct got_object_id *id)
231 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_REQUEST, 0, 0, fd,
232 id, sizeof(*id)) == -1)
233 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
235 return flush_imsg(ibuf);
238 const struct got_error *
239 got_privsep_send_raw_obj_req(struct imsgbuf *ibuf, int fd,
240 struct got_object_id *id)
242 const struct got_error *err;
244 if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_REQUEST, 0, 0, fd,
245 id, sizeof(*id)) == -1) {
246 err = got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
251 return flush_imsg(ibuf);
254 const struct got_error *
255 got_privsep_send_raw_obj_outfd(struct imsgbuf *ibuf, int outfd)
257 const struct got_error *err = NULL;
259 if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_OUTFD, 0, 0, outfd, NULL, 0)
261 err = got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
266 return flush_imsg(ibuf);
269 const struct got_error *
270 got_privsep_send_raw_obj(struct imsgbuf *ibuf, off_t size, size_t hdrlen,
273 struct got_imsg_raw_obj iobj;
274 size_t len = sizeof(iobj);
277 memset(&iobj, 0, sizeof(iobj));
278 iobj.hdrlen = hdrlen;
281 if (data && size + hdrlen <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX)
282 len += (size_t)size + hdrlen;
284 wbuf = imsg_create(ibuf, GOT_IMSG_RAW_OBJECT, 0, 0, len);
286 return got_error_from_errno("imsg_create RAW_OBJECT");
288 if (imsg_add(wbuf, &iobj, sizeof(iobj)) == -1)
289 return got_error_from_errno("imsg_add RAW_OBJECT");
291 if (data && size + hdrlen <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX) {
292 if (imsg_add(wbuf, data, size + hdrlen) == -1)
293 return got_error_from_errno("imsg_add RAW_OBJECT");
296 imsg_close(ibuf, wbuf);
297 return flush_imsg(ibuf);
300 const struct got_error *
301 got_privsep_recv_raw_obj(uint8_t **outbuf, off_t *size, size_t *hdrlen,
302 struct imsgbuf *ibuf)
304 const struct got_error *err = NULL;
306 struct got_imsg_raw_obj *iobj;
311 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
315 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
317 switch (imsg.hdr.type) {
318 case GOT_IMSG_RAW_OBJECT:
319 if (datalen < sizeof(*iobj)) {
320 err = got_error(GOT_ERR_PRIVSEP_LEN);
325 *hdrlen = iobj->hdrlen;
327 if (datalen == sizeof(*iobj)) {
328 /* Data has been written to file descriptor. */
333 *size + *hdrlen > GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX) {
334 err = got_error(GOT_ERR_PRIVSEP_LEN);
338 *outbuf = malloc(*size + *hdrlen);
339 if (*outbuf == NULL) {
340 err = got_error_from_errno("malloc");
343 memcpy(*outbuf, imsg.data + sizeof(*iobj), *size + *hdrlen);
346 err = got_error(GOT_ERR_PRIVSEP_MSG);
355 const struct got_error *
356 got_privsep_send_commit_req(struct imsgbuf *ibuf, int fd,
357 struct got_object_id *id, int pack_idx)
359 const struct got_error *err = NULL;
360 struct got_imsg_packed_object iobj;
364 memset(&iobj, 0, sizeof(iobj));
365 if (pack_idx != -1) { /* commit is packed */
367 memcpy(&iobj.id, id, sizeof(iobj.id));
375 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, data, len)
377 err = got_error_from_errno("imsg_compose COMMIT_REQUEST");
382 return flush_imsg(ibuf);
385 const struct got_error *
386 got_privsep_send_tree_req(struct imsgbuf *ibuf, int fd,
387 struct got_object_id *id, int pack_idx)
389 const struct got_error *err;
394 len = sizeof(struct got_imsg_packed_object);
398 wbuf = imsg_create(ibuf, GOT_IMSG_TREE_REQUEST, 0, 0, len);
400 err = got_error_from_errno("imsg_create TREE_REQUEST");
406 if (imsg_add(wbuf, id, sizeof(*id)) == -1) {
407 err = got_error_from_errno("imsg_add TREE_REQUEST");
413 if (pack_idx != -1) { /* tree is packed */
414 if (imsg_add(wbuf, &pack_idx, sizeof(pack_idx)) == -1) {
415 err = got_error_from_errno("imsg_add TREE_REQUEST");
422 ibuf_fd_set(wbuf, fd);
423 imsg_close(ibuf, wbuf);
425 return flush_imsg(ibuf);
428 const struct got_error *
429 got_privsep_send_tag_req(struct imsgbuf *ibuf, int fd,
430 struct got_object_id *id, int pack_idx)
432 const struct got_error *err;
433 struct got_imsg_packed_object iobj;
437 memset(&iobj, 0, sizeof(iobj));
438 if (pack_idx != -1) { /* tag is packed */
440 memcpy(&iobj.id, id, sizeof(iobj.id));
448 if (imsg_compose(ibuf, GOT_IMSG_TAG_REQUEST, 0, 0, fd, data, len)
450 err = got_error_from_errno("imsg_compose TAG_REQUEST");
456 return flush_imsg(ibuf);
459 const struct got_error *
460 got_privsep_send_blob_req(struct imsgbuf *ibuf, int infd,
461 struct got_object_id *id, int pack_idx)
463 const struct got_error *err = NULL;
464 struct got_imsg_packed_object iobj;
468 memset(&iobj, 0, sizeof(iobj));
469 if (pack_idx != -1) { /* blob is packed */
471 memcpy(&iobj.id, id, sizeof(iobj.id));
479 if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, data, len)
481 err = got_error_from_errno("imsg_compose BLOB_REQUEST");
486 return flush_imsg(ibuf);
489 const struct got_error *
490 got_privsep_send_blob_outfd(struct imsgbuf *ibuf, int outfd)
492 const struct got_error *err = NULL;
494 if (imsg_compose(ibuf, GOT_IMSG_BLOB_OUTFD, 0, 0, outfd, NULL, 0)
496 err = got_error_from_errno("imsg_compose BLOB_OUTFD");
501 return flush_imsg(ibuf);
504 static const struct got_error *
505 send_fd(struct imsgbuf *ibuf, int imsg_code, int fd)
507 const struct got_error *err = NULL;
509 if (imsg_compose(ibuf, imsg_code, 0, 0, fd, NULL, 0) == -1) {
510 err = got_error_from_errno("imsg_compose TMPFD");
515 return flush_imsg(ibuf);
518 const struct got_error *
519 got_privsep_send_tmpfd(struct imsgbuf *ibuf, int fd)
521 return send_fd(ibuf, GOT_IMSG_TMPFD, fd);
524 const struct got_error *
525 got_privsep_send_obj(struct imsgbuf *ibuf, struct got_object *obj)
527 struct got_imsg_object iobj;
529 memset(&iobj, 0, sizeof(iobj));
531 memcpy(&iobj.id, &obj->id, sizeof(iobj.id));
532 iobj.type = obj->type;
533 iobj.flags = obj->flags;
534 iobj.hdrlen = obj->hdrlen;
535 iobj.size = obj->size;
536 if (iobj.flags & GOT_OBJ_FLAG_PACKED) {
537 iobj.pack_offset = obj->pack_offset;
538 iobj.pack_idx = obj->pack_idx;
541 if (imsg_compose(ibuf, GOT_IMSG_OBJECT, 0, 0, -1, &iobj, sizeof(iobj))
543 return got_error_from_errno("imsg_compose OBJECT");
545 return flush_imsg(ibuf);
548 const struct got_error *
549 got_privsep_send_fetch_req(struct imsgbuf *ibuf, int fd,
550 struct got_pathlist_head *have_refs, int fetch_all_branches,
551 struct got_pathlist_head *wanted_branches,
552 struct got_pathlist_head *wanted_refs, int list_refs_only,
553 const char *worktree_branch, const char *remote_head,
554 int no_head, int verbosity)
556 const struct got_error *err = NULL;
558 struct got_pathlist_entry *pe;
559 struct got_imsg_fetch_request fetchreq;
560 size_t remote_head_len, worktree_branch_len, len = sizeof(fetchreq);
562 if (worktree_branch) {
563 worktree_branch_len = strlen(worktree_branch);
564 len += worktree_branch_len;
567 remote_head_len = strlen(remote_head);
568 len += remote_head_len;
571 if (len >= MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
573 return got_error(GOT_ERR_NO_SPACE);
576 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_REQUEST, 0, 0, len);
578 err = got_error_from_errno("imsg_create FETCH_HAVE_REF");
583 memset(&fetchreq, 0, sizeof(fetchreq));
584 fetchreq.no_head = no_head;
585 fetchreq.fetch_all_branches = fetch_all_branches;
586 fetchreq.list_refs_only = list_refs_only;
587 fetchreq.verbosity = verbosity;
588 if (worktree_branch != NULL)
589 fetchreq.worktree_branch_len = worktree_branch_len;
590 if (remote_head != NULL)
591 fetchreq.remote_head_len = remote_head_len;
592 TAILQ_FOREACH(pe, have_refs, entry)
593 fetchreq.n_have_refs++;
594 TAILQ_FOREACH(pe, wanted_branches, entry)
595 fetchreq.n_wanted_branches++;
596 TAILQ_FOREACH(pe, wanted_refs, entry)
597 fetchreq.n_wanted_refs++;
598 if (imsg_add(wbuf, &fetchreq, sizeof(fetchreq)) == -1)
599 return got_error_from_errno("imsg_add FETCH_REQUEST");
600 if (worktree_branch) {
601 if (imsg_add(wbuf, worktree_branch, worktree_branch_len)
603 err = got_error_from_errno("imsg_add FETCH_REQUEST");
609 if (imsg_add(wbuf, remote_head, remote_head_len) == -1) {
610 err = got_error_from_errno("imsg_add FETCH_REQUEST");
615 ibuf_fd_set(wbuf, fd);
617 imsg_close(ibuf, wbuf);
619 err = flush_imsg(ibuf);
623 TAILQ_FOREACH(pe, have_refs, entry) {
624 const char *name = pe->path;
625 size_t name_len = pe->path_len;
626 struct got_object_id *id = pe->data;
628 len = sizeof(struct got_imsg_fetch_have_ref) + name_len;
629 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_HAVE_REF, 0, 0, len);
631 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
633 /* Keep in sync with struct got_imsg_fetch_have_ref! */
634 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
635 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
636 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
637 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
638 if (imsg_add(wbuf, name, name_len) == -1)
639 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
641 imsg_close(ibuf, wbuf);
642 err = flush_imsg(ibuf);
647 TAILQ_FOREACH(pe, wanted_branches, entry) {
648 const char *name = pe->path;
649 size_t name_len = pe->path_len;
651 len = sizeof(struct got_imsg_fetch_wanted_branch) + name_len;
652 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_WANTED_BRANCH, 0, 0,
655 return got_error_from_errno(
656 "imsg_create FETCH_WANTED_BRANCH");
658 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
659 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
660 return got_error_from_errno(
661 "imsg_add FETCH_WANTED_BRANCH");
662 if (imsg_add(wbuf, name, name_len) == -1)
663 return got_error_from_errno(
664 "imsg_add FETCH_WANTED_BRANCH");
666 imsg_close(ibuf, wbuf);
667 err = flush_imsg(ibuf);
672 TAILQ_FOREACH(pe, wanted_refs, entry) {
673 const char *name = pe->path;
674 size_t name_len = pe->path_len;
676 len = sizeof(struct got_imsg_fetch_wanted_ref) + name_len;
677 wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_WANTED_REF, 0, 0,
680 return got_error_from_errno(
681 "imsg_create FETCH_WANTED_REF");
683 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
684 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
685 return got_error_from_errno(
686 "imsg_add FETCH_WANTED_REF");
687 if (imsg_add(wbuf, name, name_len) == -1)
688 return got_error_from_errno(
689 "imsg_add FETCH_WANTED_REF");
691 imsg_close(ibuf, wbuf);
692 err = flush_imsg(ibuf);
700 const struct got_error *
701 got_privsep_send_fetch_outfd(struct imsgbuf *ibuf, int fd)
703 return send_fd(ibuf, GOT_IMSG_FETCH_OUTFD, fd);
706 const struct got_error *
707 got_privsep_recv_fetch_progress(int *done, struct got_object_id **id,
708 char **refname, struct got_pathlist_head *symrefs, char **server_progress,
709 off_t *packfile_size, uint8_t *pack_sha1, struct imsgbuf *ibuf)
711 const struct got_error *err = NULL;
714 struct got_imsg_fetch_symrefs *isymrefs = NULL;
722 *server_progress = NULL;
724 memset(pack_sha1, 0, SHA1_DIGEST_LENGTH);
726 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
730 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
731 switch (imsg.hdr.type) {
732 case GOT_IMSG_FETCH_SYMREFS:
733 if (datalen < sizeof(*isymrefs)) {
734 err = got_error(GOT_ERR_PRIVSEP_LEN);
737 if (isymrefs != NULL) {
738 err = got_error(GOT_ERR_PRIVSEP_MSG);
741 isymrefs = (struct got_imsg_fetch_symrefs *)imsg.data;
742 off = sizeof(*isymrefs);
743 remain = datalen - off;
744 for (n = 0; n < isymrefs->nsymrefs; n++) {
745 struct got_imsg_fetch_symref *s;
747 if (remain < sizeof(struct got_imsg_fetch_symref)) {
748 err = got_error(GOT_ERR_PRIVSEP_LEN);
751 s = (struct got_imsg_fetch_symref *)(imsg.data + off);
753 remain -= sizeof(*s);
754 if (remain < s->name_len) {
755 err = got_error(GOT_ERR_PRIVSEP_LEN);
758 name = strndup(imsg.data + off, s->name_len);
760 err = got_error_from_errno("strndup");
764 remain -= s->name_len;
765 if (remain < s->target_len) {
766 err = got_error(GOT_ERR_PRIVSEP_LEN);
770 target = strndup(imsg.data + off, s->target_len);
771 if (target == NULL) {
772 err = got_error_from_errno("strndup");
776 off += s->target_len;
777 remain -= s->target_len;
778 err = got_pathlist_append(symrefs, name, target);
786 case GOT_IMSG_FETCH_REF:
787 if (datalen <= sizeof(**id)) {
788 err = got_error(GOT_ERR_PRIVSEP_MSG);
791 *id = malloc(sizeof(**id));
793 err = got_error_from_errno("malloc");
796 memcpy(*id, imsg.data, sizeof(**id));
797 *refname = strndup(imsg.data + sizeof(**id),
798 datalen - sizeof(**id));
799 if (*refname == NULL) {
800 err = got_error_from_errno("strndup");
804 case GOT_IMSG_FETCH_SERVER_PROGRESS:
806 err = got_error(GOT_ERR_PRIVSEP_LEN);
809 *server_progress = strndup(imsg.data, datalen);
810 if (*server_progress == NULL) {
811 err = got_error_from_errno("strndup");
814 for (i = 0; i < datalen; i++) {
815 if (!isprint((unsigned char)(*server_progress)[i]) &&
816 !isspace((unsigned char)(*server_progress)[i])) {
817 err = got_error(GOT_ERR_PRIVSEP_MSG);
818 free(*server_progress);
819 *server_progress = NULL;
824 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS:
825 if (datalen < sizeof(*packfile_size)) {
826 err = got_error(GOT_ERR_PRIVSEP_MSG);
829 memcpy(packfile_size, imsg.data, sizeof(*packfile_size));
831 case GOT_IMSG_FETCH_DONE:
832 if (datalen != SHA1_DIGEST_LENGTH) {
833 err = got_error(GOT_ERR_PRIVSEP_MSG);
836 memcpy(pack_sha1, imsg.data, SHA1_DIGEST_LENGTH);
840 err = got_error(GOT_ERR_PRIVSEP_MSG);
854 static const struct got_error *
855 send_send_ref(const char *name, size_t name_len, struct got_object_id *id,
856 int delete, struct imsgbuf *ibuf)
861 len = sizeof(struct got_imsg_send_ref) + name_len;
862 wbuf = imsg_create(ibuf, GOT_IMSG_SEND_REF, 0, 0, len);
864 return got_error_from_errno("imsg_create SEND_REF");
866 /* Keep in sync with struct got_imsg_send_ref! */
867 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
868 return got_error_from_errno("imsg_add SEND_REF");
869 if (imsg_add(wbuf, &delete, sizeof(delete)) == -1)
870 return got_error_from_errno("imsg_add SEND_REF");
871 if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1)
872 return got_error_from_errno("imsg_add SEND_REF");
873 if (imsg_add(wbuf, name, name_len) == -1)
874 return got_error_from_errno("imsg_add SEND_REF");
876 imsg_close(ibuf, wbuf);
877 return flush_imsg(ibuf);
880 const struct got_error *
881 got_privsep_send_send_req(struct imsgbuf *ibuf, int fd,
882 struct got_pathlist_head *have_refs,
883 struct got_pathlist_head *delete_refs,
886 const struct got_error *err = NULL;
887 struct got_pathlist_entry *pe;
888 struct got_imsg_send_request sendreq;
889 struct got_object_id zero_id;
891 memset(&zero_id, 0, sizeof(zero_id));
892 memset(&sendreq, 0, sizeof(sendreq));
893 sendreq.verbosity = verbosity;
894 TAILQ_FOREACH(pe, have_refs, entry)
896 TAILQ_FOREACH(pe, delete_refs, entry)
898 if (imsg_compose(ibuf, GOT_IMSG_SEND_REQUEST, 0, 0, fd,
899 &sendreq, sizeof(sendreq)) == -1) {
900 err = got_error_from_errno(
901 "imsg_compose FETCH_SERVER_PROGRESS");
906 err = flush_imsg(ibuf);
910 TAILQ_FOREACH(pe, have_refs, entry) {
911 const char *name = pe->path;
912 size_t name_len = pe->path_len;
913 struct got_object_id *id = pe->data;
914 err = send_send_ref(name, name_len, id, 0, ibuf);
919 TAILQ_FOREACH(pe, delete_refs, entry) {
920 const char *name = pe->path;
921 size_t name_len = pe->path_len;
922 err = send_send_ref(name, name_len, &zero_id, 1, ibuf);
927 if (fd != -1 && close(fd) == -1 && err == NULL)
928 err = got_error_from_errno("close");
932 const struct got_error *
933 got_privsep_recv_send_remote_refs(struct got_pathlist_head *remote_refs,
934 struct imsgbuf *ibuf)
936 const struct got_error *err = NULL;
940 struct got_imsg_send_remote_ref iremote_ref;
941 struct got_object_id *id = NULL;
942 char *refname = NULL;
943 struct got_pathlist_entry *new;
946 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
949 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
950 switch (imsg.hdr.type) {
951 case GOT_IMSG_SEND_REMOTE_REF:
952 if (datalen < sizeof(iremote_ref)) {
953 err = got_error(GOT_ERR_PRIVSEP_MSG);
956 memcpy(&iremote_ref, imsg.data, sizeof(iremote_ref));
957 if (datalen != sizeof(iremote_ref) +
958 iremote_ref.name_len) {
959 err = got_error(GOT_ERR_PRIVSEP_MSG);
962 id = malloc(sizeof(*id));
964 err = got_error_from_errno("malloc");
967 memcpy(id, &iremote_ref.id, sizeof(*id));
968 refname = strndup(imsg.data + sizeof(iremote_ref),
969 datalen - sizeof(iremote_ref));
970 if (refname == NULL) {
971 err = got_error_from_errno("strndup");
974 err = got_pathlist_insert(&new, remote_refs,
978 if (new == NULL) { /* duplicate which wasn't inserted */
985 case GOT_IMSG_SEND_PACK_REQUEST:
987 err = got_error(GOT_ERR_PRIVSEP_MSG);
990 /* got-send-pack is now waiting for a pack file. */
994 err = got_error(GOT_ERR_PRIVSEP_MSG);
1005 const struct got_error *
1006 got_privsep_send_packfd(struct imsgbuf *ibuf, int fd)
1008 return send_fd(ibuf, GOT_IMSG_SEND_PACKFD, fd);
1011 const struct got_error *
1012 got_privsep_recv_send_progress(int *done, off_t *bytes_sent,
1013 int *success, char **refname, char **errmsg, struct imsgbuf *ibuf)
1015 const struct got_error *err = NULL;
1018 struct got_imsg_send_ref_status iref_status;
1020 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1026 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
1030 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1031 switch (imsg.hdr.type) {
1032 case GOT_IMSG_SEND_UPLOAD_PROGRESS:
1033 if (datalen < sizeof(*bytes_sent)) {
1034 err = got_error(GOT_ERR_PRIVSEP_MSG);
1037 memcpy(bytes_sent, imsg.data, sizeof(*bytes_sent));
1039 case GOT_IMSG_SEND_REF_STATUS:
1040 if (datalen < sizeof(iref_status)) {
1041 err = got_error(GOT_ERR_PRIVSEP_MSG);
1044 memcpy(&iref_status, imsg.data, sizeof(iref_status));
1045 if (datalen != sizeof(iref_status) + iref_status.name_len +
1046 iref_status.errmsg_len) {
1047 err = got_error(GOT_ERR_PRIVSEP_MSG);
1050 *success = iref_status.success;
1051 *refname = strndup(imsg.data + sizeof(iref_status),
1052 iref_status.name_len);
1054 if (iref_status.errmsg_len != 0)
1055 *errmsg = strndup(imsg.data + sizeof(iref_status) +
1056 iref_status.name_len, iref_status.errmsg_len);
1058 case GOT_IMSG_SEND_DONE:
1060 err = got_error(GOT_ERR_PRIVSEP_MSG);
1066 err = got_error(GOT_ERR_PRIVSEP_MSG);
1074 const struct got_error *
1075 got_privsep_send_index_pack_req(struct imsgbuf *ibuf, uint8_t *pack_sha1,
1078 const struct got_error *err = NULL;
1080 /* Keep in sync with struct got_imsg_index_pack_request */
1081 if (imsg_compose(ibuf, GOT_IMSG_IDXPACK_REQUEST, 0, 0, fd,
1082 pack_sha1, SHA1_DIGEST_LENGTH) == -1) {
1083 err = got_error_from_errno("imsg_compose INDEX_REQUEST");
1087 return flush_imsg(ibuf);
1090 const struct got_error *
1091 got_privsep_send_index_pack_outfd(struct imsgbuf *ibuf, int fd)
1093 return send_fd(ibuf, GOT_IMSG_IDXPACK_OUTFD, fd);
1096 const struct got_error *
1097 got_privsep_recv_index_progress(int *done, int *nobj_total,
1098 int *nobj_indexed, int *nobj_loose, int *nobj_resolved,
1099 struct imsgbuf *ibuf)
1101 const struct got_error *err = NULL;
1103 struct got_imsg_index_pack_progress *iprogress;
1111 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
1115 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1116 switch (imsg.hdr.type) {
1117 case GOT_IMSG_IDXPACK_PROGRESS:
1118 if (datalen < sizeof(*iprogress)) {
1119 err = got_error(GOT_ERR_PRIVSEP_LEN);
1122 iprogress = (struct got_imsg_index_pack_progress *)imsg.data;
1123 if (iprogress->nobj_total < 0 || iprogress->nobj_indexed < 0 ||
1124 iprogress->nobj_loose < 0 || iprogress->nobj_resolved < 0) {
1125 err = got_error(GOT_ERR_RANGE);
1128 *nobj_total = iprogress->nobj_total;
1129 *nobj_indexed = iprogress->nobj_indexed;
1130 *nobj_loose = iprogress->nobj_loose;
1131 *nobj_resolved = iprogress->nobj_resolved;
1133 case GOT_IMSG_IDXPACK_DONE:
1135 err = got_error(GOT_ERR_PRIVSEP_LEN);
1141 err = got_error(GOT_ERR_PRIVSEP_MSG);
1149 const struct got_error *
1150 got_privsep_get_imsg_obj(struct got_object **obj, struct imsg *imsg,
1151 struct imsgbuf *ibuf)
1153 struct got_imsg_object *iobj;
1154 size_t datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1156 if (datalen != sizeof(*iobj))
1157 return got_error(GOT_ERR_PRIVSEP_LEN);
1160 if (iobj->pack_offset < 0)
1161 return got_error(GOT_ERR_PACK_OFFSET);
1163 *obj = calloc(1, sizeof(**obj));
1165 return got_error_from_errno("calloc");
1167 memcpy(&(*obj)->id, &iobj->id, sizeof(iobj->id));
1168 (*obj)->type = iobj->type;
1169 (*obj)->flags = iobj->flags;
1170 (*obj)->hdrlen = iobj->hdrlen;
1171 (*obj)->size = iobj->size;
1172 /* path_packfile is handled by caller */
1173 if (iobj->flags & GOT_OBJ_FLAG_PACKED) {
1174 (*obj)->pack_offset = iobj->pack_offset;
1175 (*obj)->pack_idx = iobj->pack_idx;
1177 STAILQ_INIT(&(*obj)->deltas.entries);
1181 const struct got_error *
1182 got_privsep_recv_obj(struct got_object **obj, struct imsgbuf *ibuf)
1184 const struct got_error *err = NULL;
1186 const size_t min_datalen =
1187 MIN(sizeof(struct got_imsg_error), sizeof(struct got_imsg_object));
1191 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1195 switch (imsg.hdr.type) {
1196 case GOT_IMSG_OBJECT:
1197 err = got_privsep_get_imsg_obj(obj, &imsg, ibuf);
1200 err = got_error(GOT_ERR_PRIVSEP_MSG);
1209 static const struct got_error *
1210 send_commit_logmsg(struct imsgbuf *ibuf, struct got_commit_object *commit,
1213 const struct got_error *err = NULL;
1214 size_t offset, remain;
1217 remain = logmsg_len;
1218 while (remain > 0) {
1219 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
1221 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_LOGMSG, 0, 0, -1,
1222 commit->logmsg + offset, n) == -1) {
1223 err = got_error_from_errno("imsg_compose "
1228 err = flush_imsg(ibuf);
1239 const struct got_error *
1240 got_privsep_send_commit(struct imsgbuf *ibuf, struct got_commit_object *commit)
1242 const struct got_error *err = NULL;
1243 struct got_imsg_commit_object *icommit;
1246 struct got_object_qid *qid;
1247 size_t author_len = strlen(commit->author);
1248 size_t committer_len = strlen(commit->committer);
1249 size_t logmsg_len = strlen(commit->logmsg);
1251 total = sizeof(*icommit) + author_len + committer_len +
1252 commit->nparents * sizeof(struct got_object_id);
1254 buf = malloc(total);
1256 return got_error_from_errno("malloc");
1258 icommit = (struct got_imsg_commit_object *)buf;
1259 memcpy(&icommit->tree_id, commit->tree_id, sizeof(icommit->tree_id));
1260 icommit->author_len = author_len;
1261 icommit->author_time = commit->author_time;
1262 icommit->author_gmtoff = commit->author_gmtoff;
1263 icommit->committer_len = committer_len;
1264 icommit->committer_time = commit->committer_time;
1265 icommit->committer_gmtoff = commit->committer_gmtoff;
1266 icommit->logmsg_len = logmsg_len;
1267 icommit->nparents = commit->nparents;
1269 len = sizeof(*icommit);
1270 memcpy(buf + len, commit->author, author_len);
1272 memcpy(buf + len, commit->committer, committer_len);
1273 len += committer_len;
1274 STAILQ_FOREACH(qid, &commit->parent_ids, entry) {
1275 memcpy(buf + len, &qid->id, sizeof(qid->id));
1276 len += sizeof(qid->id);
1279 if (imsg_compose(ibuf, GOT_IMSG_COMMIT, 0, 0, -1, buf, len) == -1) {
1280 err = got_error_from_errno("imsg_compose COMMIT");
1284 if (logmsg_len == 0 ||
1285 logmsg_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
1286 err = flush_imsg(ibuf);
1290 err = send_commit_logmsg(ibuf, commit, logmsg_len);
1296 static const struct got_error *
1297 get_commit_from_imsg(struct got_commit_object **commit,
1298 struct imsg *imsg, size_t datalen, struct imsgbuf *ibuf)
1300 const struct got_error *err = NULL;
1301 struct got_imsg_commit_object *icommit;
1305 if (datalen < sizeof(*icommit))
1306 return got_error(GOT_ERR_PRIVSEP_LEN);
1308 icommit = imsg->data;
1309 if (datalen != sizeof(*icommit) + icommit->author_len +
1310 icommit->committer_len +
1311 icommit->nparents * sizeof(struct got_object_id))
1312 return got_error(GOT_ERR_PRIVSEP_LEN);
1314 if (icommit->nparents < 0)
1315 return got_error(GOT_ERR_PRIVSEP_LEN);
1317 len += sizeof(*icommit);
1319 *commit = got_object_commit_alloc_partial();
1320 if (*commit == NULL)
1321 return got_error_from_errno(
1322 "got_object_commit_alloc_partial");
1324 memcpy((*commit)->tree_id, &icommit->tree_id,
1325 sizeof(icommit->tree_id));
1326 (*commit)->author_time = icommit->author_time;
1327 (*commit)->author_gmtoff = icommit->author_gmtoff;
1328 (*commit)->committer_time = icommit->committer_time;
1329 (*commit)->committer_gmtoff = icommit->committer_gmtoff;
1331 (*commit)->author = strndup(imsg->data + len, icommit->author_len);
1332 if ((*commit)->author == NULL) {
1333 err = got_error_from_errno("strndup");
1336 len += icommit->author_len;
1338 (*commit)->committer = strndup(imsg->data + len,
1339 icommit->committer_len);
1340 if ((*commit)->committer == NULL) {
1341 err = got_error_from_errno("strndup");
1344 len += icommit->committer_len;
1346 if (icommit->logmsg_len == 0) {
1347 (*commit)->logmsg = strdup("");
1348 if ((*commit)->logmsg == NULL) {
1349 err = got_error_from_errno("strdup");
1353 size_t offset = 0, remain = icommit->logmsg_len;
1355 (*commit)->logmsg = malloc(icommit->logmsg_len + 1);
1356 if ((*commit)->logmsg == NULL) {
1357 err = got_error_from_errno("malloc");
1360 while (remain > 0) {
1361 struct imsg imsg_log;
1362 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE,
1365 err = got_privsep_recv_imsg(&imsg_log, ibuf, n);
1369 if (imsg_log.hdr.type != GOT_IMSG_COMMIT_LOGMSG) {
1370 err = got_error(GOT_ERR_PRIVSEP_MSG);
1374 memcpy((*commit)->logmsg + offset,
1376 imsg_free(&imsg_log);
1380 (*commit)->logmsg[icommit->logmsg_len] = '\0';
1383 for (i = 0; i < icommit->nparents; i++) {
1384 struct got_object_qid *qid;
1386 err = got_object_qid_alloc_partial(&qid);
1389 memcpy(&qid->id, imsg->data + len +
1390 i * sizeof(qid->id), sizeof(qid->id));
1391 STAILQ_INSERT_TAIL(&(*commit)->parent_ids, qid, entry);
1392 (*commit)->nparents++;
1396 got_object_commit_close(*commit);
1402 const struct got_error *
1403 got_privsep_recv_commit(struct got_commit_object **commit, struct imsgbuf *ibuf)
1405 const struct got_error *err = NULL;
1408 const size_t min_datalen =
1409 MIN(sizeof(struct got_imsg_error),
1410 sizeof(struct got_imsg_commit_object));
1414 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1418 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1420 switch (imsg.hdr.type) {
1421 case GOT_IMSG_COMMIT:
1422 err = get_commit_from_imsg(commit, &imsg, datalen, ibuf);
1425 err = got_error(GOT_ERR_PRIVSEP_MSG);
1434 static const struct got_error *
1435 send_tree_entries_batch(struct imsgbuf *ibuf,
1436 struct got_parsed_tree_entry *entries, int idx0, int idxN, size_t len)
1439 struct got_imsg_tree_entries ientries;
1442 memset(&ientries, 0, sizeof(ientries));
1444 wbuf = imsg_create(ibuf, GOT_IMSG_TREE_ENTRIES, 0, 0, len);
1446 return got_error_from_errno("imsg_create TREE_ENTRY");
1448 ientries.nentries = idxN - idx0 + 1;
1449 if (imsg_add(wbuf, &ientries, sizeof(ientries)) == -1)
1450 return got_error_from_errno("imsg_add TREE_ENTRY");
1452 for (i = idx0; i <= idxN; i++) {
1453 struct got_parsed_tree_entry *pte = &entries[i];
1455 /* Keep in sync with struct got_imsg_tree_entry definition! */
1456 if (imsg_add(wbuf, pte->id, SHA1_DIGEST_LENGTH) == -1)
1457 return got_error_from_errno("imsg_add TREE_ENTRY");
1458 if (imsg_add(wbuf, &pte->mode, sizeof(pte->mode)) == -1)
1459 return got_error_from_errno("imsg_add TREE_ENTRY");
1460 if (imsg_add(wbuf, &pte->namelen, sizeof(pte->namelen)) == -1)
1461 return got_error_from_errno("imsg_add TREE_ENTRY");
1463 /* Remaining bytes are the entry's name. */
1464 if (imsg_add(wbuf, pte->name, pte->namelen) == -1)
1465 return got_error_from_errno("imsg_add TREE_ENTRY");
1468 imsg_close(ibuf, wbuf);
1472 static const struct got_error *
1473 send_tree_entries(struct imsgbuf *ibuf, struct got_parsed_tree_entry *entries,
1476 const struct got_error *err = NULL;
1478 size_t entries_len = sizeof(struct got_imsg_tree_entries);
1481 for (j = 0; j < nentries; j++) {
1482 struct got_parsed_tree_entry *pte = &entries[j];
1483 size_t len = sizeof(struct got_imsg_tree_entry) + pte->namelen;
1486 entries_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
1487 err = send_tree_entries_batch(ibuf, entries,
1488 i, j - 1, entries_len);
1492 entries_len = sizeof(struct got_imsg_tree_entries);
1499 err = send_tree_entries_batch(ibuf, entries, i, j - 1,
1508 const struct got_error *
1509 got_privsep_send_tree(struct imsgbuf *ibuf,
1510 struct got_parsed_tree_entry *entries, int nentries)
1512 const struct got_error *err = NULL;
1513 struct got_imsg_tree_object itree;
1515 memset(&itree, 0, sizeof(itree));
1516 itree.nentries = nentries;
1517 if (imsg_compose(ibuf, GOT_IMSG_TREE, 0, 0, -1, &itree, sizeof(itree))
1519 return got_error_from_errno("imsg_compose TREE");
1521 err = send_tree_entries(ibuf, entries, nentries);
1525 return flush_imsg(ibuf);
1529 static const struct got_error *
1530 recv_tree_entries(void *data, size_t datalen, struct got_tree_object *tree,
1533 const struct got_error *err = NULL;
1534 struct got_imsg_tree_entries *ientries;
1535 struct got_tree_entry *te;
1539 if (datalen <= sizeof(*ientries) ||
1540 datalen > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
1541 return got_error(GOT_ERR_PRIVSEP_LEN);
1543 ientries = (struct got_imsg_tree_entries *)data;
1544 if (ientries->nentries > INT_MAX) {
1545 return got_error_msg(GOT_ERR_NO_SPACE,
1546 "too many tree entries");
1549 te_offset = sizeof(*ientries);
1550 for (i = 0; i < ientries->nentries; i++) {
1551 struct got_imsg_tree_entry ite;
1552 const char *te_name;
1553 uint8_t *buf = (uint8_t *)data + te_offset;
1555 if (te_offset >= datalen) {
1556 err = got_error(GOT_ERR_PRIVSEP_LEN);
1560 /* Might not be aligned, size is ~32 bytes. */
1561 memcpy(&ite, buf, sizeof(ite));
1563 if (ite.namelen >= sizeof(te->name)) {
1564 err = got_error(GOT_ERR_PRIVSEP_LEN);
1567 if (te_offset + sizeof(ite) + ite.namelen > datalen) {
1568 err = got_error(GOT_ERR_PRIVSEP_LEN);
1572 if (*nentries >= tree->nentries) {
1573 err = got_error(GOT_ERR_PRIVSEP_LEN);
1576 te = &tree->entries[*nentries];
1577 te_name = buf + sizeof(ite);
1578 memcpy(te->name, te_name, ite.namelen);
1579 te->name[ite.namelen] = '\0';
1580 memcpy(te->id.sha1, ite.id, SHA1_DIGEST_LENGTH);
1581 te->mode = ite.mode;
1582 te->idx = *nentries;
1585 te_offset += sizeof(ite) + ite.namelen;
1591 const struct got_error *
1592 got_privsep_recv_tree(struct got_tree_object **tree, struct imsgbuf *ibuf)
1594 const struct got_error *err = NULL;
1595 const size_t min_datalen =
1596 MIN(sizeof(struct got_imsg_error),
1597 sizeof(struct got_imsg_tree_object));
1598 struct got_imsg_tree_object *itree;
1603 while (*tree == NULL || nentries < (*tree)->nentries) {
1607 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1611 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1613 switch (imsg.hdr.type) {
1615 /* This message should only appear once. */
1616 if (*tree != NULL) {
1617 err = got_error(GOT_ERR_PRIVSEP_MSG);
1620 if (datalen != sizeof(*itree)) {
1621 err = got_error(GOT_ERR_PRIVSEP_LEN);
1625 if (itree->nentries < 0) {
1626 err = got_error(GOT_ERR_PRIVSEP_LEN);
1629 *tree = malloc(sizeof(**tree));
1630 if (*tree == NULL) {
1631 err = got_error_from_errno("malloc");
1634 (*tree)->entries = calloc(itree->nentries,
1635 sizeof(struct got_tree_entry));
1636 if ((*tree)->entries == NULL) {
1637 err = got_error_from_errno("malloc");
1642 (*tree)->nentries = itree->nentries;
1643 (*tree)->refcnt = 0;
1645 case GOT_IMSG_TREE_ENTRIES:
1646 /* This message should be preceeded by GOT_IMSG_TREE. */
1647 if (*tree == NULL) {
1648 err = got_error(GOT_ERR_PRIVSEP_MSG);
1651 err = recv_tree_entries(imsg.data, datalen,
1655 err = got_error(GOT_ERR_PRIVSEP_MSG);
1664 if (*tree && (*tree)->nentries != nentries) {
1666 err = got_error(GOT_ERR_PRIVSEP_LEN);
1667 got_object_tree_close(*tree);
1674 const struct got_error *
1675 got_privsep_send_blob(struct imsgbuf *ibuf, size_t size, size_t hdrlen,
1676 const uint8_t *data)
1678 struct got_imsg_blob iblob;
1680 memset(&iblob, 0, sizeof(iblob));
1682 iblob.hdrlen = hdrlen;
1687 if (size > GOT_PRIVSEP_INLINE_BLOB_DATA_MAX)
1688 return got_error(GOT_ERR_NO_SPACE);
1690 buf = malloc(sizeof(iblob) + size);
1692 return got_error_from_errno("malloc");
1694 memcpy(buf, &iblob, sizeof(iblob));
1695 memcpy(buf + sizeof(iblob), data, size);
1696 if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, buf,
1697 sizeof(iblob) + size) == -1) {
1699 return got_error_from_errno("imsg_compose BLOB");
1703 /* Data has already been written to file descriptor. */
1704 if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, &iblob,
1705 sizeof(iblob)) == -1)
1706 return got_error_from_errno("imsg_compose BLOB");
1710 return flush_imsg(ibuf);
1713 const struct got_error *
1714 got_privsep_recv_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen,
1715 struct imsgbuf *ibuf)
1717 const struct got_error *err = NULL;
1719 struct got_imsg_blob *iblob;
1724 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
1728 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1730 switch (imsg.hdr.type) {
1732 if (datalen < sizeof(*iblob)) {
1733 err = got_error(GOT_ERR_PRIVSEP_LEN);
1737 *size = iblob->size;
1738 *hdrlen = iblob->hdrlen;
1740 if (datalen == sizeof(*iblob)) {
1741 /* Data has been written to file descriptor. */
1745 if (*size > GOT_PRIVSEP_INLINE_BLOB_DATA_MAX ||
1746 *size > datalen + sizeof(*iblob)) {
1747 err = got_error(GOT_ERR_PRIVSEP_LEN);
1751 *outbuf = malloc(*size);
1752 if (*outbuf == NULL) {
1753 err = got_error_from_errno("malloc");
1756 memcpy(*outbuf, imsg.data + sizeof(*iblob), *size);
1759 err = got_error(GOT_ERR_PRIVSEP_MSG);
1768 static const struct got_error *
1769 send_tagmsg(struct imsgbuf *ibuf, struct got_tag_object *tag, size_t tagmsg_len)
1771 const struct got_error *err = NULL;
1772 size_t offset, remain;
1775 remain = tagmsg_len;
1776 while (remain > 0) {
1777 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
1779 if (imsg_compose(ibuf, GOT_IMSG_TAG_TAGMSG, 0, 0, -1,
1780 tag->tagmsg + offset, n) == -1) {
1781 err = got_error_from_errno("imsg_compose TAG_TAGMSG");
1785 err = flush_imsg(ibuf);
1796 const struct got_error *
1797 got_privsep_send_tag(struct imsgbuf *ibuf, struct got_tag_object *tag)
1799 const struct got_error *err = NULL;
1800 struct got_imsg_tag_object *itag;
1803 size_t tag_len = strlen(tag->tag);
1804 size_t tagger_len = strlen(tag->tagger);
1805 size_t tagmsg_len = strlen(tag->tagmsg);
1807 total = sizeof(*itag) + tag_len + tagger_len + tagmsg_len;
1809 buf = malloc(total);
1811 return got_error_from_errno("malloc");
1813 itag = (struct got_imsg_tag_object *)buf;
1814 memcpy(&itag->id, &tag->id, sizeof(itag->id));
1815 itag->obj_type = tag->obj_type;
1816 itag->tag_len = tag_len;
1817 itag->tagger_len = tagger_len;
1818 itag->tagger_time = tag->tagger_time;
1819 itag->tagger_gmtoff = tag->tagger_gmtoff;
1820 itag->tagmsg_len = tagmsg_len;
1822 len = sizeof(*itag);
1823 memcpy(buf + len, tag->tag, tag_len);
1825 memcpy(buf + len, tag->tagger, tagger_len);
1828 if (imsg_compose(ibuf, GOT_IMSG_TAG, 0, 0, -1, buf, len) == -1) {
1829 err = got_error_from_errno("imsg_compose TAG");
1833 if (tagmsg_len == 0 ||
1834 tagmsg_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
1835 err = flush_imsg(ibuf);
1839 err = send_tagmsg(ibuf, tag, tagmsg_len);
1845 const struct got_error *
1846 got_privsep_recv_tag(struct got_tag_object **tag, struct imsgbuf *ibuf)
1848 const struct got_error *err = NULL;
1850 struct got_imsg_tag_object *itag;
1851 size_t len, datalen;
1852 const size_t min_datalen =
1853 MIN(sizeof(struct got_imsg_error),
1854 sizeof(struct got_imsg_tag_object));
1858 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
1862 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1865 switch (imsg.hdr.type) {
1867 if (datalen < sizeof(*itag)) {
1868 err = got_error(GOT_ERR_PRIVSEP_LEN);
1872 if (datalen != sizeof(*itag) + itag->tag_len +
1874 err = got_error(GOT_ERR_PRIVSEP_LEN);
1877 len += sizeof(*itag);
1879 *tag = calloc(1, sizeof(**tag));
1881 err = got_error_from_errno("calloc");
1885 memcpy(&(*tag)->id, &itag->id, sizeof(itag->id));
1887 (*tag)->tag = strndup(imsg.data + len, itag->tag_len);
1888 if ((*tag)->tag == NULL) {
1889 err = got_error_from_errno("strndup");
1892 len += itag->tag_len;
1894 (*tag)->obj_type = itag->obj_type;
1895 (*tag)->tagger_time = itag->tagger_time;
1896 (*tag)->tagger_gmtoff = itag->tagger_gmtoff;
1898 (*tag)->tagger = strndup(imsg.data + len, itag->tagger_len);
1899 if ((*tag)->tagger == NULL) {
1900 err = got_error_from_errno("strndup");
1903 len += itag->tagger_len;
1905 if (itag->tagmsg_len == 0) {
1906 (*tag)->tagmsg = strdup("");
1907 if ((*tag)->tagmsg == NULL) {
1908 err = got_error_from_errno("strdup");
1912 size_t offset = 0, remain = itag->tagmsg_len;
1914 (*tag)->tagmsg = malloc(itag->tagmsg_len + 1);
1915 if ((*tag)->tagmsg == NULL) {
1916 err = got_error_from_errno("malloc");
1919 while (remain > 0) {
1920 struct imsg imsg_log;
1921 size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE,
1924 err = got_privsep_recv_imsg(&imsg_log, ibuf, n);
1928 if (imsg_log.hdr.type != GOT_IMSG_TAG_TAGMSG)
1929 return got_error(GOT_ERR_PRIVSEP_MSG);
1931 memcpy((*tag)->tagmsg + offset, imsg_log.data,
1933 imsg_free(&imsg_log);
1937 (*tag)->tagmsg[itag->tagmsg_len] = '\0';
1942 err = got_error(GOT_ERR_PRIVSEP_MSG);
1951 const struct got_error *
1952 got_privsep_init_pack_child(struct imsgbuf *ibuf, struct got_pack *pack,
1953 struct got_packidx *packidx)
1955 const struct got_error *err = NULL;
1956 struct got_imsg_packidx ipackidx;
1957 struct got_imsg_pack ipack;
1960 memset(&ipackidx, 0, sizeof(ipackidx));
1961 memset(&ipack, 0, sizeof(ipack));
1963 ipackidx.len = packidx->len;
1964 ipackidx.packfile_size = pack->filesize;
1965 fd = dup(packidx->fd);
1967 return got_error_from_errno("dup");
1969 if (imsg_compose(ibuf, GOT_IMSG_PACKIDX, 0, 0, fd, &ipackidx,
1970 sizeof(ipackidx)) == -1) {
1971 err = got_error_from_errno("imsg_compose PACKIDX");
1976 if (strlcpy(ipack.path_packfile, pack->path_packfile,
1977 sizeof(ipack.path_packfile)) >= sizeof(ipack.path_packfile))
1978 return got_error(GOT_ERR_NO_SPACE);
1979 ipack.filesize = pack->filesize;
1983 return got_error_from_errno("dup");
1985 if (imsg_compose(ibuf, GOT_IMSG_PACK, 0, 0, fd, &ipack, sizeof(ipack))
1987 err = got_error_from_errno("imsg_compose PACK");
1992 return flush_imsg(ibuf);
1995 const struct got_error *
1996 got_privsep_send_packed_obj_req(struct imsgbuf *ibuf, int idx,
1997 struct got_object_id *id)
1999 struct got_imsg_packed_object iobj;
2001 memset(&iobj, 0, sizeof(iobj));
2003 memcpy(&iobj.id, id, sizeof(iobj.id));
2005 if (imsg_compose(ibuf, GOT_IMSG_PACKED_OBJECT_REQUEST, 0, 0, -1,
2006 &iobj, sizeof(iobj)) == -1)
2007 return got_error_from_errno("imsg_compose "
2008 "PACKED_OBJECT_REQUEST");
2010 return flush_imsg(ibuf);
2013 const struct got_error *
2014 got_privsep_send_packed_raw_obj_req(struct imsgbuf *ibuf, int idx,
2015 struct got_object_id *id)
2017 struct got_imsg_packed_object iobj;
2019 memset(&iobj, 0, sizeof(iobj));
2021 memcpy(&iobj.id, id, sizeof(iobj.id));
2023 if (imsg_compose(ibuf, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST, 0, 0, -1,
2024 &iobj, sizeof(iobj)) == -1)
2025 return got_error_from_errno("imsg_compose "
2026 "PACKED_OBJECT_REQUEST");
2028 return flush_imsg(ibuf);
2031 const struct got_error *
2032 got_privsep_send_gitconfig_parse_req(struct imsgbuf *ibuf, int fd)
2034 const struct got_error *err = NULL;
2036 if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_PARSE_REQUEST, 0, 0, fd,
2038 err = got_error_from_errno("imsg_compose "
2039 "GITCONFIG_PARSE_REQUEST");
2044 return flush_imsg(ibuf);
2047 const struct got_error *
2048 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf *ibuf)
2050 if (imsg_compose(ibuf,
2051 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST, 0, 0, -1,
2053 return got_error_from_errno("imsg_compose "
2054 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2056 return flush_imsg(ibuf);
2059 const struct got_error *
2060 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf *ibuf)
2062 if (imsg_compose(ibuf,
2063 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST, 0, 0, -1,
2065 return got_error_from_errno("imsg_compose "
2066 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2068 return flush_imsg(ibuf);
2072 const struct got_error *
2073 got_privsep_send_gitconfig_author_name_req(struct imsgbuf *ibuf)
2075 if (imsg_compose(ibuf,
2076 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST, 0, 0, -1, NULL, 0) == -1)
2077 return got_error_from_errno("imsg_compose "
2078 "GITCONFIG_AUTHOR_NAME_REQUEST");
2080 return flush_imsg(ibuf);
2083 const struct got_error *
2084 got_privsep_send_gitconfig_author_email_req(struct imsgbuf *ibuf)
2086 if (imsg_compose(ibuf,
2087 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST, 0, 0, -1, NULL, 0) == -1)
2088 return got_error_from_errno("imsg_compose "
2089 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2091 return flush_imsg(ibuf);
2094 const struct got_error *
2095 got_privsep_send_gitconfig_remotes_req(struct imsgbuf *ibuf)
2097 if (imsg_compose(ibuf,
2098 GOT_IMSG_GITCONFIG_REMOTES_REQUEST, 0, 0, -1, NULL, 0) == -1)
2099 return got_error_from_errno("imsg_compose "
2100 "GITCONFIG_REMOTE_REQUEST");
2102 return flush_imsg(ibuf);
2105 const struct got_error *
2106 got_privsep_send_gitconfig_owner_req(struct imsgbuf *ibuf)
2108 if (imsg_compose(ibuf,
2109 GOT_IMSG_GITCONFIG_OWNER_REQUEST, 0, 0, -1, NULL, 0) == -1)
2110 return got_error_from_errno("imsg_compose "
2111 "GITCONFIG_OWNER_REQUEST");
2113 return flush_imsg(ibuf);
2116 const struct got_error *
2117 got_privsep_recv_gitconfig_str(char **str, struct imsgbuf *ibuf)
2119 const struct got_error *err = NULL;
2125 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2128 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2130 switch (imsg.hdr.type) {
2131 case GOT_IMSG_GITCONFIG_STR_VAL:
2134 *str = strndup(imsg.data, datalen);
2136 err = got_error_from_errno("strndup");
2141 err = got_error(GOT_ERR_PRIVSEP_MSG);
2149 const struct got_error *
2150 got_privsep_recv_gitconfig_pair(char **key, char **val, struct imsgbuf *ibuf)
2152 const struct got_error *err = NULL;
2153 struct got_imsg_gitconfig_pair p;
2160 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2165 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2167 if (imsg.hdr.type != GOT_IMSG_GITCONFIG_PAIR) {
2168 err = got_error(GOT_ERR_PRIVSEP_MSG);
2172 if (datalen < sizeof(p)) {
2173 err = got_error(GOT_ERR_PRIVSEP_LEN);
2177 memcpy(&p, data, sizeof(p));
2180 if (datalen != sizeof(p) + p.klen + p.vlen) {
2181 err = got_error(GOT_ERR_PRIVSEP_LEN);
2185 *key = strndup(data, p.klen);
2187 err = got_error_from_errno("strndup");
2192 *val = strndup(data, p.vlen);
2194 err = got_error_from_errno("strndup");
2203 const struct got_error *
2204 got_privsep_recv_gitconfig_int(int *val, struct imsgbuf *ibuf)
2206 const struct got_error *err = NULL;
2209 const size_t min_datalen =
2210 MIN(sizeof(struct got_imsg_error), sizeof(int));
2214 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
2217 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2219 switch (imsg.hdr.type) {
2220 case GOT_IMSG_GITCONFIG_INT_VAL:
2221 if (datalen != sizeof(*val)) {
2222 err = got_error(GOT_ERR_PRIVSEP_LEN);
2225 memcpy(val, imsg.data, sizeof(*val));
2228 err = got_error(GOT_ERR_PRIVSEP_MSG);
2237 free_remote_data(struct got_remote_repo *remote)
2242 free(remote->fetch_url);
2243 free(remote->send_url);
2244 for (i = 0; i < remote->nfetch_branches; i++)
2245 free(remote->fetch_branches[i]);
2246 free(remote->fetch_branches);
2247 for (i = 0; i < remote->nsend_branches; i++)
2248 free(remote->send_branches[i]);
2249 free(remote->send_branches);
2250 for (i = 0; i < remote->nfetch_refs; i++)
2251 free(remote->fetch_refs[i]);
2252 free(remote->fetch_refs);
2255 const struct got_error *
2256 got_privsep_recv_gitconfig_remotes(struct got_remote_repo **remotes,
2257 int *nremotes, struct imsgbuf *ibuf)
2259 const struct got_error *err = NULL;
2262 struct got_imsg_remotes iremotes;
2263 struct got_imsg_remote iremote;
2267 iremotes.nremotes = 0;
2269 err = got_privsep_recv_imsg(&imsg, ibuf, sizeof(iremotes));
2272 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2274 switch (imsg.hdr.type) {
2275 case GOT_IMSG_GITCONFIG_REMOTES:
2276 if (datalen != sizeof(iremotes)) {
2278 return got_error(GOT_ERR_PRIVSEP_LEN);
2280 memcpy(&iremotes, imsg.data, sizeof(iremotes));
2281 if (iremotes.nremotes == 0) {
2288 return got_error(GOT_ERR_PRIVSEP_MSG);
2293 *remotes = recallocarray(NULL, 0, iremotes.nremotes, sizeof(**remotes));
2294 if (*remotes == NULL)
2295 return got_error_from_errno("recallocarray");
2297 while (*nremotes < iremotes.nremotes) {
2298 struct got_remote_repo *remote;
2300 err = got_privsep_recv_imsg(&imsg, ibuf, sizeof(iremote));
2303 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2305 switch (imsg.hdr.type) {
2306 case GOT_IMSG_GITCONFIG_REMOTE:
2307 remote = &(*remotes)[*nremotes];
2308 memset(remote, 0, sizeof(*remote));
2309 if (datalen < sizeof(iremote)) {
2310 err = got_error(GOT_ERR_PRIVSEP_LEN);
2313 memcpy(&iremote, imsg.data, sizeof(iremote));
2314 if (iremote.name_len == 0 ||
2315 iremote.fetch_url_len == 0 ||
2316 iremote.send_url_len == 0 ||
2317 (sizeof(iremote) + iremote.name_len +
2318 iremote.fetch_url_len + iremote.send_url_len) > datalen) {
2319 err = got_error(GOT_ERR_PRIVSEP_LEN);
2322 remote->name = strndup(imsg.data + sizeof(iremote),
2324 if (remote->name == NULL) {
2325 err = got_error_from_errno("strndup");
2328 remote->fetch_url = strndup(imsg.data + sizeof(iremote) +
2329 iremote.name_len, iremote.fetch_url_len);
2330 if (remote->fetch_url == NULL) {
2331 err = got_error_from_errno("strndup");
2332 free_remote_data(remote);
2335 remote->send_url = strndup(imsg.data + sizeof(iremote) +
2336 iremote.name_len + iremote.fetch_url_len,
2337 iremote.send_url_len);
2338 if (remote->send_url == NULL) {
2339 err = got_error_from_errno("strndup");
2340 free_remote_data(remote);
2343 remote->mirror_references = iremote.mirror_references;
2344 remote->fetch_all_branches = iremote.fetch_all_branches;
2345 remote->nfetch_branches = 0;
2346 remote->fetch_branches = NULL;
2347 remote->nsend_branches = 0;
2348 remote->send_branches = NULL;
2349 remote->nfetch_refs = 0;
2350 remote->fetch_refs = NULL;
2354 err = got_error(GOT_ERR_PRIVSEP_MSG);
2365 for (i = 0; i < *nremotes; i++)
2366 free_remote_data(&(*remotes)[i]);
2374 const struct got_error *
2375 got_privsep_send_gotconfig_parse_req(struct imsgbuf *ibuf, int fd)
2377 const struct got_error *err = NULL;
2379 if (imsg_compose(ibuf, GOT_IMSG_GOTCONFIG_PARSE_REQUEST, 0, 0, fd,
2381 err = got_error_from_errno("imsg_compose "
2382 "GOTCONFIG_PARSE_REQUEST");
2387 return flush_imsg(ibuf);
2390 const struct got_error *
2391 got_privsep_send_gotconfig_author_req(struct imsgbuf *ibuf)
2393 if (imsg_compose(ibuf,
2394 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST, 0, 0, -1, NULL, 0) == -1)
2395 return got_error_from_errno("imsg_compose "
2396 "GOTCONFIG_AUTHOR_REQUEST");
2398 return flush_imsg(ibuf);
2401 const struct got_error *
2402 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf *ibuf)
2404 if (imsg_compose(ibuf,
2405 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST, 0, 0, -1, NULL, 0) == -1)
2406 return got_error_from_errno("imsg_compose "
2407 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2409 return flush_imsg(ibuf);
2412 const struct got_error *
2413 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf *ibuf)
2415 if (imsg_compose(ibuf,
2416 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST, 0, 0, -1, NULL, 0) == -1)
2417 return got_error_from_errno("imsg_compose "
2418 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2420 return flush_imsg(ibuf);
2423 const struct got_error *
2424 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf *ibuf)
2426 if (imsg_compose(ibuf,
2427 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST, 0, 0, -1, NULL, 0) == -1)
2428 return got_error_from_errno("imsg_compose "
2429 "GOTCONFIG_SIGNERID_REQUEST");
2431 return flush_imsg(ibuf);
2434 const struct got_error *
2435 got_privsep_send_gotconfig_remotes_req(struct imsgbuf *ibuf)
2437 if (imsg_compose(ibuf,
2438 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST, 0, 0, -1, NULL, 0) == -1)
2439 return got_error_from_errno("imsg_compose "
2440 "GOTCONFIG_REMOTE_REQUEST");
2442 return flush_imsg(ibuf);
2445 const struct got_error *
2446 got_privsep_recv_gotconfig_str(char **str, struct imsgbuf *ibuf)
2448 const struct got_error *err = NULL;
2454 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2457 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2459 switch (imsg.hdr.type) {
2460 case GOT_IMSG_GOTCONFIG_STR_VAL:
2463 *str = strndup(imsg.data, datalen);
2465 err = got_error_from_errno("strndup");
2470 err = got_error(GOT_ERR_PRIVSEP_MSG);
2478 const struct got_error *
2479 got_privsep_recv_gotconfig_remotes(struct got_remote_repo **remotes,
2480 int *nremotes, struct imsgbuf *ibuf)
2482 const struct got_error *err = NULL;
2485 struct got_imsg_remotes iremotes;
2486 struct got_imsg_remote iremote;
2487 const size_t min_datalen =
2488 MIN(sizeof(struct got_imsg_error), sizeof(iremotes));
2492 iremotes.nremotes = 0;
2494 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
2497 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2499 switch (imsg.hdr.type) {
2500 case GOT_IMSG_GOTCONFIG_REMOTES:
2501 if (datalen != sizeof(iremotes)) {
2502 err = got_error(GOT_ERR_PRIVSEP_LEN);
2505 memcpy(&iremotes, imsg.data, sizeof(iremotes));
2506 if (iremotes.nremotes < 0) {
2507 err = got_error(GOT_ERR_PRIVSEP_LEN);
2510 if (iremotes.nremotes == 0) {
2517 return got_error(GOT_ERR_PRIVSEP_MSG);
2522 *remotes = recallocarray(NULL, 0, iremotes.nremotes, sizeof(**remotes));
2523 if (*remotes == NULL)
2524 return got_error_from_errno("recallocarray");
2526 while (*nremotes < iremotes.nremotes) {
2527 struct got_remote_repo *remote;
2528 const size_t min_datalen =
2529 MIN(sizeof(struct got_imsg_error), sizeof(iremote));
2532 err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
2535 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2537 switch (imsg.hdr.type) {
2538 case GOT_IMSG_GOTCONFIG_REMOTE:
2539 remote = &(*remotes)[*nremotes];
2540 memset(remote, 0, sizeof(*remote));
2541 if (datalen < sizeof(iremote)) {
2542 err = got_error(GOT_ERR_PRIVSEP_LEN);
2545 memcpy(&iremote, imsg.data, sizeof(iremote));
2546 if (iremote.name_len == 0 ||
2547 (iremote.fetch_url_len == 0 &&
2548 iremote.send_url_len == 0) ||
2549 (sizeof(iremote) + iremote.name_len +
2550 iremote.fetch_url_len + iremote.send_url_len) >
2552 err = got_error(GOT_ERR_PRIVSEP_LEN);
2555 remote->name = strndup(imsg.data + sizeof(iremote),
2557 if (remote->name == NULL) {
2558 err = got_error_from_errno("strndup");
2561 remote->fetch_url = strndup(imsg.data +
2562 sizeof(iremote) + iremote.name_len,
2563 iremote.fetch_url_len);
2564 if (remote->fetch_url == NULL) {
2565 err = got_error_from_errno("strndup");
2566 free_remote_data(remote);
2569 remote->send_url = strndup(imsg.data +
2570 sizeof(iremote) + iremote.name_len +
2571 iremote.fetch_url_len, iremote.send_url_len);
2572 if (remote->send_url == NULL) {
2573 err = got_error_from_errno("strndup");
2574 free_remote_data(remote);
2577 remote->mirror_references = iremote.mirror_references;
2578 remote->fetch_all_branches = iremote.fetch_all_branches;
2579 if (iremote.nfetch_branches > 0) {
2580 remote->fetch_branches = recallocarray(NULL, 0,
2581 iremote.nfetch_branches, sizeof(char *));
2582 if (remote->fetch_branches == NULL) {
2583 err = got_error_from_errno("calloc");
2584 free_remote_data(remote);
2588 remote->nfetch_branches = 0;
2589 for (i = 0; i < iremote.nfetch_branches; i++) {
2591 err = got_privsep_recv_gotconfig_str(&branch,
2594 free_remote_data(remote);
2597 remote->fetch_branches[i] = branch;
2598 remote->nfetch_branches++;
2600 if (iremote.nsend_branches > 0) {
2601 remote->send_branches = recallocarray(NULL, 0,
2602 iremote.nsend_branches, sizeof(char *));
2603 if (remote->send_branches == NULL) {
2604 err = got_error_from_errno("calloc");
2605 free_remote_data(remote);
2609 remote->nsend_branches = 0;
2610 for (i = 0; i < iremote.nsend_branches; i++) {
2612 err = got_privsep_recv_gotconfig_str(&branch,
2615 free_remote_data(remote);
2618 remote->send_branches[i] = branch;
2619 remote->nsend_branches++;
2621 if (iremote.nfetch_refs > 0) {
2622 remote->fetch_refs = recallocarray(NULL, 0,
2623 iremote.nfetch_refs, sizeof(char *));
2624 if (remote->fetch_refs == NULL) {
2625 err = got_error_from_errno("calloc");
2626 free_remote_data(remote);
2630 remote->nfetch_refs = 0;
2631 for (i = 0; i < iremote.nfetch_refs; i++) {
2633 err = got_privsep_recv_gotconfig_str(&ref,
2636 free_remote_data(remote);
2639 remote->fetch_refs[i] = ref;
2640 remote->nfetch_refs++;
2645 err = got_error(GOT_ERR_PRIVSEP_MSG);
2656 for (i = 0; i < *nremotes; i++)
2657 free_remote_data(&(*remotes)[i]);
2665 const struct got_error *
2666 got_privsep_send_commit_traversal_request(struct imsgbuf *ibuf,
2667 struct got_object_id *id, int idx, const char *path)
2670 size_t path_len = strlen(path);
2672 wbuf = imsg_create(ibuf, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST, 0, 0,
2673 sizeof(struct got_imsg_commit_traversal_request) + path_len);
2675 return got_error_from_errno(
2676 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2678 * Keep in sync with struct got_imsg_commit_traversal_request
2679 * and struct got_imsg_packed_object.
2681 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
2682 return got_error_from_errno("imsg_add "
2683 "COMMIT_TRAVERSAL_REQUEST");
2684 if (imsg_add(wbuf, &idx, sizeof(idx)) == -1)
2685 return got_error_from_errno("imsg_add "
2686 "COMMIT_TRAVERSAL_REQUEST");
2687 if (imsg_add(wbuf, &path_len, sizeof(path_len)) == -1)
2688 return got_error_from_errno("imsg_add "
2689 "COMMIT_TRAVERSAL_REQUEST");
2690 if (imsg_add(wbuf, path, path_len) == -1)
2691 return got_error_from_errno("imsg_add "
2692 "COMMIT_TRAVERSAL_REQUEST");
2694 imsg_close(ibuf, wbuf);
2695 return flush_imsg(ibuf);
2698 const struct got_error *
2699 got_privsep_recv_traversed_commits(struct got_commit_object **changed_commit,
2700 struct got_object_id **changed_commit_id,
2701 struct got_object_id_queue *commit_ids, struct imsgbuf *ibuf)
2703 const struct got_error *err = NULL;
2705 struct got_imsg_traversed_commits *icommits;
2706 struct got_object_id *ids;
2710 *changed_commit = NULL;
2711 *changed_commit_id = NULL;
2714 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2718 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2719 switch (imsg.hdr.type) {
2720 case GOT_IMSG_TRAVERSED_COMMITS:
2721 icommits = imsg.data;
2722 if (datalen != sizeof(*icommits) +
2723 icommits->ncommits * sizeof(*ids)) {
2724 err = got_error(GOT_ERR_PRIVSEP_LEN);
2727 ids = imsg.data + sizeof(*icommits);
2728 for (i = 0; i < icommits->ncommits; i++) {
2729 struct got_object_qid *qid;
2731 err = got_object_qid_alloc_partial(&qid);
2734 memcpy(&qid->id, &ids[i], sizeof(ids[i]));
2735 STAILQ_INSERT_TAIL(commit_ids, qid, entry);
2737 /* The last commit may contain a change. */
2738 if (i == icommits->ncommits - 1) {
2739 *changed_commit_id =
2740 got_object_id_dup(&qid->id);
2741 if (*changed_commit_id == NULL) {
2742 err = got_error_from_errno(
2743 "got_object_id_dup");
2749 case GOT_IMSG_COMMIT:
2750 if (*changed_commit_id == NULL) {
2751 err = got_error(GOT_ERR_PRIVSEP_MSG);
2754 err = get_commit_from_imsg(changed_commit, &imsg,
2757 case GOT_IMSG_COMMIT_TRAVERSAL_DONE:
2761 err = got_error(GOT_ERR_PRIVSEP_MSG);
2771 got_object_id_queue_free(commit_ids);
2775 const struct got_error *
2776 got_privsep_send_enumerated_tree(size_t *totlen, struct imsgbuf *ibuf,
2777 struct got_object_id *tree_id, const char *path,
2778 struct got_parsed_tree_entry *entries, int nentries)
2780 const struct got_error *err = NULL;
2782 size_t path_len = strlen(path);
2785 msglen = sizeof(struct got_imsg_enumerated_tree) + path_len;
2786 wbuf = imsg_create(ibuf, GOT_IMSG_ENUMERATED_TREE, 0, 0, msglen);
2788 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2790 if (imsg_add(wbuf, tree_id->sha1, SHA1_DIGEST_LENGTH) == -1)
2791 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2792 if (imsg_add(wbuf, &nentries, sizeof(nentries)) == -1)
2793 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2794 if (imsg_add(wbuf, path, path_len) == -1)
2795 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2797 imsg_close(ibuf, wbuf);
2800 err = send_tree_entries(ibuf, entries, nentries);
2805 return flush_imsg(ibuf);
2808 const struct got_error *
2809 got_privsep_send_object_enumeration_request(struct imsgbuf *ibuf)
2811 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_ENUMERATION_REQUEST,
2812 0, 0, -1, NULL, 0) == -1)
2813 return got_error_from_errno("imsg_compose "
2814 "OBJECT_ENUMERATION_REQUEST");
2816 return flush_imsg(ibuf);
2819 const struct got_error *
2820 got_privsep_send_object_enumeration_done(struct imsgbuf *ibuf)
2822 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_ENUMERATION_DONE,
2823 0, 0, -1, NULL, 0) == -1)
2824 return got_error_from_errno("imsg_compose "
2825 "OBJECT_ENUMERATION_DONE");
2827 return flush_imsg(ibuf);
2830 const struct got_error *
2831 got_privsep_send_object_enumeration_incomplete(struct imsgbuf *ibuf)
2833 if (imsg_compose(ibuf, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE,
2834 0, 0, -1, NULL, 0) == -1)
2835 return got_error_from_errno("imsg_compose "
2836 "OBJECT_ENUMERATION_INCOMPLETE");
2838 return flush_imsg(ibuf);
2841 const struct got_error *
2842 got_privsep_send_enumerated_commit(struct imsgbuf *ibuf,
2843 struct got_object_id *id, time_t mtime)
2847 wbuf = imsg_create(ibuf, GOT_IMSG_ENUMERATED_COMMIT, 0, 0,
2848 sizeof(struct got_imsg_enumerated_commit) + SHA1_DIGEST_LENGTH);
2850 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2852 /* Keep in sync with struct got_imsg_enumerated_commit! */
2853 if (imsg_add(wbuf, id, SHA1_DIGEST_LENGTH) == -1)
2854 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2855 if (imsg_add(wbuf, &mtime, sizeof(mtime)) == -1)
2856 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2858 imsg_close(ibuf, wbuf);
2859 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2863 const struct got_error *
2864 got_privsep_recv_enumerated_objects(int *found_all_objects,
2865 struct imsgbuf *ibuf,
2866 got_object_enumerate_commit_cb cb_commit,
2867 got_object_enumerate_tree_cb cb_tree, void *cb_arg,
2868 struct got_repository *repo)
2870 const struct got_error *err = NULL;
2872 struct got_imsg_enumerated_commit *icommit = NULL;
2873 struct got_object_id commit_id;
2874 int have_commit = 0;
2876 struct got_tree_object tree;
2877 struct got_imsg_enumerated_tree *itree;
2878 struct got_object_id tree_id;
2879 char *path = NULL, *canon_path = NULL;
2880 size_t datalen, path_len;
2884 *found_all_objects = 0;
2885 memset(&tree, 0, sizeof(tree));
2888 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
2892 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
2893 switch (imsg.hdr.type) {
2894 case GOT_IMSG_ENUMERATED_COMMIT:
2895 if (have_commit && nentries != -1) {
2896 err = got_error(GOT_ERR_PRIVSEP_MSG);
2899 if (datalen != sizeof(*icommit)) {
2900 err = got_error(GOT_ERR_PRIVSEP_LEN);
2903 icommit = (struct got_imsg_enumerated_commit *)imsg.data;
2904 memcpy(commit_id.sha1, icommit->id, SHA1_DIGEST_LENGTH);
2905 mtime = icommit->mtime;
2908 case GOT_IMSG_ENUMERATED_TREE:
2909 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2911 err = got_error(GOT_ERR_PRIVSEP_MSG);
2914 if (datalen < sizeof(*itree)) {
2915 err = got_error(GOT_ERR_PRIVSEP_LEN);
2919 path_len = datalen - sizeof(*itree);
2920 if (path_len == 0) {
2921 err = got_error(GOT_ERR_PRIVSEP_LEN);
2924 memcpy(tree_id.sha1, itree->id, sizeof(tree_id.sha1));
2926 path = strndup(imsg.data + sizeof(*itree), path_len);
2928 err = got_error_from_errno("strndup");
2932 canon_path = malloc(path_len + 1);
2933 if (canon_path == NULL) {
2934 err = got_error_from_errno("malloc");
2937 if (!got_path_is_absolute(path)) {
2938 err = got_error(GOT_ERR_BAD_PATH);
2941 if (got_path_is_root_dir(path)) {
2942 /* XXX check what got_canonpath() does wrong */
2943 canon_path[0] = '/';
2944 canon_path[1] = '\0';
2946 err = got_canonpath(path, canon_path,
2951 if (strcmp(path, canon_path) != 0) {
2952 err = got_error(GOT_ERR_BAD_PATH);
2955 if (nentries != -1) {
2956 err = got_error(GOT_ERR_PRIVSEP_MSG);
2959 if (itree->nentries < -1) {
2960 err = got_error(GOT_ERR_PRIVSEP_MSG);
2963 if (itree->nentries == -1) {
2964 /* Tree was not found in pack file. */
2965 err = cb_tree(cb_arg, NULL, mtime, &tree_id,
2969 if (itree->nentries > INT_MAX) {
2970 err = got_error(GOT_ERR_PRIVSEP_LEN);
2973 tree.entries = calloc(itree->nentries,
2974 sizeof(struct got_tree_entry));
2975 if (tree.entries == NULL) {
2976 err = got_error_from_errno("calloc");
2979 if (itree->nentries == 0) {
2980 err = cb_tree(cb_arg, &tree, mtime, &tree_id,
2985 /* Prepare for next tree. */
2987 memset(&tree, 0, sizeof(tree));
2990 tree.nentries = itree->nentries;
2994 case GOT_IMSG_TREE_ENTRIES:
2995 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2996 if (nentries <= -1) {
2997 err = got_error(GOT_ERR_PRIVSEP_MSG);
3000 err = recv_tree_entries(imsg.data, datalen,
3004 if (tree.nentries == nentries) {
3005 err = cb_tree(cb_arg, &tree, mtime, &tree_id,
3010 /* Prepare for next tree. */
3012 memset(&tree, 0, sizeof(tree));
3016 case GOT_IMSG_TREE_ENUMERATION_DONE:
3017 /* All trees have been found and traversed. */
3018 if (!have_commit || path == NULL || nentries != -1) {
3019 err = got_error(GOT_ERR_PRIVSEP_MSG);
3022 err = cb_commit(cb_arg, mtime, &commit_id, repo);
3027 case GOT_IMSG_OBJECT_ENUMERATION_DONE:
3028 *found_all_objects = 1;
3031 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE:
3035 err = got_error(GOT_ERR_PRIVSEP_MSG);
3050 const struct got_error *
3051 got_privsep_send_raw_delta_req(struct imsgbuf *ibuf, int idx,
3052 struct got_object_id *id)
3054 struct got_imsg_raw_delta_request dreq;
3056 memset(&dreq, 0, sizeof(dreq));
3058 memcpy(&dreq.id, id, sizeof(dreq.id));
3060 if (imsg_compose(ibuf, GOT_IMSG_RAW_DELTA_REQUEST, 0, 0, -1,
3061 &dreq, sizeof(dreq)) == -1)
3062 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
3064 return flush_imsg(ibuf);
3067 const struct got_error *
3068 got_privsep_send_raw_delta_outfd(struct imsgbuf *ibuf, int fd)
3070 return send_fd(ibuf, GOT_IMSG_RAW_DELTA_OUTFD, fd);
3073 const struct got_error *
3074 got_privsep_send_raw_delta(struct imsgbuf *ibuf, uint64_t base_size,
3075 uint64_t result_size, off_t delta_size, off_t delta_compressed_size,
3076 off_t delta_offset, off_t delta_out_offset, struct got_object_id *base_id)
3078 struct got_imsg_raw_delta idelta;
3081 memset(&idelta, 0, sizeof(idelta));
3082 idelta.base_size = base_size;
3083 idelta.result_size = result_size;
3084 idelta.delta_size = delta_size;
3085 idelta.delta_compressed_size = delta_compressed_size;
3086 idelta.delta_offset = delta_offset;
3087 idelta.delta_out_offset = delta_out_offset;
3088 memcpy(&idelta.base_id, &base_id, sizeof(idelta.base_id));
3090 ret = imsg_compose(ibuf, GOT_IMSG_RAW_DELTA, 0, 0, -1,
3091 &idelta, sizeof(idelta));
3093 return got_error_from_errno("imsg_compose RAW_DELTA");
3095 return flush_imsg(ibuf);
3098 const struct got_error *
3099 got_privsep_recv_raw_delta(uint64_t *base_size, uint64_t *result_size,
3100 off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
3101 off_t *delta_out_offset, struct got_object_id **base_id,
3102 struct imsgbuf *ibuf)
3104 const struct got_error *err = NULL;
3106 struct got_imsg_raw_delta *delta;
3112 *delta_compressed_size = 0;
3114 *delta_out_offset = 0;
3117 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3121 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3123 switch (imsg.hdr.type) {
3124 case GOT_IMSG_RAW_DELTA:
3125 if (datalen != sizeof(*delta)) {
3126 err = got_error(GOT_ERR_PRIVSEP_LEN);
3130 *base_size = delta->base_size;
3131 *result_size = delta->result_size;
3132 *delta_size = delta->delta_size;
3133 *delta_compressed_size = delta->delta_compressed_size;
3134 *delta_offset = delta->delta_offset;
3135 *delta_out_offset = delta->delta_out_offset;
3136 *base_id = calloc(1, sizeof(**base_id));
3137 if (*base_id == NULL) {
3138 err = got_error_from_errno("malloc");
3141 memcpy(*base_id, &delta->base_id, sizeof(**base_id));
3144 err = got_error(GOT_ERR_PRIVSEP_MSG);
3157 static const struct got_error *
3158 send_idlist(struct imsgbuf *ibuf, struct got_object_id **ids, size_t nids)
3160 const struct got_error *err = NULL;
3161 struct got_imsg_object_idlist idlist;
3165 memset(&idlist, 0, sizeof(idlist));
3167 if (nids > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS)
3168 return got_error(GOT_ERR_NO_SPACE);
3170 wbuf = imsg_create(ibuf, GOT_IMSG_OBJ_ID_LIST, 0, 0,
3171 sizeof(idlist) + nids * sizeof(**ids));
3173 err = got_error_from_errno("imsg_create OBJ_ID_LIST");
3178 if (imsg_add(wbuf, &idlist, sizeof(idlist)) == -1)
3179 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3181 for (i = 0; i < nids; i++) {
3182 struct got_object_id *id = ids[i];
3183 if (imsg_add(wbuf, id, sizeof(*id)) == -1)
3184 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3187 imsg_close(ibuf, wbuf);
3189 return flush_imsg(ibuf);
3192 const struct got_error *
3193 got_privsep_send_object_idlist(struct imsgbuf *ibuf,
3194 struct got_object_id **ids, size_t nids)
3196 const struct got_error *err = NULL;
3197 struct got_object_id *idlist[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS];
3200 for (i = 0; i < nids; i++) {
3201 idlist[i % nitems(idlist)] = ids[i];
3203 if (queued >= nitems(idlist)) {
3204 err = send_idlist(ibuf, idlist, queued);
3212 err = send_idlist(ibuf, idlist, queued);
3220 const struct got_error *
3221 got_privsep_send_object_idlist_done(struct imsgbuf *ibuf)
3223 if (imsg_compose(ibuf, GOT_IMSG_OBJ_ID_LIST_DONE, 0, 0, -1, NULL, 0)
3225 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3227 return flush_imsg(ibuf);
3230 const struct got_error *
3231 got_privsep_recv_object_idlist(int *done, struct got_object_id **ids,
3232 size_t *nids, struct imsgbuf *ibuf)
3234 const struct got_error *err = NULL;
3236 struct got_imsg_object_idlist *idlist;
3243 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3247 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3248 switch (imsg.hdr.type) {
3249 case GOT_IMSG_OBJ_ID_LIST:
3250 if (datalen < sizeof(*idlist)) {
3251 err = got_error(GOT_ERR_PRIVSEP_LEN);
3255 if (idlist->nids > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS ||
3256 idlist->nids * sizeof(**ids) > datalen - sizeof(*idlist)) {
3257 err = got_error(GOT_ERR_PRIVSEP_LEN);
3260 *nids = idlist->nids;
3261 *ids = calloc(*nids, sizeof(**ids));
3263 err = got_error_from_errno("calloc");
3266 memcpy(*ids, (uint8_t *)imsg.data + sizeof(*idlist),
3267 *nids * sizeof(**ids));
3269 case GOT_IMSG_OBJ_ID_LIST_DONE:
3273 err = got_error(GOT_ERR_PRIVSEP_MSG);
3282 const struct got_error *
3283 got_privsep_send_delta_reuse_req(struct imsgbuf *ibuf)
3285 if (imsg_compose(ibuf, GOT_IMSG_DELTA_REUSE_REQUEST, 0, 0, -1, NULL, 0)
3287 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3289 return flush_imsg(ibuf);
3292 const struct got_error *
3293 got_privsep_send_reused_deltas(struct imsgbuf *ibuf,
3294 struct got_imsg_reused_delta *deltas, size_t ndeltas)
3296 const struct got_error *err = NULL;
3298 struct got_imsg_reused_deltas ideltas;
3301 memset(&ideltas, 0, sizeof(ideltas));
3303 if (ndeltas > GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS)
3304 return got_error(GOT_ERR_NO_SPACE);
3306 wbuf = imsg_create(ibuf, GOT_IMSG_REUSED_DELTAS, 0, 0,
3307 sizeof(ideltas) + ndeltas * sizeof(*deltas));
3309 err = got_error_from_errno("imsg_create REUSED_DELTAS");
3313 ideltas.ndeltas = ndeltas;
3314 if (imsg_add(wbuf, &ideltas, sizeof(ideltas)) == -1)
3315 return got_error_from_errno("imsg_add REUSED_DELTAS");
3317 for (i = 0; i < ndeltas; i++) {
3318 struct got_imsg_reused_delta *delta = &deltas[i];
3319 if (imsg_add(wbuf, delta, sizeof(*delta)) == -1)
3320 return got_error_from_errno("imsg_add REUSED_DELTAS");
3323 imsg_close(ibuf, wbuf);
3325 return flush_imsg(ibuf);
3328 const struct got_error *
3329 got_privsep_send_reused_deltas_done(struct imsgbuf *ibuf)
3331 if (imsg_compose(ibuf, GOT_IMSG_DELTA_REUSE_DONE, 0, 0, -1, NULL, 0)
3333 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3335 return flush_imsg(ibuf);
3338 const struct got_error *
3339 got_privsep_recv_reused_deltas(int *done, struct got_imsg_reused_delta *deltas,
3340 size_t *ndeltas, struct imsgbuf *ibuf)
3342 const struct got_error *err = NULL;
3344 struct got_imsg_reused_deltas *ideltas;
3350 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3354 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3355 switch (imsg.hdr.type) {
3356 case GOT_IMSG_REUSED_DELTAS:
3357 if (datalen < sizeof(*ideltas)) {
3358 err = got_error(GOT_ERR_PRIVSEP_LEN);
3361 ideltas = imsg.data;
3362 if (ideltas->ndeltas > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS ||
3363 ideltas->ndeltas * sizeof(*deltas) >
3364 datalen - sizeof(*ideltas)) {
3365 err = got_error(GOT_ERR_PRIVSEP_LEN);
3368 *ndeltas = ideltas->ndeltas;
3369 memcpy(deltas, (uint8_t *)imsg.data + sizeof(*ideltas),
3370 *ndeltas * sizeof(*deltas));
3372 case GOT_IMSG_DELTA_REUSE_DONE:
3376 err = got_error(GOT_ERR_PRIVSEP_MSG);
3385 const struct got_error *
3386 got_privsep_init_commit_painting(struct imsgbuf *ibuf)
3388 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_PAINTING_INIT,
3391 return got_error_from_errno("imsg_compose "
3392 "COMMIT_PAINTING_INIT");
3394 return flush_imsg(ibuf);
3397 const struct got_error *
3398 got_privsep_send_painting_request(struct imsgbuf *ibuf, int idx,
3399 struct got_object_id *id, intptr_t color)
3401 struct got_imsg_commit_painting_request ireq;
3403 memset(&ireq, 0, sizeof(ireq));
3404 memcpy(&ireq.id, id, sizeof(ireq.id));
3408 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_PAINTING_REQUEST, 0, 0, -1,
3409 &ireq, sizeof(ireq)) == -1)
3410 return got_error_from_errno("imsg_compose "
3411 "COMMIT_PAINTING_REQUEST");
3413 return flush_imsg(ibuf);
3416 static const struct got_error *
3417 send_painted_commits(struct got_object_id_queue *ids, int *nids,
3418 size_t remain, int present_in_pack, struct imsgbuf *ibuf)
3420 const struct got_error *err = NULL;
3421 struct ibuf *wbuf = NULL;
3422 struct got_object_qid *qid;
3427 msglen = MIN(remain, MAX_IMSGSIZE - IMSG_HEADER_SIZE);
3428 ncommits = (msglen - sizeof(struct got_imsg_painted_commits)) /
3429 sizeof(struct got_imsg_painted_commit);
3431 wbuf = imsg_create(ibuf, GOT_IMSG_PAINTED_COMMITS, 0, 0, msglen);
3433 err = got_error_from_errno("imsg_create PAINTED_COMMITS");
3437 /* Keep in sync with struct got_imsg_painted_commits! */
3438 if (imsg_add(wbuf, &ncommits, sizeof(ncommits)) == -1)
3439 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3440 if (imsg_add(wbuf, &present_in_pack, sizeof(present_in_pack)) == -1)
3441 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3443 while (ncommits > 0) {
3444 qid = STAILQ_FIRST(ids);
3445 STAILQ_REMOVE_HEAD(ids, entry);
3448 color = (intptr_t)qid->data;
3450 /* Keep in sync with struct got_imsg_painted_commit! */
3451 if (imsg_add(wbuf, qid->id.sha1, SHA1_DIGEST_LENGTH) == -1)
3452 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3453 if (imsg_add(wbuf, &color, sizeof(color)) == -1)
3454 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3456 got_object_qid_free(qid);
3459 imsg_close(ibuf, wbuf);
3460 return flush_imsg(ibuf);
3463 const struct got_error *
3464 got_privsep_send_painted_commits(struct imsgbuf *ibuf,
3465 struct got_object_id_queue *ids, int *nids,
3466 int present_in_pack, int flush)
3468 const struct got_error *err;
3475 remain = (sizeof(struct got_imsg_painted_commits)) +
3476 *nids * sizeof(struct got_imsg_painted_commit);
3477 if (flush || remain >= MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
3478 err = send_painted_commits(ids, nids, remain,
3479 present_in_pack, ibuf);
3483 } while (flush && *nids > 0);
3488 const struct got_error *
3489 got_privsep_send_painting_commits_done(struct imsgbuf *ibuf)
3491 if (imsg_compose(ibuf, GOT_IMSG_COMMIT_PAINTING_DONE,
3494 return got_error_from_errno("imsg_compose "
3495 "COMMIT_PAINTING_DONE");
3497 return flush_imsg(ibuf);
3500 const struct got_error *
3501 got_privsep_recv_painted_commits(struct got_object_id_queue *new_ids,
3502 got_privsep_recv_painted_commit_cb cb, void *cb_arg, struct imsgbuf *ibuf)
3504 const struct got_error *err = NULL;
3506 struct got_imsg_painted_commits icommits;
3507 struct got_imsg_painted_commit icommit;
3512 err = got_privsep_recv_imsg(&imsg, ibuf, 0);
3518 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
3519 if (imsg.hdr.type == GOT_IMSG_COMMIT_PAINTING_DONE) {
3523 if (imsg.hdr.type != GOT_IMSG_PAINTED_COMMITS){
3525 return got_error(GOT_ERR_PRIVSEP_MSG);
3528 if (datalen < sizeof(icommits)){
3530 return got_error(GOT_ERR_PRIVSEP_LEN);
3532 memcpy(&icommits, imsg.data, sizeof(icommits));
3533 if (icommits.ncommits * sizeof(icommit) < icommits.ncommits ||
3534 datalen < sizeof(icommits) +
3535 icommits.ncommits * sizeof(icommit)){
3537 return got_error(GOT_ERR_PRIVSEP_LEN);
3540 for (i = 0; i < icommits.ncommits; i++) {
3542 (uint8_t *)imsg.data + sizeof(icommits) + i * sizeof(icommit),
3545 if (icommits.present_in_pack) {
3546 struct got_object_id id;
3547 memcpy(id.sha1, icommit.id, SHA1_DIGEST_LENGTH);
3548 err = cb(cb_arg, &id, icommit.color);
3552 struct got_object_qid *qid;
3553 err = got_object_qid_alloc_partial(&qid);
3556 memcpy(qid->id.sha1, icommit.id,
3557 SHA1_DIGEST_LENGTH);
3558 qid->data = (void *)icommit.color;
3559 STAILQ_INSERT_TAIL(new_ids, qid, entry);
3569 const struct got_error *
3570 got_privsep_unveil_exec_helpers(void)
3572 const char *helpers[] = {
3573 GOT_PATH_PROG_READ_PACK,
3574 GOT_PATH_PROG_READ_OBJECT,
3575 GOT_PATH_PROG_READ_COMMIT,
3576 GOT_PATH_PROG_READ_TREE,
3577 GOT_PATH_PROG_READ_BLOB,
3578 GOT_PATH_PROG_READ_TAG,
3579 GOT_PATH_PROG_READ_GITCONFIG,
3580 GOT_PATH_PROG_READ_GOTCONFIG,
3581 GOT_PATH_PROG_READ_PATCH,
3582 GOT_PATH_PROG_FETCH_PACK,
3583 GOT_PATH_PROG_INDEX_PACK,
3584 GOT_PATH_PROG_SEND_PACK,
3588 for (i = 0; i < nitems(helpers); i++) {
3589 if (unveil(helpers[i], "x") == 0)
3591 return got_error_from_errno2("unveil", helpers[i]);
3598 got_privsep_exec_child(int imsg_fds[2], const char *path, const char *repo_path)
3600 if (close(imsg_fds[0]) == -1) {
3601 fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
3605 if (dup2(imsg_fds[1], GOT_IMSG_FD_CHILD) == -1) {
3606 fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
3610 closefrom(GOT_IMSG_FD_CHILD + 1);
3612 if (execl(path, path, repo_path, (char *)NULL) == -1) {
3613 fprintf(stderr, "%s: %s: %s\n", getprogname(), path,