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
.type
== GOT_IMSG_ERROR
) {
145 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
146 err
= recv_imsg_error(imsg
, datalen
);
151 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
) {
153 return got_error(GOT_ERR_PRIVSEP_LEN
);
159 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
161 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
163 const struct got_error
*poll_err
;
164 struct got_imsg_error ierr
;
167 ierr
.code
= err
->code
;
168 if (err
->code
== GOT_ERR_ERRNO
)
169 ierr
.errno_code
= errno
;
172 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
174 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
175 getprogname(), err
->code
, err
->msg
, strerror(errno
));
179 poll_err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
181 if (poll_err
->code
!= GOT_ERR_EOF
)
182 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
183 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
187 ret
= imsg_flush(ibuf
);
189 fprintf(stderr
, "%s: error %d \"%s\": imsg_flush: %s\n",
190 getprogname(), err
->code
, err
->msg
, strerror(errno
));
196 static const struct got_error
*
197 flush_imsg(struct imsgbuf
*ibuf
)
199 const struct got_error
*err
;
201 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
205 if (imsg_flush(ibuf
) == -1) {
207 return got_error_from_errno("imsg_flush");
213 const struct got_error
*
214 got_privsep_flush_imsg(struct imsgbuf
*ibuf
)
216 return flush_imsg(ibuf
);
219 const struct got_error
*
220 got_privsep_send_stop(int fd
)
224 imsg_init(&ibuf
, fd
);
226 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1)
227 return got_error_from_errno("imsg_compose STOP");
229 return flush_imsg(&ibuf
);
232 const struct got_error
*
233 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
234 struct got_object_id
*id
)
236 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
237 id
, sizeof(*id
)) == -1)
238 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
240 return flush_imsg(ibuf
);
243 const struct got_error
*
244 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
245 struct got_object_id
*id
)
247 const struct got_error
*err
;
249 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
250 id
, sizeof(*id
)) == -1) {
251 err
= got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
256 return flush_imsg(ibuf
);
259 const struct got_error
*
260 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
262 const struct got_error
*err
= NULL
;
264 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
266 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
271 return flush_imsg(ibuf
);
274 const struct got_error
*
275 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
278 struct got_imsg_raw_obj iobj
;
279 size_t len
= sizeof(iobj
);
282 memset(&iobj
, 0, sizeof(iobj
));
283 iobj
.hdrlen
= hdrlen
;
286 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
287 len
+= (size_t)size
+ hdrlen
;
289 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
291 return got_error_from_errno("imsg_create RAW_OBJECT");
293 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1)
294 return got_error_from_errno("imsg_add RAW_OBJECT");
296 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
297 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1)
298 return got_error_from_errno("imsg_add RAW_OBJECT");
301 imsg_close(ibuf
, wbuf
);
302 return flush_imsg(ibuf
);
305 const struct got_error
*
306 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
307 struct imsgbuf
*ibuf
)
309 const struct got_error
*err
= NULL
;
311 struct got_imsg_raw_obj
*iobj
;
316 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
320 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
322 switch (imsg
.hdr
.type
) {
323 case GOT_IMSG_RAW_OBJECT
:
324 if (datalen
< sizeof(*iobj
)) {
325 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
330 *hdrlen
= iobj
->hdrlen
;
332 if (datalen
== sizeof(*iobj
)) {
333 /* Data has been written to file descriptor. */
338 *size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
339 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
343 *outbuf
= malloc(*size
+ *hdrlen
);
344 if (*outbuf
== NULL
) {
345 err
= got_error_from_errno("malloc");
348 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
351 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
360 const struct got_error
*
361 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
362 struct got_object_id
*id
, int pack_idx
)
364 const struct got_error
*err
= NULL
;
365 struct got_imsg_packed_object iobj
;
369 memset(&iobj
, 0, sizeof(iobj
));
370 if (pack_idx
!= -1) { /* commit is packed */
372 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
380 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
382 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
387 return flush_imsg(ibuf
);
390 const struct got_error
*
391 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
392 struct got_object_id
*id
, int pack_idx
)
394 const struct got_error
*err
;
399 len
= sizeof(struct got_imsg_packed_object
);
403 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
405 err
= got_error_from_errno("imsg_create TREE_REQUEST");
411 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1) {
412 err
= got_error_from_errno("imsg_add TREE_REQUEST");
418 if (pack_idx
!= -1) { /* tree is packed */
419 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1) {
420 err
= got_error_from_errno("imsg_add TREE_REQUEST");
427 ibuf_fd_set(wbuf
, fd
);
428 imsg_close(ibuf
, wbuf
);
430 return flush_imsg(ibuf
);
433 const struct got_error
*
434 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
435 struct got_object_id
*id
, int pack_idx
)
437 const struct got_error
*err
;
438 struct got_imsg_packed_object iobj
;
442 memset(&iobj
, 0, sizeof(iobj
));
443 if (pack_idx
!= -1) { /* tag is packed */
445 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
453 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
455 err
= got_error_from_errno("imsg_compose TAG_REQUEST");
461 return flush_imsg(ibuf
);
464 const struct got_error
*
465 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
466 struct got_object_id
*id
, int pack_idx
)
468 const struct got_error
*err
= NULL
;
469 struct got_imsg_packed_object iobj
;
473 memset(&iobj
, 0, sizeof(iobj
));
474 if (pack_idx
!= -1) { /* blob is packed */
476 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
484 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
486 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
491 return flush_imsg(ibuf
);
494 const struct got_error
*
495 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
497 const struct got_error
*err
= NULL
;
499 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
501 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
506 return flush_imsg(ibuf
);
509 static const struct got_error
*
510 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
512 const struct got_error
*err
= NULL
;
514 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
515 err
= got_error_from_errno("imsg_compose TMPFD");
520 return flush_imsg(ibuf
);
523 const struct got_error
*
524 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
526 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
529 const struct got_error
*
530 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
532 struct got_imsg_object iobj
;
534 memset(&iobj
, 0, sizeof(iobj
));
536 memcpy(&iobj
.id
, &obj
->id
, sizeof(iobj
.id
));
537 iobj
.type
= obj
->type
;
538 iobj
.flags
= obj
->flags
;
539 iobj
.hdrlen
= obj
->hdrlen
;
540 iobj
.size
= obj
->size
;
541 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
542 iobj
.pack_offset
= obj
->pack_offset
;
543 iobj
.pack_idx
= obj
->pack_idx
;
546 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
548 return got_error_from_errno("imsg_compose OBJECT");
550 return flush_imsg(ibuf
);
553 const struct got_error
*
554 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
555 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
556 struct got_pathlist_head
*wanted_branches
,
557 struct got_pathlist_head
*wanted_refs
, int list_refs_only
,
558 const char *worktree_branch
, const char *remote_head
,
559 int no_head
, int verbosity
)
561 const struct got_error
*err
= NULL
;
563 struct got_pathlist_entry
*pe
;
564 struct got_imsg_fetch_request fetchreq
;
565 size_t remote_head_len
, worktree_branch_len
, len
= sizeof(fetchreq
);
567 if (worktree_branch
) {
568 worktree_branch_len
= strlen(worktree_branch
);
569 len
+= worktree_branch_len
;
572 remote_head_len
= strlen(remote_head
);
573 len
+= remote_head_len
;
576 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
578 return got_error(GOT_ERR_NO_SPACE
);
581 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, len
);
583 err
= got_error_from_errno("imsg_create FETCH_HAVE_REF");
588 memset(&fetchreq
, 0, sizeof(fetchreq
));
589 fetchreq
.no_head
= no_head
;
590 fetchreq
.fetch_all_branches
= fetch_all_branches
;
591 fetchreq
.list_refs_only
= list_refs_only
;
592 fetchreq
.verbosity
= verbosity
;
593 if (worktree_branch
!= NULL
)
594 fetchreq
.worktree_branch_len
= worktree_branch_len
;
595 if (remote_head
!= NULL
)
596 fetchreq
.remote_head_len
= remote_head_len
;
597 TAILQ_FOREACH(pe
, have_refs
, entry
)
598 fetchreq
.n_have_refs
++;
599 TAILQ_FOREACH(pe
, wanted_branches
, entry
)
600 fetchreq
.n_wanted_branches
++;
601 TAILQ_FOREACH(pe
, wanted_refs
, entry
)
602 fetchreq
.n_wanted_refs
++;
603 if (imsg_add(wbuf
, &fetchreq
, sizeof(fetchreq
)) == -1)
604 return got_error_from_errno("imsg_add FETCH_REQUEST");
605 if (worktree_branch
) {
606 if (imsg_add(wbuf
, worktree_branch
, worktree_branch_len
)
608 err
= got_error_from_errno("imsg_add FETCH_REQUEST");
614 if (imsg_add(wbuf
, remote_head
, remote_head_len
) == -1) {
615 err
= got_error_from_errno("imsg_add FETCH_REQUEST");
620 ibuf_fd_set(wbuf
, fd
);
622 imsg_close(ibuf
, wbuf
);
624 err
= flush_imsg(ibuf
);
628 TAILQ_FOREACH(pe
, have_refs
, entry
) {
629 const char *name
= pe
->path
;
630 size_t name_len
= pe
->path_len
;
631 struct got_object_id
*id
= pe
->data
;
633 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
634 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
636 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
638 /* Keep in sync with struct got_imsg_fetch_have_ref! */
639 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
640 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
641 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
642 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
643 if (imsg_add(wbuf
, name
, name_len
) == -1)
644 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
646 imsg_close(ibuf
, wbuf
);
647 err
= flush_imsg(ibuf
);
652 TAILQ_FOREACH(pe
, wanted_branches
, entry
) {
653 const char *name
= pe
->path
;
654 size_t name_len
= pe
->path_len
;
656 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
657 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
660 return got_error_from_errno(
661 "imsg_create FETCH_WANTED_BRANCH");
663 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
664 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
665 return got_error_from_errno(
666 "imsg_add FETCH_WANTED_BRANCH");
667 if (imsg_add(wbuf
, name
, name_len
) == -1)
668 return got_error_from_errno(
669 "imsg_add FETCH_WANTED_BRANCH");
671 imsg_close(ibuf
, wbuf
);
672 err
= flush_imsg(ibuf
);
677 TAILQ_FOREACH(pe
, wanted_refs
, entry
) {
678 const char *name
= pe
->path
;
679 size_t name_len
= pe
->path_len
;
681 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
682 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
685 return got_error_from_errno(
686 "imsg_create FETCH_WANTED_REF");
688 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
689 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
690 return got_error_from_errno(
691 "imsg_add FETCH_WANTED_REF");
692 if (imsg_add(wbuf
, name
, name_len
) == -1)
693 return got_error_from_errno(
694 "imsg_add FETCH_WANTED_REF");
696 imsg_close(ibuf
, wbuf
);
697 err
= flush_imsg(ibuf
);
705 const struct got_error
*
706 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
708 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
711 const struct got_error
*
712 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
713 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
714 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
716 const struct got_error
*err
= NULL
;
719 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
727 *server_progress
= NULL
;
729 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
731 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
735 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
736 switch (imsg
.hdr
.type
) {
737 case GOT_IMSG_FETCH_SYMREFS
:
738 if (datalen
< sizeof(*isymrefs
)) {
739 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
742 if (isymrefs
!= NULL
) {
743 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
746 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
747 off
= sizeof(*isymrefs
);
748 remain
= datalen
- off
;
749 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
750 struct got_imsg_fetch_symref
*s
;
752 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
753 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
756 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
758 remain
-= sizeof(*s
);
759 if (remain
< s
->name_len
) {
760 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
763 name
= strndup(imsg
.data
+ off
, s
->name_len
);
765 err
= got_error_from_errno("strndup");
769 remain
-= s
->name_len
;
770 if (remain
< s
->target_len
) {
771 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
775 target
= strndup(imsg
.data
+ off
, s
->target_len
);
776 if (target
== NULL
) {
777 err
= got_error_from_errno("strndup");
781 off
+= s
->target_len
;
782 remain
-= s
->target_len
;
783 err
= got_pathlist_append(symrefs
, name
, target
);
791 case GOT_IMSG_FETCH_REF
:
792 if (datalen
<= sizeof(**id
)) {
793 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
796 *id
= malloc(sizeof(**id
));
798 err
= got_error_from_errno("malloc");
801 memcpy(*id
, imsg
.data
, sizeof(**id
));
802 *refname
= strndup(imsg
.data
+ sizeof(**id
),
803 datalen
- sizeof(**id
));
804 if (*refname
== NULL
) {
805 err
= got_error_from_errno("strndup");
809 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
811 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
814 *server_progress
= strndup(imsg
.data
, datalen
);
815 if (*server_progress
== NULL
) {
816 err
= got_error_from_errno("strndup");
819 for (i
= 0; i
< datalen
; i
++) {
820 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
821 !isspace((unsigned char)(*server_progress
)[i
])) {
822 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
823 free(*server_progress
);
824 *server_progress
= NULL
;
829 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
830 if (datalen
< sizeof(*packfile_size
)) {
831 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
834 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
836 case GOT_IMSG_FETCH_DONE
:
837 if (datalen
!= SHA1_DIGEST_LENGTH
) {
838 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
841 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
845 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
859 static const struct got_error
*
860 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
861 int delete, struct imsgbuf
*ibuf
)
866 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
867 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
869 return got_error_from_errno("imsg_create SEND_REF");
871 /* Keep in sync with struct got_imsg_send_ref! */
872 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
873 return got_error_from_errno("imsg_add SEND_REF");
874 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1)
875 return got_error_from_errno("imsg_add SEND_REF");
876 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
877 return got_error_from_errno("imsg_add SEND_REF");
878 if (imsg_add(wbuf
, name
, name_len
) == -1)
879 return got_error_from_errno("imsg_add SEND_REF");
881 imsg_close(ibuf
, wbuf
);
882 return flush_imsg(ibuf
);
885 const struct got_error
*
886 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
887 struct got_pathlist_head
*have_refs
,
888 struct got_pathlist_head
*delete_refs
,
891 const struct got_error
*err
= NULL
;
892 struct got_pathlist_entry
*pe
;
893 struct got_imsg_send_request sendreq
;
894 struct got_object_id zero_id
;
896 memset(&zero_id
, 0, sizeof(zero_id
));
897 memset(&sendreq
, 0, sizeof(sendreq
));
898 sendreq
.verbosity
= verbosity
;
899 TAILQ_FOREACH(pe
, have_refs
, entry
)
901 TAILQ_FOREACH(pe
, delete_refs
, entry
)
903 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
904 &sendreq
, sizeof(sendreq
)) == -1) {
905 err
= got_error_from_errno(
906 "imsg_compose FETCH_SERVER_PROGRESS");
911 err
= flush_imsg(ibuf
);
915 TAILQ_FOREACH(pe
, have_refs
, entry
) {
916 const char *name
= pe
->path
;
917 size_t name_len
= pe
->path_len
;
918 struct got_object_id
*id
= pe
->data
;
919 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
924 TAILQ_FOREACH(pe
, delete_refs
, entry
) {
925 const char *name
= pe
->path
;
926 size_t name_len
= pe
->path_len
;
927 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
932 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
933 err
= got_error_from_errno("close");
937 const struct got_error
*
938 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
939 struct imsgbuf
*ibuf
)
941 const struct got_error
*err
= NULL
;
945 struct got_imsg_send_remote_ref iremote_ref
;
946 struct got_object_id
*id
= NULL
;
947 char *refname
= NULL
;
948 struct got_pathlist_entry
*new;
951 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
954 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
955 switch (imsg
.hdr
.type
) {
956 case GOT_IMSG_SEND_REMOTE_REF
:
957 if (datalen
< sizeof(iremote_ref
)) {
958 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
961 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
962 if (datalen
!= sizeof(iremote_ref
) +
963 iremote_ref
.name_len
) {
964 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
967 id
= malloc(sizeof(*id
));
969 err
= got_error_from_errno("malloc");
972 memcpy(id
, &iremote_ref
.id
, sizeof(*id
));
973 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
974 datalen
- sizeof(iremote_ref
));
975 if (refname
== NULL
) {
976 err
= got_error_from_errno("strndup");
979 err
= got_pathlist_insert(&new, remote_refs
,
983 if (new == NULL
) { /* duplicate which wasn't inserted */
990 case GOT_IMSG_SEND_PACK_REQUEST
:
992 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
995 /* got-send-pack is now waiting for a pack file. */
999 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1010 const struct got_error
*
1011 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
1013 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
1016 const struct got_error
*
1017 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
1018 int *success
, char **refname
, char **errmsg
, struct imsgbuf
*ibuf
)
1020 const struct got_error
*err
= NULL
;
1023 struct got_imsg_send_ref_status iref_status
;
1025 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1031 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1035 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1036 switch (imsg
.hdr
.type
) {
1037 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
1038 if (datalen
< sizeof(*bytes_sent
)) {
1039 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1042 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
1044 case GOT_IMSG_SEND_REF_STATUS
:
1045 if (datalen
< sizeof(iref_status
)) {
1046 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1049 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
1050 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
+
1051 iref_status
.errmsg_len
) {
1052 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1055 *success
= iref_status
.success
;
1056 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1057 iref_status
.name_len
);
1059 if (iref_status
.errmsg_len
!= 0)
1060 *errmsg
= strndup(imsg
.data
+ sizeof(iref_status
) +
1061 iref_status
.name_len
, iref_status
.errmsg_len
);
1063 case GOT_IMSG_SEND_DONE
:
1065 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1071 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1079 const struct got_error
*
1080 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, uint8_t *pack_sha1
,
1083 const struct got_error
*err
= NULL
;
1085 /* Keep in sync with struct got_imsg_index_pack_request */
1086 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1087 pack_sha1
, SHA1_DIGEST_LENGTH
) == -1) {
1088 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1092 return flush_imsg(ibuf
);
1095 const struct got_error
*
1096 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1098 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1101 const struct got_error
*
1102 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1103 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1104 struct imsgbuf
*ibuf
)
1106 const struct got_error
*err
= NULL
;
1108 struct got_imsg_index_pack_progress
*iprogress
;
1116 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1120 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1121 switch (imsg
.hdr
.type
) {
1122 case GOT_IMSG_IDXPACK_PROGRESS
:
1123 if (datalen
< sizeof(*iprogress
)) {
1124 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1127 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1128 if (iprogress
->nobj_total
< 0 || iprogress
->nobj_indexed
< 0 ||
1129 iprogress
->nobj_loose
< 0 || iprogress
->nobj_resolved
< 0) {
1130 err
= got_error(GOT_ERR_RANGE
);
1133 *nobj_total
= iprogress
->nobj_total
;
1134 *nobj_indexed
= iprogress
->nobj_indexed
;
1135 *nobj_loose
= iprogress
->nobj_loose
;
1136 *nobj_resolved
= iprogress
->nobj_resolved
;
1138 case GOT_IMSG_IDXPACK_DONE
:
1140 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1146 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1154 const struct got_error
*
1155 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1156 struct imsgbuf
*ibuf
)
1158 struct got_imsg_object
*iobj
;
1159 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1161 if (datalen
!= sizeof(*iobj
))
1162 return got_error(GOT_ERR_PRIVSEP_LEN
);
1165 if (iobj
->pack_offset
< 0)
1166 return got_error(GOT_ERR_PACK_OFFSET
);
1168 *obj
= calloc(1, sizeof(**obj
));
1170 return got_error_from_errno("calloc");
1172 memcpy(&(*obj
)->id
, &iobj
->id
, sizeof(iobj
->id
));
1173 (*obj
)->type
= iobj
->type
;
1174 (*obj
)->flags
= iobj
->flags
;
1175 (*obj
)->hdrlen
= iobj
->hdrlen
;
1176 (*obj
)->size
= iobj
->size
;
1177 /* path_packfile is handled by caller */
1178 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1179 (*obj
)->pack_offset
= iobj
->pack_offset
;
1180 (*obj
)->pack_idx
= iobj
->pack_idx
;
1182 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1186 const struct got_error
*
1187 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1189 const struct got_error
*err
= NULL
;
1191 const size_t min_datalen
= sizeof(struct got_imsg_object
);
1195 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1199 switch (imsg
.hdr
.type
) {
1200 case GOT_IMSG_OBJECT
:
1201 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1204 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1213 static const struct got_error
*
1214 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1217 const struct got_error
*err
= NULL
;
1218 size_t offset
, remain
;
1221 remain
= logmsg_len
;
1222 while (remain
> 0) {
1223 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1225 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1226 commit
->logmsg
+ offset
, n
) == -1) {
1227 err
= got_error_from_errno("imsg_compose "
1232 err
= flush_imsg(ibuf
);
1243 const struct got_error
*
1244 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1246 const struct got_error
*err
= NULL
;
1247 struct got_imsg_commit_object
*icommit
;
1250 struct got_object_qid
*qid
;
1251 size_t author_len
= strlen(commit
->author
);
1252 size_t committer_len
= strlen(commit
->committer
);
1253 size_t logmsg_len
= strlen(commit
->logmsg
);
1255 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1256 commit
->nparents
* sizeof(struct got_object_id
);
1258 buf
= malloc(total
);
1260 return got_error_from_errno("malloc");
1262 icommit
= (struct got_imsg_commit_object
*)buf
;
1263 memcpy(&icommit
->tree_id
, commit
->tree_id
, sizeof(icommit
->tree_id
));
1264 icommit
->author_len
= author_len
;
1265 icommit
->author_time
= commit
->author_time
;
1266 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1267 icommit
->committer_len
= committer_len
;
1268 icommit
->committer_time
= commit
->committer_time
;
1269 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1270 icommit
->logmsg_len
= logmsg_len
;
1271 icommit
->nparents
= commit
->nparents
;
1273 len
= sizeof(*icommit
);
1274 memcpy(buf
+ len
, commit
->author
, author_len
);
1276 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1277 len
+= committer_len
;
1278 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1279 memcpy(buf
+ len
, &qid
->id
, sizeof(qid
->id
));
1280 len
+= sizeof(qid
->id
);
1283 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1284 err
= got_error_from_errno("imsg_compose COMMIT");
1288 if (logmsg_len
== 0 ||
1289 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1290 err
= flush_imsg(ibuf
);
1294 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1300 static const struct got_error
*
1301 get_commit_from_imsg(struct got_commit_object
**commit
,
1302 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1304 const struct got_error
*err
= NULL
;
1305 struct got_imsg_commit_object
*icommit
;
1309 if (datalen
< sizeof(*icommit
))
1310 return got_error(GOT_ERR_PRIVSEP_LEN
);
1312 icommit
= imsg
->data
;
1313 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1314 icommit
->committer_len
+
1315 icommit
->nparents
* sizeof(struct got_object_id
))
1316 return got_error(GOT_ERR_PRIVSEP_LEN
);
1318 if (icommit
->nparents
< 0)
1319 return got_error(GOT_ERR_PRIVSEP_LEN
);
1321 len
+= sizeof(*icommit
);
1323 *commit
= got_object_commit_alloc_partial();
1324 if (*commit
== NULL
)
1325 return got_error_from_errno(
1326 "got_object_commit_alloc_partial");
1328 memcpy((*commit
)->tree_id
, &icommit
->tree_id
,
1329 sizeof(icommit
->tree_id
));
1330 (*commit
)->author_time
= icommit
->author_time
;
1331 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1332 (*commit
)->committer_time
= icommit
->committer_time
;
1333 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1335 (*commit
)->author
= strndup(imsg
->data
+ len
, icommit
->author_len
);
1336 if ((*commit
)->author
== NULL
) {
1337 err
= got_error_from_errno("strndup");
1340 len
+= icommit
->author_len
;
1342 (*commit
)->committer
= strndup(imsg
->data
+ len
,
1343 icommit
->committer_len
);
1344 if ((*commit
)->committer
== NULL
) {
1345 err
= got_error_from_errno("strndup");
1348 len
+= icommit
->committer_len
;
1350 if (icommit
->logmsg_len
== 0) {
1351 (*commit
)->logmsg
= strdup("");
1352 if ((*commit
)->logmsg
== NULL
) {
1353 err
= got_error_from_errno("strdup");
1357 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1359 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1360 if ((*commit
)->logmsg
== NULL
) {
1361 err
= got_error_from_errno("malloc");
1364 while (remain
> 0) {
1365 struct imsg imsg_log
;
1366 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1369 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1373 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1374 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1378 memcpy((*commit
)->logmsg
+ offset
,
1380 imsg_free(&imsg_log
);
1384 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1387 for (i
= 0; i
< icommit
->nparents
; i
++) {
1388 struct got_object_qid
*qid
;
1390 err
= got_object_qid_alloc_partial(&qid
);
1393 memcpy(&qid
->id
, imsg
->data
+ len
+
1394 i
* sizeof(qid
->id
), sizeof(qid
->id
));
1395 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1396 (*commit
)->nparents
++;
1400 got_object_commit_close(*commit
);
1406 const struct got_error
*
1407 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1409 const struct got_error
*err
= NULL
;
1412 const size_t min_datalen
= sizeof(struct got_imsg_commit_object
);
1416 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1420 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1422 switch (imsg
.hdr
.type
) {
1423 case GOT_IMSG_COMMIT
:
1424 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1427 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1436 static const struct got_error
*
1437 send_tree_entries_batch(struct imsgbuf
*ibuf
,
1438 struct got_parsed_tree_entry
*entries
, int idx0
, int idxN
, size_t len
)
1441 struct got_imsg_tree_entries ientries
;
1444 memset(&ientries
, 0, sizeof(ientries
));
1446 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRIES
, 0, 0, len
);
1448 return got_error_from_errno("imsg_create TREE_ENTRY");
1450 ientries
.nentries
= idxN
- idx0
+ 1;
1451 if (imsg_add(wbuf
, &ientries
, sizeof(ientries
)) == -1)
1452 return got_error_from_errno("imsg_add TREE_ENTRY");
1454 for (i
= idx0
; i
<= idxN
; i
++) {
1455 static const char gap
[12]; /* for sha1 inside sha256 align */
1456 struct got_parsed_tree_entry
*pte
= &entries
[i
];
1458 /* Keep in sync with struct got_imsg_tree_entry definition! */
1459 if (imsg_add(wbuf
, pte
->id
, pte
->idlen
) == -1)
1460 return got_error_from_errno("imsg_add TREE_ENTRY");
1461 if (pte
->algo
== GOT_HASH_SHA1
&&
1462 imsg_add(wbuf
, gap
, sizeof(gap
)) == -1)
1463 return got_error_from_errno("imsg_add TREE_ENTRY");
1464 if (imsg_add(wbuf
, &pte
->algo
, sizeof(pte
->algo
)) == -1)
1465 return got_error_from_errno("imsg_add TREE_ENTRY");
1466 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1)
1467 return got_error_from_errno("imsg_add TREE_ENTRY");
1468 if (imsg_add(wbuf
, &pte
->namelen
, sizeof(pte
->namelen
)) == -1)
1469 return got_error_from_errno("imsg_add TREE_ENTRY");
1471 /* Remaining bytes are the entry's name. */
1472 if (imsg_add(wbuf
, pte
->name
, pte
->namelen
) == -1)
1473 return got_error_from_errno("imsg_add TREE_ENTRY");
1476 imsg_close(ibuf
, wbuf
);
1480 static const struct got_error
*
1481 send_tree_entries(struct imsgbuf
*ibuf
, struct got_parsed_tree_entry
*entries
,
1484 const struct got_error
*err
= NULL
;
1486 size_t entries_len
= sizeof(struct got_imsg_tree_entries
);
1489 for (j
= 0; j
< nentries
; j
++) {
1490 struct got_parsed_tree_entry
*pte
= &entries
[j
];
1491 size_t len
= sizeof(struct got_imsg_tree_entry
) + pte
->namelen
;
1494 entries_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1495 err
= send_tree_entries_batch(ibuf
, entries
,
1496 i
, j
- 1, entries_len
);
1500 entries_len
= sizeof(struct got_imsg_tree_entries
);
1507 err
= send_tree_entries_batch(ibuf
, entries
, i
, j
- 1,
1516 const struct got_error
*
1517 got_privsep_send_tree(struct imsgbuf
*ibuf
,
1518 struct got_parsed_tree_entry
*entries
, int nentries
)
1520 const struct got_error
*err
= NULL
;
1521 struct got_imsg_tree_object itree
;
1523 memset(&itree
, 0, sizeof(itree
));
1524 itree
.nentries
= nentries
;
1525 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1527 return got_error_from_errno("imsg_compose TREE");
1529 err
= send_tree_entries(ibuf
, entries
, nentries
);
1533 return flush_imsg(ibuf
);
1537 static const struct got_error
*
1538 recv_tree_entries(void *data
, size_t datalen
, struct got_tree_object
*tree
,
1541 const struct got_error
*err
= NULL
;
1542 struct got_imsg_tree_entries
*ientries
;
1543 struct got_tree_entry
*te
;
1547 if (datalen
<= sizeof(*ientries
) ||
1548 datalen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
1549 return got_error(GOT_ERR_PRIVSEP_LEN
);
1551 ientries
= (struct got_imsg_tree_entries
*)data
;
1552 if (ientries
->nentries
> INT_MAX
) {
1553 return got_error_msg(GOT_ERR_NO_SPACE
,
1554 "too many tree entries");
1557 te_offset
= sizeof(*ientries
);
1558 for (i
= 0; i
< ientries
->nentries
; i
++) {
1559 struct got_imsg_tree_entry ite
;
1560 const char *te_name
;
1561 uint8_t *buf
= (uint8_t *)data
+ te_offset
;
1563 if (te_offset
>= datalen
) {
1564 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1568 /* Might not be aligned, size is ~32 bytes. */
1569 memcpy(&ite
, buf
, sizeof(ite
));
1571 if (ite
.namelen
>= sizeof(te
->name
)) {
1572 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1575 if (te_offset
+ sizeof(ite
) + ite
.namelen
> datalen
) {
1576 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1580 if (*nentries
>= tree
->nentries
) {
1581 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1584 te
= &tree
->entries
[*nentries
];
1585 te_name
= buf
+ sizeof(ite
);
1586 memcpy(te
->name
, te_name
, ite
.namelen
);
1587 te
->name
[ite
.namelen
] = '\0';
1588 memcpy(te
->id
.sha1
, ite
.id
, sizeof(te
->id
.sha1
));
1589 te
->mode
= ite
.mode
;
1590 te
->idx
= *nentries
;
1593 te_offset
+= sizeof(ite
) + ite
.namelen
;
1599 const struct got_error
*
1600 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1602 const struct got_error
*err
= NULL
;
1603 const size_t min_datalen
= sizeof(struct got_imsg_tree_object
);
1604 struct got_imsg_tree_object
*itree
;
1609 while (*tree
== NULL
|| nentries
< (*tree
)->nentries
) {
1613 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1617 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1619 switch (imsg
.hdr
.type
) {
1621 /* This message should only appear once. */
1622 if (*tree
!= NULL
) {
1623 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1626 if (datalen
!= sizeof(*itree
)) {
1627 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1631 if (itree
->nentries
< 0) {
1632 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1635 *tree
= malloc(sizeof(**tree
));
1636 if (*tree
== NULL
) {
1637 err
= got_error_from_errno("malloc");
1640 (*tree
)->entries
= calloc(itree
->nentries
,
1641 sizeof(struct got_tree_entry
));
1642 if ((*tree
)->entries
== NULL
) {
1643 err
= got_error_from_errno("malloc");
1648 (*tree
)->nentries
= itree
->nentries
;
1649 (*tree
)->refcnt
= 0;
1651 case GOT_IMSG_TREE_ENTRIES
:
1652 /* This message should be preceeded by GOT_IMSG_TREE. */
1653 if (*tree
== NULL
) {
1654 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1657 err
= recv_tree_entries(imsg
.data
, datalen
,
1661 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1670 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1672 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1673 got_object_tree_close(*tree
);
1680 const struct got_error
*
1681 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1682 const uint8_t *data
)
1684 struct got_imsg_blob iblob
;
1686 memset(&iblob
, 0, sizeof(iblob
));
1688 iblob
.hdrlen
= hdrlen
;
1693 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1694 return got_error(GOT_ERR_NO_SPACE
);
1696 buf
= malloc(sizeof(iblob
) + size
);
1698 return got_error_from_errno("malloc");
1700 memcpy(buf
, &iblob
, sizeof(iblob
));
1701 memcpy(buf
+ sizeof(iblob
), data
, size
);
1702 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1703 sizeof(iblob
) + size
) == -1) {
1705 return got_error_from_errno("imsg_compose BLOB");
1709 /* Data has already been written to file descriptor. */
1710 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1711 sizeof(iblob
)) == -1)
1712 return got_error_from_errno("imsg_compose BLOB");
1716 return flush_imsg(ibuf
);
1719 const struct got_error
*
1720 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1721 struct imsgbuf
*ibuf
)
1723 const struct got_error
*err
= NULL
;
1725 struct got_imsg_blob
*iblob
;
1730 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1734 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1736 switch (imsg
.hdr
.type
) {
1738 if (datalen
< sizeof(*iblob
)) {
1739 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1743 *size
= iblob
->size
;
1744 *hdrlen
= iblob
->hdrlen
;
1746 if (datalen
== sizeof(*iblob
)) {
1747 /* Data has been written to file descriptor. */
1751 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
||
1752 *size
> datalen
+ sizeof(*iblob
)) {
1753 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1757 *outbuf
= malloc(*size
);
1758 if (*outbuf
== NULL
) {
1759 err
= got_error_from_errno("malloc");
1762 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1765 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1774 static const struct got_error
*
1775 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1777 const struct got_error
*err
= NULL
;
1778 size_t offset
, remain
;
1781 remain
= tagmsg_len
;
1782 while (remain
> 0) {
1783 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1785 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1786 tag
->tagmsg
+ offset
, n
) == -1) {
1787 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1791 err
= flush_imsg(ibuf
);
1802 const struct got_error
*
1803 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1805 const struct got_error
*err
= NULL
;
1806 struct got_imsg_tag_object
*itag
;
1809 size_t tag_len
= strlen(tag
->tag
);
1810 size_t tagger_len
= strlen(tag
->tagger
);
1811 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1813 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1815 buf
= malloc(total
);
1817 return got_error_from_errno("malloc");
1819 itag
= (struct got_imsg_tag_object
*)buf
;
1820 memcpy(&itag
->id
, &tag
->id
, sizeof(itag
->id
));
1821 itag
->obj_type
= tag
->obj_type
;
1822 itag
->tag_len
= tag_len
;
1823 itag
->tagger_len
= tagger_len
;
1824 itag
->tagger_time
= tag
->tagger_time
;
1825 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1826 itag
->tagmsg_len
= tagmsg_len
;
1828 len
= sizeof(*itag
);
1829 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1831 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1834 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1835 err
= got_error_from_errno("imsg_compose TAG");
1839 if (tagmsg_len
== 0 ||
1840 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1841 err
= flush_imsg(ibuf
);
1845 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1851 const struct got_error
*
1852 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1854 const struct got_error
*err
= NULL
;
1856 struct got_imsg_tag_object
*itag
;
1857 size_t len
, datalen
;
1858 const size_t min_datalen
= sizeof(struct got_imsg_tag_object
);
1862 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1866 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1869 switch (imsg
.hdr
.type
) {
1871 if (datalen
< sizeof(*itag
)) {
1872 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1876 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1878 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1881 len
+= sizeof(*itag
);
1883 *tag
= calloc(1, sizeof(**tag
));
1885 err
= got_error_from_errno("calloc");
1889 memcpy(&(*tag
)->id
, &itag
->id
, sizeof(itag
->id
));
1891 (*tag
)->tag
= strndup(imsg
.data
+ len
, itag
->tag_len
);
1892 if ((*tag
)->tag
== NULL
) {
1893 err
= got_error_from_errno("strndup");
1896 len
+= itag
->tag_len
;
1898 (*tag
)->obj_type
= itag
->obj_type
;
1899 (*tag
)->tagger_time
= itag
->tagger_time
;
1900 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1902 (*tag
)->tagger
= strndup(imsg
.data
+ len
, itag
->tagger_len
);
1903 if ((*tag
)->tagger
== NULL
) {
1904 err
= got_error_from_errno("strndup");
1907 len
+= itag
->tagger_len
;
1909 if (itag
->tagmsg_len
== 0) {
1910 (*tag
)->tagmsg
= strdup("");
1911 if ((*tag
)->tagmsg
== NULL
) {
1912 err
= got_error_from_errno("strdup");
1916 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1918 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1919 if ((*tag
)->tagmsg
== NULL
) {
1920 err
= got_error_from_errno("malloc");
1923 while (remain
> 0) {
1924 struct imsg imsg_log
;
1925 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1928 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1932 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1933 return got_error(GOT_ERR_PRIVSEP_MSG
);
1935 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1937 imsg_free(&imsg_log
);
1941 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1946 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1955 const struct got_error
*
1956 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1957 struct got_packidx
*packidx
)
1959 const struct got_error
*err
= NULL
;
1960 struct got_imsg_packidx ipackidx
;
1961 struct got_imsg_pack ipack
;
1964 memset(&ipackidx
, 0, sizeof(ipackidx
));
1965 memset(&ipack
, 0, sizeof(ipack
));
1967 ipackidx
.len
= packidx
->len
;
1968 ipackidx
.packfile_size
= pack
->filesize
;
1969 ipackidx
.algo
= packidx
->algo
;
1970 fd
= dup(packidx
->fd
);
1972 return got_error_from_errno("dup");
1974 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1975 sizeof(ipackidx
)) == -1) {
1976 err
= got_error_from_errno("imsg_compose PACKIDX");
1981 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1982 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1983 return got_error(GOT_ERR_NO_SPACE
);
1984 ipack
.filesize
= pack
->filesize
;
1985 ipack
.algo
= pack
->algo
;
1989 return got_error_from_errno("dup");
1991 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
1993 err
= got_error_from_errno("imsg_compose PACK");
1998 return flush_imsg(ibuf
);
2001 const struct got_error
*
2002 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
2003 struct got_object_id
*id
)
2005 struct got_imsg_packed_object iobj
;
2007 memset(&iobj
, 0, sizeof(iobj
));
2009 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2011 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
2012 &iobj
, sizeof(iobj
)) == -1)
2013 return got_error_from_errno("imsg_compose "
2014 "PACKED_OBJECT_REQUEST");
2016 return flush_imsg(ibuf
);
2019 const struct got_error
*
2020 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
2021 struct got_object_id
*id
)
2023 struct got_imsg_packed_object iobj
;
2025 memset(&iobj
, 0, sizeof(iobj
));
2027 memcpy(&iobj
.id
, id
, sizeof(iobj
.id
));
2029 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
2030 &iobj
, sizeof(iobj
)) == -1)
2031 return got_error_from_errno("imsg_compose "
2032 "PACKED_OBJECT_REQUEST");
2034 return flush_imsg(ibuf
);
2037 const struct got_error
*
2038 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2040 const struct got_error
*err
= NULL
;
2042 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2044 err
= got_error_from_errno("imsg_compose "
2045 "GITCONFIG_PARSE_REQUEST");
2050 return flush_imsg(ibuf
);
2053 const struct got_error
*
2054 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2056 if (imsg_compose(ibuf
,
2057 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2059 return got_error_from_errno("imsg_compose "
2060 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2062 return flush_imsg(ibuf
);
2065 const struct got_error
*
2066 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2068 if (imsg_compose(ibuf
,
2069 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2071 return got_error_from_errno("imsg_compose "
2072 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2074 return flush_imsg(ibuf
);
2078 const struct got_error
*
2079 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2081 if (imsg_compose(ibuf
,
2082 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2083 return got_error_from_errno("imsg_compose "
2084 "GITCONFIG_AUTHOR_NAME_REQUEST");
2086 return flush_imsg(ibuf
);
2089 const struct got_error
*
2090 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2092 if (imsg_compose(ibuf
,
2093 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2094 return got_error_from_errno("imsg_compose "
2095 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2097 return flush_imsg(ibuf
);
2100 const struct got_error
*
2101 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2103 if (imsg_compose(ibuf
,
2104 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2105 return got_error_from_errno("imsg_compose "
2106 "GITCONFIG_REMOTE_REQUEST");
2108 return flush_imsg(ibuf
);
2111 const struct got_error
*
2112 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2114 if (imsg_compose(ibuf
,
2115 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2116 return got_error_from_errno("imsg_compose "
2117 "GITCONFIG_OWNER_REQUEST");
2119 return flush_imsg(ibuf
);
2122 const struct got_error
*
2123 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2125 const struct got_error
*err
= NULL
;
2131 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2134 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2136 switch (imsg
.hdr
.type
) {
2137 case GOT_IMSG_GITCONFIG_STR_VAL
:
2140 *str
= strndup(imsg
.data
, datalen
);
2142 err
= got_error_from_errno("strndup");
2147 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2155 const struct got_error
*
2156 got_privsep_recv_gitconfig_pair(char **key
, char **val
, struct imsgbuf
*ibuf
)
2158 const struct got_error
*err
= NULL
;
2159 struct got_imsg_gitconfig_pair p
;
2166 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2171 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2173 if (imsg
.hdr
.type
!= GOT_IMSG_GITCONFIG_PAIR
) {
2174 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2178 if (datalen
< sizeof(p
)) {
2179 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2183 memcpy(&p
, data
, sizeof(p
));
2186 if (datalen
!= sizeof(p
) + p
.klen
+ p
.vlen
) {
2187 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2191 *key
= strndup(data
, p
.klen
);
2193 err
= got_error_from_errno("strndup");
2198 *val
= strndup(data
, p
.vlen
);
2200 err
= got_error_from_errno("strndup");
2209 const struct got_error
*
2210 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2212 const struct got_error
*err
= NULL
;
2215 const size_t min_datalen
= sizeof(int);
2219 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2222 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2224 switch (imsg
.hdr
.type
) {
2225 case GOT_IMSG_GITCONFIG_INT_VAL
:
2226 if (datalen
!= sizeof(*val
)) {
2227 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2230 memcpy(val
, imsg
.data
, sizeof(*val
));
2233 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2242 free_remote_data(struct got_remote_repo
*remote
)
2247 free(remote
->fetch_url
);
2248 free(remote
->send_url
);
2249 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2250 free(remote
->fetch_branches
[i
]);
2251 free(remote
->fetch_branches
);
2252 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2253 free(remote
->send_branches
[i
]);
2254 free(remote
->send_branches
);
2255 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2256 free(remote
->fetch_refs
[i
]);
2257 free(remote
->fetch_refs
);
2260 const struct got_error
*
2261 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2262 int *nremotes
, struct imsgbuf
*ibuf
)
2264 const struct got_error
*err
= NULL
;
2267 struct got_imsg_remotes iremotes
;
2268 struct got_imsg_remote iremote
;
2272 iremotes
.nremotes
= 0;
2274 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2277 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2279 switch (imsg
.hdr
.type
) {
2280 case GOT_IMSG_GITCONFIG_REMOTES
:
2281 if (datalen
!= sizeof(iremotes
)) {
2283 return got_error(GOT_ERR_PRIVSEP_LEN
);
2285 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2286 if (iremotes
.nremotes
== 0) {
2293 return got_error(GOT_ERR_PRIVSEP_MSG
);
2298 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2299 if (*remotes
== NULL
)
2300 return got_error_from_errno("recallocarray");
2302 while (*nremotes
< iremotes
.nremotes
) {
2303 struct got_remote_repo
*remote
;
2305 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2308 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2310 switch (imsg
.hdr
.type
) {
2311 case GOT_IMSG_GITCONFIG_REMOTE
:
2312 remote
= &(*remotes
)[*nremotes
];
2313 memset(remote
, 0, sizeof(*remote
));
2314 if (datalen
< sizeof(iremote
)) {
2315 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2318 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2319 if (iremote
.name_len
== 0 ||
2320 iremote
.fetch_url_len
== 0 ||
2321 iremote
.send_url_len
== 0 ||
2322 (sizeof(iremote
) + iremote
.name_len
+
2323 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2324 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2327 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2329 if (remote
->name
== NULL
) {
2330 err
= got_error_from_errno("strndup");
2333 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2334 iremote
.name_len
, iremote
.fetch_url_len
);
2335 if (remote
->fetch_url
== NULL
) {
2336 err
= got_error_from_errno("strndup");
2337 free_remote_data(remote
);
2340 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2341 iremote
.name_len
+ iremote
.fetch_url_len
,
2342 iremote
.send_url_len
);
2343 if (remote
->send_url
== NULL
) {
2344 err
= got_error_from_errno("strndup");
2345 free_remote_data(remote
);
2348 remote
->mirror_references
= iremote
.mirror_references
;
2349 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2350 remote
->nfetch_branches
= 0;
2351 remote
->fetch_branches
= NULL
;
2352 remote
->nsend_branches
= 0;
2353 remote
->send_branches
= NULL
;
2354 remote
->nfetch_refs
= 0;
2355 remote
->fetch_refs
= NULL
;
2359 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2370 for (i
= 0; i
< *nremotes
; i
++)
2371 free_remote_data(&(*remotes
)[i
]);
2379 const struct got_error
*
2380 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2382 const struct got_error
*err
= NULL
;
2384 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2386 err
= got_error_from_errno("imsg_compose "
2387 "GOTCONFIG_PARSE_REQUEST");
2392 return flush_imsg(ibuf
);
2395 const struct got_error
*
2396 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2398 if (imsg_compose(ibuf
,
2399 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2400 return got_error_from_errno("imsg_compose "
2401 "GOTCONFIG_AUTHOR_REQUEST");
2403 return flush_imsg(ibuf
);
2406 const struct got_error
*
2407 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf
*ibuf
)
2409 if (imsg_compose(ibuf
,
2410 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2411 return got_error_from_errno("imsg_compose "
2412 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2414 return flush_imsg(ibuf
);
2417 const struct got_error
*
2418 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf
*ibuf
)
2420 if (imsg_compose(ibuf
,
2421 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2422 return got_error_from_errno("imsg_compose "
2423 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2425 return flush_imsg(ibuf
);
2428 const struct got_error
*
2429 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf
*ibuf
)
2431 if (imsg_compose(ibuf
,
2432 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2433 return got_error_from_errno("imsg_compose "
2434 "GOTCONFIG_SIGNERID_REQUEST");
2436 return flush_imsg(ibuf
);
2439 const struct got_error
*
2440 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2442 if (imsg_compose(ibuf
,
2443 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2444 return got_error_from_errno("imsg_compose "
2445 "GOTCONFIG_REMOTE_REQUEST");
2447 return flush_imsg(ibuf
);
2450 const struct got_error
*
2451 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2453 const struct got_error
*err
= NULL
;
2459 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2462 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2464 switch (imsg
.hdr
.type
) {
2465 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2468 *str
= strndup(imsg
.data
, datalen
);
2470 err
= got_error_from_errno("strndup");
2475 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2483 const struct got_error
*
2484 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2485 int *nremotes
, struct imsgbuf
*ibuf
)
2487 const struct got_error
*err
= NULL
;
2490 struct got_imsg_remotes iremotes
;
2491 struct got_imsg_remote iremote
;
2492 const size_t min_datalen
= sizeof(iremotes
);
2496 iremotes
.nremotes
= 0;
2498 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2501 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2503 switch (imsg
.hdr
.type
) {
2504 case GOT_IMSG_GOTCONFIG_REMOTES
:
2505 if (datalen
!= sizeof(iremotes
)) {
2506 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2509 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2510 if (iremotes
.nremotes
< 0) {
2511 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2514 if (iremotes
.nremotes
== 0) {
2521 return got_error(GOT_ERR_PRIVSEP_MSG
);
2526 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2527 if (*remotes
== NULL
)
2528 return got_error_from_errno("recallocarray");
2530 while (*nremotes
< iremotes
.nremotes
) {
2531 struct got_remote_repo
*remote
;
2532 const size_t min_datalen
= sizeof(iremote
);
2535 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2538 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2540 switch (imsg
.hdr
.type
) {
2541 case GOT_IMSG_GOTCONFIG_REMOTE
:
2542 remote
= &(*remotes
)[*nremotes
];
2543 memset(remote
, 0, sizeof(*remote
));
2544 if (datalen
< sizeof(iremote
)) {
2545 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2548 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2549 if (iremote
.name_len
== 0 ||
2550 (iremote
.fetch_url_len
== 0 &&
2551 iremote
.send_url_len
== 0) ||
2552 (sizeof(iremote
) + iremote
.name_len
+
2553 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2555 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2558 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2560 if (remote
->name
== NULL
) {
2561 err
= got_error_from_errno("strndup");
2564 remote
->fetch_url
= strndup(imsg
.data
+
2565 sizeof(iremote
) + iremote
.name_len
,
2566 iremote
.fetch_url_len
);
2567 if (remote
->fetch_url
== NULL
) {
2568 err
= got_error_from_errno("strndup");
2569 free_remote_data(remote
);
2572 remote
->send_url
= strndup(imsg
.data
+
2573 sizeof(iremote
) + iremote
.name_len
+
2574 iremote
.fetch_url_len
, iremote
.send_url_len
);
2575 if (remote
->send_url
== NULL
) {
2576 err
= got_error_from_errno("strndup");
2577 free_remote_data(remote
);
2580 remote
->mirror_references
= iremote
.mirror_references
;
2581 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2582 if (iremote
.nfetch_branches
> 0) {
2583 remote
->fetch_branches
= recallocarray(NULL
, 0,
2584 iremote
.nfetch_branches
, sizeof(char *));
2585 if (remote
->fetch_branches
== NULL
) {
2586 err
= got_error_from_errno("calloc");
2587 free_remote_data(remote
);
2591 remote
->nfetch_branches
= 0;
2592 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2594 err
= got_privsep_recv_gotconfig_str(&branch
,
2597 free_remote_data(remote
);
2600 remote
->fetch_branches
[i
] = branch
;
2601 remote
->nfetch_branches
++;
2603 if (iremote
.nsend_branches
> 0) {
2604 remote
->send_branches
= recallocarray(NULL
, 0,
2605 iremote
.nsend_branches
, sizeof(char *));
2606 if (remote
->send_branches
== NULL
) {
2607 err
= got_error_from_errno("calloc");
2608 free_remote_data(remote
);
2612 remote
->nsend_branches
= 0;
2613 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2615 err
= got_privsep_recv_gotconfig_str(&branch
,
2618 free_remote_data(remote
);
2621 remote
->send_branches
[i
] = branch
;
2622 remote
->nsend_branches
++;
2624 if (iremote
.nfetch_refs
> 0) {
2625 remote
->fetch_refs
= recallocarray(NULL
, 0,
2626 iremote
.nfetch_refs
, sizeof(char *));
2627 if (remote
->fetch_refs
== NULL
) {
2628 err
= got_error_from_errno("calloc");
2629 free_remote_data(remote
);
2633 remote
->nfetch_refs
= 0;
2634 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2636 err
= got_privsep_recv_gotconfig_str(&ref
,
2639 free_remote_data(remote
);
2642 remote
->fetch_refs
[i
] = ref
;
2643 remote
->nfetch_refs
++;
2648 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2659 for (i
= 0; i
< *nremotes
; i
++)
2660 free_remote_data(&(*remotes
)[i
]);
2668 const struct got_error
*
2669 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2670 struct got_object_id
*id
, int idx
, const char *path
)
2673 size_t path_len
= strlen(path
);
2675 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2676 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2678 return got_error_from_errno(
2679 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2681 * Keep in sync with struct got_imsg_commit_traversal_request
2682 * and struct got_imsg_packed_object.
2684 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
2685 return got_error_from_errno("imsg_add "
2686 "COMMIT_TRAVERSAL_REQUEST");
2687 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1)
2688 return got_error_from_errno("imsg_add "
2689 "COMMIT_TRAVERSAL_REQUEST");
2690 if (imsg_add(wbuf
, &path_len
, sizeof(path_len
)) == -1)
2691 return got_error_from_errno("imsg_add "
2692 "COMMIT_TRAVERSAL_REQUEST");
2693 if (imsg_add(wbuf
, path
, path_len
) == -1)
2694 return got_error_from_errno("imsg_add "
2695 "COMMIT_TRAVERSAL_REQUEST");
2697 imsg_close(ibuf
, wbuf
);
2698 return flush_imsg(ibuf
);
2701 const struct got_error
*
2702 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2703 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2705 const struct got_error
*err
= NULL
;
2707 struct got_imsg_traversed_commits
*icommits
;
2708 struct got_object_id
*ids
;
2712 *changed_commit
= NULL
;
2715 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2719 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2720 switch (imsg
.hdr
.type
) {
2721 case GOT_IMSG_TRAVERSED_COMMITS
:
2722 icommits
= imsg
.data
;
2723 if (datalen
!= sizeof(*icommits
) +
2724 icommits
->ncommits
* sizeof(*ids
)) {
2725 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2728 ids
= imsg
.data
+ sizeof(*icommits
);
2729 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2730 struct got_object_qid
*qid
;
2732 err
= got_object_qid_alloc_partial(&qid
);
2735 memcpy(&qid
->id
, &ids
[i
], sizeof(ids
[i
]));
2736 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2740 case GOT_IMSG_COMMIT
:
2741 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2744 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2748 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2758 got_object_id_queue_free(commit_ids
);
2762 const struct got_error
*
2763 got_privsep_send_enumerated_tree(size_t *totlen
, struct imsgbuf
*ibuf
,
2764 struct got_object_id
*tree_id
, const char *path
,
2765 struct got_parsed_tree_entry
*entries
, int nentries
)
2767 const struct got_error
*err
= NULL
;
2769 size_t path_len
= strlen(path
);
2772 msglen
= sizeof(struct got_imsg_enumerated_tree
) + path_len
;
2773 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_TREE
, 0, 0, msglen
);
2775 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2777 if (imsg_add(wbuf
, tree_id
, sizeof(*tree_id
)) == -1)
2778 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2779 if (imsg_add(wbuf
, &nentries
, sizeof(nentries
)) == -1)
2780 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2781 if (imsg_add(wbuf
, path
, path_len
) == -1)
2782 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
));
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
, sizeof(*id
)) == -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");
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
, &icommit
->id
, sizeof(commit_id
));
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
, &itree
->id
, sizeof(tree_id
));
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");
3174 imsg_close(ibuf
, wbuf
);
3176 return flush_imsg(ibuf
);
3179 const struct got_error
*
3180 got_privsep_send_object_idlist(struct imsgbuf
*ibuf
,
3181 struct got_object_id
**ids
, size_t nids
)
3183 const struct got_error
*err
= NULL
;
3184 struct got_object_id
*idlist
[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
];
3187 for (i
= 0; i
< nids
; i
++) {
3188 idlist
[i
% nitems(idlist
)] = ids
[i
];
3190 if (queued
>= nitems(idlist
)) {
3191 err
= send_idlist(ibuf
, idlist
, queued
);
3199 err
= send_idlist(ibuf
, idlist
, queued
);
3207 const struct got_error
*
3208 got_privsep_send_object_idlist_done(struct imsgbuf
*ibuf
)
3210 if (imsg_compose(ibuf
, GOT_IMSG_OBJ_ID_LIST_DONE
, 0, 0, -1, NULL
, 0)
3212 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3214 return flush_imsg(ibuf
);
3217 const struct got_error
*
3218 got_privsep_recv_object_idlist(int *done
, struct got_object_id
**ids
,
3219 size_t *nids
, struct imsgbuf
*ibuf
)
3221 const struct got_error
*err
= NULL
;
3223 struct got_imsg_object_idlist
*idlist
;
3230 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3234 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3235 switch (imsg
.hdr
.type
) {
3236 case GOT_IMSG_OBJ_ID_LIST
:
3237 if (datalen
< sizeof(*idlist
)) {
3238 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3242 if (idlist
->nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3243 idlist
->nids
* sizeof(**ids
) > datalen
- sizeof(*idlist
)) {
3244 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3247 *nids
= idlist
->nids
;
3248 *ids
= calloc(*nids
, sizeof(**ids
));
3250 err
= got_error_from_errno("calloc");
3253 memcpy(*ids
, (uint8_t *)imsg
.data
+ sizeof(*idlist
),
3254 *nids
* sizeof(**ids
));
3256 case GOT_IMSG_OBJ_ID_LIST_DONE
:
3260 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3269 const struct got_error
*
3270 got_privsep_send_delta_reuse_req(struct imsgbuf
*ibuf
)
3272 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_REQUEST
, 0, 0, -1, NULL
, 0)
3274 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3276 return flush_imsg(ibuf
);
3279 const struct got_error
*
3280 got_privsep_send_reused_deltas(struct imsgbuf
*ibuf
,
3281 struct got_imsg_reused_delta
*deltas
, size_t ndeltas
)
3283 const struct got_error
*err
= NULL
;
3285 struct got_imsg_reused_deltas ideltas
;
3288 memset(&ideltas
, 0, sizeof(ideltas
));
3290 if (ndeltas
> GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS
)
3291 return got_error(GOT_ERR_NO_SPACE
);
3293 wbuf
= imsg_create(ibuf
, GOT_IMSG_REUSED_DELTAS
, 0, 0,
3294 sizeof(ideltas
) + ndeltas
* sizeof(*deltas
));
3296 err
= got_error_from_errno("imsg_create REUSED_DELTAS");
3300 ideltas
.ndeltas
= ndeltas
;
3301 if (imsg_add(wbuf
, &ideltas
, sizeof(ideltas
)) == -1)
3302 return got_error_from_errno("imsg_add REUSED_DELTAS");
3304 for (i
= 0; i
< ndeltas
; i
++) {
3305 struct got_imsg_reused_delta
*delta
= &deltas
[i
];
3306 if (imsg_add(wbuf
, delta
, sizeof(*delta
)) == -1)
3307 return got_error_from_errno("imsg_add REUSED_DELTAS");
3310 imsg_close(ibuf
, wbuf
);
3312 return flush_imsg(ibuf
);
3315 const struct got_error
*
3316 got_privsep_send_reused_deltas_done(struct imsgbuf
*ibuf
)
3318 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_DONE
, 0, 0, -1, NULL
, 0)
3320 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3322 return flush_imsg(ibuf
);
3325 const struct got_error
*
3326 got_privsep_recv_reused_deltas(int *done
, struct got_imsg_reused_delta
*deltas
,
3327 size_t *ndeltas
, struct imsgbuf
*ibuf
)
3329 const struct got_error
*err
= NULL
;
3331 struct got_imsg_reused_deltas
*ideltas
;
3337 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3341 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3342 switch (imsg
.hdr
.type
) {
3343 case GOT_IMSG_REUSED_DELTAS
:
3344 if (datalen
< sizeof(*ideltas
)) {
3345 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3348 ideltas
= imsg
.data
;
3349 if (ideltas
->ndeltas
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3350 ideltas
->ndeltas
* sizeof(*deltas
) >
3351 datalen
- sizeof(*ideltas
)) {
3352 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3355 *ndeltas
= ideltas
->ndeltas
;
3356 memcpy(deltas
, (uint8_t *)imsg
.data
+ sizeof(*ideltas
),
3357 *ndeltas
* sizeof(*deltas
));
3359 case GOT_IMSG_DELTA_REUSE_DONE
:
3363 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3372 const struct got_error
*
3373 got_privsep_init_commit_painting(struct imsgbuf
*ibuf
)
3375 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_INIT
,
3378 return got_error_from_errno("imsg_compose "
3379 "COMMIT_PAINTING_INIT");
3381 return flush_imsg(ibuf
);
3384 const struct got_error
*
3385 got_privsep_send_painting_request(struct imsgbuf
*ibuf
, int idx
,
3386 struct got_object_id
*id
, intptr_t color
)
3388 struct got_imsg_commit_painting_request ireq
;
3390 memset(&ireq
, 0, sizeof(ireq
));
3391 memcpy(&ireq
.id
, id
, sizeof(ireq
.id
));
3395 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_REQUEST
, 0, 0, -1,
3396 &ireq
, sizeof(ireq
)) == -1)
3397 return got_error_from_errno("imsg_compose "
3398 "COMMIT_PAINTING_REQUEST");
3400 return flush_imsg(ibuf
);
3403 static const struct got_error
*
3404 send_painted_commits(struct got_object_id_queue
*ids
, int *nids
,
3405 size_t remain
, int present_in_pack
, struct imsgbuf
*ibuf
)
3407 const struct got_error
*err
= NULL
;
3408 struct ibuf
*wbuf
= NULL
;
3409 struct got_object_qid
*qid
;
3414 msglen
= MIN(remain
, MAX_IMSGSIZE
- IMSG_HEADER_SIZE
);
3415 ncommits
= (msglen
- sizeof(struct got_imsg_painted_commits
)) /
3416 sizeof(struct got_imsg_painted_commit
);
3418 wbuf
= imsg_create(ibuf
, GOT_IMSG_PAINTED_COMMITS
, 0, 0, msglen
);
3420 err
= got_error_from_errno("imsg_create PAINTED_COMMITS");
3424 /* Keep in sync with struct got_imsg_painted_commits! */
3425 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1)
3426 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3427 if (imsg_add(wbuf
, &present_in_pack
, sizeof(present_in_pack
)) == -1)
3428 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3430 while (ncommits
> 0) {
3431 qid
= STAILQ_FIRST(ids
);
3432 STAILQ_REMOVE_HEAD(ids
, entry
);
3435 color
= (intptr_t)qid
->data
;
3437 /* Keep in sync with struct got_imsg_painted_commit! */
3438 if (imsg_add(wbuf
, &qid
->id
, sizeof(qid
->id
)) == -1)
3439 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3440 if (imsg_add(wbuf
, &color
, sizeof(color
)) == -1)
3441 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3443 got_object_qid_free(qid
);
3446 imsg_close(ibuf
, wbuf
);
3447 return flush_imsg(ibuf
);
3450 const struct got_error
*
3451 got_privsep_send_painted_commits(struct imsgbuf
*ibuf
,
3452 struct got_object_id_queue
*ids
, int *nids
,
3453 int present_in_pack
, int flush
)
3455 const struct got_error
*err
;
3462 remain
= (sizeof(struct got_imsg_painted_commits
)) +
3463 *nids
* sizeof(struct got_imsg_painted_commit
);
3464 if (flush
|| remain
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
3465 err
= send_painted_commits(ids
, nids
, remain
,
3466 present_in_pack
, ibuf
);
3470 } while (flush
&& *nids
> 0);
3475 const struct got_error
*
3476 got_privsep_send_painting_commits_done(struct imsgbuf
*ibuf
)
3478 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_DONE
,
3481 return got_error_from_errno("imsg_compose "
3482 "COMMIT_PAINTING_DONE");
3484 return flush_imsg(ibuf
);
3487 const struct got_error
*
3488 got_privsep_recv_painted_commits(struct got_object_id_queue
*new_ids
,
3489 got_privsep_recv_painted_commit_cb cb
, void *cb_arg
, struct imsgbuf
*ibuf
)
3491 const struct got_error
*err
= NULL
;
3493 struct got_imsg_painted_commits icommits
;
3494 struct got_imsg_painted_commit icommit
;
3499 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3503 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3504 if (imsg
.hdr
.type
== GOT_IMSG_COMMIT_PAINTING_DONE
) {
3508 if (imsg
.hdr
.type
!= GOT_IMSG_PAINTED_COMMITS
){
3510 return got_error(GOT_ERR_PRIVSEP_MSG
);
3513 if (datalen
< sizeof(icommits
)){
3515 return got_error(GOT_ERR_PRIVSEP_LEN
);
3517 memcpy(&icommits
, imsg
.data
, sizeof(icommits
));
3518 if (icommits
.ncommits
* sizeof(icommit
) < icommits
.ncommits
||
3519 datalen
< sizeof(icommits
) +
3520 icommits
.ncommits
* sizeof(icommit
)){
3522 return got_error(GOT_ERR_PRIVSEP_LEN
);
3525 for (i
= 0; i
< icommits
.ncommits
; i
++) {
3527 (uint8_t *)imsg
.data
+ sizeof(icommits
) + i
* sizeof(icommit
),
3530 if (icommits
.present_in_pack
) {
3531 struct got_object_id id
;
3532 memcpy(&id
, &icommit
.id
, sizeof(id
));
3533 err
= cb(cb_arg
, &id
, icommit
.color
);
3537 struct got_object_qid
*qid
;
3538 err
= got_object_qid_alloc_partial(&qid
);
3541 memcpy(&qid
->id
, &icommit
.id
,
3543 qid
->data
= (void *)icommit
.color
;
3544 STAILQ_INSERT_TAIL(new_ids
, qid
, entry
);
3554 const struct got_error
*
3555 got_privsep_unveil_exec_helpers(void)
3557 const char *helpers
[] = {
3558 GOT_PATH_PROG_READ_PACK
,
3559 GOT_PATH_PROG_READ_OBJECT
,
3560 GOT_PATH_PROG_READ_COMMIT
,
3561 GOT_PATH_PROG_READ_TREE
,
3562 GOT_PATH_PROG_READ_BLOB
,
3563 GOT_PATH_PROG_READ_TAG
,
3564 GOT_PATH_PROG_READ_GITCONFIG
,
3565 GOT_PATH_PROG_READ_GOTCONFIG
,
3566 GOT_PATH_PROG_READ_PATCH
,
3567 GOT_PATH_PROG_FETCH_PACK
,
3568 GOT_PATH_PROG_INDEX_PACK
,
3569 GOT_PATH_PROG_SEND_PACK
,
3570 /* GOT_PATH_PROG_FETCH_HTTP explicitly excluded */
3574 for (i
= 0; i
< nitems(helpers
); i
++) {
3575 if (unveil(helpers
[i
], "x") == 0)
3577 return got_error_from_errno2("unveil", helpers
[i
]);
3584 got_privsep_exec_child(int imsg_fds
[2], const char *path
, const char *repo_path
)
3586 if (close(imsg_fds
[0]) == -1) {
3587 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3591 if (dup2(imsg_fds
[1], GOT_IMSG_FD_CHILD
) == -1) {
3592 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3596 closefrom(GOT_IMSG_FD_CHILD
+ 1);
3598 if (execl(path
, path
, repo_path
, (char *)NULL
) == -1) {
3599 fprintf(stderr
, "%s: %s: %s\n", getprogname(), path
,