2 * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "got_compat.h"
19 #include <sys/types.h>
20 #include <sys/queue.h>
38 #include "got_error.h"
39 #include "got_object.h"
41 #include "got_version.h"
42 #include "got_fetch.h"
43 #include "got_reference.h"
45 #include "got_lib_hash.h"
46 #include "got_lib_delta.h"
47 #include "got_lib_object.h"
48 #include "got_lib_object_parse.h"
49 #include "got_lib_privsep.h"
50 #include "got_lib_pack.h"
51 #include "got_lib_pkt.h"
52 #include "got_lib_gitproto.h"
53 #include "got_lib_ratelimit.h"
56 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
60 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
63 struct got_object
*indexed
;
66 static const struct got_capability got_capabilities
[] = {
67 { GOT_CAPA_AGENT
, "got/" GOT_VERSION_STR
},
68 { GOT_CAPA_OFS_DELTA
, NULL
},
69 { GOT_CAPA_SIDE_BAND_64K
, NULL
},
73 match_remote_ref(struct got_pathlist_head
*have_refs
,
74 struct got_object_id
*my_id
, const char *refname
)
76 struct got_pathlist_entry
*pe
;
78 /* XXX zero-hash signifies we don't have this ref;
79 * we should use a flag instead */
80 memset(my_id
, 0, sizeof(*my_id
));
82 TAILQ_FOREACH(pe
, have_refs
, entry
) {
83 struct got_object_id
*id
= pe
->data
;
84 if (strcmp(pe
->path
, refname
) == 0) {
85 memcpy(my_id
, id
, sizeof(*my_id
));
92 match_branch(const char *branch
, const char *wanted_branch
)
94 if (strncmp(branch
, "refs/heads/", 11) != 0)
97 if (strncmp(wanted_branch
, "refs/heads/", 11) == 0)
100 return (strcmp(branch
+ 11, wanted_branch
) == 0);
104 match_wanted_ref(const char *refname
, const char *wanted_ref
)
106 if (strncmp(refname
, "refs/", 5) != 0)
111 * Prevent fetching of references that won't make any
112 * sense outside of the remote repository's context.
114 if (strncmp(refname
, "got/", 4) == 0)
116 if (strncmp(refname
, "remotes/", 8) == 0)
119 if (strncmp(wanted_ref
, "refs/", 5) == 0)
122 /* Allow prefix match. */
123 if (got_path_is_child(refname
, wanted_ref
, strlen(wanted_ref
)))
126 /* Allow exact match. */
127 return (strcmp(refname
, wanted_ref
) == 0);
130 static const struct got_error
*
131 send_fetch_server_progress(struct imsgbuf
*ibuf
, const char *msg
, size_t msglen
)
133 if (msglen
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
134 return got_error(GOT_ERR_NO_SPACE
);
139 if (imsg_compose(ibuf
, GOT_IMSG_FETCH_SERVER_PROGRESS
, 0, 0, -1,
141 return got_error_from_errno(
142 "imsg_compose FETCH_SERVER_PROGRESS");
144 return got_privsep_flush_imsg(ibuf
);
147 static const struct got_error
*
148 send_fetch_download_progress(struct imsgbuf
*ibuf
, off_t bytes
,
149 struct got_ratelimit
*rl
)
151 const struct got_error
*err
;
155 err
= got_ratelimit_check(&elapsed
, rl
);
160 if (imsg_compose(ibuf
, GOT_IMSG_FETCH_DOWNLOAD_PROGRESS
, 0, 0, -1,
161 &bytes
, sizeof(bytes
)) == -1)
162 return got_error_from_errno(
163 "imsg_compose FETCH_DOWNLOAD_PROGRESS");
165 return got_privsep_flush_imsg(ibuf
);
168 static const struct got_error
*
169 send_fetch_done(struct imsgbuf
*ibuf
, uint8_t *pack_sha1
)
171 if (imsg_compose(ibuf
, GOT_IMSG_FETCH_DONE
, 0, 0, -1,
172 pack_sha1
, SHA1_DIGEST_LENGTH
) == -1)
173 return got_error_from_errno("imsg_compose FETCH");
174 return got_privsep_flush_imsg(ibuf
);
177 static const struct got_error
*
178 fetch_progress(struct imsgbuf
*ibuf
, const char *buf
, size_t len
)
186 * Truncate messages which exceed the maximum imsg payload size.
187 * Server may send up to 64k.
189 if (len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
190 len
= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
;
192 /* Only allow printable ASCII. */
193 for (i
= 0; i
< len
; i
++) {
194 if (isprint((unsigned char)buf
[i
]) ||
195 isspace((unsigned char)buf
[i
]))
197 return got_error_msg(GOT_ERR_BAD_PACKET
,
198 "non-printable progress message received from server");
201 return send_fetch_server_progress(ibuf
, buf
, len
);
204 static const struct got_error
*
205 fetch_error(const char *buf
, size_t len
)
207 static char msg
[1024];
210 for (i
= 0; i
< len
&& i
< sizeof(msg
) - 1; i
++) {
211 if (!isprint((unsigned char)buf
[i
]))
212 return got_error_msg(GOT_ERR_BAD_PACKET
,
213 "non-printable error message received from server");
217 return got_error_msg(GOT_ERR_FETCH_FAILED
, msg
);
220 static const struct got_error
*
221 send_fetch_symrefs(struct imsgbuf
*ibuf
, struct got_pathlist_head
*symrefs
)
224 size_t len
, nsymrefs
= 0;
225 struct got_pathlist_entry
*pe
;
227 len
= sizeof(struct got_imsg_fetch_symrefs
);
228 TAILQ_FOREACH(pe
, symrefs
, entry
) {
229 const char *target
= pe
->data
;
230 len
+= sizeof(struct got_imsg_fetch_symref
) +
231 pe
->path_len
+ strlen(target
);
235 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
236 return got_error(GOT_ERR_NO_SPACE
);
238 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_SYMREFS
, 0, 0, len
);
240 return got_error_from_errno("imsg_create FETCH_SYMREFS");
242 /* Keep in sync with struct got_imsg_fetch_symrefs definition! */
243 if (imsg_add(wbuf
, &nsymrefs
, sizeof(nsymrefs
)) == -1)
244 return got_error_from_errno("imsg_add FETCH_SYMREFS");
246 TAILQ_FOREACH(pe
, symrefs
, entry
) {
247 const char *name
= pe
->path
;
248 size_t name_len
= pe
->path_len
;
249 const char *target
= pe
->data
;
250 size_t target_len
= strlen(target
);
252 /* Keep in sync with struct got_imsg_fetch_symref definition! */
253 if (imsg_add(wbuf
, &name_len
, sizeof(name_len
)) == -1)
254 return got_error_from_errno("imsg_add FETCH_SYMREFS");
255 if (imsg_add(wbuf
, &target_len
, sizeof(target_len
)) == -1)
256 return got_error_from_errno("imsg_add FETCH_SYMREFS");
257 if (imsg_add(wbuf
, name
, name_len
) == -1)
258 return got_error_from_errno("imsg_add FETCH_SYMREFS");
259 if (imsg_add(wbuf
, target
, target_len
) == -1)
260 return got_error_from_errno("imsg_add FETCH_SYMREFS");
264 imsg_close(ibuf
, wbuf
);
265 return got_privsep_flush_imsg(ibuf
);
268 static const struct got_error
*
269 send_fetch_ref(struct imsgbuf
*ibuf
, struct got_object_id
*refid
,
273 size_t len
, reflen
= strlen(refname
);
275 len
= sizeof(struct got_imsg_fetch_ref
) + reflen
;
276 if (len
>= MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
277 return got_error(GOT_ERR_NO_SPACE
);
279 wbuf
= imsg_create(ibuf
, GOT_IMSG_FETCH_REF
, 0, 0, len
);
281 return got_error_from_errno("imsg_create FETCH_REF");
283 /* Keep in sync with struct got_imsg_fetch_ref definition! */
284 if (imsg_add(wbuf
, refid
, sizeof(*refid
)) == -1)
285 return got_error_from_errno("imsg_add FETCH_REF");
286 if (imsg_add(wbuf
, refname
, reflen
) == -1)
287 return got_error_from_errno("imsg_add FETCH_REF");
290 imsg_close(ibuf
, wbuf
);
291 return got_privsep_flush_imsg(ibuf
);
294 static const struct got_error
*
295 fetch_ref(struct imsgbuf
*ibuf
, struct got_pathlist_head
*have_refs
,
296 struct got_object_id
*have
, struct got_object_id
*want
,
297 const char *refname
, const char *id_str
)
299 const struct got_error
*err
;
300 char *theirs
= NULL
, *mine
= NULL
;
302 if (!got_parse_object_id(want
, id_str
, GOT_HASH_SHA1
)) {
303 err
= got_error(GOT_ERR_BAD_OBJ_ID_STR
);
307 match_remote_ref(have_refs
, have
, refname
);
308 err
= send_fetch_ref(ibuf
, want
, refname
);
313 fprintf(stderr
, "%s: %s will be fetched\n",
314 getprogname(), refname
);
316 err
= got_object_id_str(&theirs
, want
);
319 err
= got_object_id_str(&mine
, have
);
322 fprintf(stderr
, "%s: remote: %s\n%s: local: %s\n",
323 getprogname(), theirs
, getprogname(), mine
);
331 static const struct got_error
*
332 fetch_pack(int fd
, int packfd
, uint8_t *pack_sha1
,
333 struct got_pathlist_head
*have_refs
, int fetch_all_branches
,
334 struct got_pathlist_head
*wanted_branches
,
335 struct got_pathlist_head
*wanted_refs
, int list_refs_only
,
336 const char *worktree_branch
, const char *remote_head
,
337 int no_head
, struct imsgbuf
*ibuf
)
339 const struct got_error
*err
= NULL
;
340 char buf
[GOT_PKT_MAX
];
341 char hashstr
[SHA1_DIGEST_STRING_LENGTH
];
342 struct got_object_id
*have
, *want
;
343 int is_firstpkt
= 1, nref
= 0, refsz
= 16;
344 int i
, n
, nwant
= 0, nhave
= 0, acked
= 0;
345 off_t packsz
= 0, last_reported_packsz
= 0;
346 char *id_str
= NULL
, *default_id_str
= NULL
, *refname
= NULL
;
347 char *server_capabilities
= NULL
, *my_capabilities
= NULL
;
348 const char *default_branch
= NULL
;
349 struct got_pathlist_head symrefs
;
350 struct got_pathlist_entry
*pe
;
351 int sent_my_capabilites
= 0, have_sidebands
= 0;
352 int found_branch
= 0;
354 uint8_t sha1_buf
[SHA1_DIGEST_LENGTH
];
355 size_t sha1_buf_len
= 0;
357 struct got_ratelimit rl
;
359 TAILQ_INIT(&symrefs
);
360 got_hash_init(&ctx
, GOT_HASH_SHA1
);
361 got_ratelimit_init(&rl
, 0, 500);
363 have
= malloc(refsz
* sizeof(have
[0]));
365 return got_error_from_errno("malloc");
366 want
= malloc(refsz
* sizeof(want
[0]));
368 err
= got_error_from_errno("malloc");
372 err
= got_pkt_readpkt(&n
, fd
, buf
, sizeof(buf
), chattygot
);
377 if (n
>= 4 && strncmp(buf
, "ERR ", 4) == 0) {
378 err
= fetch_error(&buf
[4], n
- 4);
383 err
= got_gitproto_parse_refline(&id_str
, &refname
,
384 &server_capabilities
, buf
, n
);
388 if (refsz
== nref
+ 1) {
389 struct got_object_id
*h
, *w
;
392 h
= reallocarray(have
, refsz
, sizeof(have
[0]));
394 err
= got_error_from_errno("reallocarray");
398 w
= reallocarray(want
, refsz
, sizeof(want
[0]));
400 err
= got_error_from_errno("reallocarray");
407 if (chattygot
&& server_capabilities
[0] != '\0')
408 fprintf(stderr
, "%s: server capabilities: %s\n",
409 getprogname(), server_capabilities
);
410 err
= got_gitproto_match_capabilities(&my_capabilities
,
411 &symrefs
, server_capabilities
,
412 got_capabilities
, nitems(got_capabilities
));
416 fprintf(stderr
, "%s: my capabilities:%s\n",
417 getprogname(), my_capabilities
!= NULL
?
418 my_capabilities
: "");
419 err
= send_fetch_symrefs(ibuf
, &symrefs
);
423 if (!fetch_all_branches
) {
424 TAILQ_FOREACH(pe
, &symrefs
, entry
) {
425 const char *name
= pe
->path
;
426 const char *symref_target
= pe
->data
;
427 if (strcmp(name
, GOT_REF_HEAD
) != 0)
429 default_branch
= symref_target
;
436 if (strstr(refname
, "^{}")) {
438 fprintf(stderr
, "%s: ignoring %s\n",
439 getprogname(), refname
);
443 if (default_branch
&& default_id_str
== NULL
&&
444 strcmp(refname
, default_branch
) == 0) {
445 default_id_str
= strdup(id_str
);
446 if (default_id_str
== NULL
) {
447 err
= got_error_from_errno("strdup");
452 if (list_refs_only
|| strncmp(refname
, "refs/tags/", 10) == 0) {
453 err
= fetch_ref(ibuf
, have_refs
, &have
[nref
],
454 &want
[nref
], refname
, id_str
);
458 } else if (strncmp(refname
, "refs/heads/", 11) == 0) {
459 if (fetch_all_branches
) {
460 err
= fetch_ref(ibuf
, have_refs
, &have
[nref
],
461 &want
[nref
], refname
, id_str
);
468 TAILQ_FOREACH(pe
, wanted_branches
, entry
) {
469 if (match_branch(refname
, pe
->path
))
472 if (pe
!= NULL
|| (worktree_branch
!= NULL
&&
473 match_branch(refname
, worktree_branch
))) {
474 err
= fetch_ref(ibuf
, have_refs
, &have
[nref
],
475 &want
[nref
], refname
, id_str
);
480 } else if (chattygot
) {
481 fprintf(stderr
, "%s: ignoring %s\n",
482 getprogname(), refname
);
485 TAILQ_FOREACH(pe
, wanted_refs
, entry
) {
486 if (match_wanted_ref(refname
, pe
->path
))
490 err
= fetch_ref(ibuf
, have_refs
, &have
[nref
],
491 &want
[nref
], refname
, id_str
);
495 } else if (chattygot
) {
496 fprintf(stderr
, "%s: ignoring %s\n",
497 getprogname(), refname
);
506 * If -b was not used and either none of the requested branches
507 * (got.conf, worktree) were found or the client already has the
508 * remote HEAD symref but its target changed, fetch remote's HEAD.
510 if (!no_head
&& default_branch
&& default_id_str
&&
511 strncmp(default_branch
, "refs/heads/", 11) == 0) {
512 int remote_head_changed
= 0;
515 if (strcmp(remote_head
, default_branch
+ 11) != 0)
516 remote_head_changed
= 1;
519 if (!found_branch
|| remote_head_changed
) {
520 err
= fetch_ref(ibuf
, have_refs
, &have
[nref
],
521 &want
[nref
], default_branch
, default_id_str
);
528 /* Abort if we haven't found anything to fetch. */
530 struct got_pathlist_entry
*pe
;
531 static char msg
[PATH_MAX
+ 33];
533 pe
= TAILQ_FIRST(wanted_branches
);
535 snprintf(msg
, sizeof(msg
),
536 "branch \"%s\" not found on server", pe
->path
);
537 err
= got_error_msg(GOT_ERR_FETCH_NO_BRANCH
, msg
);
541 pe
= TAILQ_FIRST(wanted_refs
);
543 snprintf(msg
, sizeof(msg
),
544 "reference \"%s\" not found on server", pe
->path
);
545 err
= got_error_msg(GOT_ERR_FETCH_NO_BRANCH
, msg
);
549 err
= got_error(GOT_ERR_FETCH_NO_BRANCH
);
553 for (i
= 0; i
< nref
; i
++) {
554 if (got_object_id_cmp(&have
[i
], &want
[i
]) == 0)
556 got_sha1_digest_to_str(want
[i
].sha1
, hashstr
, sizeof(hashstr
));
557 n
= snprintf(buf
, sizeof(buf
), "want %s%s\n", hashstr
,
558 sent_my_capabilites
|| my_capabilities
== NULL
?
559 "" : my_capabilities
);
560 if (n
< 0 || (size_t)n
>= sizeof(buf
)) {
561 err
= got_error(GOT_ERR_NO_SPACE
);
564 err
= got_pkt_writepkt(fd
, buf
, n
, chattygot
);
567 sent_my_capabilites
= 1;
570 err
= got_pkt_flushpkt(fd
, chattygot
);
577 TAILQ_FOREACH(pe
, have_refs
, entry
) {
578 struct got_object_id
*id
= pe
->data
;
579 got_sha1_digest_to_str(id
->sha1
, hashstr
, sizeof(hashstr
));
580 n
= snprintf(buf
, sizeof(buf
), "have %s\n", hashstr
);
581 if (n
< 0 || (size_t)n
>= sizeof(buf
)) {
582 err
= got_error(GOT_ERR_NO_SPACE
);
585 err
= got_pkt_writepkt(fd
, buf
, n
, chattygot
);
591 n
= strlcpy(buf
, "done\n", sizeof(buf
));
592 err
= got_pkt_writepkt(fd
, buf
, n
, chattygot
);
596 while (nhave
> 0 && !acked
) {
597 struct got_object_id common_id
;
599 /* The server should ACK the object IDs we need. */
600 err
= got_pkt_readpkt(&n
, fd
, buf
, sizeof(buf
), chattygot
);
603 if (n
>= 4 && strncmp(buf
, "ERR ", 4) == 0) {
604 err
= fetch_error(&buf
[4], n
- 4);
607 if (n
>= 4 && strncmp(buf
, "NAK\n", 4) == 0) {
609 * Server could not find a common ancestor.
610 * Perhaps it is an out-of-date mirror, or there
611 * is a repository with unrelated history.
615 if (n
< 4 + SHA1_DIGEST_STRING_LENGTH
||
616 strncmp(buf
, "ACK ", 4) != 0) {
617 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
618 "unexpected message from server");
621 if (!got_parse_object_id(&common_id
, buf
+ 4,
623 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
624 "bad object ID in ACK packet from server");
631 err
= got_pkt_readpkt(&n
, fd
, buf
, sizeof(buf
), chattygot
);
634 if (n
!= 4 || strncmp(buf
, "NAK\n", n
) != 0) {
635 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
636 "unexpected message from server");
642 fprintf(stderr
, "%s: fetching...\n", getprogname());
644 if (my_capabilities
!= NULL
&&
645 strstr(my_capabilities
, GOT_CAPA_SIDE_BAND_64K
) != NULL
)
652 if (have_sidebands
) {
653 err
= got_pkt_readhdr(&datalen
, fd
, chattygot
);
659 /* Read sideband channel ID (one byte). */
660 r
= read(fd
, buf
, 1);
662 err
= got_error_from_errno("read");
666 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
670 if (datalen
> sizeof(buf
) - 5) {
671 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
672 "bad packet length");
675 datalen
--; /* sideband ID has been read */
676 if (buf
[0] == GOT_SIDEBAND_PACKFILE_DATA
) {
677 /* Read packfile data. */
678 err
= got_pkt_readn(&r
, fd
, buf
, datalen
);
682 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
686 } else if (buf
[0] == GOT_SIDEBAND_PROGRESS_INFO
) {
687 err
= got_pkt_readn(&r
, fd
, buf
, datalen
);
691 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
695 err
= fetch_progress(ibuf
, buf
, r
);
699 } else if (buf
[0] == GOT_SIDEBAND_ERROR_INFO
) {
700 err
= got_pkt_readn(&r
, fd
, buf
, datalen
);
704 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
708 err
= fetch_error(buf
, r
);
710 } else if (buf
[0] == 'A') {
711 err
= got_pkt_readn(&r
, fd
, buf
, datalen
);
715 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
720 * Git server responds with ACK after 'done'
721 * even though multi_ack is disabled?!?
724 if (strncmp(buf
, "CK ", 3) == 0)
725 continue; /* ignore */
726 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
727 "unexpected message from server");
730 err
= got_error_msg(GOT_ERR_BAD_PACKET
,
731 "unknown side-band received from server");
735 /* No sideband channel. Every byte is packfile data. */
736 err
= got_pkt_readn(&r
, fd
, buf
, sizeof buf
);
744 * An expected SHA1 checksum sits at the end of the pack file.
745 * Since we don't know the file size ahead of time we have to
746 * keep SHA1_DIGEST_LENGTH bytes buffered and avoid mixing
747 * those bytes into our SHA1 checksum computation until we
748 * know for sure that additional pack file data bytes follow.
750 * We can assume r > 0 since otherwise the loop would exit.
752 if (r
< SHA1_DIGEST_LENGTH
) {
753 if (sha1_buf_len
< SHA1_DIGEST_LENGTH
) {
755 * If there's enough buffered + read data to
756 * fill up the buffer then shift a sufficient
757 * amount of bytes out at the front to make
758 * room, mixing those bytes into the checksum.
760 if (sha1_buf_len
> 0 &&
761 sha1_buf_len
+ r
> SHA1_DIGEST_LENGTH
) {
762 size_t nshift
= MIN(sha1_buf_len
+ r
-
763 SHA1_DIGEST_LENGTH
, sha1_buf_len
);
764 got_hash_update(&ctx
, sha1_buf
,
766 memmove(sha1_buf
, sha1_buf
+ nshift
,
767 sha1_buf_len
- nshift
);
768 sha1_buf_len
-= nshift
;
771 /* Buffer potential checksum bytes. */
772 memcpy(sha1_buf
+ sha1_buf_len
, buf
, r
);
776 * Mix in previously buffered bytes which
777 * are not part of the checksum after all.
779 got_hash_update(&ctx
, sha1_buf
, r
);
781 /* Update potential checksum buffer. */
782 memmove(sha1_buf
, sha1_buf
+ r
,
784 memcpy(sha1_buf
+ sha1_buf_len
- r
, buf
, r
);
787 /* Mix in any previously buffered bytes. */
788 got_hash_update(&ctx
, sha1_buf
, sha1_buf_len
);
790 /* Mix in bytes read minus potential checksum bytes. */
791 got_hash_update(&ctx
, buf
, r
- SHA1_DIGEST_LENGTH
);
793 /* Buffer potential checksum bytes. */
794 memcpy(sha1_buf
, buf
+ r
- SHA1_DIGEST_LENGTH
,
796 sha1_buf_len
= SHA1_DIGEST_LENGTH
;
799 /* Write packfile data to temporary pack file. */
800 w
= write(packfd
, buf
, r
);
802 err
= got_error_from_errno("write");
806 err
= got_error(GOT_ERR_IO
);
811 /* Don't send too many progress privsep messages. */
812 if (packsz
> last_reported_packsz
+ 1024) {
813 err
= send_fetch_download_progress(ibuf
, packsz
, &rl
);
816 last_reported_packsz
= packsz
;
819 err
= send_fetch_download_progress(ibuf
, packsz
, NULL
);
823 got_hash_final(&ctx
, pack_sha1
);
824 if (sha1_buf_len
!= SHA1_DIGEST_LENGTH
||
825 memcmp(pack_sha1
, sha1_buf
, sha1_buf_len
) != 0) {
826 err
= got_error_msg(GOT_ERR_BAD_PACKFILE
,
827 "pack file checksum mismatch");
830 got_pathlist_free(&symrefs
, GOT_PATHLIST_FREE_ALL
);
834 free(default_id_str
);
836 free(server_capabilities
);
842 main(int argc
, char **argv
)
844 const struct got_error
*err
= NULL
;
845 int fetchfd
= -1, packfd
= -1;
846 uint8_t pack_sha1
[SHA1_DIGEST_LENGTH
];
849 struct got_pathlist_head have_refs
;
850 struct got_pathlist_head wanted_branches
;
851 struct got_pathlist_head wanted_refs
;
852 struct got_imsg_fetch_request fetch_req
;
853 struct got_imsg_fetch_have_ref href
;
854 struct got_imsg_fetch_wanted_branch wbranch
;
855 struct got_imsg_fetch_wanted_ref wref
;
857 char *remote_head
= NULL
, *worktree_branch
= NULL
;
864 TAILQ_INIT(&have_refs
);
865 TAILQ_INIT(&wanted_branches
);
866 TAILQ_INIT(&wanted_refs
);
868 imsg_init(&ibuf
, GOT_IMSG_FD_CHILD
);
870 /* revoke access to most system calls */
871 if (pledge("stdio recvfd", NULL
) == -1) {
872 err
= got_error_from_errno("pledge");
873 got_privsep_send_error(&ibuf
, err
);
877 /* revoke fs access */
878 if (landlock_no_fs() == -1) {
879 err
= got_error_from_errno("landlock_no_fs");
880 got_privsep_send_error(&ibuf
, err
);
883 if (cap_enter() == -1) {
884 err
= got_error_from_errno("cap_enter");
885 got_privsep_send_error(&ibuf
, err
);
889 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
891 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
895 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
897 if (imsg
.hdr
.type
!= GOT_IMSG_FETCH_REQUEST
) {
898 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
901 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
902 if (datalen
< sizeof(fetch_req
)) {
903 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
906 memcpy(&fetch_req
, imsg
.data
, sizeof(fetch_req
));
909 if (datalen
!= sizeof(fetch_req
) +
910 fetch_req
.worktree_branch_len
+ fetch_req
.remote_head_len
) {
911 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
915 if (fetch_req
.worktree_branch_len
!= 0) {
916 worktree_branch
= strndup(imsg
.data
+
917 sizeof(fetch_req
), fetch_req
.worktree_branch_len
);
918 if (worktree_branch
== NULL
) {
919 err
= got_error_from_errno("strndup");
924 if (fetch_req
.remote_head_len
!= 0) {
925 remote_head
= strndup(imsg
.data
+ sizeof(fetch_req
) +
926 fetch_req
.worktree_branch_len
, fetch_req
.remote_head_len
);
927 if (remote_head
== NULL
) {
928 err
= got_error_from_errno("strndup");
935 if (fetch_req
.verbosity
> 0)
936 chattygot
+= fetch_req
.verbosity
;
938 for (i
= 0; i
< fetch_req
.n_have_refs
; i
++) {
939 struct got_object_id
*id
;
942 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
944 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
948 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
950 if (imsg
.hdr
.type
!= GOT_IMSG_FETCH_HAVE_REF
) {
951 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
954 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
955 if (datalen
< sizeof(href
)) {
956 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
959 memcpy(&href
, imsg
.data
, sizeof(href
));
960 if (datalen
- sizeof(href
) < href
.name_len
) {
961 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
964 refname
= strndup(imsg
.data
+ sizeof(href
), href
.name_len
);
965 if (refname
== NULL
) {
966 err
= got_error_from_errno("strndup");
970 id
= malloc(sizeof(*id
));
973 err
= got_error_from_errno("malloc");
976 memcpy(id
, &href
.id
, sizeof(*id
));
977 err
= got_pathlist_append(&have_refs
, refname
, id
);
987 for (i
= 0; i
< fetch_req
.n_wanted_branches
; i
++) {
990 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
992 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
996 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
998 if (imsg
.hdr
.type
!= GOT_IMSG_FETCH_WANTED_BRANCH
) {
999 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1002 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1003 if (datalen
< sizeof(wbranch
)) {
1004 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1007 memcpy(&wbranch
, imsg
.data
, sizeof(wbranch
));
1008 if (datalen
- sizeof(wbranch
) < wbranch
.name_len
) {
1009 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1012 refname
= strndup(imsg
.data
+ sizeof(wbranch
),
1014 if (refname
== NULL
) {
1015 err
= got_error_from_errno("strndup");
1019 err
= got_pathlist_append(&wanted_branches
, refname
, NULL
);
1028 for (i
= 0; i
< fetch_req
.n_wanted_refs
; i
++) {
1031 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
1033 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
1037 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
1039 if (imsg
.hdr
.type
!= GOT_IMSG_FETCH_WANTED_REF
) {
1040 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1043 datalen
= imsg
.hdr
.len
- IMSG_HEADER_SIZE
;
1044 if (datalen
< sizeof(wref
)) {
1045 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1048 memcpy(&wref
, imsg
.data
, sizeof(wref
));
1049 if (datalen
- sizeof(wref
) < wref
.name_len
) {
1050 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1053 refname
= strndup(imsg
.data
+ sizeof(wref
), wref
.name_len
);
1054 if (refname
== NULL
) {
1055 err
= got_error_from_errno("strndup");
1059 err
= got_pathlist_append(&wanted_refs
, refname
, NULL
);
1068 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
1070 if (err
->code
== GOT_ERR_PRIVSEP_PIPE
)
1074 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
1076 if (imsg
.hdr
.type
!= GOT_IMSG_FETCH_OUTFD
) {
1077 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1080 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
1081 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
1086 err
= fetch_pack(fetchfd
, packfd
, pack_sha1
, &have_refs
,
1087 fetch_req
.fetch_all_branches
, &wanted_branches
,
1088 &wanted_refs
, fetch_req
.list_refs_only
,
1089 worktree_branch
, remote_head
, fetch_req
.no_head
, &ibuf
);
1091 free(worktree_branch
);
1093 got_pathlist_free(&have_refs
, GOT_PATHLIST_FREE_ALL
);
1094 got_pathlist_free(&wanted_branches
, GOT_PATHLIST_FREE_PATH
);
1095 if (fetchfd
!= -1 && close(fetchfd
) == -1 && err
== NULL
)
1096 err
= got_error_from_errno("close");
1097 if (packfd
!= -1 && close(packfd
) == -1 && err
== NULL
)
1098 err
= got_error_from_errno("close");
1100 got_privsep_send_error(&ibuf
, err
);
1102 err
= send_fetch_done(&ibuf
, pack_sha1
);
1104 fprintf(stderr
, "%s: %s\n", getprogname(), err
->msg
);
1105 got_privsep_send_error(&ibuf
, err
);