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>
36 #include "got_compat.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
);
76 n
= imsgbuf_read(ibuf
);
78 return got_error(GOT_ERR_PRIVSEP_READ
);
80 return got_error(GOT_ERR_PRIVSEP_PIPE
);
85 const struct got_error
*
86 got_privsep_wait_for_child(pid_t pid
)
90 if (waitpid(pid
, &child_status
, 0) == -1)
91 return got_error_from_errno("waitpid");
93 if (!WIFEXITED(child_status
))
94 return got_error(GOT_ERR_PRIVSEP_DIED
);
96 if (WEXITSTATUS(child_status
) != 0)
97 return got_error(GOT_ERR_PRIVSEP_EXIT
);
102 static const struct got_error
*
103 recv_imsg_error(struct imsg
*imsg
, size_t datalen
)
105 struct got_imsg_error
*ierr
;
107 if (datalen
!= sizeof(*ierr
))
108 return got_error(GOT_ERR_PRIVSEP_LEN
);
111 if (ierr
->code
== GOT_ERR_ERRNO
) {
112 static struct got_error serr
;
113 serr
.code
= GOT_ERR_ERRNO
;
114 serr
.msg
= strerror(ierr
->errno_code
);
118 return got_error(ierr
->code
);
121 const struct got_error
*
122 got_privsep_recv_imsg(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
125 const struct got_error
*err
;
128 n
= imsg_get(ibuf
, imsg
);
130 return got_error_from_errno("imsg_get");
133 err
= read_imsg(ibuf
);
136 n
= imsg_get(ibuf
, imsg
);
138 return got_error_from_errno("imsg_get");
141 if (imsg
->hdr
.type
== GOT_IMSG_ERROR
) {
142 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
143 err
= recv_imsg_error(imsg
, datalen
);
148 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
) {
150 return got_error(GOT_ERR_PRIVSEP_LEN
);
156 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
158 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
160 const struct got_error
*poll_err
;
161 struct got_imsg_error ierr
;
164 ierr
.code
= err
->code
;
165 if (err
->code
== GOT_ERR_ERRNO
)
166 ierr
.errno_code
= errno
;
169 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
171 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
172 getprogname(), err
->code
, err
->msg
, strerror(errno
));
176 poll_err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
178 if (poll_err
->code
!= GOT_ERR_EOF
)
179 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
180 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
184 ret
= imsgbuf_flush(ibuf
);
186 fprintf(stderr
, "%s: error %d \"%s\": imsgbuf_flush: %s\n",
187 getprogname(), err
->code
, err
->msg
, strerror(errno
));
192 static const struct got_error
*
193 flush_imsg(struct imsgbuf
*ibuf
)
195 const struct got_error
*err
;
197 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
201 if (imsgbuf_flush(ibuf
) == -1)
202 return got_error_from_errno("imsgbuf_flush");
207 const struct got_error
*
208 got_privsep_flush_imsg(struct imsgbuf
*ibuf
)
210 return flush_imsg(ibuf
);
213 const struct got_error
*
214 got_privsep_send_stop(int fd
)
216 const struct got_error
*err
= NULL
;
219 if (imsgbuf_init(&ibuf
, fd
) == -1)
220 return got_error_from_errno("imsgbuf_init");
222 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1) {
223 err
= got_error_from_errno("imsg_compose STOP");
227 err
= flush_imsg(&ibuf
);
229 imsgbuf_clear(&ibuf
);
233 const struct got_error
*
234 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
235 struct got_object_id
*id
)
237 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
238 id
, sizeof(*id
)) == -1)
239 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
241 return flush_imsg(ibuf
);
244 const struct got_error
*
245 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
246 struct got_object_id
*id
)
248 const struct got_error
*err
;
250 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
251 id
, sizeof(*id
)) == -1) {
252 err
= got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
257 return flush_imsg(ibuf
);
260 const struct got_error
*
261 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
263 const struct got_error
*err
= NULL
;
265 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
267 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
272 return flush_imsg(ibuf
);
275 const struct got_error
*
276 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
279 struct got_imsg_raw_obj iobj
;
280 size_t len
= sizeof(iobj
);
283 memset(&iobj
, 0, sizeof(iobj
));
284 iobj
.hdrlen
= hdrlen
;
287 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
288 len
+= (size_t)size
+ hdrlen
;
290 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
292 return got_error_from_errno("imsg_create RAW_OBJECT");
294 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1)
295 return got_error_from_errno("imsg_add RAW_OBJECT");
297 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
298 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1)
299 return got_error_from_errno("imsg_add RAW_OBJECT");
302 imsg_close(ibuf
, wbuf
);
303 return flush_imsg(ibuf
);
306 const struct got_error
*
307 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
308 struct imsgbuf
*ibuf
)
310 const struct got_error
*err
= NULL
;
312 struct got_imsg_raw_obj
*iobj
;
317 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
321 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
323 switch (imsg
.hdr
.type
) {
324 case GOT_IMSG_RAW_OBJECT
:
325 if (datalen
< sizeof(*iobj
)) {
326 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
331 *hdrlen
= iobj
->hdrlen
;
333 if (datalen
== sizeof(*iobj
)) {
334 /* Data has been written to file descriptor. */
339 *size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
340 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
344 *outbuf
= malloc(*size
+ *hdrlen
);
345 if (*outbuf
== NULL
) {
346 err
= got_error_from_errno("malloc");
349 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
352 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
361 const struct got_error
*
362 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
363 struct got_object_id
*id
, int pack_idx
)
365 const struct got_error
*err
= NULL
;
366 struct got_imsg_packed_object iobj
;
370 memset(&iobj
, 0, sizeof(iobj
));
371 if (pack_idx
!= -1) { /* commit is packed */
373 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
381 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
383 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
388 return flush_imsg(ibuf
);
391 const struct got_error
*
392 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
393 struct got_object_id
*id
, int pack_idx
)
395 const struct got_error
*err
;
400 len
= sizeof(struct got_imsg_packed_object
);
404 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
406 err
= got_error_from_errno("imsg_create TREE_REQUEST");
412 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1) {
413 err
= got_error_from_errno("imsg_add TREE_REQUEST");
419 if (pack_idx
!= -1) { /* tree is packed */
420 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1) {
421 err
= got_error_from_errno("imsg_add TREE_REQUEST");
428 ibuf_fd_set(wbuf
, fd
);
429 imsg_close(ibuf
, wbuf
);
431 return flush_imsg(ibuf
);
434 const struct got_error
*
435 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
436 struct got_object_id
*id
, int pack_idx
)
438 const struct got_error
*err
;
439 struct got_imsg_packed_object iobj
;
443 memset(&iobj
, 0, sizeof(iobj
));
444 if (pack_idx
!= -1) { /* tag is packed */
446 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
454 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
456 err
= got_error_from_errno("imsg_compose TAG_REQUEST");
462 return flush_imsg(ibuf
);
465 const struct got_error
*
466 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
467 struct got_object_id
*id
, int pack_idx
)
469 const struct got_error
*err
= NULL
;
470 struct got_imsg_packed_object iobj
;
474 memset(&iobj
, 0, sizeof(iobj
));
475 if (pack_idx
!= -1) { /* blob is packed */
477 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
485 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
487 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
492 return flush_imsg(ibuf
);
495 const struct got_error
*
496 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
498 const struct got_error
*err
= NULL
;
500 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
502 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
507 return flush_imsg(ibuf
);
510 static const struct got_error
*
511 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
513 const struct got_error
*err
= NULL
;
515 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
516 err
= got_error_from_errno("imsg_compose TMPFD");
521 return flush_imsg(ibuf
);
524 const struct got_error
*
525 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
527 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
530 const struct got_error
*
531 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
533 struct got_imsg_object iobj
;
535 memset(&iobj
, 0, sizeof(iobj
));
537 memcpy(&iobj
.id
, &obj
->id
, sizeof(iobj
.id
));
538 iobj
.type
= obj
->type
;
539 iobj
.flags
= obj
->flags
;
540 iobj
.hdrlen
= obj
->hdrlen
;
541 iobj
.size
= obj
->size
;
542 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
543 iobj
.pack_offset
= obj
->pack_offset
;
544 iobj
.pack_idx
= obj
->pack_idx
;
547 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
549 return got_error_from_errno("imsg_compose OBJECT");
551 return flush_imsg(ibuf
);
554 const struct got_error
*
555 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
556 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
557 struct got_pathlist_head
*wanted_branches
,
558 struct got_pathlist_head
*wanted_refs
, int list_refs_only
,
559 const char *worktree_branch
, const char *remote_head
,
560 int no_head
, int verbosity
)
562 const struct got_error
*err
= NULL
;
564 struct got_pathlist_entry
*pe
;
565 struct got_imsg_fetch_request fetchreq
;
566 size_t remote_head_len
, worktree_branch_len
, len
= sizeof(fetchreq
);
568 if (worktree_branch
) {
569 worktree_branch_len
= strlen(worktree_branch
);
570 len
+= worktree_branch_len
;
573 remote_head_len
= strlen(remote_head
);
574 len
+= remote_head_len
;
577 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
579 return got_error(GOT_ERR_NO_SPACE
);
582 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, len
);
584 err
= got_error_from_errno("imsg_create FETCH_HAVE_REF");
589 memset(&fetchreq
, 0, sizeof(fetchreq
));
590 fetchreq
.no_head
= no_head
;
591 fetchreq
.fetch_all_branches
= fetch_all_branches
;
592 fetchreq
.list_refs_only
= list_refs_only
;
593 fetchreq
.verbosity
= verbosity
;
594 if (worktree_branch
!= NULL
)
595 fetchreq
.worktree_branch_len
= worktree_branch_len
;
596 if (remote_head
!= NULL
)
597 fetchreq
.remote_head_len
= remote_head_len
;
598 RB_FOREACH(pe
, got_pathlist_head
, have_refs
)
599 fetchreq
.n_have_refs
++;
600 RB_FOREACH(pe
, got_pathlist_head
, wanted_branches
)
601 fetchreq
.n_wanted_branches
++;
602 RB_FOREACH(pe
, got_pathlist_head
, wanted_refs
)
603 fetchreq
.n_wanted_refs
++;
604 if (imsg_add(wbuf
, &fetchreq
, sizeof(fetchreq
)) == -1)
605 return got_error_from_errno("imsg_add FETCH_REQUEST");
606 if (worktree_branch
) {
607 if (imsg_add(wbuf
, worktree_branch
, worktree_branch_len
)
609 err
= got_error_from_errno("imsg_add FETCH_REQUEST");
615 if (imsg_add(wbuf
, remote_head
, remote_head_len
) == -1) {
616 err
= got_error_from_errno("imsg_add FETCH_REQUEST");
621 ibuf_fd_set(wbuf
, fd
);
623 imsg_close(ibuf
, wbuf
);
625 err
= flush_imsg(ibuf
);
629 RB_FOREACH(pe
, got_pathlist_head
, have_refs
) {
630 const char *name
= pe
->path
;
631 size_t name_len
= pe
->path_len
;
632 struct got_object_id
*id
= pe
->data
;
634 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
635 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
637 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
639 /* Keep in sync with struct got_imsg_fetch_have_ref! */
640 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
641 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
642 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
643 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
644 if (imsg_add(wbuf
, name
, name_len
) == -1)
645 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
647 imsg_close(ibuf
, wbuf
);
648 err
= flush_imsg(ibuf
);
653 RB_FOREACH(pe
, got_pathlist_head
, wanted_branches
) {
654 const char *name
= pe
->path
;
655 size_t name_len
= pe
->path_len
;
657 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
658 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
661 return got_error_from_errno(
662 "imsg_create FETCH_WANTED_BRANCH");
664 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
665 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
666 return got_error_from_errno(
667 "imsg_add FETCH_WANTED_BRANCH");
668 if (imsg_add(wbuf
, name
, name_len
) == -1)
669 return got_error_from_errno(
670 "imsg_add FETCH_WANTED_BRANCH");
672 imsg_close(ibuf
, wbuf
);
673 err
= flush_imsg(ibuf
);
678 RB_FOREACH(pe
, got_pathlist_head
, wanted_refs
) {
679 const char *name
= pe
->path
;
680 size_t name_len
= pe
->path_len
;
682 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
683 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
686 return got_error_from_errno(
687 "imsg_create FETCH_WANTED_REF");
689 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
690 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
691 return got_error_from_errno(
692 "imsg_add FETCH_WANTED_REF");
693 if (imsg_add(wbuf
, name
, name_len
) == -1)
694 return got_error_from_errno(
695 "imsg_add FETCH_WANTED_REF");
697 imsg_close(ibuf
, wbuf
);
698 err
= flush_imsg(ibuf
);
706 const struct got_error
*
707 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
709 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
712 const struct got_error
*
713 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
714 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
715 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
717 const struct got_error
*err
= NULL
;
720 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
722 struct got_pathlist_entry
*new;
729 *server_progress
= NULL
;
731 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
733 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
737 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
738 switch (imsg
.hdr
.type
) {
739 case GOT_IMSG_FETCH_SYMREFS
:
740 if (datalen
< sizeof(*isymrefs
)) {
741 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
744 if (isymrefs
!= NULL
) {
745 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
748 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
749 off
= sizeof(*isymrefs
);
750 remain
= datalen
- off
;
751 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
752 struct got_imsg_fetch_symref
*s
;
754 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
755 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
758 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
760 remain
-= sizeof(*s
);
761 if (remain
< s
->name_len
) {
762 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
765 name
= strndup(imsg
.data
+ off
, s
->name_len
);
767 err
= got_error_from_errno("strndup");
771 remain
-= s
->name_len
;
772 if (remain
< s
->target_len
) {
773 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
777 target
= strndup(imsg
.data
+ off
, s
->target_len
);
778 if (target
== NULL
) {
779 err
= got_error_from_errno("strndup");
783 off
+= s
->target_len
;
784 remain
-= s
->target_len
;
785 err
= got_pathlist_insert(&new, symrefs
, name
, target
);
786 if (err
|| new == NULL
) {
789 if (err
->code
!= GOT_ERR_REF_DUP_ENTRY
)
794 case GOT_IMSG_FETCH_REF
:
795 if (datalen
<= sizeof(**id
)) {
796 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
799 *id
= malloc(sizeof(**id
));
801 err
= got_error_from_errno("malloc");
804 memcpy(*id
, imsg
.data
, sizeof(**id
));
805 *refname
= strndup(imsg
.data
+ sizeof(**id
),
806 datalen
- sizeof(**id
));
807 if (*refname
== NULL
) {
808 err
= got_error_from_errno("strndup");
812 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
814 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
817 *server_progress
= strndup(imsg
.data
, datalen
);
818 if (*server_progress
== NULL
) {
819 err
= got_error_from_errno("strndup");
822 for (i
= 0; i
< datalen
; i
++) {
823 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
824 !isspace((unsigned char)(*server_progress
)[i
])) {
825 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
826 free(*server_progress
);
827 *server_progress
= NULL
;
832 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
833 if (datalen
< sizeof(*packfile_size
)) {
834 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
837 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
839 case GOT_IMSG_FETCH_DONE
:
840 if (datalen
!= SHA1_DIGEST_LENGTH
) {
841 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
844 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
848 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
862 static const struct got_error
*
863 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
864 int delete, struct imsgbuf
*ibuf
)
869 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
870 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
872 return got_error_from_errno("imsg_create SEND_REF");
874 /* Keep in sync with struct got_imsg_send_ref! */
875 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
876 return got_error_from_errno("imsg_add SEND_REF");
877 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1)
878 return got_error_from_errno("imsg_add SEND_REF");
879 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
880 return got_error_from_errno("imsg_add SEND_REF");
881 if (imsg_add(wbuf
, name
, name_len
) == -1)
882 return got_error_from_errno("imsg_add SEND_REF");
884 imsg_close(ibuf
, wbuf
);
885 return flush_imsg(ibuf
);
888 const struct got_error
*
889 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
890 struct got_pathlist_head
*have_refs
,
891 struct got_pathlist_head
*delete_refs
,
894 const struct got_error
*err
= NULL
;
895 struct got_pathlist_entry
*pe
;
896 struct got_imsg_send_request sendreq
;
897 struct got_object_id zero_id
;
899 memset(&zero_id
, 0, sizeof(zero_id
));
900 memset(&sendreq
, 0, sizeof(sendreq
));
901 sendreq
.verbosity
= verbosity
;
902 RB_FOREACH(pe
, got_pathlist_head
, have_refs
)
904 RB_FOREACH(pe
, got_pathlist_head
, delete_refs
)
906 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
907 &sendreq
, sizeof(sendreq
)) == -1) {
908 err
= got_error_from_errno(
909 "imsg_compose FETCH_SERVER_PROGRESS");
914 err
= flush_imsg(ibuf
);
918 RB_FOREACH(pe
, got_pathlist_head
,have_refs
) {
919 const char *name
= pe
->path
;
920 size_t name_len
= pe
->path_len
;
921 struct got_object_id
*id
= pe
->data
;
922 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
927 RB_FOREACH(pe
, got_pathlist_head
, delete_refs
) {
928 const char *name
= pe
->path
;
929 size_t name_len
= pe
->path_len
;
930 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
935 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
936 err
= got_error_from_errno("close");
940 const struct got_error
*
941 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
942 struct imsgbuf
*ibuf
)
944 const struct got_error
*err
= NULL
;
947 struct got_imsg_send_remote_ref iremote_ref
;
948 struct got_object_id
*id
= NULL
;
949 char *refname
= NULL
;
950 struct got_pathlist_entry
*new;
953 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
956 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
957 switch (imsg
.hdr
.type
) {
958 case GOT_IMSG_SEND_REMOTE_REF
:
959 if (datalen
< sizeof(iremote_ref
)) {
960 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
963 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
964 if (datalen
!= sizeof(iremote_ref
) +
965 iremote_ref
.name_len
) {
966 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
969 id
= malloc(sizeof(*id
));
971 err
= got_error_from_errno("malloc");
974 memcpy(id
, &iremote_ref
.id
, sizeof(*id
));
975 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
976 datalen
- sizeof(iremote_ref
));
977 if (refname
== NULL
) {
978 err
= got_error_from_errno("strndup");
981 err
= got_pathlist_insert(&new, remote_refs
,
985 if (new == NULL
) { /* duplicate which wasn't inserted */
993 case GOT_IMSG_SEND_PACK_REQUEST
:
995 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
998 /* got-send-pack is now waiting for a pack file. */
1001 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1012 const struct got_error
*
1013 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
1015 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
1018 const struct got_error
*
1019 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
1020 int *success
, char **refname
, char **errmsg
, struct imsgbuf
*ibuf
)
1022 const struct got_error
*err
= NULL
;
1025 struct got_imsg_send_ref_status iref_status
;
1027 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1033 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1037 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1038 switch (imsg
.hdr
.type
) {
1039 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
1040 if (datalen
< sizeof(*bytes_sent
)) {
1041 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1044 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
1046 case GOT_IMSG_SEND_REF_STATUS
:
1047 if (datalen
< sizeof(iref_status
)) {
1048 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1051 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
1052 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
+
1053 iref_status
.errmsg_len
) {
1054 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1057 *success
= iref_status
.success
;
1058 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1059 iref_status
.name_len
);
1061 if (iref_status
.errmsg_len
!= 0)
1062 *errmsg
= strndup(imsg
.data
+ sizeof(iref_status
) +
1063 iref_status
.name_len
, iref_status
.errmsg_len
);
1065 case GOT_IMSG_SEND_DONE
:
1067 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1073 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1081 const struct got_error
*
1082 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, struct got_object_id
*id
,
1085 const struct got_error
*err
= NULL
;
1087 /* Keep in sync with struct got_imsg_index_pack_request */
1088 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1089 id
, sizeof(*id
)) == -1) {
1090 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1094 return flush_imsg(ibuf
);
1097 const struct got_error
*
1098 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1100 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1103 const struct got_error
*
1104 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1105 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1106 struct imsgbuf
*ibuf
)
1108 const struct got_error
*err
= NULL
;
1110 struct got_imsg_index_pack_progress
*iprogress
;
1118 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1122 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1123 switch (imsg
.hdr
.type
) {
1124 case GOT_IMSG_IDXPACK_PROGRESS
:
1125 if (datalen
< sizeof(*iprogress
)) {
1126 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1129 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1130 if (iprogress
->nobj_total
< 0 || iprogress
->nobj_indexed
< 0 ||
1131 iprogress
->nobj_loose
< 0 || iprogress
->nobj_resolved
< 0) {
1132 err
= got_error(GOT_ERR_RANGE
);
1135 *nobj_total
= iprogress
->nobj_total
;
1136 *nobj_indexed
= iprogress
->nobj_indexed
;
1137 *nobj_loose
= iprogress
->nobj_loose
;
1138 *nobj_resolved
= iprogress
->nobj_resolved
;
1140 case GOT_IMSG_IDXPACK_DONE
:
1142 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1148 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1156 const struct got_error
*
1157 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1158 struct imsgbuf
*ibuf
)
1160 struct got_imsg_object
*iobj
;
1161 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1163 if (datalen
!= sizeof(*iobj
))
1164 return got_error(GOT_ERR_PRIVSEP_LEN
);
1167 if (iobj
->pack_offset
< 0)
1168 return got_error(GOT_ERR_PACK_OFFSET
);
1170 *obj
= calloc(1, sizeof(**obj
));
1172 return got_error_from_errno("calloc");
1174 memcpy(&(*obj
)->id
, &iobj
->id
, sizeof(iobj
->id
));
1175 (*obj
)->type
= iobj
->type
;
1176 (*obj
)->flags
= iobj
->flags
;
1177 (*obj
)->hdrlen
= iobj
->hdrlen
;
1178 (*obj
)->size
= iobj
->size
;
1179 /* path_packfile is handled by caller */
1180 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1181 (*obj
)->pack_offset
= iobj
->pack_offset
;
1182 (*obj
)->pack_idx
= iobj
->pack_idx
;
1184 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1188 const struct got_error
*
1189 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1191 const struct got_error
*err
= NULL
;
1193 const size_t min_datalen
= sizeof(struct got_imsg_object
);
1197 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1201 switch (imsg
.hdr
.type
) {
1202 case GOT_IMSG_OBJECT
:
1203 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1206 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1215 static const struct got_error
*
1216 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1219 const struct got_error
*err
= NULL
;
1220 size_t offset
, remain
;
1223 remain
= logmsg_len
;
1224 while (remain
> 0) {
1225 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1227 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1228 commit
->logmsg
+ offset
, n
) == -1) {
1229 err
= got_error_from_errno("imsg_compose "
1234 err
= flush_imsg(ibuf
);
1245 const struct got_error
*
1246 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1248 const struct got_error
*err
= NULL
;
1249 struct got_imsg_commit_object
*icommit
;
1252 struct got_object_qid
*qid
;
1253 size_t author_len
= strlen(commit
->author
);
1254 size_t committer_len
= strlen(commit
->committer
);
1255 size_t logmsg_len
= strlen(commit
->logmsg
);
1257 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1258 commit
->nparents
* sizeof(struct got_object_id
);
1260 buf
= malloc(total
);
1262 return got_error_from_errno("malloc");
1264 icommit
= (struct got_imsg_commit_object
*)buf
;
1265 memcpy(&icommit
->tree_id
, commit
->tree_id
, sizeof(icommit
->tree_id
));
1266 icommit
->author_len
= author_len
;
1267 icommit
->author_time
= commit
->author_time
;
1268 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1269 icommit
->committer_len
= committer_len
;
1270 icommit
->committer_time
= commit
->committer_time
;
1271 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1272 icommit
->logmsg_len
= logmsg_len
;
1273 icommit
->nparents
= commit
->nparents
;
1275 len
= sizeof(*icommit
);
1276 memcpy(buf
+ len
, commit
->author
, author_len
);
1278 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1279 len
+= committer_len
;
1280 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1281 memcpy(buf
+ len
, &qid
->id
, sizeof(qid
->id
));
1282 len
+= sizeof(qid
->id
);
1285 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1286 err
= got_error_from_errno("imsg_compose COMMIT");
1290 if (logmsg_len
== 0 ||
1291 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1292 err
= flush_imsg(ibuf
);
1296 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1302 static const struct got_error
*
1303 get_commit_from_imsg(struct got_commit_object
**commit
,
1304 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1306 const struct got_error
*err
= NULL
;
1307 struct got_imsg_commit_object
*icommit
;
1311 if (datalen
< sizeof(*icommit
))
1312 return got_error(GOT_ERR_PRIVSEP_LEN
);
1314 icommit
= imsg
->data
;
1315 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1316 icommit
->committer_len
+
1317 icommit
->nparents
* sizeof(struct got_object_id
))
1318 return got_error(GOT_ERR_PRIVSEP_LEN
);
1320 if (icommit
->nparents
< 0)
1321 return got_error(GOT_ERR_PRIVSEP_LEN
);
1323 len
+= sizeof(*icommit
);
1325 *commit
= got_object_commit_alloc_partial();
1326 if (*commit
== NULL
)
1327 return got_error_from_errno(
1328 "got_object_commit_alloc_partial");
1330 memcpy((*commit
)->tree_id
, &icommit
->tree_id
,
1331 sizeof(icommit
->tree_id
));
1332 (*commit
)->author_time
= icommit
->author_time
;
1333 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1334 (*commit
)->committer_time
= icommit
->committer_time
;
1335 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1337 (*commit
)->author
= strndup(imsg
->data
+ len
, icommit
->author_len
);
1338 if ((*commit
)->author
== NULL
) {
1339 err
= got_error_from_errno("strndup");
1342 len
+= icommit
->author_len
;
1344 (*commit
)->committer
= strndup(imsg
->data
+ len
,
1345 icommit
->committer_len
);
1346 if ((*commit
)->committer
== NULL
) {
1347 err
= got_error_from_errno("strndup");
1350 len
+= icommit
->committer_len
;
1352 if (icommit
->logmsg_len
== 0) {
1353 (*commit
)->logmsg
= strdup("");
1354 if ((*commit
)->logmsg
== NULL
) {
1355 err
= got_error_from_errno("strdup");
1359 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1361 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1362 if ((*commit
)->logmsg
== NULL
) {
1363 err
= got_error_from_errno("malloc");
1366 while (remain
> 0) {
1367 struct imsg imsg_log
;
1368 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1371 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1375 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1376 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1380 memcpy((*commit
)->logmsg
+ offset
,
1382 imsg_free(&imsg_log
);
1386 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1389 for (i
= 0; i
< icommit
->nparents
; i
++) {
1390 struct got_object_qid
*qid
;
1392 err
= got_object_qid_alloc_partial(&qid
);
1395 memcpy(&qid
->id
, imsg
->data
+ len
+
1396 i
* sizeof(qid
->id
), sizeof(qid
->id
));
1397 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1398 (*commit
)->nparents
++;
1402 got_object_commit_close(*commit
);
1408 const struct got_error
*
1409 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1411 const struct got_error
*err
= NULL
;
1414 const size_t min_datalen
= sizeof(struct got_imsg_commit_object
);
1418 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1422 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1424 switch (imsg
.hdr
.type
) {
1425 case GOT_IMSG_COMMIT
:
1426 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1429 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1438 static const struct got_error
*
1439 send_tree_entries_batch(struct imsgbuf
*ibuf
,
1440 struct got_parsed_tree_entry
*entries
, int idx0
, int idxN
, size_t len
)
1443 struct got_imsg_tree_entries ientries
;
1446 memset(&ientries
, 0, sizeof(ientries
));
1448 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRIES
, 0, 0, len
);
1450 return got_error_from_errno("imsg_create TREE_ENTRY");
1452 ientries
.nentries
= idxN
- idx0
+ 1;
1453 if (imsg_add(wbuf
, &ientries
, sizeof(ientries
)) == -1)
1454 return got_error_from_errno("imsg_add TREE_ENTRY");
1456 for (i
= idx0
; i
<= idxN
; i
++) {
1457 static const char gap
[12]; /* for sha1 inside sha256 align */
1458 struct got_parsed_tree_entry
*pte
= &entries
[i
];
1460 /* Keep in sync with struct got_imsg_tree_entry definition! */
1461 if (imsg_add(wbuf
, pte
->id
, pte
->digest_len
) == -1)
1462 return got_error_from_errno("imsg_add TREE_ENTRY");
1463 if (pte
->algo
== GOT_HASH_SHA1
&&
1464 imsg_add(wbuf
, gap
, sizeof(gap
)) == -1)
1465 return got_error_from_errno("imsg_add TREE_ENTRY");
1466 if (imsg_add(wbuf
, &pte
->algo
, sizeof(pte
->algo
)) == -1)
1467 return got_error_from_errno("imsg_add TREE_ENTRY");
1468 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1)
1469 return got_error_from_errno("imsg_add TREE_ENTRY");
1470 if (imsg_add(wbuf
, &pte
->namelen
, sizeof(pte
->namelen
)) == -1)
1471 return got_error_from_errno("imsg_add TREE_ENTRY");
1473 /* Remaining bytes are the entry's name. */
1474 if (imsg_add(wbuf
, pte
->name
, pte
->namelen
) == -1)
1475 return got_error_from_errno("imsg_add TREE_ENTRY");
1478 imsg_close(ibuf
, wbuf
);
1482 static const struct got_error
*
1483 send_tree_entries(struct imsgbuf
*ibuf
, struct got_parsed_tree_entry
*entries
,
1486 const struct got_error
*err
= NULL
;
1488 size_t entries_len
= sizeof(struct got_imsg_tree_entries
);
1491 for (j
= 0; j
< nentries
; j
++) {
1492 struct got_parsed_tree_entry
*pte
= &entries
[j
];
1493 size_t len
= sizeof(struct got_imsg_tree_entry
) + pte
->namelen
;
1496 entries_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1497 err
= send_tree_entries_batch(ibuf
, entries
,
1498 i
, j
- 1, entries_len
);
1502 entries_len
= sizeof(struct got_imsg_tree_entries
);
1509 err
= send_tree_entries_batch(ibuf
, entries
, i
, j
- 1,
1518 const struct got_error
*
1519 got_privsep_send_tree(struct imsgbuf
*ibuf
,
1520 struct got_parsed_tree_entry
*entries
, int nentries
)
1522 const struct got_error
*err
= NULL
;
1523 struct got_imsg_tree_object itree
;
1525 memset(&itree
, 0, sizeof(itree
));
1526 itree
.nentries
= nentries
;
1527 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1529 return got_error_from_errno("imsg_compose TREE");
1531 err
= send_tree_entries(ibuf
, entries
, nentries
);
1535 return flush_imsg(ibuf
);
1539 static const struct got_error
*
1540 recv_tree_entries(void *data
, size_t datalen
, struct got_tree_object
*tree
,
1543 const struct got_error
*err
= NULL
;
1544 struct got_imsg_tree_entries
*ientries
;
1545 struct got_tree_entry
*te
;
1549 if (datalen
<= sizeof(*ientries
) ||
1550 datalen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
1551 return got_error(GOT_ERR_PRIVSEP_LEN
);
1553 ientries
= (struct got_imsg_tree_entries
*)data
;
1554 if (ientries
->nentries
> INT_MAX
) {
1555 return got_error_msg(GOT_ERR_NO_SPACE
,
1556 "too many tree entries");
1559 te_offset
= sizeof(*ientries
);
1560 for (i
= 0; i
< ientries
->nentries
; i
++) {
1561 struct got_imsg_tree_entry ite
;
1562 const char *te_name
;
1563 uint8_t *buf
= (uint8_t *)data
+ te_offset
;
1565 if (te_offset
>= datalen
) {
1566 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1570 /* Might not be aligned, size is ~32 bytes. */
1571 memcpy(&ite
, buf
, sizeof(ite
));
1573 if (ite
.namelen
>= sizeof(te
->name
)) {
1574 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1577 if (te_offset
+ sizeof(ite
) + ite
.namelen
> datalen
) {
1578 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1582 if (*nentries
>= tree
->nentries
) {
1583 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1586 te
= &tree
->entries
[*nentries
];
1587 te_name
= buf
+ sizeof(ite
);
1588 memcpy(te
->name
, te_name
, ite
.namelen
);
1589 te
->name
[ite
.namelen
] = '\0';
1590 memcpy(te
->id
.hash
, ite
.id
, sizeof(te
->id
.hash
));
1591 memcpy(te
->id
.hash
, ite
.id
, got_hash_digest_length(ite
.algo
));
1592 te
->id
.algo
= ite
.algo
;
1593 te
->mode
= ite
.mode
;
1594 te
->idx
= *nentries
;
1597 te_offset
+= sizeof(ite
) + ite
.namelen
;
1603 const struct got_error
*
1604 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1606 const struct got_error
*err
= NULL
;
1607 const size_t min_datalen
= sizeof(struct got_imsg_tree_object
);
1608 struct got_imsg_tree_object
*itree
;
1613 while (*tree
== NULL
|| nentries
< (*tree
)->nentries
) {
1617 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1621 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1623 switch (imsg
.hdr
.type
) {
1625 /* This message should only appear once. */
1626 if (*tree
!= NULL
) {
1627 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1630 if (datalen
!= sizeof(*itree
)) {
1631 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1635 if (itree
->nentries
< 0) {
1636 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1639 *tree
= malloc(sizeof(**tree
));
1640 if (*tree
== NULL
) {
1641 err
= got_error_from_errno("malloc");
1644 (*tree
)->entries
= calloc(itree
->nentries
,
1645 sizeof(struct got_tree_entry
));
1646 if ((*tree
)->entries
== NULL
) {
1647 err
= got_error_from_errno("malloc");
1652 (*tree
)->nentries
= itree
->nentries
;
1653 (*tree
)->refcnt
= 0;
1655 case GOT_IMSG_TREE_ENTRIES
:
1656 /* This message should be preceeded by GOT_IMSG_TREE. */
1657 if (*tree
== NULL
) {
1658 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1661 err
= recv_tree_entries(imsg
.data
, datalen
,
1665 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1674 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1676 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1677 got_object_tree_close(*tree
);
1684 const struct got_error
*
1685 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1686 const uint8_t *data
)
1688 struct got_imsg_blob iblob
;
1690 memset(&iblob
, 0, sizeof(iblob
));
1692 iblob
.hdrlen
= hdrlen
;
1697 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1698 return got_error(GOT_ERR_NO_SPACE
);
1700 buf
= malloc(sizeof(iblob
) + size
);
1702 return got_error_from_errno("malloc");
1704 memcpy(buf
, &iblob
, sizeof(iblob
));
1705 memcpy(buf
+ sizeof(iblob
), data
, size
);
1706 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1707 sizeof(iblob
) + size
) == -1) {
1709 return got_error_from_errno("imsg_compose BLOB");
1713 /* Data has already been written to file descriptor. */
1714 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1715 sizeof(iblob
)) == -1)
1716 return got_error_from_errno("imsg_compose BLOB");
1720 return flush_imsg(ibuf
);
1723 const struct got_error
*
1724 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1725 struct imsgbuf
*ibuf
)
1727 const struct got_error
*err
= NULL
;
1729 struct got_imsg_blob
*iblob
;
1734 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1738 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1740 switch (imsg
.hdr
.type
) {
1742 if (datalen
< sizeof(*iblob
)) {
1743 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1747 *size
= iblob
->size
;
1748 *hdrlen
= iblob
->hdrlen
;
1750 if (datalen
== sizeof(*iblob
)) {
1751 /* Data has been written to file descriptor. */
1755 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
||
1756 *size
> datalen
+ sizeof(*iblob
)) {
1757 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1761 *outbuf
= malloc(*size
);
1762 if (*outbuf
== NULL
) {
1763 err
= got_error_from_errno("malloc");
1766 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1769 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1778 static const struct got_error
*
1779 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1781 const struct got_error
*err
= NULL
;
1782 size_t offset
, remain
;
1785 remain
= tagmsg_len
;
1786 while (remain
> 0) {
1787 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1789 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1790 tag
->tagmsg
+ offset
, n
) == -1) {
1791 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1795 err
= flush_imsg(ibuf
);
1806 const struct got_error
*
1807 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1809 const struct got_error
*err
= NULL
;
1810 struct got_imsg_tag_object
*itag
;
1813 size_t tag_len
= strlen(tag
->tag
);
1814 size_t tagger_len
= strlen(tag
->tagger
);
1815 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1817 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1819 buf
= malloc(total
);
1821 return got_error_from_errno("malloc");
1823 itag
= (struct got_imsg_tag_object
*)buf
;
1824 memcpy(&itag
->id
, &tag
->id
, sizeof(itag
->id
));
1825 itag
->obj_type
= tag
->obj_type
;
1826 itag
->tag_len
= tag_len
;
1827 itag
->tagger_len
= tagger_len
;
1828 itag
->tagger_time
= tag
->tagger_time
;
1829 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1830 itag
->tagmsg_len
= tagmsg_len
;
1832 len
= sizeof(*itag
);
1833 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1835 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1838 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1839 err
= got_error_from_errno("imsg_compose TAG");
1843 if (tagmsg_len
== 0 ||
1844 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1845 err
= flush_imsg(ibuf
);
1849 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1855 const struct got_error
*
1856 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1858 const struct got_error
*err
= NULL
;
1860 struct got_imsg_tag_object
*itag
;
1861 size_t len
, datalen
;
1862 const size_t min_datalen
= sizeof(struct got_imsg_tag_object
);
1866 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1870 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1873 switch (imsg
.hdr
.type
) {
1875 if (datalen
< sizeof(*itag
)) {
1876 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1880 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1882 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1885 len
+= sizeof(*itag
);
1887 *tag
= calloc(1, sizeof(**tag
));
1889 err
= got_error_from_errno("calloc");
1893 memcpy(&(*tag
)->id
, &itag
->id
, sizeof(itag
->id
));
1895 (*tag
)->tag
= strndup(imsg
.data
+ len
, itag
->tag_len
);
1896 if ((*tag
)->tag
== NULL
) {
1897 err
= got_error_from_errno("strndup");
1900 len
+= itag
->tag_len
;
1902 (*tag
)->obj_type
= itag
->obj_type
;
1903 (*tag
)->tagger_time
= itag
->tagger_time
;
1904 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1906 (*tag
)->tagger
= strndup(imsg
.data
+ len
, itag
->tagger_len
);
1907 if ((*tag
)->tagger
== NULL
) {
1908 err
= got_error_from_errno("strndup");
1911 len
+= itag
->tagger_len
;
1913 if (itag
->tagmsg_len
== 0) {
1914 (*tag
)->tagmsg
= strdup("");
1915 if ((*tag
)->tagmsg
== NULL
) {
1916 err
= got_error_from_errno("strdup");
1920 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1922 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1923 if ((*tag
)->tagmsg
== NULL
) {
1924 err
= got_error_from_errno("malloc");
1927 while (remain
> 0) {
1928 struct imsg imsg_log
;
1929 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1932 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1936 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1937 return got_error(GOT_ERR_PRIVSEP_MSG
);
1939 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1941 imsg_free(&imsg_log
);
1945 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1950 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1959 const struct got_error
*
1960 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1961 struct got_packidx
*packidx
)
1963 const struct got_error
*err
= NULL
;
1964 struct got_imsg_packidx ipackidx
;
1965 struct got_imsg_pack ipack
;
1968 memset(&ipackidx
, 0, sizeof(ipackidx
));
1969 memset(&ipack
, 0, sizeof(ipack
));
1971 ipackidx
.len
= packidx
->len
;
1972 ipackidx
.packfile_size
= pack
->filesize
;
1973 ipackidx
.algo
= packidx
->algo
;
1974 fd
= dup(packidx
->fd
);
1976 return got_error_from_errno("dup");
1978 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1979 sizeof(ipackidx
)) == -1) {
1980 err
= got_error_from_errno("imsg_compose PACKIDX");
1985 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1986 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1987 return got_error(GOT_ERR_NO_SPACE
);
1988 ipack
.filesize
= pack
->filesize
;
1989 ipack
.algo
= pack
->algo
;
1993 return got_error_from_errno("dup");
1995 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
1997 err
= got_error_from_errno("imsg_compose PACK");
2002 return flush_imsg(ibuf
);
2005 const struct got_error
*
2006 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
2007 struct got_object_id
*id
)
2009 struct got_imsg_packed_object iobj
;
2011 memset(&iobj
, 0, sizeof(iobj
));
2013 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2015 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
2016 &iobj
, sizeof(iobj
)) == -1)
2017 return got_error_from_errno("imsg_compose "
2018 "PACKED_OBJECT_REQUEST");
2020 return flush_imsg(ibuf
);
2023 const struct got_error
*
2024 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
2025 struct got_object_id
*id
)
2027 struct got_imsg_packed_object iobj
;
2029 memset(&iobj
, 0, sizeof(iobj
));
2031 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2033 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
2034 &iobj
, sizeof(iobj
)) == -1)
2035 return got_error_from_errno("imsg_compose "
2036 "PACKED_OBJECT_REQUEST");
2038 return flush_imsg(ibuf
);
2041 const struct got_error
*
2042 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2044 const struct got_error
*err
= NULL
;
2046 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2048 err
= got_error_from_errno("imsg_compose "
2049 "GITCONFIG_PARSE_REQUEST");
2054 return flush_imsg(ibuf
);
2057 const struct got_error
*
2058 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2060 if (imsg_compose(ibuf
,
2061 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2063 return got_error_from_errno("imsg_compose "
2064 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2066 return flush_imsg(ibuf
);
2069 const struct got_error
*
2070 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2072 if (imsg_compose(ibuf
,
2073 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2075 return got_error_from_errno("imsg_compose "
2076 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2078 return flush_imsg(ibuf
);
2082 const struct got_error
*
2083 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2085 if (imsg_compose(ibuf
,
2086 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2087 return got_error_from_errno("imsg_compose "
2088 "GITCONFIG_AUTHOR_NAME_REQUEST");
2090 return flush_imsg(ibuf
);
2093 const struct got_error
*
2094 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2096 if (imsg_compose(ibuf
,
2097 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2098 return got_error_from_errno("imsg_compose "
2099 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2101 return flush_imsg(ibuf
);
2104 const struct got_error
*
2105 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2107 if (imsg_compose(ibuf
,
2108 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2109 return got_error_from_errno("imsg_compose "
2110 "GITCONFIG_REMOTE_REQUEST");
2112 return flush_imsg(ibuf
);
2115 const struct got_error
*
2116 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2118 if (imsg_compose(ibuf
,
2119 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2120 return got_error_from_errno("imsg_compose "
2121 "GITCONFIG_OWNER_REQUEST");
2123 return flush_imsg(ibuf
);
2126 const struct got_error
*
2127 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2129 const struct got_error
*err
= NULL
;
2135 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2138 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2140 switch (imsg
.hdr
.type
) {
2141 case GOT_IMSG_GITCONFIG_STR_VAL
:
2144 *str
= strndup(imsg
.data
, datalen
);
2146 err
= got_error_from_errno("strndup");
2151 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2159 const struct got_error
*
2160 got_privsep_recv_gitconfig_pair(char **key
, char **val
, struct imsgbuf
*ibuf
)
2162 const struct got_error
*err
= NULL
;
2163 struct got_imsg_gitconfig_pair p
;
2170 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2175 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2177 if (imsg
.hdr
.type
!= GOT_IMSG_GITCONFIG_PAIR
) {
2178 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2182 if (datalen
< sizeof(p
)) {
2183 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2187 memcpy(&p
, data
, sizeof(p
));
2190 if (datalen
!= sizeof(p
) + p
.klen
+ p
.vlen
) {
2191 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2195 *key
= strndup(data
, p
.klen
);
2197 err
= got_error_from_errno("strndup");
2202 *val
= strndup(data
, p
.vlen
);
2204 err
= got_error_from_errno("strndup");
2213 const struct got_error
*
2214 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2216 const struct got_error
*err
= NULL
;
2219 const size_t min_datalen
= sizeof(int);
2223 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2226 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2228 switch (imsg
.hdr
.type
) {
2229 case GOT_IMSG_GITCONFIG_INT_VAL
:
2230 if (datalen
!= sizeof(*val
)) {
2231 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2234 memcpy(val
, imsg
.data
, sizeof(*val
));
2237 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2246 free_remote_data(struct got_remote_repo
*remote
)
2251 free(remote
->fetch_url
);
2252 free(remote
->send_url
);
2253 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2254 free(remote
->fetch_branches
[i
]);
2255 free(remote
->fetch_branches
);
2256 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2257 free(remote
->send_branches
[i
]);
2258 free(remote
->send_branches
);
2259 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2260 free(remote
->fetch_refs
[i
]);
2261 free(remote
->fetch_refs
);
2264 const struct got_error
*
2265 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2266 int *nremotes
, struct imsgbuf
*ibuf
)
2268 const struct got_error
*err
= NULL
;
2271 struct got_imsg_remotes iremotes
;
2272 struct got_imsg_remote iremote
;
2276 iremotes
.nremotes
= 0;
2278 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2281 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2283 switch (imsg
.hdr
.type
) {
2284 case GOT_IMSG_GITCONFIG_REMOTES
:
2285 if (datalen
!= sizeof(iremotes
)) {
2287 return got_error(GOT_ERR_PRIVSEP_LEN
);
2289 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2290 if (iremotes
.nremotes
== 0) {
2297 return got_error(GOT_ERR_PRIVSEP_MSG
);
2302 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2303 if (*remotes
== NULL
)
2304 return got_error_from_errno("recallocarray");
2306 while (*nremotes
< iremotes
.nremotes
) {
2307 struct got_remote_repo
*remote
;
2309 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2312 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2314 switch (imsg
.hdr
.type
) {
2315 case GOT_IMSG_GITCONFIG_REMOTE
:
2316 remote
= &(*remotes
)[*nremotes
];
2317 memset(remote
, 0, sizeof(*remote
));
2318 if (datalen
< sizeof(iremote
)) {
2319 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2322 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2323 if (iremote
.name_len
== 0 ||
2324 iremote
.fetch_url_len
== 0 ||
2325 iremote
.send_url_len
== 0 ||
2326 (sizeof(iremote
) + iremote
.name_len
+
2327 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2328 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2331 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2333 if (remote
->name
== NULL
) {
2334 err
= got_error_from_errno("strndup");
2337 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2338 iremote
.name_len
, iremote
.fetch_url_len
);
2339 if (remote
->fetch_url
== NULL
) {
2340 err
= got_error_from_errno("strndup");
2341 free_remote_data(remote
);
2344 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2345 iremote
.name_len
+ iremote
.fetch_url_len
,
2346 iremote
.send_url_len
);
2347 if (remote
->send_url
== NULL
) {
2348 err
= got_error_from_errno("strndup");
2349 free_remote_data(remote
);
2352 remote
->mirror_references
= iremote
.mirror_references
;
2353 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2354 remote
->nfetch_branches
= 0;
2355 remote
->fetch_branches
= NULL
;
2356 remote
->nsend_branches
= 0;
2357 remote
->send_branches
= NULL
;
2358 remote
->nfetch_refs
= 0;
2359 remote
->fetch_refs
= NULL
;
2363 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2374 for (i
= 0; i
< *nremotes
; i
++)
2375 free_remote_data(&(*remotes
)[i
]);
2383 const struct got_error
*
2384 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2386 const struct got_error
*err
= NULL
;
2388 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2390 err
= got_error_from_errno("imsg_compose "
2391 "GOTCONFIG_PARSE_REQUEST");
2396 return flush_imsg(ibuf
);
2399 const struct got_error
*
2400 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2402 if (imsg_compose(ibuf
,
2403 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2404 return got_error_from_errno("imsg_compose "
2405 "GOTCONFIG_AUTHOR_REQUEST");
2407 return flush_imsg(ibuf
);
2410 const struct got_error
*
2411 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf
*ibuf
)
2413 if (imsg_compose(ibuf
,
2414 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2415 return got_error_from_errno("imsg_compose "
2416 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2418 return flush_imsg(ibuf
);
2421 const struct got_error
*
2422 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf
*ibuf
)
2424 if (imsg_compose(ibuf
,
2425 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2426 return got_error_from_errno("imsg_compose "
2427 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2429 return flush_imsg(ibuf
);
2432 const struct got_error
*
2433 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf
*ibuf
)
2435 if (imsg_compose(ibuf
,
2436 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2437 return got_error_from_errno("imsg_compose "
2438 "GOTCONFIG_SIGNERID_REQUEST");
2440 return flush_imsg(ibuf
);
2443 const struct got_error
*
2444 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2446 if (imsg_compose(ibuf
,
2447 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2448 return got_error_from_errno("imsg_compose "
2449 "GOTCONFIG_REMOTE_REQUEST");
2451 return flush_imsg(ibuf
);
2454 const struct got_error
*
2455 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2457 const struct got_error
*err
= NULL
;
2463 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2466 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2468 switch (imsg
.hdr
.type
) {
2469 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2472 *str
= strndup(imsg
.data
, datalen
);
2474 err
= got_error_from_errno("strndup");
2479 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2487 const struct got_error
*
2488 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2489 int *nremotes
, struct imsgbuf
*ibuf
)
2491 const struct got_error
*err
= NULL
;
2494 struct got_imsg_remotes iremotes
;
2495 struct got_imsg_remote iremote
;
2496 const size_t min_datalen
= sizeof(iremotes
);
2500 iremotes
.nremotes
= 0;
2502 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2505 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2507 switch (imsg
.hdr
.type
) {
2508 case GOT_IMSG_GOTCONFIG_REMOTES
:
2509 if (datalen
!= sizeof(iremotes
)) {
2510 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2513 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2514 if (iremotes
.nremotes
< 0) {
2515 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2518 if (iremotes
.nremotes
== 0) {
2525 return got_error(GOT_ERR_PRIVSEP_MSG
);
2530 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2531 if (*remotes
== NULL
)
2532 return got_error_from_errno("recallocarray");
2534 while (*nremotes
< iremotes
.nremotes
) {
2535 struct got_remote_repo
*remote
;
2536 const size_t min_datalen
= sizeof(iremote
);
2539 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2542 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2544 switch (imsg
.hdr
.type
) {
2545 case GOT_IMSG_GOTCONFIG_REMOTE
:
2546 remote
= &(*remotes
)[*nremotes
];
2547 memset(remote
, 0, sizeof(*remote
));
2548 if (datalen
< sizeof(iremote
)) {
2549 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2552 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2553 if (iremote
.name_len
== 0 ||
2554 (iremote
.fetch_url_len
== 0 &&
2555 iremote
.send_url_len
== 0) ||
2556 (sizeof(iremote
) + iremote
.name_len
+
2557 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2559 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2562 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2564 if (remote
->name
== NULL
) {
2565 err
= got_error_from_errno("strndup");
2568 remote
->fetch_url
= strndup(imsg
.data
+
2569 sizeof(iremote
) + iremote
.name_len
,
2570 iremote
.fetch_url_len
);
2571 if (remote
->fetch_url
== NULL
) {
2572 err
= got_error_from_errno("strndup");
2573 free_remote_data(remote
);
2576 remote
->send_url
= strndup(imsg
.data
+
2577 sizeof(iremote
) + iremote
.name_len
+
2578 iremote
.fetch_url_len
, iremote
.send_url_len
);
2579 if (remote
->send_url
== NULL
) {
2580 err
= got_error_from_errno("strndup");
2581 free_remote_data(remote
);
2584 remote
->mirror_references
= iremote
.mirror_references
;
2585 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2586 if (iremote
.nfetch_branches
> 0) {
2587 remote
->fetch_branches
= recallocarray(NULL
, 0,
2588 iremote
.nfetch_branches
, sizeof(char *));
2589 if (remote
->fetch_branches
== NULL
) {
2590 err
= got_error_from_errno("calloc");
2591 free_remote_data(remote
);
2595 remote
->nfetch_branches
= 0;
2596 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2598 err
= got_privsep_recv_gotconfig_str(&branch
,
2601 free_remote_data(remote
);
2604 remote
->fetch_branches
[i
] = branch
;
2605 remote
->nfetch_branches
++;
2607 if (iremote
.nsend_branches
> 0) {
2608 remote
->send_branches
= recallocarray(NULL
, 0,
2609 iremote
.nsend_branches
, sizeof(char *));
2610 if (remote
->send_branches
== NULL
) {
2611 err
= got_error_from_errno("calloc");
2612 free_remote_data(remote
);
2616 remote
->nsend_branches
= 0;
2617 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2619 err
= got_privsep_recv_gotconfig_str(&branch
,
2622 free_remote_data(remote
);
2625 remote
->send_branches
[i
] = branch
;
2626 remote
->nsend_branches
++;
2628 if (iremote
.nfetch_refs
> 0) {
2629 remote
->fetch_refs
= recallocarray(NULL
, 0,
2630 iremote
.nfetch_refs
, sizeof(char *));
2631 if (remote
->fetch_refs
== NULL
) {
2632 err
= got_error_from_errno("calloc");
2633 free_remote_data(remote
);
2637 remote
->nfetch_refs
= 0;
2638 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2640 err
= got_privsep_recv_gotconfig_str(&ref
,
2643 free_remote_data(remote
);
2646 remote
->fetch_refs
[i
] = ref
;
2647 remote
->nfetch_refs
++;
2652 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2663 for (i
= 0; i
< *nremotes
; i
++)
2664 free_remote_data(&(*remotes
)[i
]);
2672 const struct got_error
*
2673 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2674 struct got_object_id
*id
, int idx
, const char *path
)
2677 size_t path_len
= strlen(path
);
2679 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2680 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2682 return got_error_from_errno(
2683 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2685 * Keep in sync with struct got_imsg_commit_traversal_request
2686 * and struct got_imsg_packed_object.
2688 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2689 return got_error_from_errno("imsg_add "
2690 "COMMIT_TRAVERSAL_REQUEST");
2691 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1)
2692 return got_error_from_errno("imsg_add "
2693 "COMMIT_TRAVERSAL_REQUEST");
2694 if (imsg_add(wbuf
, &path_len
, sizeof(path_len
)) == -1)
2695 return got_error_from_errno("imsg_add "
2696 "COMMIT_TRAVERSAL_REQUEST");
2697 if (imsg_add(wbuf
, path
, path_len
) == -1)
2698 return got_error_from_errno("imsg_add "
2699 "COMMIT_TRAVERSAL_REQUEST");
2701 imsg_close(ibuf
, wbuf
);
2702 return flush_imsg(ibuf
);
2705 const struct got_error
*
2706 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2707 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2709 const struct got_error
*err
= NULL
;
2711 struct got_imsg_traversed_commits
*icommits
;
2712 struct got_object_id
*ids
;
2716 *changed_commit
= NULL
;
2719 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2723 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2724 switch (imsg
.hdr
.type
) {
2725 case GOT_IMSG_TRAVERSED_COMMITS
:
2726 icommits
= imsg
.data
;
2727 if (datalen
!= sizeof(*icommits
) +
2728 icommits
->ncommits
* sizeof(*ids
)) {
2729 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2732 ids
= imsg
.data
+ sizeof(*icommits
);
2733 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2734 struct got_object_qid
*qid
;
2736 err
= got_object_qid_alloc_partial(&qid
);
2739 memcpy(&qid
->id
, &ids
[i
], sizeof(ids
[i
]));
2740 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2744 case GOT_IMSG_COMMIT
:
2745 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2748 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2752 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2762 got_object_id_queue_free(commit_ids
);
2766 const struct got_error
*
2767 got_privsep_send_enumerated_tree(size_t *totlen
, struct imsgbuf
*ibuf
,
2768 struct got_object_id
*tree_id
, const char *path
,
2769 struct got_parsed_tree_entry
*entries
, int nentries
)
2771 const struct got_error
*err
= NULL
;
2773 size_t path_len
= strlen(path
);
2776 msglen
= sizeof(struct got_imsg_enumerated_tree
) + path_len
;
2777 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_TREE
, 0, 0, msglen
);
2779 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2781 if (imsg_add(wbuf
, tree_id
, sizeof(*tree_id
)) == -1)
2782 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2783 if (imsg_add(wbuf
, &nentries
, sizeof(nentries
)) == -1)
2784 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2785 if (imsg_add(wbuf
, path
, path_len
) == -1)
2786 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2788 imsg_close(ibuf
, wbuf
);
2791 err
= send_tree_entries(ibuf
, entries
, nentries
);
2796 return flush_imsg(ibuf
);
2799 const struct got_error
*
2800 got_privsep_send_object_enumeration_request(struct imsgbuf
*ibuf
)
2802 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_REQUEST
,
2803 0, 0, -1, NULL
, 0) == -1)
2804 return got_error_from_errno("imsg_compose "
2805 "OBJECT_ENUMERATION_REQUEST");
2807 return flush_imsg(ibuf
);
2810 const struct got_error
*
2811 got_privsep_send_object_enumeration_done(struct imsgbuf
*ibuf
)
2813 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_DONE
,
2814 0, 0, -1, NULL
, 0) == -1)
2815 return got_error_from_errno("imsg_compose "
2816 "OBJECT_ENUMERATION_DONE");
2818 return flush_imsg(ibuf
);
2821 const struct got_error
*
2822 got_privsep_send_object_enumeration_incomplete(struct imsgbuf
*ibuf
)
2824 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
,
2825 0, 0, -1, NULL
, 0) == -1)
2826 return got_error_from_errno("imsg_compose "
2827 "OBJECT_ENUMERATION_INCOMPLETE");
2829 return flush_imsg(ibuf
);
2832 const struct got_error
*
2833 got_privsep_send_enumerated_commit(struct imsgbuf
*ibuf
,
2834 struct got_object_id
*id
, time_t mtime
)
2838 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_COMMIT
, 0, 0,
2839 sizeof(struct got_imsg_enumerated_commit
));
2841 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2843 /* Keep in sync with struct got_imsg_enumerated_commit! */
2844 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2845 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2846 if (imsg_add(wbuf
, &mtime
, sizeof(mtime
)) == -1)
2847 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2849 imsg_close(ibuf
, wbuf
);
2850 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2854 const struct got_error
*
2855 got_privsep_recv_enumerated_objects(int *found_all_objects
,
2856 struct imsgbuf
*ibuf
,
2857 got_object_enumerate_commit_cb cb_commit
,
2858 got_object_enumerate_tree_cb cb_tree
, void *cb_arg
,
2859 struct got_repository
*repo
)
2861 const struct got_error
*err
= NULL
;
2863 struct got_imsg_enumerated_commit
*icommit
= NULL
;
2864 struct got_object_id commit_id
;
2865 int have_commit
= 0;
2867 struct got_tree_object tree
;
2868 struct got_imsg_enumerated_tree
*itree
;
2869 struct got_object_id tree_id
;
2870 char *path
= NULL
, *canon_path
= NULL
;
2871 size_t datalen
, path_len
;
2875 *found_all_objects
= 0;
2876 memset(&tree
, 0, sizeof(tree
));
2879 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2883 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2884 switch (imsg
.hdr
.type
) {
2885 case GOT_IMSG_ENUMERATED_COMMIT
:
2886 if (have_commit
&& nentries
!= -1) {
2887 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2890 if (datalen
!= sizeof(*icommit
)) {
2891 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2894 icommit
= (struct got_imsg_enumerated_commit
*)imsg
.data
;
2895 memcpy(&commit_id
, &icommit
->id
, sizeof(commit_id
));
2896 mtime
= icommit
->mtime
;
2899 case GOT_IMSG_ENUMERATED_TREE
:
2900 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2902 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2905 if (datalen
< sizeof(*itree
)) {
2906 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2910 path_len
= datalen
- sizeof(*itree
);
2911 if (path_len
== 0) {
2912 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2915 memcpy(&tree_id
, &itree
->id
, sizeof(tree_id
));
2917 path
= strndup(imsg
.data
+ sizeof(*itree
), path_len
);
2919 err
= got_error_from_errno("strndup");
2923 canon_path
= malloc(path_len
+ 1);
2924 if (canon_path
== NULL
) {
2925 err
= got_error_from_errno("malloc");
2928 if (!got_path_is_absolute(path
)) {
2929 err
= got_error(GOT_ERR_BAD_PATH
);
2932 if (got_path_is_root_dir(path
)) {
2933 /* XXX check what got_canonpath() does wrong */
2934 canon_path
[0] = '/';
2935 canon_path
[1] = '\0';
2937 err
= got_canonpath(path
, canon_path
,
2942 if (strcmp(path
, canon_path
) != 0) {
2943 err
= got_error(GOT_ERR_BAD_PATH
);
2946 if (nentries
!= -1) {
2947 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2950 if (itree
->nentries
< -1) {
2951 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2954 if (itree
->nentries
== -1) {
2955 /* Tree was not found in pack file. */
2956 err
= cb_tree(cb_arg
, NULL
, mtime
, &tree_id
,
2960 if (itree
->nentries
> INT_MAX
) {
2961 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2964 tree
.entries
= calloc(itree
->nentries
,
2965 sizeof(struct got_tree_entry
));
2966 if (tree
.entries
== NULL
) {
2967 err
= got_error_from_errno("calloc");
2970 if (itree
->nentries
== 0) {
2971 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2976 /* Prepare for next tree. */
2978 memset(&tree
, 0, sizeof(tree
));
2981 tree
.nentries
= itree
->nentries
;
2985 case GOT_IMSG_TREE_ENTRIES
:
2986 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2987 if (nentries
<= -1) {
2988 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2991 err
= recv_tree_entries(imsg
.data
, datalen
,
2995 if (tree
.nentries
== nentries
) {
2996 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
3001 /* Prepare for next tree. */
3003 memset(&tree
, 0, sizeof(tree
));
3007 case GOT_IMSG_TREE_ENUMERATION_DONE
:
3008 /* All trees have been found and traversed. */
3009 if (!have_commit
|| path
== NULL
|| nentries
!= -1) {
3010 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3013 err
= cb_commit(cb_arg
, mtime
, &commit_id
, repo
);
3018 case GOT_IMSG_OBJECT_ENUMERATION_DONE
:
3019 *found_all_objects
= 1;
3022 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
:
3026 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3041 const struct got_error
*
3042 got_privsep_send_raw_delta_req(struct imsgbuf
*ibuf
, int idx
,
3043 struct got_object_id
*id
)
3045 struct got_imsg_raw_delta_request dreq
;
3047 memset(&dreq
, 0, sizeof(dreq
));
3049 memcpy(&dreq
.id
, id
, sizeof(dreq
.id
));
3051 if (imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA_REQUEST
, 0, 0, -1,
3052 &dreq
, sizeof(dreq
)) == -1)
3053 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
3055 return flush_imsg(ibuf
);
3058 const struct got_error
*
3059 got_privsep_send_raw_delta_outfd(struct imsgbuf
*ibuf
, int fd
)
3061 return send_fd(ibuf
, GOT_IMSG_RAW_DELTA_OUTFD
, fd
);
3064 const struct got_error
*
3065 got_privsep_send_raw_delta(struct imsgbuf
*ibuf
, uint64_t base_size
,
3066 uint64_t result_size
, off_t delta_size
, off_t delta_compressed_size
,
3067 off_t delta_offset
, off_t delta_out_offset
, struct got_object_id
*base_id
)
3069 struct got_imsg_raw_delta idelta
;
3072 memset(&idelta
, 0, sizeof(idelta
));
3073 idelta
.base_size
= base_size
;
3074 idelta
.result_size
= result_size
;
3075 idelta
.delta_size
= delta_size
;
3076 idelta
.delta_compressed_size
= delta_compressed_size
;
3077 idelta
.delta_offset
= delta_offset
;
3078 idelta
.delta_out_offset
= delta_out_offset
;
3079 memcpy(&idelta
.base_id
, &base_id
, sizeof(idelta
.base_id
));
3081 ret
= imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA
, 0, 0, -1,
3082 &idelta
, sizeof(idelta
));
3084 return got_error_from_errno("imsg_compose RAW_DELTA");
3086 return flush_imsg(ibuf
);
3089 const struct got_error
*
3090 got_privsep_recv_raw_delta(uint64_t *base_size
, uint64_t *result_size
,
3091 off_t
*delta_size
, off_t
*delta_compressed_size
, off_t
*delta_offset
,
3092 off_t
*delta_out_offset
, struct got_object_id
**base_id
,
3093 struct imsgbuf
*ibuf
)
3095 const struct got_error
*err
= NULL
;
3097 struct got_imsg_raw_delta
*delta
;
3103 *delta_compressed_size
= 0;
3105 *delta_out_offset
= 0;
3108 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3112 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3114 switch (imsg
.hdr
.type
) {
3115 case GOT_IMSG_RAW_DELTA
:
3116 if (datalen
!= sizeof(*delta
)) {
3117 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3121 *base_size
= delta
->base_size
;
3122 *result_size
= delta
->result_size
;
3123 *delta_size
= delta
->delta_size
;
3124 *delta_compressed_size
= delta
->delta_compressed_size
;
3125 *delta_offset
= delta
->delta_offset
;
3126 *delta_out_offset
= delta
->delta_out_offset
;
3127 *base_id
= calloc(1, sizeof(**base_id
));
3128 if (*base_id
== NULL
) {
3129 err
= got_error_from_errno("malloc");
3132 memcpy(*base_id
, &delta
->base_id
, sizeof(**base_id
));
3135 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3148 static const struct got_error
*
3149 send_idlist(struct imsgbuf
*ibuf
, struct got_object_id
**ids
, size_t nids
)
3151 const struct got_error
*err
= NULL
;
3152 struct got_imsg_object_idlist idlist
;
3156 memset(&idlist
, 0, sizeof(idlist
));
3158 if (nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
)
3159 return got_error(GOT_ERR_NO_SPACE
);
3161 wbuf
= imsg_create(ibuf
, GOT_IMSG_OBJ_ID_LIST
, 0, 0,
3162 sizeof(idlist
) + nids
* sizeof(**ids
));
3164 err
= got_error_from_errno("imsg_create OBJ_ID_LIST");
3169 if (imsg_add(wbuf
, &idlist
, sizeof(idlist
)) == -1)
3170 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3172 for (i
= 0; i
< nids
; i
++) {
3173 struct got_object_id
*id
= ids
[i
];
3174 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
3175 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3178 imsg_close(ibuf
, wbuf
);
3180 return flush_imsg(ibuf
);
3183 const struct got_error
*
3184 got_privsep_send_object_idlist(struct imsgbuf
*ibuf
,
3185 struct got_object_id
**ids
, size_t nids
)
3187 const struct got_error
*err
= NULL
;
3188 struct got_object_id
*idlist
[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
];
3191 for (i
= 0; i
< nids
; i
++) {
3192 idlist
[i
% nitems(idlist
)] = ids
[i
];
3194 if (queued
>= nitems(idlist
)) {
3195 err
= send_idlist(ibuf
, idlist
, queued
);
3203 err
= send_idlist(ibuf
, idlist
, queued
);
3211 const struct got_error
*
3212 got_privsep_send_object_idlist_done(struct imsgbuf
*ibuf
)
3214 if (imsg_compose(ibuf
, GOT_IMSG_OBJ_ID_LIST_DONE
, 0, 0, -1, NULL
, 0)
3216 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3218 return flush_imsg(ibuf
);
3221 const struct got_error
*
3222 got_privsep_recv_object_idlist(int *done
, struct got_object_id
**ids
,
3223 size_t *nids
, struct imsgbuf
*ibuf
)
3225 const struct got_error
*err
= NULL
;
3227 struct got_imsg_object_idlist
*idlist
;
3234 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3238 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3239 switch (imsg
.hdr
.type
) {
3240 case GOT_IMSG_OBJ_ID_LIST
:
3241 if (datalen
< sizeof(*idlist
)) {
3242 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3246 if (idlist
->nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3247 idlist
->nids
* sizeof(**ids
) > datalen
- sizeof(*idlist
)) {
3248 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3251 *nids
= idlist
->nids
;
3252 *ids
= calloc(*nids
, sizeof(**ids
));
3254 err
= got_error_from_errno("calloc");
3257 memcpy(*ids
, (uint8_t *)imsg
.data
+ sizeof(*idlist
),
3258 *nids
* sizeof(**ids
));
3260 case GOT_IMSG_OBJ_ID_LIST_DONE
:
3264 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3273 const struct got_error
*
3274 got_privsep_send_delta_reuse_req(struct imsgbuf
*ibuf
)
3276 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_REQUEST
, 0, 0, -1, NULL
, 0)
3278 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3280 return flush_imsg(ibuf
);
3283 const struct got_error
*
3284 got_privsep_send_reused_deltas(struct imsgbuf
*ibuf
,
3285 struct got_imsg_reused_delta
*deltas
, size_t ndeltas
)
3287 const struct got_error
*err
= NULL
;
3289 struct got_imsg_reused_deltas ideltas
;
3292 memset(&ideltas
, 0, sizeof(ideltas
));
3294 if (ndeltas
> GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS
)
3295 return got_error(GOT_ERR_NO_SPACE
);
3297 wbuf
= imsg_create(ibuf
, GOT_IMSG_REUSED_DELTAS
, 0, 0,
3298 sizeof(ideltas
) + ndeltas
* sizeof(*deltas
));
3300 err
= got_error_from_errno("imsg_create REUSED_DELTAS");
3304 ideltas
.ndeltas
= ndeltas
;
3305 if (imsg_add(wbuf
, &ideltas
, sizeof(ideltas
)) == -1)
3306 return got_error_from_errno("imsg_add REUSED_DELTAS");
3308 for (i
= 0; i
< ndeltas
; i
++) {
3309 struct got_imsg_reused_delta
*delta
= &deltas
[i
];
3310 if (imsg_add(wbuf
, delta
, sizeof(*delta
)) == -1)
3311 return got_error_from_errno("imsg_add REUSED_DELTAS");
3314 imsg_close(ibuf
, wbuf
);
3316 return flush_imsg(ibuf
);
3319 const struct got_error
*
3320 got_privsep_send_reused_deltas_done(struct imsgbuf
*ibuf
)
3322 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_DONE
, 0, 0, -1, NULL
, 0)
3324 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3326 return flush_imsg(ibuf
);
3329 const struct got_error
*
3330 got_privsep_recv_reused_deltas(int *done
, struct got_imsg_reused_delta
*deltas
,
3331 size_t *ndeltas
, struct imsgbuf
*ibuf
)
3333 const struct got_error
*err
= NULL
;
3335 struct got_imsg_reused_deltas
*ideltas
;
3341 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3345 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3346 switch (imsg
.hdr
.type
) {
3347 case GOT_IMSG_REUSED_DELTAS
:
3348 if (datalen
< sizeof(*ideltas
)) {
3349 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3352 ideltas
= imsg
.data
;
3353 if (ideltas
->ndeltas
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3354 ideltas
->ndeltas
* sizeof(*deltas
) >
3355 datalen
- sizeof(*ideltas
)) {
3356 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3359 *ndeltas
= ideltas
->ndeltas
;
3360 memcpy(deltas
, (uint8_t *)imsg
.data
+ sizeof(*ideltas
),
3361 *ndeltas
* sizeof(*deltas
));
3363 case GOT_IMSG_DELTA_REUSE_DONE
:
3367 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3376 const struct got_error
*
3377 got_privsep_init_commit_painting(struct imsgbuf
*ibuf
)
3379 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_INIT
,
3380 0, 0, -1, NULL
, 0) == -1)
3381 return got_error_from_errno("imsg_compose "
3382 "COMMIT_PAINTING_INIT");
3384 return flush_imsg(ibuf
);
3387 const struct got_error
*
3388 got_privsep_send_painting_request(struct imsgbuf
*ibuf
)
3390 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_REQUEST
, 0, 0, -1,
3392 return got_error_from_errno("imsg_compose "
3393 "COMMIT_PAINTING_REQUEST");
3395 return flush_imsg(ibuf
);
3398 static const struct got_error
*
3399 send_painted_commits(struct got_object_id_queue
*ids
, int *nids
,
3400 size_t remain
, int present_in_pack
, struct imsgbuf
*ibuf
)
3402 const struct got_error
*err
= NULL
;
3403 struct ibuf
*wbuf
= NULL
;
3404 struct got_object_qid
*qid
;
3409 msglen
= MIN(remain
, MAX_IMSGSIZE
- IMSG_HEADER_SIZE
);
3410 ncommits
= (msglen
- sizeof(struct got_imsg_painted_commits
)) /
3411 sizeof(struct got_imsg_painted_commit
);
3413 wbuf
= imsg_create(ibuf
, GOT_IMSG_PAINTED_COMMITS
, 0, 0, msglen
);
3415 err
= got_error_from_errno("imsg_create PAINTED_COMMITS");
3419 /* Keep in sync with struct got_imsg_painted_commits! */
3420 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1)
3421 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3422 if (imsg_add(wbuf
, &present_in_pack
, sizeof(present_in_pack
)) == -1)
3423 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3425 while (ncommits
> 0) {
3426 qid
= STAILQ_FIRST(ids
);
3427 STAILQ_REMOVE_HEAD(ids
, entry
);
3430 color
= (intptr_t)qid
->data
;
3432 /* Keep in sync with struct got_imsg_painted_commit! */
3433 if (imsg_add(wbuf
, &qid
->id
, sizeof(qid
->id
)) == -1)
3434 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3435 if (imsg_add(wbuf
, &color
, sizeof(color
)) == -1)
3436 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3438 got_object_qid_free(qid
);
3441 imsg_close(ibuf
, wbuf
);
3442 return flush_imsg(ibuf
);
3445 const struct got_error
*
3446 got_privsep_send_painted_commits(struct imsgbuf
*ibuf
,
3447 struct got_object_id_queue
*ids
, int *nids
,
3448 int present_in_pack
, int flush
)
3450 const struct got_error
*err
;
3457 remain
= (sizeof(struct got_imsg_painted_commits
)) +
3458 *nids
* sizeof(struct got_imsg_painted_commit
);
3459 if (flush
|| remain
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
3460 err
= send_painted_commits(ids
, nids
, remain
,
3461 present_in_pack
, ibuf
);
3465 } while (flush
&& *nids
> 0);
3470 const struct got_error
*
3471 got_privsep_send_painting_commits_done(struct imsgbuf
*ibuf
)
3473 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_DONE
,
3476 return got_error_from_errno("imsg_compose "
3477 "COMMIT_PAINTING_DONE");
3479 return flush_imsg(ibuf
);
3482 const struct got_error
*
3483 got_privsep_recv_painted_commits(struct got_object_id_queue
*new_ids
,
3484 got_privsep_recv_painted_commit_cb cb
, void *cb_arg
, struct imsgbuf
*ibuf
)
3486 const struct got_error
*err
= NULL
;
3488 struct got_imsg_painted_commits icommits
;
3489 struct got_imsg_painted_commit icommit
;
3494 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3498 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3499 if (imsg
.hdr
.type
== GOT_IMSG_COMMIT_PAINTING_DONE
) {
3503 if (imsg
.hdr
.type
!= GOT_IMSG_PAINTED_COMMITS
){
3505 return got_error(GOT_ERR_PRIVSEP_MSG
);
3508 if (datalen
< sizeof(icommits
)){
3510 return got_error(GOT_ERR_PRIVSEP_LEN
);
3512 memcpy(&icommits
, imsg
.data
, sizeof(icommits
));
3513 if (icommits
.ncommits
* sizeof(icommit
) < icommits
.ncommits
||
3514 datalen
< sizeof(icommits
) +
3515 icommits
.ncommits
* sizeof(icommit
)){
3517 return got_error(GOT_ERR_PRIVSEP_LEN
);
3520 for (i
= 0; i
< icommits
.ncommits
; i
++) {
3522 (uint8_t *)imsg
.data
+ sizeof(icommits
) + i
* sizeof(icommit
),
3525 if (icommits
.present_in_pack
) {
3526 struct got_object_id id
;
3527 memcpy(&id
, &icommit
.id
, sizeof(id
));
3528 err
= cb(cb_arg
, &id
, icommit
.color
);
3532 struct got_object_qid
*qid
;
3533 err
= got_object_qid_alloc_partial(&qid
);
3536 memcpy(&qid
->id
, &icommit
.id
,
3538 qid
->data
= (void *)icommit
.color
;
3539 STAILQ_INSERT_TAIL(new_ids
, qid
, entry
);
3549 const struct got_error
*
3550 got_privsep_unveil_exec_helpers(void)
3552 const char *helpers
[] = {
3553 GOT_PATH_PROG_READ_PACK
,
3554 GOT_PATH_PROG_READ_OBJECT
,
3555 GOT_PATH_PROG_READ_COMMIT
,
3556 GOT_PATH_PROG_READ_TREE
,
3557 GOT_PATH_PROG_READ_BLOB
,
3558 GOT_PATH_PROG_READ_TAG
,
3559 GOT_PATH_PROG_READ_GITCONFIG
,
3560 GOT_PATH_PROG_READ_GOTCONFIG
,
3561 GOT_PATH_PROG_READ_PATCH
,
3562 GOT_PATH_PROG_FETCH_PACK
,
3563 GOT_PATH_PROG_INDEX_PACK
,
3564 GOT_PATH_PROG_SEND_PACK
,
3565 /* GOT_PATH_PROG_FETCH_HTTP explicitly excluded */
3569 for (i
= 0; i
< nitems(helpers
); i
++) {
3570 if (unveil(helpers
[i
], "x") == 0)
3572 return got_error_from_errno2("unveil", helpers
[i
]);
3579 got_privsep_exec_child(int imsg_fds
[2], const char *path
, const char *repo_path
)
3581 if (close(imsg_fds
[0]) == -1) {
3582 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3586 if (dup2(imsg_fds
[1], GOT_IMSG_FD_CHILD
) == -1) {
3587 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3591 closefrom(GOT_IMSG_FD_CHILD
+ 1);
3593 if (execl(path
, path
, repo_path
, (char *)NULL
) == -1) {
3594 fprintf(stderr
, "%s: %s: %s\n", getprogname(), path
,