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>
35 #include "got_compat.h"
37 #include "got_object.h"
38 #include "got_error.h"
40 #include "got_repository.h"
42 #include "got_lib_sha1.h"
43 #include "got_lib_delta.h"
44 #include "got_lib_inflate.h"
45 #include "got_lib_object.h"
46 #include "got_lib_object_parse.h"
47 #include "got_lib_privsep.h"
48 #include "got_lib_pack.h"
49 #include "got_lib_poll.h"
51 #include "got_privsep.h"
54 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
58 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
61 static const struct got_error
*
62 read_imsg(struct imsgbuf
*ibuf
)
64 const struct got_error
*err
;
67 err
= got_poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
69 if (err
->code
== GOT_ERR_EOF
)
70 return got_error(GOT_ERR_PRIVSEP_PIPE
);
76 if (errno
== EAGAIN
) /* Could be a file-descriptor leak. */
77 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
78 return got_error(GOT_ERR_PRIVSEP_READ
);
81 return got_error(GOT_ERR_PRIVSEP_PIPE
);
86 const struct got_error
*
87 got_privsep_wait_for_child(pid_t pid
)
91 if (waitpid(pid
, &child_status
, 0) == -1)
92 return got_error_from_errno("waitpid");
94 if (!WIFEXITED(child_status
))
95 return got_error(GOT_ERR_PRIVSEP_DIED
);
97 if (WEXITSTATUS(child_status
) != 0)
98 return got_error(GOT_ERR_PRIVSEP_EXIT
);
103 static const struct got_error
*
104 recv_imsg_error(struct imsg
*imsg
, size_t datalen
)
106 struct got_imsg_error
*ierr
;
108 if (datalen
!= sizeof(*ierr
))
109 return got_error(GOT_ERR_PRIVSEP_LEN
);
112 if (ierr
->code
== GOT_ERR_ERRNO
) {
113 static struct got_error serr
;
114 serr
.code
= GOT_ERR_ERRNO
;
115 serr
.msg
= strerror(ierr
->errno_code
);
119 return got_error(ierr
->code
);
122 const struct got_error
*
123 got_privsep_recv_imsg(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
126 const struct got_error
*err
;
129 n
= imsg_get(ibuf
, imsg
);
131 return got_error_from_errno("imsg_get");
134 err
= read_imsg(ibuf
);
137 n
= imsg_get(ibuf
, imsg
);
139 return got_error_from_errno("imsg_get");
142 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
143 return got_error(GOT_ERR_PRIVSEP_LEN
);
145 if (imsg
->hdr
.type
== GOT_IMSG_ERROR
) {
146 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
147 return recv_imsg_error(imsg
, datalen
);
153 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
155 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
157 const struct got_error
*poll_err
;
158 struct got_imsg_error ierr
;
161 ierr
.code
= err
->code
;
162 if (err
->code
== GOT_ERR_ERRNO
)
163 ierr
.errno_code
= errno
;
166 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
168 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
169 getprogname(), err
->code
, err
->msg
, strerror(errno
));
173 poll_err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
175 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
176 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
180 ret
= imsg_flush(ibuf
);
182 fprintf(stderr
, "%s: error %d \"%s\": imsg_flush: %s\n",
183 getprogname(), err
->code
, err
->msg
, strerror(errno
));
189 static const struct got_error
*
190 flush_imsg(struct imsgbuf
*ibuf
)
192 const struct got_error
*err
;
194 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
198 if (imsg_flush(ibuf
) == -1) {
200 return got_error_from_errno("imsg_flush");
206 const struct got_error
*
207 got_privsep_flush_imsg(struct imsgbuf
*ibuf
)
209 return flush_imsg(ibuf
);
212 const struct got_error
*
213 got_privsep_send_stop(int fd
)
215 const struct got_error
*err
= NULL
;
218 imsg_init(&ibuf
, fd
);
220 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1)
221 return got_error_from_errno("imsg_compose STOP");
223 err
= flush_imsg(&ibuf
);
227 const struct got_error
*
228 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
229 struct got_object_id
*id
)
231 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
232 id
, sizeof(*id
)) == -1)
233 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
235 return flush_imsg(ibuf
);
238 const struct got_error
*
239 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
240 struct got_object_id
*id
)
242 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
243 id
, sizeof(*id
)) == -1)
244 return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
246 return flush_imsg(ibuf
);
249 const struct got_error
*
250 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
252 const struct got_error
*err
= NULL
;
254 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
256 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
261 return flush_imsg(ibuf
);
264 const struct got_error
*
265 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
268 const struct got_error
*err
= NULL
;
269 struct got_imsg_raw_obj iobj
;
270 size_t len
= sizeof(iobj
);
273 memset(&iobj
, 0, sizeof(iobj
));
274 iobj
.hdrlen
= hdrlen
;
277 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
278 len
+= (size_t)size
+ hdrlen
;
280 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
282 err
= got_error_from_errno("imsg_create RAW_OBJECT");
286 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1)
287 return got_error_from_errno("imsg_add RAW_OBJECT");
289 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
290 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1)
291 return got_error_from_errno("imsg_add RAW_OBJECT");
295 imsg_close(ibuf
, wbuf
);
297 return flush_imsg(ibuf
);
300 const struct got_error
*
301 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
302 struct imsgbuf
*ibuf
)
304 const struct got_error
*err
= NULL
;
306 struct got_imsg_raw_obj
*iobj
;
311 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
315 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
317 switch (imsg
.hdr
.type
) {
318 case GOT_IMSG_RAW_OBJECT
:
319 if (datalen
< sizeof(*iobj
)) {
320 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
325 *hdrlen
= iobj
->hdrlen
;
327 if (datalen
== sizeof(*iobj
)) {
328 /* Data has been written to file descriptor. */
333 *size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
334 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
338 *outbuf
= malloc(*size
+ *hdrlen
);
339 if (*outbuf
== NULL
) {
340 err
= got_error_from_errno("malloc");
343 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
346 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
355 const struct got_error
*
356 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
357 struct got_object_id
*id
, int pack_idx
)
359 const struct got_error
*err
= NULL
;
360 struct got_imsg_packed_object iobj
;
364 memset(&iobj
, 0, sizeof(iobj
));
365 if (pack_idx
!= -1) { /* commit is packed */
367 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
375 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
377 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
382 return flush_imsg(ibuf
);
385 const struct got_error
*
386 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
387 struct got_object_id
*id
, int pack_idx
)
393 len
= sizeof(struct got_imsg_packed_object
);
397 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
399 return got_error_from_errno("imsg_create TREE_REQUEST");
401 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1)
402 return got_error_from_errno("imsg_add TREE_REQUEST");
404 if (pack_idx
!= -1) { /* tree is packed */
405 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1)
406 return got_error_from_errno("imsg_add TREE_REQUEST");
410 imsg_close(ibuf
, wbuf
);
412 return flush_imsg(ibuf
);
415 const struct got_error
*
416 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
417 struct got_object_id
*id
, int pack_idx
)
419 struct got_imsg_packed_object iobj
;
423 memset(&iobj
, 0, sizeof(iobj
));
424 if (pack_idx
!= -1) { /* tag is packed */
426 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
434 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
436 return got_error_from_errno("imsg_compose TAG_REQUEST");
438 return flush_imsg(ibuf
);
441 const struct got_error
*
442 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
443 struct got_object_id
*id
, int pack_idx
)
445 const struct got_error
*err
= NULL
;
446 struct got_imsg_packed_object iobj
;
450 memset(&iobj
, 0, sizeof(iobj
));
451 if (pack_idx
!= -1) { /* blob is packed */
453 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
461 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
463 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
468 return flush_imsg(ibuf
);
471 const struct got_error
*
472 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
474 const struct got_error
*err
= NULL
;
476 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
478 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
483 return flush_imsg(ibuf
);
486 static const struct got_error
*
487 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
489 const struct got_error
*err
= NULL
;
491 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
492 err
= got_error_from_errno("imsg_compose TMPFD");
497 return flush_imsg(ibuf
);
500 const struct got_error
*
501 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
503 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
506 const struct got_error
*
507 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
509 struct got_imsg_object iobj
;
511 memset(&iobj
, 0, sizeof(iobj
));
513 memcpy(iobj
.id
, obj
->id
.sha1
, sizeof(iobj
.id
));
514 iobj
.type
= obj
->type
;
515 iobj
.flags
= obj
->flags
;
516 iobj
.hdrlen
= obj
->hdrlen
;
517 iobj
.size
= obj
->size
;
518 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
519 iobj
.pack_offset
= obj
->pack_offset
;
520 iobj
.pack_idx
= obj
->pack_idx
;
523 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
525 return got_error_from_errno("imsg_compose OBJECT");
527 return flush_imsg(ibuf
);
530 const struct got_error
*
531 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
532 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
533 struct got_pathlist_head
*wanted_branches
,
534 struct got_pathlist_head
*wanted_refs
, int list_refs_only
, int verbosity
)
536 const struct got_error
*err
= NULL
;
539 struct got_pathlist_entry
*pe
;
540 struct got_imsg_fetch_request fetchreq
;
542 memset(&fetchreq
, 0, sizeof(fetchreq
));
543 fetchreq
.fetch_all_branches
= fetch_all_branches
;
544 fetchreq
.list_refs_only
= list_refs_only
;
545 fetchreq
.verbosity
= verbosity
;
546 TAILQ_FOREACH(pe
, have_refs
, entry
)
547 fetchreq
.n_have_refs
++;
548 TAILQ_FOREACH(pe
, wanted_branches
, entry
)
549 fetchreq
.n_wanted_branches
++;
550 TAILQ_FOREACH(pe
, wanted_refs
, entry
)
551 fetchreq
.n_wanted_refs
++;
552 len
= sizeof(struct got_imsg_fetch_request
);
553 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
555 return got_error(GOT_ERR_NO_SPACE
);
558 if (imsg_compose(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, fd
,
559 &fetchreq
, sizeof(fetchreq
)) == -1)
560 return got_error_from_errno(
561 "imsg_compose FETCH_SERVER_PROGRESS");
563 err
= flush_imsg(ibuf
);
570 TAILQ_FOREACH(pe
, have_refs
, entry
) {
571 const char *name
= pe
->path
;
572 size_t name_len
= pe
->path_len
;
573 struct got_object_id
*id
= pe
->data
;
575 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
576 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
578 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
580 /* Keep in sync with struct got_imsg_fetch_have_ref! */
581 if (imsg_add(wbuf
, id
->sha1
, sizeof(id
->sha1
)) == -1)
582 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
583 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
584 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
585 if (imsg_add(wbuf
, name
, name_len
) == -1)
586 return got_error_from_errno("imsg_add FETCH_HAVE_REF");
589 imsg_close(ibuf
, wbuf
);
590 err
= flush_imsg(ibuf
);
595 TAILQ_FOREACH(pe
, wanted_branches
, entry
) {
596 const char *name
= pe
->path
;
597 size_t name_len
= pe
->path_len
;
599 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
600 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
603 return got_error_from_errno(
604 "imsg_create FETCH_WANTED_BRANCH");
606 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
607 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
608 return got_error_from_errno(
609 "imsg_add FETCH_WANTED_BRANCH");
610 if (imsg_add(wbuf
, name
, name_len
) == -1)
611 return got_error_from_errno(
612 "imsg_add FETCH_WANTED_BRANCH");
615 imsg_close(ibuf
, wbuf
);
616 err
= flush_imsg(ibuf
);
621 TAILQ_FOREACH(pe
, wanted_refs
, entry
) {
622 const char *name
= pe
->path
;
623 size_t name_len
= pe
->path_len
;
625 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
626 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
629 return got_error_from_errno(
630 "imsg_create FETCH_WANTED_REF");
632 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
633 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
634 return got_error_from_errno(
635 "imsg_add FETCH_WANTED_REF");
636 if (imsg_add(wbuf
, name
, name_len
) == -1)
637 return got_error_from_errno(
638 "imsg_add FETCH_WANTED_REF");
641 imsg_close(ibuf
, wbuf
);
642 err
= flush_imsg(ibuf
);
652 const struct got_error
*
653 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
655 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
658 const struct got_error
*
659 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
660 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
661 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
663 const struct got_error
*err
= NULL
;
666 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
674 *server_progress
= NULL
;
676 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
678 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
682 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
683 switch (imsg
.hdr
.type
) {
684 case GOT_IMSG_FETCH_SYMREFS
:
685 if (datalen
< sizeof(*isymrefs
)) {
686 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
689 if (isymrefs
!= NULL
) {
690 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
693 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
694 off
= sizeof(*isymrefs
);
695 remain
= datalen
- off
;
696 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
697 struct got_imsg_fetch_symref
*s
;
699 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
700 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
703 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
705 remain
-= sizeof(*s
);
706 if (remain
< s
->name_len
) {
707 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
710 name
= strndup(imsg
.data
+ off
, s
->name_len
);
712 err
= got_error_from_errno("strndup");
716 remain
-= s
->name_len
;
717 if (remain
< s
->target_len
) {
718 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
722 target
= strndup(imsg
.data
+ off
, s
->target_len
);
723 if (target
== NULL
) {
724 err
= got_error_from_errno("strndup");
728 off
+= s
->target_len
;
729 remain
-= s
->target_len
;
730 err
= got_pathlist_append(symrefs
, name
, target
);
738 case GOT_IMSG_FETCH_REF
:
739 if (datalen
<= SHA1_DIGEST_LENGTH
) {
740 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
743 *id
= malloc(sizeof(**id
));
745 err
= got_error_from_errno("malloc");
748 memcpy((*id
)->sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
749 *refname
= strndup(imsg
.data
+ SHA1_DIGEST_LENGTH
,
750 datalen
- SHA1_DIGEST_LENGTH
);
751 if (*refname
== NULL
) {
752 err
= got_error_from_errno("strndup");
756 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
758 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
761 *server_progress
= strndup(imsg
.data
, datalen
);
762 if (*server_progress
== NULL
) {
763 err
= got_error_from_errno("strndup");
766 for (i
= 0; i
< datalen
; i
++) {
767 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
768 !isspace((unsigned char)(*server_progress
)[i
])) {
769 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
770 free(*server_progress
);
771 *server_progress
= NULL
;
776 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
777 if (datalen
< sizeof(*packfile_size
)) {
778 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
781 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
783 case GOT_IMSG_FETCH_DONE
:
784 if (datalen
!= SHA1_DIGEST_LENGTH
) {
785 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
788 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
792 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
806 static const struct got_error
*
807 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
808 int delete, struct imsgbuf
*ibuf
)
813 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
814 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
816 return got_error_from_errno("imsg_create SEND_REF");
818 /* Keep in sync with struct got_imsg_send_ref! */
819 if (imsg_add(wbuf
, id
->sha1
, sizeof(id
->sha1
)) == -1)
820 return got_error_from_errno("imsg_add SEND_REF");
821 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1)
822 return got_error_from_errno("imsg_add SEND_REF");
823 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
824 return got_error_from_errno("imsg_add SEND_REF");
825 if (imsg_add(wbuf
, name
, name_len
) == -1)
826 return got_error_from_errno("imsg_add SEND_REF");
829 imsg_close(ibuf
, wbuf
);
830 return flush_imsg(ibuf
);
833 const struct got_error
*
834 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
835 struct got_pathlist_head
*have_refs
,
836 struct got_pathlist_head
*delete_refs
,
839 const struct got_error
*err
= NULL
;
840 struct got_pathlist_entry
*pe
;
841 struct got_imsg_send_request sendreq
;
842 struct got_object_id zero_id
;
844 memset(&zero_id
, 0, sizeof(zero_id
));
845 memset(&sendreq
, 0, sizeof(sendreq
));
846 sendreq
.verbosity
= verbosity
;
847 TAILQ_FOREACH(pe
, have_refs
, entry
)
849 TAILQ_FOREACH(pe
, delete_refs
, entry
)
851 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
852 &sendreq
, sizeof(sendreq
)) == -1) {
853 err
= got_error_from_errno(
854 "imsg_compose FETCH_SERVER_PROGRESS");
858 err
= flush_imsg(ibuf
);
863 TAILQ_FOREACH(pe
, have_refs
, entry
) {
864 const char *name
= pe
->path
;
865 size_t name_len
= pe
->path_len
;
866 struct got_object_id
*id
= pe
->data
;
867 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
872 TAILQ_FOREACH(pe
, delete_refs
, entry
) {
873 const char *name
= pe
->path
;
874 size_t name_len
= pe
->path_len
;
875 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
880 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
881 err
= got_error_from_errno("close");
886 const struct got_error
*
887 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
888 struct imsgbuf
*ibuf
)
890 const struct got_error
*err
= NULL
;
894 struct got_imsg_send_remote_ref iremote_ref
;
895 struct got_object_id
*id
= NULL
;
896 char *refname
= NULL
;
897 struct got_pathlist_entry
*new;
900 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
903 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
904 switch (imsg
.hdr
.type
) {
905 case GOT_IMSG_SEND_REMOTE_REF
:
906 if (datalen
< sizeof(iremote_ref
)) {
907 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
910 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
911 if (datalen
!= sizeof(iremote_ref
) +
912 iremote_ref
.name_len
) {
913 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
916 id
= malloc(sizeof(*id
));
918 err
= got_error_from_errno("malloc");
921 memcpy(id
->sha1
, iremote_ref
.id
, SHA1_DIGEST_LENGTH
);
922 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
923 datalen
- sizeof(iremote_ref
));
924 if (refname
== NULL
) {
925 err
= got_error_from_errno("strndup");
928 err
= got_pathlist_insert(&new, remote_refs
,
932 if (new == NULL
) { /* duplicate which wasn't inserted */
939 case GOT_IMSG_SEND_PACK_REQUEST
:
941 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
944 /* got-send-pack is now waiting for a pack file. */
948 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
959 const struct got_error
*
960 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
962 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
965 const struct got_error
*
966 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
967 int *success
, char **refname
, struct imsgbuf
*ibuf
)
969 const struct got_error
*err
= NULL
;
972 struct got_imsg_send_ref_status iref_status
;
974 /* Do not reset the current value of 'bytes_sent', it accumulates. */
979 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
983 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
984 switch (imsg
.hdr
.type
) {
985 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
986 if (datalen
< sizeof(*bytes_sent
)) {
987 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
990 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
992 case GOT_IMSG_SEND_REF_STATUS
:
993 if (datalen
< sizeof(iref_status
)) {
994 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
997 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
998 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
) {
999 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1002 *success
= iref_status
.success
;
1003 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1004 iref_status
.name_len
);
1006 case GOT_IMSG_SEND_DONE
:
1008 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1014 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1022 const struct got_error
*
1023 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, uint8_t *pack_sha1
,
1026 const struct got_error
*err
= NULL
;
1028 /* Keep in sync with struct got_imsg_index_pack_request */
1029 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1030 pack_sha1
, SHA1_DIGEST_LENGTH
) == -1) {
1031 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1035 return flush_imsg(ibuf
);
1038 const struct got_error
*
1039 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1041 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1044 const struct got_error
*
1045 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1046 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1047 struct imsgbuf
*ibuf
)
1049 const struct got_error
*err
= NULL
;
1051 struct got_imsg_index_pack_progress
*iprogress
;
1059 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1063 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1064 switch (imsg
.hdr
.type
) {
1065 case GOT_IMSG_IDXPACK_PROGRESS
:
1066 if (datalen
< sizeof(*iprogress
)) {
1067 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1070 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1071 if (iprogress
->nobj_total
< 0 || iprogress
->nobj_indexed
< 0 ||
1072 iprogress
->nobj_loose
< 0 || iprogress
->nobj_resolved
< 0) {
1073 err
= got_error(GOT_ERR_RANGE
);
1076 *nobj_total
= iprogress
->nobj_total
;
1077 *nobj_indexed
= iprogress
->nobj_indexed
;
1078 *nobj_loose
= iprogress
->nobj_loose
;
1079 *nobj_resolved
= iprogress
->nobj_resolved
;
1081 case GOT_IMSG_IDXPACK_DONE
:
1083 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1089 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1097 const struct got_error
*
1098 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1099 struct imsgbuf
*ibuf
)
1101 struct got_imsg_object
*iobj
;
1102 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1104 if (datalen
!= sizeof(*iobj
))
1105 return got_error(GOT_ERR_PRIVSEP_LEN
);
1108 if (iobj
->pack_offset
< 0)
1109 return got_error(GOT_ERR_PACK_OFFSET
);
1111 *obj
= calloc(1, sizeof(**obj
));
1113 return got_error_from_errno("calloc");
1115 memcpy((*obj
)->id
.sha1
, iobj
->id
, SHA1_DIGEST_LENGTH
);
1116 (*obj
)->type
= iobj
->type
;
1117 (*obj
)->flags
= iobj
->flags
;
1118 (*obj
)->hdrlen
= iobj
->hdrlen
;
1119 (*obj
)->size
= iobj
->size
;
1120 /* path_packfile is handled by caller */
1121 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1122 (*obj
)->pack_offset
= iobj
->pack_offset
;
1123 (*obj
)->pack_idx
= iobj
->pack_idx
;
1125 STAILQ_INIT(&(*obj
)->deltas
.entries
);
1129 const struct got_error
*
1130 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1132 const struct got_error
*err
= NULL
;
1134 const size_t min_datalen
=
1135 MIN(sizeof(struct got_imsg_error
), sizeof(struct got_imsg_object
));
1139 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1143 switch (imsg
.hdr
.type
) {
1144 case GOT_IMSG_OBJECT
:
1145 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1148 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1157 static const struct got_error
*
1158 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1161 const struct got_error
*err
= NULL
;
1162 size_t offset
, remain
;
1165 remain
= logmsg_len
;
1166 while (remain
> 0) {
1167 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1169 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1170 commit
->logmsg
+ offset
, n
) == -1) {
1171 err
= got_error_from_errno("imsg_compose "
1176 err
= flush_imsg(ibuf
);
1187 const struct got_error
*
1188 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1190 const struct got_error
*err
= NULL
;
1191 struct got_imsg_commit_object
*icommit
;
1194 struct got_object_qid
*qid
;
1195 size_t author_len
= strlen(commit
->author
);
1196 size_t committer_len
= strlen(commit
->committer
);
1197 size_t logmsg_len
= strlen(commit
->logmsg
);
1199 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1200 commit
->nparents
* SHA1_DIGEST_LENGTH
;
1202 buf
= malloc(total
);
1204 return got_error_from_errno("malloc");
1206 icommit
= (struct got_imsg_commit_object
*)buf
;
1207 memcpy(icommit
->tree_id
, commit
->tree_id
->sha1
,
1208 sizeof(icommit
->tree_id
));
1209 icommit
->author_len
= author_len
;
1210 icommit
->author_time
= commit
->author_time
;
1211 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1212 icommit
->committer_len
= committer_len
;
1213 icommit
->committer_time
= commit
->committer_time
;
1214 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1215 icommit
->logmsg_len
= logmsg_len
;
1216 icommit
->nparents
= commit
->nparents
;
1218 len
= sizeof(*icommit
);
1219 memcpy(buf
+ len
, commit
->author
, author_len
);
1221 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1222 len
+= committer_len
;
1223 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1224 memcpy(buf
+ len
, &qid
->id
, SHA1_DIGEST_LENGTH
);
1225 len
+= SHA1_DIGEST_LENGTH
;
1228 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1229 err
= got_error_from_errno("imsg_compose COMMIT");
1233 if (logmsg_len
== 0 ||
1234 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1235 err
= flush_imsg(ibuf
);
1239 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1245 static const struct got_error
*
1246 get_commit_from_imsg(struct got_commit_object
**commit
,
1247 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1249 const struct got_error
*err
= NULL
;
1250 struct got_imsg_commit_object
*icommit
;
1254 if (datalen
< sizeof(*icommit
))
1255 return got_error(GOT_ERR_PRIVSEP_LEN
);
1257 icommit
= imsg
->data
;
1258 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1259 icommit
->committer_len
+
1260 icommit
->nparents
* SHA1_DIGEST_LENGTH
)
1261 return got_error(GOT_ERR_PRIVSEP_LEN
);
1263 if (icommit
->nparents
< 0)
1264 return got_error(GOT_ERR_PRIVSEP_LEN
);
1266 len
+= sizeof(*icommit
);
1268 *commit
= got_object_commit_alloc_partial();
1269 if (*commit
== NULL
)
1270 return got_error_from_errno(
1271 "got_object_commit_alloc_partial");
1273 memcpy((*commit
)->tree_id
->sha1
, icommit
->tree_id
,
1274 SHA1_DIGEST_LENGTH
);
1275 (*commit
)->author_time
= icommit
->author_time
;
1276 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1277 (*commit
)->committer_time
= icommit
->committer_time
;
1278 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1280 (*commit
)->author
= strndup(imsg
->data
+ len
, icommit
->author_len
);
1281 if ((*commit
)->author
== NULL
) {
1282 err
= got_error_from_errno("strndup");
1285 len
+= icommit
->author_len
;
1287 (*commit
)->committer
= strndup(imsg
->data
+ len
,
1288 icommit
->committer_len
);
1289 if ((*commit
)->committer
== NULL
) {
1290 err
= got_error_from_errno("strndup");
1293 len
+= icommit
->committer_len
;
1295 if (icommit
->logmsg_len
== 0) {
1296 (*commit
)->logmsg
= strdup("");
1297 if ((*commit
)->logmsg
== NULL
) {
1298 err
= got_error_from_errno("strdup");
1302 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1304 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1305 if ((*commit
)->logmsg
== NULL
) {
1306 err
= got_error_from_errno("malloc");
1309 while (remain
> 0) {
1310 struct imsg imsg_log
;
1311 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1314 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1318 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1319 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1323 memcpy((*commit
)->logmsg
+ offset
,
1325 imsg_free(&imsg_log
);
1329 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1332 for (i
= 0; i
< icommit
->nparents
; i
++) {
1333 struct got_object_qid
*qid
;
1335 err
= got_object_qid_alloc_partial(&qid
);
1338 memcpy(&qid
->id
, imsg
->data
+ len
+
1339 i
* SHA1_DIGEST_LENGTH
, sizeof(qid
->id
));
1340 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1341 (*commit
)->nparents
++;
1345 got_object_commit_close(*commit
);
1351 const struct got_error
*
1352 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1354 const struct got_error
*err
= NULL
;
1357 const size_t min_datalen
=
1358 MIN(sizeof(struct got_imsg_error
),
1359 sizeof(struct got_imsg_commit_object
));
1363 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1367 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1369 switch (imsg
.hdr
.type
) {
1370 case GOT_IMSG_COMMIT
:
1371 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1374 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1383 static const struct got_error
*
1384 send_tree_entries_batch(struct imsgbuf
*ibuf
,
1385 struct got_parsed_tree_entry
*entries
, int idx0
, int idxN
, size_t len
)
1388 struct got_imsg_tree_entries ientries
;
1391 memset(&ientries
, 0, sizeof(ientries
));
1393 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRIES
, 0, 0, len
);
1395 return got_error_from_errno("imsg_create TREE_ENTRY");
1397 ientries
.nentries
= idxN
- idx0
+ 1;
1398 if (imsg_add(wbuf
, &ientries
, sizeof(ientries
)) == -1)
1399 return got_error_from_errno("imsg_add TREE_ENTRY");
1401 for (i
= idx0
; i
<= idxN
; i
++) {
1402 struct got_parsed_tree_entry
*pte
= &entries
[i
];
1404 /* Keep in sync with struct got_imsg_tree_object definition! */
1405 if (imsg_add(wbuf
, pte
->id
, SHA1_DIGEST_LENGTH
) == -1)
1406 return got_error_from_errno("imsg_add TREE_ENTRY");
1407 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1)
1408 return got_error_from_errno("imsg_add TREE_ENTRY");
1409 if (imsg_add(wbuf
, &pte
->namelen
, sizeof(pte
->namelen
)) == -1)
1410 return got_error_from_errno("imsg_add TREE_ENTRY");
1412 /* Remaining bytes are the entry's name. */
1413 if (imsg_add(wbuf
, pte
->name
, pte
->namelen
) == -1)
1414 return got_error_from_errno("imsg_add TREE_ENTRY");
1418 imsg_close(ibuf
, wbuf
);
1422 static const struct got_error
*
1423 send_tree_entries(struct imsgbuf
*ibuf
, struct got_parsed_tree_entry
*entries
,
1426 const struct got_error
*err
= NULL
;
1428 size_t entries_len
= sizeof(struct got_imsg_tree_entries
);
1431 for (j
= 0; j
< nentries
; j
++) {
1432 struct got_parsed_tree_entry
*pte
= &entries
[j
];
1433 size_t len
= SHA1_DIGEST_LENGTH
+ sizeof(pte
->mode
) +
1434 sizeof(pte
->namelen
) + pte
->namelen
;
1437 entries_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1438 err
= send_tree_entries_batch(ibuf
, entries
,
1439 i
, j
- 1, entries_len
);
1443 entries_len
= sizeof(struct got_imsg_tree_entries
);
1450 err
= send_tree_entries_batch(ibuf
, entries
, i
, j
- 1,
1459 const struct got_error
*
1460 got_privsep_send_tree(struct imsgbuf
*ibuf
,
1461 struct got_parsed_tree_entry
*entries
, int nentries
)
1463 const struct got_error
*err
= NULL
;
1464 struct got_imsg_tree_object itree
;
1466 memset(&itree
, 0, sizeof(itree
));
1467 itree
.nentries
= nentries
;
1468 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1470 return got_error_from_errno("imsg_compose TREE");
1472 err
= send_tree_entries(ibuf
, entries
, nentries
);
1476 return flush_imsg(ibuf
);
1480 static const struct got_error
*
1481 recv_tree_entries(void *data
, size_t datalen
, struct got_tree_object
*tree
,
1484 const struct got_error
*err
= NULL
;
1485 struct got_imsg_tree_entries
*ientries
;
1486 struct got_tree_entry
*te
;
1490 if (datalen
<= sizeof(*ientries
) ||
1491 datalen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
1492 return got_error(GOT_ERR_PRIVSEP_LEN
);
1494 ientries
= (struct got_imsg_tree_entries
*)data
;
1495 if (ientries
->nentries
> INT_MAX
) {
1496 return got_error_msg(GOT_ERR_NO_SPACE
,
1497 "too many tree entries");
1500 te_offset
= sizeof(*ientries
);
1501 for (i
= 0; i
< ientries
->nentries
; i
++) {
1502 struct got_imsg_tree_entry ite
;
1503 const char *te_name
;
1504 uint8_t *buf
= (uint8_t *)data
+ te_offset
;
1506 if (te_offset
>= datalen
) {
1507 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1511 /* Might not be aligned, size is ~32 bytes. */
1512 memcpy(&ite
, buf
, sizeof(ite
));
1514 if (ite
.namelen
>= sizeof(te
->name
)) {
1515 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1518 if (te_offset
+ sizeof(ite
) + ite
.namelen
> datalen
) {
1519 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1523 if (*nentries
>= tree
->nentries
) {
1524 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1527 te
= &tree
->entries
[*nentries
];
1528 te_name
= buf
+ sizeof(ite
);
1529 memcpy(te
->name
, te_name
, ite
.namelen
);
1530 te
->name
[ite
.namelen
] = '\0';
1531 memcpy(te
->id
.sha1
, ite
.id
, SHA1_DIGEST_LENGTH
);
1532 te
->mode
= ite
.mode
;
1533 te
->idx
= *nentries
;
1536 te_offset
+= sizeof(ite
) + ite
.namelen
;
1542 const struct got_error
*
1543 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1545 const struct got_error
*err
= NULL
;
1546 const size_t min_datalen
=
1547 MIN(sizeof(struct got_imsg_error
),
1548 sizeof(struct got_imsg_tree_object
));
1549 struct got_imsg_tree_object
*itree
;
1554 while (*tree
== NULL
|| nentries
< (*tree
)->nentries
) {
1558 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1562 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1564 switch (imsg
.hdr
.type
) {
1566 /* This message should only appear once. */
1567 if (*tree
!= NULL
) {
1568 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1571 if (datalen
!= sizeof(*itree
)) {
1572 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1576 if (itree
->nentries
< 0) {
1577 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1580 *tree
= malloc(sizeof(**tree
));
1581 if (*tree
== NULL
) {
1582 err
= got_error_from_errno("malloc");
1585 (*tree
)->entries
= calloc(itree
->nentries
,
1586 sizeof(struct got_tree_entry
));
1587 if ((*tree
)->entries
== NULL
) {
1588 err
= got_error_from_errno("malloc");
1593 (*tree
)->nentries
= itree
->nentries
;
1594 (*tree
)->refcnt
= 0;
1596 case GOT_IMSG_TREE_ENTRIES
:
1597 /* This message should be preceeded by GOT_IMSG_TREE. */
1598 if (*tree
== NULL
) {
1599 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1602 err
= recv_tree_entries(imsg
.data
, datalen
,
1606 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1615 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1617 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1618 got_object_tree_close(*tree
);
1625 const struct got_error
*
1626 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1627 const uint8_t *data
)
1629 struct got_imsg_blob iblob
;
1631 memset(&iblob
, 0, sizeof(iblob
));
1633 iblob
.hdrlen
= hdrlen
;
1638 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1639 return got_error(GOT_ERR_NO_SPACE
);
1641 buf
= malloc(sizeof(iblob
) + size
);
1643 return got_error_from_errno("malloc");
1645 memcpy(buf
, &iblob
, sizeof(iblob
));
1646 memcpy(buf
+ sizeof(iblob
), data
, size
);
1647 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1648 sizeof(iblob
) + size
) == -1) {
1650 return got_error_from_errno("imsg_compose BLOB");
1654 /* Data has already been written to file descriptor. */
1655 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1656 sizeof(iblob
)) == -1)
1657 return got_error_from_errno("imsg_compose BLOB");
1661 return flush_imsg(ibuf
);
1664 const struct got_error
*
1665 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1666 struct imsgbuf
*ibuf
)
1668 const struct got_error
*err
= NULL
;
1670 struct got_imsg_blob
*iblob
;
1675 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1679 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1681 switch (imsg
.hdr
.type
) {
1683 if (datalen
< sizeof(*iblob
)) {
1684 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1688 *size
= iblob
->size
;
1689 *hdrlen
= iblob
->hdrlen
;
1691 if (datalen
== sizeof(*iblob
)) {
1692 /* Data has been written to file descriptor. */
1696 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
||
1697 *size
> datalen
+ sizeof(*iblob
)) {
1698 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1702 *outbuf
= malloc(*size
);
1703 if (*outbuf
== NULL
) {
1704 err
= got_error_from_errno("malloc");
1707 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1710 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1719 static const struct got_error
*
1720 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1722 const struct got_error
*err
= NULL
;
1723 size_t offset
, remain
;
1726 remain
= tagmsg_len
;
1727 while (remain
> 0) {
1728 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1730 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1731 tag
->tagmsg
+ offset
, n
) == -1) {
1732 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1736 err
= flush_imsg(ibuf
);
1747 const struct got_error
*
1748 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1750 const struct got_error
*err
= NULL
;
1751 struct got_imsg_tag_object
*itag
;
1754 size_t tag_len
= strlen(tag
->tag
);
1755 size_t tagger_len
= strlen(tag
->tagger
);
1756 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1758 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1760 buf
= malloc(total
);
1762 return got_error_from_errno("malloc");
1764 itag
= (struct got_imsg_tag_object
*)buf
;
1765 memcpy(itag
->id
, tag
->id
.sha1
, sizeof(itag
->id
));
1766 itag
->obj_type
= tag
->obj_type
;
1767 itag
->tag_len
= tag_len
;
1768 itag
->tagger_len
= tagger_len
;
1769 itag
->tagger_time
= tag
->tagger_time
;
1770 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1771 itag
->tagmsg_len
= tagmsg_len
;
1773 len
= sizeof(*itag
);
1774 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1776 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1779 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1780 err
= got_error_from_errno("imsg_compose TAG");
1784 if (tagmsg_len
== 0 ||
1785 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1786 err
= flush_imsg(ibuf
);
1790 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1796 const struct got_error
*
1797 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1799 const struct got_error
*err
= NULL
;
1801 struct got_imsg_tag_object
*itag
;
1802 size_t len
, datalen
;
1803 const size_t min_datalen
=
1804 MIN(sizeof(struct got_imsg_error
),
1805 sizeof(struct got_imsg_tag_object
));
1809 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1813 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1816 switch (imsg
.hdr
.type
) {
1818 if (datalen
< sizeof(*itag
)) {
1819 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1823 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1825 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1828 len
+= sizeof(*itag
);
1830 *tag
= calloc(1, sizeof(**tag
));
1832 err
= got_error_from_errno("calloc");
1836 memcpy((*tag
)->id
.sha1
, itag
->id
, SHA1_DIGEST_LENGTH
);
1838 (*tag
)->tag
= strndup(imsg
.data
+ len
, itag
->tag_len
);
1839 if ((*tag
)->tag
== NULL
) {
1840 err
= got_error_from_errno("strndup");
1843 len
+= itag
->tag_len
;
1845 (*tag
)->obj_type
= itag
->obj_type
;
1846 (*tag
)->tagger_time
= itag
->tagger_time
;
1847 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1849 (*tag
)->tagger
= strndup(imsg
.data
+ len
, itag
->tagger_len
);
1850 if ((*tag
)->tagger
== NULL
) {
1851 err
= got_error_from_errno("strndup");
1854 len
+= itag
->tagger_len
;
1856 if (itag
->tagmsg_len
== 0) {
1857 (*tag
)->tagmsg
= strdup("");
1858 if ((*tag
)->tagmsg
== NULL
) {
1859 err
= got_error_from_errno("strdup");
1863 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1865 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1866 if ((*tag
)->tagmsg
== NULL
) {
1867 err
= got_error_from_errno("malloc");
1870 while (remain
> 0) {
1871 struct imsg imsg_log
;
1872 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1875 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1879 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1880 return got_error(GOT_ERR_PRIVSEP_MSG
);
1882 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1884 imsg_free(&imsg_log
);
1888 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1893 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1902 const struct got_error
*
1903 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1904 struct got_packidx
*packidx
)
1906 const struct got_error
*err
= NULL
;
1907 struct got_imsg_packidx ipackidx
;
1908 struct got_imsg_pack ipack
;
1911 memset(&ipackidx
, 0, sizeof(ipackidx
));
1912 memset(&ipack
, 0, sizeof(ipack
));
1914 ipackidx
.len
= packidx
->len
;
1915 ipackidx
.packfile_size
= pack
->filesize
;
1916 fd
= dup(packidx
->fd
);
1918 return got_error_from_errno("dup");
1920 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1921 sizeof(ipackidx
)) == -1) {
1922 err
= got_error_from_errno("imsg_compose PACKIDX");
1927 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1928 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1929 return got_error(GOT_ERR_NO_SPACE
);
1930 ipack
.filesize
= pack
->filesize
;
1934 return got_error_from_errno("dup");
1936 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
1938 err
= got_error_from_errno("imsg_compose PACK");
1943 return flush_imsg(ibuf
);
1946 const struct got_error
*
1947 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
1948 struct got_object_id
*id
)
1950 struct got_imsg_packed_object iobj
;
1952 memset(&iobj
, 0, sizeof(iobj
));
1954 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
1956 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
1957 &iobj
, sizeof(iobj
)) == -1)
1958 return got_error_from_errno("imsg_compose "
1959 "PACKED_OBJECT_REQUEST");
1961 return flush_imsg(ibuf
);
1964 const struct got_error
*
1965 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
1966 struct got_object_id
*id
)
1968 struct got_imsg_packed_object iobj
;
1970 memset(&iobj
, 0, sizeof(iobj
));
1972 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
1974 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
1975 &iobj
, sizeof(iobj
)) == -1)
1976 return got_error_from_errno("imsg_compose "
1977 "PACKED_OBJECT_REQUEST");
1979 return flush_imsg(ibuf
);
1982 const struct got_error
*
1983 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
1985 const struct got_error
*err
= NULL
;
1987 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
1989 err
= got_error_from_errno("imsg_compose "
1990 "GITCONFIG_PARSE_REQUEST");
1995 return flush_imsg(ibuf
);
1998 const struct got_error
*
1999 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2001 if (imsg_compose(ibuf
,
2002 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2004 return got_error_from_errno("imsg_compose "
2005 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2007 return flush_imsg(ibuf
);
2010 const struct got_error
*
2011 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2013 if (imsg_compose(ibuf
,
2014 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2016 return got_error_from_errno("imsg_compose "
2017 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2019 return flush_imsg(ibuf
);
2023 const struct got_error
*
2024 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2026 if (imsg_compose(ibuf
,
2027 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2028 return got_error_from_errno("imsg_compose "
2029 "GITCONFIG_AUTHOR_NAME_REQUEST");
2031 return flush_imsg(ibuf
);
2034 const struct got_error
*
2035 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2037 if (imsg_compose(ibuf
,
2038 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2039 return got_error_from_errno("imsg_compose "
2040 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2042 return flush_imsg(ibuf
);
2045 const struct got_error
*
2046 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2048 if (imsg_compose(ibuf
,
2049 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2050 return got_error_from_errno("imsg_compose "
2051 "GITCONFIG_REMOTE_REQUEST");
2053 return flush_imsg(ibuf
);
2056 const struct got_error
*
2057 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2059 if (imsg_compose(ibuf
,
2060 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2061 return got_error_from_errno("imsg_compose "
2062 "GITCONFIG_OWNER_REQUEST");
2064 return flush_imsg(ibuf
);
2067 const struct got_error
*
2068 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2070 const struct got_error
*err
= NULL
;
2076 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2079 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2081 switch (imsg
.hdr
.type
) {
2082 case GOT_IMSG_GITCONFIG_STR_VAL
:
2085 /* datalen does not include terminating \0 */
2086 *str
= malloc(datalen
+ 1);
2088 err
= got_error_from_errno("malloc");
2091 memcpy(*str
, imsg
.data
, datalen
);
2092 (*str
)[datalen
] = '\0';
2095 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2103 const struct got_error
*
2104 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2106 const struct got_error
*err
= NULL
;
2109 const size_t min_datalen
=
2110 MIN(sizeof(struct got_imsg_error
), sizeof(int));
2114 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2117 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2119 switch (imsg
.hdr
.type
) {
2120 case GOT_IMSG_GITCONFIG_INT_VAL
:
2121 if (datalen
!= sizeof(*val
)) {
2122 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2125 memcpy(val
, imsg
.data
, sizeof(*val
));
2128 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2137 free_remote_data(struct got_remote_repo
*remote
)
2142 free(remote
->fetch_url
);
2143 free(remote
->send_url
);
2144 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2145 free(remote
->fetch_branches
[i
]);
2146 free(remote
->fetch_branches
);
2147 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2148 free(remote
->send_branches
[i
]);
2149 free(remote
->send_branches
);
2150 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2151 free(remote
->fetch_refs
[i
]);
2152 free(remote
->fetch_refs
);
2155 const struct got_error
*
2156 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2157 int *nremotes
, struct imsgbuf
*ibuf
)
2159 const struct got_error
*err
= NULL
;
2162 struct got_imsg_remotes iremotes
;
2163 struct got_imsg_remote iremote
;
2167 iremotes
.nremotes
= 0;
2169 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2172 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2174 switch (imsg
.hdr
.type
) {
2175 case GOT_IMSG_GITCONFIG_REMOTES
:
2176 if (datalen
!= sizeof(iremotes
)) {
2177 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2180 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2181 if (iremotes
.nremotes
== 0) {
2188 return got_error(GOT_ERR_PRIVSEP_MSG
);
2193 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2194 if (*remotes
== NULL
)
2195 return got_error_from_errno("recallocarray");
2197 while (*nremotes
< iremotes
.nremotes
) {
2198 struct got_remote_repo
*remote
;
2200 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2203 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2205 switch (imsg
.hdr
.type
) {
2206 case GOT_IMSG_GITCONFIG_REMOTE
:
2207 remote
= &(*remotes
)[*nremotes
];
2208 memset(remote
, 0, sizeof(*remote
));
2209 if (datalen
< sizeof(iremote
)) {
2210 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2213 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2214 if (iremote
.name_len
== 0 ||
2215 iremote
.fetch_url_len
== 0 ||
2216 iremote
.send_url_len
== 0 ||
2217 (sizeof(iremote
) + iremote
.name_len
+
2218 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2219 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2222 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2224 if (remote
->name
== NULL
) {
2225 err
= got_error_from_errno("strndup");
2228 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2229 iremote
.name_len
, iremote
.fetch_url_len
);
2230 if (remote
->fetch_url
== NULL
) {
2231 err
= got_error_from_errno("strndup");
2232 free_remote_data(remote
);
2235 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2236 iremote
.name_len
+ iremote
.fetch_url_len
,
2237 iremote
.send_url_len
);
2238 if (remote
->send_url
== NULL
) {
2239 err
= got_error_from_errno("strndup");
2240 free_remote_data(remote
);
2243 remote
->mirror_references
= iremote
.mirror_references
;
2244 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2245 remote
->nfetch_branches
= 0;
2246 remote
->fetch_branches
= NULL
;
2247 remote
->nsend_branches
= 0;
2248 remote
->send_branches
= NULL
;
2249 remote
->nfetch_refs
= 0;
2250 remote
->fetch_refs
= NULL
;
2254 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2265 for (i
= 0; i
< *nremotes
; i
++)
2266 free_remote_data(&(*remotes
)[i
]);
2274 const struct got_error
*
2275 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2277 const struct got_error
*err
= NULL
;
2279 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2281 err
= got_error_from_errno("imsg_compose "
2282 "GOTCONFIG_PARSE_REQUEST");
2287 return flush_imsg(ibuf
);
2290 const struct got_error
*
2291 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2293 if (imsg_compose(ibuf
,
2294 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2295 return got_error_from_errno("imsg_compose "
2296 "GOTCONFIG_AUTHOR_REQUEST");
2298 return flush_imsg(ibuf
);
2301 const struct got_error
*
2302 got_privsep_send_gotconfig_allowed_signers_req(struct imsgbuf
*ibuf
)
2304 if (imsg_compose(ibuf
,
2305 GOT_IMSG_GOTCONFIG_ALLOWEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2306 return got_error_from_errno("imsg_compose "
2307 "GOTCONFIG_ALLOWEDSIGNERS_REQUEST");
2309 return flush_imsg(ibuf
);
2312 const struct got_error
*
2313 got_privsep_send_gotconfig_revoked_signers_req(struct imsgbuf
*ibuf
)
2315 if (imsg_compose(ibuf
,
2316 GOT_IMSG_GOTCONFIG_REVOKEDSIGNERS_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2317 return got_error_from_errno("imsg_compose "
2318 "GOTCONFIG_REVOKEDSIGNERS_REQUEST");
2320 return flush_imsg(ibuf
);
2323 const struct got_error
*
2324 got_privsep_send_gotconfig_signer_id_req(struct imsgbuf
*ibuf
)
2326 if (imsg_compose(ibuf
,
2327 GOT_IMSG_GOTCONFIG_SIGNERID_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2328 return got_error_from_errno("imsg_compose "
2329 "GOTCONFIG_SIGNERID_REQUEST");
2331 return flush_imsg(ibuf
);
2334 const struct got_error
*
2335 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2337 if (imsg_compose(ibuf
,
2338 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2339 return got_error_from_errno("imsg_compose "
2340 "GOTCONFIG_REMOTE_REQUEST");
2342 return flush_imsg(ibuf
);
2345 const struct got_error
*
2346 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2348 const struct got_error
*err
= NULL
;
2354 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2357 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2359 switch (imsg
.hdr
.type
) {
2360 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2363 /* datalen does not include terminating \0 */
2364 *str
= malloc(datalen
+ 1);
2366 err
= got_error_from_errno("malloc");
2369 memcpy(*str
, imsg
.data
, datalen
);
2370 (*str
)[datalen
] = '\0';
2373 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2381 const struct got_error
*
2382 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2383 int *nremotes
, struct imsgbuf
*ibuf
)
2385 const struct got_error
*err
= NULL
;
2388 struct got_imsg_remotes iremotes
;
2389 struct got_imsg_remote iremote
;
2390 const size_t min_datalen
=
2391 MIN(sizeof(struct got_imsg_error
), sizeof(iremotes
));
2395 iremotes
.nremotes
= 0;
2397 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2400 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2402 switch (imsg
.hdr
.type
) {
2403 case GOT_IMSG_GOTCONFIG_REMOTES
:
2404 if (datalen
!= sizeof(iremotes
)) {
2405 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2408 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2409 if (iremotes
.nremotes
< 0) {
2410 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2413 if (iremotes
.nremotes
== 0) {
2420 return got_error(GOT_ERR_PRIVSEP_MSG
);
2425 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2426 if (*remotes
== NULL
)
2427 return got_error_from_errno("recallocarray");
2429 while (*nremotes
< iremotes
.nremotes
) {
2430 struct got_remote_repo
*remote
;
2431 const size_t min_datalen
=
2432 MIN(sizeof(struct got_imsg_error
), sizeof(iremote
));
2435 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2438 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2440 switch (imsg
.hdr
.type
) {
2441 case GOT_IMSG_GOTCONFIG_REMOTE
:
2442 remote
= &(*remotes
)[*nremotes
];
2443 memset(remote
, 0, sizeof(*remote
));
2444 if (datalen
< sizeof(iremote
)) {
2445 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2448 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2449 if (iremote
.name_len
== 0 ||
2450 (iremote
.fetch_url_len
== 0 &&
2451 iremote
.send_url_len
== 0) ||
2452 (sizeof(iremote
) + iremote
.name_len
+
2453 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2455 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2458 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2460 if (remote
->name
== NULL
) {
2461 err
= got_error_from_errno("strndup");
2464 remote
->fetch_url
= strndup(imsg
.data
+
2465 sizeof(iremote
) + iremote
.name_len
,
2466 iremote
.fetch_url_len
);
2467 if (remote
->fetch_url
== NULL
) {
2468 err
= got_error_from_errno("strndup");
2469 free_remote_data(remote
);
2472 remote
->send_url
= strndup(imsg
.data
+
2473 sizeof(iremote
) + iremote
.name_len
+
2474 iremote
.fetch_url_len
, iremote
.send_url_len
);
2475 if (remote
->send_url
== NULL
) {
2476 err
= got_error_from_errno("strndup");
2477 free_remote_data(remote
);
2480 remote
->mirror_references
= iremote
.mirror_references
;
2481 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2482 if (iremote
.nfetch_branches
> 0) {
2483 remote
->fetch_branches
= recallocarray(NULL
, 0,
2484 iremote
.nfetch_branches
, sizeof(char *));
2485 if (remote
->fetch_branches
== NULL
) {
2486 err
= got_error_from_errno("calloc");
2487 free_remote_data(remote
);
2491 remote
->nfetch_branches
= 0;
2492 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2494 err
= got_privsep_recv_gotconfig_str(&branch
,
2497 free_remote_data(remote
);
2500 remote
->fetch_branches
[i
] = branch
;
2501 remote
->nfetch_branches
++;
2503 if (iremote
.nsend_branches
> 0) {
2504 remote
->send_branches
= recallocarray(NULL
, 0,
2505 iremote
.nsend_branches
, sizeof(char *));
2506 if (remote
->send_branches
== NULL
) {
2507 err
= got_error_from_errno("calloc");
2508 free_remote_data(remote
);
2512 remote
->nsend_branches
= 0;
2513 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2515 err
= got_privsep_recv_gotconfig_str(&branch
,
2518 free_remote_data(remote
);
2521 remote
->send_branches
[i
] = branch
;
2522 remote
->nsend_branches
++;
2524 if (iremote
.nfetch_refs
> 0) {
2525 remote
->fetch_refs
= recallocarray(NULL
, 0,
2526 iremote
.nfetch_refs
, sizeof(char *));
2527 if (remote
->fetch_refs
== NULL
) {
2528 err
= got_error_from_errno("calloc");
2529 free_remote_data(remote
);
2533 remote
->nfetch_refs
= 0;
2534 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2536 err
= got_privsep_recv_gotconfig_str(&ref
,
2539 free_remote_data(remote
);
2542 remote
->fetch_refs
[i
] = ref
;
2543 remote
->nfetch_refs
++;
2548 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2559 for (i
= 0; i
< *nremotes
; i
++)
2560 free_remote_data(&(*remotes
)[i
]);
2568 const struct got_error
*
2569 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2570 struct got_object_id
*id
, int idx
, const char *path
)
2573 size_t path_len
= strlen(path
) + 1;
2575 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2576 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2578 return got_error_from_errno(
2579 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2580 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1)
2581 return got_error_from_errno("imsg_add "
2582 "COMMIT_TRAVERSAL_REQUEST");
2583 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1)
2584 return got_error_from_errno("imsg_add "
2585 "COMMIT_TRAVERSAL_REQUEST");
2586 if (imsg_add(wbuf
, path
, path_len
) == -1)
2587 return got_error_from_errno("imsg_add "
2588 "COMMIT_TRAVERSAL_REQUEST");
2591 imsg_close(ibuf
, wbuf
);
2593 return flush_imsg(ibuf
);
2596 const struct got_error
*
2597 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2598 struct got_object_id
**changed_commit_id
,
2599 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2601 const struct got_error
*err
= NULL
;
2603 struct got_imsg_traversed_commits
*icommits
;
2607 *changed_commit
= NULL
;
2608 *changed_commit_id
= NULL
;
2611 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2615 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2616 switch (imsg
.hdr
.type
) {
2617 case GOT_IMSG_TRAVERSED_COMMITS
:
2618 icommits
= imsg
.data
;
2619 if (datalen
!= sizeof(*icommits
) +
2620 icommits
->ncommits
* SHA1_DIGEST_LENGTH
) {
2621 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2624 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2625 struct got_object_qid
*qid
;
2626 uint8_t *sha1
= (uint8_t *)imsg
.data
+
2627 sizeof(*icommits
) + i
* SHA1_DIGEST_LENGTH
;
2628 err
= got_object_qid_alloc_partial(&qid
);
2631 memcpy(qid
->id
.sha1
, sha1
, SHA1_DIGEST_LENGTH
);
2632 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2634 /* The last commit may contain a change. */
2635 if (i
== icommits
->ncommits
- 1) {
2636 *changed_commit_id
=
2637 got_object_id_dup(&qid
->id
);
2638 if (*changed_commit_id
== NULL
) {
2639 err
= got_error_from_errno(
2640 "got_object_id_dup");
2646 case GOT_IMSG_COMMIT
:
2647 if (*changed_commit_id
== NULL
) {
2648 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2651 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2654 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2658 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2668 got_object_id_queue_free(commit_ids
);
2672 const struct got_error
*
2673 got_privsep_send_enumerated_tree(size_t *totlen
, struct imsgbuf
*ibuf
,
2674 struct got_object_id
*tree_id
, const char *path
,
2675 struct got_parsed_tree_entry
*entries
, int nentries
)
2677 const struct got_error
*err
= NULL
;
2679 size_t path_len
= strlen(path
);
2682 msglen
= sizeof(struct got_imsg_enumerated_tree
) + path_len
;
2683 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_TREE
, 0, 0, msglen
);
2685 return got_error_from_errno("imsg_create ENUMERATED_TREE");
2687 if (imsg_add(wbuf
, tree_id
->sha1
, SHA1_DIGEST_LENGTH
) == -1)
2688 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2689 if (imsg_add(wbuf
, &nentries
, sizeof(nentries
)) == -1)
2690 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2691 if (imsg_add(wbuf
, path
, path_len
) == -1)
2692 return got_error_from_errno("imsg_add ENUMERATED_TREE");
2695 imsg_close(ibuf
, wbuf
);
2698 err
= send_tree_entries(ibuf
, entries
, nentries
);
2703 return flush_imsg(ibuf
);
2706 const struct got_error
*
2707 got_privsep_send_object_enumeration_request(struct imsgbuf
*ibuf
)
2709 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_REQUEST
,
2710 0, 0, -1, NULL
, 0) == -1)
2711 return got_error_from_errno("imsg_compose "
2712 "OBJECT_ENUMERATION_REQUEST");
2714 return flush_imsg(ibuf
);
2717 const struct got_error
*
2718 got_privsep_send_object_enumeration_done(struct imsgbuf
*ibuf
)
2720 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_DONE
,
2721 0, 0, -1, NULL
, 0) == -1)
2722 return got_error_from_errno("imsg_compose "
2723 "OBJECT_ENUMERATION_DONE");
2725 return flush_imsg(ibuf
);
2728 const struct got_error
*
2729 got_privsep_send_object_enumeration_incomplete(struct imsgbuf
*ibuf
)
2731 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
,
2732 0, 0, -1, NULL
, 0) == -1)
2733 return got_error_from_errno("imsg_compose "
2734 "OBJECT_ENUMERATION_INCOMPLETE");
2736 return flush_imsg(ibuf
);
2739 const struct got_error
*
2740 got_privsep_send_enumerated_commit(struct imsgbuf
*ibuf
,
2741 struct got_object_id
*id
, time_t mtime
)
2745 wbuf
= imsg_create(ibuf
, GOT_IMSG_ENUMERATED_COMMIT
, 0, 0,
2746 sizeof(struct got_imsg_enumerated_commit
) + SHA1_DIGEST_LENGTH
);
2748 return got_error_from_errno("imsg_create ENUMERATED_COMMIT");
2750 /* Keep in sync with struct got_imsg_enumerated_commit! */
2751 if (imsg_add(wbuf
, id
, SHA1_DIGEST_LENGTH
) == -1)
2752 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2753 if (imsg_add(wbuf
, &mtime
, sizeof(mtime
)) == -1)
2754 return got_error_from_errno("imsg_add ENUMERATED_COMMIT");
2757 imsg_close(ibuf
, wbuf
);
2758 /* Don't flush yet, tree entries or ENUMERATION_DONE will follow. */
2762 const struct got_error
*
2763 got_privsep_recv_enumerated_objects(int *found_all_objects
,
2764 struct imsgbuf
*ibuf
,
2765 got_object_enumerate_commit_cb cb_commit
,
2766 got_object_enumerate_tree_cb cb_tree
, void *cb_arg
,
2767 struct got_repository
*repo
)
2769 const struct got_error
*err
= NULL
;
2771 struct got_imsg_enumerated_commit
*icommit
= NULL
;
2772 struct got_object_id commit_id
;
2773 int have_commit
= 0;
2775 struct got_tree_object tree
;
2776 struct got_imsg_enumerated_tree
*itree
;
2777 struct got_object_id tree_id
;
2778 char *path
= NULL
, *canon_path
= NULL
;
2779 size_t datalen
, path_len
;
2783 *found_all_objects
= 0;
2784 memset(&tree
, 0, sizeof(tree
));
2787 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2791 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2792 switch (imsg
.hdr
.type
) {
2793 case GOT_IMSG_ENUMERATED_COMMIT
:
2794 if (have_commit
&& nentries
!= -1) {
2795 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2798 if (datalen
!= sizeof(*icommit
)) {
2799 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2802 icommit
= (struct got_imsg_enumerated_commit
*)imsg
.data
;
2803 memcpy(commit_id
.sha1
, icommit
->id
, SHA1_DIGEST_LENGTH
);
2804 mtime
= icommit
->mtime
;
2807 case GOT_IMSG_ENUMERATED_TREE
:
2808 /* Should be preceeded by GOT_IMSG_ENUMERATED_COMMIT. */
2810 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2813 if (datalen
< sizeof(*itree
)) {
2814 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2818 path_len
= datalen
- sizeof(*itree
);
2819 if (path_len
== 0) {
2820 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2823 memcpy(tree_id
.sha1
, itree
->id
, sizeof(tree_id
.sha1
));
2825 path
= malloc(path_len
+ 1);
2827 err
= got_error_from_errno("malloc");
2831 canon_path
= malloc(path_len
+ 1);
2832 if (canon_path
== NULL
) {
2833 err
= got_error_from_errno("malloc");
2836 memcpy(path
, (uint8_t *)imsg
.data
+ sizeof(*itree
),
2838 path
[path_len
] = '\0';
2839 if (!got_path_is_absolute(path
)) {
2840 err
= got_error(GOT_ERR_BAD_PATH
);
2843 if (got_path_is_root_dir(path
)) {
2844 /* XXX check what got_canonpath() does wrong */
2845 canon_path
[0] = '/';
2846 canon_path
[1] = '\0';
2848 err
= got_canonpath(path
, canon_path
,
2853 if (strcmp(path
, canon_path
) != 0) {
2854 err
= got_error(GOT_ERR_BAD_PATH
);
2857 if (nentries
!= -1) {
2858 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2861 if (itree
->nentries
< -1) {
2862 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2865 if (itree
->nentries
== -1) {
2866 /* Tree was not found in pack file. */
2867 err
= cb_tree(cb_arg
, NULL
, mtime
, &tree_id
,
2871 if (itree
->nentries
> INT_MAX
) {
2872 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2875 tree
.entries
= calloc(itree
->nentries
,
2876 sizeof(struct got_tree_entry
));
2877 if (tree
.entries
== NULL
) {
2878 err
= got_error_from_errno("calloc");
2881 if (itree
->nentries
== 0) {
2882 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2887 /* Prepare for next tree. */
2889 memset(&tree
, 0, sizeof(tree
));
2892 tree
.nentries
= itree
->nentries
;
2896 case GOT_IMSG_TREE_ENTRIES
:
2897 /* Should be preceeded by GOT_IMSG_ENUMERATED_TREE. */
2898 if (nentries
<= -1) {
2899 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2902 err
= recv_tree_entries(imsg
.data
, datalen
,
2906 if (tree
.nentries
== nentries
) {
2907 err
= cb_tree(cb_arg
, &tree
, mtime
, &tree_id
,
2912 /* Prepare for next tree. */
2914 memset(&tree
, 0, sizeof(tree
));
2918 case GOT_IMSG_TREE_ENUMERATION_DONE
:
2919 /* All trees have been found and traversed. */
2920 if (!have_commit
|| path
== NULL
|| nentries
!= -1) {
2921 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2924 err
= cb_commit(cb_arg
, mtime
, &commit_id
, repo
);
2929 case GOT_IMSG_OBJECT_ENUMERATION_DONE
:
2930 *found_all_objects
= 1;
2933 case GOT_IMSG_OBJECT_ENUMERATION_INCOMPLETE
:
2937 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2952 const struct got_error
*
2953 got_privsep_send_raw_delta_req(struct imsgbuf
*ibuf
, int idx
,
2954 struct got_object_id
*id
)
2956 struct got_imsg_raw_delta_request dreq
;
2958 memset(&dreq
, 0, sizeof(dreq
));
2960 memcpy(dreq
.id
, id
->sha1
, SHA1_DIGEST_LENGTH
);
2962 if (imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA_REQUEST
, 0, 0, -1,
2963 &dreq
, sizeof(dreq
)) == -1)
2964 return got_error_from_errno("imsg_compose RAW_DELTA_REQUEST");
2966 return flush_imsg(ibuf
);
2969 const struct got_error
*
2970 got_privsep_send_raw_delta_outfd(struct imsgbuf
*ibuf
, int fd
)
2972 return send_fd(ibuf
, GOT_IMSG_RAW_DELTA_OUTFD
, fd
);
2975 const struct got_error
*
2976 got_privsep_send_raw_delta(struct imsgbuf
*ibuf
, uint64_t base_size
,
2977 uint64_t result_size
, off_t delta_size
, off_t delta_compressed_size
,
2978 off_t delta_offset
, off_t delta_out_offset
, struct got_object_id
*base_id
)
2980 struct got_imsg_raw_delta idelta
;
2983 memset(&idelta
, 0, sizeof(idelta
));
2984 idelta
.base_size
= base_size
;
2985 idelta
.result_size
= result_size
;
2986 idelta
.delta_size
= delta_size
;
2987 idelta
.delta_compressed_size
= delta_compressed_size
;
2988 idelta
.delta_offset
= delta_offset
;
2989 idelta
.delta_out_offset
= delta_out_offset
;
2990 memcpy(idelta
.base_id
, base_id
->sha1
, SHA1_DIGEST_LENGTH
);
2992 ret
= imsg_compose(ibuf
, GOT_IMSG_RAW_DELTA
, 0, 0, -1,
2993 &idelta
, sizeof(idelta
));
2995 return got_error_from_errno("imsg_compose RAW_DELTA");
2997 return flush_imsg(ibuf
);
3000 const struct got_error
*
3001 got_privsep_recv_raw_delta(uint64_t *base_size
, uint64_t *result_size
,
3002 off_t
*delta_size
, off_t
*delta_compressed_size
, off_t
*delta_offset
,
3003 off_t
*delta_out_offset
, struct got_object_id
**base_id
, struct imsgbuf
*ibuf
)
3005 const struct got_error
*err
= NULL
;
3007 struct got_imsg_raw_delta
*delta
;
3013 *delta_compressed_size
= 0;
3015 *delta_out_offset
= 0;
3018 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3022 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3024 switch (imsg
.hdr
.type
) {
3025 case GOT_IMSG_RAW_DELTA
:
3026 if (datalen
!= sizeof(*delta
)) {
3027 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3031 *base_size
= delta
->base_size
;
3032 *result_size
= delta
->result_size
;
3033 *delta_size
= delta
->delta_size
;
3034 *delta_compressed_size
= delta
->delta_compressed_size
;
3035 *delta_offset
= delta
->delta_offset
;
3036 *delta_out_offset
= delta
->delta_out_offset
;
3037 *base_id
= calloc(1, sizeof(**base_id
));
3038 if (*base_id
== NULL
) {
3039 err
= got_error_from_errno("malloc");
3042 memcpy((*base_id
)->sha1
, delta
->base_id
, SHA1_DIGEST_LENGTH
);
3045 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3058 static const struct got_error
*
3059 send_idlist(struct imsgbuf
*ibuf
, struct got_object_id
**ids
, size_t nids
)
3061 const struct got_error
*err
= NULL
;
3062 struct got_imsg_object_idlist idlist
;
3066 memset(&idlist
, 0, sizeof(idlist
));
3068 if (nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
)
3069 return got_error(GOT_ERR_NO_SPACE
);
3071 wbuf
= imsg_create(ibuf
, GOT_IMSG_OBJ_ID_LIST
, 0, 0,
3072 sizeof(idlist
) + nids
* sizeof(**ids
));
3074 err
= got_error_from_errno("imsg_create OBJ_ID_LIST");
3079 if (imsg_add(wbuf
, &idlist
, sizeof(idlist
)) == -1)
3080 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3082 for (i
= 0; i
< nids
; i
++) {
3083 struct got_object_id
*id
= ids
[i
];
3084 if (imsg_add(wbuf
, id
, sizeof(*id
)) == -1)
3085 return got_error_from_errno("imsg_add OBJ_ID_LIST");
3089 imsg_close(ibuf
, wbuf
);
3091 return flush_imsg(ibuf
);
3094 const struct got_error
*
3095 got_privsep_send_object_idlist(struct imsgbuf
*ibuf
,
3096 struct got_object_id
**ids
, size_t nids
)
3098 const struct got_error
*err
= NULL
;
3099 struct got_object_id
*idlist
[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
];
3102 for (i
= 0; i
< nids
; i
++) {
3103 idlist
[i
% nitems(idlist
)] = ids
[i
];
3105 if (queued
>= nitems(idlist
)) {
3106 err
= send_idlist(ibuf
, idlist
, queued
);
3114 err
= send_idlist(ibuf
, idlist
, queued
);
3122 const struct got_error
*
3123 got_privsep_send_object_idlist_done(struct imsgbuf
*ibuf
)
3125 if (imsg_compose(ibuf
, GOT_IMSG_OBJ_ID_LIST_DONE
, 0, 0, -1, NULL
, 0)
3127 return got_error_from_errno("imsg_compose OBJ_ID_LIST_DONE");
3129 return flush_imsg(ibuf
);
3132 const struct got_error
*
3133 got_privsep_recv_object_idlist(int *done
, struct got_object_id
**ids
,
3134 size_t *nids
, struct imsgbuf
*ibuf
)
3136 const struct got_error
*err
= NULL
;
3138 struct got_imsg_object_idlist
*idlist
;
3145 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3149 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3150 switch (imsg
.hdr
.type
) {
3151 case GOT_IMSG_OBJ_ID_LIST
:
3152 if (datalen
< sizeof(*idlist
)) {
3153 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3157 if (idlist
->nids
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3158 idlist
->nids
* sizeof(**ids
) > datalen
- sizeof(*idlist
)) {
3159 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3162 *nids
= idlist
->nids
;
3163 *ids
= calloc(*nids
, sizeof(**ids
));
3165 err
= got_error_from_errno("calloc");
3168 memcpy(*ids
, (uint8_t *)imsg
.data
+ sizeof(*idlist
),
3169 *nids
* sizeof(**ids
));
3171 case GOT_IMSG_OBJ_ID_LIST_DONE
:
3175 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3184 const struct got_error
*
3185 got_privsep_send_delta_reuse_req(struct imsgbuf
*ibuf
)
3187 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_REQUEST
, 0, 0, -1, NULL
, 0)
3189 return got_error_from_errno("imsg_compose DELTA_REUSE_REQUEST");
3191 return flush_imsg(ibuf
);
3194 const struct got_error
*
3195 got_privsep_send_reused_deltas(struct imsgbuf
*ibuf
,
3196 struct got_imsg_reused_delta
*deltas
, size_t ndeltas
)
3198 const struct got_error
*err
= NULL
;
3200 struct got_imsg_reused_deltas ideltas
;
3203 memset(&ideltas
, 0, sizeof(ideltas
));
3205 if (ndeltas
> GOT_IMSG_REUSED_DELTAS_MAX_NDELTAS
)
3206 return got_error(GOT_ERR_NO_SPACE
);
3208 wbuf
= imsg_create(ibuf
, GOT_IMSG_REUSED_DELTAS
, 0, 0,
3209 sizeof(ideltas
) + ndeltas
* sizeof(*deltas
));
3211 err
= got_error_from_errno("imsg_create REUSED_DELTAS");
3215 ideltas
.ndeltas
= ndeltas
;
3216 if (imsg_add(wbuf
, &ideltas
, sizeof(ideltas
)) == -1)
3217 return got_error_from_errno("imsg_add REUSED_DELTAS");
3219 for (i
= 0; i
< ndeltas
; i
++) {
3220 struct got_imsg_reused_delta
*delta
= &deltas
[i
];
3221 if (imsg_add(wbuf
, delta
, sizeof(*delta
)) == -1)
3222 return got_error_from_errno("imsg_add REUSED_DELTAS");
3226 imsg_close(ibuf
, wbuf
);
3228 return flush_imsg(ibuf
);
3231 const struct got_error
*
3232 got_privsep_send_reused_deltas_done(struct imsgbuf
*ibuf
)
3234 if (imsg_compose(ibuf
, GOT_IMSG_DELTA_REUSE_DONE
, 0, 0, -1, NULL
, 0)
3236 return got_error_from_errno("imsg_compose DELTA_REUSE_DONE");
3238 return flush_imsg(ibuf
);
3241 const struct got_error
*
3242 got_privsep_recv_reused_deltas(int *done
, struct got_imsg_reused_delta
*deltas
,
3243 size_t *ndeltas
, struct imsgbuf
*ibuf
)
3245 const struct got_error
*err
= NULL
;
3247 struct got_imsg_reused_deltas
*ideltas
;
3253 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3257 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3258 switch (imsg
.hdr
.type
) {
3259 case GOT_IMSG_REUSED_DELTAS
:
3260 if (datalen
< sizeof(*ideltas
)) {
3261 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3264 ideltas
= imsg
.data
;
3265 if (ideltas
->ndeltas
> GOT_IMSG_OBJ_ID_LIST_MAX_NIDS
||
3266 ideltas
->ndeltas
* sizeof(*deltas
) >
3267 datalen
- sizeof(*ideltas
)) {
3268 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
3271 *ndeltas
= ideltas
->ndeltas
;
3272 memcpy(deltas
, (uint8_t *)imsg
.data
+ sizeof(*ideltas
),
3273 *ndeltas
* sizeof(*deltas
));
3275 case GOT_IMSG_DELTA_REUSE_DONE
:
3279 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
3288 const struct got_error
*
3289 got_privsep_init_commit_painting(struct imsgbuf
*ibuf
)
3291 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_INIT
,
3294 return got_error_from_errno("imsg_compose "
3295 "COMMIT_PAINTING_INIT");
3297 return flush_imsg(ibuf
);
3300 const struct got_error
*
3301 got_privsep_send_painting_request(struct imsgbuf
*ibuf
, int idx
,
3302 struct got_object_id
*id
, intptr_t color
)
3304 struct got_imsg_commit_painting_request ireq
;
3306 memset(&ireq
, 0, sizeof(ireq
));
3307 memcpy(ireq
.id
, id
->sha1
, sizeof(ireq
.id
));
3311 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_REQUEST
, 0, 0, -1,
3312 &ireq
, sizeof(ireq
)) == -1)
3313 return got_error_from_errno("imsg_compose "
3314 "COMMIT_PAINTING_REQUEST");
3316 return flush_imsg(ibuf
);
3319 static const struct got_error
*
3320 send_painted_commits(struct got_object_id_queue
*ids
, int *nids
,
3321 size_t remain
, int present_in_pack
, struct imsgbuf
*ibuf
)
3323 const struct got_error
*err
= NULL
;
3324 struct ibuf
*wbuf
= NULL
;
3325 struct got_object_qid
*qid
;
3330 msglen
= MIN(remain
, MAX_IMSGSIZE
- IMSG_HEADER_SIZE
);
3331 ncommits
= (msglen
- sizeof(struct got_imsg_painted_commits
)) /
3332 sizeof(struct got_imsg_painted_commit
);
3334 wbuf
= imsg_create(ibuf
, GOT_IMSG_PAINTED_COMMITS
, 0, 0, msglen
);
3336 err
= got_error_from_errno("imsg_create PAINTED_COMMITS");
3340 /* Keep in sync with struct got_imsg_painted_commits! */
3341 if (imsg_add(wbuf
, &ncommits
, sizeof(ncommits
)) == -1)
3342 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3343 if (imsg_add(wbuf
, &present_in_pack
, sizeof(present_in_pack
)) == -1)
3344 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3346 while (ncommits
> 0) {
3347 qid
= STAILQ_FIRST(ids
);
3348 STAILQ_REMOVE_HEAD(ids
, entry
);
3351 color
= (intptr_t)qid
->data
;
3353 /* Keep in sync with struct got_imsg_painted_commit! */
3354 if (imsg_add(wbuf
, qid
->id
.sha1
, SHA1_DIGEST_LENGTH
) == -1)
3355 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3356 if (imsg_add(wbuf
, &color
, sizeof(color
)) == -1)
3357 return got_error_from_errno("imsg_add PAINTED_COMMITS");
3359 got_object_qid_free(qid
);
3363 imsg_close(ibuf
, wbuf
);
3365 return flush_imsg(ibuf
);
3368 const struct got_error
*
3369 got_privsep_send_painted_commits(struct imsgbuf
*ibuf
,
3370 struct got_object_id_queue
*ids
, int *nids
,
3371 int present_in_pack
, int flush
)
3373 const struct got_error
*err
;
3380 remain
= (sizeof(struct got_imsg_painted_commits
)) +
3381 *nids
* sizeof(struct got_imsg_painted_commit
);
3382 if (flush
|| remain
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
3383 err
= send_painted_commits(ids
, nids
, remain
,
3384 present_in_pack
, ibuf
);
3388 } while (flush
&& *nids
> 0);
3393 const struct got_error
*
3394 got_privsep_send_painting_commits_done(struct imsgbuf
*ibuf
)
3396 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_PAINTING_DONE
,
3399 return got_error_from_errno("imsg_compose "
3400 "COMMIT_PAINTING_DONE");
3402 return flush_imsg(ibuf
);
3405 const struct got_error
*
3406 got_privsep_recv_painted_commits(struct got_object_id_queue
*new_ids
,
3407 got_privsep_recv_painted_commit_cb cb
, void *cb_arg
, struct imsgbuf
*ibuf
)
3409 const struct got_error
*err
= NULL
;
3411 struct got_imsg_painted_commits icommits
;
3412 struct got_imsg_painted_commit icommit
;
3417 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
3421 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
3422 if (imsg
.hdr
.type
== GOT_IMSG_COMMIT_PAINTING_DONE
)
3424 if (imsg
.hdr
.type
!= GOT_IMSG_PAINTED_COMMITS
)
3425 return got_error(GOT_ERR_PRIVSEP_MSG
);
3427 if (datalen
< sizeof(icommits
))
3428 return got_error(GOT_ERR_PRIVSEP_LEN
);
3429 memcpy(&icommits
, imsg
.data
, sizeof(icommits
));
3430 if (icommits
.ncommits
* sizeof(icommit
) < icommits
.ncommits
||
3431 datalen
< sizeof(icommits
) +
3432 icommits
.ncommits
* sizeof(icommit
))
3433 return got_error(GOT_ERR_PRIVSEP_LEN
);
3435 for (i
= 0; i
< icommits
.ncommits
; i
++) {
3437 (uint8_t *)imsg
.data
+ sizeof(icommits
) + i
* sizeof(icommit
),
3440 if (icommits
.present_in_pack
) {
3441 struct got_object_id id
;
3442 memcpy(id
.sha1
, icommit
.id
, SHA1_DIGEST_LENGTH
);
3443 err
= cb(cb_arg
, &id
, icommit
.color
);
3447 struct got_object_qid
*qid
;
3448 err
= got_object_qid_alloc_partial(&qid
);
3451 memcpy(qid
->id
.sha1
, icommit
.id
,
3452 SHA1_DIGEST_LENGTH
);
3453 qid
->data
= (void *)icommit
.color
;
3454 STAILQ_INSERT_TAIL(new_ids
, qid
, entry
);
3464 const struct got_error
*
3465 got_privsep_unveil_exec_helpers(void)
3467 const char *helpers
[] = {
3468 GOT_PATH_PROG_READ_PACK
,
3469 GOT_PATH_PROG_READ_OBJECT
,
3470 GOT_PATH_PROG_READ_COMMIT
,
3471 GOT_PATH_PROG_READ_TREE
,
3472 GOT_PATH_PROG_READ_BLOB
,
3473 GOT_PATH_PROG_READ_TAG
,
3474 GOT_PATH_PROG_READ_GITCONFIG
,
3475 GOT_PATH_PROG_READ_GOTCONFIG
,
3476 GOT_PATH_PROG_READ_PATCH
,
3477 GOT_PATH_PROG_FETCH_PACK
,
3478 GOT_PATH_PROG_INDEX_PACK
,
3479 GOT_PATH_PROG_SEND_PACK
,
3483 for (i
= 0; i
< nitems(helpers
); i
++) {
3484 if (unveil(helpers
[i
], "x") == 0)
3486 return got_error_from_errno2("unveil", helpers
[i
]);
3493 got_privsep_exec_child(int imsg_fds
[2], const char *path
, const char *repo_path
)
3495 if (close(imsg_fds
[0]) == -1) {
3496 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3500 if (dup2(imsg_fds
[1], GOT_IMSG_FD_CHILD
) == -1) {
3501 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
3505 closefrom(GOT_IMSG_FD_CHILD
+ 1);
3507 if (execl(path
, path
, repo_path
, (char *)NULL
) == -1) {
3508 fprintf(stderr
, "%s: %s: %s\n", getprogname(), path
,