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
);
78 if (errno
== EAGAIN
) /* Could be a file-descriptor leak. */
79 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
80 return got_error(GOT_ERR_PRIVSEP_READ
);
83 return got_error(GOT_ERR_PRIVSEP_PIPE
);
88 const struct got_error
*
89 got_privsep_wait_for_child(pid_t pid
)
93 if (waitpid(pid
, &child_status
, 0) == -1)
94 return got_error_from_errno("waitpid");
96 if (!WIFEXITED(child_status
))
97 return got_error(GOT_ERR_PRIVSEP_DIED
);
99 if (WEXITSTATUS(child_status
) != 0)
100 return got_error(GOT_ERR_PRIVSEP_EXIT
);
105 static const struct got_error
*
106 recv_imsg_error(struct imsg
*imsg
, size_t datalen
)
108 struct got_imsg_error
*ierr
;
110 if (datalen
!= sizeof(*ierr
))
111 return got_error(GOT_ERR_PRIVSEP_LEN
);
114 if (ierr
->code
== GOT_ERR_ERRNO
) {
115 static struct got_error serr
;
116 serr
.code
= GOT_ERR_ERRNO
;
117 serr
.msg
= strerror(ierr
->errno_code
);
121 return got_error(ierr
->code
);
124 const struct got_error
*
125 got_privsep_recv_imsg(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
128 const struct got_error
*err
;
131 n
= imsg_get(ibuf
, imsg
);
133 return got_error_from_errno("imsg_get");
136 err
= read_imsg(ibuf
);
139 n
= imsg_get(ibuf
, imsg
);
141 return got_error_from_errno("imsg_get");
144 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
145 return got_error(GOT_ERR_PRIVSEP_LEN
);
147 if (imsg
->hdr
.type
== GOT_IMSG_ERROR
) {
148 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
149 return recv_imsg_error(imsg
, datalen
);
155 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
157 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
159 const struct got_error
*poll_err
;
160 struct got_imsg_error ierr
;
163 ierr
.code
= err
->code
;
164 if (err
->code
== GOT_ERR_ERRNO
)
165 ierr
.errno_code
= errno
;
168 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
170 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
171 getprogname(), err
->code
, err
->msg
, strerror(errno
));
175 poll_err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
177 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
178 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
182 ret
= imsg_flush(ibuf
);
184 fprintf(stderr
, "%s: error %d \"%s\": imsg_flush: %s\n",
185 getprogname(), err
->code
, err
->msg
, strerror(errno
));
191 static const struct got_error
*
192 flush_imsg(struct imsgbuf
*ibuf
)
194 const struct got_error
*err
;
196 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
200 if (imsg_flush(ibuf
) == -1) {
202 return got_error_from_errno("imsg_flush");
208 const struct got_error
*
209 got_privsep_flush_imsg(struct imsgbuf
*ibuf
)
211 return flush_imsg(ibuf
);
214 const struct got_error
*
215 got_privsep_send_stop(int fd
)
217 const struct got_error
*err
= NULL
;
220 imsg_init(&ibuf
, fd
);
222 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1)
223 return got_error_from_errno("imsg_compose STOP");
225 err
= flush_imsg(&ibuf
);
229 const struct got_error
*
230 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
231 struct got_object_id
*id
)
233 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
234 id
, sizeof(*id
)) == -1)
235 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
237 return flush_imsg(ibuf
);
240 const struct got_error
*
241 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
242 struct got_object_id
*id
)
244 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
245 id
, sizeof(*id
)) == -1)
246 return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
248 return flush_imsg(ibuf
);
251 const struct got_error
*
252 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
254 const struct got_error
*err
= NULL
;
256 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
258 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
263 return flush_imsg(ibuf
);
266 const struct got_error
*
267 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
270 const struct got_error
*err
= NULL
;
271 struct got_imsg_raw_obj iobj
;
272 size_t len
= sizeof(iobj
);
275 memset(&iobj
, 0, sizeof(iobj
));
276 iobj
.hdrlen
= hdrlen
;
279 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
280 len
+= (size_t)size
+ hdrlen
;
282 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
284 err
= got_error_from_errno("imsg_create RAW_OBJECT");
288 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1)
289 return got_error_from_errno("imsg_add RAW_OBJECT");
291 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
292 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1)
293 return got_error_from_errno("imsg_add RAW_OBJECT");
297 imsg_close(ibuf
, wbuf
);
299 return flush_imsg(ibuf
);
302 const struct got_error
*
303 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
304 struct imsgbuf
*ibuf
)
306 const struct got_error
*err
= NULL
;
308 struct got_imsg_raw_obj
*iobj
;
313 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
317 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
319 switch (imsg
.hdr
.type
) {
320 case GOT_IMSG_RAW_OBJECT
:
321 if (datalen
< sizeof(*iobj
)) {
322 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
327 *hdrlen
= iobj
->hdrlen
;
329 if (datalen
== sizeof(*iobj
)) {
330 /* Data has been written to file descriptor. */
335 *size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
336 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
340 *outbuf
= malloc(*size
+ *hdrlen
);
341 if (*outbuf
== NULL
) {
342 err
= got_error_from_errno("malloc");
345 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
348 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
357 const struct got_error
*
358 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
359 struct got_object_id
*id
, int pack_idx
)
361 const struct got_error
*err
= NULL
;
362 struct got_imsg_packed_object iobj
;
366 memset(&iobj
, 0, sizeof(iobj
));
367 if (pack_idx
!= -1) { /* commit is packed */
369 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
377 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
379 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
384 return flush_imsg(ibuf
);
387 const struct got_error
*
388 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
389 struct got_object_id
*id
, int pack_idx
)
395 len
= sizeof(struct got_imsg_packed_object
);
399 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
401 return got_error_from_errno("imsg_create TREE_REQUEST");
403 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
404 return got_error_from_errno("imsg_add TREE_REQUEST");
406 if (pack_idx
!= -1) { /* tree is packed */
407 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1)
408 return got_error_from_errno("imsg_add TREE_REQUEST");
412 imsg_close(ibuf
, wbuf
);
414 return flush_imsg(ibuf
);
417 const struct got_error
*
418 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
419 struct got_object_id
*id
, int pack_idx
)
421 struct got_imsg_packed_object iobj
;
425 memset(&iobj
, 0, sizeof(iobj
));
426 if (pack_idx
!= -1) { /* tag is packed */
428 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
436 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
438 return got_error_from_errno("imsg_compose TAG_REQUEST");
440 return flush_imsg(ibuf
);
443 const struct got_error
*
444 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
445 struct got_object_id
*id
, int pack_idx
)
447 const struct got_error
*err
= NULL
;
448 struct got_imsg_packed_object iobj
;
452 memset(&iobj
, 0, sizeof(iobj
));
453 if (pack_idx
!= -1) { /* blob is packed */
455 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
463 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
465 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
470 return flush_imsg(ibuf
);
473 const struct got_error
*
474 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
476 const struct got_error
*err
= NULL
;
478 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
480 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
485 return flush_imsg(ibuf
);
488 static const struct got_error
*
489 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
491 const struct got_error
*err
= NULL
;
493 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
494 err
= got_error_from_errno("imsg_compose TMPFD");
499 return flush_imsg(ibuf
);
502 const struct got_error
*
503 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
505 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
508 const struct got_error
*
509 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
511 struct got_imsg_object iobj
;
513 memset(&iobj
, 0, sizeof(iobj
));
515 memcpy(&iobj
.id
, &obj
->id
, sizeof(iobj
.id
));
516 iobj
.type
= obj
->type
;
517 iobj
.flags
= obj
->flags
;
518 iobj
.hdrlen
= obj
->hdrlen
;
519 iobj
.size
= obj
->size
;
520 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
521 iobj
.pack_offset
= obj
->pack_offset
;
522 iobj
.pack_idx
= obj
->pack_idx
;
525 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
527 return got_error_from_errno("imsg_compose OBJECT");
529 return flush_imsg(ibuf
);
532 const struct got_error
*
533 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
534 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
535 struct got_pathlist_head
*wanted_branches
,
536 struct got_pathlist_head
*wanted_refs
, int list_refs_only
,
537 const char *worktree_branch
, const char *remote_head
,
538 int no_head
, int verbosity
)
540 const struct got_error
*err
= NULL
;
542 struct got_pathlist_entry
*pe
;
543 struct got_imsg_fetch_request fetchreq
;
544 size_t remote_head_len
, worktree_branch_len
, len
= sizeof(fetchreq
);
546 if (worktree_branch
) {
547 worktree_branch_len
= strlen(worktree_branch
);
548 len
+= worktree_branch_len
;
551 remote_head_len
= strlen(remote_head
);
552 len
+= remote_head_len
;
555 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
557 return got_error(GOT_ERR_NO_SPACE
);
560 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, len
);
562 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
564 memset(&fetchreq
, 0, sizeof(fetchreq
));
565 fetchreq
.no_head
= no_head
;
566 fetchreq
.fetch_all_branches
= fetch_all_branches
;
567 fetchreq
.list_refs_only
= list_refs_only
;
568 fetchreq
.verbosity
= verbosity
;
569 if (worktree_branch
!= NULL
)
570 fetchreq
.worktree_branch_len
= worktree_branch_len
;
571 if (remote_head
!= NULL
)
572 fetchreq
.remote_head_len
= remote_head_len
;
573 TAILQ_FOREACH(pe
, have_refs
, entry
)
574 fetchreq
.n_have_refs
++;
575 TAILQ_FOREACH(pe
, wanted_branches
, entry
)
576 fetchreq
.n_wanted_branches
++;
577 TAILQ_FOREACH(pe
, wanted_refs
, entry
)
578 fetchreq
.n_wanted_refs
++;
579 if (imsg_add(wbuf
, &fetchreq
, sizeof(fetchreq
)) == -1)
580 return got_error_from_errno("imsg_add FETCH_REQUEST");
581 if (worktree_branch
) {
582 if (imsg_add(wbuf
, worktree_branch
, worktree_branch_len
) == -1)
583 return got_error_from_errno("imsg_add FETCH_REQUEST");
586 if (imsg_add(wbuf
, remote_head
, remote_head_len
) == -1)
587 return got_error_from_errno("imsg_add FETCH_REQUEST");
590 imsg_close(ibuf
, wbuf
);
592 err
= flush_imsg(ibuf
);
599 TAILQ_FOREACH(pe
, have_refs
, entry
) {
600 const char *name
= pe
->path
;
601 size_t name_len
= pe
->path_len
;
602 struct got_object_id
*id
= pe
->data
;
604 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
605 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
607 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
609 /* Keep in sync with struct got_imsg_fetch_have_ref! */
610 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
611 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
612 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
613 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
614 if (imsg_add(wbuf
, name
, name_len
) == -1)
615 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
618 imsg_close(ibuf
, wbuf
);
619 err
= flush_imsg(ibuf
);
624 TAILQ_FOREACH(pe
, wanted_branches
, entry
) {
625 const char *name
= pe
->path
;
626 size_t name_len
= pe
->path_len
;
628 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
629 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
632 return got_error_from_errno(
633 "imsg_create FETCH_WANTED_BRANCH");
635 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
636 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
637 return got_error_from_errno(
638 "imsg_add FETCH_WANTED_BRANCH");
639 if (imsg_add(wbuf
, name
, name_len
) == -1)
640 return got_error_from_errno(
641 "imsg_add FETCH_WANTED_BRANCH");
644 imsg_close(ibuf
, wbuf
);
645 err
= flush_imsg(ibuf
);
650 TAILQ_FOREACH(pe
, wanted_refs
, entry
) {
651 const char *name
= pe
->path
;
652 size_t name_len
= pe
->path_len
;
654 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
655 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
658 return got_error_from_errno(
659 "imsg_create FETCH_WANTED_REF");
661 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
662 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
663 return got_error_from_errno(
664 "imsg_add FETCH_WANTED_REF");
665 if (imsg_add(wbuf
, name
, name_len
) == -1)
666 return got_error_from_errno(
667 "imsg_add FETCH_WANTED_REF");
670 imsg_close(ibuf
, wbuf
);
671 err
= flush_imsg(ibuf
);
681 const struct got_error
*
682 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
684 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
687 const struct got_error
*
688 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
689 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
690 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
692 const struct got_error
*err
= NULL
;
695 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
703 *server_progress
= NULL
;
705 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
707 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
711 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
712 switch (imsg
.hdr
.type
) {
713 case GOT_IMSG_FETCH_SYMREFS
:
714 if (datalen
< sizeof(*isymrefs
)) {
715 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
718 if (isymrefs
!= NULL
) {
719 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
722 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
723 off
= sizeof(*isymrefs
);
724 remain
= datalen
- off
;
725 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
726 struct got_imsg_fetch_symref
*s
;
728 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
729 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
732 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
734 remain
-= sizeof(*s
);
735 if (remain
< s
->name_len
) {
736 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
739 name
= strndup(imsg
.data
+ off
, s
->name_len
);
741 err
= got_error_from_errno("strndup");
745 remain
-= s
->name_len
;
746 if (remain
< s
->target_len
) {
747 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
751 target
= strndup(imsg
.data
+ off
, s
->target_len
);
752 if (target
== NULL
) {
753 err
= got_error_from_errno("strndup");
757 off
+= s
->target_len
;
758 remain
-= s
->target_len
;
759 err
= got_pathlist_append(symrefs
, name
, target
);
767 case GOT_IMSG_FETCH_REF
:
768 if (datalen
<= sizeof(**id
)) {
769 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
772 *id
= malloc(sizeof(**id
));
774 err
= got_error_from_errno("malloc");
777 memcpy(*id
, imsg
.data
, sizeof(**id
));
778 *refname
= strndup(imsg
.data
+ sizeof(**id
),
779 datalen
- sizeof(**id
));
780 if (*refname
== NULL
) {
781 err
= got_error_from_errno("strndup");
785 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
787 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
790 *server_progress
= strndup(imsg
.data
, datalen
);
791 if (*server_progress
== NULL
) {
792 err
= got_error_from_errno("strndup");
795 for (i
= 0; i
< datalen
; i
++) {
796 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
797 !isspace((unsigned char)(*server_progress
)[i
])) {
798 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
799 free(*server_progress
);
800 *server_progress
= NULL
;
805 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
806 if (datalen
< sizeof(*packfile_size
)) {
807 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
810 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
812 case GOT_IMSG_FETCH_DONE
:
813 if (datalen
!= SHA1_DIGEST_LENGTH
) {
814 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
817 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
821 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
835 static const struct got_error
*
836 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
837 int delete, struct imsgbuf
*ibuf
)
842 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
843 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
845 return got_error_from_errno("imsg_create SEND_REF");
847 /* Keep in sync with struct got_imsg_send_ref! */
848 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
849 return got_error_from_errno("imsg_add SEND_REF");
850 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1)
851 return got_error_from_errno("imsg_add SEND_REF");
852 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
853 return got_error_from_errno("imsg_add SEND_REF");
854 if (imsg_add(wbuf
, name
, name_len
) == -1)
855 return got_error_from_errno("imsg_add SEND_REF");
858 imsg_close(ibuf
, wbuf
);
859 return flush_imsg(ibuf
);
862 const struct got_error
*
863 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
864 struct got_pathlist_head
*have_refs
,
865 struct got_pathlist_head
*delete_refs
,
868 const struct got_error
*err
= NULL
;
869 struct got_pathlist_entry
*pe
;
870 struct got_imsg_send_request sendreq
;
871 struct got_object_id zero_id
;
873 memset(&zero_id
, 0, sizeof(zero_id
));
874 memset(&sendreq
, 0, sizeof(sendreq
));
875 sendreq
.verbosity
= verbosity
;
876 TAILQ_FOREACH(pe
, have_refs
, entry
)
878 TAILQ_FOREACH(pe
, delete_refs
, entry
)
880 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
881 &sendreq
, sizeof(sendreq
)) == -1) {
882 err
= got_error_from_errno(
883 "imsg_compose FETCH_SERVER_PROGRESS");
887 err
= flush_imsg(ibuf
);
892 TAILQ_FOREACH(pe
, have_refs
, entry
) {
893 const char *name
= pe
->path
;
894 size_t name_len
= pe
->path_len
;
895 struct got_object_id
*id
= pe
->data
;
896 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
901 TAILQ_FOREACH(pe
, delete_refs
, entry
) {
902 const char *name
= pe
->path
;
903 size_t name_len
= pe
->path_len
;
904 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
909 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
910 err
= got_error_from_errno("close");
915 const struct got_error
*
916 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
917 struct imsgbuf
*ibuf
)
919 const struct got_error
*err
= NULL
;
923 struct got_imsg_send_remote_ref iremote_ref
;
924 struct got_object_id
*id
= NULL
;
925 char *refname
= NULL
;
926 struct got_pathlist_entry
*new;
929 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
932 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
933 switch (imsg
.hdr
.type
) {
934 case GOT_IMSG_SEND_REMOTE_REF
:
935 if (datalen
< sizeof(iremote_ref
)) {
936 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
939 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
940 if (datalen
!= sizeof(iremote_ref
) +
941 iremote_ref
.name_len
) {
942 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
945 id
= malloc(sizeof(*id
));
947 err
= got_error_from_errno("malloc");
950 memcpy(id
, &iremote_ref
.id
, sizeof(*id
));
951 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
952 datalen
- sizeof(iremote_ref
));
953 if (refname
== NULL
) {
954 err
= got_error_from_errno("strndup");
957 err
= got_pathlist_insert(&new, remote_refs
,
961 if (new == NULL
) { /* duplicate which wasn't inserted */
968 case GOT_IMSG_SEND_PACK_REQUEST
:
970 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
973 /* got-send-pack is now waiting for a pack file. */
977 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
988 const struct got_error
*
989 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
991 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
994 const struct got_error
*
995 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
996 int *success
, char **refname
, char **errmsg
, struct imsgbuf
*ibuf
)
998 const struct got_error
*err
= NULL
;
1001 struct got_imsg_send_ref_status iref_status
;
1003 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1009 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1013 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1014 switch (imsg
.hdr
.type
) {
1015 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
1016 if (datalen
< sizeof(*bytes_sent
)) {
1017 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1020 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
1022 case GOT_IMSG_SEND_REF_STATUS
:
1023 if (datalen
< sizeof(iref_status
)) {
1024 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1027 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
1028 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
+
1029 iref_status
.errmsg_len
) {
1030 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1033 *success
= iref_status
.success
;
1034 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1035 iref_status
.name_len
);
1037 if (iref_status
.errmsg_len
!= 0)
1038 *errmsg
= strndup(imsg
.data
+ sizeof(iref_status
) +
1039 iref_status
.name_len
, iref_status
.errmsg_len
);
1041 case GOT_IMSG_SEND_DONE
:
1043 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1049 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1057 const struct got_error
*
1058 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, uint8_t *pack_sha1
,
1061 const struct got_error
*err
= NULL
;
1063 /* Keep in sync with struct got_imsg_index_pack_request */
1064 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1065 pack_sha1
, SHA1_DIGEST_LENGTH
) == -1) {
1066 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1070 return flush_imsg(ibuf
);
1073 const struct got_error
*
1074 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1076 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1079 const struct got_error
*
1080 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1081 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1082 struct imsgbuf
*ibuf
)
1084 const struct got_error
*err
= NULL
;
1086 struct got_imsg_index_pack_progress
*iprogress
;
1094 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1098 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1099 switch (imsg
.hdr
.type
) {
1100 case GOT_IMSG_IDXPACK_PROGRESS
:
1101 if (datalen
< sizeof(*iprogress
)) {
1102 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1105 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1106 if (iprogress
->nobj_total
< 0 || iprogress
->nobj_indexed
< 0 ||
1107 iprogress
->nobj_loose
< 0 || iprogress
->nobj_resolved
< 0) {
1108 err
= got_error(GOT_ERR_RANGE
);
1111 *nobj_total
= iprogress
->nobj_total
;
1112 *nobj_indexed
= iprogress
->nobj_indexed
;
1113 *nobj_loose
= iprogress
->nobj_loose
;
1114 *nobj_resolved
= iprogress
->nobj_resolved
;
1116 case GOT_IMSG_IDXPACK_DONE
:
1118 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1124 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1132 const struct got_error
*
1133 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1134 struct imsgbuf
*ibuf
)
1136 struct got_imsg_object
*iobj
;
1137 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1139 if (datalen
!= sizeof(*iobj
))
1140 return got_error(GOT_ERR_PRIVSEP_LEN
);
1143 if (iobj
->pack_offset
< 0)
1144 return got_error(GOT_ERR_PACK_OFFSET
);
1146 *obj
= calloc(1, sizeof(**obj
));
1148 return got_error_from_errno("calloc");
1150 memcpy(&(*obj
)->id
, &iobj
->id
, sizeof(iobj
->id
));
1151 (*obj
)->type
= iobj
->type
;
1152 (*obj
)->flags
= iobj
->flags
;
1153 (*obj
)->hdrlen
= iobj
->hdrlen
;
1154 (*obj
)->size
= iobj
->size
;
1155 /* path_packfile is handled by caller */
1156 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1157 (*obj
)->pack_offset
= iobj
->pack_offset
;
1158 (*obj
)->pack_idx
= iobj
->pack_idx
;
1160 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1164 const struct got_error
*
1165 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1167 const struct got_error
*err
= NULL
;
1169 const size_t min_datalen
=
1170 MIN(sizeof(struct got_imsg_error
), sizeof(struct got_imsg_object
));
1174 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1178 switch (imsg
.hdr
.type
) {
1179 case GOT_IMSG_OBJECT
:
1180 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1183 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1192 static const struct got_error
*
1193 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1196 const struct got_error
*err
= NULL
;
1197 size_t offset
, remain
;
1200 remain
= logmsg_len
;
1201 while (remain
> 0) {
1202 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1204 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1205 commit
->logmsg
+ offset
, n
) == -1) {
1206 err
= got_error_from_errno("imsg_compose "
1211 err
= flush_imsg(ibuf
);
1222 const struct got_error
*
1223 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1225 const struct got_error
*err
= NULL
;
1226 struct got_imsg_commit_object
*icommit
;
1229 struct got_object_qid
*qid
;
1230 size_t author_len
= strlen(commit
->author
);
1231 size_t committer_len
= strlen(commit
->committer
);
1232 size_t logmsg_len
= strlen(commit
->logmsg
);
1234 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1235 commit
->nparents
* sizeof(struct got_object_id
);
1237 buf
= malloc(total
);
1239 return got_error_from_errno("malloc");
1241 icommit
= (struct got_imsg_commit_object
*)buf
;
1242 memcpy(&icommit
->tree_id
, commit
->tree_id
, sizeof(icommit
->tree_id
));
1243 icommit
->author_len
= author_len
;
1244 icommit
->author_time
= commit
->author_time
;
1245 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1246 icommit
->committer_len
= committer_len
;
1247 icommit
->committer_time
= commit
->committer_time
;
1248 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1249 icommit
->logmsg_len
= logmsg_len
;
1250 icommit
->nparents
= commit
->nparents
;
1252 len
= sizeof(*icommit
);
1253 memcpy(buf
+ len
, commit
->author
, author_len
);
1255 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1256 len
+= committer_len
;
1257 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1258 memcpy(buf
+ len
, &qid
->id
, sizeof(qid
->id
));
1259 len
+= sizeof(qid
->id
);
1262 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1263 err
= got_error_from_errno("imsg_compose COMMIT");
1267 if (logmsg_len
== 0 ||
1268 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1269 err
= flush_imsg(ibuf
);
1273 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1279 static const struct got_error
*
1280 get_commit_from_imsg(struct got_commit_object
**commit
,
1281 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1283 const struct got_error
*err
= NULL
;
1284 struct got_imsg_commit_object
*icommit
;
1288 if (datalen
< sizeof(*icommit
))
1289 return got_error(GOT_ERR_PRIVSEP_LEN
);
1291 icommit
= imsg
->data
;
1292 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1293 icommit
->committer_len
+
1294 icommit
->nparents
* sizeof(struct got_object_id
))
1295 return got_error(GOT_ERR_PRIVSEP_LEN
);
1297 if (icommit
->nparents
< 0)
1298 return got_error(GOT_ERR_PRIVSEP_LEN
);
1300 len
+= sizeof(*icommit
);
1302 *commit
= got_object_commit_alloc_partial();
1303 if (*commit
== NULL
)
1304 return got_error_from_errno(
1305 "got_object_commit_alloc_partial");
1307 memcpy((*commit
)->tree_id
, &icommit
->tree_id
,
1308 sizeof(icommit
->tree_id
));
1309 (*commit
)->author_time
= icommit
->author_time
;
1310 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1311 (*commit
)->committer_time
= icommit
->committer_time
;
1312 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1314 (*commit
)->author
= strndup(imsg
->data
+ len
, icommit
->author_len
);
1315 if ((*commit
)->author
== NULL
) {
1316 err
= got_error_from_errno("strndup");
1319 len
+= icommit
->author_len
;
1321 (*commit
)->committer
= strndup(imsg
->data
+ len
,
1322 icommit
->committer_len
);
1323 if ((*commit
)->committer
== NULL
) {
1324 err
= got_error_from_errno("strndup");
1327 len
+= icommit
->committer_len
;
1329 if (icommit
->logmsg_len
== 0) {
1330 (*commit
)->logmsg
= strdup("");
1331 if ((*commit
)->logmsg
== NULL
) {
1332 err
= got_error_from_errno("strdup");
1336 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1338 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1339 if ((*commit
)->logmsg
== NULL
) {
1340 err
= got_error_from_errno("malloc");
1343 while (remain
> 0) {
1344 struct imsg imsg_log
;
1345 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1348 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1352 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1353 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1357 memcpy((*commit
)->logmsg
+ offset
,
1359 imsg_free(&imsg_log
);
1363 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1366 for (i
= 0; i
< icommit
->nparents
; i
++) {
1367 struct got_object_qid
*qid
;
1369 err
= got_object_qid_alloc_partial(&qid
);
1372 memcpy(&qid
->id
, imsg
->data
+ len
+
1373 i
* sizeof(qid
->id
), sizeof(qid
->id
));
1374 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1375 (*commit
)->nparents
++;
1379 got_object_commit_close(*commit
);
1385 const struct got_error
*
1386 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1388 const struct got_error
*err
= NULL
;
1391 const size_t min_datalen
=
1392 MIN(sizeof(struct got_imsg_error
),
1393 sizeof(struct got_imsg_commit_object
));
1397 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1401 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1403 switch (imsg
.hdr
.type
) {
1404 case GOT_IMSG_COMMIT
:
1405 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1408 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1417 static const struct got_error
*
1418 send_tree_entries_batch(struct imsgbuf
*ibuf
,
1419 struct got_parsed_tree_entry
*entries
, int idx0
, int idxN
, size_t len
)
1422 struct got_imsg_tree_entries ientries
;
1425 memset(&ientries
, 0, sizeof(ientries
));
1427 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRIES
, 0, 0, len
);
1429 return got_error_from_errno("imsg_create TREE_ENTRY");
1431 ientries
.nentries
= idxN
- idx0
+ 1;
1432 if (imsg_add(wbuf
, &ientries
, sizeof(ientries
)) == -1)
1433 return got_error_from_errno("imsg_add TREE_ENTRY");
1435 for (i
= idx0
; i
<= idxN
; i
++) {
1436 struct got_parsed_tree_entry
*pte
= &entries
[i
];
1438 /* Keep in sync with struct got_imsg_tree_entry definition! */
1439 if (imsg_add(wbuf
, pte
->id
, SHA1_DIGEST_LENGTH
) == -1)
1440 return got_error_from_errno("imsg_add TREE_ENTRY");
1441 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1)
1442 return got_error_from_errno("imsg_add TREE_ENTRY");
1443 if (imsg_add(wbuf
, &pte
->namelen
, sizeof(pte
->namelen
)) == -1)
1444 return got_error_from_errno("imsg_add TREE_ENTRY");
1446 /* Remaining bytes are the entry's name. */
1447 if (imsg_add(wbuf
, pte
->name
, pte
->namelen
) == -1)
1448 return got_error_from_errno("imsg_add TREE_ENTRY");
1452 imsg_close(ibuf
, wbuf
);
1456 static const struct got_error
*
1457 send_tree_entries(struct imsgbuf
*ibuf
, struct got_parsed_tree_entry
*entries
,
1460 const struct got_error
*err
= NULL
;
1462 size_t entries_len
= sizeof(struct got_imsg_tree_entries
);
1465 for (j
= 0; j
< nentries
; j
++) {
1466 struct got_parsed_tree_entry
*pte
= &entries
[j
];
1467 size_t len
= sizeof(struct got_imsg_tree_entry
) + pte
->namelen
;
1470 entries_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1471 err
= send_tree_entries_batch(ibuf
, entries
,
1472 i
, j
- 1, entries_len
);
1476 entries_len
= sizeof(struct got_imsg_tree_entries
);
1483 err
= send_tree_entries_batch(ibuf
, entries
, i
, j
- 1,
1492 const struct got_error
*
1493 got_privsep_send_tree(struct imsgbuf
*ibuf
,
1494 struct got_parsed_tree_entry
*entries
, int nentries
)
1496 const struct got_error
*err
= NULL
;
1497 struct got_imsg_tree_object itree
;
1499 memset(&itree
, 0, sizeof(itree
));
1500 itree
.nentries
= nentries
;
1501 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1503 return got_error_from_errno("imsg_compose TREE");
1505 err
= send_tree_entries(ibuf
, entries
, nentries
);
1509 return flush_imsg(ibuf
);
1513 static const struct got_error
*
1514 recv_tree_entries(void *data
, size_t datalen
, struct got_tree_object
*tree
,
1517 const struct got_error
*err
= NULL
;
1518 struct got_imsg_tree_entries
*ientries
;
1519 struct got_tree_entry
*te
;
1523 if (datalen
<= sizeof(*ientries
) ||
1524 datalen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
1525 return got_error(GOT_ERR_PRIVSEP_LEN
);
1527 ientries
= (struct got_imsg_tree_entries
*)data
;
1528 if (ientries
->nentries
> INT_MAX
) {
1529 return got_error_msg(GOT_ERR_NO_SPACE
,
1530 "too many tree entries");
1533 te_offset
= sizeof(*ientries
);
1534 for (i
= 0; i
< ientries
->nentries
; i
++) {
1535 struct got_imsg_tree_entry ite
;
1536 const char *te_name
;
1537 uint8_t *buf
= (uint8_t *)data
+ te_offset
;
1539 if (te_offset
>= datalen
) {
1540 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1544 /* Might not be aligned, size is ~32 bytes. */
1545 memcpy(&ite
, buf
, sizeof(ite
));
1547 if (ite
.namelen
>= sizeof(te
->name
)) {
1548 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1551 if (te_offset
+ sizeof(ite
) + ite
.namelen
> datalen
) {
1552 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1556 if (*nentries
>= tree
->nentries
) {
1557 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1560 te
= &tree
->entries
[*nentries
];
1561 te_name
= buf
+ sizeof(ite
);
1562 memcpy(te
->name
, te_name
, ite
.namelen
);
1563 te
->name
[ite
.namelen
] = '\0';
1564 memcpy(te
->id
.sha1
, ite
.id
, SHA1_DIGEST_LENGTH
);
1565 te
->mode
= ite
.mode
;
1566 te
->idx
= *nentries
;
1569 te_offset
+= sizeof(ite
) + ite
.namelen
;
1575 const struct got_error
*
1576 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1578 const struct got_error
*err
= NULL
;
1579 const size_t min_datalen
=
1580 MIN(sizeof(struct got_imsg_error
),
1581 sizeof(struct got_imsg_tree_object
));
1582 struct got_imsg_tree_object
*itree
;
1587 while (*tree
== NULL
|| nentries
< (*tree
)->nentries
) {
1591 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1595 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1597 switch (imsg
.hdr
.type
) {
1599 /* This message should only appear once. */
1600 if (*tree
!= NULL
) {
1601 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1604 if (datalen
!= sizeof(*itree
)) {
1605 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1609 if (itree
->nentries
< 0) {
1610 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1613 *tree
= malloc(sizeof(**tree
));
1614 if (*tree
== NULL
) {
1615 err
= got_error_from_errno("malloc");
1618 (*tree
)->entries
= calloc(itree
->nentries
,
1619 sizeof(struct got_tree_entry
));
1620 if ((*tree
)->entries
== NULL
) {
1621 err
= got_error_from_errno("malloc");
1626 (*tree
)->nentries
= itree
->nentries
;
1627 (*tree
)->refcnt
= 0;
1629 case GOT_IMSG_TREE_ENTRIES
:
1630 /* This message should be preceeded by GOT_IMSG_TREE. */
1631 if (*tree
== NULL
) {
1632 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1635 err
= recv_tree_entries(imsg
.data
, datalen
,
1639 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1648 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1650 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1651 got_object_tree_close(*tree
);
1658 const struct got_error
*
1659 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1660 const uint8_t *data
)
1662 struct got_imsg_blob iblob
;
1664 memset(&iblob
, 0, sizeof(iblob
));
1666 iblob
.hdrlen
= hdrlen
;
1671 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1672 return got_error(GOT_ERR_NO_SPACE
);
1674 buf
= malloc(sizeof(iblob
) + size
);
1676 return got_error_from_errno("malloc");
1678 memcpy(buf
, &iblob
, sizeof(iblob
));
1679 memcpy(buf
+ sizeof(iblob
), data
, size
);
1680 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1681 sizeof(iblob
) + size
) == -1) {
1683 return got_error_from_errno("imsg_compose BLOB");
1687 /* Data has already been written to file descriptor. */
1688 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1689 sizeof(iblob
)) == -1)
1690 return got_error_from_errno("imsg_compose BLOB");
1694 return flush_imsg(ibuf
);
1697 const struct got_error
*
1698 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1699 struct imsgbuf
*ibuf
)
1701 const struct got_error
*err
= NULL
;
1703 struct got_imsg_blob
*iblob
;
1708 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1712 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1714 switch (imsg
.hdr
.type
) {
1716 if (datalen
< sizeof(*iblob
)) {
1717 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1721 *size
= iblob
->size
;
1722 *hdrlen
= iblob
->hdrlen
;
1724 if (datalen
== sizeof(*iblob
)) {
1725 /* Data has been written to file descriptor. */
1729 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
||
1730 *size
> datalen
+ sizeof(*iblob
)) {
1731 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1735 *outbuf
= malloc(*size
);
1736 if (*outbuf
== NULL
) {
1737 err
= got_error_from_errno("malloc");
1740 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1743 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1752 static const struct got_error
*
1753 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1755 const struct got_error
*err
= NULL
;
1756 size_t offset
, remain
;
1759 remain
= tagmsg_len
;
1760 while (remain
> 0) {
1761 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1763 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1764 tag
->tagmsg
+ offset
, n
) == -1) {
1765 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1769 err
= flush_imsg(ibuf
);
1780 const struct got_error
*
1781 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1783 const struct got_error
*err
= NULL
;
1784 struct got_imsg_tag_object
*itag
;
1787 size_t tag_len
= strlen(tag
->tag
);
1788 size_t tagger_len
= strlen(tag
->tagger
);
1789 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1791 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1793 buf
= malloc(total
);
1795 return got_error_from_errno("malloc");
1797 itag
= (struct got_imsg_tag_object
*)buf
;
1798 memcpy(&itag
->id
, &tag
->id
, sizeof(itag
->id
));
1799 itag
->obj_type
= tag
->obj_type
;
1800 itag
->tag_len
= tag_len
;
1801 itag
->tagger_len
= tagger_len
;
1802 itag
->tagger_time
= tag
->tagger_time
;
1803 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1804 itag
->tagmsg_len
= tagmsg_len
;
1806 len
= sizeof(*itag
);
1807 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1809 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1812 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1813 err
= got_error_from_errno("imsg_compose TAG");
1817 if (tagmsg_len
== 0 ||
1818 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1819 err
= flush_imsg(ibuf
);
1823 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1829 const struct got_error
*
1830 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1832 const struct got_error
*err
= NULL
;
1834 struct got_imsg_tag_object
*itag
;
1835 size_t len
, datalen
;
1836 const size_t min_datalen
=
1837 MIN(sizeof(struct got_imsg_error
),
1838 sizeof(struct got_imsg_tag_object
));
1842 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1846 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1849 switch (imsg
.hdr
.type
) {
1851 if (datalen
< sizeof(*itag
)) {
1852 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1856 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1858 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1861 len
+= sizeof(*itag
);
1863 *tag
= calloc(1, sizeof(**tag
));
1865 err
= got_error_from_errno("calloc");
1869 memcpy(&(*tag
)->id
, &itag
->id
, sizeof(itag
->id
));
1871 (*tag
)->tag
= strndup(imsg
.data
+ len
, itag
->tag_len
);
1872 if ((*tag
)->tag
== NULL
) {
1873 err
= got_error_from_errno("strndup");
1876 len
+= itag
->tag_len
;
1878 (*tag
)->obj_type
= itag
->obj_type
;
1879 (*tag
)->tagger_time
= itag
->tagger_time
;
1880 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1882 (*tag
)->tagger
= strndup(imsg
.data
+ len
, itag
->tagger_len
);
1883 if ((*tag
)->tagger
== NULL
) {
1884 err
= got_error_from_errno("strndup");
1887 len
+= itag
->tagger_len
;
1889 if (itag
->tagmsg_len
== 0) {
1890 (*tag
)->tagmsg
= strdup("");
1891 if ((*tag
)->tagmsg
== NULL
) {
1892 err
= got_error_from_errno("strdup");
1896 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1898 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1899 if ((*tag
)->tagmsg
== NULL
) {
1900 err
= got_error_from_errno("malloc");
1903 while (remain
> 0) {
1904 struct imsg imsg_log
;
1905 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1908 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1912 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1913 return got_error(GOT_ERR_PRIVSEP_MSG
);
1915 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1917 imsg_free(&imsg_log
);
1921 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1926 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1935 const struct got_error
*
1936 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1937 struct got_packidx
*packidx
)
1939 const struct got_error
*err
= NULL
;
1940 struct got_imsg_packidx ipackidx
;
1941 struct got_imsg_pack ipack
;
1944 memset(&ipackidx
, 0, sizeof(ipackidx
));
1945 memset(&ipack
, 0, sizeof(ipack
));
1947 ipackidx
.len
= packidx
->len
;
1948 ipackidx
.packfile_size
= pack
->filesize
;
1949 fd
= dup(packidx
->fd
);
1951 return got_error_from_errno("dup");
1953 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1954 sizeof(ipackidx
)) == -1) {
1955 err
= got_error_from_errno("imsg_compose PACKIDX");
1960 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1961 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1962 return got_error(GOT_ERR_NO_SPACE
);
1963 ipack
.filesize
= pack
->filesize
;
1967 return got_error_from_errno("dup");
1969 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
1971 err
= got_error_from_errno("imsg_compose PACK");
1976 return flush_imsg(ibuf
);
1979 const struct got_error
*
1980 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
1981 struct got_object_id
*id
)
1983 struct got_imsg_packed_object iobj
;
1985 memset(&iobj
, 0, sizeof(iobj
));
1987 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
1989 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
1990 &iobj
, sizeof(iobj
)) == -1)
1991 return got_error_from_errno("imsg_compose "
1992 "PACKED_OBJECT_REQUEST");
1994 return flush_imsg(ibuf
);
1997 const struct got_error
*
1998 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
1999 struct got_object_id
*id
)
2001 struct got_imsg_packed_object iobj
;
2003 memset(&iobj
, 0, sizeof(iobj
));
2005 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2007 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
2008 &iobj
, sizeof(iobj
)) == -1)
2009 return got_error_from_errno("imsg_compose "
2010 "PACKED_OBJECT_REQUEST");
2012 return flush_imsg(ibuf
);
2015 const struct got_error
*
2016 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2018 const struct got_error
*err
= NULL
;
2020 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2022 err
= got_error_from_errno("imsg_compose "
2023 "GITCONFIG_PARSE_REQUEST");
2028 return flush_imsg(ibuf
);
2031 const struct got_error
*
2032 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2034 if (imsg_compose(ibuf
,
2035 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2037 return got_error_from_errno("imsg_compose "
2038 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2040 return flush_imsg(ibuf
);
2043 const struct got_error
*
2044 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2046 if (imsg_compose(ibuf
,
2047 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2049 return got_error_from_errno("imsg_compose "
2050 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2052 return flush_imsg(ibuf
);
2056 const struct got_error
*
2057 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2059 if (imsg_compose(ibuf
,
2060 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2061 return got_error_from_errno("imsg_compose "
2062 "GITCONFIG_AUTHOR_NAME_REQUEST");
2064 return flush_imsg(ibuf
);
2067 const struct got_error
*
2068 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2070 if (imsg_compose(ibuf
,
2071 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2072 return got_error_from_errno("imsg_compose "
2073 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2075 return flush_imsg(ibuf
);
2078 const struct got_error
*
2079 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2081 if (imsg_compose(ibuf
,
2082 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2083 return got_error_from_errno("imsg_compose "
2084 "GITCONFIG_REMOTE_REQUEST");
2086 return flush_imsg(ibuf
);
2089 const struct got_error
*
2090 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2092 if (imsg_compose(ibuf
,
2093 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2094 return got_error_from_errno("imsg_compose "
2095 "GITCONFIG_OWNER_REQUEST");
2097 return flush_imsg(ibuf
);
2100 const struct got_error
*
2101 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2103 const struct got_error
*err
= NULL
;
2109 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2112 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2114 switch (imsg
.hdr
.type
) {
2115 case GOT_IMSG_GITCONFIG_STR_VAL
:
2118 *str
= strndup(imsg
.data
, datalen
);
2120 err
= got_error_from_errno("strndup");
2125 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2133 const struct got_error
*
2134 got_privsep_recv_gitconfig_pair(char **key
, char **val
, struct imsgbuf
*ibuf
)
2136 const struct got_error
*err
= NULL
;
2137 struct got_imsg_gitconfig_pair p
;
2144 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2149 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2151 if (imsg
.hdr
.type
!= GOT_IMSG_GITCONFIG_PAIR
) {
2152 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2156 if (datalen
< sizeof(p
)) {
2157 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2161 memcpy(&p
, data
, sizeof(p
));
2164 if (datalen
!= sizeof(p
) + p
.klen
+ p
.vlen
) {
2165 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2169 *key
= strndup(data
, p
.klen
);
2171 err
= got_error_from_errno("strndup");
2176 *val
= strndup(data
, p
.vlen
);
2178 err
= got_error_from_errno("strndup");
2187 const struct got_error
*
2188 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2190 const struct got_error
*err
= NULL
;
2193 const size_t min_datalen
=
2194 MIN(sizeof(struct got_imsg_error
), sizeof(int));
2198 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2201 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2203 switch (imsg
.hdr
.type
) {
2204 case GOT_IMSG_GITCONFIG_INT_VAL
:
2205 if (datalen
!= sizeof(*val
)) {
2206 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2209 memcpy(val
, imsg
.data
, sizeof(*val
));
2212 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2221 free_remote_data(struct got_remote_repo
*remote
)
2226 free(remote
->fetch_url
);
2227 free(remote
->send_url
);
2228 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2229 free(remote
->fetch_branches
[i
]);
2230 free(remote
->fetch_branches
);
2231 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2232 free(remote
->send_branches
[i
]);
2233 free(remote
->send_branches
);
2234 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2235 free(remote
->fetch_refs
[i
]);
2236 free(remote
->fetch_refs
);
2239 const struct got_error
*
2240 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2241 int *nremotes
, struct imsgbuf
*ibuf
)
2243 const struct got_error
*err
= NULL
;
2246 struct got_imsg_remotes iremotes
;
2247 struct got_imsg_remote iremote
;
2251 iremotes
.nremotes
= 0;
2253 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2256 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2258 switch (imsg
.hdr
.type
) {
2259 case GOT_IMSG_GITCONFIG_REMOTES
:
2260 if (datalen
!= sizeof(iremotes
)) {
2261 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2264 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2265 if (iremotes
.nremotes
== 0) {
2272 return got_error(GOT_ERR_PRIVSEP_MSG
);
2277 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2278 if (*remotes
== NULL
)
2279 return got_error_from_errno("recallocarray");
2281 while (*nremotes
< iremotes
.nremotes
) {
2282 struct got_remote_repo
*remote
;
2284 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2287 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2289 switch (imsg
.hdr
.type
) {
2290 case GOT_IMSG_GITCONFIG_REMOTE
:
2291 remote
= &(*remotes
)[*nremotes
];
2292 memset(remote
, 0, sizeof(*remote
));
2293 if (datalen
< sizeof(iremote
)) {
2294 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2297 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2298 if (iremote
.name_len
== 0 ||
2299 iremote
.fetch_url_len
== 0 ||
2300 iremote
.send_url_len
== 0 ||
2301 (sizeof(iremote
) + iremote
.name_len
+
2302 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2303 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2306 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2308 if (remote
->name
== NULL
) {
2309 err
= got_error_from_errno("strndup");
2312 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2313 iremote
.name_len
, iremote
.fetch_url_len
);
2314 if (remote
->fetch_url
== NULL
) {
2315 err
= got_error_from_errno("strndup");
2316 free_remote_data(remote
);
2319 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2320 iremote
.name_len
+ iremote
.fetch_url_len
,
2321 iremote
.send_url_len
);
2322 if (remote
->send_url
== NULL
) {
2323 err
= got_error_from_errno("strndup");
2324 free_remote_data(remote
);
2327 remote
->mirror_references
= iremote
.mirror_references
;
2328 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2329 remote
->nfetch_branches
= 0;
2330 remote
->fetch_branches
= NULL
;
2331 remote
->nsend_branches
= 0;
2332 remote
->send_branches
= NULL
;
2333 remote
->nfetch_refs
= 0;
2334 remote
->fetch_refs
= NULL
;
2338 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2349 for (i
= 0; i
< *nremotes
; i
++)
2350 free_remote_data(&(*remotes
)[i
]);
2358 const struct got_error
*
2359 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2361 const struct got_error
*err
= NULL
;
2363 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2365 err
= got_error_from_errno("imsg_compose "
2366 "GOTCONFIG_PARSE_REQUEST");
2371 return flush_imsg(ibuf
);
2374 const struct got_error
*
2375 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2377 if (imsg_compose(ibuf
,
2378 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2379 return got_error_from_errno("imsg_compose "
2380 "GOTCONFIG_AUTHOR_REQUEST");
2382 return flush_imsg(ibuf
);
2385 const struct got_error
*
2386 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf
*ibuf
)
2388 if (imsg_compose(ibuf
,
2389 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2390 return got_error_from_errno("imsg_compose "
2391 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2393 return flush_imsg(ibuf
);
2396 const struct got_error
*
2397 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf
*ibuf
)
2399 if (imsg_compose(ibuf
,
2400 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2401 return got_error_from_errno("imsg_compose "
2402 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2404 return flush_imsg(ibuf
);
2407 const struct got_error
*
2408 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf
*ibuf
)
2410 if (imsg_compose(ibuf
,
2411 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2412 return got_error_from_errno("imsg_compose "
2413 "GOTCONFIG_SIGNERID_REQUEST");
2415 return flush_imsg(ibuf
);
2418 const struct got_error
*
2419 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2421 if (imsg_compose(ibuf
,
2422 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2423 return got_error_from_errno("imsg_compose "
2424 "GOTCONFIG_REMOTE_REQUEST");
2426 return flush_imsg(ibuf
);
2429 const struct got_error
*
2430 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2432 const struct got_error
*err
= NULL
;
2438 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2441 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2443 switch (imsg
.hdr
.type
) {
2444 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2447 *str
= strndup(imsg
.data
, datalen
);
2449 err
= got_error_from_errno("strndup");
2454 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2462 const struct got_error
*
2463 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2464 int *nremotes
, struct imsgbuf
*ibuf
)
2466 const struct got_error
*err
= NULL
;
2469 struct got_imsg_remotes iremotes
;
2470 struct got_imsg_remote iremote
;
2471 const size_t min_datalen
=
2472 MIN(sizeof(struct got_imsg_error
), sizeof(iremotes
));
2476 iremotes
.nremotes
= 0;
2478 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2481 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2483 switch (imsg
.hdr
.type
) {
2484 case GOT_IMSG_GOTCONFIG_REMOTES
:
2485 if (datalen
!= sizeof(iremotes
)) {
2486 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2489 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2490 if (iremotes
.nremotes
< 0) {
2491 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2494 if (iremotes
.nremotes
== 0) {
2501 return got_error(GOT_ERR_PRIVSEP_MSG
);
2506 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2507 if (*remotes
== NULL
)
2508 return got_error_from_errno("recallocarray");
2510 while (*nremotes
< iremotes
.nremotes
) {
2511 struct got_remote_repo
*remote
;
2512 const size_t min_datalen
=
2513 MIN(sizeof(struct got_imsg_error
), sizeof(iremote
));
2516 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2519 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2521 switch (imsg
.hdr
.type
) {
2522 case GOT_IMSG_GOTCONFIG_REMOTE
:
2523 remote
= &(*remotes
)[*nremotes
];
2524 memset(remote
, 0, sizeof(*remote
));
2525 if (datalen
< sizeof(iremote
)) {
2526 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2529 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2530 if (iremote
.name_len
== 0 ||
2531 (iremote
.fetch_url_len
== 0 &&
2532 iremote
.send_url_len
== 0) ||
2533 (sizeof(iremote
) + iremote
.name_len
+
2534 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2536 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2539 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2541 if (remote
->name
== NULL
) {
2542 err
= got_error_from_errno("strndup");
2545 remote
->fetch_url
= strndup(imsg
.data
+
2546 sizeof(iremote
) + iremote
.name_len
,
2547 iremote
.fetch_url_len
);
2548 if (remote
->fetch_url
== NULL
) {
2549 err
= got_error_from_errno("strndup");
2550 free_remote_data(remote
);
2553 remote
->send_url
= strndup(imsg
.data
+
2554 sizeof(iremote
) + iremote
.name_len
+
2555 iremote
.fetch_url_len
, iremote
.send_url_len
);
2556 if (remote
->send_url
== NULL
) {
2557 err
= got_error_from_errno("strndup");
2558 free_remote_data(remote
);
2561 remote
->mirror_references
= iremote
.mirror_references
;
2562 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2563 if (iremote
.nfetch_branches
> 0) {
2564 remote
->fetch_branches
= recallocarray(NULL
, 0,
2565 iremote
.nfetch_branches
, sizeof(char *));
2566 if (remote
->fetch_branches
== NULL
) {
2567 err
= got_error_from_errno("calloc");
2568 free_remote_data(remote
);
2572 remote
->nfetch_branches
= 0;
2573 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2575 err
= got_privsep_recv_gotconfig_str(&branch
,
2578 free_remote_data(remote
);
2581 remote
->fetch_branches
[i
] = branch
;
2582 remote
->nfetch_branches
++;
2584 if (iremote
.nsend_branches
> 0) {
2585 remote
->send_branches
= recallocarray(NULL
, 0,
2586 iremote
.nsend_branches
, sizeof(char *));
2587 if (remote
->send_branches
== NULL
) {
2588 err
= got_error_from_errno("calloc");
2589 free_remote_data(remote
);
2593 remote
->nsend_branches
= 0;
2594 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2596 err
= got_privsep_recv_gotconfig_str(&branch
,
2599 free_remote_data(remote
);
2602 remote
->send_branches
[i
] = branch
;
2603 remote
->nsend_branches
++;
2605 if (iremote
.nfetch_refs
> 0) {
2606 remote
->fetch_refs
= recallocarray(NULL
, 0,
2607 iremote
.nfetch_refs
, sizeof(char *));
2608 if (remote
->fetch_refs
== NULL
) {
2609 err
= got_error_from_errno("calloc");
2610 free_remote_data(remote
);
2614 remote
->nfetch_refs
= 0;
2615 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2617 err
= got_privsep_recv_gotconfig_str(&ref
,
2620 free_remote_data(remote
);
2623 remote
->fetch_refs
[i
] = ref
;
2624 remote
->nfetch_refs
++;
2629 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2640 for (i
= 0; i
< *nremotes
; i
++)
2641 free_remote_data(&(*remotes
)[i
]);
2649 const struct got_error
*
2650 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2651 struct got_object_id
*id
, int idx
, const char *path
)
2654 size_t path_len
= strlen(path
);
2656 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2657 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2659 return got_error_from_errno(
2660 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2662 * Keep in sync with struct got_imsg_commit_traversal_request
2663 * and struct got_imsg_packed_object.
2665 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2666 return got_error_from_errno("imsg_add "
2667 "COMMIT_TRAVERSAL_REQUEST");
2668 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1)
2669 return got_error_from_errno("imsg_add "
2670 "COMMIT_TRAVERSAL_REQUEST");
2671 if (imsg_add(wbuf
, &path_len
, sizeof(path_len
)) == -1)
2672 return got_error_from_errno("imsg_add "
2673 "COMMIT_TRAVERSAL_REQUEST");
2674 if (imsg_add(wbuf
, path
, path_len
) == -1)
2675 return got_error_from_errno("imsg_add "
2676 "COMMIT_TRAVERSAL_REQUEST");
2679 imsg_close(ibuf
, wbuf
);
2681 return flush_imsg(ibuf
);
2684 const struct got_error
*
2685 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2686 struct got_object_id
**changed_commit_id
,
2687 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2689 const struct got_error
*err
= NULL
;
2691 struct got_imsg_traversed_commits
*icommits
;
2692 struct got_object_id
*ids
;
2696 *changed_commit
= NULL
;
2697 *changed_commit_id
= NULL
;
2700 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2704 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2705 switch (imsg
.hdr
.type
) {
2706 case GOT_IMSG_TRAVERSED_COMMITS
:
2707 icommits
= imsg
.data
;
2708 if (datalen
!= sizeof(*icommits
) +
2709 icommits
->ncommits
* sizeof(*ids
)) {
2710 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2713 ids
= imsg
.data
+ sizeof(*icommits
);
2714 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2715 struct got_object_qid
*qid
;
2717 err
= got_object_qid_alloc_partial(&qid
);
2720 memcpy(&qid
->id
, &ids
[i
], sizeof(ids
[i
]));
2721 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2723 /* The last commit may contain a change. */
2724 if (i
== icommits
->ncommits
- 1) {
2725 *changed_commit_id
=
2726 got_object_id_dup(&qid
->id
);
2727 if (*changed_commit_id
== NULL
) {
2728 err
= got_error_from_errno(
2729 "got_object_id_dup");
2735 case GOT_IMSG_COMMIT
:
2736 if (*changed_commit_id
== NULL
) {
2737 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2740 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2743 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2747 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2757 got_object_id_queue_free(commit_ids
);
2761 const struct got_error
*
2762 got_privsep_send_enumerated_tree(size_t *totlen
, struct imsgbuf
*ibuf
,
2763 struct got_object_id
*tree_id
, const char *path
,
2764 struct got_parsed_tree_entry
*entries
, int nentries
)
2766 const struct got_error
*err
= NULL
;
2768 size_t path_len
= strlen(path
);
2771 msglen
= sizeof(struct got_imsg_enumerated_tree
) + path_len
;
2772 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_TREE
, 0, 0, msglen
);
2774 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2776 if (imsg_add(wbuf
, tree_id
->sha1
, SHA1_DIGEST_LENGTH
) == -1)
2777 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2778 if (imsg_add(wbuf
, &nentries
, sizeof(nentries
)) == -1)
2779 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2780 if (imsg_add(wbuf
, path
, path_len
) == -1)
2781 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2784 imsg_close(ibuf
, wbuf
);
2787 err
= send_tree_entries(ibuf
, entries
, nentries
);
2792 return flush_imsg(ibuf
);
2795 const struct got_error
*
2796 got_privsep_send_object_enumeration_request(struct imsgbuf
*ibuf
)
2798 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_REQUEST
,
2799 0, 0, -1, NULL
, 0) == -1)
2800 return got_error_from_errno("imsg_compose "
2801 "OBJECT_ENUMERATION_REQUEST");
2803 return flush_imsg(ibuf
);
2806 const struct got_error
*
2807 got_privsep_send_object_enumeration_done(struct imsgbuf
*ibuf
)
2809 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_DONE
,
2810 0, 0, -1, NULL
, 0) == -1)
2811 return got_error_from_errno("imsg_compose "
2812 "OBJECT_ENUMERATION_DONE");
2814 return flush_imsg(ibuf
);
2817 const struct got_error
*
2818 got_privsep_send_object_enumeration_incomplete(struct imsgbuf
*ibuf
)
2820 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
,
2821 0, 0, -1, NULL
, 0) == -1)
2822 return got_error_from_errno("imsg_compose "
2823 "OBJECT_ENUMERATION_INCOMPLETE");
2825 return flush_imsg(ibuf
);
2828 const struct got_error
*
2829 got_privsep_send_enumerated_commit(struct imsgbuf
*ibuf
,
2830 struct got_object_id
*id
, time_t mtime
)
2834 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_COMMIT
, 0, 0,
2835 sizeof(struct got_imsg_enumerated_commit
) + SHA1_DIGEST_LENGTH
);
2837 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2839 /* Keep in sync with struct got_imsg_enumerated_commit! */
2840 if (imsg_add(wbuf
, id
, SHA1_DIGEST_LENGTH
) == -1)
2841 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2842 if (imsg_add(wbuf
, &mtime
, sizeof(mtime
)) == -1)
2843 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2846 imsg_close(ibuf
, wbuf
);
2847 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2851 const struct got_error
*
2852 got_privsep_recv_enumerated_objects(int *found_all_objects
,
2853 struct imsgbuf
*ibuf
,
2854 got_object_enumerate_commit_cb cb_commit
,
2855 got_object_enumerate_tree_cb cb_tree
, void *cb_arg
,
2856 struct got_repository
*repo
)
2858 const struct got_error
*err
= NULL
;
2860 struct got_imsg_enumerated_commit
*icommit
= NULL
;
2861 struct got_object_id commit_id
;
2862 int have_commit
= 0;
2864 struct got_tree_object tree
;
2865 struct got_imsg_enumerated_tree
*itree
;
2866 struct got_object_id tree_id
;
2867 char *path
= NULL
, *canon_path
= NULL
;
2868 size_t datalen
, path_len
;
2872 *found_all_objects
= 0;
2873 memset(&tree
, 0, sizeof(tree
));
2876 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2880 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2881 switch (imsg
.hdr
.type
) {
2882 case GOT_IMSG_ENUMERATED_COMMIT
:
2883 if (have_commit
&& nentries
!= -1) {
2884 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2887 if (datalen
!= sizeof(*icommit
)) {
2888 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2891 icommit
= (struct got_imsg_enumerated_commit
*)imsg
.data
;
2892 memcpy(commit_id
.sha1
, icommit
->id
, SHA1_DIGEST_LENGTH
);
2893 mtime
= icommit
->mtime
;
2896 case GOT_IMSG_ENUMERATED_TREE
:
2897 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2899 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2902 if (datalen
< sizeof(*itree
)) {
2903 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2907 path_len
= datalen
- sizeof(*itree
);
2908 if (path_len
== 0) {
2909 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2912 memcpy(tree_id
.sha1
, itree
->id
, sizeof(tree_id
.sha1
));
2914 path
= strndup(imsg
.data
+ sizeof(*itree
), path_len
);
2916 err
= got_error_from_errno("strndup");
2920 canon_path
= malloc(path_len
+ 1);
2921 if (canon_path
== NULL
) {
2922 err
= got_error_from_errno("malloc");
2925 if (!got_path_is_absolute(path
)) {
2926 err
= got_error(GOT_ERR_BAD_PATH
);
2929 if (got_path_is_root_dir(path
)) {
2930 /* XXX check what got_canonpath() does wrong */
2931 canon_path
[0] = '/';
2932 canon_path
[1] = '\0';
2934 err
= got_canonpath(path
, canon_path
,
2939 if (strcmp(path
, canon_path
) != 0) {
2940 err
= got_error(GOT_ERR_BAD_PATH
);
2943 if (nentries
!= -1) {
2944 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2947 if (itree
->nentries
< -1) {
2948 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2951 if (itree
->nentries
== -1) {
2952 /* Tree was not found in pack file. */
2953 err
= cb_tree(cb_arg
, NULL
, mtime
, &tree_id
,
2957 if (itree
->nentries
> INT_MAX
) {
2958 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2961 tree
.entries
= calloc(itree
->nentries
,
2962 sizeof(struct got_tree_entry
));
2963 if (tree
.entries
== NULL
) {
2964 err
= got_error_from_errno("calloc");
2967 if (itree
->nentries
== 0) {
2968 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2973 /* Prepare for next tree. */
2975 memset(&tree
, 0, sizeof(tree
));
2978 tree
.nentries
= itree
->nentries
;
2982 case GOT_IMSG_TREE_ENTRIES
:
2983 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2984 if (nentries
<= -1) {
2985 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2988 err
= recv_tree_entries(imsg
.data
, datalen
,
2992 if (tree
.nentries
== nentries
) {
2993 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2998 /* Prepare for next tree. */
3000 memset(&tree
, 0, sizeof(tree
));
3004 case GOT_IMSG_TREE_ENUMERATION_DONE
:
3005 /* All trees have been found and traversed. */
3006 if (!have_commit
|| path
== NULL
|| nentries
!= -1) {
3007 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3010 err
= cb_commit(cb_arg
, mtime
, &commit_id
, repo
);
3015 case GOT_IMSG_OBJECT_ENUMERATION_DONE
:
3016 *found_all_objects
= 1;
3019 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
:
3023 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3038 const struct got_error
*
3039 got_privsep_send_raw_delta_req(struct imsgbuf
*ibuf
, int idx
,
3040 struct got_object_id
*id
)
3042 struct got_imsg_raw_delta_request dreq
;
3044 memset(&dreq
, 0, sizeof(dreq
));
3046 memcpy(&dreq
.id
, id
, sizeof(dreq
.id
));
3048 if (imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA_REQUEST
, 0, 0, -1,
3049 &dreq
, sizeof(dreq
)) == -1)
3050 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
3052 return flush_imsg(ibuf
);
3055 const struct got_error
*
3056 got_privsep_send_raw_delta_outfd(struct imsgbuf
*ibuf
, int fd
)
3058 return send_fd(ibuf
, GOT_IMSG_RAW_DELTA_OUTFD
, fd
);
3061 const struct got_error
*
3062 got_privsep_send_raw_delta(struct imsgbuf
*ibuf
, uint64_t base_size
,
3063 uint64_t result_size
, off_t delta_size
, off_t delta_compressed_size
,
3064 off_t delta_offset
, off_t delta_out_offset
, struct got_object_id
*base_id
)
3066 struct got_imsg_raw_delta idelta
;
3069 memset(&idelta
, 0, sizeof(idelta
));
3070 idelta
.base_size
= base_size
;
3071 idelta
.result_size
= result_size
;
3072 idelta
.delta_size
= delta_size
;
3073 idelta
.delta_compressed_size
= delta_compressed_size
;
3074 idelta
.delta_offset
= delta_offset
;
3075 idelta
.delta_out_offset
= delta_out_offset
;
3076 memcpy(&idelta
.base_id
, &base_id
, sizeof(idelta
.base_id
));
3078 ret
= imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA
, 0, 0, -1,
3079 &idelta
, sizeof(idelta
));
3081 return got_error_from_errno("imsg_compose RAW_DELTA");
3083 return flush_imsg(ibuf
);
3086 const struct got_error
*
3087 got_privsep_recv_raw_delta(uint64_t *base_size
, uint64_t *result_size
,
3088 off_t
*delta_size
, off_t
*delta_compressed_size
, off_t
*delta_offset
,
3089 off_t
*delta_out_offset
, struct got_object_id
**base_id
,
3090 struct imsgbuf
*ibuf
)
3092 const struct got_error
*err
= NULL
;
3094 struct got_imsg_raw_delta
*delta
;
3100 *delta_compressed_size
= 0;
3102 *delta_out_offset
= 0;
3105 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3109 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3111 switch (imsg
.hdr
.type
) {
3112 case GOT_IMSG_RAW_DELTA
:
3113 if (datalen
!= sizeof(*delta
)) {
3114 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3118 *base_size
= delta
->base_size
;
3119 *result_size
= delta
->result_size
;
3120 *delta_size
= delta
->delta_size
;
3121 *delta_compressed_size
= delta
->delta_compressed_size
;
3122 *delta_offset
= delta
->delta_offset
;
3123 *delta_out_offset
= delta
->delta_out_offset
;
3124 *base_id
= calloc(1, sizeof(**base_id
));
3125 if (*base_id
== NULL
) {
3126 err
= got_error_from_errno("malloc");
3129 memcpy(*base_id
, &delta
->base_id
, sizeof(**base_id
));
3132 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3145 static const struct got_error
*
3146 send_idlist(struct imsgbuf
*ibuf
, struct got_object_id
**ids
, size_t nids
)
3148 const struct got_error
*err
= NULL
;
3149 struct got_imsg_object_idlist idlist
;
3153 memset(&idlist
, 0, sizeof(idlist
));
3155 if (nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
)
3156 return got_error(GOT_ERR_NO_SPACE
);
3158 wbuf
= imsg_create(ibuf
, GOT_IMSG_OBJ_ID_LIST
, 0, 0,
3159 sizeof(idlist
) + nids
* sizeof(**ids
));
3161 err
= got_error_from_errno("imsg_create OBJ_ID_LIST");
3166 if (imsg_add(wbuf
, &idlist
, sizeof(idlist
)) == -1)
3167 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3169 for (i
= 0; i
< nids
; i
++) {
3170 struct got_object_id
*id
= ids
[i
];
3171 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
3172 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3176 imsg_close(ibuf
, wbuf
);
3178 return flush_imsg(ibuf
);
3181 const struct got_error
*
3182 got_privsep_send_object_idlist(struct imsgbuf
*ibuf
,
3183 struct got_object_id
**ids
, size_t nids
)
3185 const struct got_error
*err
= NULL
;
3186 struct got_object_id
*idlist
[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
];
3189 for (i
= 0; i
< nids
; i
++) {
3190 idlist
[i
% nitems(idlist
)] = ids
[i
];
3192 if (queued
>= nitems(idlist
)) {
3193 err
= send_idlist(ibuf
, idlist
, queued
);
3201 err
= send_idlist(ibuf
, idlist
, queued
);
3209 const struct got_error
*
3210 got_privsep_send_object_idlist_done(struct imsgbuf
*ibuf
)
3212 if (imsg_compose(ibuf
, GOT_IMSG_OBJ_ID_LIST_DONE
, 0, 0, -1, NULL
, 0)
3214 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3216 return flush_imsg(ibuf
);
3219 const struct got_error
*
3220 got_privsep_recv_object_idlist(int *done
, struct got_object_id
**ids
,
3221 size_t *nids
, struct imsgbuf
*ibuf
)
3223 const struct got_error
*err
= NULL
;
3225 struct got_imsg_object_idlist
*idlist
;
3232 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3236 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3237 switch (imsg
.hdr
.type
) {
3238 case GOT_IMSG_OBJ_ID_LIST
:
3239 if (datalen
< sizeof(*idlist
)) {
3240 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3244 if (idlist
->nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3245 idlist
->nids
* sizeof(**ids
) > datalen
- sizeof(*idlist
)) {
3246 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3249 *nids
= idlist
->nids
;
3250 *ids
= calloc(*nids
, sizeof(**ids
));
3252 err
= got_error_from_errno("calloc");
3255 memcpy(*ids
, (uint8_t *)imsg
.data
+ sizeof(*idlist
),
3256 *nids
* sizeof(**ids
));
3258 case GOT_IMSG_OBJ_ID_LIST_DONE
:
3262 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3271 const struct got_error
*
3272 got_privsep_send_delta_reuse_req(struct imsgbuf
*ibuf
)
3274 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_REQUEST
, 0, 0, -1, NULL
, 0)
3276 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3278 return flush_imsg(ibuf
);
3281 const struct got_error
*
3282 got_privsep_send_reused_deltas(struct imsgbuf
*ibuf
,
3283 struct got_imsg_reused_delta
*deltas
, size_t ndeltas
)
3285 const struct got_error
*err
= NULL
;
3287 struct got_imsg_reused_deltas ideltas
;
3290 memset(&ideltas
, 0, sizeof(ideltas
));
3292 if (ndeltas
> GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS
)
3293 return got_error(GOT_ERR_NO_SPACE
);
3295 wbuf
= imsg_create(ibuf
, GOT_IMSG_REUSED_DELTAS
, 0, 0,
3296 sizeof(ideltas
) + ndeltas
* sizeof(*deltas
));
3298 err
= got_error_from_errno("imsg_create REUSED_DELTAS");
3302 ideltas
.ndeltas
= ndeltas
;
3303 if (imsg_add(wbuf
, &ideltas
, sizeof(ideltas
)) == -1)
3304 return got_error_from_errno("imsg_add REUSED_DELTAS");
3306 for (i
= 0; i
< ndeltas
; i
++) {
3307 struct got_imsg_reused_delta
*delta
= &deltas
[i
];
3308 if (imsg_add(wbuf
, delta
, sizeof(*delta
)) == -1)
3309 return got_error_from_errno("imsg_add REUSED_DELTAS");
3313 imsg_close(ibuf
, wbuf
);
3315 return flush_imsg(ibuf
);
3318 const struct got_error
*
3319 got_privsep_send_reused_deltas_done(struct imsgbuf
*ibuf
)
3321 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_DONE
, 0, 0, -1, NULL
, 0)
3323 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3325 return flush_imsg(ibuf
);
3328 const struct got_error
*
3329 got_privsep_recv_reused_deltas(int *done
, struct got_imsg_reused_delta
*deltas
,
3330 size_t *ndeltas
, struct imsgbuf
*ibuf
)
3332 const struct got_error
*err
= NULL
;
3334 struct got_imsg_reused_deltas
*ideltas
;
3340 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3344 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3345 switch (imsg
.hdr
.type
) {
3346 case GOT_IMSG_REUSED_DELTAS
:
3347 if (datalen
< sizeof(*ideltas
)) {
3348 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3351 ideltas
= imsg
.data
;
3352 if (ideltas
->ndeltas
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3353 ideltas
->ndeltas
* sizeof(*deltas
) >
3354 datalen
- sizeof(*ideltas
)) {
3355 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3358 *ndeltas
= ideltas
->ndeltas
;
3359 memcpy(deltas
, (uint8_t *)imsg
.data
+ sizeof(*ideltas
),
3360 *ndeltas
* sizeof(*deltas
));
3362 case GOT_IMSG_DELTA_REUSE_DONE
:
3366 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3375 const struct got_error
*
3376 got_privsep_init_commit_painting(struct imsgbuf
*ibuf
)
3378 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_INIT
,
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
, int idx
,
3389 struct got_object_id
*id
, intptr_t color
)
3391 struct got_imsg_commit_painting_request ireq
;
3393 memset(&ireq
, 0, sizeof(ireq
));
3394 memcpy(&ireq
.id
, id
, sizeof(ireq
.id
));
3398 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_REQUEST
, 0, 0, -1,
3399 &ireq
, sizeof(ireq
)) == -1)
3400 return got_error_from_errno("imsg_compose "
3401 "COMMIT_PAINTING_REQUEST");
3403 return flush_imsg(ibuf
);
3406 static const struct got_error
*
3407 send_painted_commits(struct got_object_id_queue
*ids
, int *nids
,
3408 size_t remain
, int present_in_pack
, struct imsgbuf
*ibuf
)
3410 const struct got_error
*err
= NULL
;
3411 struct ibuf
*wbuf
= NULL
;
3412 struct got_object_qid
*qid
;
3417 msglen
= MIN(remain
, MAX_IMSGSIZE
- IMSG_HEADER_SIZE
);
3418 ncommits
= (msglen
- sizeof(struct got_imsg_painted_commits
)) /
3419 sizeof(struct got_imsg_painted_commit
);
3421 wbuf
= imsg_create(ibuf
, GOT_IMSG_PAINTED_COMMITS
, 0, 0, msglen
);
3423 err
= got_error_from_errno("imsg_create PAINTED_COMMITS");
3427 /* Keep in sync with struct got_imsg_painted_commits! */
3428 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1)
3429 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3430 if (imsg_add(wbuf
, &present_in_pack
, sizeof(present_in_pack
)) == -1)
3431 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3433 while (ncommits
> 0) {
3434 qid
= STAILQ_FIRST(ids
);
3435 STAILQ_REMOVE_HEAD(ids
, entry
);
3438 color
= (intptr_t)qid
->data
;
3440 /* Keep in sync with struct got_imsg_painted_commit! */
3441 if (imsg_add(wbuf
, qid
->id
.sha1
, SHA1_DIGEST_LENGTH
) == -1)
3442 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3443 if (imsg_add(wbuf
, &color
, sizeof(color
)) == -1)
3444 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3446 got_object_qid_free(qid
);
3450 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
)
3511 if (imsg
.hdr
.type
!= GOT_IMSG_PAINTED_COMMITS
)
3512 return got_error(GOT_ERR_PRIVSEP_MSG
);
3514 if (datalen
< sizeof(icommits
))
3515 return got_error(GOT_ERR_PRIVSEP_LEN
);
3516 memcpy(&icommits
, imsg
.data
, sizeof(icommits
));
3517 if (icommits
.ncommits
* sizeof(icommit
) < icommits
.ncommits
||
3518 datalen
< sizeof(icommits
) +
3519 icommits
.ncommits
* sizeof(icommit
))
3520 return got_error(GOT_ERR_PRIVSEP_LEN
);
3522 for (i
= 0; i
< icommits
.ncommits
; i
++) {
3524 (uint8_t *)imsg
.data
+ sizeof(icommits
) + i
* sizeof(icommit
),
3527 if (icommits
.present_in_pack
) {
3528 struct got_object_id id
;
3529 memcpy(id
.sha1
, icommit
.id
, SHA1_DIGEST_LENGTH
);
3530 err
= cb(cb_arg
, &id
, icommit
.color
);
3534 struct got_object_qid
*qid
;
3535 err
= got_object_qid_alloc_partial(&qid
);
3538 memcpy(qid
->id
.sha1
, icommit
.id
,
3539 SHA1_DIGEST_LENGTH
);
3540 qid
->data
= (void *)icommit
.color
;
3541 STAILQ_INSERT_TAIL(new_ids
, qid
, entry
);
3551 const struct got_error
*
3552 got_privsep_unveil_exec_helpers(void)
3554 const char *helpers
[] = {
3555 GOT_PATH_PROG_READ_PACK
,
3556 GOT_PATH_PROG_READ_OBJECT
,
3557 GOT_PATH_PROG_READ_COMMIT
,
3558 GOT_PATH_PROG_READ_TREE
,
3559 GOT_PATH_PROG_READ_BLOB
,
3560 GOT_PATH_PROG_READ_TAG
,
3561 GOT_PATH_PROG_READ_GITCONFIG
,
3562 GOT_PATH_PROG_READ_GOTCONFIG
,
3563 GOT_PATH_PROG_READ_PATCH
,
3564 GOT_PATH_PROG_FETCH_PACK
,
3565 GOT_PATH_PROG_INDEX_PACK
,
3566 GOT_PATH_PROG_SEND_PACK
,
3570 for (i
= 0; i
< nitems(helpers
); i
++) {
3571 if (unveil(helpers
[i
], "x") == 0)
3573 return got_error_from_errno2("unveil", helpers
[i
]);
3580 got_privsep_exec_child(int imsg_fds
[2], const char *path
, const char *repo_path
)
3582 if (close(imsg_fds
[0]) == -1) {
3583 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3587 if (dup2(imsg_fds
[1], GOT_IMSG_FD_CHILD
) == -1) {
3588 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3592 closefrom(GOT_IMSG_FD_CHILD
+ 1);
3594 if (execl(path
, path
, repo_path
, (char *)NULL
) == -1) {
3595 fprintf(stderr
, "%s: %s: %s\n", getprogname(), path
,