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_privsep.h"
49 #include "got_lib_pack.h"
50 #include "got_lib_poll.h"
52 #include "got_privsep.h"
55 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
59 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
62 static const struct got_error
*
63 read_imsg(struct imsgbuf
*ibuf
)
65 const struct got_error
*err
;
68 err
= got_poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
70 if (err
->code
== GOT_ERR_EOF
)
71 return got_error(GOT_ERR_PRIVSEP_PIPE
);
77 if (errno
== EAGAIN
) /* Could be a file-descriptor leak. */
78 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
79 return got_error(GOT_ERR_PRIVSEP_READ
);
82 return got_error(GOT_ERR_PRIVSEP_PIPE
);
87 const struct got_error
*
88 got_privsep_wait_for_child(pid_t pid
)
92 if (waitpid(pid
, &child_status
, 0) == -1)
93 return got_error_from_errno("waitpid");
95 if (!WIFEXITED(child_status
))
96 return got_error(GOT_ERR_PRIVSEP_DIED
);
98 if (WEXITSTATUS(child_status
) != 0)
99 return got_error(GOT_ERR_PRIVSEP_EXIT
);
104 static const struct got_error
*
105 recv_imsg_error(struct imsg
*imsg
, size_t datalen
)
107 struct got_imsg_error
*ierr
;
109 if (datalen
!= sizeof(*ierr
))
110 return got_error(GOT_ERR_PRIVSEP_LEN
);
113 if (ierr
->code
== GOT_ERR_ERRNO
) {
114 static struct got_error serr
;
115 serr
.code
= GOT_ERR_ERRNO
;
116 serr
.msg
= strerror(ierr
->errno_code
);
120 return got_error(ierr
->code
);
123 const struct got_error
*
124 got_privsep_recv_imsg(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
127 const struct got_error
*err
;
130 n
= imsg_get(ibuf
, imsg
);
132 return got_error_from_errno("imsg_get");
135 err
= read_imsg(ibuf
);
138 n
= imsg_get(ibuf
, imsg
);
140 return got_error_from_errno("imsg_get");
143 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
144 return got_error(GOT_ERR_PRIVSEP_LEN
);
146 if (imsg
->hdr
.type
== GOT_IMSG_ERROR
) {
147 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
148 return recv_imsg_error(imsg
, datalen
);
154 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
156 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
158 const struct got_error
*poll_err
;
159 struct got_imsg_error ierr
;
162 ierr
.code
= err
->code
;
163 if (err
->code
== GOT_ERR_ERRNO
)
164 ierr
.errno_code
= errno
;
167 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
169 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
170 getprogname(), err
->code
, err
->msg
, strerror(errno
));
174 poll_err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
176 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
177 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
181 ret
= imsg_flush(ibuf
);
183 fprintf(stderr
, "%s: error %d \"%s\": imsg_flush: %s\n",
184 getprogname(), err
->code
, err
->msg
, strerror(errno
));
190 static const struct got_error
*
191 flush_imsg(struct imsgbuf
*ibuf
)
193 const struct got_error
*err
;
195 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
199 if (imsg_flush(ibuf
) == -1) {
201 return got_error_from_errno("imsg_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 imsg_init(&ibuf
, fd
);
221 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1)
222 return got_error_from_errno("imsg_compose STOP");
224 err
= flush_imsg(&ibuf
);
228 const struct got_error
*
229 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
230 struct got_object_id
*id
)
232 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
233 id
, sizeof(*id
)) == -1)
234 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
236 return flush_imsg(ibuf
);
239 const struct got_error
*
240 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
241 struct got_object_id
*id
)
243 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
244 id
, sizeof(*id
)) == -1)
245 return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
247 return flush_imsg(ibuf
);
250 const struct got_error
*
251 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
253 const struct got_error
*err
= NULL
;
255 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
257 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
262 return flush_imsg(ibuf
);
265 const struct got_error
*
266 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
269 const struct got_error
*err
= NULL
;
270 struct got_imsg_raw_obj iobj
;
271 size_t len
= sizeof(iobj
);
274 memset(&iobj
, 0, sizeof(iobj
));
275 iobj
.hdrlen
= hdrlen
;
278 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
279 len
+= (size_t)size
+ hdrlen
;
281 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
283 err
= got_error_from_errno("imsg_create RAW_OBJECT");
287 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1)
288 return got_error_from_errno("imsg_add RAW_OBJECT");
290 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
291 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1)
292 return got_error_from_errno("imsg_add RAW_OBJECT");
296 imsg_close(ibuf
, wbuf
);
298 return flush_imsg(ibuf
);
301 const struct got_error
*
302 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
303 struct imsgbuf
*ibuf
)
305 const struct got_error
*err
= NULL
;
307 struct got_imsg_raw_obj
*iobj
;
312 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
316 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
318 switch (imsg
.hdr
.type
) {
319 case GOT_IMSG_RAW_OBJECT
:
320 if (datalen
< sizeof(*iobj
)) {
321 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
326 *hdrlen
= iobj
->hdrlen
;
328 if (datalen
== sizeof(*iobj
)) {
329 /* Data has been written to file descriptor. */
334 *size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
335 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
339 *outbuf
= malloc(*size
+ *hdrlen
);
340 if (*outbuf
== NULL
) {
341 err
= got_error_from_errno("malloc");
344 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
347 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
356 const struct got_error
*
357 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
358 struct got_object_id
*id
, int pack_idx
)
360 const struct got_error
*err
= NULL
;
361 struct got_imsg_packed_object iobj
;
365 memset(&iobj
, 0, sizeof(iobj
));
366 if (pack_idx
!= -1) { /* commit is packed */
368 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
376 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
378 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
383 return flush_imsg(ibuf
);
386 const struct got_error
*
387 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
388 struct got_object_id
*id
, int pack_idx
)
394 len
= sizeof(struct got_imsg_packed_object
);
398 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
400 return got_error_from_errno("imsg_create TREE_REQUEST");
402 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
403 return got_error_from_errno("imsg_add TREE_REQUEST");
405 if (pack_idx
!= -1) { /* tree is packed */
406 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1)
407 return got_error_from_errno("imsg_add TREE_REQUEST");
411 imsg_close(ibuf
, wbuf
);
413 return flush_imsg(ibuf
);
416 const struct got_error
*
417 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
418 struct got_object_id
*id
, int pack_idx
)
420 struct got_imsg_packed_object iobj
;
424 memset(&iobj
, 0, sizeof(iobj
));
425 if (pack_idx
!= -1) { /* tag is packed */
427 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
435 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
437 return got_error_from_errno("imsg_compose TAG_REQUEST");
439 return flush_imsg(ibuf
);
442 const struct got_error
*
443 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
444 struct got_object_id
*id
, int pack_idx
)
446 const struct got_error
*err
= NULL
;
447 struct got_imsg_packed_object iobj
;
451 memset(&iobj
, 0, sizeof(iobj
));
452 if (pack_idx
!= -1) { /* blob is packed */
454 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
462 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
464 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
469 return flush_imsg(ibuf
);
472 const struct got_error
*
473 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
475 const struct got_error
*err
= NULL
;
477 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
479 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
484 return flush_imsg(ibuf
);
487 static const struct got_error
*
488 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
490 const struct got_error
*err
= NULL
;
492 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
493 err
= got_error_from_errno("imsg_compose TMPFD");
498 return flush_imsg(ibuf
);
501 const struct got_error
*
502 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
504 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
507 const struct got_error
*
508 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
510 struct got_imsg_object iobj
;
512 memset(&iobj
, 0, sizeof(iobj
));
514 memcpy(&iobj
.id
, &obj
->id
, sizeof(iobj
.id
));
515 iobj
.type
= obj
->type
;
516 iobj
.flags
= obj
->flags
;
517 iobj
.hdrlen
= obj
->hdrlen
;
518 iobj
.size
= obj
->size
;
519 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
520 iobj
.pack_offset
= obj
->pack_offset
;
521 iobj
.pack_idx
= obj
->pack_idx
;
524 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
526 return got_error_from_errno("imsg_compose OBJECT");
528 return flush_imsg(ibuf
);
531 const struct got_error
*
532 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
533 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
534 struct got_pathlist_head
*wanted_branches
,
535 struct got_pathlist_head
*wanted_refs
, int list_refs_only
,
536 const char *worktree_branch
, const char *remote_head
,
537 int no_head
, int verbosity
)
539 const struct got_error
*err
= NULL
;
541 struct got_pathlist_entry
*pe
;
542 struct got_imsg_fetch_request fetchreq
;
543 size_t remote_head_len
, worktree_branch_len
, len
= sizeof(fetchreq
);
545 if (worktree_branch
) {
546 worktree_branch_len
= strlen(worktree_branch
);
547 len
+= worktree_branch_len
;
550 remote_head_len
= strlen(remote_head
);
551 len
+= remote_head_len
;
554 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
556 return got_error(GOT_ERR_NO_SPACE
);
559 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, len
);
561 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
563 memset(&fetchreq
, 0, sizeof(fetchreq
));
564 fetchreq
.no_head
= no_head
;
565 fetchreq
.fetch_all_branches
= fetch_all_branches
;
566 fetchreq
.list_refs_only
= list_refs_only
;
567 fetchreq
.verbosity
= verbosity
;
568 if (worktree_branch
!= NULL
)
569 fetchreq
.worktree_branch_len
= worktree_branch_len
;
570 if (remote_head
!= NULL
)
571 fetchreq
.remote_head_len
= remote_head_len
;
572 TAILQ_FOREACH(pe
, have_refs
, entry
)
573 fetchreq
.n_have_refs
++;
574 TAILQ_FOREACH(pe
, wanted_branches
, entry
)
575 fetchreq
.n_wanted_branches
++;
576 TAILQ_FOREACH(pe
, wanted_refs
, entry
)
577 fetchreq
.n_wanted_refs
++;
578 if (imsg_add(wbuf
, &fetchreq
, sizeof(fetchreq
)) == -1)
579 return got_error_from_errno("imsg_add FETCH_REQUEST");
580 if (worktree_branch
) {
581 if (imsg_add(wbuf
, worktree_branch
, worktree_branch_len
) == -1)
582 return got_error_from_errno("imsg_add FETCH_REQUEST");
585 if (imsg_add(wbuf
, remote_head
, remote_head_len
) == -1)
586 return got_error_from_errno("imsg_add FETCH_REQUEST");
589 imsg_close(ibuf
, wbuf
);
591 err
= flush_imsg(ibuf
);
598 TAILQ_FOREACH(pe
, have_refs
, entry
) {
599 const char *name
= pe
->path
;
600 size_t name_len
= pe
->path_len
;
601 struct got_object_id
*id
= pe
->data
;
603 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
604 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
606 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
608 /* Keep in sync with struct got_imsg_fetch_have_ref! */
609 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
610 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
611 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
612 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
613 if (imsg_add(wbuf
, name
, name_len
) == -1)
614 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
617 imsg_close(ibuf
, wbuf
);
618 err
= flush_imsg(ibuf
);
623 TAILQ_FOREACH(pe
, wanted_branches
, entry
) {
624 const char *name
= pe
->path
;
625 size_t name_len
= pe
->path_len
;
627 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
628 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
631 return got_error_from_errno(
632 "imsg_create FETCH_WANTED_BRANCH");
634 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
635 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
636 return got_error_from_errno(
637 "imsg_add FETCH_WANTED_BRANCH");
638 if (imsg_add(wbuf
, name
, name_len
) == -1)
639 return got_error_from_errno(
640 "imsg_add FETCH_WANTED_BRANCH");
643 imsg_close(ibuf
, wbuf
);
644 err
= flush_imsg(ibuf
);
649 TAILQ_FOREACH(pe
, wanted_refs
, entry
) {
650 const char *name
= pe
->path
;
651 size_t name_len
= pe
->path_len
;
653 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
654 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
657 return got_error_from_errno(
658 "imsg_create FETCH_WANTED_REF");
660 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
661 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
662 return got_error_from_errno(
663 "imsg_add FETCH_WANTED_REF");
664 if (imsg_add(wbuf
, name
, name_len
) == -1)
665 return got_error_from_errno(
666 "imsg_add FETCH_WANTED_REF");
669 imsg_close(ibuf
, wbuf
);
670 err
= flush_imsg(ibuf
);
680 const struct got_error
*
681 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
683 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
686 const struct got_error
*
687 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
688 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
689 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
691 const struct got_error
*err
= NULL
;
694 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
702 *server_progress
= NULL
;
704 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
706 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
710 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
711 switch (imsg
.hdr
.type
) {
712 case GOT_IMSG_FETCH_SYMREFS
:
713 if (datalen
< sizeof(*isymrefs
)) {
714 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
717 if (isymrefs
!= NULL
) {
718 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
721 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
722 off
= sizeof(*isymrefs
);
723 remain
= datalen
- off
;
724 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
725 struct got_imsg_fetch_symref
*s
;
727 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
728 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
731 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
733 remain
-= sizeof(*s
);
734 if (remain
< s
->name_len
) {
735 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
738 name
= strndup(imsg
.data
+ off
, s
->name_len
);
740 err
= got_error_from_errno("strndup");
744 remain
-= s
->name_len
;
745 if (remain
< s
->target_len
) {
746 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
750 target
= strndup(imsg
.data
+ off
, s
->target_len
);
751 if (target
== NULL
) {
752 err
= got_error_from_errno("strndup");
756 off
+= s
->target_len
;
757 remain
-= s
->target_len
;
758 err
= got_pathlist_append(symrefs
, name
, target
);
766 case GOT_IMSG_FETCH_REF
:
767 if (datalen
<= sizeof(**id
)) {
768 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
771 *id
= malloc(sizeof(**id
));
773 err
= got_error_from_errno("malloc");
776 memcpy(*id
, imsg
.data
, sizeof(**id
));
777 *refname
= strndup(imsg
.data
+ sizeof(**id
),
778 datalen
- sizeof(**id
));
779 if (*refname
== NULL
) {
780 err
= got_error_from_errno("strndup");
784 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
786 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
789 *server_progress
= strndup(imsg
.data
, datalen
);
790 if (*server_progress
== NULL
) {
791 err
= got_error_from_errno("strndup");
794 for (i
= 0; i
< datalen
; i
++) {
795 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
796 !isspace((unsigned char)(*server_progress
)[i
])) {
797 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
798 free(*server_progress
);
799 *server_progress
= NULL
;
804 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
805 if (datalen
< sizeof(*packfile_size
)) {
806 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
809 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
811 case GOT_IMSG_FETCH_DONE
:
812 if (datalen
!= SHA1_DIGEST_LENGTH
) {
813 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
816 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
820 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
834 static const struct got_error
*
835 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
836 int delete, struct imsgbuf
*ibuf
)
841 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
842 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
844 return got_error_from_errno("imsg_create SEND_REF");
846 /* Keep in sync with struct got_imsg_send_ref! */
847 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
848 return got_error_from_errno("imsg_add SEND_REF");
849 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1)
850 return got_error_from_errno("imsg_add SEND_REF");
851 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
852 return got_error_from_errno("imsg_add SEND_REF");
853 if (imsg_add(wbuf
, name
, name_len
) == -1)
854 return got_error_from_errno("imsg_add SEND_REF");
857 imsg_close(ibuf
, wbuf
);
858 return flush_imsg(ibuf
);
861 const struct got_error
*
862 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
863 struct got_pathlist_head
*have_refs
,
864 struct got_pathlist_head
*delete_refs
,
867 const struct got_error
*err
= NULL
;
868 struct got_pathlist_entry
*pe
;
869 struct got_imsg_send_request sendreq
;
870 struct got_object_id zero_id
;
872 memset(&zero_id
, 0, sizeof(zero_id
));
873 memset(&sendreq
, 0, sizeof(sendreq
));
874 sendreq
.verbosity
= verbosity
;
875 TAILQ_FOREACH(pe
, have_refs
, entry
)
877 TAILQ_FOREACH(pe
, delete_refs
, entry
)
879 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
880 &sendreq
, sizeof(sendreq
)) == -1) {
881 err
= got_error_from_errno(
882 "imsg_compose FETCH_SERVER_PROGRESS");
886 err
= flush_imsg(ibuf
);
891 TAILQ_FOREACH(pe
, have_refs
, entry
) {
892 const char *name
= pe
->path
;
893 size_t name_len
= pe
->path_len
;
894 struct got_object_id
*id
= pe
->data
;
895 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
900 TAILQ_FOREACH(pe
, delete_refs
, entry
) {
901 const char *name
= pe
->path
;
902 size_t name_len
= pe
->path_len
;
903 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
908 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
909 err
= got_error_from_errno("close");
914 const struct got_error
*
915 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
916 struct imsgbuf
*ibuf
)
918 const struct got_error
*err
= NULL
;
922 struct got_imsg_send_remote_ref iremote_ref
;
923 struct got_object_id
*id
= NULL
;
924 char *refname
= NULL
;
925 struct got_pathlist_entry
*new;
928 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
931 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
932 switch (imsg
.hdr
.type
) {
933 case GOT_IMSG_SEND_REMOTE_REF
:
934 if (datalen
< sizeof(iremote_ref
)) {
935 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
938 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
939 if (datalen
!= sizeof(iremote_ref
) +
940 iremote_ref
.name_len
) {
941 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
944 id
= malloc(sizeof(*id
));
946 err
= got_error_from_errno("malloc");
949 memcpy(id
, &iremote_ref
.id
, sizeof(*id
));
950 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
951 datalen
- sizeof(iremote_ref
));
952 if (refname
== NULL
) {
953 err
= got_error_from_errno("strndup");
956 err
= got_pathlist_insert(&new, remote_refs
,
960 if (new == NULL
) { /* duplicate which wasn't inserted */
967 case GOT_IMSG_SEND_PACK_REQUEST
:
969 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
972 /* got-send-pack is now waiting for a pack file. */
976 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
987 const struct got_error
*
988 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
990 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
993 const struct got_error
*
994 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
995 int *success
, char **refname
, char **errmsg
, struct imsgbuf
*ibuf
)
997 const struct got_error
*err
= NULL
;
1000 struct got_imsg_send_ref_status iref_status
;
1002 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1008 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1012 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1013 switch (imsg
.hdr
.type
) {
1014 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
1015 if (datalen
< sizeof(*bytes_sent
)) {
1016 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1019 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
1021 case GOT_IMSG_SEND_REF_STATUS
:
1022 if (datalen
< sizeof(iref_status
)) {
1023 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1026 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
1027 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
+
1028 iref_status
.errmsg_len
) {
1029 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1032 *success
= iref_status
.success
;
1033 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1034 iref_status
.name_len
);
1036 if (iref_status
.errmsg_len
!= 0)
1037 *errmsg
= strndup(imsg
.data
+ sizeof(iref_status
) +
1038 iref_status
.name_len
, iref_status
.errmsg_len
);
1040 case GOT_IMSG_SEND_DONE
:
1042 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1048 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1056 const struct got_error
*
1057 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, uint8_t *pack_sha1
,
1060 const struct got_error
*err
= NULL
;
1062 /* Keep in sync with struct got_imsg_index_pack_request */
1063 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1064 pack_sha1
, SHA1_DIGEST_LENGTH
) == -1) {
1065 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1069 return flush_imsg(ibuf
);
1072 const struct got_error
*
1073 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1075 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1078 const struct got_error
*
1079 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1080 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1081 struct imsgbuf
*ibuf
)
1083 const struct got_error
*err
= NULL
;
1085 struct got_imsg_index_pack_progress
*iprogress
;
1093 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1097 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1098 switch (imsg
.hdr
.type
) {
1099 case GOT_IMSG_IDXPACK_PROGRESS
:
1100 if (datalen
< sizeof(*iprogress
)) {
1101 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1104 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1105 if (iprogress
->nobj_total
< 0 || iprogress
->nobj_indexed
< 0 ||
1106 iprogress
->nobj_loose
< 0 || iprogress
->nobj_resolved
< 0) {
1107 err
= got_error(GOT_ERR_RANGE
);
1110 *nobj_total
= iprogress
->nobj_total
;
1111 *nobj_indexed
= iprogress
->nobj_indexed
;
1112 *nobj_loose
= iprogress
->nobj_loose
;
1113 *nobj_resolved
= iprogress
->nobj_resolved
;
1115 case GOT_IMSG_IDXPACK_DONE
:
1117 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1123 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1131 const struct got_error
*
1132 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1133 struct imsgbuf
*ibuf
)
1135 struct got_imsg_object
*iobj
;
1136 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1138 if (datalen
!= sizeof(*iobj
))
1139 return got_error(GOT_ERR_PRIVSEP_LEN
);
1142 if (iobj
->pack_offset
< 0)
1143 return got_error(GOT_ERR_PACK_OFFSET
);
1145 *obj
= calloc(1, sizeof(**obj
));
1147 return got_error_from_errno("calloc");
1149 memcpy(&(*obj
)->id
, &iobj
->id
, sizeof(iobj
->id
));
1150 (*obj
)->type
= iobj
->type
;
1151 (*obj
)->flags
= iobj
->flags
;
1152 (*obj
)->hdrlen
= iobj
->hdrlen
;
1153 (*obj
)->size
= iobj
->size
;
1154 /* path_packfile is handled by caller */
1155 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1156 (*obj
)->pack_offset
= iobj
->pack_offset
;
1157 (*obj
)->pack_idx
= iobj
->pack_idx
;
1159 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1163 const struct got_error
*
1164 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1166 const struct got_error
*err
= NULL
;
1168 const size_t min_datalen
=
1169 MIN(sizeof(struct got_imsg_error
), sizeof(struct got_imsg_object
));
1173 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1177 switch (imsg
.hdr
.type
) {
1178 case GOT_IMSG_OBJECT
:
1179 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1182 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1191 static const struct got_error
*
1192 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1195 const struct got_error
*err
= NULL
;
1196 size_t offset
, remain
;
1199 remain
= logmsg_len
;
1200 while (remain
> 0) {
1201 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1203 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1204 commit
->logmsg
+ offset
, n
) == -1) {
1205 err
= got_error_from_errno("imsg_compose "
1210 err
= flush_imsg(ibuf
);
1221 const struct got_error
*
1222 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1224 const struct got_error
*err
= NULL
;
1225 struct got_imsg_commit_object
*icommit
;
1228 struct got_object_qid
*qid
;
1229 size_t author_len
= strlen(commit
->author
);
1230 size_t committer_len
= strlen(commit
->committer
);
1231 size_t logmsg_len
= strlen(commit
->logmsg
);
1233 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1234 commit
->nparents
* sizeof(struct got_object_id
);
1236 buf
= malloc(total
);
1238 return got_error_from_errno("malloc");
1240 icommit
= (struct got_imsg_commit_object
*)buf
;
1241 memcpy(&icommit
->tree_id
, commit
->tree_id
, sizeof(icommit
->tree_id
));
1242 icommit
->author_len
= author_len
;
1243 icommit
->author_time
= commit
->author_time
;
1244 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1245 icommit
->committer_len
= committer_len
;
1246 icommit
->committer_time
= commit
->committer_time
;
1247 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1248 icommit
->logmsg_len
= logmsg_len
;
1249 icommit
->nparents
= commit
->nparents
;
1251 len
= sizeof(*icommit
);
1252 memcpy(buf
+ len
, commit
->author
, author_len
);
1254 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1255 len
+= committer_len
;
1256 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1257 memcpy(buf
+ len
, &qid
->id
, sizeof(qid
->id
));
1258 len
+= sizeof(qid
->id
);
1261 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1262 err
= got_error_from_errno("imsg_compose COMMIT");
1266 if (logmsg_len
== 0 ||
1267 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1268 err
= flush_imsg(ibuf
);
1272 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1278 static const struct got_error
*
1279 get_commit_from_imsg(struct got_commit_object
**commit
,
1280 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1282 const struct got_error
*err
= NULL
;
1283 struct got_imsg_commit_object
*icommit
;
1287 if (datalen
< sizeof(*icommit
))
1288 return got_error(GOT_ERR_PRIVSEP_LEN
);
1290 icommit
= imsg
->data
;
1291 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1292 icommit
->committer_len
+
1293 icommit
->nparents
* sizeof(struct got_object_id
))
1294 return got_error(GOT_ERR_PRIVSEP_LEN
);
1296 if (icommit
->nparents
< 0)
1297 return got_error(GOT_ERR_PRIVSEP_LEN
);
1299 len
+= sizeof(*icommit
);
1301 *commit
= got_object_commit_alloc_partial();
1302 if (*commit
== NULL
)
1303 return got_error_from_errno(
1304 "got_object_commit_alloc_partial");
1306 memcpy((*commit
)->tree_id
, &icommit
->tree_id
,
1307 sizeof(icommit
->tree_id
));
1308 (*commit
)->author_time
= icommit
->author_time
;
1309 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1310 (*commit
)->committer_time
= icommit
->committer_time
;
1311 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1313 (*commit
)->author
= strndup(imsg
->data
+ len
, icommit
->author_len
);
1314 if ((*commit
)->author
== NULL
) {
1315 err
= got_error_from_errno("strndup");
1318 len
+= icommit
->author_len
;
1320 (*commit
)->committer
= strndup(imsg
->data
+ len
,
1321 icommit
->committer_len
);
1322 if ((*commit
)->committer
== NULL
) {
1323 err
= got_error_from_errno("strndup");
1326 len
+= icommit
->committer_len
;
1328 if (icommit
->logmsg_len
== 0) {
1329 (*commit
)->logmsg
= strdup("");
1330 if ((*commit
)->logmsg
== NULL
) {
1331 err
= got_error_from_errno("strdup");
1335 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1337 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1338 if ((*commit
)->logmsg
== NULL
) {
1339 err
= got_error_from_errno("malloc");
1342 while (remain
> 0) {
1343 struct imsg imsg_log
;
1344 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1347 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1351 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1352 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1356 memcpy((*commit
)->logmsg
+ offset
,
1358 imsg_free(&imsg_log
);
1362 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1365 for (i
= 0; i
< icommit
->nparents
; i
++) {
1366 struct got_object_qid
*qid
;
1368 err
= got_object_qid_alloc_partial(&qid
);
1371 memcpy(&qid
->id
, imsg
->data
+ len
+
1372 i
* sizeof(qid
->id
), sizeof(qid
->id
));
1373 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1374 (*commit
)->nparents
++;
1378 got_object_commit_close(*commit
);
1384 const struct got_error
*
1385 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1387 const struct got_error
*err
= NULL
;
1390 const size_t min_datalen
=
1391 MIN(sizeof(struct got_imsg_error
),
1392 sizeof(struct got_imsg_commit_object
));
1396 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1400 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1402 switch (imsg
.hdr
.type
) {
1403 case GOT_IMSG_COMMIT
:
1404 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1407 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1416 static const struct got_error
*
1417 send_tree_entries_batch(struct imsgbuf
*ibuf
,
1418 struct got_parsed_tree_entry
*entries
, int idx0
, int idxN
, size_t len
)
1421 struct got_imsg_tree_entries ientries
;
1424 memset(&ientries
, 0, sizeof(ientries
));
1426 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRIES
, 0, 0, len
);
1428 return got_error_from_errno("imsg_create TREE_ENTRY");
1430 ientries
.nentries
= idxN
- idx0
+ 1;
1431 if (imsg_add(wbuf
, &ientries
, sizeof(ientries
)) == -1)
1432 return got_error_from_errno("imsg_add TREE_ENTRY");
1434 for (i
= idx0
; i
<= idxN
; i
++) {
1435 struct got_parsed_tree_entry
*pte
= &entries
[i
];
1437 /* Keep in sync with struct got_imsg_tree_entry definition! */
1438 if (imsg_add(wbuf
, pte
->id
, SHA1_DIGEST_LENGTH
) == -1)
1439 return got_error_from_errno("imsg_add TREE_ENTRY");
1440 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1)
1441 return got_error_from_errno("imsg_add TREE_ENTRY");
1442 if (imsg_add(wbuf
, &pte
->namelen
, sizeof(pte
->namelen
)) == -1)
1443 return got_error_from_errno("imsg_add TREE_ENTRY");
1445 /* Remaining bytes are the entry's name. */
1446 if (imsg_add(wbuf
, pte
->name
, pte
->namelen
) == -1)
1447 return got_error_from_errno("imsg_add TREE_ENTRY");
1451 imsg_close(ibuf
, wbuf
);
1455 static const struct got_error
*
1456 send_tree_entries(struct imsgbuf
*ibuf
, struct got_parsed_tree_entry
*entries
,
1459 const struct got_error
*err
= NULL
;
1461 size_t entries_len
= sizeof(struct got_imsg_tree_entries
);
1464 for (j
= 0; j
< nentries
; j
++) {
1465 struct got_parsed_tree_entry
*pte
= &entries
[j
];
1466 size_t len
= sizeof(struct got_imsg_tree_entry
) + pte
->namelen
;
1469 entries_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1470 err
= send_tree_entries_batch(ibuf
, entries
,
1471 i
, j
- 1, entries_len
);
1475 entries_len
= sizeof(struct got_imsg_tree_entries
);
1482 err
= send_tree_entries_batch(ibuf
, entries
, i
, j
- 1,
1491 const struct got_error
*
1492 got_privsep_send_tree(struct imsgbuf
*ibuf
,
1493 struct got_parsed_tree_entry
*entries
, int nentries
)
1495 const struct got_error
*err
= NULL
;
1496 struct got_imsg_tree_object itree
;
1498 memset(&itree
, 0, sizeof(itree
));
1499 itree
.nentries
= nentries
;
1500 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1502 return got_error_from_errno("imsg_compose TREE");
1504 err
= send_tree_entries(ibuf
, entries
, nentries
);
1508 return flush_imsg(ibuf
);
1512 static const struct got_error
*
1513 recv_tree_entries(void *data
, size_t datalen
, struct got_tree_object
*tree
,
1516 const struct got_error
*err
= NULL
;
1517 struct got_imsg_tree_entries
*ientries
;
1518 struct got_tree_entry
*te
;
1522 if (datalen
<= sizeof(*ientries
) ||
1523 datalen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
1524 return got_error(GOT_ERR_PRIVSEP_LEN
);
1526 ientries
= (struct got_imsg_tree_entries
*)data
;
1527 if (ientries
->nentries
> INT_MAX
) {
1528 return got_error_msg(GOT_ERR_NO_SPACE
,
1529 "too many tree entries");
1532 te_offset
= sizeof(*ientries
);
1533 for (i
= 0; i
< ientries
->nentries
; i
++) {
1534 struct got_imsg_tree_entry ite
;
1535 const char *te_name
;
1536 uint8_t *buf
= (uint8_t *)data
+ te_offset
;
1538 if (te_offset
>= datalen
) {
1539 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1543 /* Might not be aligned, size is ~32 bytes. */
1544 memcpy(&ite
, buf
, sizeof(ite
));
1546 if (ite
.namelen
>= sizeof(te
->name
)) {
1547 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1550 if (te_offset
+ sizeof(ite
) + ite
.namelen
> datalen
) {
1551 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1555 if (*nentries
>= tree
->nentries
) {
1556 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1559 te
= &tree
->entries
[*nentries
];
1560 te_name
= buf
+ sizeof(ite
);
1561 memcpy(te
->name
, te_name
, ite
.namelen
);
1562 te
->name
[ite
.namelen
] = '\0';
1563 memcpy(te
->id
.sha1
, ite
.id
, SHA1_DIGEST_LENGTH
);
1564 te
->mode
= ite
.mode
;
1565 te
->idx
= *nentries
;
1568 te_offset
+= sizeof(ite
) + ite
.namelen
;
1574 const struct got_error
*
1575 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1577 const struct got_error
*err
= NULL
;
1578 const size_t min_datalen
=
1579 MIN(sizeof(struct got_imsg_error
),
1580 sizeof(struct got_imsg_tree_object
));
1581 struct got_imsg_tree_object
*itree
;
1586 while (*tree
== NULL
|| nentries
< (*tree
)->nentries
) {
1590 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1594 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1596 switch (imsg
.hdr
.type
) {
1598 /* This message should only appear once. */
1599 if (*tree
!= NULL
) {
1600 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1603 if (datalen
!= sizeof(*itree
)) {
1604 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1608 if (itree
->nentries
< 0) {
1609 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1612 *tree
= malloc(sizeof(**tree
));
1613 if (*tree
== NULL
) {
1614 err
= got_error_from_errno("malloc");
1617 (*tree
)->entries
= calloc(itree
->nentries
,
1618 sizeof(struct got_tree_entry
));
1619 if ((*tree
)->entries
== NULL
) {
1620 err
= got_error_from_errno("malloc");
1625 (*tree
)->nentries
= itree
->nentries
;
1626 (*tree
)->refcnt
= 0;
1628 case GOT_IMSG_TREE_ENTRIES
:
1629 /* This message should be preceeded by GOT_IMSG_TREE. */
1630 if (*tree
== NULL
) {
1631 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1634 err
= recv_tree_entries(imsg
.data
, datalen
,
1638 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1647 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1649 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1650 got_object_tree_close(*tree
);
1657 const struct got_error
*
1658 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1659 const uint8_t *data
)
1661 struct got_imsg_blob iblob
;
1663 memset(&iblob
, 0, sizeof(iblob
));
1665 iblob
.hdrlen
= hdrlen
;
1670 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1671 return got_error(GOT_ERR_NO_SPACE
);
1673 buf
= malloc(sizeof(iblob
) + size
);
1675 return got_error_from_errno("malloc");
1677 memcpy(buf
, &iblob
, sizeof(iblob
));
1678 memcpy(buf
+ sizeof(iblob
), data
, size
);
1679 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1680 sizeof(iblob
) + size
) == -1) {
1682 return got_error_from_errno("imsg_compose BLOB");
1686 /* Data has already been written to file descriptor. */
1687 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1688 sizeof(iblob
)) == -1)
1689 return got_error_from_errno("imsg_compose BLOB");
1693 return flush_imsg(ibuf
);
1696 const struct got_error
*
1697 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1698 struct imsgbuf
*ibuf
)
1700 const struct got_error
*err
= NULL
;
1702 struct got_imsg_blob
*iblob
;
1707 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1711 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1713 switch (imsg
.hdr
.type
) {
1715 if (datalen
< sizeof(*iblob
)) {
1716 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1720 *size
= iblob
->size
;
1721 *hdrlen
= iblob
->hdrlen
;
1723 if (datalen
== sizeof(*iblob
)) {
1724 /* Data has been written to file descriptor. */
1728 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
||
1729 *size
> datalen
+ sizeof(*iblob
)) {
1730 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1734 *outbuf
= malloc(*size
);
1735 if (*outbuf
== NULL
) {
1736 err
= got_error_from_errno("malloc");
1739 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1742 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1751 static const struct got_error
*
1752 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1754 const struct got_error
*err
= NULL
;
1755 size_t offset
, remain
;
1758 remain
= tagmsg_len
;
1759 while (remain
> 0) {
1760 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1762 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1763 tag
->tagmsg
+ offset
, n
) == -1) {
1764 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1768 err
= flush_imsg(ibuf
);
1779 const struct got_error
*
1780 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1782 const struct got_error
*err
= NULL
;
1783 struct got_imsg_tag_object
*itag
;
1786 size_t tag_len
= strlen(tag
->tag
);
1787 size_t tagger_len
= strlen(tag
->tagger
);
1788 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1790 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1792 buf
= malloc(total
);
1794 return got_error_from_errno("malloc");
1796 itag
= (struct got_imsg_tag_object
*)buf
;
1797 memcpy(&itag
->id
, &tag
->id
, sizeof(itag
->id
));
1798 itag
->obj_type
= tag
->obj_type
;
1799 itag
->tag_len
= tag_len
;
1800 itag
->tagger_len
= tagger_len
;
1801 itag
->tagger_time
= tag
->tagger_time
;
1802 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1803 itag
->tagmsg_len
= tagmsg_len
;
1805 len
= sizeof(*itag
);
1806 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1808 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1811 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1812 err
= got_error_from_errno("imsg_compose TAG");
1816 if (tagmsg_len
== 0 ||
1817 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1818 err
= flush_imsg(ibuf
);
1822 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1828 const struct got_error
*
1829 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1831 const struct got_error
*err
= NULL
;
1833 struct got_imsg_tag_object
*itag
;
1834 size_t len
, datalen
;
1835 const size_t min_datalen
=
1836 MIN(sizeof(struct got_imsg_error
),
1837 sizeof(struct got_imsg_tag_object
));
1841 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1845 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1848 switch (imsg
.hdr
.type
) {
1850 if (datalen
< sizeof(*itag
)) {
1851 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1855 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1857 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1860 len
+= sizeof(*itag
);
1862 *tag
= calloc(1, sizeof(**tag
));
1864 err
= got_error_from_errno("calloc");
1868 memcpy(&(*tag
)->id
, &itag
->id
, sizeof(itag
->id
));
1870 (*tag
)->tag
= strndup(imsg
.data
+ len
, itag
->tag_len
);
1871 if ((*tag
)->tag
== NULL
) {
1872 err
= got_error_from_errno("strndup");
1875 len
+= itag
->tag_len
;
1877 (*tag
)->obj_type
= itag
->obj_type
;
1878 (*tag
)->tagger_time
= itag
->tagger_time
;
1879 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1881 (*tag
)->tagger
= strndup(imsg
.data
+ len
, itag
->tagger_len
);
1882 if ((*tag
)->tagger
== NULL
) {
1883 err
= got_error_from_errno("strndup");
1886 len
+= itag
->tagger_len
;
1888 if (itag
->tagmsg_len
== 0) {
1889 (*tag
)->tagmsg
= strdup("");
1890 if ((*tag
)->tagmsg
== NULL
) {
1891 err
= got_error_from_errno("strdup");
1895 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1897 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1898 if ((*tag
)->tagmsg
== NULL
) {
1899 err
= got_error_from_errno("malloc");
1902 while (remain
> 0) {
1903 struct imsg imsg_log
;
1904 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1907 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1911 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1912 return got_error(GOT_ERR_PRIVSEP_MSG
);
1914 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1916 imsg_free(&imsg_log
);
1920 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1925 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1934 const struct got_error
*
1935 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1936 struct got_packidx
*packidx
)
1938 const struct got_error
*err
= NULL
;
1939 struct got_imsg_packidx ipackidx
;
1940 struct got_imsg_pack ipack
;
1943 memset(&ipackidx
, 0, sizeof(ipackidx
));
1944 memset(&ipack
, 0, sizeof(ipack
));
1946 ipackidx
.len
= packidx
->len
;
1947 ipackidx
.packfile_size
= pack
->filesize
;
1948 fd
= dup(packidx
->fd
);
1950 return got_error_from_errno("dup");
1952 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1953 sizeof(ipackidx
)) == -1) {
1954 err
= got_error_from_errno("imsg_compose PACKIDX");
1959 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1960 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1961 return got_error(GOT_ERR_NO_SPACE
);
1962 ipack
.filesize
= pack
->filesize
;
1966 return got_error_from_errno("dup");
1968 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
1970 err
= got_error_from_errno("imsg_compose PACK");
1975 return flush_imsg(ibuf
);
1978 const struct got_error
*
1979 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
1980 struct got_object_id
*id
)
1982 struct got_imsg_packed_object iobj
;
1984 memset(&iobj
, 0, sizeof(iobj
));
1986 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
1988 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
1989 &iobj
, sizeof(iobj
)) == -1)
1990 return got_error_from_errno("imsg_compose "
1991 "PACKED_OBJECT_REQUEST");
1993 return flush_imsg(ibuf
);
1996 const struct got_error
*
1997 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
1998 struct got_object_id
*id
)
2000 struct got_imsg_packed_object iobj
;
2002 memset(&iobj
, 0, sizeof(iobj
));
2004 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2006 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
2007 &iobj
, sizeof(iobj
)) == -1)
2008 return got_error_from_errno("imsg_compose "
2009 "PACKED_OBJECT_REQUEST");
2011 return flush_imsg(ibuf
);
2014 const struct got_error
*
2015 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2017 const struct got_error
*err
= NULL
;
2019 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2021 err
= got_error_from_errno("imsg_compose "
2022 "GITCONFIG_PARSE_REQUEST");
2027 return flush_imsg(ibuf
);
2030 const struct got_error
*
2031 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2033 if (imsg_compose(ibuf
,
2034 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2036 return got_error_from_errno("imsg_compose "
2037 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2039 return flush_imsg(ibuf
);
2042 const struct got_error
*
2043 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2045 if (imsg_compose(ibuf
,
2046 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2048 return got_error_from_errno("imsg_compose "
2049 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2051 return flush_imsg(ibuf
);
2055 const struct got_error
*
2056 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2058 if (imsg_compose(ibuf
,
2059 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2060 return got_error_from_errno("imsg_compose "
2061 "GITCONFIG_AUTHOR_NAME_REQUEST");
2063 return flush_imsg(ibuf
);
2066 const struct got_error
*
2067 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2069 if (imsg_compose(ibuf
,
2070 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2071 return got_error_from_errno("imsg_compose "
2072 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2074 return flush_imsg(ibuf
);
2077 const struct got_error
*
2078 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2080 if (imsg_compose(ibuf
,
2081 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2082 return got_error_from_errno("imsg_compose "
2083 "GITCONFIG_REMOTE_REQUEST");
2085 return flush_imsg(ibuf
);
2088 const struct got_error
*
2089 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2091 if (imsg_compose(ibuf
,
2092 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2093 return got_error_from_errno("imsg_compose "
2094 "GITCONFIG_OWNER_REQUEST");
2096 return flush_imsg(ibuf
);
2099 const struct got_error
*
2100 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2102 const struct got_error
*err
= NULL
;
2108 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2111 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2113 switch (imsg
.hdr
.type
) {
2114 case GOT_IMSG_GITCONFIG_STR_VAL
:
2117 *str
= strndup(imsg
.data
, datalen
);
2119 err
= got_error_from_errno("strndup");
2124 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2132 const struct got_error
*
2133 got_privsep_recv_gitconfig_pair(char **key
, char **val
, struct imsgbuf
*ibuf
)
2135 const struct got_error
*err
= NULL
;
2136 struct got_imsg_gitconfig_pair p
;
2143 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2148 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2150 if (imsg
.hdr
.type
!= GOT_IMSG_GITCONFIG_PAIR
) {
2151 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2155 if (datalen
< sizeof(p
)) {
2156 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2160 memcpy(&p
, data
, sizeof(p
));
2163 if (datalen
!= sizeof(p
) + p
.klen
+ p
.vlen
) {
2164 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2168 *key
= strndup(data
, p
.klen
);
2170 err
= got_error_from_errno("strndup");
2175 *val
= strndup(data
, p
.vlen
);
2177 err
= got_error_from_errno("strndup");
2186 const struct got_error
*
2187 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2189 const struct got_error
*err
= NULL
;
2192 const size_t min_datalen
=
2193 MIN(sizeof(struct got_imsg_error
), sizeof(int));
2197 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2200 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2202 switch (imsg
.hdr
.type
) {
2203 case GOT_IMSG_GITCONFIG_INT_VAL
:
2204 if (datalen
!= sizeof(*val
)) {
2205 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2208 memcpy(val
, imsg
.data
, sizeof(*val
));
2211 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2220 free_remote_data(struct got_remote_repo
*remote
)
2225 free(remote
->fetch_url
);
2226 free(remote
->send_url
);
2227 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2228 free(remote
->fetch_branches
[i
]);
2229 free(remote
->fetch_branches
);
2230 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2231 free(remote
->send_branches
[i
]);
2232 free(remote
->send_branches
);
2233 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2234 free(remote
->fetch_refs
[i
]);
2235 free(remote
->fetch_refs
);
2238 const struct got_error
*
2239 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2240 int *nremotes
, struct imsgbuf
*ibuf
)
2242 const struct got_error
*err
= NULL
;
2245 struct got_imsg_remotes iremotes
;
2246 struct got_imsg_remote iremote
;
2250 iremotes
.nremotes
= 0;
2252 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2255 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2257 switch (imsg
.hdr
.type
) {
2258 case GOT_IMSG_GITCONFIG_REMOTES
:
2259 if (datalen
!= sizeof(iremotes
)) {
2260 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2263 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2264 if (iremotes
.nremotes
== 0) {
2271 return got_error(GOT_ERR_PRIVSEP_MSG
);
2276 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2277 if (*remotes
== NULL
)
2278 return got_error_from_errno("recallocarray");
2280 while (*nremotes
< iremotes
.nremotes
) {
2281 struct got_remote_repo
*remote
;
2283 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2286 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2288 switch (imsg
.hdr
.type
) {
2289 case GOT_IMSG_GITCONFIG_REMOTE
:
2290 remote
= &(*remotes
)[*nremotes
];
2291 memset(remote
, 0, sizeof(*remote
));
2292 if (datalen
< sizeof(iremote
)) {
2293 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2296 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2297 if (iremote
.name_len
== 0 ||
2298 iremote
.fetch_url_len
== 0 ||
2299 iremote
.send_url_len
== 0 ||
2300 (sizeof(iremote
) + iremote
.name_len
+
2301 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2302 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2305 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2307 if (remote
->name
== NULL
) {
2308 err
= got_error_from_errno("strndup");
2311 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2312 iremote
.name_len
, iremote
.fetch_url_len
);
2313 if (remote
->fetch_url
== NULL
) {
2314 err
= got_error_from_errno("strndup");
2315 free_remote_data(remote
);
2318 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2319 iremote
.name_len
+ iremote
.fetch_url_len
,
2320 iremote
.send_url_len
);
2321 if (remote
->send_url
== NULL
) {
2322 err
= got_error_from_errno("strndup");
2323 free_remote_data(remote
);
2326 remote
->mirror_references
= iremote
.mirror_references
;
2327 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2328 remote
->nfetch_branches
= 0;
2329 remote
->fetch_branches
= NULL
;
2330 remote
->nsend_branches
= 0;
2331 remote
->send_branches
= NULL
;
2332 remote
->nfetch_refs
= 0;
2333 remote
->fetch_refs
= NULL
;
2337 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2348 for (i
= 0; i
< *nremotes
; i
++)
2349 free_remote_data(&(*remotes
)[i
]);
2357 const struct got_error
*
2358 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2360 const struct got_error
*err
= NULL
;
2362 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2364 err
= got_error_from_errno("imsg_compose "
2365 "GOTCONFIG_PARSE_REQUEST");
2370 return flush_imsg(ibuf
);
2373 const struct got_error
*
2374 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2376 if (imsg_compose(ibuf
,
2377 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2378 return got_error_from_errno("imsg_compose "
2379 "GOTCONFIG_AUTHOR_REQUEST");
2381 return flush_imsg(ibuf
);
2384 const struct got_error
*
2385 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf
*ibuf
)
2387 if (imsg_compose(ibuf
,
2388 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2389 return got_error_from_errno("imsg_compose "
2390 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2392 return flush_imsg(ibuf
);
2395 const struct got_error
*
2396 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf
*ibuf
)
2398 if (imsg_compose(ibuf
,
2399 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2400 return got_error_from_errno("imsg_compose "
2401 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2403 return flush_imsg(ibuf
);
2406 const struct got_error
*
2407 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf
*ibuf
)
2409 if (imsg_compose(ibuf
,
2410 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2411 return got_error_from_errno("imsg_compose "
2412 "GOTCONFIG_SIGNERID_REQUEST");
2414 return flush_imsg(ibuf
);
2417 const struct got_error
*
2418 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2420 if (imsg_compose(ibuf
,
2421 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2422 return got_error_from_errno("imsg_compose "
2423 "GOTCONFIG_REMOTE_REQUEST");
2425 return flush_imsg(ibuf
);
2428 const struct got_error
*
2429 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2431 const struct got_error
*err
= NULL
;
2437 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2440 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2442 switch (imsg
.hdr
.type
) {
2443 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2446 *str
= strndup(imsg
.data
, datalen
);
2448 err
= got_error_from_errno("strndup");
2453 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2461 const struct got_error
*
2462 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2463 int *nremotes
, struct imsgbuf
*ibuf
)
2465 const struct got_error
*err
= NULL
;
2468 struct got_imsg_remotes iremotes
;
2469 struct got_imsg_remote iremote
;
2470 const size_t min_datalen
=
2471 MIN(sizeof(struct got_imsg_error
), sizeof(iremotes
));
2475 iremotes
.nremotes
= 0;
2477 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2480 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2482 switch (imsg
.hdr
.type
) {
2483 case GOT_IMSG_GOTCONFIG_REMOTES
:
2484 if (datalen
!= sizeof(iremotes
)) {
2485 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2488 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2489 if (iremotes
.nremotes
< 0) {
2490 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2493 if (iremotes
.nremotes
== 0) {
2500 return got_error(GOT_ERR_PRIVSEP_MSG
);
2505 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2506 if (*remotes
== NULL
)
2507 return got_error_from_errno("recallocarray");
2509 while (*nremotes
< iremotes
.nremotes
) {
2510 struct got_remote_repo
*remote
;
2511 const size_t min_datalen
=
2512 MIN(sizeof(struct got_imsg_error
), sizeof(iremote
));
2515 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2518 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2520 switch (imsg
.hdr
.type
) {
2521 case GOT_IMSG_GOTCONFIG_REMOTE
:
2522 remote
= &(*remotes
)[*nremotes
];
2523 memset(remote
, 0, sizeof(*remote
));
2524 if (datalen
< sizeof(iremote
)) {
2525 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2528 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2529 if (iremote
.name_len
== 0 ||
2530 (iremote
.fetch_url_len
== 0 &&
2531 iremote
.send_url_len
== 0) ||
2532 (sizeof(iremote
) + iremote
.name_len
+
2533 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2535 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2538 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2540 if (remote
->name
== NULL
) {
2541 err
= got_error_from_errno("strndup");
2544 remote
->fetch_url
= strndup(imsg
.data
+
2545 sizeof(iremote
) + iremote
.name_len
,
2546 iremote
.fetch_url_len
);
2547 if (remote
->fetch_url
== NULL
) {
2548 err
= got_error_from_errno("strndup");
2549 free_remote_data(remote
);
2552 remote
->send_url
= strndup(imsg
.data
+
2553 sizeof(iremote
) + iremote
.name_len
+
2554 iremote
.fetch_url_len
, iremote
.send_url_len
);
2555 if (remote
->send_url
== NULL
) {
2556 err
= got_error_from_errno("strndup");
2557 free_remote_data(remote
);
2560 remote
->mirror_references
= iremote
.mirror_references
;
2561 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2562 if (iremote
.nfetch_branches
> 0) {
2563 remote
->fetch_branches
= recallocarray(NULL
, 0,
2564 iremote
.nfetch_branches
, sizeof(char *));
2565 if (remote
->fetch_branches
== NULL
) {
2566 err
= got_error_from_errno("calloc");
2567 free_remote_data(remote
);
2571 remote
->nfetch_branches
= 0;
2572 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2574 err
= got_privsep_recv_gotconfig_str(&branch
,
2577 free_remote_data(remote
);
2580 remote
->fetch_branches
[i
] = branch
;
2581 remote
->nfetch_branches
++;
2583 if (iremote
.nsend_branches
> 0) {
2584 remote
->send_branches
= recallocarray(NULL
, 0,
2585 iremote
.nsend_branches
, sizeof(char *));
2586 if (remote
->send_branches
== NULL
) {
2587 err
= got_error_from_errno("calloc");
2588 free_remote_data(remote
);
2592 remote
->nsend_branches
= 0;
2593 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2595 err
= got_privsep_recv_gotconfig_str(&branch
,
2598 free_remote_data(remote
);
2601 remote
->send_branches
[i
] = branch
;
2602 remote
->nsend_branches
++;
2604 if (iremote
.nfetch_refs
> 0) {
2605 remote
->fetch_refs
= recallocarray(NULL
, 0,
2606 iremote
.nfetch_refs
, sizeof(char *));
2607 if (remote
->fetch_refs
== NULL
) {
2608 err
= got_error_from_errno("calloc");
2609 free_remote_data(remote
);
2613 remote
->nfetch_refs
= 0;
2614 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2616 err
= got_privsep_recv_gotconfig_str(&ref
,
2619 free_remote_data(remote
);
2622 remote
->fetch_refs
[i
] = ref
;
2623 remote
->nfetch_refs
++;
2628 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2639 for (i
= 0; i
< *nremotes
; i
++)
2640 free_remote_data(&(*remotes
)[i
]);
2648 const struct got_error
*
2649 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2650 struct got_object_id
*id
, int idx
, const char *path
)
2653 size_t path_len
= strlen(path
);
2655 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2656 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2658 return got_error_from_errno(
2659 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2661 * Keep in sync with struct got_imsg_commit_traversal_request
2662 * and struct got_imsg_packed_object.
2664 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2665 return got_error_from_errno("imsg_add "
2666 "COMMIT_TRAVERSAL_REQUEST");
2667 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1)
2668 return got_error_from_errno("imsg_add "
2669 "COMMIT_TRAVERSAL_REQUEST");
2670 if (imsg_add(wbuf
, &path_len
, sizeof(path_len
)) == -1)
2671 return got_error_from_errno("imsg_add "
2672 "COMMIT_TRAVERSAL_REQUEST");
2673 if (imsg_add(wbuf
, path
, path_len
) == -1)
2674 return got_error_from_errno("imsg_add "
2675 "COMMIT_TRAVERSAL_REQUEST");
2678 imsg_close(ibuf
, wbuf
);
2680 return flush_imsg(ibuf
);
2683 const struct got_error
*
2684 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2685 struct got_object_id
**changed_commit_id
,
2686 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2688 const struct got_error
*err
= NULL
;
2690 struct got_imsg_traversed_commits
*icommits
;
2691 struct got_object_id
*ids
;
2695 *changed_commit
= NULL
;
2696 *changed_commit_id
= NULL
;
2699 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2703 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2704 switch (imsg
.hdr
.type
) {
2705 case GOT_IMSG_TRAVERSED_COMMITS
:
2706 icommits
= imsg
.data
;
2707 if (datalen
!= sizeof(*icommits
) +
2708 icommits
->ncommits
* sizeof(*ids
)) {
2709 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2712 ids
= imsg
.data
+ sizeof(*icommits
);
2713 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2714 struct got_object_qid
*qid
;
2716 err
= got_object_qid_alloc_partial(&qid
);
2719 memcpy(&qid
->id
, &ids
[i
], sizeof(ids
[i
]));
2720 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2722 /* The last commit may contain a change. */
2723 if (i
== icommits
->ncommits
- 1) {
2724 *changed_commit_id
=
2725 got_object_id_dup(&qid
->id
);
2726 if (*changed_commit_id
== NULL
) {
2727 err
= got_error_from_errno(
2728 "got_object_id_dup");
2734 case GOT_IMSG_COMMIT
:
2735 if (*changed_commit_id
== NULL
) {
2736 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2739 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2742 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2746 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2756 got_object_id_queue_free(commit_ids
);
2760 const struct got_error
*
2761 got_privsep_send_enumerated_tree(size_t *totlen
, struct imsgbuf
*ibuf
,
2762 struct got_object_id
*tree_id
, const char *path
,
2763 struct got_parsed_tree_entry
*entries
, int nentries
)
2765 const struct got_error
*err
= NULL
;
2767 size_t path_len
= strlen(path
);
2770 msglen
= sizeof(struct got_imsg_enumerated_tree
) + path_len
;
2771 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_TREE
, 0, 0, msglen
);
2773 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2775 if (imsg_add(wbuf
, tree_id
->sha1
, SHA1_DIGEST_LENGTH
) == -1)
2776 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2777 if (imsg_add(wbuf
, &nentries
, sizeof(nentries
)) == -1)
2778 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2779 if (imsg_add(wbuf
, path
, path_len
) == -1)
2780 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2783 imsg_close(ibuf
, wbuf
);
2786 err
= send_tree_entries(ibuf
, entries
, nentries
);
2791 return flush_imsg(ibuf
);
2794 const struct got_error
*
2795 got_privsep_send_object_enumeration_request(struct imsgbuf
*ibuf
)
2797 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_REQUEST
,
2798 0, 0, -1, NULL
, 0) == -1)
2799 return got_error_from_errno("imsg_compose "
2800 "OBJECT_ENUMERATION_REQUEST");
2802 return flush_imsg(ibuf
);
2805 const struct got_error
*
2806 got_privsep_send_object_enumeration_done(struct imsgbuf
*ibuf
)
2808 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_DONE
,
2809 0, 0, -1, NULL
, 0) == -1)
2810 return got_error_from_errno("imsg_compose "
2811 "OBJECT_ENUMERATION_DONE");
2813 return flush_imsg(ibuf
);
2816 const struct got_error
*
2817 got_privsep_send_object_enumeration_incomplete(struct imsgbuf
*ibuf
)
2819 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
,
2820 0, 0, -1, NULL
, 0) == -1)
2821 return got_error_from_errno("imsg_compose "
2822 "OBJECT_ENUMERATION_INCOMPLETE");
2824 return flush_imsg(ibuf
);
2827 const struct got_error
*
2828 got_privsep_send_enumerated_commit(struct imsgbuf
*ibuf
,
2829 struct got_object_id
*id
, time_t mtime
)
2833 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_COMMIT
, 0, 0,
2834 sizeof(struct got_imsg_enumerated_commit
) + SHA1_DIGEST_LENGTH
);
2836 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2838 /* Keep in sync with struct got_imsg_enumerated_commit! */
2839 if (imsg_add(wbuf
, id
, SHA1_DIGEST_LENGTH
) == -1)
2840 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2841 if (imsg_add(wbuf
, &mtime
, sizeof(mtime
)) == -1)
2842 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2845 imsg_close(ibuf
, wbuf
);
2846 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2850 const struct got_error
*
2851 got_privsep_recv_enumerated_objects(int *found_all_objects
,
2852 struct imsgbuf
*ibuf
,
2853 got_object_enumerate_commit_cb cb_commit
,
2854 got_object_enumerate_tree_cb cb_tree
, void *cb_arg
,
2855 struct got_repository
*repo
)
2857 const struct got_error
*err
= NULL
;
2859 struct got_imsg_enumerated_commit
*icommit
= NULL
;
2860 struct got_object_id commit_id
;
2861 int have_commit
= 0;
2863 struct got_tree_object tree
;
2864 struct got_imsg_enumerated_tree
*itree
;
2865 struct got_object_id tree_id
;
2866 char *path
= NULL
, *canon_path
= NULL
;
2867 size_t datalen
, path_len
;
2871 *found_all_objects
= 0;
2872 memset(&tree
, 0, sizeof(tree
));
2875 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2879 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2880 switch (imsg
.hdr
.type
) {
2881 case GOT_IMSG_ENUMERATED_COMMIT
:
2882 if (have_commit
&& nentries
!= -1) {
2883 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2886 if (datalen
!= sizeof(*icommit
)) {
2887 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2890 icommit
= (struct got_imsg_enumerated_commit
*)imsg
.data
;
2891 memcpy(commit_id
.sha1
, icommit
->id
, SHA1_DIGEST_LENGTH
);
2892 mtime
= icommit
->mtime
;
2895 case GOT_IMSG_ENUMERATED_TREE
:
2896 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2898 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2901 if (datalen
< sizeof(*itree
)) {
2902 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2906 path_len
= datalen
- sizeof(*itree
);
2907 if (path_len
== 0) {
2908 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2911 memcpy(tree_id
.sha1
, itree
->id
, sizeof(tree_id
.sha1
));
2913 path
= strndup(imsg
.data
+ sizeof(*itree
), path_len
);
2915 err
= got_error_from_errno("strndup");
2919 canon_path
= malloc(path_len
+ 1);
2920 if (canon_path
== NULL
) {
2921 err
= got_error_from_errno("malloc");
2924 if (!got_path_is_absolute(path
)) {
2925 err
= got_error(GOT_ERR_BAD_PATH
);
2928 if (got_path_is_root_dir(path
)) {
2929 /* XXX check what got_canonpath() does wrong */
2930 canon_path
[0] = '/';
2931 canon_path
[1] = '\0';
2933 err
= got_canonpath(path
, canon_path
,
2938 if (strcmp(path
, canon_path
) != 0) {
2939 err
= got_error(GOT_ERR_BAD_PATH
);
2942 if (nentries
!= -1) {
2943 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2946 if (itree
->nentries
< -1) {
2947 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2950 if (itree
->nentries
== -1) {
2951 /* Tree was not found in pack file. */
2952 err
= cb_tree(cb_arg
, NULL
, mtime
, &tree_id
,
2956 if (itree
->nentries
> INT_MAX
) {
2957 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2960 tree
.entries
= calloc(itree
->nentries
,
2961 sizeof(struct got_tree_entry
));
2962 if (tree
.entries
== NULL
) {
2963 err
= got_error_from_errno("calloc");
2966 if (itree
->nentries
== 0) {
2967 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2972 /* Prepare for next tree. */
2974 memset(&tree
, 0, sizeof(tree
));
2977 tree
.nentries
= itree
->nentries
;
2981 case GOT_IMSG_TREE_ENTRIES
:
2982 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2983 if (nentries
<= -1) {
2984 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2987 err
= recv_tree_entries(imsg
.data
, datalen
,
2991 if (tree
.nentries
== nentries
) {
2992 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2997 /* Prepare for next tree. */
2999 memset(&tree
, 0, sizeof(tree
));
3003 case GOT_IMSG_TREE_ENUMERATION_DONE
:
3004 /* All trees have been found and traversed. */
3005 if (!have_commit
|| path
== NULL
|| nentries
!= -1) {
3006 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3009 err
= cb_commit(cb_arg
, mtime
, &commit_id
, repo
);
3014 case GOT_IMSG_OBJECT_ENUMERATION_DONE
:
3015 *found_all_objects
= 1;
3018 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
:
3022 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3037 const struct got_error
*
3038 got_privsep_send_raw_delta_req(struct imsgbuf
*ibuf
, int idx
,
3039 struct got_object_id
*id
)
3041 struct got_imsg_raw_delta_request dreq
;
3043 memset(&dreq
, 0, sizeof(dreq
));
3045 memcpy(&dreq
.id
, id
, sizeof(dreq
.id
));
3047 if (imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA_REQUEST
, 0, 0, -1,
3048 &dreq
, sizeof(dreq
)) == -1)
3049 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
3051 return flush_imsg(ibuf
);
3054 const struct got_error
*
3055 got_privsep_send_raw_delta_outfd(struct imsgbuf
*ibuf
, int fd
)
3057 return send_fd(ibuf
, GOT_IMSG_RAW_DELTA_OUTFD
, fd
);
3060 const struct got_error
*
3061 got_privsep_send_raw_delta(struct imsgbuf
*ibuf
, uint64_t base_size
,
3062 uint64_t result_size
, off_t delta_size
, off_t delta_compressed_size
,
3063 off_t delta_offset
, off_t delta_out_offset
, struct got_object_id
*base_id
)
3065 struct got_imsg_raw_delta idelta
;
3068 memset(&idelta
, 0, sizeof(idelta
));
3069 idelta
.base_size
= base_size
;
3070 idelta
.result_size
= result_size
;
3071 idelta
.delta_size
= delta_size
;
3072 idelta
.delta_compressed_size
= delta_compressed_size
;
3073 idelta
.delta_offset
= delta_offset
;
3074 idelta
.delta_out_offset
= delta_out_offset
;
3075 memcpy(&idelta
.base_id
, &base_id
, sizeof(idelta
.base_id
));
3077 ret
= imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA
, 0, 0, -1,
3078 &idelta
, sizeof(idelta
));
3080 return got_error_from_errno("imsg_compose RAW_DELTA");
3082 return flush_imsg(ibuf
);
3085 const struct got_error
*
3086 got_privsep_recv_raw_delta(uint64_t *base_size
, uint64_t *result_size
,
3087 off_t
*delta_size
, off_t
*delta_compressed_size
, off_t
*delta_offset
,
3088 off_t
*delta_out_offset
, struct got_object_id
**base_id
,
3089 struct imsgbuf
*ibuf
)
3091 const struct got_error
*err
= NULL
;
3093 struct got_imsg_raw_delta
*delta
;
3099 *delta_compressed_size
= 0;
3101 *delta_out_offset
= 0;
3104 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3108 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3110 switch (imsg
.hdr
.type
) {
3111 case GOT_IMSG_RAW_DELTA
:
3112 if (datalen
!= sizeof(*delta
)) {
3113 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3117 *base_size
= delta
->base_size
;
3118 *result_size
= delta
->result_size
;
3119 *delta_size
= delta
->delta_size
;
3120 *delta_compressed_size
= delta
->delta_compressed_size
;
3121 *delta_offset
= delta
->delta_offset
;
3122 *delta_out_offset
= delta
->delta_out_offset
;
3123 *base_id
= calloc(1, sizeof(**base_id
));
3124 if (*base_id
== NULL
) {
3125 err
= got_error_from_errno("malloc");
3128 memcpy(*base_id
, &delta
->base_id
, sizeof(**base_id
));
3131 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3144 static const struct got_error
*
3145 send_idlist(struct imsgbuf
*ibuf
, struct got_object_id
**ids
, size_t nids
)
3147 const struct got_error
*err
= NULL
;
3148 struct got_imsg_object_idlist idlist
;
3152 memset(&idlist
, 0, sizeof(idlist
));
3154 if (nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
)
3155 return got_error(GOT_ERR_NO_SPACE
);
3157 wbuf
= imsg_create(ibuf
, GOT_IMSG_OBJ_ID_LIST
, 0, 0,
3158 sizeof(idlist
) + nids
* sizeof(**ids
));
3160 err
= got_error_from_errno("imsg_create OBJ_ID_LIST");
3165 if (imsg_add(wbuf
, &idlist
, sizeof(idlist
)) == -1)
3166 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3168 for (i
= 0; i
< nids
; i
++) {
3169 struct got_object_id
*id
= ids
[i
];
3170 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
3171 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3175 imsg_close(ibuf
, wbuf
);
3177 return flush_imsg(ibuf
);
3180 const struct got_error
*
3181 got_privsep_send_object_idlist(struct imsgbuf
*ibuf
,
3182 struct got_object_id
**ids
, size_t nids
)
3184 const struct got_error
*err
= NULL
;
3185 struct got_object_id
*idlist
[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
];
3188 for (i
= 0; i
< nids
; i
++) {
3189 idlist
[i
% nitems(idlist
)] = ids
[i
];
3191 if (queued
>= nitems(idlist
)) {
3192 err
= send_idlist(ibuf
, idlist
, queued
);
3200 err
= send_idlist(ibuf
, idlist
, queued
);
3208 const struct got_error
*
3209 got_privsep_send_object_idlist_done(struct imsgbuf
*ibuf
)
3211 if (imsg_compose(ibuf
, GOT_IMSG_OBJ_ID_LIST_DONE
, 0, 0, -1, NULL
, 0)
3213 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3215 return flush_imsg(ibuf
);
3218 const struct got_error
*
3219 got_privsep_recv_object_idlist(int *done
, struct got_object_id
**ids
,
3220 size_t *nids
, struct imsgbuf
*ibuf
)
3222 const struct got_error
*err
= NULL
;
3224 struct got_imsg_object_idlist
*idlist
;
3231 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3235 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3236 switch (imsg
.hdr
.type
) {
3237 case GOT_IMSG_OBJ_ID_LIST
:
3238 if (datalen
< sizeof(*idlist
)) {
3239 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3243 if (idlist
->nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3244 idlist
->nids
* sizeof(**ids
) > datalen
- sizeof(*idlist
)) {
3245 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3248 *nids
= idlist
->nids
;
3249 *ids
= calloc(*nids
, sizeof(**ids
));
3251 err
= got_error_from_errno("calloc");
3254 memcpy(*ids
, (uint8_t *)imsg
.data
+ sizeof(*idlist
),
3255 *nids
* sizeof(**ids
));
3257 case GOT_IMSG_OBJ_ID_LIST_DONE
:
3261 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3270 const struct got_error
*
3271 got_privsep_send_delta_reuse_req(struct imsgbuf
*ibuf
)
3273 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_REQUEST
, 0, 0, -1, NULL
, 0)
3275 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3277 return flush_imsg(ibuf
);
3280 const struct got_error
*
3281 got_privsep_send_reused_deltas(struct imsgbuf
*ibuf
,
3282 struct got_imsg_reused_delta
*deltas
, size_t ndeltas
)
3284 const struct got_error
*err
= NULL
;
3286 struct got_imsg_reused_deltas ideltas
;
3289 memset(&ideltas
, 0, sizeof(ideltas
));
3291 if (ndeltas
> GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS
)
3292 return got_error(GOT_ERR_NO_SPACE
);
3294 wbuf
= imsg_create(ibuf
, GOT_IMSG_REUSED_DELTAS
, 0, 0,
3295 sizeof(ideltas
) + ndeltas
* sizeof(*deltas
));
3297 err
= got_error_from_errno("imsg_create REUSED_DELTAS");
3301 ideltas
.ndeltas
= ndeltas
;
3302 if (imsg_add(wbuf
, &ideltas
, sizeof(ideltas
)) == -1)
3303 return got_error_from_errno("imsg_add REUSED_DELTAS");
3305 for (i
= 0; i
< ndeltas
; i
++) {
3306 struct got_imsg_reused_delta
*delta
= &deltas
[i
];
3307 if (imsg_add(wbuf
, delta
, sizeof(*delta
)) == -1)
3308 return got_error_from_errno("imsg_add REUSED_DELTAS");
3312 imsg_close(ibuf
, wbuf
);
3314 return flush_imsg(ibuf
);
3317 const struct got_error
*
3318 got_privsep_send_reused_deltas_done(struct imsgbuf
*ibuf
)
3320 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_DONE
, 0, 0, -1, NULL
, 0)
3322 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3324 return flush_imsg(ibuf
);
3327 const struct got_error
*
3328 got_privsep_recv_reused_deltas(int *done
, struct got_imsg_reused_delta
*deltas
,
3329 size_t *ndeltas
, struct imsgbuf
*ibuf
)
3331 const struct got_error
*err
= NULL
;
3333 struct got_imsg_reused_deltas
*ideltas
;
3339 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3343 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3344 switch (imsg
.hdr
.type
) {
3345 case GOT_IMSG_REUSED_DELTAS
:
3346 if (datalen
< sizeof(*ideltas
)) {
3347 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3350 ideltas
= imsg
.data
;
3351 if (ideltas
->ndeltas
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3352 ideltas
->ndeltas
* sizeof(*deltas
) >
3353 datalen
- sizeof(*ideltas
)) {
3354 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3357 *ndeltas
= ideltas
->ndeltas
;
3358 memcpy(deltas
, (uint8_t *)imsg
.data
+ sizeof(*ideltas
),
3359 *ndeltas
* sizeof(*deltas
));
3361 case GOT_IMSG_DELTA_REUSE_DONE
:
3365 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3374 const struct got_error
*
3375 got_privsep_init_commit_painting(struct imsgbuf
*ibuf
)
3377 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_INIT
,
3380 return got_error_from_errno("imsg_compose "
3381 "COMMIT_PAINTING_INIT");
3383 return flush_imsg(ibuf
);
3386 const struct got_error
*
3387 got_privsep_send_painting_request(struct imsgbuf
*ibuf
, int idx
,
3388 struct got_object_id
*id
, intptr_t color
)
3390 struct got_imsg_commit_painting_request ireq
;
3392 memset(&ireq
, 0, sizeof(ireq
));
3393 memcpy(&ireq
.id
, id
, sizeof(ireq
.id
));
3397 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_REQUEST
, 0, 0, -1,
3398 &ireq
, sizeof(ireq
)) == -1)
3399 return got_error_from_errno("imsg_compose "
3400 "COMMIT_PAINTING_REQUEST");
3402 return flush_imsg(ibuf
);
3405 static const struct got_error
*
3406 send_painted_commits(struct got_object_id_queue
*ids
, int *nids
,
3407 size_t remain
, int present_in_pack
, struct imsgbuf
*ibuf
)
3409 const struct got_error
*err
= NULL
;
3410 struct ibuf
*wbuf
= NULL
;
3411 struct got_object_qid
*qid
;
3416 msglen
= MIN(remain
, MAX_IMSGSIZE
- IMSG_HEADER_SIZE
);
3417 ncommits
= (msglen
- sizeof(struct got_imsg_painted_commits
)) /
3418 sizeof(struct got_imsg_painted_commit
);
3420 wbuf
= imsg_create(ibuf
, GOT_IMSG_PAINTED_COMMITS
, 0, 0, msglen
);
3422 err
= got_error_from_errno("imsg_create PAINTED_COMMITS");
3426 /* Keep in sync with struct got_imsg_painted_commits! */
3427 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1)
3428 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3429 if (imsg_add(wbuf
, &present_in_pack
, sizeof(present_in_pack
)) == -1)
3430 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3432 while (ncommits
> 0) {
3433 qid
= STAILQ_FIRST(ids
);
3434 STAILQ_REMOVE_HEAD(ids
, entry
);
3437 color
= (intptr_t)qid
->data
;
3439 /* Keep in sync with struct got_imsg_painted_commit! */
3440 if (imsg_add(wbuf
, qid
->id
.sha1
, SHA1_DIGEST_LENGTH
) == -1)
3441 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3442 if (imsg_add(wbuf
, &color
, sizeof(color
)) == -1)
3443 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3445 got_object_qid_free(qid
);
3449 imsg_close(ibuf
, wbuf
);
3451 return flush_imsg(ibuf
);
3454 const struct got_error
*
3455 got_privsep_send_painted_commits(struct imsgbuf
*ibuf
,
3456 struct got_object_id_queue
*ids
, int *nids
,
3457 int present_in_pack
, int flush
)
3459 const struct got_error
*err
;
3466 remain
= (sizeof(struct got_imsg_painted_commits
)) +
3467 *nids
* sizeof(struct got_imsg_painted_commit
);
3468 if (flush
|| remain
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
3469 err
= send_painted_commits(ids
, nids
, remain
,
3470 present_in_pack
, ibuf
);
3474 } while (flush
&& *nids
> 0);
3479 const struct got_error
*
3480 got_privsep_send_painting_commits_done(struct imsgbuf
*ibuf
)
3482 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_DONE
,
3485 return got_error_from_errno("imsg_compose "
3486 "COMMIT_PAINTING_DONE");
3488 return flush_imsg(ibuf
);
3491 const struct got_error
*
3492 got_privsep_recv_painted_commits(struct got_object_id_queue
*new_ids
,
3493 got_privsep_recv_painted_commit_cb cb
, void *cb_arg
, struct imsgbuf
*ibuf
)
3495 const struct got_error
*err
= NULL
;
3497 struct got_imsg_painted_commits icommits
;
3498 struct got_imsg_painted_commit icommit
;
3503 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3507 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3508 if (imsg
.hdr
.type
== GOT_IMSG_COMMIT_PAINTING_DONE
)
3510 if (imsg
.hdr
.type
!= GOT_IMSG_PAINTED_COMMITS
)
3511 return got_error(GOT_ERR_PRIVSEP_MSG
);
3513 if (datalen
< sizeof(icommits
))
3514 return got_error(GOT_ERR_PRIVSEP_LEN
);
3515 memcpy(&icommits
, imsg
.data
, sizeof(icommits
));
3516 if (icommits
.ncommits
* sizeof(icommit
) < icommits
.ncommits
||
3517 datalen
< sizeof(icommits
) +
3518 icommits
.ncommits
* sizeof(icommit
))
3519 return got_error(GOT_ERR_PRIVSEP_LEN
);
3521 for (i
= 0; i
< icommits
.ncommits
; i
++) {
3523 (uint8_t *)imsg
.data
+ sizeof(icommits
) + i
* sizeof(icommit
),
3526 if (icommits
.present_in_pack
) {
3527 struct got_object_id id
;
3528 memcpy(id
.sha1
, icommit
.id
, SHA1_DIGEST_LENGTH
);
3529 err
= cb(cb_arg
, &id
, icommit
.color
);
3533 struct got_object_qid
*qid
;
3534 err
= got_object_qid_alloc_partial(&qid
);
3537 memcpy(qid
->id
.sha1
, icommit
.id
,
3538 SHA1_DIGEST_LENGTH
);
3539 qid
->data
= (void *)icommit
.color
;
3540 STAILQ_INSERT_TAIL(new_ids
, qid
, entry
);
3550 const struct got_error
*
3551 got_privsep_unveil_exec_helpers(void)
3553 const char *helpers
[] = {
3554 GOT_PATH_PROG_READ_PACK
,
3555 GOT_PATH_PROG_READ_OBJECT
,
3556 GOT_PATH_PROG_READ_COMMIT
,
3557 GOT_PATH_PROG_READ_TREE
,
3558 GOT_PATH_PROG_READ_BLOB
,
3559 GOT_PATH_PROG_READ_TAG
,
3560 GOT_PATH_PROG_READ_GITCONFIG
,
3561 GOT_PATH_PROG_READ_GOTCONFIG
,
3562 GOT_PATH_PROG_READ_PATCH
,
3563 GOT_PATH_PROG_FETCH_PACK
,
3564 GOT_PATH_PROG_INDEX_PACK
,
3565 GOT_PATH_PROG_SEND_PACK
,
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
,