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>
37 #include "got_compat.h"
39 #include "got_object.h"
40 #include "got_error.h"
42 #include "got_repository.h"
44 #include "got_lib_hash.h"
45 #include "got_lib_delta.h"
46 #include "got_lib_inflate.h"
47 #include "got_lib_object.h"
48 #include "got_lib_object_parse.h"
49 #include "got_lib_object_qid.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
);
77 n
= imsgbuf_read(ibuf
);
79 return got_error(GOT_ERR_PRIVSEP_READ
);
81 return got_error(GOT_ERR_PRIVSEP_PIPE
);
86 const struct got_error
*
87 got_privsep_wait_for_child(pid_t pid
)
91 if (waitpid(pid
, &child_status
, 0) == -1)
92 return got_error_from_errno("waitpid");
94 if (!WIFEXITED(child_status
))
95 return got_error(GOT_ERR_PRIVSEP_DIED
);
97 if (WEXITSTATUS(child_status
) != 0)
98 return got_error(GOT_ERR_PRIVSEP_EXIT
);
103 static const struct got_error
*
104 recv_imsg_error(struct imsg
*imsg
, size_t datalen
)
106 struct got_imsg_error
*ierr
;
108 if (datalen
!= sizeof(*ierr
))
109 return got_error(GOT_ERR_PRIVSEP_LEN
);
112 if (ierr
->code
== GOT_ERR_ERRNO
) {
113 static struct got_error serr
;
114 serr
.code
= GOT_ERR_ERRNO
;
115 serr
.msg
= strerror(ierr
->errno_code
);
119 return got_error(ierr
->code
);
122 const struct got_error
*
123 got_privsep_recv_imsg(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
126 const struct got_error
*err
;
129 n
= imsg_get(ibuf
, imsg
);
131 return got_error_from_errno("imsg_get");
134 err
= read_imsg(ibuf
);
137 n
= imsg_get(ibuf
, imsg
);
139 return got_error_from_errno("imsg_get");
142 if (imsg
->hdr
.type
== GOT_IMSG_ERROR
) {
143 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
144 err
= recv_imsg_error(imsg
, datalen
);
149 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
) {
151 return got_error(GOT_ERR_PRIVSEP_LEN
);
157 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
159 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
161 const struct got_error
*poll_err
;
162 struct got_imsg_error ierr
;
165 ierr
.code
= err
->code
;
166 if (err
->code
== GOT_ERR_ERRNO
)
167 ierr
.errno_code
= errno
;
170 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
172 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
173 getprogname(), err
->code
, err
->msg
, strerror(errno
));
177 poll_err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
179 if (poll_err
->code
!= GOT_ERR_EOF
)
180 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
181 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
185 ret
= imsgbuf_flush(ibuf
);
187 fprintf(stderr
, "%s: error %d \"%s\": imsgbuf_flush: %s\n",
188 getprogname(), err
->code
, err
->msg
, strerror(errno
));
193 static const struct got_error
*
194 flush_imsg(struct imsgbuf
*ibuf
)
196 const struct got_error
*err
;
198 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
202 if (imsgbuf_flush(ibuf
) == -1)
203 return got_error_from_errno("imsgbuf_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
)
217 const struct got_error
*err
= NULL
;
220 if (imsgbuf_init(&ibuf
, fd
) == -1)
221 return got_error_from_errno("imsgbuf_init");
223 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1) {
224 err
= got_error_from_errno("imsg_compose STOP");
228 err
= flush_imsg(&ibuf
);
230 imsgbuf_clear(&ibuf
);
234 const struct got_error
*
235 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
236 struct got_object_id
*id
)
238 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
239 id
, sizeof(*id
)) == -1)
240 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
242 return flush_imsg(ibuf
);
245 const struct got_error
*
246 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
247 struct got_object_id
*id
)
249 const struct got_error
*err
;
251 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
252 id
, sizeof(*id
)) == -1) {
253 err
= got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
258 return flush_imsg(ibuf
);
261 const struct got_error
*
262 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
264 const struct got_error
*err
= NULL
;
266 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
268 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
273 return flush_imsg(ibuf
);
276 const struct got_error
*
277 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
280 struct got_imsg_raw_obj iobj
;
281 size_t len
= sizeof(iobj
);
284 memset(&iobj
, 0, sizeof(iobj
));
285 iobj
.hdrlen
= hdrlen
;
288 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
289 len
+= (size_t)size
+ hdrlen
;
291 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
293 return got_error_from_errno("imsg_create RAW_OBJECT");
295 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1)
296 return got_error_from_errno("imsg_add RAW_OBJECT");
298 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
299 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1)
300 return got_error_from_errno("imsg_add RAW_OBJECT");
303 imsg_close(ibuf
, wbuf
);
304 return flush_imsg(ibuf
);
307 const struct got_error
*
308 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
309 struct imsgbuf
*ibuf
)
311 const struct got_error
*err
= NULL
;
313 struct got_imsg_raw_obj
*iobj
;
318 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
322 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
324 switch (imsg
.hdr
.type
) {
325 case GOT_IMSG_RAW_OBJECT
:
326 if (datalen
< sizeof(*iobj
)) {
327 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
332 *hdrlen
= iobj
->hdrlen
;
334 if (datalen
== sizeof(*iobj
)) {
335 /* Data has been written to file descriptor. */
340 *size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
341 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
345 *outbuf
= malloc(*size
+ *hdrlen
);
346 if (*outbuf
== NULL
) {
347 err
= got_error_from_errno("malloc");
350 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
353 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
362 const struct got_error
*
363 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
364 struct got_object_id
*id
, int pack_idx
)
366 const struct got_error
*err
= NULL
;
367 struct got_imsg_packed_object iobj
;
371 memset(&iobj
, 0, sizeof(iobj
));
372 if (pack_idx
!= -1) { /* commit is packed */
374 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
382 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
384 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
389 return flush_imsg(ibuf
);
392 const struct got_error
*
393 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
394 struct got_object_id
*id
, int pack_idx
)
396 const struct got_error
*err
;
401 len
= sizeof(struct got_imsg_packed_object
);
405 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
407 err
= got_error_from_errno("imsg_create TREE_REQUEST");
413 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1) {
414 err
= got_error_from_errno("imsg_add TREE_REQUEST");
420 if (pack_idx
!= -1) { /* tree is packed */
421 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1) {
422 err
= got_error_from_errno("imsg_add TREE_REQUEST");
429 ibuf_fd_set(wbuf
, fd
);
430 imsg_close(ibuf
, wbuf
);
432 return flush_imsg(ibuf
);
435 const struct got_error
*
436 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
437 struct got_object_id
*id
, int pack_idx
)
439 const struct got_error
*err
;
440 struct got_imsg_packed_object iobj
;
444 memset(&iobj
, 0, sizeof(iobj
));
445 if (pack_idx
!= -1) { /* tag is packed */
447 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
455 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
457 err
= got_error_from_errno("imsg_compose TAG_REQUEST");
463 return flush_imsg(ibuf
);
466 const struct got_error
*
467 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
468 struct got_object_id
*id
, int pack_idx
)
470 const struct got_error
*err
= NULL
;
471 struct got_imsg_packed_object iobj
;
475 memset(&iobj
, 0, sizeof(iobj
));
476 if (pack_idx
!= -1) { /* blob is packed */
478 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
486 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
488 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
493 return flush_imsg(ibuf
);
496 const struct got_error
*
497 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
499 const struct got_error
*err
= NULL
;
501 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
503 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
508 return flush_imsg(ibuf
);
511 static const struct got_error
*
512 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
514 const struct got_error
*err
= NULL
;
516 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
517 err
= got_error_from_errno("imsg_compose TMPFD");
522 return flush_imsg(ibuf
);
525 const struct got_error
*
526 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
528 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
531 const struct got_error
*
532 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
534 struct got_imsg_object iobj
;
536 memset(&iobj
, 0, sizeof(iobj
));
538 memcpy(&iobj
.id
, &obj
->id
, sizeof(iobj
.id
));
539 iobj
.type
= obj
->type
;
540 iobj
.flags
= obj
->flags
;
541 iobj
.hdrlen
= obj
->hdrlen
;
542 iobj
.size
= obj
->size
;
543 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
544 iobj
.pack_offset
= obj
->pack_offset
;
545 iobj
.pack_idx
= obj
->pack_idx
;
548 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
550 return got_error_from_errno("imsg_compose OBJECT");
552 return flush_imsg(ibuf
);
555 const struct got_error
*
556 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
557 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
558 struct got_pathlist_head
*wanted_branches
,
559 struct got_pathlist_head
*wanted_refs
, int list_refs_only
,
560 const char *worktree_branch
, const char *remote_head
,
561 int no_head
, int verbosity
)
563 const struct got_error
*err
= NULL
;
565 struct got_pathlist_entry
*pe
;
566 struct got_imsg_fetch_request fetchreq
;
567 size_t remote_head_len
, worktree_branch_len
, len
= sizeof(fetchreq
);
569 if (worktree_branch
) {
570 worktree_branch_len
= strlen(worktree_branch
);
571 len
+= worktree_branch_len
;
574 remote_head_len
= strlen(remote_head
);
575 len
+= remote_head_len
;
578 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
580 return got_error(GOT_ERR_NO_SPACE
);
583 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, len
);
585 err
= got_error_from_errno("imsg_create FETCH_HAVE_REF");
590 memset(&fetchreq
, 0, sizeof(fetchreq
));
591 fetchreq
.no_head
= no_head
;
592 fetchreq
.fetch_all_branches
= fetch_all_branches
;
593 fetchreq
.list_refs_only
= list_refs_only
;
594 fetchreq
.verbosity
= verbosity
;
595 if (worktree_branch
!= NULL
)
596 fetchreq
.worktree_branch_len
= worktree_branch_len
;
597 if (remote_head
!= NULL
)
598 fetchreq
.remote_head_len
= remote_head_len
;
599 RB_FOREACH(pe
, got_pathlist_head
, have_refs
)
600 fetchreq
.n_have_refs
++;
601 RB_FOREACH(pe
, got_pathlist_head
, wanted_branches
)
602 fetchreq
.n_wanted_branches
++;
603 RB_FOREACH(pe
, got_pathlist_head
, wanted_refs
)
604 fetchreq
.n_wanted_refs
++;
605 if (imsg_add(wbuf
, &fetchreq
, sizeof(fetchreq
)) == -1)
606 return got_error_from_errno("imsg_add FETCH_REQUEST");
607 if (worktree_branch
) {
608 if (imsg_add(wbuf
, worktree_branch
, worktree_branch_len
)
610 err
= got_error_from_errno("imsg_add FETCH_REQUEST");
616 if (imsg_add(wbuf
, remote_head
, remote_head_len
) == -1) {
617 err
= got_error_from_errno("imsg_add FETCH_REQUEST");
622 ibuf_fd_set(wbuf
, fd
);
624 imsg_close(ibuf
, wbuf
);
626 err
= flush_imsg(ibuf
);
630 RB_FOREACH(pe
, got_pathlist_head
, have_refs
) {
631 const char *name
= pe
->path
;
632 size_t name_len
= pe
->path_len
;
633 struct got_object_id
*id
= pe
->data
;
635 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
636 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
638 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
640 /* Keep in sync with struct got_imsg_fetch_have_ref! */
641 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
642 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
643 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
644 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
645 if (imsg_add(wbuf
, name
, name_len
) == -1)
646 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
648 imsg_close(ibuf
, wbuf
);
649 err
= flush_imsg(ibuf
);
654 RB_FOREACH(pe
, got_pathlist_head
, wanted_branches
) {
655 const char *name
= pe
->path
;
656 size_t name_len
= pe
->path_len
;
658 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
659 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
662 return got_error_from_errno(
663 "imsg_create FETCH_WANTED_BRANCH");
665 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
666 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
667 return got_error_from_errno(
668 "imsg_add FETCH_WANTED_BRANCH");
669 if (imsg_add(wbuf
, name
, name_len
) == -1)
670 return got_error_from_errno(
671 "imsg_add FETCH_WANTED_BRANCH");
673 imsg_close(ibuf
, wbuf
);
674 err
= flush_imsg(ibuf
);
679 RB_FOREACH(pe
, got_pathlist_head
, wanted_refs
) {
680 const char *name
= pe
->path
;
681 size_t name_len
= pe
->path_len
;
683 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
684 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
687 return got_error_from_errno(
688 "imsg_create FETCH_WANTED_REF");
690 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
691 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
692 return got_error_from_errno(
693 "imsg_add FETCH_WANTED_REF");
694 if (imsg_add(wbuf
, name
, name_len
) == -1)
695 return got_error_from_errno(
696 "imsg_add FETCH_WANTED_REF");
698 imsg_close(ibuf
, wbuf
);
699 err
= flush_imsg(ibuf
);
707 const struct got_error
*
708 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
710 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
713 const struct got_error
*
714 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
715 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
716 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
718 const struct got_error
*err
= NULL
;
721 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
723 struct got_pathlist_entry
*new;
730 *server_progress
= NULL
;
732 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
734 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
738 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
739 switch (imsg
.hdr
.type
) {
740 case GOT_IMSG_FETCH_SYMREFS
:
741 if (datalen
< sizeof(*isymrefs
)) {
742 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
745 if (isymrefs
!= NULL
) {
746 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
749 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
750 off
= sizeof(*isymrefs
);
751 remain
= datalen
- off
;
752 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
753 struct got_imsg_fetch_symref
*s
;
755 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
756 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
759 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
761 remain
-= sizeof(*s
);
762 if (remain
< s
->name_len
) {
763 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
766 name
= strndup(imsg
.data
+ off
, s
->name_len
);
768 err
= got_error_from_errno("strndup");
772 remain
-= s
->name_len
;
773 if (remain
< s
->target_len
) {
774 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
778 target
= strndup(imsg
.data
+ off
, s
->target_len
);
779 if (target
== NULL
) {
780 err
= got_error_from_errno("strndup");
784 off
+= s
->target_len
;
785 remain
-= s
->target_len
;
786 err
= got_pathlist_insert(&new, symrefs
, name
, target
);
787 if (err
|| new == NULL
) {
790 if (err
->code
!= GOT_ERR_REF_DUP_ENTRY
)
795 case GOT_IMSG_FETCH_REF
:
796 if (datalen
<= sizeof(**id
)) {
797 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
800 *id
= malloc(sizeof(**id
));
802 err
= got_error_from_errno("malloc");
805 memcpy(*id
, imsg
.data
, sizeof(**id
));
806 *refname
= strndup(imsg
.data
+ sizeof(**id
),
807 datalen
- sizeof(**id
));
808 if (*refname
== NULL
) {
809 err
= got_error_from_errno("strndup");
813 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
815 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
818 *server_progress
= strndup(imsg
.data
, datalen
);
819 if (*server_progress
== NULL
) {
820 err
= got_error_from_errno("strndup");
823 for (i
= 0; i
< datalen
; i
++) {
824 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
825 !isspace((unsigned char)(*server_progress
)[i
])) {
826 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
827 free(*server_progress
);
828 *server_progress
= NULL
;
833 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
834 if (datalen
< sizeof(*packfile_size
)) {
835 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
838 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
840 case GOT_IMSG_FETCH_DONE
:
841 if (datalen
!= SHA1_DIGEST_LENGTH
) {
842 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
845 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
849 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
863 static const struct got_error
*
864 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
865 int delete, struct imsgbuf
*ibuf
)
870 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
871 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
873 return got_error_from_errno("imsg_create SEND_REF");
875 /* Keep in sync with struct got_imsg_send_ref! */
876 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
877 return got_error_from_errno("imsg_add SEND_REF");
878 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1)
879 return got_error_from_errno("imsg_add SEND_REF");
880 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
881 return got_error_from_errno("imsg_add SEND_REF");
882 if (imsg_add(wbuf
, name
, name_len
) == -1)
883 return got_error_from_errno("imsg_add SEND_REF");
885 imsg_close(ibuf
, wbuf
);
886 return flush_imsg(ibuf
);
889 const struct got_error
*
890 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
891 struct got_pathlist_head
*have_refs
,
892 struct got_pathlist_head
*delete_refs
,
895 const struct got_error
*err
= NULL
;
896 struct got_pathlist_entry
*pe
;
897 struct got_imsg_send_request sendreq
;
898 struct got_object_id zero_id
;
900 memset(&zero_id
, 0, sizeof(zero_id
));
901 memset(&sendreq
, 0, sizeof(sendreq
));
902 sendreq
.verbosity
= verbosity
;
903 RB_FOREACH(pe
, got_pathlist_head
, have_refs
)
905 RB_FOREACH(pe
, got_pathlist_head
, delete_refs
)
907 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
908 &sendreq
, sizeof(sendreq
)) == -1) {
909 err
= got_error_from_errno(
910 "imsg_compose FETCH_SERVER_PROGRESS");
915 err
= flush_imsg(ibuf
);
919 RB_FOREACH(pe
, got_pathlist_head
,have_refs
) {
920 const char *name
= pe
->path
;
921 size_t name_len
= pe
->path_len
;
922 struct got_object_id
*id
= pe
->data
;
923 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
928 RB_FOREACH(pe
, got_pathlist_head
, delete_refs
) {
929 const char *name
= pe
->path
;
930 size_t name_len
= pe
->path_len
;
931 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
936 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
937 err
= got_error_from_errno("close");
941 const struct got_error
*
942 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
943 struct imsgbuf
*ibuf
)
945 const struct got_error
*err
= NULL
;
948 struct got_imsg_send_remote_ref iremote_ref
;
949 struct got_object_id
*id
= NULL
;
950 char *refname
= NULL
;
951 struct got_pathlist_entry
*new;
954 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
957 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
958 switch (imsg
.hdr
.type
) {
959 case GOT_IMSG_SEND_REMOTE_REF
:
960 if (datalen
< sizeof(iremote_ref
)) {
961 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
964 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
965 if (datalen
!= sizeof(iremote_ref
) +
966 iremote_ref
.name_len
) {
967 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
970 id
= malloc(sizeof(*id
));
972 err
= got_error_from_errno("malloc");
975 memcpy(id
, &iremote_ref
.id
, sizeof(*id
));
976 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
977 datalen
- sizeof(iremote_ref
));
978 if (refname
== NULL
) {
979 err
= got_error_from_errno("strndup");
982 err
= got_pathlist_insert(&new, remote_refs
,
986 if (new == NULL
) { /* duplicate which wasn't inserted */
994 case GOT_IMSG_SEND_PACK_REQUEST
:
996 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
999 /* got-send-pack is now waiting for a pack file. */
1002 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1013 const struct got_error
*
1014 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
1016 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
1019 const struct got_error
*
1020 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
1021 int *success
, char **refname
, char **errmsg
, struct imsgbuf
*ibuf
)
1023 const struct got_error
*err
= NULL
;
1026 struct got_imsg_send_ref_status iref_status
;
1028 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1034 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1038 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1039 switch (imsg
.hdr
.type
) {
1040 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
1041 if (datalen
< sizeof(*bytes_sent
)) {
1042 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1045 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
1047 case GOT_IMSG_SEND_REF_STATUS
:
1048 if (datalen
< sizeof(iref_status
)) {
1049 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1052 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
1053 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
+
1054 iref_status
.errmsg_len
) {
1055 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1058 *success
= iref_status
.success
;
1059 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1060 iref_status
.name_len
);
1062 if (iref_status
.errmsg_len
!= 0)
1063 *errmsg
= strndup(imsg
.data
+ sizeof(iref_status
) +
1064 iref_status
.name_len
, iref_status
.errmsg_len
);
1066 case GOT_IMSG_SEND_DONE
:
1068 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1074 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1082 const struct got_error
*
1083 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, struct got_object_id
*id
,
1086 const struct got_error
*err
= NULL
;
1088 /* Keep in sync with struct got_imsg_index_pack_request */
1089 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1090 id
, sizeof(*id
)) == -1) {
1091 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1095 return flush_imsg(ibuf
);
1098 const struct got_error
*
1099 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1101 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1104 const struct got_error
*
1105 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1106 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1107 struct imsgbuf
*ibuf
)
1109 const struct got_error
*err
= NULL
;
1111 struct got_imsg_index_pack_progress
*iprogress
;
1119 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1123 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1124 switch (imsg
.hdr
.type
) {
1125 case GOT_IMSG_IDXPACK_PROGRESS
:
1126 if (datalen
< sizeof(*iprogress
)) {
1127 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1130 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1131 if (iprogress
->nobj_total
< 0 || iprogress
->nobj_indexed
< 0 ||
1132 iprogress
->nobj_loose
< 0 || iprogress
->nobj_resolved
< 0) {
1133 err
= got_error(GOT_ERR_RANGE
);
1136 *nobj_total
= iprogress
->nobj_total
;
1137 *nobj_indexed
= iprogress
->nobj_indexed
;
1138 *nobj_loose
= iprogress
->nobj_loose
;
1139 *nobj_resolved
= iprogress
->nobj_resolved
;
1141 case GOT_IMSG_IDXPACK_DONE
:
1143 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1149 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1157 const struct got_error
*
1158 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1159 struct imsgbuf
*ibuf
)
1161 struct got_imsg_object
*iobj
;
1162 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1164 if (datalen
!= sizeof(*iobj
))
1165 return got_error(GOT_ERR_PRIVSEP_LEN
);
1168 if (iobj
->pack_offset
< 0)
1169 return got_error(GOT_ERR_PACK_OFFSET
);
1171 *obj
= calloc(1, sizeof(**obj
));
1173 return got_error_from_errno("calloc");
1175 memcpy(&(*obj
)->id
, &iobj
->id
, sizeof(iobj
->id
));
1176 (*obj
)->type
= iobj
->type
;
1177 (*obj
)->flags
= iobj
->flags
;
1178 (*obj
)->hdrlen
= iobj
->hdrlen
;
1179 (*obj
)->size
= iobj
->size
;
1180 /* path_packfile is handled by caller */
1181 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1182 (*obj
)->pack_offset
= iobj
->pack_offset
;
1183 (*obj
)->pack_idx
= iobj
->pack_idx
;
1185 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1189 const struct got_error
*
1190 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1192 const struct got_error
*err
= NULL
;
1194 const size_t min_datalen
= sizeof(struct got_imsg_object
);
1198 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1202 switch (imsg
.hdr
.type
) {
1203 case GOT_IMSG_OBJECT
:
1204 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1207 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1216 static const struct got_error
*
1217 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1220 const struct got_error
*err
= NULL
;
1221 size_t offset
, remain
;
1224 remain
= logmsg_len
;
1225 while (remain
> 0) {
1226 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1228 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1229 commit
->logmsg
+ offset
, n
) == -1) {
1230 err
= got_error_from_errno("imsg_compose "
1235 err
= flush_imsg(ibuf
);
1246 const struct got_error
*
1247 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1249 const struct got_error
*err
= NULL
;
1250 struct got_imsg_commit_object
*icommit
;
1253 struct got_object_qid
*qid
;
1254 size_t author_len
= strlen(commit
->author
);
1255 size_t committer_len
= strlen(commit
->committer
);
1256 size_t logmsg_len
= strlen(commit
->logmsg
);
1258 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1259 commit
->nparents
* sizeof(struct got_object_id
);
1261 buf
= malloc(total
);
1263 return got_error_from_errno("malloc");
1265 icommit
= (struct got_imsg_commit_object
*)buf
;
1266 memcpy(&icommit
->tree_id
, commit
->tree_id
, sizeof(icommit
->tree_id
));
1267 icommit
->author_len
= author_len
;
1268 icommit
->author_time
= commit
->author_time
;
1269 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1270 icommit
->committer_len
= committer_len
;
1271 icommit
->committer_time
= commit
->committer_time
;
1272 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1273 icommit
->logmsg_len
= logmsg_len
;
1274 icommit
->nparents
= commit
->nparents
;
1276 len
= sizeof(*icommit
);
1277 memcpy(buf
+ len
, commit
->author
, author_len
);
1279 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1280 len
+= committer_len
;
1281 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1282 memcpy(buf
+ len
, &qid
->id
, sizeof(qid
->id
));
1283 len
+= sizeof(qid
->id
);
1286 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1287 err
= got_error_from_errno("imsg_compose COMMIT");
1291 if (logmsg_len
== 0 ||
1292 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1293 err
= flush_imsg(ibuf
);
1297 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1303 static const struct got_error
*
1304 get_commit_from_imsg(struct got_commit_object
**commit
,
1305 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1307 const struct got_error
*err
= NULL
;
1308 struct got_imsg_commit_object
*icommit
;
1312 if (datalen
< sizeof(*icommit
))
1313 return got_error(GOT_ERR_PRIVSEP_LEN
);
1315 icommit
= imsg
->data
;
1316 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1317 icommit
->committer_len
+
1318 icommit
->nparents
* sizeof(struct got_object_id
))
1319 return got_error(GOT_ERR_PRIVSEP_LEN
);
1321 if (icommit
->nparents
< 0)
1322 return got_error(GOT_ERR_PRIVSEP_LEN
);
1324 len
+= sizeof(*icommit
);
1326 *commit
= got_object_commit_alloc_partial();
1327 if (*commit
== NULL
)
1328 return got_error_from_errno(
1329 "got_object_commit_alloc_partial");
1331 memcpy((*commit
)->tree_id
, &icommit
->tree_id
,
1332 sizeof(icommit
->tree_id
));
1333 (*commit
)->author_time
= icommit
->author_time
;
1334 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1335 (*commit
)->committer_time
= icommit
->committer_time
;
1336 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1338 (*commit
)->author
= strndup(imsg
->data
+ len
, icommit
->author_len
);
1339 if ((*commit
)->author
== NULL
) {
1340 err
= got_error_from_errno("strndup");
1343 len
+= icommit
->author_len
;
1345 (*commit
)->committer
= strndup(imsg
->data
+ len
,
1346 icommit
->committer_len
);
1347 if ((*commit
)->committer
== NULL
) {
1348 err
= got_error_from_errno("strndup");
1351 len
+= icommit
->committer_len
;
1353 if (icommit
->logmsg_len
== 0) {
1354 (*commit
)->logmsg
= strdup("");
1355 if ((*commit
)->logmsg
== NULL
) {
1356 err
= got_error_from_errno("strdup");
1360 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1362 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1363 if ((*commit
)->logmsg
== NULL
) {
1364 err
= got_error_from_errno("malloc");
1367 while (remain
> 0) {
1368 struct imsg imsg_log
;
1369 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1372 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1376 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1377 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1381 memcpy((*commit
)->logmsg
+ offset
,
1383 imsg_free(&imsg_log
);
1387 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1390 for (i
= 0; i
< icommit
->nparents
; i
++) {
1391 struct got_object_qid
*qid
;
1393 err
= got_object_qid_alloc_partial(&qid
);
1396 memcpy(&qid
->id
, imsg
->data
+ len
+
1397 i
* sizeof(qid
->id
), sizeof(qid
->id
));
1398 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1399 (*commit
)->nparents
++;
1403 got_object_commit_close(*commit
);
1409 const struct got_error
*
1410 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1412 const struct got_error
*err
= NULL
;
1415 const size_t min_datalen
= sizeof(struct got_imsg_commit_object
);
1419 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1423 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1425 switch (imsg
.hdr
.type
) {
1426 case GOT_IMSG_COMMIT
:
1427 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1430 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1439 static const struct got_error
*
1440 send_tree_entries_batch(struct imsgbuf
*ibuf
,
1441 struct got_parsed_tree_entry
*entries
, int idx0
, int idxN
, size_t len
)
1444 struct got_imsg_tree_entries ientries
;
1447 memset(&ientries
, 0, sizeof(ientries
));
1449 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRIES
, 0, 0, len
);
1451 return got_error_from_errno("imsg_create TREE_ENTRY");
1453 ientries
.nentries
= idxN
- idx0
+ 1;
1454 if (imsg_add(wbuf
, &ientries
, sizeof(ientries
)) == -1)
1455 return got_error_from_errno("imsg_add TREE_ENTRY");
1457 for (i
= idx0
; i
<= idxN
; i
++) {
1458 static const char gap
[12]; /* for sha1 inside sha256 align */
1459 struct got_parsed_tree_entry
*pte
= &entries
[i
];
1461 /* Keep in sync with struct got_imsg_tree_entry definition! */
1462 if (imsg_add(wbuf
, pte
->id
, pte
->digest_len
) == -1)
1463 return got_error_from_errno("imsg_add TREE_ENTRY");
1464 if (pte
->algo
== GOT_HASH_SHA1
&&
1465 imsg_add(wbuf
, gap
, sizeof(gap
)) == -1)
1466 return got_error_from_errno("imsg_add TREE_ENTRY");
1467 if (imsg_add(wbuf
, &pte
->algo
, sizeof(pte
->algo
)) == -1)
1468 return got_error_from_errno("imsg_add TREE_ENTRY");
1469 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1)
1470 return got_error_from_errno("imsg_add TREE_ENTRY");
1471 if (imsg_add(wbuf
, &pte
->namelen
, sizeof(pte
->namelen
)) == -1)
1472 return got_error_from_errno("imsg_add TREE_ENTRY");
1474 /* Remaining bytes are the entry's name. */
1475 if (imsg_add(wbuf
, pte
->name
, pte
->namelen
) == -1)
1476 return got_error_from_errno("imsg_add TREE_ENTRY");
1479 imsg_close(ibuf
, wbuf
);
1483 static const struct got_error
*
1484 send_tree_entries(struct imsgbuf
*ibuf
, struct got_parsed_tree_entry
*entries
,
1487 const struct got_error
*err
= NULL
;
1489 size_t entries_len
= sizeof(struct got_imsg_tree_entries
);
1492 for (j
= 0; j
< nentries
; j
++) {
1493 struct got_parsed_tree_entry
*pte
= &entries
[j
];
1494 size_t len
= sizeof(struct got_imsg_tree_entry
) + pte
->namelen
;
1497 entries_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1498 err
= send_tree_entries_batch(ibuf
, entries
,
1499 i
, j
- 1, entries_len
);
1503 entries_len
= sizeof(struct got_imsg_tree_entries
);
1510 err
= send_tree_entries_batch(ibuf
, entries
, i
, j
- 1,
1519 const struct got_error
*
1520 got_privsep_send_tree(struct imsgbuf
*ibuf
,
1521 struct got_parsed_tree_entry
*entries
, int nentries
)
1523 const struct got_error
*err
= NULL
;
1524 struct got_imsg_tree_object itree
;
1526 memset(&itree
, 0, sizeof(itree
));
1527 itree
.nentries
= nentries
;
1528 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1530 return got_error_from_errno("imsg_compose TREE");
1532 err
= send_tree_entries(ibuf
, entries
, nentries
);
1536 return flush_imsg(ibuf
);
1540 static const struct got_error
*
1541 recv_tree_entries(void *data
, size_t datalen
, struct got_tree_object
*tree
,
1544 const struct got_error
*err
= NULL
;
1545 struct got_imsg_tree_entries
*ientries
;
1546 struct got_tree_entry
*te
;
1550 if (datalen
<= sizeof(*ientries
) ||
1551 datalen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
1552 return got_error(GOT_ERR_PRIVSEP_LEN
);
1554 ientries
= (struct got_imsg_tree_entries
*)data
;
1555 if (ientries
->nentries
> INT_MAX
) {
1556 return got_error_msg(GOT_ERR_NO_SPACE
,
1557 "too many tree entries");
1560 te_offset
= sizeof(*ientries
);
1561 for (i
= 0; i
< ientries
->nentries
; i
++) {
1562 struct got_imsg_tree_entry ite
;
1563 const char *te_name
;
1564 uint8_t *buf
= (uint8_t *)data
+ te_offset
;
1566 if (te_offset
>= datalen
) {
1567 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1571 /* Might not be aligned, size is ~32 bytes. */
1572 memcpy(&ite
, buf
, sizeof(ite
));
1574 if (ite
.namelen
>= sizeof(te
->name
)) {
1575 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1578 if (te_offset
+ sizeof(ite
) + ite
.namelen
> datalen
) {
1579 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1583 if (*nentries
>= tree
->nentries
) {
1584 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1587 te
= &tree
->entries
[*nentries
];
1588 te_name
= buf
+ sizeof(ite
);
1589 memcpy(te
->name
, te_name
, ite
.namelen
);
1590 te
->name
[ite
.namelen
] = '\0';
1591 memcpy(te
->id
.hash
, ite
.id
, sizeof(te
->id
.hash
));
1592 memcpy(te
->id
.hash
, ite
.id
, got_hash_digest_length(ite
.algo
));
1593 te
->id
.algo
= ite
.algo
;
1594 te
->mode
= ite
.mode
;
1595 te
->idx
= *nentries
;
1598 te_offset
+= sizeof(ite
) + ite
.namelen
;
1604 const struct got_error
*
1605 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1607 const struct got_error
*err
= NULL
;
1608 const size_t min_datalen
= sizeof(struct got_imsg_tree_object
);
1609 struct got_imsg_tree_object
*itree
;
1614 while (*tree
== NULL
|| nentries
< (*tree
)->nentries
) {
1618 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1622 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1624 switch (imsg
.hdr
.type
) {
1626 /* This message should only appear once. */
1627 if (*tree
!= NULL
) {
1628 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1631 if (datalen
!= sizeof(*itree
)) {
1632 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1636 if (itree
->nentries
< 0) {
1637 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1640 *tree
= malloc(sizeof(**tree
));
1641 if (*tree
== NULL
) {
1642 err
= got_error_from_errno("malloc");
1645 (*tree
)->entries
= calloc(itree
->nentries
,
1646 sizeof(struct got_tree_entry
));
1647 if ((*tree
)->entries
== NULL
) {
1648 err
= got_error_from_errno("malloc");
1653 (*tree
)->nentries
= itree
->nentries
;
1654 (*tree
)->refcnt
= 0;
1656 case GOT_IMSG_TREE_ENTRIES
:
1657 /* This message should be preceeded by GOT_IMSG_TREE. */
1658 if (*tree
== NULL
) {
1659 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1662 err
= recv_tree_entries(imsg
.data
, datalen
,
1666 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1675 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1677 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1678 got_object_tree_close(*tree
);
1685 const struct got_error
*
1686 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1687 const uint8_t *data
)
1689 struct got_imsg_blob iblob
;
1691 memset(&iblob
, 0, sizeof(iblob
));
1693 iblob
.hdrlen
= hdrlen
;
1698 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1699 return got_error(GOT_ERR_NO_SPACE
);
1701 buf
= malloc(sizeof(iblob
) + size
);
1703 return got_error_from_errno("malloc");
1705 memcpy(buf
, &iblob
, sizeof(iblob
));
1706 memcpy(buf
+ sizeof(iblob
), data
, size
);
1707 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1708 sizeof(iblob
) + size
) == -1) {
1710 return got_error_from_errno("imsg_compose BLOB");
1714 /* Data has already been written to file descriptor. */
1715 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1716 sizeof(iblob
)) == -1)
1717 return got_error_from_errno("imsg_compose BLOB");
1721 return flush_imsg(ibuf
);
1724 const struct got_error
*
1725 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1726 struct imsgbuf
*ibuf
)
1728 const struct got_error
*err
= NULL
;
1730 struct got_imsg_blob
*iblob
;
1735 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1739 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1741 switch (imsg
.hdr
.type
) {
1743 if (datalen
< sizeof(*iblob
)) {
1744 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1748 *size
= iblob
->size
;
1749 *hdrlen
= iblob
->hdrlen
;
1751 if (datalen
== sizeof(*iblob
)) {
1752 /* Data has been written to file descriptor. */
1756 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
||
1757 *size
> datalen
+ sizeof(*iblob
)) {
1758 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1762 *outbuf
= malloc(*size
);
1763 if (*outbuf
== NULL
) {
1764 err
= got_error_from_errno("malloc");
1767 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1770 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1779 static const struct got_error
*
1780 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1782 const struct got_error
*err
= NULL
;
1783 size_t offset
, remain
;
1786 remain
= tagmsg_len
;
1787 while (remain
> 0) {
1788 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1790 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1791 tag
->tagmsg
+ offset
, n
) == -1) {
1792 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1796 err
= flush_imsg(ibuf
);
1807 const struct got_error
*
1808 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1810 const struct got_error
*err
= NULL
;
1811 struct got_imsg_tag_object
*itag
;
1814 size_t tag_len
= strlen(tag
->tag
);
1815 size_t tagger_len
= strlen(tag
->tagger
);
1816 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1818 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1820 buf
= malloc(total
);
1822 return got_error_from_errno("malloc");
1824 itag
= (struct got_imsg_tag_object
*)buf
;
1825 memcpy(&itag
->id
, &tag
->id
, sizeof(itag
->id
));
1826 itag
->obj_type
= tag
->obj_type
;
1827 itag
->tag_len
= tag_len
;
1828 itag
->tagger_len
= tagger_len
;
1829 itag
->tagger_time
= tag
->tagger_time
;
1830 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1831 itag
->tagmsg_len
= tagmsg_len
;
1833 len
= sizeof(*itag
);
1834 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1836 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1839 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1840 err
= got_error_from_errno("imsg_compose TAG");
1844 if (tagmsg_len
== 0 ||
1845 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1846 err
= flush_imsg(ibuf
);
1850 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1856 const struct got_error
*
1857 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1859 const struct got_error
*err
= NULL
;
1861 struct got_imsg_tag_object
*itag
;
1862 size_t len
, datalen
;
1863 const size_t min_datalen
= sizeof(struct got_imsg_tag_object
);
1867 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1871 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1874 switch (imsg
.hdr
.type
) {
1876 if (datalen
< sizeof(*itag
)) {
1877 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1881 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1883 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1886 len
+= sizeof(*itag
);
1888 *tag
= calloc(1, sizeof(**tag
));
1890 err
= got_error_from_errno("calloc");
1894 memcpy(&(*tag
)->id
, &itag
->id
, sizeof(itag
->id
));
1896 (*tag
)->tag
= strndup(imsg
.data
+ len
, itag
->tag_len
);
1897 if ((*tag
)->tag
== NULL
) {
1898 err
= got_error_from_errno("strndup");
1901 len
+= itag
->tag_len
;
1903 (*tag
)->obj_type
= itag
->obj_type
;
1904 (*tag
)->tagger_time
= itag
->tagger_time
;
1905 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1907 (*tag
)->tagger
= strndup(imsg
.data
+ len
, itag
->tagger_len
);
1908 if ((*tag
)->tagger
== NULL
) {
1909 err
= got_error_from_errno("strndup");
1912 len
+= itag
->tagger_len
;
1914 if (itag
->tagmsg_len
== 0) {
1915 (*tag
)->tagmsg
= strdup("");
1916 if ((*tag
)->tagmsg
== NULL
) {
1917 err
= got_error_from_errno("strdup");
1921 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1923 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1924 if ((*tag
)->tagmsg
== NULL
) {
1925 err
= got_error_from_errno("malloc");
1928 while (remain
> 0) {
1929 struct imsg imsg_log
;
1930 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1933 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1937 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1938 return got_error(GOT_ERR_PRIVSEP_MSG
);
1940 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1942 imsg_free(&imsg_log
);
1946 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1951 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1960 const struct got_error
*
1961 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1962 struct got_packidx
*packidx
)
1964 const struct got_error
*err
= NULL
;
1965 struct got_imsg_packidx ipackidx
;
1966 struct got_imsg_pack ipack
;
1969 memset(&ipackidx
, 0, sizeof(ipackidx
));
1970 memset(&ipack
, 0, sizeof(ipack
));
1972 ipackidx
.len
= packidx
->len
;
1973 ipackidx
.packfile_size
= pack
->filesize
;
1974 ipackidx
.algo
= packidx
->algo
;
1975 fd
= dup(packidx
->fd
);
1977 return got_error_from_errno("dup");
1979 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1980 sizeof(ipackidx
)) == -1) {
1981 err
= got_error_from_errno("imsg_compose PACKIDX");
1986 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1987 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1988 return got_error(GOT_ERR_NO_SPACE
);
1989 ipack
.filesize
= pack
->filesize
;
1990 ipack
.algo
= pack
->algo
;
1994 return got_error_from_errno("dup");
1996 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
1998 err
= got_error_from_errno("imsg_compose PACK");
2003 return flush_imsg(ibuf
);
2006 const struct got_error
*
2007 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
2008 struct got_object_id
*id
)
2010 struct got_imsg_packed_object iobj
;
2012 memset(&iobj
, 0, sizeof(iobj
));
2014 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2016 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
2017 &iobj
, sizeof(iobj
)) == -1)
2018 return got_error_from_errno("imsg_compose "
2019 "PACKED_OBJECT_REQUEST");
2021 return flush_imsg(ibuf
);
2024 const struct got_error
*
2025 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
2026 struct got_object_id
*id
)
2028 struct got_imsg_packed_object iobj
;
2030 memset(&iobj
, 0, sizeof(iobj
));
2032 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2034 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
2035 &iobj
, sizeof(iobj
)) == -1)
2036 return got_error_from_errno("imsg_compose "
2037 "PACKED_OBJECT_REQUEST");
2039 return flush_imsg(ibuf
);
2042 const struct got_error
*
2043 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2045 const struct got_error
*err
= NULL
;
2047 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2049 err
= got_error_from_errno("imsg_compose "
2050 "GITCONFIG_PARSE_REQUEST");
2055 return flush_imsg(ibuf
);
2058 const struct got_error
*
2059 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2061 if (imsg_compose(ibuf
,
2062 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2064 return got_error_from_errno("imsg_compose "
2065 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2067 return flush_imsg(ibuf
);
2070 const struct got_error
*
2071 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2073 if (imsg_compose(ibuf
,
2074 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2076 return got_error_from_errno("imsg_compose "
2077 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2079 return flush_imsg(ibuf
);
2083 const struct got_error
*
2084 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2086 if (imsg_compose(ibuf
,
2087 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2088 return got_error_from_errno("imsg_compose "
2089 "GITCONFIG_AUTHOR_NAME_REQUEST");
2091 return flush_imsg(ibuf
);
2094 const struct got_error
*
2095 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2097 if (imsg_compose(ibuf
,
2098 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2099 return got_error_from_errno("imsg_compose "
2100 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2102 return flush_imsg(ibuf
);
2105 const struct got_error
*
2106 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2108 if (imsg_compose(ibuf
,
2109 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2110 return got_error_from_errno("imsg_compose "
2111 "GITCONFIG_REMOTE_REQUEST");
2113 return flush_imsg(ibuf
);
2116 const struct got_error
*
2117 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2119 if (imsg_compose(ibuf
,
2120 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2121 return got_error_from_errno("imsg_compose "
2122 "GITCONFIG_OWNER_REQUEST");
2124 return flush_imsg(ibuf
);
2127 const struct got_error
*
2128 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2130 const struct got_error
*err
= NULL
;
2136 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2139 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2141 switch (imsg
.hdr
.type
) {
2142 case GOT_IMSG_GITCONFIG_STR_VAL
:
2145 *str
= strndup(imsg
.data
, datalen
);
2147 err
= got_error_from_errno("strndup");
2152 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2160 const struct got_error
*
2161 got_privsep_recv_gitconfig_pair(char **key
, char **val
, struct imsgbuf
*ibuf
)
2163 const struct got_error
*err
= NULL
;
2164 struct got_imsg_gitconfig_pair p
;
2171 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2176 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2178 if (imsg
.hdr
.type
!= GOT_IMSG_GITCONFIG_PAIR
) {
2179 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2183 if (datalen
< sizeof(p
)) {
2184 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2188 memcpy(&p
, data
, sizeof(p
));
2191 if (datalen
!= sizeof(p
) + p
.klen
+ p
.vlen
) {
2192 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2196 *key
= strndup(data
, p
.klen
);
2198 err
= got_error_from_errno("strndup");
2203 *val
= strndup(data
, p
.vlen
);
2205 err
= got_error_from_errno("strndup");
2214 const struct got_error
*
2215 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2217 const struct got_error
*err
= NULL
;
2220 const size_t min_datalen
= sizeof(int);
2224 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2227 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2229 switch (imsg
.hdr
.type
) {
2230 case GOT_IMSG_GITCONFIG_INT_VAL
:
2231 if (datalen
!= sizeof(*val
)) {
2232 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2235 memcpy(val
, imsg
.data
, sizeof(*val
));
2238 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2247 free_remote_data(struct got_remote_repo
*remote
)
2252 free(remote
->fetch_url
);
2253 free(remote
->send_url
);
2254 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2255 free(remote
->fetch_branches
[i
]);
2256 free(remote
->fetch_branches
);
2257 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2258 free(remote
->send_branches
[i
]);
2259 free(remote
->send_branches
);
2260 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2261 free(remote
->fetch_refs
[i
]);
2262 free(remote
->fetch_refs
);
2265 const struct got_error
*
2266 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2267 int *nremotes
, struct imsgbuf
*ibuf
)
2269 const struct got_error
*err
= NULL
;
2272 struct got_imsg_remotes iremotes
;
2273 struct got_imsg_remote iremote
;
2277 iremotes
.nremotes
= 0;
2279 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2282 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2284 switch (imsg
.hdr
.type
) {
2285 case GOT_IMSG_GITCONFIG_REMOTES
:
2286 if (datalen
!= sizeof(iremotes
)) {
2288 return got_error(GOT_ERR_PRIVSEP_LEN
);
2290 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2291 if (iremotes
.nremotes
== 0) {
2298 return got_error(GOT_ERR_PRIVSEP_MSG
);
2303 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2304 if (*remotes
== NULL
)
2305 return got_error_from_errno("recallocarray");
2307 while (*nremotes
< iremotes
.nremotes
) {
2308 struct got_remote_repo
*remote
;
2310 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2313 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2315 switch (imsg
.hdr
.type
) {
2316 case GOT_IMSG_GITCONFIG_REMOTE
:
2317 remote
= &(*remotes
)[*nremotes
];
2318 memset(remote
, 0, sizeof(*remote
));
2319 if (datalen
< sizeof(iremote
)) {
2320 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2323 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2324 if (iremote
.name_len
== 0 ||
2325 iremote
.fetch_url_len
== 0 ||
2326 iremote
.send_url_len
== 0 ||
2327 (sizeof(iremote
) + iremote
.name_len
+
2328 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2329 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2332 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2334 if (remote
->name
== NULL
) {
2335 err
= got_error_from_errno("strndup");
2338 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2339 iremote
.name_len
, iremote
.fetch_url_len
);
2340 if (remote
->fetch_url
== NULL
) {
2341 err
= got_error_from_errno("strndup");
2342 free_remote_data(remote
);
2345 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2346 iremote
.name_len
+ iremote
.fetch_url_len
,
2347 iremote
.send_url_len
);
2348 if (remote
->send_url
== NULL
) {
2349 err
= got_error_from_errno("strndup");
2350 free_remote_data(remote
);
2353 remote
->mirror_references
= iremote
.mirror_references
;
2354 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2355 remote
->nfetch_branches
= 0;
2356 remote
->fetch_branches
= NULL
;
2357 remote
->nsend_branches
= 0;
2358 remote
->send_branches
= NULL
;
2359 remote
->nfetch_refs
= 0;
2360 remote
->fetch_refs
= NULL
;
2364 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2375 for (i
= 0; i
< *nremotes
; i
++)
2376 free_remote_data(&(*remotes
)[i
]);
2384 const struct got_error
*
2385 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2387 const struct got_error
*err
= NULL
;
2389 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2391 err
= got_error_from_errno("imsg_compose "
2392 "GOTCONFIG_PARSE_REQUEST");
2397 return flush_imsg(ibuf
);
2400 const struct got_error
*
2401 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2403 if (imsg_compose(ibuf
,
2404 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2405 return got_error_from_errno("imsg_compose "
2406 "GOTCONFIG_AUTHOR_REQUEST");
2408 return flush_imsg(ibuf
);
2411 const struct got_error
*
2412 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf
*ibuf
)
2414 if (imsg_compose(ibuf
,
2415 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2416 return got_error_from_errno("imsg_compose "
2417 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2419 return flush_imsg(ibuf
);
2422 const struct got_error
*
2423 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf
*ibuf
)
2425 if (imsg_compose(ibuf
,
2426 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2427 return got_error_from_errno("imsg_compose "
2428 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2430 return flush_imsg(ibuf
);
2433 const struct got_error
*
2434 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf
*ibuf
)
2436 if (imsg_compose(ibuf
,
2437 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2438 return got_error_from_errno("imsg_compose "
2439 "GOTCONFIG_SIGNERID_REQUEST");
2441 return flush_imsg(ibuf
);
2444 const struct got_error
*
2445 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2447 if (imsg_compose(ibuf
,
2448 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2449 return got_error_from_errno("imsg_compose "
2450 "GOTCONFIG_REMOTE_REQUEST");
2452 return flush_imsg(ibuf
);
2455 const struct got_error
*
2456 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2458 const struct got_error
*err
= NULL
;
2464 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2467 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2469 switch (imsg
.hdr
.type
) {
2470 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2473 *str
= strndup(imsg
.data
, datalen
);
2475 err
= got_error_from_errno("strndup");
2480 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2488 const struct got_error
*
2489 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2490 int *nremotes
, struct imsgbuf
*ibuf
)
2492 const struct got_error
*err
= NULL
;
2495 struct got_imsg_remotes iremotes
;
2496 struct got_imsg_remote iremote
;
2497 const size_t min_datalen
= sizeof(iremotes
);
2501 iremotes
.nremotes
= 0;
2503 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2506 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2508 switch (imsg
.hdr
.type
) {
2509 case GOT_IMSG_GOTCONFIG_REMOTES
:
2510 if (datalen
!= sizeof(iremotes
)) {
2511 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2514 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2515 if (iremotes
.nremotes
< 0) {
2516 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2519 if (iremotes
.nremotes
== 0) {
2526 return got_error(GOT_ERR_PRIVSEP_MSG
);
2531 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2532 if (*remotes
== NULL
)
2533 return got_error_from_errno("recallocarray");
2535 while (*nremotes
< iremotes
.nremotes
) {
2536 struct got_remote_repo
*remote
;
2537 const size_t min_datalen
= sizeof(iremote
);
2540 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2543 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2545 switch (imsg
.hdr
.type
) {
2546 case GOT_IMSG_GOTCONFIG_REMOTE
:
2547 remote
= &(*remotes
)[*nremotes
];
2548 memset(remote
, 0, sizeof(*remote
));
2549 if (datalen
< sizeof(iremote
)) {
2550 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2553 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2554 if (iremote
.name_len
== 0 ||
2555 (iremote
.fetch_url_len
== 0 &&
2556 iremote
.send_url_len
== 0) ||
2557 (sizeof(iremote
) + iremote
.name_len
+
2558 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2560 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2563 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2565 if (remote
->name
== NULL
) {
2566 err
= got_error_from_errno("strndup");
2569 remote
->fetch_url
= strndup(imsg
.data
+
2570 sizeof(iremote
) + iremote
.name_len
,
2571 iremote
.fetch_url_len
);
2572 if (remote
->fetch_url
== NULL
) {
2573 err
= got_error_from_errno("strndup");
2574 free_remote_data(remote
);
2577 remote
->send_url
= strndup(imsg
.data
+
2578 sizeof(iremote
) + iremote
.name_len
+
2579 iremote
.fetch_url_len
, iremote
.send_url_len
);
2580 if (remote
->send_url
== NULL
) {
2581 err
= got_error_from_errno("strndup");
2582 free_remote_data(remote
);
2585 remote
->mirror_references
= iremote
.mirror_references
;
2586 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2587 if (iremote
.nfetch_branches
> 0) {
2588 remote
->fetch_branches
= recallocarray(NULL
, 0,
2589 iremote
.nfetch_branches
, sizeof(char *));
2590 if (remote
->fetch_branches
== NULL
) {
2591 err
= got_error_from_errno("calloc");
2592 free_remote_data(remote
);
2596 remote
->nfetch_branches
= 0;
2597 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2599 err
= got_privsep_recv_gotconfig_str(&branch
,
2602 free_remote_data(remote
);
2605 remote
->fetch_branches
[i
] = branch
;
2606 remote
->nfetch_branches
++;
2608 if (iremote
.nsend_branches
> 0) {
2609 remote
->send_branches
= recallocarray(NULL
, 0,
2610 iremote
.nsend_branches
, sizeof(char *));
2611 if (remote
->send_branches
== NULL
) {
2612 err
= got_error_from_errno("calloc");
2613 free_remote_data(remote
);
2617 remote
->nsend_branches
= 0;
2618 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2620 err
= got_privsep_recv_gotconfig_str(&branch
,
2623 free_remote_data(remote
);
2626 remote
->send_branches
[i
] = branch
;
2627 remote
->nsend_branches
++;
2629 if (iremote
.nfetch_refs
> 0) {
2630 remote
->fetch_refs
= recallocarray(NULL
, 0,
2631 iremote
.nfetch_refs
, sizeof(char *));
2632 if (remote
->fetch_refs
== NULL
) {
2633 err
= got_error_from_errno("calloc");
2634 free_remote_data(remote
);
2638 remote
->nfetch_refs
= 0;
2639 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2641 err
= got_privsep_recv_gotconfig_str(&ref
,
2644 free_remote_data(remote
);
2647 remote
->fetch_refs
[i
] = ref
;
2648 remote
->nfetch_refs
++;
2653 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2664 for (i
= 0; i
< *nremotes
; i
++)
2665 free_remote_data(&(*remotes
)[i
]);
2673 const struct got_error
*
2674 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2675 struct got_object_id
*id
, int idx
, const char *path
)
2678 size_t path_len
= strlen(path
);
2680 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2681 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2683 return got_error_from_errno(
2684 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2686 * Keep in sync with struct got_imsg_commit_traversal_request
2687 * and struct got_imsg_packed_object.
2689 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2690 return got_error_from_errno("imsg_add "
2691 "COMMIT_TRAVERSAL_REQUEST");
2692 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1)
2693 return got_error_from_errno("imsg_add "
2694 "COMMIT_TRAVERSAL_REQUEST");
2695 if (imsg_add(wbuf
, &path_len
, sizeof(path_len
)) == -1)
2696 return got_error_from_errno("imsg_add "
2697 "COMMIT_TRAVERSAL_REQUEST");
2698 if (imsg_add(wbuf
, path
, path_len
) == -1)
2699 return got_error_from_errno("imsg_add "
2700 "COMMIT_TRAVERSAL_REQUEST");
2702 imsg_close(ibuf
, wbuf
);
2703 return flush_imsg(ibuf
);
2706 const struct got_error
*
2707 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2708 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2710 const struct got_error
*err
= NULL
;
2712 struct got_imsg_traversed_commits
*icommits
;
2713 struct got_object_id
*ids
;
2717 *changed_commit
= NULL
;
2720 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2724 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2725 switch (imsg
.hdr
.type
) {
2726 case GOT_IMSG_TRAVERSED_COMMITS
:
2727 icommits
= imsg
.data
;
2728 if (datalen
!= sizeof(*icommits
) +
2729 icommits
->ncommits
* sizeof(*ids
)) {
2730 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2733 ids
= imsg
.data
+ sizeof(*icommits
);
2734 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2735 struct got_object_qid
*qid
;
2737 err
= got_object_qid_alloc_partial(&qid
);
2740 memcpy(&qid
->id
, &ids
[i
], sizeof(ids
[i
]));
2741 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2745 case GOT_IMSG_COMMIT
:
2746 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2749 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2753 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2763 got_object_id_queue_free(commit_ids
);
2767 const struct got_error
*
2768 got_privsep_send_enumerated_tree(size_t *totlen
, struct imsgbuf
*ibuf
,
2769 struct got_object_id
*tree_id
, const char *path
,
2770 struct got_parsed_tree_entry
*entries
, int nentries
)
2772 const struct got_error
*err
= NULL
;
2774 size_t path_len
= strlen(path
);
2777 msglen
= sizeof(struct got_imsg_enumerated_tree
) + path_len
;
2778 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_TREE
, 0, 0, msglen
);
2780 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2782 if (imsg_add(wbuf
, tree_id
, sizeof(*tree_id
)) == -1)
2783 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2784 if (imsg_add(wbuf
, &nentries
, sizeof(nentries
)) == -1)
2785 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2786 if (imsg_add(wbuf
, path
, path_len
) == -1)
2787 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2789 imsg_close(ibuf
, wbuf
);
2792 err
= send_tree_entries(ibuf
, entries
, nentries
);
2797 return flush_imsg(ibuf
);
2800 const struct got_error
*
2801 got_privsep_send_object_enumeration_request(struct imsgbuf
*ibuf
)
2803 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_REQUEST
,
2804 0, 0, -1, NULL
, 0) == -1)
2805 return got_error_from_errno("imsg_compose "
2806 "OBJECT_ENUMERATION_REQUEST");
2808 return flush_imsg(ibuf
);
2811 const struct got_error
*
2812 got_privsep_send_object_enumeration_done(struct imsgbuf
*ibuf
)
2814 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_DONE
,
2815 0, 0, -1, NULL
, 0) == -1)
2816 return got_error_from_errno("imsg_compose "
2817 "OBJECT_ENUMERATION_DONE");
2819 return flush_imsg(ibuf
);
2822 const struct got_error
*
2823 got_privsep_send_object_enumeration_incomplete(struct imsgbuf
*ibuf
)
2825 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
,
2826 0, 0, -1, NULL
, 0) == -1)
2827 return got_error_from_errno("imsg_compose "
2828 "OBJECT_ENUMERATION_INCOMPLETE");
2830 return flush_imsg(ibuf
);
2833 const struct got_error
*
2834 got_privsep_send_enumerated_commit(struct imsgbuf
*ibuf
,
2835 struct got_object_id
*id
, time_t mtime
)
2839 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_COMMIT
, 0, 0,
2840 sizeof(struct got_imsg_enumerated_commit
));
2842 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2844 /* Keep in sync with struct got_imsg_enumerated_commit! */
2845 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2846 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2847 if (imsg_add(wbuf
, &mtime
, sizeof(mtime
)) == -1)
2848 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2850 imsg_close(ibuf
, wbuf
);
2851 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2855 const struct got_error
*
2856 got_privsep_recv_enumerated_objects(int *found_all_objects
,
2857 struct imsgbuf
*ibuf
,
2858 got_object_enumerate_commit_cb cb_commit
,
2859 got_object_enumerate_tree_cb cb_tree
, void *cb_arg
,
2860 struct got_repository
*repo
)
2862 const struct got_error
*err
= NULL
;
2864 struct got_imsg_enumerated_commit
*icommit
= NULL
;
2865 struct got_object_id commit_id
;
2866 int have_commit
= 0;
2868 struct got_tree_object tree
;
2869 struct got_imsg_enumerated_tree
*itree
;
2870 struct got_object_id tree_id
;
2871 char *path
= NULL
, *canon_path
= NULL
;
2872 size_t datalen
, path_len
;
2876 *found_all_objects
= 0;
2877 memset(&tree
, 0, sizeof(tree
));
2880 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2884 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2885 switch (imsg
.hdr
.type
) {
2886 case GOT_IMSG_ENUMERATED_COMMIT
:
2887 if (have_commit
&& nentries
!= -1) {
2888 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2891 if (datalen
!= sizeof(*icommit
)) {
2892 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2895 icommit
= (struct got_imsg_enumerated_commit
*)imsg
.data
;
2896 memcpy(&commit_id
, &icommit
->id
, sizeof(commit_id
));
2897 mtime
= icommit
->mtime
;
2900 case GOT_IMSG_ENUMERATED_TREE
:
2901 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2903 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2906 if (datalen
< sizeof(*itree
)) {
2907 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2911 path_len
= datalen
- sizeof(*itree
);
2912 if (path_len
== 0) {
2913 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2916 memcpy(&tree_id
, &itree
->id
, sizeof(tree_id
));
2918 path
= strndup(imsg
.data
+ sizeof(*itree
), path_len
);
2920 err
= got_error_from_errno("strndup");
2924 canon_path
= malloc(path_len
+ 1);
2925 if (canon_path
== NULL
) {
2926 err
= got_error_from_errno("malloc");
2929 if (!got_path_is_absolute(path
)) {
2930 err
= got_error(GOT_ERR_BAD_PATH
);
2933 if (got_path_is_root_dir(path
)) {
2934 /* XXX check what got_canonpath() does wrong */
2935 canon_path
[0] = '/';
2936 canon_path
[1] = '\0';
2938 err
= got_canonpath(path
, canon_path
,
2943 if (strcmp(path
, canon_path
) != 0) {
2944 err
= got_error(GOT_ERR_BAD_PATH
);
2947 if (nentries
!= -1) {
2948 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2951 if (itree
->nentries
< -1) {
2952 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2955 if (itree
->nentries
== -1) {
2956 /* Tree was not found in pack file. */
2957 err
= cb_tree(cb_arg
, NULL
, mtime
, &tree_id
,
2961 if (itree
->nentries
> INT_MAX
) {
2962 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2965 tree
.entries
= calloc(itree
->nentries
,
2966 sizeof(struct got_tree_entry
));
2967 if (tree
.entries
== NULL
) {
2968 err
= got_error_from_errno("calloc");
2971 if (itree
->nentries
== 0) {
2972 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2977 /* Prepare for next tree. */
2979 memset(&tree
, 0, sizeof(tree
));
2982 tree
.nentries
= itree
->nentries
;
2986 case GOT_IMSG_TREE_ENTRIES
:
2987 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2988 if (nentries
<= -1) {
2989 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2992 err
= recv_tree_entries(imsg
.data
, datalen
,
2996 if (tree
.nentries
== nentries
) {
2997 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
3002 /* Prepare for next tree. */
3004 memset(&tree
, 0, sizeof(tree
));
3008 case GOT_IMSG_TREE_ENUMERATION_DONE
:
3009 /* All trees have been found and traversed. */
3010 if (!have_commit
|| path
== NULL
|| nentries
!= -1) {
3011 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3014 err
= cb_commit(cb_arg
, mtime
, &commit_id
, repo
);
3019 case GOT_IMSG_OBJECT_ENUMERATION_DONE
:
3020 *found_all_objects
= 1;
3023 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
:
3027 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3042 const struct got_error
*
3043 got_privsep_send_raw_delta_req(struct imsgbuf
*ibuf
, int idx
,
3044 struct got_object_id
*id
)
3046 struct got_imsg_raw_delta_request dreq
;
3048 memset(&dreq
, 0, sizeof(dreq
));
3050 memcpy(&dreq
.id
, id
, sizeof(dreq
.id
));
3052 if (imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA_REQUEST
, 0, 0, -1,
3053 &dreq
, sizeof(dreq
)) == -1)
3054 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
3056 return flush_imsg(ibuf
);
3059 const struct got_error
*
3060 got_privsep_send_raw_delta_outfd(struct imsgbuf
*ibuf
, int fd
)
3062 return send_fd(ibuf
, GOT_IMSG_RAW_DELTA_OUTFD
, fd
);
3065 const struct got_error
*
3066 got_privsep_send_raw_delta(struct imsgbuf
*ibuf
, uint64_t base_size
,
3067 uint64_t result_size
, off_t delta_size
, off_t delta_compressed_size
,
3068 off_t delta_offset
, off_t delta_out_offset
, struct got_object_id
*base_id
)
3070 struct got_imsg_raw_delta idelta
;
3073 memset(&idelta
, 0, sizeof(idelta
));
3074 idelta
.base_size
= base_size
;
3075 idelta
.result_size
= result_size
;
3076 idelta
.delta_size
= delta_size
;
3077 idelta
.delta_compressed_size
= delta_compressed_size
;
3078 idelta
.delta_offset
= delta_offset
;
3079 idelta
.delta_out_offset
= delta_out_offset
;
3080 memcpy(&idelta
.base_id
, &base_id
, sizeof(idelta
.base_id
));
3082 ret
= imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA
, 0, 0, -1,
3083 &idelta
, sizeof(idelta
));
3085 return got_error_from_errno("imsg_compose RAW_DELTA");
3087 return flush_imsg(ibuf
);
3090 const struct got_error
*
3091 got_privsep_recv_raw_delta(uint64_t *base_size
, uint64_t *result_size
,
3092 off_t
*delta_size
, off_t
*delta_compressed_size
, off_t
*delta_offset
,
3093 off_t
*delta_out_offset
, struct got_object_id
**base_id
,
3094 struct imsgbuf
*ibuf
)
3096 const struct got_error
*err
= NULL
;
3098 struct got_imsg_raw_delta
*delta
;
3104 *delta_compressed_size
= 0;
3106 *delta_out_offset
= 0;
3109 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3113 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3115 switch (imsg
.hdr
.type
) {
3116 case GOT_IMSG_RAW_DELTA
:
3117 if (datalen
!= sizeof(*delta
)) {
3118 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3122 *base_size
= delta
->base_size
;
3123 *result_size
= delta
->result_size
;
3124 *delta_size
= delta
->delta_size
;
3125 *delta_compressed_size
= delta
->delta_compressed_size
;
3126 *delta_offset
= delta
->delta_offset
;
3127 *delta_out_offset
= delta
->delta_out_offset
;
3128 *base_id
= calloc(1, sizeof(**base_id
));
3129 if (*base_id
== NULL
) {
3130 err
= got_error_from_errno("malloc");
3133 memcpy(*base_id
, &delta
->base_id
, sizeof(**base_id
));
3136 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3149 static const struct got_error
*
3150 send_idlist(struct imsgbuf
*ibuf
, struct got_object_id
**ids
, size_t nids
)
3152 const struct got_error
*err
= NULL
;
3153 struct got_imsg_object_idlist idlist
;
3157 memset(&idlist
, 0, sizeof(idlist
));
3159 if (nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
)
3160 return got_error(GOT_ERR_NO_SPACE
);
3162 wbuf
= imsg_create(ibuf
, GOT_IMSG_OBJ_ID_LIST
, 0, 0,
3163 sizeof(idlist
) + nids
* sizeof(**ids
));
3165 err
= got_error_from_errno("imsg_create OBJ_ID_LIST");
3170 if (imsg_add(wbuf
, &idlist
, sizeof(idlist
)) == -1)
3171 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3173 for (i
= 0; i
< nids
; i
++) {
3174 struct got_object_id
*id
= ids
[i
];
3175 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
3176 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3179 imsg_close(ibuf
, wbuf
);
3181 return flush_imsg(ibuf
);
3184 const struct got_error
*
3185 got_privsep_send_object_idlist(struct imsgbuf
*ibuf
,
3186 struct got_object_id
**ids
, size_t nids
)
3188 const struct got_error
*err
= NULL
;
3189 struct got_object_id
*idlist
[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
];
3192 for (i
= 0; i
< nids
; i
++) {
3193 idlist
[i
% nitems(idlist
)] = ids
[i
];
3195 if (queued
>= nitems(idlist
)) {
3196 err
= send_idlist(ibuf
, idlist
, queued
);
3204 err
= send_idlist(ibuf
, idlist
, queued
);
3212 const struct got_error
*
3213 got_privsep_send_object_idlist_done(struct imsgbuf
*ibuf
)
3215 if (imsg_compose(ibuf
, GOT_IMSG_OBJ_ID_LIST_DONE
, 0, 0, -1, NULL
, 0)
3217 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3219 return flush_imsg(ibuf
);
3222 const struct got_error
*
3223 got_privsep_recv_object_idlist(int *done
, struct got_object_id
**ids
,
3224 size_t *nids
, struct imsgbuf
*ibuf
)
3226 const struct got_error
*err
= NULL
;
3228 struct got_imsg_object_idlist
*idlist
;
3235 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3239 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3240 switch (imsg
.hdr
.type
) {
3241 case GOT_IMSG_OBJ_ID_LIST
:
3242 if (datalen
< sizeof(*idlist
)) {
3243 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3247 if (idlist
->nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3248 idlist
->nids
* sizeof(**ids
) > datalen
- sizeof(*idlist
)) {
3249 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3252 *nids
= idlist
->nids
;
3253 *ids
= calloc(*nids
, sizeof(**ids
));
3255 err
= got_error_from_errno("calloc");
3258 memcpy(*ids
, (uint8_t *)imsg
.data
+ sizeof(*idlist
),
3259 *nids
* sizeof(**ids
));
3261 case GOT_IMSG_OBJ_ID_LIST_DONE
:
3265 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3274 const struct got_error
*
3275 got_privsep_send_delta_reuse_req(struct imsgbuf
*ibuf
)
3277 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_REQUEST
, 0, 0, -1, NULL
, 0)
3279 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3281 return flush_imsg(ibuf
);
3284 const struct got_error
*
3285 got_privsep_send_reused_deltas(struct imsgbuf
*ibuf
,
3286 struct got_imsg_reused_delta
*deltas
, size_t ndeltas
)
3288 const struct got_error
*err
= NULL
;
3290 struct got_imsg_reused_deltas ideltas
;
3293 memset(&ideltas
, 0, sizeof(ideltas
));
3295 if (ndeltas
> GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS
)
3296 return got_error(GOT_ERR_NO_SPACE
);
3298 wbuf
= imsg_create(ibuf
, GOT_IMSG_REUSED_DELTAS
, 0, 0,
3299 sizeof(ideltas
) + ndeltas
* sizeof(*deltas
));
3301 err
= got_error_from_errno("imsg_create REUSED_DELTAS");
3305 ideltas
.ndeltas
= ndeltas
;
3306 if (imsg_add(wbuf
, &ideltas
, sizeof(ideltas
)) == -1)
3307 return got_error_from_errno("imsg_add REUSED_DELTAS");
3309 for (i
= 0; i
< ndeltas
; i
++) {
3310 struct got_imsg_reused_delta
*delta
= &deltas
[i
];
3311 if (imsg_add(wbuf
, delta
, sizeof(*delta
)) == -1)
3312 return got_error_from_errno("imsg_add REUSED_DELTAS");
3315 imsg_close(ibuf
, wbuf
);
3317 return flush_imsg(ibuf
);
3320 const struct got_error
*
3321 got_privsep_send_reused_deltas_done(struct imsgbuf
*ibuf
)
3323 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_DONE
, 0, 0, -1, NULL
, 0)
3325 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3327 return flush_imsg(ibuf
);
3330 const struct got_error
*
3331 got_privsep_recv_reused_deltas(int *done
, struct got_imsg_reused_delta
*deltas
,
3332 size_t *ndeltas
, struct imsgbuf
*ibuf
)
3334 const struct got_error
*err
= NULL
;
3336 struct got_imsg_reused_deltas
*ideltas
;
3342 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3346 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3347 switch (imsg
.hdr
.type
) {
3348 case GOT_IMSG_REUSED_DELTAS
:
3349 if (datalen
< sizeof(*ideltas
)) {
3350 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3353 ideltas
= imsg
.data
;
3354 if (ideltas
->ndeltas
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3355 ideltas
->ndeltas
* sizeof(*deltas
) >
3356 datalen
- sizeof(*ideltas
)) {
3357 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3360 *ndeltas
= ideltas
->ndeltas
;
3361 memcpy(deltas
, (uint8_t *)imsg
.data
+ sizeof(*ideltas
),
3362 *ndeltas
* sizeof(*deltas
));
3364 case GOT_IMSG_DELTA_REUSE_DONE
:
3368 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3377 const struct got_error
*
3378 got_privsep_init_commit_painting(struct imsgbuf
*ibuf
)
3380 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_INIT
,
3383 return got_error_from_errno("imsg_compose "
3384 "COMMIT_PAINTING_INIT");
3386 return flush_imsg(ibuf
);
3389 const struct got_error
*
3390 got_privsep_send_painting_request(struct imsgbuf
*ibuf
, int idx
,
3391 struct got_object_id
*id
, intptr_t color
)
3393 struct got_imsg_commit_painting_request ireq
;
3395 memset(&ireq
, 0, sizeof(ireq
));
3396 memcpy(&ireq
.id
, id
, sizeof(ireq
.id
));
3400 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_REQUEST
, 0, 0, -1,
3401 &ireq
, sizeof(ireq
)) == -1)
3402 return got_error_from_errno("imsg_compose "
3403 "COMMIT_PAINTING_REQUEST");
3405 return flush_imsg(ibuf
);
3408 static const struct got_error
*
3409 send_painted_commits(struct got_object_id_queue
*ids
, int *nids
,
3410 size_t remain
, int present_in_pack
, struct imsgbuf
*ibuf
)
3412 const struct got_error
*err
= NULL
;
3413 struct ibuf
*wbuf
= NULL
;
3414 struct got_object_qid
*qid
;
3419 msglen
= MIN(remain
, MAX_IMSGSIZE
- IMSG_HEADER_SIZE
);
3420 ncommits
= (msglen
- sizeof(struct got_imsg_painted_commits
)) /
3421 sizeof(struct got_imsg_painted_commit
);
3423 wbuf
= imsg_create(ibuf
, GOT_IMSG_PAINTED_COMMITS
, 0, 0, msglen
);
3425 err
= got_error_from_errno("imsg_create PAINTED_COMMITS");
3429 /* Keep in sync with struct got_imsg_painted_commits! */
3430 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1)
3431 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3432 if (imsg_add(wbuf
, &present_in_pack
, sizeof(present_in_pack
)) == -1)
3433 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3435 while (ncommits
> 0) {
3436 qid
= STAILQ_FIRST(ids
);
3437 STAILQ_REMOVE_HEAD(ids
, entry
);
3440 color
= (intptr_t)qid
->data
;
3442 /* Keep in sync with struct got_imsg_painted_commit! */
3443 if (imsg_add(wbuf
, &qid
->id
, sizeof(qid
->id
)) == -1)
3444 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3445 if (imsg_add(wbuf
, &color
, sizeof(color
)) == -1)
3446 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3448 got_object_qid_free(qid
);
3451 imsg_close(ibuf
, wbuf
);
3452 return flush_imsg(ibuf
);
3455 const struct got_error
*
3456 got_privsep_send_painted_commits(struct imsgbuf
*ibuf
,
3457 struct got_object_id_queue
*ids
, int *nids
,
3458 int present_in_pack
, int flush
)
3460 const struct got_error
*err
;
3467 remain
= (sizeof(struct got_imsg_painted_commits
)) +
3468 *nids
* sizeof(struct got_imsg_painted_commit
);
3469 if (flush
|| remain
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
3470 err
= send_painted_commits(ids
, nids
, remain
,
3471 present_in_pack
, ibuf
);
3475 } while (flush
&& *nids
> 0);
3480 const struct got_error
*
3481 got_privsep_send_painting_commits_done(struct imsgbuf
*ibuf
)
3483 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_DONE
,
3486 return got_error_from_errno("imsg_compose "
3487 "COMMIT_PAINTING_DONE");
3489 return flush_imsg(ibuf
);
3492 const struct got_error
*
3493 got_privsep_recv_painted_commits(struct got_object_id_queue
*new_ids
,
3494 got_privsep_recv_painted_commit_cb cb
, void *cb_arg
, struct imsgbuf
*ibuf
)
3496 const struct got_error
*err
= NULL
;
3498 struct got_imsg_painted_commits icommits
;
3499 struct got_imsg_painted_commit icommit
;
3504 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3508 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3509 if (imsg
.hdr
.type
== GOT_IMSG_COMMIT_PAINTING_DONE
) {
3513 if (imsg
.hdr
.type
!= GOT_IMSG_PAINTED_COMMITS
){
3515 return got_error(GOT_ERR_PRIVSEP_MSG
);
3518 if (datalen
< sizeof(icommits
)){
3520 return got_error(GOT_ERR_PRIVSEP_LEN
);
3522 memcpy(&icommits
, imsg
.data
, sizeof(icommits
));
3523 if (icommits
.ncommits
* sizeof(icommit
) < icommits
.ncommits
||
3524 datalen
< sizeof(icommits
) +
3525 icommits
.ncommits
* sizeof(icommit
)){
3527 return got_error(GOT_ERR_PRIVSEP_LEN
);
3530 for (i
= 0; i
< icommits
.ncommits
; i
++) {
3532 (uint8_t *)imsg
.data
+ sizeof(icommits
) + i
* sizeof(icommit
),
3535 if (icommits
.present_in_pack
) {
3536 struct got_object_id id
;
3537 memcpy(&id
, &icommit
.id
, sizeof(id
));
3538 err
= cb(cb_arg
, &id
, icommit
.color
);
3542 struct got_object_qid
*qid
;
3543 err
= got_object_qid_alloc_partial(&qid
);
3546 memcpy(&qid
->id
, &icommit
.id
,
3548 qid
->data
= (void *)icommit
.color
;
3549 STAILQ_INSERT_TAIL(new_ids
, qid
, entry
);
3559 const struct got_error
*
3560 got_privsep_unveil_exec_helpers(void)
3562 const char *helpers
[] = {
3563 GOT_PATH_PROG_READ_PACK
,
3564 GOT_PATH_PROG_READ_OBJECT
,
3565 GOT_PATH_PROG_READ_COMMIT
,
3566 GOT_PATH_PROG_READ_TREE
,
3567 GOT_PATH_PROG_READ_BLOB
,
3568 GOT_PATH_PROG_READ_TAG
,
3569 GOT_PATH_PROG_READ_GITCONFIG
,
3570 GOT_PATH_PROG_READ_GOTCONFIG
,
3571 GOT_PATH_PROG_READ_PATCH
,
3572 GOT_PATH_PROG_FETCH_PACK
,
3573 GOT_PATH_PROG_INDEX_PACK
,
3574 GOT_PATH_PROG_SEND_PACK
,
3575 /* GOT_PATH_PROG_FETCH_HTTP explicitly excluded */
3579 for (i
= 0; i
< nitems(helpers
); i
++) {
3580 if (unveil(helpers
[i
], "x") == 0)
3582 return got_error_from_errno2("unveil", helpers
[i
]);
3589 got_privsep_exec_child(int imsg_fds
[2], const char *path
, const char *repo_path
)
3591 if (close(imsg_fds
[0]) == -1) {
3592 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3596 if (dup2(imsg_fds
[1], GOT_IMSG_FD_CHILD
) == -1) {
3597 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3601 closefrom(GOT_IMSG_FD_CHILD
+ 1);
3603 if (execl(path
, path
, repo_path
, (char *)NULL
) == -1) {
3604 fprintf(stderr
, "%s: %s: %s\n", getprogname(), path
,