2 * Copyright (c) 2022 Stefan Sperling <stsp@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 <sys/queue.h>
19 #include <sys/types.h>
36 #include "got_error.h"
37 #include "got_repository.h"
38 #include "got_object.h"
39 #include "got_reference.h"
42 #include "got_lib_delta.h"
43 #include "got_lib_delta_cache.h"
44 #include "got_lib_hash.h"
45 #include "got_lib_object.h"
46 #include "got_lib_object_cache.h"
47 #include "got_lib_object_idset.h"
48 #include "got_lib_object_parse.h"
49 #include "got_lib_ratelimit.h"
50 #include "got_lib_pack.h"
51 #include "got_lib_pack_index.h"
52 #include "got_lib_repository.h"
53 #include "got_lib_poll.h"
57 #include "repo_write.h"
60 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
63 static struct repo_write
{
66 struct got_repository
*repo
;
70 struct gotd_imsgev session_iev
;
71 struct got_pathlist_head
*protected_tag_namespaces
;
72 struct got_pathlist_head
*protected_branch_namespaces
;
73 struct got_pathlist_head
*protected_branches
;
76 struct gotd_ref_update
{
77 STAILQ_ENTRY(gotd_ref_update
) entry
;
78 struct got_reference
*ref
;
81 struct got_object_id old_id
;
82 struct got_object_id new_id
;
84 STAILQ_HEAD(gotd_ref_updates
, gotd_ref_update
);
86 static struct repo_write_client
{
91 uint8_t pack_sha1
[SHA1_DIGEST_LENGTH
];
93 struct gotd_ref_updates ref_updates
;
99 static volatile sig_atomic_t sigint_received
;
100 static volatile sig_atomic_t sigterm_received
;
103 catch_sigint(int signo
)
109 catch_sigterm(int signo
)
111 sigterm_received
= 1;
114 static const struct got_error
*
115 check_cancelled(void *arg
)
117 if (sigint_received
|| sigterm_received
)
118 return got_error(GOT_ERR_CANCELLED
);
123 static const struct got_error
*
124 send_peeled_tag_ref(struct got_reference
*ref
, struct got_object
*obj
,
125 struct imsgbuf
*ibuf
)
127 const struct got_error
*err
= NULL
;
128 struct got_tag_object
*tag
;
130 char *peeled_refname
= NULL
;
131 struct got_object_id
*id
;
134 err
= got_object_tag_open(&tag
, repo_write
.repo
, obj
);
138 if (asprintf(&peeled_refname
, "%s^{}", got_ref_get_name(ref
)) == -1) {
139 err
= got_error_from_errno("asprintf");
143 id
= got_object_tag_get_object_id(tag
);
144 namelen
= strlen(peeled_refname
);
146 len
= sizeof(struct gotd_imsg_ref
) + namelen
;
147 if (len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
148 err
= got_error(GOT_ERR_NO_SPACE
);
152 wbuf
= imsg_create(ibuf
, GOTD_IMSG_REF
, PROC_REPO_WRITE
,
153 repo_write
.pid
, len
);
155 err
= got_error_from_errno("imsg_create REF");
159 /* Keep in sync with struct gotd_imsg_ref definition. */
160 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1) {
161 err
= got_error_from_errno("imsg_add REF");
164 if (imsg_add(wbuf
, &namelen
, sizeof(namelen
)) == -1) {
165 err
= got_error_from_errno("imsg_add REF");
168 if (imsg_add(wbuf
, peeled_refname
, namelen
) == -1) {
169 err
= got_error_from_errno("imsg_add REF");
174 imsg_close(ibuf
, wbuf
);
176 got_object_tag_close(tag
);
180 static const struct got_error
*
181 send_ref(struct got_reference
*ref
, struct imsgbuf
*ibuf
)
183 const struct got_error
*err
;
184 const char *refname
= got_ref_get_name(ref
);
186 struct got_object_id
*id
= NULL
;
187 struct got_object
*obj
= NULL
;
191 namelen
= strlen(refname
);
193 len
= sizeof(struct gotd_imsg_ref
) + namelen
;
194 if (len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
195 return got_error(GOT_ERR_NO_SPACE
);
197 err
= got_ref_resolve(&id
, repo_write
.repo
, ref
);
201 wbuf
= imsg_create(ibuf
, GOTD_IMSG_REF
, PROC_REPO_WRITE
,
202 repo_write
.pid
, len
);
204 err
= got_error_from_errno("imsg_create REF");
208 /* Keep in sync with struct gotd_imsg_ref definition. */
209 if (imsg_add(wbuf
, id
->sha1
, SHA1_DIGEST_LENGTH
) == -1)
210 return got_error_from_errno("imsg_add REF");
211 if (imsg_add(wbuf
, &namelen
, sizeof(namelen
)) == -1)
212 return got_error_from_errno("imsg_add REF");
213 if (imsg_add(wbuf
, refname
, namelen
) == -1)
214 return got_error_from_errno("imsg_add REF");
217 imsg_close(ibuf
, wbuf
);
219 err
= got_object_open(&obj
, repo_write
.repo
, id
);
222 if (obj
->type
== GOT_OBJ_TYPE_TAG
)
223 err
= send_peeled_tag_ref(ref
, obj
, ibuf
);
226 got_object_close(obj
);
231 static const struct got_error
*
232 list_refs(struct imsg
*imsg
)
234 const struct got_error
*err
;
235 struct repo_write_client
*client
= &repo_write_client
;
236 struct got_reflist_head refs
;
237 struct got_reflist_entry
*re
;
238 struct gotd_imsg_list_refs_internal ireq
;
240 struct gotd_imsg_reflist irefs
;
242 int client_fd
= imsg
->fd
;
247 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
249 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
250 if (datalen
!= sizeof(ireq
))
251 return got_error(GOT_ERR_PRIVSEP_LEN
);
252 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
254 if (ireq
.client_id
== 0)
255 return got_error(GOT_ERR_CLIENT_ID
);
256 if (client
->id
!= 0) {
257 return got_error_msg(GOT_ERR_CLIENT_ID
,
258 "duplicate list-refs request");
260 client
->id
= ireq
.client_id
;
261 client
->fd
= client_fd
;
262 client
->nref_updates
= 0;
263 client
->nref_del
= 0;
264 client
->nref_new
= 0;
266 imsg_init(&ibuf
, client_fd
);
268 err
= got_ref_list(&refs
, repo_write
.repo
, "",
269 got_ref_cmp_by_name
, NULL
);
273 memset(&irefs
, 0, sizeof(irefs
));
274 TAILQ_FOREACH(re
, &refs
, entry
) {
275 struct got_object_id
*id
;
278 if (got_ref_is_symbolic(re
->ref
))
283 /* Account for a peeled tag refs. */
284 err
= got_ref_resolve(&id
, repo_write
.repo
, re
->ref
);
287 err
= got_object_get_type(&obj_type
, repo_write
.repo
, id
);
291 if (obj_type
== GOT_OBJ_TYPE_TAG
)
295 if (imsg_compose(&ibuf
, GOTD_IMSG_REFLIST
, PROC_REPO_WRITE
,
296 repo_write
.pid
, -1, &irefs
, sizeof(irefs
)) == -1) {
297 err
= got_error_from_errno("imsg_compose REFLIST");
301 TAILQ_FOREACH(re
, &refs
, entry
) {
302 if (got_ref_is_symbolic(re
->ref
))
304 err
= send_ref(re
->ref
, &ibuf
);
309 err
= gotd_imsg_flush(&ibuf
);
311 got_ref_list_free(&refs
);
316 static const struct got_error
*
317 validate_namespace(const char *namespace)
319 size_t len
= strlen(namespace);
321 if (len
< 5 || strncmp("refs/", namespace, 5) != 0 ||
322 namespace[len
-1] != '/') {
323 return got_error_fmt(GOT_ERR_BAD_REF_NAME
,
324 "reference namespace '%s'", namespace);
330 static const struct got_error
*
331 protect_ref_namespace(const char *refname
, const char *namespace)
333 const struct got_error
*err
;
335 err
= validate_namespace(namespace);
339 if (strncmp(namespace, refname
, strlen(namespace)) == 0)
340 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
345 static const struct got_error
*
346 verify_object_type(struct got_object_id
*id
, int expected_obj_type
,
347 struct got_pack
*pack
, struct got_packidx
*packidx
)
349 const struct got_error
*err
;
350 char hex
[SHA1_DIGEST_STRING_LENGTH
];
351 struct got_object
*obj
;
355 idx
= got_packidx_get_object_idx(packidx
, id
);
357 got_sha1_digest_to_str(id
->sha1
, hex
, sizeof(hex
));
358 return got_error_fmt(GOT_ERR_BAD_PACKFILE
,
359 "object %s is missing from pack file", hex
);
362 err
= got_object_open_from_packfile(&obj
, id
, pack
, packidx
,
363 idx
, repo_write
.repo
);
367 if (obj
->type
!= expected_obj_type
) {
368 got_sha1_digest_to_str(id
->sha1
, hex
, sizeof(hex
));
369 got_object_type_label(&typestr
, expected_obj_type
);
370 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
371 "%s is not pointing at a %s object", hex
, typestr
);
373 got_object_close(obj
);
377 static const struct got_error
*
378 protect_tag_namespace(const char *namespace, struct got_pack
*pack
,
379 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
381 const struct got_error
*err
;
383 err
= validate_namespace(namespace);
387 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
388 strlen(namespace)) != 0)
391 if (!ref_update
->ref_is_new
)
392 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
394 return verify_object_type(&ref_update
->new_id
, GOT_OBJ_TYPE_TAG
,
398 static const struct got_error
*
399 protect_require_yca(struct got_object_id
*tip_id
,
400 size_t max_commits_to_traverse
, struct got_pack
*pack
,
401 struct got_packidx
*packidx
, struct got_reference
*ref
)
403 const struct got_error
*err
;
406 struct got_object_id
*expected_yca_id
= NULL
;
407 struct got_object
*obj
= NULL
;
408 struct got_commit_object
*commit
= NULL
;
409 char hex
[SHA1_DIGEST_STRING_LENGTH
];
410 const struct got_object_id_queue
*parent_ids
;
411 struct got_object_id_queue ids
;
412 struct got_object_qid
*pid
, *qid
;
413 struct got_object_idset
*traversed_set
= NULL
;
414 int found_yca
= 0, obj_type
;
418 err
= got_ref_resolve(&expected_yca_id
, repo_write
.repo
, ref
);
422 err
= got_object_get_type(&obj_type
, repo_write
.repo
, expected_yca_id
);
426 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
) {
427 got_sha1_digest_to_str(expected_yca_id
->sha1
, hex
, sizeof(hex
));
428 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
429 "%s is not pointing at a commit object", hex
);
433 traversed_set
= got_object_idset_alloc();
434 if (traversed_set
== NULL
) {
435 err
= got_error_from_errno("got_object_idset_alloc");
439 err
= got_object_qid_alloc(&qid
, tip_id
);
442 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
443 while (!STAILQ_EMPTY(&ids
)) {
444 err
= check_cancelled(NULL
);
448 qid
= STAILQ_FIRST(&ids
);
449 if (got_object_id_cmp(&qid
->id
, expected_yca_id
) == 0) {
454 if (got_object_idset_num_elements(traversed_set
) >=
455 max_commits_to_traverse
)
458 if (got_object_idset_contains(traversed_set
, &qid
->id
)) {
459 STAILQ_REMOVE_HEAD(&ids
, entry
);
460 got_object_qid_free(qid
);
464 err
= got_object_idset_add(traversed_set
, &qid
->id
, NULL
);
468 err
= got_object_open(&obj
, repo_write
.repo
, &qid
->id
);
469 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
473 err
= got_object_commit_open(&commit
, repo_write
.repo
,
480 idx
= got_packidx_get_object_idx(packidx
, &qid
->id
);
482 got_sha1_digest_to_str(qid
->id
.sha1
,
484 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
485 "object %s is missing from pack file", hex
);
489 err
= got_object_open_from_packfile(&obj
, &qid
->id
,
490 pack
, packidx
, idx
, repo_write
.repo
);
494 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
495 got_sha1_digest_to_str(qid
->id
.sha1
,
497 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
498 "%s is not pointing at a commit object",
503 err
= got_packfile_extract_object_to_mem(&buf
, &len
,
508 err
= got_object_parse_commit(&commit
, buf
, len
);
516 got_object_close(obj
);
519 STAILQ_REMOVE_HEAD(&ids
, entry
);
520 got_object_qid_free(qid
);
523 if (got_object_commit_get_nparents(commit
) == 0)
526 parent_ids
= got_object_commit_get_parent_ids(commit
);
527 STAILQ_FOREACH(pid
, parent_ids
, entry
) {
528 err
= check_cancelled(NULL
);
531 err
= got_object_qid_alloc(&qid
, &pid
->id
);
534 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
537 got_object_commit_close(commit
);
542 err
= got_error_fmt(GOT_ERR_REF_PROTECTED
, "%s",
543 got_ref_get_name(ref
));
546 got_object_idset_free(traversed_set
);
547 got_object_id_queue_free(&ids
);
550 got_object_close(obj
);
552 got_object_commit_close(commit
);
553 free(expected_yca_id
);
557 static const struct got_error
*
558 protect_branch_namespace(const char *namespace, struct got_pack
*pack
,
559 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
561 const struct got_error
*err
;
563 err
= validate_namespace(namespace);
567 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
568 strlen(namespace)) != 0)
571 if (ref_update
->ref_is_new
) {
572 return verify_object_type(&ref_update
->new_id
,
573 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
576 return protect_require_yca(&ref_update
->new_id
,
577 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
581 static const struct got_error
*
582 protect_branch(const char *refname
, struct got_pack
*pack
,
583 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
585 if (strcmp(refname
, got_ref_get_name(ref_update
->ref
)) != 0)
588 /* Always allow new branches to be created. */
589 if (ref_update
->ref_is_new
) {
590 return verify_object_type(&ref_update
->new_id
,
591 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
594 return protect_require_yca(&ref_update
->new_id
,
595 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
599 static const struct got_error
*
600 recv_ref_update(struct imsg
*imsg
)
602 static const char zero_id
[SHA1_DIGEST_LENGTH
];
603 const struct got_error
*err
= NULL
;
604 struct repo_write_client
*client
= &repo_write_client
;
605 struct gotd_imsg_ref_update iref
;
607 char *refname
= NULL
;
608 struct got_reference
*ref
= NULL
;
609 struct got_object_id
*id
= NULL
;
611 struct gotd_ref_update
*ref_update
= NULL
;
613 log_debug("ref-update received");
615 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
616 if (datalen
< sizeof(iref
))
617 return got_error(GOT_ERR_PRIVSEP_LEN
);
618 memcpy(&iref
, imsg
->data
, sizeof(iref
));
619 if (datalen
!= sizeof(iref
) + iref
.name_len
)
620 return got_error(GOT_ERR_PRIVSEP_LEN
);
622 imsg_init(&ibuf
, client
->fd
);
624 refname
= strndup(imsg
->data
+ sizeof(iref
), iref
.name_len
);
626 return got_error_from_errno("strndup");
628 ref_update
= calloc(1, sizeof(*ref_update
));
629 if (ref_update
== NULL
) {
630 err
= got_error_from_errno("malloc");
634 memcpy(ref_update
->old_id
.sha1
, iref
.old_id
, SHA1_DIGEST_LENGTH
);
635 memcpy(ref_update
->new_id
.sha1
, iref
.new_id
, SHA1_DIGEST_LENGTH
);
637 err
= got_ref_open(&ref
, repo_write
.repo
, refname
, 0);
639 if (err
->code
!= GOT_ERR_NOT_REF
)
641 if (memcmp(ref_update
->new_id
.sha1
,
642 zero_id
, sizeof(zero_id
)) == 0) {
643 err
= got_error_fmt(GOT_ERR_BAD_OBJ_ID
,
647 err
= got_ref_alloc(&ref
, refname
, &ref_update
->new_id
);
650 ref_update
->ref_is_new
= 1;
653 if (got_ref_is_symbolic(ref
)) {
654 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
655 "'%s' is a symbolic reference and cannot "
656 "be updated", got_ref_get_name(ref
));
659 if (strncmp("refs/", got_ref_get_name(ref
), 5) != 0) {
660 err
= got_error_fmt(GOT_ERR_BAD_REF_NAME
,
661 "%s: does not begin with 'refs/'",
662 got_ref_get_name(ref
));
666 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/got/");
669 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/remotes/");
673 if (!ref_update
->ref_is_new
) {
675 * Ensure the client's idea of this update is still valid.
676 * At this point we can only return an error, to prevent
677 * the client from uploading a pack file which will likely
678 * have to be discarded.
680 err
= got_ref_resolve(&id
, repo_write
.repo
, ref
);
684 if (got_object_id_cmp(id
, &ref_update
->old_id
) != 0) {
685 err
= got_error_fmt(GOT_ERR_REF_BUSY
,
686 "%s has been modified by someone else "
687 "while transaction was in progress",
688 got_ref_get_name(ref
));
693 gotd_imsg_send_ack(&ref_update
->new_id
, &ibuf
, PROC_REPO_WRITE
,
696 ref_update
->ref
= ref
;
697 if (memcmp(ref_update
->new_id
.sha1
, zero_id
, sizeof(zero_id
)) == 0) {
698 ref_update
->delete_ref
= 1;
701 STAILQ_INSERT_HEAD(&client
->ref_updates
, ref_update
, entry
);
702 client
->nref_updates
++;
714 static const struct got_error
*
715 pack_index_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
716 uint32_t nobj_loose
, uint32_t nobj_resolved
)
718 int p_indexed
= 0, p_resolved
= 0;
719 int nobj_delta
= nobj_total
- nobj_loose
;
722 p_indexed
= (nobj_indexed
* 100) / nobj_total
;
725 p_resolved
= (nobj_resolved
* 100) / nobj_delta
;
727 if (p_resolved
> 0) {
728 log_debug("indexing %d objects %d%%; resolving %d deltas %d%%",
729 nobj_total
, p_indexed
, nobj_delta
, p_resolved
);
731 log_debug("indexing %d objects %d%%", nobj_total
, p_indexed
);
736 static const struct got_error
*
737 read_more_pack_stream(int infd
, BUF
*buf
, size_t minsize
)
739 const struct got_error
*err
= NULL
;
740 uint8_t readahead
[65536];
743 err
= got_poll_read_full(infd
, &have
,
744 readahead
, sizeof(readahead
), minsize
);
748 err
= buf_append(&newlen
, buf
, readahead
, have
);
754 static const struct got_error
*
755 copy_object_type_and_size(uint8_t *type
, uint64_t *size
, int infd
, int outfd
,
756 off_t
*outsize
, BUF
*buf
, size_t *buf_pos
, struct got_hash
*ctx
)
758 const struct got_error
*err
= NULL
;
763 off_t obj_offset
= *outsize
;
766 /* We do not support size values which don't fit in 64 bit. */
768 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
769 "packfile offset %lld", (long long)obj_offset
);
771 if (buf_len(buf
) - *buf_pos
< sizeof(sizebuf
[0])) {
772 err
= read_more_pack_stream(infd
, buf
,
778 sizebuf
[i
] = buf_getc(buf
, *buf_pos
);
779 *buf_pos
+= sizeof(sizebuf
[i
]);
782 t
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_TYPE_MASK
) >>
783 GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT
;
784 s
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_VAL_MASK
);
786 size_t shift
= 4 + 7 * (i
- 1);
787 s
|= ((sizebuf
[i
] & GOT_PACK_OBJ_SIZE_VAL_MASK
) <<
791 } while (sizebuf
[i
- 1] & GOT_PACK_OBJ_SIZE_MORE
);
793 err
= got_pack_hwrite(outfd
, sizebuf
, i
, ctx
);
803 static const struct got_error
*
804 copy_ref_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
805 struct got_hash
*ctx
)
807 const struct got_error
*err
= NULL
;
808 size_t remain
= buf_len(buf
) - *buf_pos
;
810 if (remain
< SHA1_DIGEST_LENGTH
) {
811 err
= read_more_pack_stream(infd
, buf
,
812 SHA1_DIGEST_LENGTH
- remain
);
817 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
818 SHA1_DIGEST_LENGTH
, ctx
);
822 *buf_pos
+= SHA1_DIGEST_LENGTH
;
826 static const struct got_error
*
827 copy_offset_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
828 struct got_hash
*ctx
)
830 const struct got_error
*err
= NULL
;
834 off_t obj_offset
= *outsize
;
837 /* We do not support offset values which don't fit in 64 bit. */
839 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
840 "packfile offset %lld", (long long)obj_offset
);
842 if (buf_len(buf
) - *buf_pos
< sizeof(offbuf
[0])) {
843 err
= read_more_pack_stream(infd
, buf
,
849 offbuf
[i
] = buf_getc(buf
, *buf_pos
);
850 *buf_pos
+= sizeof(offbuf
[i
]);
853 o
= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
857 o
+= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
860 } while (offbuf
[i
- 1] & GOT_PACK_OBJ_DELTA_OFF_MORE
);
862 if (o
< sizeof(struct got_packfile_hdr
) || o
> *outsize
)
863 return got_error(GOT_ERR_PACK_OFFSET
);
865 err
= got_pack_hwrite(outfd
, offbuf
, i
, ctx
);
873 static const struct got_error
*
874 copy_zstream(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
875 struct got_hash
*ctx
)
877 const struct got_error
*err
= NULL
;
881 size_t consumed_total
= 0;
882 off_t zstream_offset
= *outsize
;
884 memset(&z
, 0, sizeof(z
));
888 zret
= inflateInit(&z
);
891 return got_error_from_errno("inflateInit");
892 if (zret
== Z_MEM_ERROR
) {
894 return got_error_from_errno("inflateInit");
896 return got_error_msg(GOT_ERR_DECOMPRESSION
,
897 "inflateInit failed");
900 while (zret
!= Z_STREAM_END
) {
901 size_t last_total_in
, consumed
;
904 * Decompress into the void. Object data will be parsed
905 * later, when the pack file is indexed. For now, we just
906 * want to locate the end of the compressed stream.
908 while (zret
!= Z_STREAM_END
&& buf_len(buf
) - *buf_pos
> 0) {
909 last_total_in
= z
.total_in
;
910 z
.next_in
= buf_get(buf
) + *buf_pos
;
911 z
.avail_in
= buf_len(buf
) - *buf_pos
;
912 z
.next_out
= voidbuf
;
913 z
.avail_out
= sizeof(voidbuf
);
915 zret
= inflate(&z
, Z_SYNC_FLUSH
);
916 if (zret
!= Z_OK
&& zret
!= Z_BUF_ERROR
&&
917 zret
!= Z_STREAM_END
) {
918 err
= got_error_fmt(GOT_ERR_DECOMPRESSION
,
919 "packfile offset %lld",
920 (long long)zstream_offset
);
923 consumed
= z
.total_in
- last_total_in
;
925 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
930 err
= buf_discard(buf
, *buf_pos
+ consumed
);
935 consumed_total
+= consumed
;
938 if (zret
!= Z_STREAM_END
) {
939 err
= read_more_pack_stream(infd
, buf
, 1);
946 *outsize
+= consumed_total
;
952 static const struct got_error
*
953 validate_object_type(int obj_type
)
956 case GOT_OBJ_TYPE_BLOB
:
957 case GOT_OBJ_TYPE_COMMIT
:
958 case GOT_OBJ_TYPE_TREE
:
959 case GOT_OBJ_TYPE_TAG
:
960 case GOT_OBJ_TYPE_REF_DELTA
:
961 case GOT_OBJ_TYPE_OFFSET_DELTA
:
967 return got_error(GOT_ERR_OBJ_TYPE
);
970 static const struct got_error
*
971 recv_packdata(off_t
*outsize
, uint32_t *nobj
, uint8_t *sha1
,
974 const struct got_error
*err
;
975 struct repo_write_client
*client
= &repo_write_client
;
976 struct got_packfile_hdr hdr
;
980 uint8_t expected_sha1
[SHA1_DIGEST_LENGTH
];
981 char hex
[SHA1_DIGEST_STRING_LENGTH
];
983 size_t buf_pos
= 0, remain
;
989 /* if only deleting references there's nothing to read */
990 if (client
->nref_updates
== client
->nref_del
)
993 got_hash_init(&ctx
, GOT_HASH_SHA1
);
995 err
= got_poll_read_full(infd
, &have
, &hdr
, sizeof(hdr
), sizeof(hdr
));
998 if (have
!= sizeof(hdr
))
999 return got_error_msg(GOT_ERR_BAD_PACKFILE
, "short pack file");
1002 if (hdr
.signature
!= htobe32(GOT_PACKFILE_SIGNATURE
))
1003 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1004 "bad packfile signature");
1005 if (hdr
.version
!= htobe32(GOT_PACKFILE_VERSION
))
1006 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1007 "bad packfile version");
1009 *nobj
= be32toh(hdr
.nobjects
);
1012 * Clients which are creating new references only
1013 * will send us an empty pack file.
1015 if (client
->nref_updates
> 0 &&
1016 client
->nref_updates
== client
->nref_new
)
1019 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1020 "bad packfile with zero objects");
1023 log_debug("expecting %d objects", *nobj
);
1025 err
= got_pack_hwrite(outfd
, &hdr
, sizeof(hdr
), &ctx
);
1029 err
= buf_alloc(&buf
, 65536);
1033 while (nhave
!= *nobj
) {
1037 err
= copy_object_type_and_size(&obj_type
, &obj_size
,
1038 infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1042 err
= validate_object_type(obj_type
);
1046 if (obj_type
== GOT_OBJ_TYPE_REF_DELTA
) {
1047 err
= copy_ref_delta(infd
, outfd
, outsize
,
1048 buf
, &buf_pos
, &ctx
);
1051 } else if (obj_type
== GOT_OBJ_TYPE_OFFSET_DELTA
) {
1052 err
= copy_offset_delta(infd
, outfd
, outsize
,
1053 buf
, &buf_pos
, &ctx
);
1058 err
= copy_zstream(infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1065 log_debug("received %u objects", *nobj
);
1067 got_hash_final(&ctx
, expected_sha1
);
1069 remain
= buf_len(buf
) - buf_pos
;
1070 if (remain
< SHA1_DIGEST_LENGTH
) {
1071 err
= read_more_pack_stream(infd
, buf
,
1072 SHA1_DIGEST_LENGTH
- remain
);
1077 got_sha1_digest_to_str(expected_sha1
, hex
, sizeof(hex
));
1078 log_debug("expect SHA1: %s", hex
);
1079 got_sha1_digest_to_str(buf_get(buf
) + buf_pos
, hex
, sizeof(hex
));
1080 log_debug("actual SHA1: %s", hex
);
1082 if (memcmp(buf_get(buf
) + buf_pos
, expected_sha1
,
1083 SHA1_DIGEST_LENGTH
) != 0) {
1084 err
= got_error(GOT_ERR_PACKFILE_CSUM
);
1088 memcpy(sha1
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1090 w
= write(outfd
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1092 err
= got_error_from_errno("write");
1095 if (w
!= SHA1_DIGEST_LENGTH
) {
1096 err
= got_error(GOT_ERR_IO
);
1100 *outsize
+= SHA1_DIGEST_LENGTH
;
1102 if (fsync(outfd
) == -1) {
1103 err
= got_error_from_errno("fsync");
1106 if (lseek(outfd
, 0L, SEEK_SET
) == -1) {
1107 err
= got_error_from_errno("lseek");
1115 static const struct got_error
*
1116 report_pack_status(const struct got_error
*unpack_err
)
1118 const struct got_error
*err
= NULL
;
1119 struct repo_write_client
*client
= &repo_write_client
;
1120 struct gotd_imsg_packfile_status istatus
;
1122 struct imsgbuf ibuf
;
1123 const char *unpack_ok
= "unpack ok\n";
1126 imsg_init(&ibuf
, client
->fd
);
1129 istatus
.reason_len
= strlen(unpack_err
->msg
);
1131 istatus
.reason_len
= strlen(unpack_ok
);
1133 len
= sizeof(istatus
) + istatus
.reason_len
;
1134 wbuf
= imsg_create(&ibuf
, GOTD_IMSG_PACKFILE_STATUS
, PROC_REPO_WRITE
,
1135 repo_write
.pid
, len
);
1137 err
= got_error_from_errno("imsg_create PACKFILE_STATUS");
1141 if (imsg_add(wbuf
, &istatus
, sizeof(istatus
)) == -1) {
1142 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1146 if (imsg_add(wbuf
, err
? err
->msg
: unpack_ok
,
1147 istatus
.reason_len
) == -1) {
1148 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1153 imsg_close(&ibuf
, wbuf
);
1155 err
= gotd_imsg_flush(&ibuf
);
1161 static const struct got_error
*
1162 recv_packfile(int *have_packfile
, struct imsg
*imsg
)
1164 const struct got_error
*err
= NULL
, *unpack_err
;
1165 struct repo_write_client
*client
= &repo_write_client
;
1166 struct gotd_imsg_recv_packfile ireq
;
1167 FILE *tempfiles
[3] = { NULL
, NULL
, NULL
};
1168 struct repo_tempfile
{
1171 } repo_tempfiles
[3] = { { - 1, - 1 }, { - 1, - 1 }, { - 1, - 1 }, };
1174 struct imsgbuf ibuf
;
1175 struct got_ratelimit rl
;
1176 struct got_pack
*pack
= NULL
;
1177 off_t pack_filesize
= 0;
1180 log_debug("packfile request received");
1183 got_ratelimit_init(&rl
, 2, 0);
1185 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1186 if (datalen
!= sizeof(ireq
))
1187 return got_error(GOT_ERR_PRIVSEP_LEN
);
1188 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1190 if (client
->pack_pipe
== -1 || client
->packidx_fd
== -1)
1191 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1193 imsg_init(&ibuf
, client
->fd
);
1196 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1198 pack
= &client
->pack
;
1199 memset(pack
, 0, sizeof(*pack
));
1200 pack
->fd
= imsg
->fd
;
1201 err
= got_delta_cache_alloc(&pack
->delta_cache
);
1205 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1206 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1207 err
= got_repo_temp_fds_get(&t
->fd
, &t
->idx
, repo_write
.repo
);
1212 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1216 fd
= dup(repo_tempfiles
[i
].fd
);
1218 err
= got_error_from_errno("dup");
1221 f
= fdopen(fd
, "w+");
1223 err
= got_error_from_errno("fdopen");
1230 /* Send pack file pipe to gotsh(1). */
1231 if (imsg_compose(&ibuf
, GOTD_IMSG_RECV_PACKFILE
, PROC_REPO_WRITE
,
1232 repo_write
.pid
, (*client
)->pack_pipe
[1], NULL
, 0) == -1) {
1233 (*client
)->pack_pipe
[1] = -1;
1234 err
= got_error_from_errno("imsg_compose ACK");
1238 (*client
)->pack_pipe
[1] = -1;
1239 err
= gotd_imsg_flush(&ibuf
);
1243 log_debug("receiving pack data");
1244 unpack_err
= recv_packdata(&pack_filesize
, &nobj
,
1245 client
->pack_sha1
, client
->pack_pipe
, pack
->fd
);
1246 if (ireq
.report_status
) {
1247 err
= report_pack_status(unpack_err
);
1249 /* Git clients hang up after sending the pack file. */
1250 if (err
->code
== GOT_ERR_EOF
)
1259 log_debug("pack data received");
1262 * Clients which are creating new references only will
1263 * send us an empty pack file.
1266 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1267 client
->nref_updates
> 0 &&
1268 client
->nref_updates
== client
->nref_new
)
1272 * Clients which are deleting references only will send
1276 client
->nref_del
> 0 &&
1277 client
->nref_updates
== client
->nref_del
)
1280 pack
->filesize
= pack_filesize
;
1283 log_debug("begin indexing pack (%lld bytes in size)",
1284 (long long)pack
->filesize
);
1285 err
= got_pack_index(pack
, client
->packidx_fd
,
1286 tempfiles
[0], tempfiles
[1], tempfiles
[2], client
->pack_sha1
,
1287 pack_index_progress
, NULL
, &rl
);
1290 log_debug("done indexing pack");
1292 if (fsync(client
->packidx_fd
) == -1) {
1293 err
= got_error_from_errno("fsync");
1296 if (lseek(client
->packidx_fd
, 0L, SEEK_SET
) == -1)
1297 err
= got_error_from_errno("lseek");
1299 if (close(client
->pack_pipe
) == -1 && err
== NULL
)
1300 err
= got_error_from_errno("close");
1301 client
->pack_pipe
= -1;
1302 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1303 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1305 got_repo_temp_fds_put(t
->idx
, repo_write
.repo
);
1307 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1308 if (tempfiles
[i
] && fclose(tempfiles
[i
]) == EOF
&& err
== NULL
)
1309 err
= got_error_from_errno("fclose");
1312 got_pack_close(pack
);
1317 static const struct got_error
*
1318 verify_packfile(void)
1320 const struct got_error
*err
= NULL
, *close_err
;
1321 struct repo_write_client
*client
= &repo_write_client
;
1322 struct gotd_ref_update
*ref_update
;
1323 struct got_packidx
*packidx
= NULL
;
1325 char *id_str
= NULL
;
1326 struct got_object
*obj
= NULL
;
1327 struct got_pathlist_entry
*pe
;
1328 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1330 if (STAILQ_EMPTY(&client
->ref_updates
)) {
1331 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1332 "cannot verify pack file without any ref-updates");
1335 if (client
->pack
.fd
== -1) {
1336 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1337 "invalid pack file handle during pack verification");
1339 if (client
->packidx_fd
== -1) {
1340 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1341 "invalid pack index handle during pack verification");
1344 if (fstat(client
->packidx_fd
, &sb
) == -1)
1345 return got_error_from_errno("pack index fstat");
1347 packidx
= malloc(sizeof(*packidx
));
1348 memset(packidx
, 0, sizeof(*packidx
));
1349 packidx
->fd
= client
->packidx_fd
;
1350 client
->packidx_fd
= -1;
1351 packidx
->len
= sb
.st_size
;
1353 err
= got_packidx_init_hdr(packidx
, 1, client
->pack
.filesize
);
1357 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1358 if (ref_update
->delete_ref
)
1361 TAILQ_FOREACH(pe
, repo_write
.protected_tag_namespaces
, entry
) {
1362 err
= protect_tag_namespace(pe
->path
, &client
->pack
,
1363 packidx
, ref_update
);
1369 * Objects which already exist in our repository need
1370 * not be present in the pack file.
1372 err
= got_object_open(&obj
, repo_write
.repo
,
1373 &ref_update
->new_id
);
1374 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
1378 got_object_close(obj
);
1381 int idx
= got_packidx_get_object_idx(packidx
,
1382 &ref_update
->new_id
);
1384 got_sha1_digest_to_str(ref_update
->new_id
.sha1
,
1386 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
1387 "object %s is missing from pack file",
1393 TAILQ_FOREACH(pe
, repo_write
.protected_branch_namespaces
,
1395 err
= protect_branch_namespace(pe
->path
,
1396 &client
->pack
, packidx
, ref_update
);
1400 TAILQ_FOREACH(pe
, repo_write
.protected_branches
, entry
) {
1401 err
= protect_branch(pe
->path
, &client
->pack
,
1402 packidx
, ref_update
);
1409 close_err
= got_packidx_close(packidx
);
1410 if (close_err
&& err
== NULL
)
1414 got_object_close(obj
);
1418 static const struct got_error
*
1419 protect_refs_from_deletion(void)
1421 const struct got_error
*err
= NULL
;
1422 struct repo_write_client
*client
= &repo_write_client
;
1423 struct gotd_ref_update
*ref_update
;
1424 struct got_pathlist_entry
*pe
;
1425 const char *refname
;
1427 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1428 if (!ref_update
->delete_ref
)
1431 refname
= got_ref_get_name(ref_update
->ref
);
1433 TAILQ_FOREACH(pe
, repo_write
.protected_tag_namespaces
, entry
) {
1434 err
= protect_ref_namespace(refname
, pe
->path
);
1439 TAILQ_FOREACH(pe
, repo_write
.protected_branch_namespaces
,
1441 err
= protect_ref_namespace(refname
, pe
->path
);
1446 TAILQ_FOREACH(pe
, repo_write
.protected_branches
, entry
) {
1447 if (strcmp(refname
, pe
->path
) == 0) {
1448 return got_error_fmt(GOT_ERR_REF_PROTECTED
,
1457 static const struct got_error
*
1458 install_packfile(struct gotd_imsgev
*iev
)
1460 struct repo_write_client
*client
= &repo_write_client
;
1461 struct gotd_imsg_packfile_install inst
;
1464 memset(&inst
, 0, sizeof(inst
));
1465 inst
.client_id
= client
->id
;
1466 memcpy(inst
.pack_sha1
, client
->pack_sha1
, SHA1_DIGEST_LENGTH
);
1468 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_PACKFILE_INSTALL
,
1469 PROC_REPO_WRITE
, -1, &inst
, sizeof(inst
));
1471 return got_error_from_errno("imsg_compose PACKFILE_INSTALL");
1476 static const struct got_error
*
1477 send_ref_updates_start(int nref_updates
, struct gotd_imsgev
*iev
)
1479 struct repo_write_client
*client
= &repo_write_client
;
1480 struct gotd_imsg_ref_updates_start istart
;
1483 memset(&istart
, 0, sizeof(istart
));
1484 istart
.nref_updates
= nref_updates
;
1485 istart
.client_id
= client
->id
;
1487 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_REF_UPDATES_START
,
1488 PROC_REPO_WRITE
, -1, &istart
, sizeof(istart
));
1490 return got_error_from_errno("imsg_compose REF_UPDATES_START");
1496 static const struct got_error
*
1497 send_ref_update(struct gotd_ref_update
*ref_update
, struct gotd_imsgev
*iev
)
1499 struct repo_write_client
*client
= &repo_write_client
;
1500 struct gotd_imsg_ref_update iref
;
1501 const char *refname
= got_ref_get_name(ref_update
->ref
);
1505 memset(&iref
, 0, sizeof(iref
));
1506 memcpy(iref
.old_id
, ref_update
->old_id
.sha1
, SHA1_DIGEST_LENGTH
);
1507 memcpy(iref
.new_id
, ref_update
->new_id
.sha1
, SHA1_DIGEST_LENGTH
);
1508 iref
.ref_is_new
= ref_update
->ref_is_new
;
1509 iref
.delete_ref
= ref_update
->delete_ref
;
1510 iref
.client_id
= client
->id
;
1511 iref
.name_len
= strlen(refname
);
1513 len
= sizeof(iref
) + iref
.name_len
;
1514 wbuf
= imsg_create(&iev
->ibuf
, GOTD_IMSG_REF_UPDATE
, PROC_REPO_WRITE
,
1515 repo_write
.pid
, len
);
1517 return got_error_from_errno("imsg_create REF_UPDATE");
1519 if (imsg_add(wbuf
, &iref
, sizeof(iref
)) == -1)
1520 return got_error_from_errno("imsg_add REF_UPDATE");
1521 if (imsg_add(wbuf
, refname
, iref
.name_len
) == -1)
1522 return got_error_from_errno("imsg_add REF_UPDATE");
1525 imsg_close(&iev
->ibuf
, wbuf
);
1527 gotd_imsg_event_add(iev
);
1531 static const struct got_error
*
1532 update_refs(struct gotd_imsgev
*iev
)
1534 const struct got_error
*err
= NULL
;
1535 struct repo_write_client
*client
= &repo_write_client
;
1536 struct gotd_ref_update
*ref_update
;
1538 err
= send_ref_updates_start(client
->nref_updates
, iev
);
1542 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1543 err
= send_ref_update(ref_update
, iev
);
1551 static const struct got_error
*
1552 receive_pack_pipe(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1554 struct repo_write_client
*client
= &repo_write_client
;
1555 struct gotd_imsg_packfile_pipe ireq
;
1558 log_debug("receving pack pipe descriptor");
1561 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1563 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1564 if (datalen
!= sizeof(ireq
))
1565 return got_error(GOT_ERR_PRIVSEP_LEN
);
1566 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1568 if (client
->pack_pipe
!= -1)
1569 return got_error(GOT_ERR_PRIVSEP_MSG
);
1571 client
->pack_pipe
= imsg
->fd
;
1575 static const struct got_error
*
1576 receive_pack_idx(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1578 struct repo_write_client
*client
= &repo_write_client
;
1579 struct gotd_imsg_packidx_file ireq
;
1582 log_debug("receving pack index output file");
1585 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1587 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1588 if (datalen
!= sizeof(ireq
))
1589 return got_error(GOT_ERR_PRIVSEP_LEN
);
1590 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1592 if (client
->packidx_fd
!= -1)
1593 return got_error(GOT_ERR_PRIVSEP_MSG
);
1595 client
->packidx_fd
= imsg
->fd
;
1600 repo_write_dispatch_session(int fd
, short event
, void *arg
)
1602 const struct got_error
*err
= NULL
;
1603 struct gotd_imsgev
*iev
= arg
;
1604 struct imsgbuf
*ibuf
= &iev
->ibuf
;
1606 struct repo_write_client
*client
= &repo_write_client
;
1608 int shut
= 0, have_packfile
= 0;
1610 if (event
& EV_READ
) {
1611 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
1612 fatal("imsg_read error");
1613 if (n
== 0) /* Connection closed. */
1617 if (event
& EV_WRITE
) {
1618 n
= msgbuf_write(&ibuf
->w
);
1619 if (n
== -1 && errno
!= EAGAIN
)
1620 fatal("msgbuf_write");
1621 if (n
== 0) /* Connection closed. */
1626 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
1627 fatal("%s: imsg_get error", __func__
);
1628 if (n
== 0) /* No more messages. */
1631 if (imsg
.hdr
.type
!= GOTD_IMSG_LIST_REFS_INTERNAL
&&
1633 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1637 switch (imsg
.hdr
.type
) {
1638 case GOTD_IMSG_LIST_REFS_INTERNAL
:
1639 err
= list_refs(&imsg
);
1641 log_warnx("ls-refs: %s", err
->msg
);
1643 case GOTD_IMSG_REF_UPDATE
:
1644 err
= recv_ref_update(&imsg
);
1646 log_warnx("ref-update: %s", err
->msg
);
1648 case GOTD_IMSG_PACKFILE_PIPE
:
1649 err
= receive_pack_pipe(&imsg
, iev
);
1651 log_warnx("receiving pack pipe: %s", err
->msg
);
1655 case GOTD_IMSG_PACKIDX_FILE
:
1656 err
= receive_pack_idx(&imsg
, iev
);
1658 log_warnx("receiving pack index: %s",
1663 case GOTD_IMSG_RECV_PACKFILE
:
1664 err
= protect_refs_from_deletion();
1667 err
= recv_packfile(&have_packfile
, &imsg
);
1669 log_warnx("receive packfile: %s", err
->msg
);
1672 if (have_packfile
) {
1673 err
= verify_packfile();
1675 log_warnx("verify packfile: %s",
1679 err
= install_packfile(iev
);
1681 log_warnx("install packfile: %s",
1686 err
= update_refs(iev
);
1688 log_warnx("update refs: %s", err
->msg
);
1692 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
1699 if (!shut
&& check_cancelled(NULL
) == NULL
) {
1701 gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
1702 client
->id
, err
) == -1) {
1703 log_warnx("could not send error to parent: %s",
1706 gotd_imsg_event_add(iev
);
1708 /* This pipe is dead. Remove its event handler */
1709 event_del(&iev
->ev
);
1710 event_loopexit(NULL
);
1714 static const struct got_error
*
1715 recv_connect(struct imsg
*imsg
)
1717 struct gotd_imsgev
*iev
= &repo_write
.session_iev
;
1720 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1722 return got_error(GOT_ERR_PRIVSEP_LEN
);
1724 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1726 if (repo_write
.session_fd
!= -1)
1727 return got_error(GOT_ERR_PRIVSEP_MSG
);
1729 repo_write
.session_fd
= imsg
->fd
;
1731 imsg_init(&iev
->ibuf
, repo_write
.session_fd
);
1732 iev
->handler
= repo_write_dispatch_session
;
1733 iev
->events
= EV_READ
;
1734 iev
->handler_arg
= NULL
;
1735 event_set(&iev
->ev
, iev
->ibuf
.fd
, EV_READ
,
1736 repo_write_dispatch_session
, iev
);
1737 gotd_imsg_event_add(iev
);
1743 repo_write_dispatch(int fd
, short event
, void *arg
)
1745 const struct got_error
*err
= NULL
;
1746 struct gotd_imsgev
*iev
= arg
;
1747 struct imsgbuf
*ibuf
= &iev
->ibuf
;
1751 struct repo_write_client
*client
= &repo_write_client
;
1753 if (event
& EV_READ
) {
1754 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
1755 fatal("imsg_read error");
1756 if (n
== 0) /* Connection closed. */
1760 if (event
& EV_WRITE
) {
1761 n
= msgbuf_write(&ibuf
->w
);
1762 if (n
== -1 && errno
!= EAGAIN
)
1763 fatal("msgbuf_write");
1764 if (n
== 0) /* Connection closed. */
1768 while (err
== NULL
&& check_cancelled(NULL
) == NULL
) {
1769 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
1770 fatal("%s: imsg_get", __func__
);
1771 if (n
== 0) /* No more messages. */
1774 switch (imsg
.hdr
.type
) {
1775 case GOTD_IMSG_CONNECT_REPO_CHILD
:
1776 err
= recv_connect(&imsg
);
1779 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
1786 if (!shut
&& check_cancelled(NULL
) == NULL
) {
1788 gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
1789 client
->id
, err
) == -1) {
1790 log_warnx("could not send error to parent: %s",
1793 gotd_imsg_event_add(iev
);
1795 /* This pipe is dead. Remove its event handler */
1796 event_del(&iev
->ev
);
1797 event_loopexit(NULL
);
1802 repo_write_main(const char *title
, const char *repo_path
,
1803 int *pack_fds
, int *temp_fds
,
1804 struct got_pathlist_head
*protected_tag_namespaces
,
1805 struct got_pathlist_head
*protected_branch_namespaces
,
1806 struct got_pathlist_head
*protected_branches
)
1808 const struct got_error
*err
= NULL
;
1809 struct repo_write_client
*client
= &repo_write_client
;
1810 struct gotd_imsgev iev
;
1813 client
->pack_pipe
= -1;
1814 client
->packidx_fd
= -1;
1815 client
->pack
.fd
= -1;
1817 repo_write
.title
= title
;
1818 repo_write
.pid
= getpid();
1819 repo_write
.pack_fds
= pack_fds
;
1820 repo_write
.temp_fds
= temp_fds
;
1821 repo_write
.session_fd
= -1;
1822 repo_write
.session_iev
.ibuf
.fd
= -1;
1823 repo_write
.protected_tag_namespaces
= protected_tag_namespaces
;
1824 repo_write
.protected_branch_namespaces
= protected_branch_namespaces
;
1825 repo_write
.protected_branches
= protected_branches
;
1827 STAILQ_INIT(&repo_write_client
.ref_updates
);
1829 err
= got_repo_open(&repo_write
.repo
, repo_path
, NULL
, pack_fds
);
1832 if (!got_repo_is_bare(repo_write
.repo
)) {
1833 err
= got_error_msg(GOT_ERR_NOT_GIT_REPO
,
1834 "bare git repository required");
1838 got_repo_temp_fds_set(repo_write
.repo
, temp_fds
);
1840 signal(SIGINT
, catch_sigint
);
1841 signal(SIGTERM
, catch_sigterm
);
1842 signal(SIGPIPE
, SIG_IGN
);
1843 signal(SIGHUP
, SIG_IGN
);
1845 imsg_init(&iev
.ibuf
, GOTD_FILENO_MSG_PIPE
);
1846 iev
.handler
= repo_write_dispatch
;
1847 iev
.events
= EV_READ
;
1848 iev
.handler_arg
= NULL
;
1849 event_set(&iev
.ev
, iev
.ibuf
.fd
, EV_READ
, repo_write_dispatch
, &iev
);
1850 if (gotd_imsg_compose_event(&iev
, GOTD_IMSG_REPO_CHILD_READY
,
1851 PROC_REPO_WRITE
, -1, NULL
, 0) == -1) {
1852 err
= got_error_from_errno("imsg compose REPO_CHILD_READY");
1859 log_warnx("%s: %s", title
, err
->msg
);
1860 repo_write_shutdown();
1864 repo_write_shutdown(void)
1866 struct repo_write_client
*client
= &repo_write_client
;
1867 struct gotd_ref_update
*ref_update
;
1869 log_debug("shutting down");
1871 while (!STAILQ_EMPTY(&client
->ref_updates
)) {
1872 ref_update
= STAILQ_FIRST(&client
->ref_updates
);
1873 STAILQ_REMOVE_HEAD(&client
->ref_updates
, entry
);
1874 got_ref_close(ref_update
->ref
);
1878 got_pack_close(&client
->pack
);
1879 if (client
->fd
!= -1)
1881 if (client
->pack_pipe
!= -1)
1882 close(client
->pack_pipe
);
1883 if (client
->packidx_fd
!= -1)
1884 close(client
->packidx_fd
);
1886 if (repo_write
.repo
)
1887 got_repo_close(repo_write
.repo
);
1888 got_repo_pack_fds_close(repo_write
.pack_fds
);
1889 got_repo_temp_fds_close(repo_write
.temp_fds
);
1890 if (repo_write
.session_fd
!= -1)
1891 close(repo_write
.session_fd
);