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>
36 #include "got_compat.h"
38 #include "got_object.h"
39 #include "got_error.h"
41 #include "got_repository.h"
43 #include "got_lib_sha1.h"
44 #include "got_lib_delta.h"
45 #include "got_lib_inflate.h"
46 #include "got_lib_object.h"
47 #include "got_lib_object_parse.h"
48 #include "got_lib_privsep.h"
49 #include "got_lib_pack.h"
52 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
56 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
59 static const struct got_error
*
60 poll_fd(int fd
, int events
, int timeout
)
68 pfd
[0].events
= events
;
73 if (sigemptyset(&sigset
) == -1)
74 return got_error_from_errno("sigemptyset");
75 if (sigaddset(&sigset
, SIGWINCH
) == -1)
76 return got_error_from_errno("sigaddset");
78 n
= ppoll(pfd
, 1, timeout
== INFTIM
? NULL
: &ts
, &sigset
);
80 return got_error_from_errno("ppoll");
82 return got_error(GOT_ERR_TIMEOUT
);
83 if (pfd
[0].revents
& (POLLERR
| POLLNVAL
))
84 return got_error_from_errno("poll error");
85 if (pfd
[0].revents
& (events
| POLLHUP
))
88 return got_error(GOT_ERR_INTERRUPT
);
91 static const struct got_error
*
92 read_imsg(struct imsgbuf
*ibuf
)
94 const struct got_error
*err
;
97 err
= poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
103 if (errno
== EAGAIN
) /* Could be a file-descriptor leak. */
104 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
105 return got_error(GOT_ERR_PRIVSEP_READ
);
108 return got_error(GOT_ERR_PRIVSEP_PIPE
);
113 const struct got_error
*
114 got_privsep_wait_for_child(pid_t pid
)
118 if (waitpid(pid
, &child_status
, 0) == -1)
119 return got_error_from_errno("waitpid");
121 if (!WIFEXITED(child_status
))
122 return got_error(GOT_ERR_PRIVSEP_DIED
);
124 if (WEXITSTATUS(child_status
) != 0)
125 return got_error(GOT_ERR_PRIVSEP_EXIT
);
130 static const struct got_error
*
131 recv_imsg_error(struct imsg
*imsg
, size_t datalen
)
133 struct got_imsg_error
*ierr
;
135 if (datalen
!= sizeof(*ierr
))
136 return got_error(GOT_ERR_PRIVSEP_LEN
);
139 if (ierr
->code
== GOT_ERR_ERRNO
) {
140 static struct got_error serr
;
141 serr
.code
= GOT_ERR_ERRNO
;
142 serr
.msg
= strerror(ierr
->errno_code
);
146 return got_error(ierr
->code
);
149 const struct got_error
*
150 got_privsep_recv_imsg(struct imsg
*imsg
, struct imsgbuf
*ibuf
,
153 const struct got_error
*err
;
156 n
= imsg_get(ibuf
, imsg
);
158 return got_error_from_errno("imsg_get");
161 err
= read_imsg(ibuf
);
164 n
= imsg_get(ibuf
, imsg
);
166 return got_error_from_errno("imsg_get");
169 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
170 return got_error(GOT_ERR_PRIVSEP_LEN
);
172 if (imsg
->hdr
.type
== GOT_IMSG_ERROR
) {
173 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
174 return recv_imsg_error(imsg
, datalen
);
180 /* Attempt to send an error in an imsg. Complain on stderr as a last resort. */
182 got_privsep_send_error(struct imsgbuf
*ibuf
, const struct got_error
*err
)
184 const struct got_error
*poll_err
;
185 struct got_imsg_error ierr
;
188 ierr
.code
= err
->code
;
189 if (err
->code
== GOT_ERR_ERRNO
)
190 ierr
.errno_code
= errno
;
193 ret
= imsg_compose(ibuf
, GOT_IMSG_ERROR
, 0, 0, -1, &ierr
, sizeof(ierr
));
195 fprintf(stderr
, "%s: error %d \"%s\": imsg_compose: %s\n",
196 getprogname(), err
->code
, err
->msg
, strerror(errno
));
200 poll_err
= poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
202 fprintf(stderr
, "%s: error %d \"%s\": poll: %s\n",
203 getprogname(), err
->code
, err
->msg
, poll_err
->msg
);
207 ret
= imsg_flush(ibuf
);
209 fprintf(stderr
, "%s: error %d \"%s\": imsg_flush: %s\n",
210 getprogname(), err
->code
, err
->msg
, strerror(errno
));
215 static const struct got_error
*
216 flush_imsg(struct imsgbuf
*ibuf
)
218 const struct got_error
*err
;
220 err
= poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
224 if (imsg_flush(ibuf
) == -1)
225 return got_error_from_errno("imsg_flush");
230 const struct got_error
*
231 got_privsep_flush_imsg(struct imsgbuf
*ibuf
)
233 return flush_imsg(ibuf
);
236 const struct got_error
*
237 got_privsep_send_stop(int fd
)
239 const struct got_error
*err
= NULL
;
242 imsg_init(&ibuf
, fd
);
244 if (imsg_compose(&ibuf
, GOT_IMSG_STOP
, 0, 0, -1, NULL
, 0) == -1)
245 return got_error_from_errno("imsg_compose STOP");
247 err
= flush_imsg(&ibuf
);
252 const struct got_error
*
253 got_privsep_send_obj_req(struct imsgbuf
*ibuf
, int fd
,
254 struct got_object_id
*id
)
256 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT_REQUEST
, 0, 0, fd
,
257 id
, sizeof(*id
)) == -1)
258 return got_error_from_errno("imsg_compose OBJECT_REQUEST");
260 return flush_imsg(ibuf
);
263 const struct got_error
*
264 got_privsep_send_raw_obj_req(struct imsgbuf
*ibuf
, int fd
,
265 struct got_object_id
*id
)
267 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_REQUEST
, 0, 0, fd
,
268 id
, sizeof(*id
)) == -1)
269 return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
271 return flush_imsg(ibuf
);
274 const struct got_error
*
275 got_privsep_send_raw_obj_outfd(struct imsgbuf
*ibuf
, int outfd
)
277 const struct got_error
*err
= NULL
;
279 if (imsg_compose(ibuf
, GOT_IMSG_RAW_OBJECT_OUTFD
, 0, 0, outfd
, NULL
, 0)
281 err
= got_error_from_errno("imsg_compose RAW_OBJECT_OUTFD");
286 return flush_imsg(ibuf
);
289 const struct got_error
*
290 got_privsep_send_raw_obj(struct imsgbuf
*ibuf
, off_t size
, size_t hdrlen
,
293 const struct got_error
*err
= NULL
;
294 struct got_imsg_raw_obj iobj
;
295 size_t len
= sizeof(iobj
);
298 iobj
.hdrlen
= hdrlen
;
301 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
)
302 len
+= (size_t)size
+ hdrlen
;
304 wbuf
= imsg_create(ibuf
, GOT_IMSG_RAW_OBJECT
, 0, 0, len
);
306 err
= got_error_from_errno("imsg_create RAW_OBJECT");
310 if (imsg_add(wbuf
, &iobj
, sizeof(iobj
)) == -1) {
311 err
= got_error_from_errno("imsg_add RAW_OBJECT");
316 if (data
&& size
+ hdrlen
<= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
317 if (imsg_add(wbuf
, data
, size
+ hdrlen
) == -1) {
318 err
= got_error_from_errno("imsg_add RAW_OBJECT");
325 imsg_close(ibuf
, wbuf
);
327 return flush_imsg(ibuf
);
330 const struct got_error
*
331 got_privsep_recv_raw_obj(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
332 struct imsgbuf
*ibuf
)
334 const struct got_error
*err
= NULL
;
336 struct got_imsg_raw_obj
*iobj
;
341 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
345 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
347 switch (imsg
.hdr
.type
) {
348 case GOT_IMSG_RAW_OBJECT
:
349 if (datalen
< sizeof(*iobj
)) {
350 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
355 *hdrlen
= iobj
->hdrlen
;
357 if (datalen
== sizeof(*iobj
)) {
358 /* Data has been written to file descriptor. */
362 if (*size
+ *hdrlen
> GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX
) {
363 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
367 *outbuf
= malloc(*size
+ *hdrlen
);
368 if (*outbuf
== NULL
) {
369 err
= got_error_from_errno("malloc");
372 memcpy(*outbuf
, imsg
.data
+ sizeof(*iobj
), *size
+ *hdrlen
);
375 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
384 const struct got_error
*
385 got_privsep_send_commit_req(struct imsgbuf
*ibuf
, int fd
,
386 struct got_object_id
*id
, int pack_idx
)
388 const struct got_error
*err
= NULL
;
389 struct got_imsg_packed_object iobj
;
393 if (pack_idx
!= -1) { /* commit is packed */
395 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
403 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_REQUEST
, 0, 0, fd
, data
, len
)
405 err
= got_error_from_errno("imsg_compose COMMIT_REQUEST");
410 return flush_imsg(ibuf
);
413 const struct got_error
*
414 got_privsep_send_tree_req(struct imsgbuf
*ibuf
, int fd
,
415 struct got_object_id
*id
, int pack_idx
)
417 const struct got_error
*err
= NULL
;
422 len
= sizeof(struct got_imsg_packed_object
);
426 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_REQUEST
, 0, 0, len
);
428 return got_error_from_errno("imsg_create TREE_REQUEST");
430 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1) {
431 err
= got_error_from_errno("imsg_add TREE_ENTRY");
436 if (pack_idx
!= -1) { /* tree is packed */
437 if (imsg_add(wbuf
, &pack_idx
, sizeof(pack_idx
)) == -1) {
438 err
= got_error_from_errno("imsg_add TREE_ENTRY");
445 imsg_close(ibuf
, wbuf
);
447 return flush_imsg(ibuf
);
450 const struct got_error
*
451 got_privsep_send_tag_req(struct imsgbuf
*ibuf
, int fd
,
452 struct got_object_id
*id
, int pack_idx
)
454 struct got_imsg_packed_object iobj
;
458 if (pack_idx
!= -1) { /* tag is packed */
460 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
468 if (imsg_compose(ibuf
, GOT_IMSG_TAG_REQUEST
, 0, 0, fd
, data
, len
)
470 return got_error_from_errno("imsg_compose TAG_REQUEST");
472 return flush_imsg(ibuf
);
475 const struct got_error
*
476 got_privsep_send_blob_req(struct imsgbuf
*ibuf
, int infd
,
477 struct got_object_id
*id
, int pack_idx
)
479 const struct got_error
*err
= NULL
;
480 struct got_imsg_packed_object iobj
;
484 if (pack_idx
!= -1) { /* blob is packed */
486 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
494 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_REQUEST
, 0, 0, infd
, data
, len
)
496 err
= got_error_from_errno("imsg_compose BLOB_REQUEST");
501 return flush_imsg(ibuf
);
504 const struct got_error
*
505 got_privsep_send_blob_outfd(struct imsgbuf
*ibuf
, int outfd
)
507 const struct got_error
*err
= NULL
;
509 if (imsg_compose(ibuf
, GOT_IMSG_BLOB_OUTFD
, 0, 0, outfd
, NULL
, 0)
511 err
= got_error_from_errno("imsg_compose BLOB_OUTFD");
516 return flush_imsg(ibuf
);
519 static const struct got_error
*
520 send_fd(struct imsgbuf
*ibuf
, int imsg_code
, int fd
)
522 const struct got_error
*err
= NULL
;
524 if (imsg_compose(ibuf
, imsg_code
, 0, 0, fd
, NULL
, 0) == -1) {
525 err
= got_error_from_errno("imsg_compose TMPFD");
530 return flush_imsg(ibuf
);
533 const struct got_error
*
534 got_privsep_send_tmpfd(struct imsgbuf
*ibuf
, int fd
)
536 return send_fd(ibuf
, GOT_IMSG_TMPFD
, fd
);
539 const struct got_error
*
540 got_privsep_send_obj(struct imsgbuf
*ibuf
, struct got_object
*obj
)
542 struct got_imsg_object iobj
;
544 memcpy(iobj
.id
, obj
->id
.sha1
, sizeof(iobj
.id
));
545 iobj
.type
= obj
->type
;
546 iobj
.flags
= obj
->flags
;
547 iobj
.hdrlen
= obj
->hdrlen
;
548 iobj
.size
= obj
->size
;
549 if (iobj
.flags
& GOT_OBJ_FLAG_PACKED
) {
550 iobj
.pack_offset
= obj
->pack_offset
;
551 iobj
.pack_idx
= obj
->pack_idx
;
554 if (imsg_compose(ibuf
, GOT_IMSG_OBJECT
, 0, 0, -1, &iobj
, sizeof(iobj
))
556 return got_error_from_errno("imsg_compose OBJECT");
558 return flush_imsg(ibuf
);
561 const struct got_error
*
562 got_privsep_send_fetch_req(struct imsgbuf
*ibuf
, int fd
,
563 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
564 struct got_pathlist_head
*wanted_branches
,
565 struct got_pathlist_head
*wanted_refs
, int list_refs_only
, int verbosity
)
567 const struct got_error
*err
= NULL
;
570 struct got_pathlist_entry
*pe
;
571 struct got_imsg_fetch_request fetchreq
;
573 memset(&fetchreq
, 0, sizeof(fetchreq
));
574 fetchreq
.fetch_all_branches
= fetch_all_branches
;
575 fetchreq
.list_refs_only
= list_refs_only
;
576 fetchreq
.verbosity
= verbosity
;
577 TAILQ_FOREACH(pe
, have_refs
, entry
)
578 fetchreq
.n_have_refs
++;
579 TAILQ_FOREACH(pe
, wanted_branches
, entry
)
580 fetchreq
.n_wanted_branches
++;
581 TAILQ_FOREACH(pe
, wanted_refs
, entry
)
582 fetchreq
.n_wanted_refs
++;
583 len
= sizeof(struct got_imsg_fetch_request
);
584 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
586 return got_error(GOT_ERR_NO_SPACE
);
589 if (imsg_compose(ibuf
, GOT_IMSG_FETCH_REQUEST
, 0, 0, fd
,
590 &fetchreq
, sizeof(fetchreq
)) == -1)
591 return got_error_from_errno(
592 "imsg_compose FETCH_SERVER_PROGRESS");
594 err
= flush_imsg(ibuf
);
601 TAILQ_FOREACH(pe
, have_refs
, entry
) {
602 const char *name
= pe
->path
;
603 size_t name_len
= pe
->path_len
;
604 struct got_object_id
*id
= pe
->data
;
606 len
= sizeof(struct got_imsg_fetch_have_ref
) + name_len
;
607 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_HAVE_REF
, 0, 0, len
);
609 return got_error_from_errno("imsg_create FETCH_HAVE_REF");
611 /* Keep in sync with struct got_imsg_fetch_have_ref! */
612 if (imsg_add(wbuf
, id
->sha1
, sizeof(id
->sha1
)) == -1) {
613 err
= got_error_from_errno("imsg_add FETCH_HAVE_REF");
617 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1) {
618 err
= got_error_from_errno("imsg_add FETCH_HAVE_REF");
622 if (imsg_add(wbuf
, name
, name_len
) == -1) {
623 err
= got_error_from_errno("imsg_add FETCH_HAVE_REF");
629 imsg_close(ibuf
, wbuf
);
630 err
= flush_imsg(ibuf
);
635 TAILQ_FOREACH(pe
, wanted_branches
, entry
) {
636 const char *name
= pe
->path
;
637 size_t name_len
= pe
->path_len
;
639 len
= sizeof(struct got_imsg_fetch_wanted_branch
) + name_len
;
640 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_BRANCH
, 0, 0,
643 return got_error_from_errno(
644 "imsg_create FETCH_WANTED_BRANCH");
646 /* Keep in sync with struct got_imsg_fetch_wanted_branch! */
647 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1) {
648 err
= got_error_from_errno(
649 "imsg_add FETCH_WANTED_BRANCH");
653 if (imsg_add(wbuf
, name
, name_len
) == -1) {
654 err
= got_error_from_errno(
655 "imsg_add FETCH_WANTED_BRANCH");
661 imsg_close(ibuf
, wbuf
);
662 err
= flush_imsg(ibuf
);
667 TAILQ_FOREACH(pe
, wanted_refs
, entry
) {
668 const char *name
= pe
->path
;
669 size_t name_len
= pe
->path_len
;
671 len
= sizeof(struct got_imsg_fetch_wanted_ref
) + name_len
;
672 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_WANTED_REF
, 0, 0,
675 return got_error_from_errno(
676 "imsg_create FETCH_WANTED_REF");
678 /* Keep in sync with struct got_imsg_fetch_wanted_ref! */
679 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1) {
680 err
= got_error_from_errno(
681 "imsg_add FETCH_WANTED_REF");
685 if (imsg_add(wbuf
, name
, name_len
) == -1) {
686 err
= got_error_from_errno(
687 "imsg_add FETCH_WANTED_REF");
693 imsg_close(ibuf
, wbuf
);
694 err
= flush_imsg(ibuf
);
704 const struct got_error
*
705 got_privsep_send_fetch_outfd(struct imsgbuf
*ibuf
, int fd
)
707 return send_fd(ibuf
, GOT_IMSG_FETCH_OUTFD
, fd
);
710 const struct got_error
*
711 got_privsep_recv_fetch_progress(int *done
, struct got_object_id
**id
,
712 char **refname
, struct got_pathlist_head
*symrefs
, char **server_progress
,
713 off_t
*packfile_size
, uint8_t *pack_sha1
, struct imsgbuf
*ibuf
)
715 const struct got_error
*err
= NULL
;
718 struct got_imsg_fetch_symrefs
*isymrefs
= NULL
;
726 *server_progress
= NULL
;
728 memset(pack_sha1
, 0, SHA1_DIGEST_LENGTH
);
730 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
734 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
735 switch (imsg
.hdr
.type
) {
737 if (datalen
< sizeof(struct got_imsg_error
)) {
738 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
741 err
= recv_imsg_error(&imsg
, datalen
);
743 case GOT_IMSG_FETCH_SYMREFS
:
744 if (datalen
< sizeof(*isymrefs
)) {
745 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
748 if (isymrefs
!= NULL
) {
749 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
752 isymrefs
= (struct got_imsg_fetch_symrefs
*)imsg
.data
;
753 off
= sizeof(*isymrefs
);
754 remain
= datalen
- off
;
755 for (n
= 0; n
< isymrefs
->nsymrefs
; n
++) {
756 struct got_imsg_fetch_symref
*s
;
758 if (remain
< sizeof(struct got_imsg_fetch_symref
)) {
759 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
762 s
= (struct got_imsg_fetch_symref
*)(imsg
.data
+ off
);
764 remain
-= sizeof(*s
);
765 if (remain
< s
->name_len
) {
766 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
769 name
= strndup(imsg
.data
+ off
, s
->name_len
);
771 err
= got_error_from_errno("strndup");
775 remain
-= s
->name_len
;
776 if (remain
< s
->target_len
) {
777 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
781 target
= strndup(imsg
.data
+ off
, s
->target_len
);
782 if (target
== NULL
) {
783 err
= got_error_from_errno("strndup");
787 off
+= s
->target_len
;
788 remain
-= s
->target_len
;
789 err
= got_pathlist_append(symrefs
, name
, target
);
797 case GOT_IMSG_FETCH_REF
:
798 if (datalen
<= SHA1_DIGEST_LENGTH
) {
799 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
802 *id
= malloc(sizeof(**id
));
804 err
= got_error_from_errno("malloc");
807 memcpy((*id
)->sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
808 *refname
= strndup(imsg
.data
+ SHA1_DIGEST_LENGTH
,
809 datalen
- SHA1_DIGEST_LENGTH
);
810 if (*refname
== NULL
) {
811 err
= got_error_from_errno("strndup");
815 case GOT_IMSG_FETCH_SERVER_PROGRESS
:
817 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
820 *server_progress
= strndup(imsg
.data
, datalen
);
821 if (*server_progress
== NULL
) {
822 err
= got_error_from_errno("strndup");
825 for (i
= 0; i
< datalen
; i
++) {
826 if (!isprint((unsigned char)(*server_progress
)[i
]) &&
827 !isspace((unsigned char)(*server_progress
)[i
])) {
828 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
829 free(*server_progress
);
830 *server_progress
= NULL
;
835 case GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
:
836 if (datalen
< sizeof(*packfile_size
)) {
837 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
840 memcpy(packfile_size
, imsg
.data
, sizeof(*packfile_size
));
842 case GOT_IMSG_FETCH_DONE
:
843 if (datalen
!= SHA1_DIGEST_LENGTH
) {
844 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
847 memcpy(pack_sha1
, imsg
.data
, SHA1_DIGEST_LENGTH
);
851 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
865 static const struct got_error
*
866 send_send_ref(const char *name
, size_t name_len
, struct got_object_id
*id
,
867 int delete, struct imsgbuf
*ibuf
)
869 const struct got_error
*err
= NULL
;
873 len
= sizeof(struct got_imsg_send_ref
) + name_len
;
874 wbuf
= imsg_create(ibuf
, GOT_IMSG_SEND_REF
, 0, 0, len
);
876 return got_error_from_errno("imsg_create SEND_REF");
878 /* Keep in sync with struct got_imsg_send_ref! */
879 if (imsg_add(wbuf
, id
->sha1
, sizeof(id
->sha1
)) == -1) {
880 err
= got_error_from_errno("imsg_add SEND_REF");
884 if (imsg_add(wbuf
, &delete, sizeof(delete)) == -1) {
885 err
= got_error_from_errno("imsg_add SEND_REF");
889 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1) {
890 err
= got_error_from_errno("imsg_add SEND_REF");
894 if (imsg_add(wbuf
, name
, name_len
) == -1) {
895 err
= got_error_from_errno("imsg_add SEND_REF");
901 imsg_close(ibuf
, wbuf
);
902 return flush_imsg(ibuf
);
905 const struct got_error
*
906 got_privsep_send_send_req(struct imsgbuf
*ibuf
, int fd
,
907 struct got_pathlist_head
*have_refs
,
908 struct got_pathlist_head
*delete_refs
,
911 const struct got_error
*err
= NULL
;
912 struct got_pathlist_entry
*pe
;
913 struct got_imsg_send_request sendreq
;
914 struct got_object_id zero_id
;
916 memset(&zero_id
, 0, sizeof(zero_id
));
917 memset(&sendreq
, 0, sizeof(sendreq
));
918 sendreq
.verbosity
= verbosity
;
919 TAILQ_FOREACH(pe
, have_refs
, entry
)
921 TAILQ_FOREACH(pe
, delete_refs
, entry
)
923 if (imsg_compose(ibuf
, GOT_IMSG_SEND_REQUEST
, 0, 0, fd
,
924 &sendreq
, sizeof(sendreq
)) == -1) {
925 err
= got_error_from_errno(
926 "imsg_compose FETCH_SERVER_PROGRESS");
930 err
= flush_imsg(ibuf
);
935 TAILQ_FOREACH(pe
, have_refs
, entry
) {
936 const char *name
= pe
->path
;
937 size_t name_len
= pe
->path_len
;
938 struct got_object_id
*id
= pe
->data
;
939 err
= send_send_ref(name
, name_len
, id
, 0, ibuf
);
944 TAILQ_FOREACH(pe
, delete_refs
, entry
) {
945 const char *name
= pe
->path
;
946 size_t name_len
= pe
->path_len
;
947 err
= send_send_ref(name
, name_len
, &zero_id
, 1, ibuf
);
952 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
953 err
= got_error_from_errno("close");
958 const struct got_error
*
959 got_privsep_recv_send_remote_refs(struct got_pathlist_head
*remote_refs
,
960 struct imsgbuf
*ibuf
)
962 const struct got_error
*err
= NULL
;
966 struct got_imsg_send_remote_ref iremote_ref
;
967 struct got_object_id
*id
= NULL
;
968 char *refname
= NULL
;
969 struct got_pathlist_entry
*new;
972 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
975 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
976 switch (imsg
.hdr
.type
) {
978 if (datalen
< sizeof(struct got_imsg_error
)) {
979 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
982 err
= recv_imsg_error(&imsg
, datalen
);
984 case GOT_IMSG_SEND_REMOTE_REF
:
985 if (datalen
< sizeof(iremote_ref
)) {
986 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
989 memcpy(&iremote_ref
, imsg
.data
, sizeof(iremote_ref
));
990 if (datalen
!= sizeof(iremote_ref
) +
991 iremote_ref
.name_len
) {
992 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
995 id
= malloc(sizeof(*id
));
997 err
= got_error_from_errno("malloc");
1000 memcpy(id
->sha1
, iremote_ref
.id
, SHA1_DIGEST_LENGTH
);
1001 refname
= strndup(imsg
.data
+ sizeof(iremote_ref
),
1002 datalen
- sizeof(iremote_ref
));
1003 if (refname
== NULL
) {
1004 err
= got_error_from_errno("strndup");
1007 err
= got_pathlist_insert(&new, remote_refs
,
1011 if (new == NULL
) { /* duplicate which wasn't inserted */
1018 case GOT_IMSG_SEND_PACK_REQUEST
:
1020 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1023 /* got-send-pack is now waiting for a pack file. */
1027 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1038 const struct got_error
*
1039 got_privsep_send_packfd(struct imsgbuf
*ibuf
, int fd
)
1041 return send_fd(ibuf
, GOT_IMSG_SEND_PACKFD
, fd
);
1044 const struct got_error
*
1045 got_privsep_recv_send_progress(int *done
, off_t
*bytes_sent
,
1046 int *success
, char **refname
, struct imsgbuf
*ibuf
)
1048 const struct got_error
*err
= NULL
;
1051 struct got_imsg_send_ref_status iref_status
;
1053 /* Do not reset the current value of 'bytes_sent', it accumulates. */
1058 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1062 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1063 switch (imsg
.hdr
.type
) {
1064 case GOT_IMSG_ERROR
:
1065 if (datalen
< sizeof(struct got_imsg_error
)) {
1066 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1069 err
= recv_imsg_error(&imsg
, datalen
);
1071 case GOT_IMSG_SEND_UPLOAD_PROGRESS
:
1072 if (datalen
< sizeof(*bytes_sent
)) {
1073 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1076 memcpy(bytes_sent
, imsg
.data
, sizeof(*bytes_sent
));
1078 case GOT_IMSG_SEND_REF_STATUS
:
1079 if (datalen
< sizeof(iref_status
)) {
1080 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1083 memcpy(&iref_status
, imsg
.data
, sizeof(iref_status
));
1084 if (datalen
!= sizeof(iref_status
) + iref_status
.name_len
) {
1085 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1088 *success
= iref_status
.success
;
1089 *refname
= strndup(imsg
.data
+ sizeof(iref_status
),
1090 iref_status
.name_len
);
1092 case GOT_IMSG_SEND_DONE
:
1094 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1100 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1108 const struct got_error
*
1109 got_privsep_send_index_pack_req(struct imsgbuf
*ibuf
, uint8_t *pack_sha1
,
1112 const struct got_error
*err
= NULL
;
1114 /* Keep in sync with struct got_imsg_index_pack_request */
1115 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_REQUEST
, 0, 0, fd
,
1116 pack_sha1
, SHA1_DIGEST_LENGTH
) == -1) {
1117 err
= got_error_from_errno("imsg_compose INDEX_REQUEST");
1121 return flush_imsg(ibuf
);
1124 const struct got_error
*
1125 got_privsep_send_index_pack_outfd(struct imsgbuf
*ibuf
, int fd
)
1127 return send_fd(ibuf
, GOT_IMSG_IDXPACK_OUTFD
, fd
);
1130 const struct got_error
*
1131 got_privsep_recv_index_progress(int *done
, int *nobj_total
,
1132 int *nobj_indexed
, int *nobj_loose
, int *nobj_resolved
,
1133 struct imsgbuf
*ibuf
)
1135 const struct got_error
*err
= NULL
;
1137 struct got_imsg_index_pack_progress
*iprogress
;
1145 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1149 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1150 switch (imsg
.hdr
.type
) {
1151 case GOT_IMSG_ERROR
:
1152 if (datalen
< sizeof(struct got_imsg_error
)) {
1153 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1156 err
= recv_imsg_error(&imsg
, datalen
);
1158 case GOT_IMSG_IDXPACK_PROGRESS
:
1159 if (datalen
< sizeof(*iprogress
)) {
1160 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1163 iprogress
= (struct got_imsg_index_pack_progress
*)imsg
.data
;
1164 *nobj_total
= iprogress
->nobj_total
;
1165 *nobj_indexed
= iprogress
->nobj_indexed
;
1166 *nobj_loose
= iprogress
->nobj_loose
;
1167 *nobj_resolved
= iprogress
->nobj_resolved
;
1169 case GOT_IMSG_IDXPACK_DONE
:
1171 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1177 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1185 const struct got_error
*
1186 got_privsep_get_imsg_obj(struct got_object
**obj
, struct imsg
*imsg
,
1187 struct imsgbuf
*ibuf
)
1189 const struct got_error
*err
= NULL
;
1190 struct got_imsg_object
*iobj
;
1191 size_t datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1193 if (datalen
!= sizeof(*iobj
))
1194 return got_error(GOT_ERR_PRIVSEP_LEN
);
1197 *obj
= calloc(1, sizeof(**obj
));
1199 return got_error_from_errno("calloc");
1201 memcpy((*obj
)->id
.sha1
, iobj
->id
, SHA1_DIGEST_LENGTH
);
1202 (*obj
)->type
= iobj
->type
;
1203 (*obj
)->flags
= iobj
->flags
;
1204 (*obj
)->hdrlen
= iobj
->hdrlen
;
1205 (*obj
)->size
= iobj
->size
;
1206 /* path_packfile is handled by caller */
1207 if (iobj
->flags
& GOT_OBJ_FLAG_PACKED
) {
1208 (*obj
)->pack_offset
= iobj
->pack_offset
;
1209 (*obj
)->pack_idx
= iobj
->pack_idx
;
1215 const struct got_error
*
1216 got_privsep_recv_obj(struct got_object
**obj
, struct imsgbuf
*ibuf
)
1218 const struct got_error
*err
= NULL
;
1220 const size_t min_datalen
=
1221 MIN(sizeof(struct got_imsg_error
), sizeof(struct got_imsg_object
));
1225 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1229 switch (imsg
.hdr
.type
) {
1230 case GOT_IMSG_OBJECT
:
1231 err
= got_privsep_get_imsg_obj(obj
, &imsg
, ibuf
);
1234 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1243 static const struct got_error
*
1244 send_commit_logmsg(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
,
1247 const struct got_error
*err
= NULL
;
1248 size_t offset
, remain
;
1251 remain
= logmsg_len
;
1252 while (remain
> 0) {
1253 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1255 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT_LOGMSG
, 0, 0, -1,
1256 commit
->logmsg
+ offset
, n
) == -1) {
1257 err
= got_error_from_errno("imsg_compose "
1262 err
= flush_imsg(ibuf
);
1273 const struct got_error
*
1274 got_privsep_send_commit(struct imsgbuf
*ibuf
, struct got_commit_object
*commit
)
1276 const struct got_error
*err
= NULL
;
1277 struct got_imsg_commit_object
*icommit
;
1280 struct got_object_qid
*qid
;
1281 size_t author_len
= strlen(commit
->author
);
1282 size_t committer_len
= strlen(commit
->committer
);
1283 size_t logmsg_len
= strlen(commit
->logmsg
);
1285 total
= sizeof(*icommit
) + author_len
+ committer_len
+
1286 commit
->nparents
* SHA1_DIGEST_LENGTH
;
1288 buf
= malloc(total
);
1290 return got_error_from_errno("malloc");
1292 icommit
= (struct got_imsg_commit_object
*)buf
;
1293 memcpy(icommit
->tree_id
, commit
->tree_id
->sha1
,
1294 sizeof(icommit
->tree_id
));
1295 icommit
->author_len
= author_len
;
1296 icommit
->author_time
= commit
->author_time
;
1297 icommit
->author_gmtoff
= commit
->author_gmtoff
;
1298 icommit
->committer_len
= committer_len
;
1299 icommit
->committer_time
= commit
->committer_time
;
1300 icommit
->committer_gmtoff
= commit
->committer_gmtoff
;
1301 icommit
->logmsg_len
= logmsg_len
;
1302 icommit
->nparents
= commit
->nparents
;
1304 len
= sizeof(*icommit
);
1305 memcpy(buf
+ len
, commit
->author
, author_len
);
1307 memcpy(buf
+ len
, commit
->committer
, committer_len
);
1308 len
+= committer_len
;
1309 STAILQ_FOREACH(qid
, &commit
->parent_ids
, entry
) {
1310 memcpy(buf
+ len
, qid
->id
, SHA1_DIGEST_LENGTH
);
1311 len
+= SHA1_DIGEST_LENGTH
;
1314 if (imsg_compose(ibuf
, GOT_IMSG_COMMIT
, 0, 0, -1, buf
, len
) == -1) {
1315 err
= got_error_from_errno("imsg_compose COMMIT");
1319 if (logmsg_len
== 0 ||
1320 logmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1321 err
= flush_imsg(ibuf
);
1325 err
= send_commit_logmsg(ibuf
, commit
, logmsg_len
);
1331 static const struct got_error
*
1332 get_commit_from_imsg(struct got_commit_object
**commit
,
1333 struct imsg
*imsg
, size_t datalen
, struct imsgbuf
*ibuf
)
1335 const struct got_error
*err
= NULL
;
1336 struct got_imsg_commit_object
*icommit
;
1340 if (datalen
< sizeof(*icommit
))
1341 return got_error(GOT_ERR_PRIVSEP_LEN
);
1343 icommit
= imsg
->data
;
1344 if (datalen
!= sizeof(*icommit
) + icommit
->author_len
+
1345 icommit
->committer_len
+
1346 icommit
->nparents
* SHA1_DIGEST_LENGTH
)
1347 return got_error(GOT_ERR_PRIVSEP_LEN
);
1349 if (icommit
->nparents
< 0)
1350 return got_error(GOT_ERR_PRIVSEP_LEN
);
1352 len
+= sizeof(*icommit
);
1354 *commit
= got_object_commit_alloc_partial();
1355 if (*commit
== NULL
)
1356 return got_error_from_errno(
1357 "got_object_commit_alloc_partial");
1359 memcpy((*commit
)->tree_id
->sha1
, icommit
->tree_id
,
1360 SHA1_DIGEST_LENGTH
);
1361 (*commit
)->author_time
= icommit
->author_time
;
1362 (*commit
)->author_gmtoff
= icommit
->author_gmtoff
;
1363 (*commit
)->committer_time
= icommit
->committer_time
;
1364 (*commit
)->committer_gmtoff
= icommit
->committer_gmtoff
;
1366 if (icommit
->author_len
== 0) {
1367 (*commit
)->author
= strdup("");
1368 if ((*commit
)->author
== NULL
) {
1369 err
= got_error_from_errno("strdup");
1373 (*commit
)->author
= malloc(icommit
->author_len
+ 1);
1374 if ((*commit
)->author
== NULL
) {
1375 err
= got_error_from_errno("malloc");
1378 memcpy((*commit
)->author
, imsg
->data
+ len
,
1379 icommit
->author_len
);
1380 (*commit
)->author
[icommit
->author_len
] = '\0';
1382 len
+= icommit
->author_len
;
1384 if (icommit
->committer_len
== 0) {
1385 (*commit
)->committer
= strdup("");
1386 if ((*commit
)->committer
== NULL
) {
1387 err
= got_error_from_errno("strdup");
1391 (*commit
)->committer
=
1392 malloc(icommit
->committer_len
+ 1);
1393 if ((*commit
)->committer
== NULL
) {
1394 err
= got_error_from_errno("malloc");
1397 memcpy((*commit
)->committer
, imsg
->data
+ len
,
1398 icommit
->committer_len
);
1399 (*commit
)->committer
[icommit
->committer_len
] = '\0';
1401 len
+= icommit
->committer_len
;
1403 if (icommit
->logmsg_len
== 0) {
1404 (*commit
)->logmsg
= strdup("");
1405 if ((*commit
)->logmsg
== NULL
) {
1406 err
= got_error_from_errno("strdup");
1410 size_t offset
= 0, remain
= icommit
->logmsg_len
;
1412 (*commit
)->logmsg
= malloc(icommit
->logmsg_len
+ 1);
1413 if ((*commit
)->logmsg
== NULL
) {
1414 err
= got_error_from_errno("malloc");
1417 while (remain
> 0) {
1418 struct imsg imsg_log
;
1419 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1422 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1426 if (imsg_log
.hdr
.type
!= GOT_IMSG_COMMIT_LOGMSG
) {
1427 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1431 memcpy((*commit
)->logmsg
+ offset
,
1433 imsg_free(&imsg_log
);
1437 (*commit
)->logmsg
[icommit
->logmsg_len
] = '\0';
1440 for (i
= 0; i
< icommit
->nparents
; i
++) {
1441 struct got_object_qid
*qid
;
1443 err
= got_object_qid_alloc_partial(&qid
);
1446 memcpy(qid
->id
, imsg
->data
+ len
+
1447 i
* SHA1_DIGEST_LENGTH
, sizeof(*qid
->id
));
1448 STAILQ_INSERT_TAIL(&(*commit
)->parent_ids
, qid
, entry
);
1449 (*commit
)->nparents
++;
1453 got_object_commit_close(*commit
);
1459 const struct got_error
*
1460 got_privsep_recv_commit(struct got_commit_object
**commit
, struct imsgbuf
*ibuf
)
1462 const struct got_error
*err
= NULL
;
1465 const size_t min_datalen
=
1466 MIN(sizeof(struct got_imsg_error
),
1467 sizeof(struct got_imsg_commit_object
));
1471 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1475 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1477 switch (imsg
.hdr
.type
) {
1478 case GOT_IMSG_COMMIT
:
1479 err
= get_commit_from_imsg(commit
, &imsg
, datalen
, ibuf
);
1482 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1491 const struct got_error
*
1492 got_privsep_send_tree(struct imsgbuf
*ibuf
, struct got_pathlist_head
*entries
,
1495 const struct got_error
*err
= NULL
;
1496 struct got_imsg_tree_object itree
;
1497 struct got_pathlist_entry
*pe
;
1499 int nimsg
; /* number of imsg queued in ibuf */
1501 itree
.nentries
= nentries
;
1502 if (imsg_compose(ibuf
, GOT_IMSG_TREE
, 0, 0, -1, &itree
, sizeof(itree
))
1504 return got_error_from_errno("imsg_compose TREE");
1506 totlen
= sizeof(itree
);
1508 TAILQ_FOREACH(pe
, entries
, entry
) {
1509 const char *name
= pe
->path
;
1510 struct got_parsed_tree_entry
*pte
= pe
->data
;
1512 size_t namelen
= strlen(name
);
1513 size_t len
= sizeof(struct got_imsg_tree_entry
) + namelen
;
1515 if (len
> MAX_IMSGSIZE
)
1516 return got_error(GOT_ERR_NO_SPACE
);
1519 if (totlen
+ len
>= MAX_IMSGSIZE
- (IMSG_HEADER_SIZE
* nimsg
)) {
1520 err
= flush_imsg(ibuf
);
1526 wbuf
= imsg_create(ibuf
, GOT_IMSG_TREE_ENTRY
, 0, 0, len
);
1528 return got_error_from_errno("imsg_create TREE_ENTRY");
1530 /* Keep in sync with struct got_imsg_tree_object definition! */
1531 if (imsg_add(wbuf
, pte
->id
, SHA1_DIGEST_LENGTH
) == -1) {
1532 err
= got_error_from_errno("imsg_add TREE_ENTRY");
1536 if (imsg_add(wbuf
, &pte
->mode
, sizeof(pte
->mode
)) == -1) {
1537 err
= got_error_from_errno("imsg_add TREE_ENTRY");
1542 if (imsg_add(wbuf
, name
, namelen
) == -1) {
1543 err
= got_error_from_errno("imsg_add TREE_ENTRY");
1549 imsg_close(ibuf
, wbuf
);
1554 return flush_imsg(ibuf
);
1557 const struct got_error
*
1558 got_privsep_recv_tree(struct got_tree_object
**tree
, struct imsgbuf
*ibuf
)
1560 const struct got_error
*err
= NULL
;
1561 const size_t min_datalen
=
1562 MIN(sizeof(struct got_imsg_error
),
1563 sizeof(struct got_imsg_tree_object
));
1564 struct got_imsg_tree_object
*itree
;
1569 err
= read_imsg(ibuf
);
1577 struct got_imsg_tree_entry
*ite
;
1578 struct got_tree_entry
*te
= NULL
;
1580 n
= imsg_get(ibuf
, &imsg
);
1582 if (*tree
&& (*tree
)->nentries
!= nentries
)
1587 if (imsg
.hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
) {
1589 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1593 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1595 switch (imsg
.hdr
.type
) {
1596 case GOT_IMSG_ERROR
:
1597 err
= recv_imsg_error(&imsg
, datalen
);
1600 /* This message should only appear once. */
1601 if (*tree
!= NULL
) {
1602 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1605 if (datalen
!= sizeof(*itree
)) {
1606 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1610 *tree
= malloc(sizeof(**tree
));
1611 if (*tree
== NULL
) {
1612 err
= got_error_from_errno("malloc");
1615 (*tree
)->entries
= calloc(itree
->nentries
,
1616 sizeof(struct got_tree_entry
));
1617 if ((*tree
)->entries
== NULL
) {
1618 err
= got_error_from_errno("malloc");
1621 (*tree
)->nentries
= itree
->nentries
;
1622 (*tree
)->refcnt
= 0;
1624 case GOT_IMSG_TREE_ENTRY
:
1625 /* This message should be preceeded by GOT_IMSG_TREE. */
1626 if (*tree
== NULL
) {
1627 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1630 if (datalen
< sizeof(*ite
) || datalen
> MAX_IMSGSIZE
) {
1631 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1635 /* Remaining data contains the entry's name. */
1636 datalen
-= sizeof(*ite
);
1637 if (datalen
== 0 || datalen
> MAX_IMSGSIZE
) {
1638 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1643 if (datalen
+ 1 > sizeof(te
->name
)) {
1644 err
= got_error(GOT_ERR_NO_SPACE
);
1647 te
= &(*tree
)->entries
[nentries
];
1648 memcpy(te
->name
, imsg
.data
+ sizeof(*ite
), datalen
);
1649 te
->name
[datalen
] = '\0';
1651 memcpy(te
->id
.sha1
, ite
->id
, SHA1_DIGEST_LENGTH
);
1652 te
->mode
= ite
->mode
;
1657 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1666 if (*tree
&& (*tree
)->nentries
!= nentries
) {
1668 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1669 got_object_tree_close(*tree
);
1676 const struct got_error
*
1677 got_privsep_send_blob(struct imsgbuf
*ibuf
, size_t size
, size_t hdrlen
,
1678 const uint8_t *data
)
1680 struct got_imsg_blob iblob
;
1683 iblob
.hdrlen
= hdrlen
;
1688 if (size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
)
1689 return got_error(GOT_ERR_NO_SPACE
);
1691 buf
= malloc(sizeof(iblob
) + size
);
1693 return got_error_from_errno("malloc");
1695 memcpy(buf
, &iblob
, sizeof(iblob
));
1696 memcpy(buf
+ sizeof(iblob
), data
, size
);
1697 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, buf
,
1698 sizeof(iblob
) + size
) == -1) {
1700 return got_error_from_errno("imsg_compose BLOB");
1704 /* Data has already been written to file descriptor. */
1705 if (imsg_compose(ibuf
, GOT_IMSG_BLOB
, 0, 0, -1, &iblob
,
1706 sizeof(iblob
)) == -1)
1707 return got_error_from_errno("imsg_compose BLOB");
1711 return flush_imsg(ibuf
);
1714 const struct got_error
*
1715 got_privsep_recv_blob(uint8_t **outbuf
, size_t *size
, size_t *hdrlen
,
1716 struct imsgbuf
*ibuf
)
1718 const struct got_error
*err
= NULL
;
1720 struct got_imsg_blob
*iblob
;
1725 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
1729 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1731 switch (imsg
.hdr
.type
) {
1733 if (datalen
< sizeof(*iblob
)) {
1734 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1738 *size
= iblob
->size
;
1739 *hdrlen
= iblob
->hdrlen
;
1741 if (datalen
== sizeof(*iblob
)) {
1742 /* Data has been written to file descriptor. */
1746 if (*size
> GOT_PRIVSEP_INLINE_BLOB_DATA_MAX
) {
1747 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1751 *outbuf
= malloc(*size
);
1752 if (*outbuf
== NULL
) {
1753 err
= got_error_from_errno("malloc");
1756 memcpy(*outbuf
, imsg
.data
+ sizeof(*iblob
), *size
);
1759 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1768 static const struct got_error
*
1769 send_tagmsg(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
, size_t tagmsg_len
)
1771 const struct got_error
*err
= NULL
;
1772 size_t offset
, remain
;
1775 remain
= tagmsg_len
;
1776 while (remain
> 0) {
1777 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
, remain
);
1779 if (imsg_compose(ibuf
, GOT_IMSG_TAG_TAGMSG
, 0, 0, -1,
1780 tag
->tagmsg
+ offset
, n
) == -1) {
1781 err
= got_error_from_errno("imsg_compose TAG_TAGMSG");
1785 err
= flush_imsg(ibuf
);
1796 const struct got_error
*
1797 got_privsep_send_tag(struct imsgbuf
*ibuf
, struct got_tag_object
*tag
)
1799 const struct got_error
*err
= NULL
;
1800 struct got_imsg_tag_object
*itag
;
1803 size_t tag_len
= strlen(tag
->tag
);
1804 size_t tagger_len
= strlen(tag
->tagger
);
1805 size_t tagmsg_len
= strlen(tag
->tagmsg
);
1807 total
= sizeof(*itag
) + tag_len
+ tagger_len
+ tagmsg_len
;
1809 buf
= malloc(total
);
1811 return got_error_from_errno("malloc");
1813 itag
= (struct got_imsg_tag_object
*)buf
;
1814 memcpy(itag
->id
, tag
->id
.sha1
, sizeof(itag
->id
));
1815 itag
->obj_type
= tag
->obj_type
;
1816 itag
->tag_len
= tag_len
;
1817 itag
->tagger_len
= tagger_len
;
1818 itag
->tagger_time
= tag
->tagger_time
;
1819 itag
->tagger_gmtoff
= tag
->tagger_gmtoff
;
1820 itag
->tagmsg_len
= tagmsg_len
;
1822 len
= sizeof(*itag
);
1823 memcpy(buf
+ len
, tag
->tag
, tag_len
);
1825 memcpy(buf
+ len
, tag
->tagger
, tagger_len
);
1828 if (imsg_compose(ibuf
, GOT_IMSG_TAG
, 0, 0, -1, buf
, len
) == -1) {
1829 err
= got_error_from_errno("imsg_compose TAG");
1833 if (tagmsg_len
== 0 ||
1834 tagmsg_len
+ len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
1835 err
= flush_imsg(ibuf
);
1839 err
= send_tagmsg(ibuf
, tag
, tagmsg_len
);
1845 const struct got_error
*
1846 got_privsep_recv_tag(struct got_tag_object
**tag
, struct imsgbuf
*ibuf
)
1848 const struct got_error
*err
= NULL
;
1850 struct got_imsg_tag_object
*itag
;
1851 size_t len
, datalen
;
1852 const size_t min_datalen
=
1853 MIN(sizeof(struct got_imsg_error
),
1854 sizeof(struct got_imsg_tag_object
));
1858 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
1862 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1865 switch (imsg
.hdr
.type
) {
1867 if (datalen
< sizeof(*itag
)) {
1868 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1872 if (datalen
!= sizeof(*itag
) + itag
->tag_len
+
1874 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1877 len
+= sizeof(*itag
);
1879 *tag
= calloc(1, sizeof(**tag
));
1881 err
= got_error_from_errno("calloc");
1885 memcpy((*tag
)->id
.sha1
, itag
->id
, SHA1_DIGEST_LENGTH
);
1887 if (itag
->tag_len
== 0) {
1888 (*tag
)->tag
= strdup("");
1889 if ((*tag
)->tag
== NULL
) {
1890 err
= got_error_from_errno("strdup");
1894 (*tag
)->tag
= malloc(itag
->tag_len
+ 1);
1895 if ((*tag
)->tag
== NULL
) {
1896 err
= got_error_from_errno("malloc");
1899 memcpy((*tag
)->tag
, imsg
.data
+ len
,
1901 (*tag
)->tag
[itag
->tag_len
] = '\0';
1903 len
+= itag
->tag_len
;
1905 (*tag
)->obj_type
= itag
->obj_type
;
1906 (*tag
)->tagger_time
= itag
->tagger_time
;
1907 (*tag
)->tagger_gmtoff
= itag
->tagger_gmtoff
;
1909 if (itag
->tagger_len
== 0) {
1910 (*tag
)->tagger
= strdup("");
1911 if ((*tag
)->tagger
== NULL
) {
1912 err
= got_error_from_errno("strdup");
1916 (*tag
)->tagger
= malloc(itag
->tagger_len
+ 1);
1917 if ((*tag
)->tagger
== NULL
) {
1918 err
= got_error_from_errno("malloc");
1921 memcpy((*tag
)->tagger
, imsg
.data
+ len
,
1923 (*tag
)->tagger
[itag
->tagger_len
] = '\0';
1925 len
+= itag
->tagger_len
;
1927 if (itag
->tagmsg_len
== 0) {
1928 (*tag
)->tagmsg
= strdup("");
1929 if ((*tag
)->tagmsg
== NULL
) {
1930 err
= got_error_from_errno("strdup");
1934 size_t offset
= 0, remain
= itag
->tagmsg_len
;
1936 (*tag
)->tagmsg
= malloc(itag
->tagmsg_len
+ 1);
1937 if ((*tag
)->tagmsg
== NULL
) {
1938 err
= got_error_from_errno("malloc");
1941 while (remain
> 0) {
1942 struct imsg imsg_log
;
1943 size_t n
= MIN(MAX_IMSGSIZE
- IMSG_HEADER_SIZE
,
1946 err
= got_privsep_recv_imsg(&imsg_log
, ibuf
, n
);
1950 if (imsg_log
.hdr
.type
!= GOT_IMSG_TAG_TAGMSG
)
1951 return got_error(GOT_ERR_PRIVSEP_MSG
);
1953 memcpy((*tag
)->tagmsg
+ offset
, imsg_log
.data
,
1955 imsg_free(&imsg_log
);
1959 (*tag
)->tagmsg
[itag
->tagmsg_len
] = '\0';
1964 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1973 const struct got_error
*
1974 got_privsep_init_pack_child(struct imsgbuf
*ibuf
, struct got_pack
*pack
,
1975 struct got_packidx
*packidx
)
1977 const struct got_error
*err
= NULL
;
1978 struct got_imsg_packidx ipackidx
;
1979 struct got_imsg_pack ipack
;
1982 ipackidx
.len
= packidx
->len
;
1983 ipackidx
.packfile_size
= pack
->filesize
;
1984 fd
= dup(packidx
->fd
);
1986 return got_error_from_errno("dup");
1988 if (imsg_compose(ibuf
, GOT_IMSG_PACKIDX
, 0, 0, fd
, &ipackidx
,
1989 sizeof(ipackidx
)) == -1) {
1990 err
= got_error_from_errno("imsg_compose PACKIDX");
1995 if (strlcpy(ipack
.path_packfile
, pack
->path_packfile
,
1996 sizeof(ipack
.path_packfile
)) >= sizeof(ipack
.path_packfile
))
1997 return got_error(GOT_ERR_NO_SPACE
);
1998 ipack
.filesize
= pack
->filesize
;
2002 return got_error_from_errno("dup");
2004 if (imsg_compose(ibuf
, GOT_IMSG_PACK
, 0, 0, fd
, &ipack
, sizeof(ipack
))
2006 err
= got_error_from_errno("imsg_compose PACK");
2011 return flush_imsg(ibuf
);
2014 const struct got_error
*
2015 got_privsep_send_packed_obj_req(struct imsgbuf
*ibuf
, int idx
,
2016 struct got_object_id
*id
)
2018 struct got_imsg_packed_object iobj
;
2021 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
2023 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_OBJECT_REQUEST
, 0, 0, -1,
2024 &iobj
, sizeof(iobj
)) == -1)
2025 return got_error_from_errno("imsg_compose "
2026 "PACKED_OBJECT_REQUEST");
2028 return flush_imsg(ibuf
);
2031 const struct got_error
*
2032 got_privsep_send_packed_raw_obj_req(struct imsgbuf
*ibuf
, int idx
,
2033 struct got_object_id
*id
)
2035 struct got_imsg_packed_object iobj
;
2038 memcpy(iobj
.id
, id
->sha1
, sizeof(iobj
.id
));
2040 if (imsg_compose(ibuf
, GOT_IMSG_PACKED_RAW_OBJECT_REQUEST
, 0, 0, -1,
2041 &iobj
, sizeof(iobj
)) == -1)
2042 return got_error_from_errno("imsg_compose "
2043 "PACKED_OBJECT_REQUEST");
2045 return flush_imsg(ibuf
);
2048 const struct got_error
*
2049 got_privsep_send_gitconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2051 const struct got_error
*err
= NULL
;
2053 if (imsg_compose(ibuf
, GOT_IMSG_GITCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2055 err
= got_error_from_errno("imsg_compose "
2056 "GITCONFIG_PARSE_REQUEST");
2061 return flush_imsg(ibuf
);
2064 const struct got_error
*
2065 got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf
*ibuf
)
2067 if (imsg_compose(ibuf
,
2068 GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST
, 0, 0, -1,
2070 return got_error_from_errno("imsg_compose "
2071 "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
2073 return flush_imsg(ibuf
);
2076 const struct got_error
*
2077 got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf
*ibuf
)
2079 if (imsg_compose(ibuf
,
2080 GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST
, 0, 0, -1,
2082 return got_error_from_errno("imsg_compose "
2083 "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
2085 return flush_imsg(ibuf
);
2089 const struct got_error
*
2090 got_privsep_send_gitconfig_author_name_req(struct imsgbuf
*ibuf
)
2092 if (imsg_compose(ibuf
,
2093 GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2094 return got_error_from_errno("imsg_compose "
2095 "GITCONFIG_AUTHOR_NAME_REQUEST");
2097 return flush_imsg(ibuf
);
2100 const struct got_error
*
2101 got_privsep_send_gitconfig_author_email_req(struct imsgbuf
*ibuf
)
2103 if (imsg_compose(ibuf
,
2104 GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2105 return got_error_from_errno("imsg_compose "
2106 "GITCONFIG_AUTHOR_EMAIL_REQUEST");
2108 return flush_imsg(ibuf
);
2111 const struct got_error
*
2112 got_privsep_send_gitconfig_remotes_req(struct imsgbuf
*ibuf
)
2114 if (imsg_compose(ibuf
,
2115 GOT_IMSG_GITCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2116 return got_error_from_errno("imsg_compose "
2117 "GITCONFIG_REMOTE_REQUEST");
2119 return flush_imsg(ibuf
);
2122 const struct got_error
*
2123 got_privsep_send_gitconfig_owner_req(struct imsgbuf
*ibuf
)
2125 if (imsg_compose(ibuf
,
2126 GOT_IMSG_GITCONFIG_OWNER_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2127 return got_error_from_errno("imsg_compose "
2128 "GITCONFIG_OWNER_REQUEST");
2130 return flush_imsg(ibuf
);
2133 const struct got_error
*
2134 got_privsep_recv_gitconfig_str(char **str
, struct imsgbuf
*ibuf
)
2136 const struct got_error
*err
= NULL
;
2139 const size_t min_datalen
= 0;
2143 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2146 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2148 switch (imsg
.hdr
.type
) {
2149 case GOT_IMSG_GITCONFIG_STR_VAL
:
2152 /* datalen does not include terminating \0 */
2153 *str
= malloc(datalen
+ 1);
2155 err
= got_error_from_errno("malloc");
2158 memcpy(*str
, imsg
.data
, datalen
);
2159 (*str
)[datalen
] = '\0';
2162 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2170 const struct got_error
*
2171 got_privsep_recv_gitconfig_int(int *val
, struct imsgbuf
*ibuf
)
2173 const struct got_error
*err
= NULL
;
2176 const size_t min_datalen
=
2177 MIN(sizeof(struct got_imsg_error
), sizeof(int));
2181 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2184 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2186 switch (imsg
.hdr
.type
) {
2187 case GOT_IMSG_GITCONFIG_INT_VAL
:
2188 if (datalen
!= sizeof(*val
)) {
2189 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2192 memcpy(val
, imsg
.data
, sizeof(*val
));
2195 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2204 free_remote_data(struct got_remote_repo
*remote
)
2209 free(remote
->fetch_url
);
2210 free(remote
->send_url
);
2211 for (i
= 0; i
< remote
->nfetch_branches
; i
++)
2212 free(remote
->fetch_branches
[i
]);
2213 free(remote
->fetch_branches
);
2214 for (i
= 0; i
< remote
->nsend_branches
; i
++)
2215 free(remote
->send_branches
[i
]);
2216 free(remote
->send_branches
);
2217 for (i
= 0; i
< remote
->nfetch_refs
; i
++)
2218 free(remote
->fetch_refs
[i
]);
2219 free(remote
->fetch_refs
);
2222 const struct got_error
*
2223 got_privsep_recv_gitconfig_remotes(struct got_remote_repo
**remotes
,
2224 int *nremotes
, struct imsgbuf
*ibuf
)
2226 const struct got_error
*err
= NULL
;
2229 struct got_imsg_remotes iremotes
;
2230 struct got_imsg_remote iremote
;
2234 iremotes
.nremotes
= 0;
2236 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremotes
));
2239 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2241 switch (imsg
.hdr
.type
) {
2242 case GOT_IMSG_GITCONFIG_REMOTES
:
2243 if (datalen
!= sizeof(iremotes
)) {
2244 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2247 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2248 if (iremotes
.nremotes
== 0) {
2255 return got_error(GOT_ERR_PRIVSEP_MSG
);
2260 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2261 if (*remotes
== NULL
)
2262 return got_error_from_errno("recallocarray");
2264 while (*nremotes
< iremotes
.nremotes
) {
2265 struct got_remote_repo
*remote
;
2267 err
= got_privsep_recv_imsg(&imsg
, ibuf
, sizeof(iremote
));
2270 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2272 switch (imsg
.hdr
.type
) {
2273 case GOT_IMSG_GITCONFIG_REMOTE
:
2274 remote
= &(*remotes
)[*nremotes
];
2275 memset(remote
, 0, sizeof(*remote
));
2276 if (datalen
< sizeof(iremote
)) {
2277 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2280 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2281 if (iremote
.name_len
== 0 ||
2282 iremote
.fetch_url_len
== 0 ||
2283 iremote
.send_url_len
== 0 ||
2284 (sizeof(iremote
) + iremote
.name_len
+
2285 iremote
.fetch_url_len
+ iremote
.send_url_len
) > datalen
) {
2286 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2289 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2291 if (remote
->name
== NULL
) {
2292 err
= got_error_from_errno("strndup");
2295 remote
->fetch_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2296 iremote
.name_len
, iremote
.fetch_url_len
);
2297 if (remote
->fetch_url
== NULL
) {
2298 err
= got_error_from_errno("strndup");
2299 free_remote_data(remote
);
2302 remote
->send_url
= strndup(imsg
.data
+ sizeof(iremote
) +
2303 iremote
.name_len
+ iremote
.fetch_url_len
,
2304 iremote
.send_url_len
);
2305 if (remote
->send_url
== NULL
) {
2306 err
= got_error_from_errno("strndup");
2307 free_remote_data(remote
);
2310 remote
->mirror_references
= iremote
.mirror_references
;
2311 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2312 remote
->nfetch_branches
= 0;
2313 remote
->fetch_branches
= NULL
;
2314 remote
->nsend_branches
= 0;
2315 remote
->send_branches
= NULL
;
2316 remote
->nfetch_refs
= 0;
2317 remote
->fetch_refs
= NULL
;
2321 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2332 for (i
= 0; i
< *nremotes
; i
++)
2333 free_remote_data(&(*remotes
)[i
]);
2341 const struct got_error
*
2342 got_privsep_send_gotconfig_parse_req(struct imsgbuf
*ibuf
, int fd
)
2344 const struct got_error
*err
= NULL
;
2346 if (imsg_compose(ibuf
, GOT_IMSG_GOTCONFIG_PARSE_REQUEST
, 0, 0, fd
,
2348 err
= got_error_from_errno("imsg_compose "
2349 "GOTCONFIG_PARSE_REQUEST");
2354 return flush_imsg(ibuf
);
2357 const struct got_error
*
2358 got_privsep_send_gotconfig_author_req(struct imsgbuf
*ibuf
)
2360 if (imsg_compose(ibuf
,
2361 GOT_IMSG_GOTCONFIG_AUTHOR_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2362 return got_error_from_errno("imsg_compose "
2363 "GOTCONFIG_AUTHOR_REQUEST");
2365 return flush_imsg(ibuf
);
2368 const struct got_error
*
2369 got_privsep_send_gotconfig_remotes_req(struct imsgbuf
*ibuf
)
2371 if (imsg_compose(ibuf
,
2372 GOT_IMSG_GOTCONFIG_REMOTES_REQUEST
, 0, 0, -1, NULL
, 0) == -1)
2373 return got_error_from_errno("imsg_compose "
2374 "GOTCONFIG_REMOTE_REQUEST");
2376 return flush_imsg(ibuf
);
2379 const struct got_error
*
2380 got_privsep_recv_gotconfig_str(char **str
, struct imsgbuf
*ibuf
)
2382 const struct got_error
*err
= NULL
;
2385 const size_t min_datalen
= 0;
2389 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2392 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2394 switch (imsg
.hdr
.type
) {
2395 case GOT_IMSG_ERROR
:
2396 if (datalen
< sizeof(struct got_imsg_error
)) {
2397 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2400 err
= recv_imsg_error(&imsg
, datalen
);
2402 case GOT_IMSG_GOTCONFIG_STR_VAL
:
2405 /* datalen does not include terminating \0 */
2406 *str
= malloc(datalen
+ 1);
2408 err
= got_error_from_errno("malloc");
2411 memcpy(*str
, imsg
.data
, datalen
);
2412 (*str
)[datalen
] = '\0';
2415 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2423 const struct got_error
*
2424 got_privsep_recv_gotconfig_remotes(struct got_remote_repo
**remotes
,
2425 int *nremotes
, struct imsgbuf
*ibuf
)
2427 const struct got_error
*err
= NULL
;
2430 struct got_imsg_remotes iremotes
;
2431 struct got_imsg_remote iremote
;
2432 const size_t min_datalen
=
2433 MIN(sizeof(struct got_imsg_error
), sizeof(iremotes
));
2437 iremotes
.nremotes
= 0;
2439 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2442 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2444 switch (imsg
.hdr
.type
) {
2445 case GOT_IMSG_ERROR
:
2446 if (datalen
< sizeof(struct got_imsg_error
)) {
2447 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2450 err
= recv_imsg_error(&imsg
, datalen
);
2452 case GOT_IMSG_GOTCONFIG_REMOTES
:
2453 if (datalen
!= sizeof(iremotes
)) {
2454 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2457 memcpy(&iremotes
, imsg
.data
, sizeof(iremotes
));
2458 if (iremotes
.nremotes
== 0) {
2465 return got_error(GOT_ERR_PRIVSEP_MSG
);
2470 *remotes
= recallocarray(NULL
, 0, iremotes
.nremotes
, sizeof(**remotes
));
2471 if (*remotes
== NULL
)
2472 return got_error_from_errno("recallocarray");
2474 while (*nremotes
< iremotes
.nremotes
) {
2475 struct got_remote_repo
*remote
;
2476 const size_t min_datalen
=
2477 MIN(sizeof(struct got_imsg_error
), sizeof(iremote
));
2480 err
= got_privsep_recv_imsg(&imsg
, ibuf
, min_datalen
);
2483 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2485 switch (imsg
.hdr
.type
) {
2486 case GOT_IMSG_ERROR
:
2487 if (datalen
< sizeof(struct got_imsg_error
)) {
2488 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2491 err
= recv_imsg_error(&imsg
, datalen
);
2493 case GOT_IMSG_GOTCONFIG_REMOTE
:
2494 remote
= &(*remotes
)[*nremotes
];
2495 memset(remote
, 0, sizeof(*remote
));
2496 if (datalen
< sizeof(iremote
)) {
2497 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2500 memcpy(&iremote
, imsg
.data
, sizeof(iremote
));
2501 if (iremote
.name_len
== 0 ||
2502 (iremote
.fetch_url_len
== 0 &&
2503 iremote
.send_url_len
== 0) ||
2504 (sizeof(iremote
) + iremote
.name_len
+
2505 iremote
.fetch_url_len
+ iremote
.send_url_len
) >
2507 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2510 remote
->name
= strndup(imsg
.data
+ sizeof(iremote
),
2512 if (remote
->name
== NULL
) {
2513 err
= got_error_from_errno("strndup");
2516 remote
->fetch_url
= strndup(imsg
.data
+
2517 sizeof(iremote
) + iremote
.name_len
,
2518 iremote
.fetch_url_len
);
2519 if (remote
->fetch_url
== NULL
) {
2520 err
= got_error_from_errno("strndup");
2521 free_remote_data(remote
);
2524 remote
->send_url
= strndup(imsg
.data
+
2525 sizeof(iremote
) + iremote
.name_len
+
2526 iremote
.fetch_url_len
, iremote
.send_url_len
);
2527 if (remote
->send_url
== NULL
) {
2528 err
= got_error_from_errno("strndup");
2529 free_remote_data(remote
);
2532 remote
->mirror_references
= iremote
.mirror_references
;
2533 remote
->fetch_all_branches
= iremote
.fetch_all_branches
;
2534 if (iremote
.nfetch_branches
> 0) {
2535 remote
->fetch_branches
= recallocarray(NULL
, 0,
2536 iremote
.nfetch_branches
, sizeof(char *));
2537 if (remote
->fetch_branches
== NULL
) {
2538 err
= got_error_from_errno("calloc");
2539 free_remote_data(remote
);
2543 remote
->nfetch_branches
= 0;
2544 for (i
= 0; i
< iremote
.nfetch_branches
; i
++) {
2546 err
= got_privsep_recv_gotconfig_str(&branch
,
2549 free_remote_data(remote
);
2552 remote
->fetch_branches
[i
] = branch
;
2553 remote
->nfetch_branches
++;
2555 if (iremote
.nsend_branches
> 0) {
2556 remote
->send_branches
= recallocarray(NULL
, 0,
2557 iremote
.nsend_branches
, sizeof(char *));
2558 if (remote
->send_branches
== NULL
) {
2559 err
= got_error_from_errno("calloc");
2560 free_remote_data(remote
);
2564 remote
->nsend_branches
= 0;
2565 for (i
= 0; i
< iremote
.nsend_branches
; i
++) {
2567 err
= got_privsep_recv_gotconfig_str(&branch
,
2570 free_remote_data(remote
);
2573 remote
->send_branches
[i
] = branch
;
2574 remote
->nsend_branches
++;
2576 if (iremote
.nfetch_refs
> 0) {
2577 remote
->fetch_refs
= recallocarray(NULL
, 0,
2578 iremote
.nfetch_refs
, sizeof(char *));
2579 if (remote
->fetch_refs
== NULL
) {
2580 err
= got_error_from_errno("calloc");
2581 free_remote_data(remote
);
2585 remote
->nfetch_refs
= 0;
2586 for (i
= 0; i
< iremote
.nfetch_refs
; i
++) {
2588 err
= got_privsep_recv_gotconfig_str(&ref
,
2591 free_remote_data(remote
);
2594 remote
->fetch_refs
[i
] = ref
;
2595 remote
->nfetch_refs
++;
2600 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2611 for (i
= 0; i
< *nremotes
; i
++)
2612 free_remote_data(&(*remotes
)[i
]);
2620 const struct got_error
*
2621 got_privsep_send_commit_traversal_request(struct imsgbuf
*ibuf
,
2622 struct got_object_id
*id
, int idx
, const char *path
)
2624 const struct got_error
*err
= NULL
;
2626 size_t path_len
= strlen(path
) + 1;
2628 wbuf
= imsg_create(ibuf
, GOT_IMSG_COMMIT_TRAVERSAL_REQUEST
, 0, 0,
2629 sizeof(struct got_imsg_commit_traversal_request
) + path_len
);
2631 return got_error_from_errno(
2632 "imsg_create COMMIT_TRAVERSAL_REQUEST");
2633 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1) {
2634 err
= got_error_from_errno("imsg_add COMMIT_TRAVERSAL_REQUEST");
2638 if (imsg_add(wbuf
, &idx
, sizeof(idx
)) == -1) {
2639 err
= got_error_from_errno("imsg_add COMMIT_TRAVERSAL_REQUEST");
2643 if (imsg_add(wbuf
, path
, path_len
) == -1) {
2644 err
= got_error_from_errno("imsg_add COMMIT_TRAVERSAL_REQUEST");
2650 imsg_close(ibuf
, wbuf
);
2652 return flush_imsg(ibuf
);
2655 const struct got_error
*
2656 got_privsep_recv_traversed_commits(struct got_commit_object
**changed_commit
,
2657 struct got_object_id
**changed_commit_id
,
2658 struct got_object_id_queue
*commit_ids
, struct imsgbuf
*ibuf
)
2660 const struct got_error
*err
= NULL
;
2662 struct got_imsg_traversed_commits
*icommits
;
2666 *changed_commit
= NULL
;
2667 *changed_commit_id
= NULL
;
2670 err
= got_privsep_recv_imsg(&imsg
, ibuf
, 0);
2674 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
2675 switch (imsg
.hdr
.type
) {
2676 case GOT_IMSG_TRAVERSED_COMMITS
:
2677 icommits
= imsg
.data
;
2678 if (datalen
!= sizeof(*icommits
) +
2679 icommits
->ncommits
* SHA1_DIGEST_LENGTH
) {
2680 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2683 for (i
= 0; i
< icommits
->ncommits
; i
++) {
2684 struct got_object_qid
*qid
;
2685 uint8_t *sha1
= (uint8_t *)imsg
.data
+
2686 sizeof(*icommits
) + i
* SHA1_DIGEST_LENGTH
;
2687 err
= got_object_qid_alloc_partial(&qid
);
2690 memcpy(qid
->id
->sha1
, sha1
, SHA1_DIGEST_LENGTH
);
2691 STAILQ_INSERT_TAIL(commit_ids
, qid
, entry
);
2693 /* The last commit may contain a change. */
2694 if (i
== icommits
->ncommits
- 1) {
2695 *changed_commit_id
=
2696 got_object_id_dup(qid
->id
);
2697 if (*changed_commit_id
== NULL
) {
2698 err
= got_error_from_errno(
2699 "got_object_id_dup");
2705 case GOT_IMSG_COMMIT
:
2706 if (*changed_commit_id
== NULL
) {
2707 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2710 err
= get_commit_from_imsg(changed_commit
, &imsg
,
2713 case GOT_IMSG_COMMIT_TRAVERSAL_DONE
:
2717 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2727 got_object_id_queue_free(commit_ids
);
2731 const struct got_error
*
2732 got_privsep_unveil_exec_helpers(void)
2734 const char *helpers
[] = {
2735 GOT_PATH_PROG_READ_PACK
,
2736 GOT_PATH_PROG_READ_OBJECT
,
2737 GOT_PATH_PROG_READ_COMMIT
,
2738 GOT_PATH_PROG_READ_TREE
,
2739 GOT_PATH_PROG_READ_BLOB
,
2740 GOT_PATH_PROG_READ_TAG
,
2741 GOT_PATH_PROG_READ_GITCONFIG
,
2742 GOT_PATH_PROG_READ_GOTCONFIG
,
2743 GOT_PATH_PROG_FETCH_PACK
,
2744 GOT_PATH_PROG_INDEX_PACK
,
2745 GOT_PATH_PROG_SEND_PACK
,
2749 for (i
= 0; i
< nitems(helpers
); i
++) {
2750 if (unveil(helpers
[i
], "x") == 0)
2752 return got_error_from_errno2("unveil", helpers
[i
]);
2759 got_privsep_exec_child(int imsg_fds
[2], const char *path
, const char *repo_path
)
2761 if (close(imsg_fds
[0]) == -1) {
2762 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
2766 if (dup2(imsg_fds
[1], GOT_IMSG_FD_CHILD
) == -1) {
2767 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
2770 if (closefrom(GOT_IMSG_FD_CHILD
+ 1) == -1) {
2771 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(errno
));
2775 if (execl(path
, path
, repo_path
, (char *)NULL
) == -1) {
2776 fprintf(stderr
, "%s: %s: %s\n", getprogname(), path
,