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>
35 #include "got_error.h"
36 #include "got_repository.h"
37 #include "got_object.h"
38 #include "got_reference.h"
41 #include "got_lib_delta.h"
42 #include "got_lib_delta_cache.h"
43 #include "got_lib_hash.h"
44 #include "got_lib_object.h"
45 #include "got_lib_object_cache.h"
46 #include "got_lib_object_idset.h"
47 #include "got_lib_object_parse.h"
48 #include "got_lib_ratelimit.h"
49 #include "got_lib_pack.h"
50 #include "got_lib_pack_index.h"
51 #include "got_lib_repository.h"
52 #include "got_lib_poll.h"
56 #include "repo_write.h"
59 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
62 static struct repo_write
{
65 struct got_repository
*repo
;
69 struct gotd_imsgev session_iev
;
70 struct got_pathlist_head
*protected_tag_namespaces
;
71 struct got_pathlist_head
*protected_branch_namespaces
;
72 struct got_pathlist_head
*protected_branches
;
75 struct gotd_ref_update
{
76 STAILQ_ENTRY(gotd_ref_update
) entry
;
77 struct got_reference
*ref
;
80 struct got_object_id old_id
;
81 struct got_object_id new_id
;
83 STAILQ_HEAD(gotd_ref_updates
, gotd_ref_update
);
85 static struct repo_write_client
{
90 uint8_t pack_sha1
[SHA1_DIGEST_LENGTH
];
92 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;
265 client
->nref_move
= 0;
267 imsg_init(&ibuf
, client_fd
);
269 err
= got_ref_list(&refs
, repo_write
.repo
, "",
270 got_ref_cmp_by_name
, NULL
);
274 memset(&irefs
, 0, sizeof(irefs
));
275 TAILQ_FOREACH(re
, &refs
, entry
) {
276 struct got_object_id
*id
;
279 if (got_ref_is_symbolic(re
->ref
))
284 /* Account for a peeled tag refs. */
285 err
= got_ref_resolve(&id
, repo_write
.repo
, re
->ref
);
288 err
= got_object_get_type(&obj_type
, repo_write
.repo
, id
);
292 if (obj_type
== GOT_OBJ_TYPE_TAG
)
296 if (imsg_compose(&ibuf
, GOTD_IMSG_REFLIST
, PROC_REPO_WRITE
,
297 repo_write
.pid
, -1, &irefs
, sizeof(irefs
)) == -1) {
298 err
= got_error_from_errno("imsg_compose REFLIST");
302 TAILQ_FOREACH(re
, &refs
, entry
) {
303 if (got_ref_is_symbolic(re
->ref
))
305 err
= send_ref(re
->ref
, &ibuf
);
310 err
= gotd_imsg_flush(&ibuf
);
312 got_ref_list_free(&refs
);
317 static const struct got_error
*
318 validate_namespace(const char *namespace)
320 size_t len
= strlen(namespace);
322 if (len
< 5 || strncmp("refs/", namespace, 5) != 0 ||
323 namespace[len
-1] != '/') {
324 return got_error_fmt(GOT_ERR_BAD_REF_NAME
,
325 "reference namespace '%s'", namespace);
331 static const struct got_error
*
332 protect_ref_namespace(const char *refname
, const char *namespace)
334 const struct got_error
*err
;
336 err
= validate_namespace(namespace);
340 if (strncmp(namespace, refname
, strlen(namespace)) == 0)
341 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
346 static const struct got_error
*
347 verify_object_type(struct got_object_id
*id
, int expected_obj_type
,
348 struct got_pack
*pack
, struct got_packidx
*packidx
)
350 const struct got_error
*err
;
351 char hex
[SHA1_DIGEST_STRING_LENGTH
];
352 struct got_object
*obj
;
356 idx
= got_packidx_get_object_idx(packidx
, id
);
358 got_sha1_digest_to_str(id
->sha1
, hex
, sizeof(hex
));
359 return got_error_fmt(GOT_ERR_BAD_PACKFILE
,
360 "object %s is missing from pack file", hex
);
363 err
= got_object_open_from_packfile(&obj
, id
, pack
, packidx
,
364 idx
, repo_write
.repo
);
368 if (obj
->type
!= expected_obj_type
) {
369 got_sha1_digest_to_str(id
->sha1
, hex
, sizeof(hex
));
370 got_object_type_label(&typestr
, expected_obj_type
);
371 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
372 "%s is not pointing at a %s object", hex
, typestr
);
374 got_object_close(obj
);
378 static const struct got_error
*
379 protect_tag_namespace(const char *namespace, struct got_pack
*pack
,
380 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
382 const struct got_error
*err
;
384 err
= validate_namespace(namespace);
388 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
389 strlen(namespace)) != 0)
392 if (!ref_update
->ref_is_new
)
393 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
395 return verify_object_type(&ref_update
->new_id
, GOT_OBJ_TYPE_TAG
,
399 static const struct got_error
*
400 protect_require_yca(struct got_object_id
*tip_id
,
401 size_t max_commits_to_traverse
, struct got_pack
*pack
,
402 struct got_packidx
*packidx
, struct got_reference
*ref
)
404 const struct got_error
*err
;
407 struct got_object_id
*expected_yca_id
= NULL
;
408 struct got_object
*obj
= NULL
;
409 struct got_commit_object
*commit
= NULL
;
410 char hex
[SHA1_DIGEST_STRING_LENGTH
];
411 const struct got_object_id_queue
*parent_ids
;
412 struct got_object_id_queue ids
;
413 struct got_object_qid
*pid
, *qid
;
414 struct got_object_idset
*traversed_set
= NULL
;
415 int found_yca
= 0, obj_type
;
419 err
= got_ref_resolve(&expected_yca_id
, repo_write
.repo
, ref
);
423 err
= got_object_get_type(&obj_type
, repo_write
.repo
, expected_yca_id
);
427 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
) {
428 got_sha1_digest_to_str(expected_yca_id
->sha1
, hex
, sizeof(hex
));
429 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
430 "%s is not pointing at a commit object", hex
);
434 traversed_set
= got_object_idset_alloc();
435 if (traversed_set
== NULL
) {
436 err
= got_error_from_errno("got_object_idset_alloc");
440 err
= got_object_qid_alloc(&qid
, tip_id
);
443 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
444 while (!STAILQ_EMPTY(&ids
)) {
445 err
= check_cancelled(NULL
);
449 qid
= STAILQ_FIRST(&ids
);
450 if (got_object_id_cmp(&qid
->id
, expected_yca_id
) == 0) {
455 if (got_object_idset_num_elements(traversed_set
) >=
456 max_commits_to_traverse
)
459 if (got_object_idset_contains(traversed_set
, &qid
->id
)) {
460 STAILQ_REMOVE_HEAD(&ids
, entry
);
461 got_object_qid_free(qid
);
465 err
= got_object_idset_add(traversed_set
, &qid
->id
, NULL
);
469 err
= got_object_open(&obj
, repo_write
.repo
, &qid
->id
);
470 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
474 err
= got_object_commit_open(&commit
, repo_write
.repo
,
481 idx
= got_packidx_get_object_idx(packidx
, &qid
->id
);
483 got_sha1_digest_to_str(qid
->id
.sha1
,
485 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
486 "object %s is missing from pack file", hex
);
490 err
= got_object_open_from_packfile(&obj
, &qid
->id
,
491 pack
, packidx
, idx
, repo_write
.repo
);
495 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
496 got_sha1_digest_to_str(qid
->id
.sha1
,
498 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
499 "%s is not pointing at a commit object",
504 err
= got_packfile_extract_object_to_mem(&buf
, &len
,
509 err
= got_object_parse_commit(&commit
, buf
, len
);
517 got_object_close(obj
);
520 STAILQ_REMOVE_HEAD(&ids
, entry
);
521 got_object_qid_free(qid
);
524 if (got_object_commit_get_nparents(commit
) == 0)
527 parent_ids
= got_object_commit_get_parent_ids(commit
);
528 STAILQ_FOREACH(pid
, parent_ids
, entry
) {
529 err
= check_cancelled(NULL
);
532 err
= got_object_qid_alloc(&qid
, &pid
->id
);
535 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
538 got_object_commit_close(commit
);
543 err
= got_error_fmt(GOT_ERR_REF_PROTECTED
, "%s",
544 got_ref_get_name(ref
));
547 got_object_idset_free(traversed_set
);
548 got_object_id_queue_free(&ids
);
551 got_object_close(obj
);
553 got_object_commit_close(commit
);
554 free(expected_yca_id
);
558 static const struct got_error
*
559 protect_branch_namespace(const char *namespace, struct got_pack
*pack
,
560 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
562 const struct got_error
*err
;
564 err
= validate_namespace(namespace);
568 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
569 strlen(namespace)) != 0)
572 if (ref_update
->ref_is_new
) {
573 return verify_object_type(&ref_update
->new_id
,
574 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
577 return protect_require_yca(&ref_update
->new_id
,
578 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
582 static const struct got_error
*
583 protect_branch(const char *refname
, struct got_pack
*pack
,
584 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
586 if (strcmp(refname
, got_ref_get_name(ref_update
->ref
)) != 0)
589 /* Always allow new branches to be created. */
590 if (ref_update
->ref_is_new
) {
591 return verify_object_type(&ref_update
->new_id
,
592 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
595 return protect_require_yca(&ref_update
->new_id
,
596 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
600 static const struct got_error
*
601 recv_ref_update(struct imsg
*imsg
)
603 static const char zero_id
[SHA1_DIGEST_LENGTH
];
604 const struct got_error
*err
= NULL
;
605 struct repo_write_client
*client
= &repo_write_client
;
606 struct gotd_imsg_ref_update iref
;
608 char *refname
= NULL
;
609 struct got_reference
*ref
= NULL
;
610 struct got_object_id
*id
= NULL
;
612 struct gotd_ref_update
*ref_update
= NULL
;
614 log_debug("ref-update received");
616 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
617 if (datalen
< sizeof(iref
))
618 return got_error(GOT_ERR_PRIVSEP_LEN
);
619 memcpy(&iref
, imsg
->data
, sizeof(iref
));
620 if (datalen
!= sizeof(iref
) + iref
.name_len
)
621 return got_error(GOT_ERR_PRIVSEP_LEN
);
623 imsg_init(&ibuf
, client
->fd
);
625 refname
= strndup(imsg
->data
+ sizeof(iref
), iref
.name_len
);
627 return got_error_from_errno("strndup");
629 ref_update
= calloc(1, sizeof(*ref_update
));
630 if (ref_update
== NULL
) {
631 err
= got_error_from_errno("malloc");
635 memcpy(ref_update
->old_id
.sha1
, iref
.old_id
, SHA1_DIGEST_LENGTH
);
636 memcpy(ref_update
->new_id
.sha1
, iref
.new_id
, SHA1_DIGEST_LENGTH
);
638 err
= got_ref_open(&ref
, repo_write
.repo
, refname
, 0);
640 if (err
->code
!= GOT_ERR_NOT_REF
)
642 if (memcmp(ref_update
->new_id
.sha1
,
643 zero_id
, sizeof(zero_id
)) == 0) {
644 err
= got_error_fmt(GOT_ERR_BAD_OBJ_ID
,
648 err
= got_ref_alloc(&ref
, refname
, &ref_update
->new_id
);
651 ref_update
->ref_is_new
= 1;
654 if (got_ref_is_symbolic(ref
)) {
655 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
656 "'%s' is a symbolic reference and cannot "
657 "be updated", got_ref_get_name(ref
));
660 if (strncmp("refs/", got_ref_get_name(ref
), 5) != 0) {
661 err
= got_error_fmt(GOT_ERR_BAD_REF_NAME
,
662 "%s: does not begin with 'refs/'",
663 got_ref_get_name(ref
));
667 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/got/");
670 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/remotes/");
674 if (!ref_update
->ref_is_new
) {
676 * Ensure the client's idea of this update is still valid.
677 * At this point we can only return an error, to prevent
678 * the client from uploading a pack file which will likely
679 * have to be discarded.
681 err
= got_ref_resolve(&id
, repo_write
.repo
, ref
);
685 if (got_object_id_cmp(id
, &ref_update
->old_id
) != 0) {
686 err
= got_error_fmt(GOT_ERR_REF_BUSY
,
687 "%s has been modified by someone else "
688 "while transaction was in progress",
689 got_ref_get_name(ref
));
694 gotd_imsg_send_ack(&ref_update
->new_id
, &ibuf
, PROC_REPO_WRITE
,
697 ref_update
->ref
= ref
;
698 if (memcmp(ref_update
->new_id
.sha1
, zero_id
, sizeof(zero_id
)) == 0) {
699 ref_update
->delete_ref
= 1;
702 STAILQ_INSERT_HEAD(&client
->ref_updates
, ref_update
, entry
);
703 client
->nref_updates
++;
715 static const struct got_error
*
716 pack_index_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
717 uint32_t nobj_loose
, uint32_t nobj_resolved
)
719 int p_indexed
= 0, p_resolved
= 0;
720 int nobj_delta
= nobj_total
- nobj_loose
;
723 p_indexed
= (nobj_indexed
* 100) / nobj_total
;
726 p_resolved
= (nobj_resolved
* 100) / nobj_delta
;
728 if (p_resolved
> 0) {
729 log_debug("indexing %d objects %d%%; resolving %d deltas %d%%",
730 nobj_total
, p_indexed
, nobj_delta
, p_resolved
);
732 log_debug("indexing %d objects %d%%", nobj_total
, p_indexed
);
737 static const struct got_error
*
738 read_more_pack_stream(int infd
, BUF
*buf
, size_t minsize
)
740 const struct got_error
*err
= NULL
;
741 uint8_t readahead
[65536];
744 err
= got_poll_read_full(infd
, &have
,
745 readahead
, sizeof(readahead
), minsize
);
749 err
= buf_append(&newlen
, buf
, readahead
, have
);
755 static const struct got_error
*
756 copy_object_type_and_size(uint8_t *type
, uint64_t *size
, int infd
, int outfd
,
757 off_t
*outsize
, BUF
*buf
, size_t *buf_pos
, struct got_hash
*ctx
)
759 const struct got_error
*err
= NULL
;
764 off_t obj_offset
= *outsize
;
767 /* We do not support size values which don't fit in 64 bit. */
769 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
770 "packfile offset %lld", (long long)obj_offset
);
772 if (buf_len(buf
) - *buf_pos
< sizeof(sizebuf
[0])) {
773 err
= read_more_pack_stream(infd
, buf
,
779 sizebuf
[i
] = buf_getc(buf
, *buf_pos
);
780 *buf_pos
+= sizeof(sizebuf
[i
]);
783 t
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_TYPE_MASK
) >>
784 GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT
;
785 s
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_VAL_MASK
);
787 size_t shift
= 4 + 7 * (i
- 1);
788 s
|= ((sizebuf
[i
] & GOT_PACK_OBJ_SIZE_VAL_MASK
) <<
792 } while (sizebuf
[i
- 1] & GOT_PACK_OBJ_SIZE_MORE
);
794 err
= got_pack_hwrite(outfd
, sizebuf
, i
, ctx
);
804 static const struct got_error
*
805 copy_ref_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
806 struct got_hash
*ctx
)
808 const struct got_error
*err
= NULL
;
809 size_t remain
= buf_len(buf
) - *buf_pos
;
811 if (remain
< SHA1_DIGEST_LENGTH
) {
812 err
= read_more_pack_stream(infd
, buf
,
813 SHA1_DIGEST_LENGTH
- remain
);
818 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
819 SHA1_DIGEST_LENGTH
, ctx
);
823 *buf_pos
+= SHA1_DIGEST_LENGTH
;
827 static const struct got_error
*
828 copy_offset_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
829 struct got_hash
*ctx
)
831 const struct got_error
*err
= NULL
;
835 off_t obj_offset
= *outsize
;
838 /* We do not support offset values which don't fit in 64 bit. */
840 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
841 "packfile offset %lld", (long long)obj_offset
);
843 if (buf_len(buf
) - *buf_pos
< sizeof(offbuf
[0])) {
844 err
= read_more_pack_stream(infd
, buf
,
850 offbuf
[i
] = buf_getc(buf
, *buf_pos
);
851 *buf_pos
+= sizeof(offbuf
[i
]);
854 o
= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
858 o
+= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
861 } while (offbuf
[i
- 1] & GOT_PACK_OBJ_DELTA_OFF_MORE
);
863 if (o
< sizeof(struct got_packfile_hdr
) || o
> *outsize
)
864 return got_error(GOT_ERR_PACK_OFFSET
);
866 err
= got_pack_hwrite(outfd
, offbuf
, i
, ctx
);
874 static const struct got_error
*
875 copy_zstream(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
876 struct got_hash
*ctx
)
878 const struct got_error
*err
= NULL
;
882 size_t consumed_total
= 0;
883 off_t zstream_offset
= *outsize
;
885 memset(&z
, 0, sizeof(z
));
889 zret
= inflateInit(&z
);
892 return got_error_from_errno("inflateInit");
893 if (zret
== Z_MEM_ERROR
) {
895 return got_error_from_errno("inflateInit");
897 return got_error_msg(GOT_ERR_DECOMPRESSION
,
898 "inflateInit failed");
901 while (zret
!= Z_STREAM_END
) {
902 size_t last_total_in
, consumed
;
905 * Decompress into the void. Object data will be parsed
906 * later, when the pack file is indexed. For now, we just
907 * want to locate the end of the compressed stream.
909 while (zret
!= Z_STREAM_END
&& buf_len(buf
) - *buf_pos
> 0) {
910 last_total_in
= z
.total_in
;
911 z
.next_in
= buf_get(buf
) + *buf_pos
;
912 z
.avail_in
= buf_len(buf
) - *buf_pos
;
913 z
.next_out
= voidbuf
;
914 z
.avail_out
= sizeof(voidbuf
);
916 zret
= inflate(&z
, Z_SYNC_FLUSH
);
917 if (zret
!= Z_OK
&& zret
!= Z_BUF_ERROR
&&
918 zret
!= Z_STREAM_END
) {
919 err
= got_error_fmt(GOT_ERR_DECOMPRESSION
,
920 "packfile offset %lld",
921 (long long)zstream_offset
);
924 consumed
= z
.total_in
- last_total_in
;
926 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
931 err
= buf_discard(buf
, *buf_pos
+ consumed
);
936 consumed_total
+= consumed
;
939 if (zret
!= Z_STREAM_END
) {
940 err
= read_more_pack_stream(infd
, buf
, 1);
947 *outsize
+= consumed_total
;
953 static const struct got_error
*
954 validate_object_type(int obj_type
)
957 case GOT_OBJ_TYPE_BLOB
:
958 case GOT_OBJ_TYPE_COMMIT
:
959 case GOT_OBJ_TYPE_TREE
:
960 case GOT_OBJ_TYPE_TAG
:
961 case GOT_OBJ_TYPE_REF_DELTA
:
962 case GOT_OBJ_TYPE_OFFSET_DELTA
:
968 return got_error(GOT_ERR_OBJ_TYPE
);
971 static const struct got_error
*
972 ensure_all_objects_exist_locally(struct gotd_ref_updates
*ref_updates
)
974 const struct got_error
*err
= NULL
;
975 struct gotd_ref_update
*ref_update
;
976 struct got_object
*obj
;
978 STAILQ_FOREACH(ref_update
, ref_updates
, entry
) {
979 err
= got_object_open(&obj
, repo_write
.repo
,
980 &ref_update
->new_id
);
983 got_object_close(obj
);
989 static const struct got_error
*
990 recv_packdata(off_t
*outsize
, uint32_t *nobj
, uint8_t *sha1
,
993 const struct got_error
*err
;
994 struct repo_write_client
*client
= &repo_write_client
;
995 struct got_packfile_hdr hdr
;
999 uint8_t expected_sha1
[SHA1_DIGEST_LENGTH
];
1000 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1002 size_t buf_pos
= 0, remain
;
1008 /* if only deleting references there's nothing to read */
1009 if (client
->nref_updates
== client
->nref_del
)
1012 got_hash_init(&ctx
, GOT_HASH_SHA1
);
1014 err
= got_poll_read_full(infd
, &have
, &hdr
, sizeof(hdr
), sizeof(hdr
));
1017 if (have
!= sizeof(hdr
))
1018 return got_error_msg(GOT_ERR_BAD_PACKFILE
, "short pack file");
1021 if (hdr
.signature
!= htobe32(GOT_PACKFILE_SIGNATURE
))
1022 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1023 "bad packfile signature");
1024 if (hdr
.version
!= htobe32(GOT_PACKFILE_VERSION
))
1025 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1026 "bad packfile version");
1028 *nobj
= be32toh(hdr
.nobjects
);
1031 * Clients which are creating new references only
1032 * will send us an empty pack file.
1034 if (client
->nref_updates
> 0 &&
1035 client
->nref_updates
== client
->nref_new
)
1039 * Clients which only move existing refs will send us an empty
1040 * pack file. All referenced objects must exist locally.
1042 err
= ensure_all_objects_exist_locally(&client
->ref_updates
);
1044 if (err
->code
!= GOT_ERR_NO_OBJ
)
1046 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1047 "bad packfile with zero objects");
1050 client
->nref_move
= client
->nref_updates
;
1054 log_debug("expecting %d objects", *nobj
);
1056 err
= got_pack_hwrite(outfd
, &hdr
, sizeof(hdr
), &ctx
);
1060 err
= buf_alloc(&buf
, 65536);
1064 while (nhave
!= *nobj
) {
1068 err
= copy_object_type_and_size(&obj_type
, &obj_size
,
1069 infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1073 err
= validate_object_type(obj_type
);
1077 if (obj_type
== GOT_OBJ_TYPE_REF_DELTA
) {
1078 err
= copy_ref_delta(infd
, outfd
, outsize
,
1079 buf
, &buf_pos
, &ctx
);
1082 } else if (obj_type
== GOT_OBJ_TYPE_OFFSET_DELTA
) {
1083 err
= copy_offset_delta(infd
, outfd
, outsize
,
1084 buf
, &buf_pos
, &ctx
);
1089 err
= copy_zstream(infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1096 log_debug("received %u objects", *nobj
);
1098 got_hash_final(&ctx
, expected_sha1
);
1100 remain
= buf_len(buf
) - buf_pos
;
1101 if (remain
< SHA1_DIGEST_LENGTH
) {
1102 err
= read_more_pack_stream(infd
, buf
,
1103 SHA1_DIGEST_LENGTH
- remain
);
1108 got_sha1_digest_to_str(expected_sha1
, hex
, sizeof(hex
));
1109 log_debug("expect SHA1: %s", hex
);
1110 got_sha1_digest_to_str(buf_get(buf
) + buf_pos
, hex
, sizeof(hex
));
1111 log_debug("actual SHA1: %s", hex
);
1113 if (memcmp(buf_get(buf
) + buf_pos
, expected_sha1
,
1114 SHA1_DIGEST_LENGTH
) != 0) {
1115 err
= got_error(GOT_ERR_PACKFILE_CSUM
);
1119 memcpy(sha1
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1121 w
= write(outfd
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1123 err
= got_error_from_errno("write");
1126 if (w
!= SHA1_DIGEST_LENGTH
) {
1127 err
= got_error(GOT_ERR_IO
);
1131 *outsize
+= SHA1_DIGEST_LENGTH
;
1133 if (fsync(outfd
) == -1) {
1134 err
= got_error_from_errno("fsync");
1137 if (lseek(outfd
, 0L, SEEK_SET
) == -1) {
1138 err
= got_error_from_errno("lseek");
1146 static const struct got_error
*
1147 report_pack_status(const struct got_error
*unpack_err
)
1149 const struct got_error
*err
= NULL
;
1150 struct repo_write_client
*client
= &repo_write_client
;
1151 struct gotd_imsg_packfile_status istatus
;
1153 struct imsgbuf ibuf
;
1154 const char *unpack_ok
= "unpack ok\n";
1157 imsg_init(&ibuf
, client
->fd
);
1160 istatus
.reason_len
= strlen(unpack_err
->msg
);
1162 istatus
.reason_len
= strlen(unpack_ok
);
1164 len
= sizeof(istatus
) + istatus
.reason_len
;
1165 wbuf
= imsg_create(&ibuf
, GOTD_IMSG_PACKFILE_STATUS
, PROC_REPO_WRITE
,
1166 repo_write
.pid
, len
);
1168 err
= got_error_from_errno("imsg_create PACKFILE_STATUS");
1172 if (imsg_add(wbuf
, &istatus
, sizeof(istatus
)) == -1) {
1173 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1177 if (imsg_add(wbuf
, err
? err
->msg
: unpack_ok
,
1178 istatus
.reason_len
) == -1) {
1179 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1184 imsg_close(&ibuf
, wbuf
);
1186 err
= gotd_imsg_flush(&ibuf
);
1192 static const struct got_error
*
1193 recv_packfile(int *have_packfile
, struct imsg
*imsg
)
1195 const struct got_error
*err
= NULL
, *unpack_err
;
1196 struct repo_write_client
*client
= &repo_write_client
;
1197 struct gotd_imsg_recv_packfile ireq
;
1198 FILE *tempfiles
[3] = { NULL
, NULL
, NULL
};
1199 struct repo_tempfile
{
1202 } repo_tempfiles
[3] = { { - 1, - 1 }, { - 1, - 1 }, { - 1, - 1 }, };
1205 struct imsgbuf ibuf
;
1206 struct got_ratelimit rl
;
1207 struct got_pack
*pack
= NULL
;
1208 off_t pack_filesize
= 0;
1211 log_debug("packfile request received");
1214 got_ratelimit_init(&rl
, 2, 0);
1216 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1217 if (datalen
!= sizeof(ireq
))
1218 return got_error(GOT_ERR_PRIVSEP_LEN
);
1219 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1221 if (client
->pack_pipe
== -1 || client
->packidx_fd
== -1)
1222 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1224 imsg_init(&ibuf
, client
->fd
);
1227 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1229 pack
= &client
->pack
;
1230 memset(pack
, 0, sizeof(*pack
));
1231 pack
->fd
= imsg
->fd
;
1232 err
= got_delta_cache_alloc(&pack
->delta_cache
);
1236 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1237 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1238 err
= got_repo_temp_fds_get(&t
->fd
, &t
->idx
, repo_write
.repo
);
1243 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1247 fd
= dup(repo_tempfiles
[i
].fd
);
1249 err
= got_error_from_errno("dup");
1252 f
= fdopen(fd
, "w+");
1254 err
= got_error_from_errno("fdopen");
1261 err
= gotd_imsg_flush(&ibuf
);
1265 log_debug("receiving pack data");
1266 unpack_err
= recv_packdata(&pack_filesize
, &nobj
,
1267 client
->pack_sha1
, client
->pack_pipe
, pack
->fd
);
1268 if (ireq
.report_status
) {
1269 err
= report_pack_status(unpack_err
);
1271 /* Git clients hang up after sending the pack file. */
1272 if (err
->code
== GOT_ERR_EOF
)
1281 log_debug("pack data received");
1284 * Clients which are creating new references only will
1285 * send us an empty pack file.
1288 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1289 client
->nref_updates
> 0 &&
1290 client
->nref_updates
== client
->nref_new
)
1294 * Clients which are deleting references only will send
1298 client
->nref_del
> 0 &&
1299 client
->nref_updates
== client
->nref_del
)
1303 * Clients which only move existing refs will send us an empty
1304 * pack file. All referenced objects must exist locally.
1307 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1308 client
->nref_move
> 0 &&
1309 client
->nref_updates
== client
->nref_move
)
1312 pack
->filesize
= pack_filesize
;
1315 log_debug("begin indexing pack (%lld bytes in size)",
1316 (long long)pack
->filesize
);
1317 err
= got_pack_index(pack
, client
->packidx_fd
,
1318 tempfiles
[0], tempfiles
[1], tempfiles
[2], client
->pack_sha1
,
1319 pack_index_progress
, NULL
, &rl
);
1322 log_debug("done indexing pack");
1324 if (fsync(client
->packidx_fd
) == -1) {
1325 err
= got_error_from_errno("fsync");
1328 if (lseek(client
->packidx_fd
, 0L, SEEK_SET
) == -1)
1329 err
= got_error_from_errno("lseek");
1331 if (close(client
->pack_pipe
) == -1 && err
== NULL
)
1332 err
= got_error_from_errno("close");
1333 client
->pack_pipe
= -1;
1334 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1335 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1337 got_repo_temp_fds_put(t
->idx
, repo_write
.repo
);
1339 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1340 if (tempfiles
[i
] && fclose(tempfiles
[i
]) == EOF
&& err
== NULL
)
1341 err
= got_error_from_errno("fclose");
1344 got_pack_close(pack
);
1349 static const struct got_error
*
1350 verify_packfile(void)
1352 const struct got_error
*err
= NULL
, *close_err
;
1353 struct repo_write_client
*client
= &repo_write_client
;
1354 struct gotd_ref_update
*ref_update
;
1355 struct got_packidx
*packidx
= NULL
;
1357 char *id_str
= NULL
;
1358 struct got_object
*obj
= NULL
;
1359 struct got_pathlist_entry
*pe
;
1360 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1362 if (STAILQ_EMPTY(&client
->ref_updates
)) {
1363 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1364 "cannot verify pack file without any ref-updates");
1367 if (client
->pack
.fd
== -1) {
1368 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1369 "invalid pack file handle during pack verification");
1371 if (client
->packidx_fd
== -1) {
1372 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1373 "invalid pack index handle during pack verification");
1376 if (fstat(client
->packidx_fd
, &sb
) == -1)
1377 return got_error_from_errno("pack index fstat");
1379 packidx
= malloc(sizeof(*packidx
));
1380 memset(packidx
, 0, sizeof(*packidx
));
1381 packidx
->fd
= client
->packidx_fd
;
1382 client
->packidx_fd
= -1;
1383 packidx
->len
= sb
.st_size
;
1385 err
= got_packidx_init_hdr(packidx
, 1, client
->pack
.filesize
);
1389 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1390 if (ref_update
->delete_ref
)
1393 TAILQ_FOREACH(pe
, repo_write
.protected_tag_namespaces
, entry
) {
1394 err
= protect_tag_namespace(pe
->path
, &client
->pack
,
1395 packidx
, ref_update
);
1401 * Objects which already exist in our repository need
1402 * not be present in the pack file.
1404 err
= got_object_open(&obj
, repo_write
.repo
,
1405 &ref_update
->new_id
);
1406 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
1410 got_object_close(obj
);
1413 int idx
= got_packidx_get_object_idx(packidx
,
1414 &ref_update
->new_id
);
1416 got_sha1_digest_to_str(ref_update
->new_id
.sha1
,
1418 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
1419 "object %s is missing from pack file",
1425 TAILQ_FOREACH(pe
, repo_write
.protected_branch_namespaces
,
1427 err
= protect_branch_namespace(pe
->path
,
1428 &client
->pack
, packidx
, ref_update
);
1432 TAILQ_FOREACH(pe
, repo_write
.protected_branches
, entry
) {
1433 err
= protect_branch(pe
->path
, &client
->pack
,
1434 packidx
, ref_update
);
1441 close_err
= got_packidx_close(packidx
);
1442 if (close_err
&& err
== NULL
)
1446 got_object_close(obj
);
1450 static const struct got_error
*
1451 protect_refs_from_deletion(void)
1453 const struct got_error
*err
= NULL
;
1454 struct repo_write_client
*client
= &repo_write_client
;
1455 struct gotd_ref_update
*ref_update
;
1456 struct got_pathlist_entry
*pe
;
1457 const char *refname
;
1459 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1460 if (!ref_update
->delete_ref
)
1463 refname
= got_ref_get_name(ref_update
->ref
);
1465 TAILQ_FOREACH(pe
, repo_write
.protected_tag_namespaces
, entry
) {
1466 err
= protect_ref_namespace(refname
, pe
->path
);
1471 TAILQ_FOREACH(pe
, repo_write
.protected_branch_namespaces
,
1473 err
= protect_ref_namespace(refname
, pe
->path
);
1478 TAILQ_FOREACH(pe
, repo_write
.protected_branches
, entry
) {
1479 if (strcmp(refname
, pe
->path
) == 0) {
1480 return got_error_fmt(GOT_ERR_REF_PROTECTED
,
1489 static const struct got_error
*
1490 install_packfile(struct gotd_imsgev
*iev
)
1492 struct repo_write_client
*client
= &repo_write_client
;
1493 struct gotd_imsg_packfile_install inst
;
1496 memset(&inst
, 0, sizeof(inst
));
1497 inst
.client_id
= client
->id
;
1498 memcpy(inst
.pack_sha1
, client
->pack_sha1
, SHA1_DIGEST_LENGTH
);
1500 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_PACKFILE_INSTALL
,
1501 PROC_REPO_WRITE
, -1, &inst
, sizeof(inst
));
1503 return got_error_from_errno("imsg_compose PACKFILE_INSTALL");
1508 static const struct got_error
*
1509 send_ref_updates_start(int nref_updates
, struct gotd_imsgev
*iev
)
1511 struct repo_write_client
*client
= &repo_write_client
;
1512 struct gotd_imsg_ref_updates_start istart
;
1515 memset(&istart
, 0, sizeof(istart
));
1516 istart
.nref_updates
= nref_updates
;
1517 istart
.client_id
= client
->id
;
1519 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_REF_UPDATES_START
,
1520 PROC_REPO_WRITE
, -1, &istart
, sizeof(istart
));
1522 return got_error_from_errno("imsg_compose REF_UPDATES_START");
1528 static const struct got_error
*
1529 send_ref_update(struct gotd_ref_update
*ref_update
, struct gotd_imsgev
*iev
)
1531 struct repo_write_client
*client
= &repo_write_client
;
1532 struct gotd_imsg_ref_update iref
;
1533 const char *refname
= got_ref_get_name(ref_update
->ref
);
1537 memset(&iref
, 0, sizeof(iref
));
1538 memcpy(iref
.old_id
, ref_update
->old_id
.sha1
, SHA1_DIGEST_LENGTH
);
1539 memcpy(iref
.new_id
, ref_update
->new_id
.sha1
, SHA1_DIGEST_LENGTH
);
1540 iref
.ref_is_new
= ref_update
->ref_is_new
;
1541 iref
.delete_ref
= ref_update
->delete_ref
;
1542 iref
.client_id
= client
->id
;
1543 iref
.name_len
= strlen(refname
);
1545 len
= sizeof(iref
) + iref
.name_len
;
1546 wbuf
= imsg_create(&iev
->ibuf
, GOTD_IMSG_REF_UPDATE
, PROC_REPO_WRITE
,
1547 repo_write
.pid
, len
);
1549 return got_error_from_errno("imsg_create REF_UPDATE");
1551 if (imsg_add(wbuf
, &iref
, sizeof(iref
)) == -1)
1552 return got_error_from_errno("imsg_add REF_UPDATE");
1553 if (imsg_add(wbuf
, refname
, iref
.name_len
) == -1)
1554 return got_error_from_errno("imsg_add REF_UPDATE");
1557 imsg_close(&iev
->ibuf
, wbuf
);
1559 gotd_imsg_event_add(iev
);
1563 static const struct got_error
*
1564 update_refs(struct gotd_imsgev
*iev
)
1566 const struct got_error
*err
= NULL
;
1567 struct repo_write_client
*client
= &repo_write_client
;
1568 struct gotd_ref_update
*ref_update
;
1570 err
= send_ref_updates_start(client
->nref_updates
, iev
);
1574 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1575 err
= send_ref_update(ref_update
, iev
);
1583 static const struct got_error
*
1584 receive_pack_pipe(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1586 struct repo_write_client
*client
= &repo_write_client
;
1587 struct gotd_imsg_packfile_pipe ireq
;
1590 log_debug("receiving pack pipe descriptor");
1593 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1595 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1596 if (datalen
!= sizeof(ireq
))
1597 return got_error(GOT_ERR_PRIVSEP_LEN
);
1598 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1600 if (client
->pack_pipe
!= -1)
1601 return got_error(GOT_ERR_PRIVSEP_MSG
);
1603 client
->pack_pipe
= imsg
->fd
;
1607 static const struct got_error
*
1608 receive_pack_idx(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1610 struct repo_write_client
*client
= &repo_write_client
;
1611 struct gotd_imsg_packidx_file ireq
;
1614 log_debug("receiving pack index output file");
1617 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1619 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1620 if (datalen
!= sizeof(ireq
))
1621 return got_error(GOT_ERR_PRIVSEP_LEN
);
1622 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1624 if (client
->packidx_fd
!= -1)
1625 return got_error(GOT_ERR_PRIVSEP_MSG
);
1627 client
->packidx_fd
= imsg
->fd
;
1632 repo_write_dispatch_session(int fd
, short event
, void *arg
)
1634 const struct got_error
*err
= NULL
;
1635 struct gotd_imsgev
*iev
= arg
;
1636 struct imsgbuf
*ibuf
= &iev
->ibuf
;
1638 struct repo_write_client
*client
= &repo_write_client
;
1640 int shut
= 0, have_packfile
= 0;
1642 if (event
& EV_READ
) {
1643 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
1644 fatal("imsg_read error");
1645 if (n
== 0) /* Connection closed. */
1649 if (event
& EV_WRITE
) {
1650 n
= msgbuf_write(&ibuf
->w
);
1651 if (n
== -1 && errno
!= EAGAIN
)
1652 fatal("msgbuf_write");
1653 if (n
== 0) /* Connection closed. */
1658 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
1659 fatal("%s: imsg_get error", __func__
);
1660 if (n
== 0) /* No more messages. */
1663 if (imsg
.hdr
.type
!= GOTD_IMSG_LIST_REFS_INTERNAL
&&
1665 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
1669 switch (imsg
.hdr
.type
) {
1670 case GOTD_IMSG_LIST_REFS_INTERNAL
:
1671 err
= list_refs(&imsg
);
1673 log_warnx("ls-refs: %s", err
->msg
);
1675 case GOTD_IMSG_REF_UPDATE
:
1676 err
= recv_ref_update(&imsg
);
1678 log_warnx("ref-update: %s", err
->msg
);
1680 case GOTD_IMSG_PACKFILE_PIPE
:
1681 err
= receive_pack_pipe(&imsg
, iev
);
1683 log_warnx("receiving pack pipe: %s", err
->msg
);
1687 case GOTD_IMSG_PACKIDX_FILE
:
1688 err
= receive_pack_idx(&imsg
, iev
);
1690 log_warnx("receiving pack index: %s",
1695 case GOTD_IMSG_RECV_PACKFILE
:
1696 err
= protect_refs_from_deletion();
1699 err
= recv_packfile(&have_packfile
, &imsg
);
1701 log_warnx("receive packfile: %s", err
->msg
);
1704 if (have_packfile
) {
1705 err
= verify_packfile();
1707 log_warnx("verify packfile: %s",
1711 err
= install_packfile(iev
);
1713 log_warnx("install packfile: %s",
1718 err
= update_refs(iev
);
1720 log_warnx("update refs: %s", err
->msg
);
1724 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
1731 if (!shut
&& check_cancelled(NULL
) == NULL
) {
1733 gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
1734 client
->id
, err
) == -1) {
1735 log_warnx("could not send error to parent: %s",
1738 gotd_imsg_event_add(iev
);
1740 /* This pipe is dead. Remove its event handler */
1741 event_del(&iev
->ev
);
1742 event_loopexit(NULL
);
1746 static const struct got_error
*
1747 recv_connect(struct imsg
*imsg
)
1749 struct gotd_imsgev
*iev
= &repo_write
.session_iev
;
1752 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1754 return got_error(GOT_ERR_PRIVSEP_LEN
);
1756 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1758 if (repo_write
.session_fd
!= -1)
1759 return got_error(GOT_ERR_PRIVSEP_MSG
);
1761 repo_write
.session_fd
= imsg
->fd
;
1763 imsg_init(&iev
->ibuf
, repo_write
.session_fd
);
1764 iev
->handler
= repo_write_dispatch_session
;
1765 iev
->events
= EV_READ
;
1766 iev
->handler_arg
= NULL
;
1767 event_set(&iev
->ev
, iev
->ibuf
.fd
, EV_READ
,
1768 repo_write_dispatch_session
, iev
);
1769 gotd_imsg_event_add(iev
);
1775 repo_write_dispatch(int fd
, short event
, void *arg
)
1777 const struct got_error
*err
= NULL
;
1778 struct gotd_imsgev
*iev
= arg
;
1779 struct imsgbuf
*ibuf
= &iev
->ibuf
;
1783 struct repo_write_client
*client
= &repo_write_client
;
1785 if (event
& EV_READ
) {
1786 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
1787 fatal("imsg_read error");
1788 if (n
== 0) /* Connection closed. */
1792 if (event
& EV_WRITE
) {
1793 n
= msgbuf_write(&ibuf
->w
);
1794 if (n
== -1 && errno
!= EAGAIN
)
1795 fatal("msgbuf_write");
1796 if (n
== 0) /* Connection closed. */
1800 while (err
== NULL
&& check_cancelled(NULL
) == NULL
) {
1801 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
1802 fatal("%s: imsg_get", __func__
);
1803 if (n
== 0) /* No more messages. */
1806 switch (imsg
.hdr
.type
) {
1807 case GOTD_IMSG_CONNECT_REPO_CHILD
:
1808 err
= recv_connect(&imsg
);
1811 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
1818 if (!shut
&& check_cancelled(NULL
) == NULL
) {
1820 gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
1821 client
->id
, err
) == -1) {
1822 log_warnx("could not send error to parent: %s",
1825 gotd_imsg_event_add(iev
);
1827 /* This pipe is dead. Remove its event handler */
1828 event_del(&iev
->ev
);
1829 event_loopexit(NULL
);
1834 repo_write_main(const char *title
, const char *repo_path
,
1835 int *pack_fds
, int *temp_fds
,
1836 struct got_pathlist_head
*protected_tag_namespaces
,
1837 struct got_pathlist_head
*protected_branch_namespaces
,
1838 struct got_pathlist_head
*protected_branches
)
1840 const struct got_error
*err
= NULL
;
1841 struct repo_write_client
*client
= &repo_write_client
;
1842 struct gotd_imsgev iev
;
1845 client
->pack_pipe
= -1;
1846 client
->packidx_fd
= -1;
1847 client
->pack
.fd
= -1;
1849 repo_write
.title
= title
;
1850 repo_write
.pid
= getpid();
1851 repo_write
.pack_fds
= pack_fds
;
1852 repo_write
.temp_fds
= temp_fds
;
1853 repo_write
.session_fd
= -1;
1854 repo_write
.session_iev
.ibuf
.fd
= -1;
1855 repo_write
.protected_tag_namespaces
= protected_tag_namespaces
;
1856 repo_write
.protected_branch_namespaces
= protected_branch_namespaces
;
1857 repo_write
.protected_branches
= protected_branches
;
1859 STAILQ_INIT(&repo_write_client
.ref_updates
);
1861 err
= got_repo_open(&repo_write
.repo
, repo_path
, NULL
, pack_fds
);
1864 if (!got_repo_is_bare(repo_write
.repo
)) {
1865 err
= got_error_msg(GOT_ERR_NOT_GIT_REPO
,
1866 "bare git repository required");
1870 got_repo_temp_fds_set(repo_write
.repo
, temp_fds
);
1872 signal(SIGINT
, catch_sigint
);
1873 signal(SIGTERM
, catch_sigterm
);
1874 signal(SIGPIPE
, SIG_IGN
);
1875 signal(SIGHUP
, SIG_IGN
);
1877 imsg_init(&iev
.ibuf
, GOTD_FILENO_MSG_PIPE
);
1878 iev
.handler
= repo_write_dispatch
;
1879 iev
.events
= EV_READ
;
1880 iev
.handler_arg
= NULL
;
1881 event_set(&iev
.ev
, iev
.ibuf
.fd
, EV_READ
, repo_write_dispatch
, &iev
);
1882 if (gotd_imsg_compose_event(&iev
, GOTD_IMSG_REPO_CHILD_READY
,
1883 PROC_REPO_WRITE
, -1, NULL
, 0) == -1) {
1884 err
= got_error_from_errno("imsg compose REPO_CHILD_READY");
1891 log_warnx("%s: %s", title
, err
->msg
);
1892 repo_write_shutdown();
1896 repo_write_shutdown(void)
1898 struct repo_write_client
*client
= &repo_write_client
;
1899 struct gotd_ref_update
*ref_update
;
1901 log_debug("shutting down");
1903 while (!STAILQ_EMPTY(&client
->ref_updates
)) {
1904 ref_update
= STAILQ_FIRST(&client
->ref_updates
);
1905 STAILQ_REMOVE_HEAD(&client
->ref_updates
, entry
);
1906 got_ref_close(ref_update
->ref
);
1910 got_pack_close(&client
->pack
);
1911 if (client
->fd
!= -1)
1913 if (client
->pack_pipe
!= -1)
1914 close(client
->pack_pipe
);
1915 if (client
->packidx_fd
!= -1)
1916 close(client
->packidx_fd
);
1918 if (repo_write
.repo
)
1919 got_repo_close(repo_write
.repo
);
1920 got_repo_pack_fds_close(repo_write
.pack_fds
);
1921 got_repo_temp_fds_close(repo_write
.temp_fds
);
1922 if (repo_write
.session_fd
!= -1)
1923 close(repo_write
.session_fd
);