2 8e359fa0 2022-10-13 stsp * Copyright (c) 2018, 2019, 2022 Stefan Sperling <stsp@openbsd.org>
4 8e359fa0 2022-10-13 stsp * Permission to use, copy, modify, and distribute this software for any
5 8e359fa0 2022-10-13 stsp * purpose with or without fee is hereby granted, provided that the above
6 8e359fa0 2022-10-13 stsp * copyright notice and this permission notice appear in all copies.
8 8e359fa0 2022-10-13 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 8e359fa0 2022-10-13 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 8e359fa0 2022-10-13 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 8e359fa0 2022-10-13 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 8e359fa0 2022-10-13 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 8e359fa0 2022-10-13 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 8e359fa0 2022-10-13 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 8e359fa0 2022-10-13 stsp #include <sys/mman.h>
18 8e359fa0 2022-10-13 stsp #include <sys/queue.h>
19 8e359fa0 2022-10-13 stsp #include <sys/types.h>
20 8e359fa0 2022-10-13 stsp #include <sys/tree.h>
21 8e359fa0 2022-10-13 stsp #include <sys/stat.h>
22 8e359fa0 2022-10-13 stsp #include <sys/socket.h>
23 8e359fa0 2022-10-13 stsp #include <sys/uio.h>
25 8e359fa0 2022-10-13 stsp #include <errno.h>
26 8e359fa0 2022-10-13 stsp #include <imsg.h>
27 494e2b9b 2024-03-27 stsp #include <stddef.h>
28 8e359fa0 2022-10-13 stsp #include <stdio.h>
29 8e359fa0 2022-10-13 stsp #include <stdint.h>
30 8e359fa0 2022-10-13 stsp #include <stdlib.h>
31 8e359fa0 2022-10-13 stsp #include <string.h>
32 8e359fa0 2022-10-13 stsp #include <sha1.h>
33 5822e79e 2023-02-23 op #include <sha2.h>
34 8e359fa0 2022-10-13 stsp #include <limits.h>
35 8e359fa0 2022-10-13 stsp #include <unistd.h>
37 8e359fa0 2022-10-13 stsp #include "got_error.h"
38 8e359fa0 2022-10-13 stsp #include "got_object.h"
39 8e359fa0 2022-10-13 stsp #include "got_repository.h"
40 8e359fa0 2022-10-13 stsp #include "got_opentemp.h"
41 8e359fa0 2022-10-13 stsp #include "got_path.h"
43 8e359fa0 2022-10-13 stsp #include "got_lib_delta.h"
44 8e359fa0 2022-10-13 stsp #include "got_lib_object.h"
45 8e359fa0 2022-10-13 stsp #include "got_lib_privsep.h"
46 8e359fa0 2022-10-13 stsp #include "got_lib_object_cache.h"
47 8e359fa0 2022-10-13 stsp #include "got_lib_pack.h"
48 8e359fa0 2022-10-13 stsp #include "got_lib_repository.h"
50 8e359fa0 2022-10-13 stsp static const struct got_error *
51 8e359fa0 2022-10-13 stsp request_packed_object(struct got_object **obj, struct got_pack *pack, int idx,
52 8e359fa0 2022-10-13 stsp struct got_object_id *id)
54 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
55 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf = pack->privsep_child->ibuf;
57 8e359fa0 2022-10-13 stsp err = got_privsep_send_packed_obj_req(ibuf, idx, id);
61 8e359fa0 2022-10-13 stsp err = got_privsep_recv_obj(obj, ibuf);
65 8e359fa0 2022-10-13 stsp memcpy(&(*obj)->id, id, sizeof((*obj)->id));
67 8e359fa0 2022-10-13 stsp return NULL;
70 8e359fa0 2022-10-13 stsp /* Create temporary files used during delta application. */
71 8e359fa0 2022-10-13 stsp static const struct got_error *
72 8e359fa0 2022-10-13 stsp pack_child_send_tempfiles(struct imsgbuf *ibuf, struct got_pack *pack)
74 8e359fa0 2022-10-13 stsp const struct got_error *err;
75 8e359fa0 2022-10-13 stsp int basefd = -1, accumfd = -1;
78 8e359fa0 2022-10-13 stsp * For performance reasons, the child will keep reusing the
79 8e359fa0 2022-10-13 stsp * same temporary files during every object request.
80 8e359fa0 2022-10-13 stsp * Opening and closing new files for every object request is
81 8e359fa0 2022-10-13 stsp * too expensive during operations such as 'gotadmin pack'.
83 8e359fa0 2022-10-13 stsp if (pack->child_has_tempfiles)
84 8e359fa0 2022-10-13 stsp return NULL;
86 8e359fa0 2022-10-13 stsp basefd = dup(pack->basefd);
87 8e359fa0 2022-10-13 stsp if (basefd == -1)
88 8e359fa0 2022-10-13 stsp return got_error_from_errno("dup");
90 8e359fa0 2022-10-13 stsp accumfd = dup(pack->accumfd);
91 8e359fa0 2022-10-13 stsp if (accumfd == -1) {
92 8e359fa0 2022-10-13 stsp err = got_error_from_errno("dup");
96 8e359fa0 2022-10-13 stsp err = got_privsep_send_tmpfd(ibuf, basefd);
100 8e359fa0 2022-10-13 stsp err = got_privsep_send_tmpfd(ibuf, accumfd);
103 8e359fa0 2022-10-13 stsp if (basefd != -1)
104 8e359fa0 2022-10-13 stsp close(basefd);
105 8e359fa0 2022-10-13 stsp if (accumfd != -1)
106 8e359fa0 2022-10-13 stsp close(accumfd);
108 8e359fa0 2022-10-13 stsp pack->child_has_tempfiles = 1;
109 c33c3763 2023-02-03 mark return err;
112 8e359fa0 2022-10-13 stsp static const struct got_error *
113 8e359fa0 2022-10-13 stsp request_packed_object_raw(uint8_t **outbuf, off_t *size, size_t *hdrlen,
114 8e359fa0 2022-10-13 stsp int outfd, struct got_pack *pack, int idx, struct got_object_id *id)
116 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
117 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf = pack->privsep_child->ibuf;
118 8e359fa0 2022-10-13 stsp int outfd_child;
120 06bd8ee4 2024-02-13 op err = pack_child_send_tempfiles(ibuf, pack);
122 8e359fa0 2022-10-13 stsp return err;
124 8e359fa0 2022-10-13 stsp outfd_child = dup(outfd);
125 8e359fa0 2022-10-13 stsp if (outfd_child == -1)
126 8e359fa0 2022-10-13 stsp return got_error_from_errno("dup");
128 8e359fa0 2022-10-13 stsp err = got_privsep_send_packed_raw_obj_req(ibuf, idx, id);
130 8e359fa0 2022-10-13 stsp close(outfd_child);
131 8e359fa0 2022-10-13 stsp return err;
134 8e359fa0 2022-10-13 stsp err = got_privsep_send_raw_obj_outfd(ibuf, outfd_child);
136 8e359fa0 2022-10-13 stsp return err;
138 8e359fa0 2022-10-13 stsp err = got_privsep_recv_raw_obj(outbuf, size, hdrlen, ibuf);
140 8e359fa0 2022-10-13 stsp return err;
142 8e359fa0 2022-10-13 stsp return NULL;
145 8e359fa0 2022-10-13 stsp static const struct got_error *
146 8e359fa0 2022-10-13 stsp read_packed_object_privsep(struct got_object **obj,
147 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_pack *pack,
148 8e359fa0 2022-10-13 stsp struct got_packidx *packidx, int idx, struct got_object_id *id)
150 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
152 8e359fa0 2022-10-13 stsp if (pack->privsep_child == NULL) {
153 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
155 8e359fa0 2022-10-13 stsp return err;
158 8e359fa0 2022-10-13 stsp return request_packed_object(obj, pack, idx, id);
161 8e359fa0 2022-10-13 stsp static const struct got_error *
162 8e359fa0 2022-10-13 stsp read_packed_object_raw_privsep(uint8_t **outbuf, off_t *size, size_t *hdrlen,
163 8e359fa0 2022-10-13 stsp int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
164 8e359fa0 2022-10-13 stsp struct got_object_id *id)
166 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
168 8e359fa0 2022-10-13 stsp if (pack->privsep_child == NULL) {
169 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
171 8e359fa0 2022-10-13 stsp return err;
174 8e359fa0 2022-10-13 stsp return request_packed_object_raw(outbuf, size, hdrlen, outfd, pack,
178 8e359fa0 2022-10-13 stsp const struct got_error *
179 8e359fa0 2022-10-13 stsp got_object_open_packed(struct got_object **obj, struct got_object_id *id,
180 8e359fa0 2022-10-13 stsp struct got_repository *repo)
182 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
183 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
184 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
186 8e359fa0 2022-10-13 stsp char *path_packfile;
188 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
190 8e359fa0 2022-10-13 stsp return err;
192 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
193 8e359fa0 2022-10-13 stsp packidx->path_packidx);
195 8e359fa0 2022-10-13 stsp return err;
197 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
198 8e359fa0 2022-10-13 stsp if (pack == NULL) {
199 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
204 8e359fa0 2022-10-13 stsp err = read_packed_object_privsep(obj, repo, pack, packidx, idx, id);
208 8e359fa0 2022-10-13 stsp free(path_packfile);
209 8e359fa0 2022-10-13 stsp return err;
212 8e359fa0 2022-10-13 stsp const struct got_error *
213 8e359fa0 2022-10-13 stsp got_object_open_from_packfile(struct got_object **obj, struct got_object_id *id,
214 8e359fa0 2022-10-13 stsp struct got_pack *pack, struct got_packidx *packidx, int obj_idx,
215 8e359fa0 2022-10-13 stsp struct got_repository *repo)
217 8e359fa0 2022-10-13 stsp return read_packed_object_privsep(obj, repo, pack, packidx,
218 8e359fa0 2022-10-13 stsp obj_idx, id);
221 8e359fa0 2022-10-13 stsp const struct got_error *
222 8e359fa0 2022-10-13 stsp got_object_read_raw_delta(uint64_t *base_size, uint64_t *result_size,
223 8e359fa0 2022-10-13 stsp off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
224 8e359fa0 2022-10-13 stsp off_t *delta_out_offset, struct got_object_id **base_id, int delta_cache_fd,
225 8e359fa0 2022-10-13 stsp struct got_packidx *packidx, int obj_idx, struct got_object_id *id,
226 8e359fa0 2022-10-13 stsp struct got_repository *repo)
228 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
229 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
230 8e359fa0 2022-10-13 stsp char *path_packfile;
232 8e359fa0 2022-10-13 stsp *base_size = 0;
233 8e359fa0 2022-10-13 stsp *result_size = 0;
234 8e359fa0 2022-10-13 stsp *delta_size = 0;
235 8e359fa0 2022-10-13 stsp *delta_compressed_size = 0;
236 8e359fa0 2022-10-13 stsp *delta_offset = 0;
237 8e359fa0 2022-10-13 stsp *delta_out_offset = 0;
239 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
240 8e359fa0 2022-10-13 stsp packidx->path_packidx);
242 8e359fa0 2022-10-13 stsp return err;
244 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
245 8e359fa0 2022-10-13 stsp if (pack == NULL) {
246 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
248 8e359fa0 2022-10-13 stsp return err;
251 8e359fa0 2022-10-13 stsp if (pack->privsep_child == NULL) {
252 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
254 8e359fa0 2022-10-13 stsp return err;
257 8e359fa0 2022-10-13 stsp if (!pack->child_has_delta_outfd) {
258 8e359fa0 2022-10-13 stsp int outfd_child;
259 8e359fa0 2022-10-13 stsp outfd_child = dup(delta_cache_fd);
260 8e359fa0 2022-10-13 stsp if (outfd_child == -1)
261 8e359fa0 2022-10-13 stsp return got_error_from_errno("dup");
262 8e359fa0 2022-10-13 stsp err = got_privsep_send_raw_delta_outfd(
263 8e359fa0 2022-10-13 stsp pack->privsep_child->ibuf, outfd_child);
265 8e359fa0 2022-10-13 stsp return err;
266 8e359fa0 2022-10-13 stsp pack->child_has_delta_outfd = 1;
269 8e359fa0 2022-10-13 stsp err = got_privsep_send_raw_delta_req(pack->privsep_child->ibuf,
270 8e359fa0 2022-10-13 stsp obj_idx, id);
272 8e359fa0 2022-10-13 stsp return err;
274 8e359fa0 2022-10-13 stsp return got_privsep_recv_raw_delta(base_size, result_size, delta_size,
275 8e359fa0 2022-10-13 stsp delta_compressed_size, delta_offset, delta_out_offset, base_id,
276 8e359fa0 2022-10-13 stsp pack->privsep_child->ibuf);
279 8e359fa0 2022-10-13 stsp static const struct got_error *
280 8e359fa0 2022-10-13 stsp request_object(struct got_object **obj, struct got_object_id *id,
281 8e359fa0 2022-10-13 stsp struct got_repository *repo, int fd)
283 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
284 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
286 8e359fa0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].ibuf;
288 8e359fa0 2022-10-13 stsp err = got_privsep_send_obj_req(ibuf, fd, id);
290 8e359fa0 2022-10-13 stsp return err;
292 8e359fa0 2022-10-13 stsp return got_privsep_recv_obj(obj, ibuf);
295 8e359fa0 2022-10-13 stsp static const struct got_error *
296 8e359fa0 2022-10-13 stsp request_raw_object(uint8_t **outbuf, off_t *size, size_t *hdrlen, int outfd,
297 8e359fa0 2022-10-13 stsp struct got_object_id *id, struct got_repository *repo, int infd)
299 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
300 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
301 8e359fa0 2022-10-13 stsp int outfd_child;
303 8e359fa0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].ibuf;
305 8e359fa0 2022-10-13 stsp outfd_child = dup(outfd);
306 8e359fa0 2022-10-13 stsp if (outfd_child == -1)
307 8e359fa0 2022-10-13 stsp return got_error_from_errno("dup");
309 8e359fa0 2022-10-13 stsp err = got_privsep_send_raw_obj_req(ibuf, infd, id);
311 8e359fa0 2022-10-13 stsp return err;
313 8e359fa0 2022-10-13 stsp err = got_privsep_send_raw_obj_outfd(ibuf, outfd_child);
315 8e359fa0 2022-10-13 stsp return err;
317 8e359fa0 2022-10-13 stsp return got_privsep_recv_raw_obj(outbuf, size, hdrlen, ibuf);
320 8e359fa0 2022-10-13 stsp static const struct got_error *
321 1d9e43b0 2022-10-13 stsp start_child(struct got_repository *repo, int type)
323 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
324 8e359fa0 2022-10-13 stsp int imsg_fds[2];
326 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
327 1d9e43b0 2022-10-13 stsp const char *prog_path;
329 1d9e43b0 2022-10-13 stsp switch (type) {
330 1d9e43b0 2022-10-13 stsp case GOT_REPO_PRIVSEP_CHILD_OBJECT:
331 1d9e43b0 2022-10-13 stsp prog_path = GOT_PATH_PROG_READ_OBJECT;
333 1d9e43b0 2022-10-13 stsp case GOT_REPO_PRIVSEP_CHILD_TREE:
334 1d9e43b0 2022-10-13 stsp prog_path = GOT_PATH_PROG_READ_TREE;
336 1d9e43b0 2022-10-13 stsp case GOT_REPO_PRIVSEP_CHILD_COMMIT:
337 1d9e43b0 2022-10-13 stsp prog_path = GOT_PATH_PROG_READ_COMMIT;
339 1d9e43b0 2022-10-13 stsp case GOT_REPO_PRIVSEP_CHILD_BLOB:
340 1d9e43b0 2022-10-13 stsp prog_path = GOT_PATH_PROG_READ_BLOB;
342 1d9e43b0 2022-10-13 stsp case GOT_REPO_PRIVSEP_CHILD_TAG:
343 1d9e43b0 2022-10-13 stsp prog_path = GOT_PATH_PROG_READ_TAG;
346 1d9e43b0 2022-10-13 stsp return got_error(GOT_ERR_OBJ_TYPE);
349 8e359fa0 2022-10-13 stsp ibuf = calloc(1, sizeof(*ibuf));
350 8e359fa0 2022-10-13 stsp if (ibuf == NULL)
351 8e359fa0 2022-10-13 stsp return got_error_from_errno("calloc");
353 8e359fa0 2022-10-13 stsp if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1) {
354 8e359fa0 2022-10-13 stsp err = got_error_from_errno("socketpair");
355 8e359fa0 2022-10-13 stsp free(ibuf);
356 8e359fa0 2022-10-13 stsp return err;
359 8e359fa0 2022-10-13 stsp pid = fork();
360 8e359fa0 2022-10-13 stsp if (pid == -1) {
361 8e359fa0 2022-10-13 stsp err = got_error_from_errno("fork");
362 8e359fa0 2022-10-13 stsp free(ibuf);
363 8e359fa0 2022-10-13 stsp return err;
365 8e359fa0 2022-10-13 stsp else if (pid == 0) {
366 1d9e43b0 2022-10-13 stsp got_privsep_exec_child(imsg_fds, prog_path, repo->path);
367 8e359fa0 2022-10-13 stsp /* not reached */
370 8e359fa0 2022-10-13 stsp if (close(imsg_fds[1]) == -1) {
371 8e359fa0 2022-10-13 stsp err = got_error_from_errno("close");
372 8e359fa0 2022-10-13 stsp free(ibuf);
373 8e359fa0 2022-10-13 stsp return err;
376 1d9e43b0 2022-10-13 stsp repo->privsep_children[type].imsg_fd = imsg_fds[0];
377 1d9e43b0 2022-10-13 stsp repo->privsep_children[type].pid = pid;
378 8e359fa0 2022-10-13 stsp imsg_init(ibuf, imsg_fds[0]);
379 1d9e43b0 2022-10-13 stsp repo->privsep_children[type].ibuf = ibuf;
381 8e359fa0 2022-10-13 stsp return NULL;
384 8e359fa0 2022-10-13 stsp const struct got_error *
385 8e359fa0 2022-10-13 stsp got_object_read_header_privsep(struct got_object **obj,
386 8e359fa0 2022-10-13 stsp struct got_object_id *id, struct got_repository *repo, int obj_fd)
388 8e359fa0 2022-10-13 stsp const struct got_error *err;
390 8e359fa0 2022-10-13 stsp if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].imsg_fd != -1)
391 8e359fa0 2022-10-13 stsp return request_object(obj, id, repo, obj_fd);
393 1d9e43b0 2022-10-13 stsp err = start_child(repo, GOT_REPO_PRIVSEP_CHILD_OBJECT);
395 8e359fa0 2022-10-13 stsp return err;
397 8e359fa0 2022-10-13 stsp return request_object(obj, id, repo, obj_fd);
400 8e359fa0 2022-10-13 stsp static const struct got_error *
401 8e359fa0 2022-10-13 stsp read_object_raw_privsep(uint8_t **outbuf, off_t *size, size_t *hdrlen,
402 8e359fa0 2022-10-13 stsp int outfd, struct got_object_id *id, struct got_repository *repo,
403 8e359fa0 2022-10-13 stsp int obj_fd)
405 8e359fa0 2022-10-13 stsp const struct got_error *err;
407 8e359fa0 2022-10-13 stsp if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].imsg_fd != -1)
408 8e359fa0 2022-10-13 stsp return request_raw_object(outbuf, size, hdrlen, outfd, id,
409 8e359fa0 2022-10-13 stsp repo, obj_fd);
411 1d9e43b0 2022-10-13 stsp err = start_child(repo, GOT_REPO_PRIVSEP_CHILD_OBJECT);
413 8e359fa0 2022-10-13 stsp return err;
415 8e359fa0 2022-10-13 stsp return request_raw_object(outbuf, size, hdrlen, outfd, id, repo,
419 8e359fa0 2022-10-13 stsp const struct got_error *
420 8e359fa0 2022-10-13 stsp got_object_open(struct got_object **obj, struct got_repository *repo,
421 8e359fa0 2022-10-13 stsp struct got_object_id *id)
423 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
426 8e359fa0 2022-10-13 stsp *obj = got_repo_get_cached_object(repo, id);
427 8e359fa0 2022-10-13 stsp if (*obj != NULL) {
428 8e359fa0 2022-10-13 stsp (*obj)->refcnt++;
429 8e359fa0 2022-10-13 stsp return NULL;
432 8e359fa0 2022-10-13 stsp err = got_object_open_packed(obj, id, repo);
433 8e359fa0 2022-10-13 stsp if (err && err->code != GOT_ERR_NO_OBJ)
434 8e359fa0 2022-10-13 stsp return err;
435 8e359fa0 2022-10-13 stsp if (*obj) {
436 8e359fa0 2022-10-13 stsp (*obj)->refcnt++;
437 8e359fa0 2022-10-13 stsp return got_repo_cache_object(repo, id, *obj);
440 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&fd, id, repo);
442 8e359fa0 2022-10-13 stsp if (err->code == GOT_ERR_ERRNO && errno == ENOENT)
443 8e359fa0 2022-10-13 stsp err = got_error_no_obj(id);
444 8e359fa0 2022-10-13 stsp return err;
447 8e359fa0 2022-10-13 stsp err = got_object_read_header_privsep(obj, id, repo, fd);
449 8e359fa0 2022-10-13 stsp return err;
451 3e0381db 2023-02-05 op memcpy(&(*obj)->id, id, sizeof(*id));
453 8e359fa0 2022-10-13 stsp (*obj)->refcnt++;
454 8e359fa0 2022-10-13 stsp return got_repo_cache_object(repo, id, *obj);
457 8e359fa0 2022-10-13 stsp /* *outfd must be initialized to -1 by caller */
458 8e359fa0 2022-10-13 stsp const struct got_error *
459 8e359fa0 2022-10-13 stsp got_object_raw_open(struct got_raw_object **obj, int *outfd,
460 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object_id *id)
462 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
463 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
465 8e359fa0 2022-10-13 stsp uint8_t *outbuf = NULL;
466 8e359fa0 2022-10-13 stsp off_t size = 0;
467 8e359fa0 2022-10-13 stsp size_t hdrlen = 0;
468 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
470 8e359fa0 2022-10-13 stsp *obj = got_repo_get_cached_raw_object(repo, id);
471 8e359fa0 2022-10-13 stsp if (*obj != NULL) {
472 8e359fa0 2022-10-13 stsp (*obj)->refcnt++;
473 8e359fa0 2022-10-13 stsp return NULL;
476 8e359fa0 2022-10-13 stsp if (*outfd == -1) {
477 8e359fa0 2022-10-13 stsp *outfd = got_opentempfd();
478 8e359fa0 2022-10-13 stsp if (*outfd == -1)
479 8e359fa0 2022-10-13 stsp return got_error_from_errno("got_opentempfd");
482 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
483 8e359fa0 2022-10-13 stsp if (err == NULL) {
484 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
486 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
487 8e359fa0 2022-10-13 stsp packidx->path_packidx);
491 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
492 8e359fa0 2022-10-13 stsp if (pack == NULL) {
493 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
498 8e359fa0 2022-10-13 stsp err = read_packed_object_raw_privsep(&outbuf, &size, &hdrlen,
499 8e359fa0 2022-10-13 stsp *outfd, pack, packidx, idx, id);
502 8e359fa0 2022-10-13 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
505 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&fd, id, repo);
508 8e359fa0 2022-10-13 stsp err = read_object_raw_privsep(&outbuf, &size, &hdrlen, *outfd,
509 8e359fa0 2022-10-13 stsp id, repo, fd);
514 60c140ae 2023-01-09 stsp err = got_object_raw_alloc(obj, outbuf, outfd,
515 60c140ae 2023-01-09 stsp GOT_DELTA_RESULT_SIZE_CACHED_MAX, hdrlen, size);
519 8e359fa0 2022-10-13 stsp err = got_repo_cache_raw_object(repo, id, *obj);
521 8e359fa0 2022-10-13 stsp free(path_packfile);
523 8e359fa0 2022-10-13 stsp if (*obj) {
524 8e359fa0 2022-10-13 stsp got_object_raw_close(*obj);
525 8e359fa0 2022-10-13 stsp *obj = NULL;
527 8e359fa0 2022-10-13 stsp free(outbuf);
529 8e359fa0 2022-10-13 stsp return err;
532 8e359fa0 2022-10-13 stsp static const struct got_error *
533 8e359fa0 2022-10-13 stsp request_packed_commit(struct got_commit_object **commit, struct got_pack *pack,
534 8e359fa0 2022-10-13 stsp int pack_idx, struct got_object_id *id)
536 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
538 8e359fa0 2022-10-13 stsp err = got_privsep_send_commit_req(pack->privsep_child->ibuf, -1, id,
541 8e359fa0 2022-10-13 stsp return err;
543 8e359fa0 2022-10-13 stsp err = got_privsep_recv_commit(commit, pack->privsep_child->ibuf);
545 8e359fa0 2022-10-13 stsp return err;
547 8e359fa0 2022-10-13 stsp (*commit)->flags |= GOT_COMMIT_FLAG_PACKED;
548 8e359fa0 2022-10-13 stsp return NULL;
551 8e359fa0 2022-10-13 stsp static const struct got_error *
552 8e359fa0 2022-10-13 stsp read_packed_commit_privsep(struct got_commit_object **commit,
553 8e359fa0 2022-10-13 stsp struct got_pack *pack, struct got_packidx *packidx, int idx,
554 8e359fa0 2022-10-13 stsp struct got_object_id *id)
556 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
558 8e359fa0 2022-10-13 stsp if (pack->privsep_child)
559 8e359fa0 2022-10-13 stsp return request_packed_commit(commit, pack, idx, id);
561 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
563 8e359fa0 2022-10-13 stsp return err;
565 8e359fa0 2022-10-13 stsp return request_packed_commit(commit, pack, idx, id);
568 8e359fa0 2022-10-13 stsp static const struct got_error *
569 8e359fa0 2022-10-13 stsp request_commit(struct got_commit_object **commit, struct got_repository *repo,
570 8e359fa0 2022-10-13 stsp int fd, struct got_object_id *id)
572 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
573 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
575 8e359fa0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf;
577 8e359fa0 2022-10-13 stsp err = got_privsep_send_commit_req(ibuf, fd, id, -1);
579 8e359fa0 2022-10-13 stsp return err;
581 8e359fa0 2022-10-13 stsp return got_privsep_recv_commit(commit, ibuf);
584 8e359fa0 2022-10-13 stsp static const struct got_error *
585 8e359fa0 2022-10-13 stsp read_commit_privsep(struct got_commit_object **commit, int obj_fd,
586 8e359fa0 2022-10-13 stsp struct got_object_id *id, struct got_repository *repo)
588 8e359fa0 2022-10-13 stsp const struct got_error *err;
590 8e359fa0 2022-10-13 stsp if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].imsg_fd != -1)
591 8e359fa0 2022-10-13 stsp return request_commit(commit, repo, obj_fd, id);
593 1d9e43b0 2022-10-13 stsp err = start_child(repo, GOT_REPO_PRIVSEP_CHILD_COMMIT);
595 8e359fa0 2022-10-13 stsp return err;
597 8e359fa0 2022-10-13 stsp return request_commit(commit, repo, obj_fd, id);
600 8e359fa0 2022-10-13 stsp static const struct got_error *
601 8e359fa0 2022-10-13 stsp open_commit(struct got_commit_object **commit,
602 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object_id *id, int check_cache)
604 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
605 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
607 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
609 8e359fa0 2022-10-13 stsp if (check_cache) {
610 8e359fa0 2022-10-13 stsp *commit = got_repo_get_cached_commit(repo, id);
611 8e359fa0 2022-10-13 stsp if (*commit != NULL) {
612 8e359fa0 2022-10-13 stsp (*commit)->refcnt++;
613 8e359fa0 2022-10-13 stsp return NULL;
616 8e359fa0 2022-10-13 stsp *commit = NULL;
618 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
619 8e359fa0 2022-10-13 stsp if (err == NULL) {
620 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
622 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
623 8e359fa0 2022-10-13 stsp packidx->path_packidx);
625 8e359fa0 2022-10-13 stsp return err;
627 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
628 8e359fa0 2022-10-13 stsp if (pack == NULL) {
629 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
634 8e359fa0 2022-10-13 stsp err = read_packed_commit_privsep(commit, pack,
635 8e359fa0 2022-10-13 stsp packidx, idx, id);
636 8e359fa0 2022-10-13 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
639 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&fd, id, repo);
641 8e359fa0 2022-10-13 stsp return err;
642 8e359fa0 2022-10-13 stsp err = read_commit_privsep(commit, fd, id, repo);
645 8e359fa0 2022-10-13 stsp if (err == NULL) {
646 8e359fa0 2022-10-13 stsp (*commit)->refcnt++;
647 8e359fa0 2022-10-13 stsp err = got_repo_cache_commit(repo, id, *commit);
650 8e359fa0 2022-10-13 stsp free(path_packfile);
651 8e359fa0 2022-10-13 stsp return err;
654 8e359fa0 2022-10-13 stsp const struct got_error *
655 8e359fa0 2022-10-13 stsp got_object_open_as_commit(struct got_commit_object **commit,
656 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object_id *id)
658 8e359fa0 2022-10-13 stsp *commit = got_repo_get_cached_commit(repo, id);
659 8e359fa0 2022-10-13 stsp if (*commit != NULL) {
660 8e359fa0 2022-10-13 stsp (*commit)->refcnt++;
661 8e359fa0 2022-10-13 stsp return NULL;
664 8e359fa0 2022-10-13 stsp return open_commit(commit, repo, id, 0);
667 8e359fa0 2022-10-13 stsp const struct got_error *
668 8e359fa0 2022-10-13 stsp got_object_commit_open(struct got_commit_object **commit,
669 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object *obj)
671 8e359fa0 2022-10-13 stsp return open_commit(commit, repo, got_object_get_id(obj), 1);
674 8e359fa0 2022-10-13 stsp static const struct got_error *
675 8e359fa0 2022-10-13 stsp request_packed_tree(struct got_tree_object **tree, struct got_pack *pack,
676 8e359fa0 2022-10-13 stsp int pack_idx, struct got_object_id *id)
678 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
680 8e359fa0 2022-10-13 stsp err = got_privsep_send_tree_req(pack->privsep_child->ibuf, -1, id,
683 8e359fa0 2022-10-13 stsp return err;
685 8e359fa0 2022-10-13 stsp return got_privsep_recv_tree(tree, pack->privsep_child->ibuf);
688 8e359fa0 2022-10-13 stsp static const struct got_error *
689 8e359fa0 2022-10-13 stsp read_packed_tree_privsep(struct got_tree_object **tree,
690 8e359fa0 2022-10-13 stsp struct got_pack *pack, struct got_packidx *packidx, int idx,
691 8e359fa0 2022-10-13 stsp struct got_object_id *id)
693 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
695 8e359fa0 2022-10-13 stsp if (pack->privsep_child)
696 8e359fa0 2022-10-13 stsp return request_packed_tree(tree, pack, idx, id);
698 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
700 8e359fa0 2022-10-13 stsp return err;
702 8e359fa0 2022-10-13 stsp return request_packed_tree(tree, pack, idx, id);
705 8e359fa0 2022-10-13 stsp static const struct got_error *
706 8e359fa0 2022-10-13 stsp request_tree(struct got_tree_object **tree, struct got_repository *repo,
707 8e359fa0 2022-10-13 stsp int fd, struct got_object_id *id)
709 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
710 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
712 8e359fa0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf;
714 8e359fa0 2022-10-13 stsp err = got_privsep_send_tree_req(ibuf, fd, id, -1);
716 8e359fa0 2022-10-13 stsp return err;
718 8e359fa0 2022-10-13 stsp return got_privsep_recv_tree(tree, ibuf);
721 8e359fa0 2022-10-13 stsp static const struct got_error *
722 8e359fa0 2022-10-13 stsp read_tree_privsep(struct got_tree_object **tree, int obj_fd,
723 8e359fa0 2022-10-13 stsp struct got_object_id *id, struct got_repository *repo)
725 8e359fa0 2022-10-13 stsp const struct got_error *err;
727 8e359fa0 2022-10-13 stsp if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].imsg_fd != -1)
728 8e359fa0 2022-10-13 stsp return request_tree(tree, repo, obj_fd, id);
730 1d9e43b0 2022-10-13 stsp err = start_child(repo, GOT_REPO_PRIVSEP_CHILD_TREE);
732 8e359fa0 2022-10-13 stsp return err;
734 8e359fa0 2022-10-13 stsp return request_tree(tree, repo, obj_fd, id);
737 8e359fa0 2022-10-13 stsp static const struct got_error *
738 8e359fa0 2022-10-13 stsp open_tree(struct got_tree_object **tree, struct got_repository *repo,
739 8e359fa0 2022-10-13 stsp struct got_object_id *id, int check_cache)
741 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
742 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
744 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
746 8e359fa0 2022-10-13 stsp if (check_cache) {
747 8e359fa0 2022-10-13 stsp *tree = got_repo_get_cached_tree(repo, id);
748 8e359fa0 2022-10-13 stsp if (*tree != NULL) {
749 8e359fa0 2022-10-13 stsp (*tree)->refcnt++;
750 8e359fa0 2022-10-13 stsp return NULL;
753 8e359fa0 2022-10-13 stsp *tree = NULL;
755 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
756 8e359fa0 2022-10-13 stsp if (err == NULL) {
757 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
759 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
760 8e359fa0 2022-10-13 stsp packidx->path_packidx);
762 8e359fa0 2022-10-13 stsp return err;
764 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
765 8e359fa0 2022-10-13 stsp if (pack == NULL) {
766 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
771 8e359fa0 2022-10-13 stsp err = read_packed_tree_privsep(tree, pack,
772 8e359fa0 2022-10-13 stsp packidx, idx, id);
773 8e359fa0 2022-10-13 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
776 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&fd, id, repo);
778 8e359fa0 2022-10-13 stsp return err;
779 8e359fa0 2022-10-13 stsp err = read_tree_privsep(tree, fd, id, repo);
782 8e359fa0 2022-10-13 stsp if (err == NULL) {
783 8e359fa0 2022-10-13 stsp (*tree)->refcnt++;
784 8e359fa0 2022-10-13 stsp err = got_repo_cache_tree(repo, id, *tree);
787 8e359fa0 2022-10-13 stsp free(path_packfile);
788 8e359fa0 2022-10-13 stsp return err;
791 8e359fa0 2022-10-13 stsp const struct got_error *
792 8e359fa0 2022-10-13 stsp got_object_open_as_tree(struct got_tree_object **tree,
793 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object_id *id)
795 8e359fa0 2022-10-13 stsp *tree = got_repo_get_cached_tree(repo, id);
796 8e359fa0 2022-10-13 stsp if (*tree != NULL) {
797 8e359fa0 2022-10-13 stsp (*tree)->refcnt++;
798 8e359fa0 2022-10-13 stsp return NULL;
801 8e359fa0 2022-10-13 stsp return open_tree(tree, repo, id, 0);
804 8e359fa0 2022-10-13 stsp const struct got_error *
805 8e359fa0 2022-10-13 stsp got_object_tree_open(struct got_tree_object **tree,
806 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object *obj)
808 8e359fa0 2022-10-13 stsp return open_tree(tree, repo, got_object_get_id(obj), 1);
811 8e359fa0 2022-10-13 stsp static const struct got_error *
812 8e359fa0 2022-10-13 stsp request_packed_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen, int outfd,
813 8e359fa0 2022-10-13 stsp struct got_pack *pack, struct got_packidx *packidx, int idx,
814 8e359fa0 2022-10-13 stsp struct got_object_id *id)
816 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
817 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf = pack->privsep_child->ibuf;
818 8e359fa0 2022-10-13 stsp int outfd_child;
820 06bd8ee4 2024-02-13 op err = pack_child_send_tempfiles(ibuf, pack);
822 8e359fa0 2022-10-13 stsp return err;
824 8e359fa0 2022-10-13 stsp outfd_child = dup(outfd);
825 8e359fa0 2022-10-13 stsp if (outfd_child == -1)
826 8e359fa0 2022-10-13 stsp return got_error_from_errno("dup");
828 8e359fa0 2022-10-13 stsp err = got_privsep_send_blob_req(pack->privsep_child->ibuf, -1, id, idx);
830 8e359fa0 2022-10-13 stsp return err;
832 8e359fa0 2022-10-13 stsp err = got_privsep_send_blob_outfd(pack->privsep_child->ibuf,
833 8e359fa0 2022-10-13 stsp outfd_child);
835 8e359fa0 2022-10-13 stsp return err;
838 8e359fa0 2022-10-13 stsp err = got_privsep_recv_blob(outbuf, size, hdrlen,
839 8e359fa0 2022-10-13 stsp pack->privsep_child->ibuf);
841 8e359fa0 2022-10-13 stsp return err;
843 8e359fa0 2022-10-13 stsp if (lseek(outfd, SEEK_SET, 0) == -1)
844 8e359fa0 2022-10-13 stsp err = got_error_from_errno("lseek");
846 8e359fa0 2022-10-13 stsp return err;
849 8e359fa0 2022-10-13 stsp static const struct got_error *
850 8e359fa0 2022-10-13 stsp read_packed_blob_privsep(uint8_t **outbuf, size_t *size, size_t *hdrlen,
851 8e359fa0 2022-10-13 stsp int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
852 8e359fa0 2022-10-13 stsp struct got_object_id *id)
854 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
856 8e359fa0 2022-10-13 stsp if (pack->privsep_child == NULL) {
857 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
859 8e359fa0 2022-10-13 stsp return err;
862 8e359fa0 2022-10-13 stsp return request_packed_blob(outbuf, size, hdrlen, outfd, pack, packidx,
866 8e359fa0 2022-10-13 stsp static const struct got_error *
867 8e359fa0 2022-10-13 stsp request_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen, int outfd,
868 8e359fa0 2022-10-13 stsp int infd, struct got_object_id *id, struct imsgbuf *ibuf)
870 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
871 8e359fa0 2022-10-13 stsp int outfd_child;
873 8e359fa0 2022-10-13 stsp outfd_child = dup(outfd);
874 8e359fa0 2022-10-13 stsp if (outfd_child == -1)
875 8e359fa0 2022-10-13 stsp return got_error_from_errno("dup");
877 8e359fa0 2022-10-13 stsp err = got_privsep_send_blob_req(ibuf, infd, id, -1);
879 8e359fa0 2022-10-13 stsp return err;
881 8e359fa0 2022-10-13 stsp err = got_privsep_send_blob_outfd(ibuf, outfd_child);
883 8e359fa0 2022-10-13 stsp return err;
885 8e359fa0 2022-10-13 stsp err = got_privsep_recv_blob(outbuf, size, hdrlen, ibuf);
887 8e359fa0 2022-10-13 stsp return err;
889 8e359fa0 2022-10-13 stsp if (lseek(outfd, SEEK_SET, 0) == -1)
890 8e359fa0 2022-10-13 stsp return got_error_from_errno("lseek");
892 8e359fa0 2022-10-13 stsp return err;
895 8e359fa0 2022-10-13 stsp static const struct got_error *
896 8e359fa0 2022-10-13 stsp read_blob_privsep(uint8_t **outbuf, size_t *size, size_t *hdrlen,
897 8e359fa0 2022-10-13 stsp int outfd, int infd, struct got_object_id *id, struct got_repository *repo)
899 8e359fa0 2022-10-13 stsp const struct got_error *err;
900 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
902 8e359fa0 2022-10-13 stsp if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].imsg_fd != -1) {
903 8e359fa0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf;
904 8e359fa0 2022-10-13 stsp return request_blob(outbuf, size, hdrlen, outfd, infd, id,
908 1d9e43b0 2022-10-13 stsp err = start_child(repo, GOT_REPO_PRIVSEP_CHILD_BLOB);
910 8e359fa0 2022-10-13 stsp return err;
912 1d9e43b0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf;
913 8e359fa0 2022-10-13 stsp return request_blob(outbuf, size, hdrlen, outfd, infd, id, ibuf);
916 8e359fa0 2022-10-13 stsp static const struct got_error *
917 8e359fa0 2022-10-13 stsp open_blob(struct got_blob_object **blob, struct got_repository *repo,
918 8e359fa0 2022-10-13 stsp struct got_object_id *id, size_t blocksize, int outfd)
920 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
921 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
922 8e359fa0 2022-10-13 stsp int idx, dfd = -1;
923 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
924 8e359fa0 2022-10-13 stsp uint8_t *outbuf;
925 8e359fa0 2022-10-13 stsp size_t size, hdrlen;
926 8e359fa0 2022-10-13 stsp struct stat sb;
928 8e359fa0 2022-10-13 stsp *blob = calloc(1, sizeof(**blob));
929 8e359fa0 2022-10-13 stsp if (*blob == NULL)
930 8e359fa0 2022-10-13 stsp return got_error_from_errno("calloc");
932 8e359fa0 2022-10-13 stsp (*blob)->read_buf = malloc(blocksize);
933 8e359fa0 2022-10-13 stsp if ((*blob)->read_buf == NULL) {
934 8e359fa0 2022-10-13 stsp err = got_error_from_errno("malloc");
938 8e359fa0 2022-10-13 stsp if (ftruncate(outfd, 0L) == -1) {
939 8e359fa0 2022-10-13 stsp err = got_error_from_errno("ftruncate");
942 8e359fa0 2022-10-13 stsp if (lseek(outfd, SEEK_SET, 0) == -1) {
943 8e359fa0 2022-10-13 stsp err = got_error_from_errno("lseek");
947 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
948 8e359fa0 2022-10-13 stsp if (err == NULL) {
949 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
951 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
952 8e359fa0 2022-10-13 stsp packidx->path_packidx);
956 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
957 8e359fa0 2022-10-13 stsp if (pack == NULL) {
958 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
963 8e359fa0 2022-10-13 stsp err = read_packed_blob_privsep(&outbuf, &size, &hdrlen, outfd,
964 8e359fa0 2022-10-13 stsp pack, packidx, idx, id);
965 8e359fa0 2022-10-13 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
968 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&infd, id, repo);
971 8e359fa0 2022-10-13 stsp err = read_blob_privsep(&outbuf, &size, &hdrlen, outfd, infd,
977 8e359fa0 2022-10-13 stsp if (hdrlen > size) {
978 8e359fa0 2022-10-13 stsp err = got_error(GOT_ERR_BAD_OBJ_HDR);
982 8e359fa0 2022-10-13 stsp if (outbuf) {
983 8e359fa0 2022-10-13 stsp (*blob)->f = fmemopen(outbuf, size, "rb");
984 8e359fa0 2022-10-13 stsp if ((*blob)->f == NULL) {
985 8e359fa0 2022-10-13 stsp err = got_error_from_errno("fmemopen");
986 8e359fa0 2022-10-13 stsp free(outbuf);
989 8e359fa0 2022-10-13 stsp (*blob)->data = outbuf;
991 8e359fa0 2022-10-13 stsp if (fstat(outfd, &sb) == -1) {
992 8e359fa0 2022-10-13 stsp err = got_error_from_errno("fstat");
996 8e359fa0 2022-10-13 stsp if (sb.st_size != size) {
997 8e359fa0 2022-10-13 stsp err = got_error(GOT_ERR_PRIVSEP_LEN);
1001 8e359fa0 2022-10-13 stsp dfd = dup(outfd);
1002 8e359fa0 2022-10-13 stsp if (dfd == -1) {
1003 8e359fa0 2022-10-13 stsp err = got_error_from_errno("dup");
1004 8e359fa0 2022-10-13 stsp goto done;
1007 8e359fa0 2022-10-13 stsp (*blob)->f = fdopen(dfd, "rb");
1008 8e359fa0 2022-10-13 stsp if ((*blob)->f == NULL) {
1009 8e359fa0 2022-10-13 stsp err = got_error_from_errno("fdopen");
1010 8e359fa0 2022-10-13 stsp close(dfd);
1012 8e359fa0 2022-10-13 stsp goto done;
1016 8e359fa0 2022-10-13 stsp (*blob)->hdrlen = hdrlen;
1017 8e359fa0 2022-10-13 stsp (*blob)->blocksize = blocksize;
1018 08175cbb 2023-02-10 op memcpy(&(*blob)->id, id, sizeof(*id));
1021 8e359fa0 2022-10-13 stsp free(path_packfile);
1022 8e359fa0 2022-10-13 stsp if (err) {
1023 8e359fa0 2022-10-13 stsp if (*blob) {
1024 8e359fa0 2022-10-13 stsp got_object_blob_close(*blob);
1025 8e359fa0 2022-10-13 stsp *blob = NULL;
1028 8e359fa0 2022-10-13 stsp return err;
1031 8e359fa0 2022-10-13 stsp const struct got_error *
1032 8e359fa0 2022-10-13 stsp got_object_open_as_blob(struct got_blob_object **blob,
1033 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object_id *id, size_t blocksize,
1034 8e359fa0 2022-10-13 stsp int outfd)
1036 8e359fa0 2022-10-13 stsp return open_blob(blob, repo, id, blocksize, outfd);
1039 8e359fa0 2022-10-13 stsp const struct got_error *
1040 8e359fa0 2022-10-13 stsp got_object_blob_open(struct got_blob_object **blob,
1041 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object *obj, size_t blocksize,
1042 8e359fa0 2022-10-13 stsp int outfd)
1044 8e359fa0 2022-10-13 stsp return open_blob(blob, repo, got_object_get_id(obj), blocksize, outfd);
1047 8e359fa0 2022-10-13 stsp static const struct got_error *
1048 8e359fa0 2022-10-13 stsp request_packed_tag(struct got_tag_object **tag, struct got_pack *pack,
1049 8e359fa0 2022-10-13 stsp int pack_idx, struct got_object_id *id)
1051 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
1053 8e359fa0 2022-10-13 stsp err = got_privsep_send_tag_req(pack->privsep_child->ibuf, -1, id,
1054 8e359fa0 2022-10-13 stsp pack_idx);
1056 8e359fa0 2022-10-13 stsp return err;
1058 8e359fa0 2022-10-13 stsp return got_privsep_recv_tag(tag, pack->privsep_child->ibuf);
1061 8e359fa0 2022-10-13 stsp static const struct got_error *
1062 8e359fa0 2022-10-13 stsp read_packed_tag_privsep(struct got_tag_object **tag,
1063 8e359fa0 2022-10-13 stsp struct got_pack *pack, struct got_packidx *packidx, int idx,
1064 8e359fa0 2022-10-13 stsp struct got_object_id *id)
1066 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
1068 8e359fa0 2022-10-13 stsp if (pack->privsep_child)
1069 8e359fa0 2022-10-13 stsp return request_packed_tag(tag, pack, idx, id);
1071 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
1073 8e359fa0 2022-10-13 stsp return err;
1075 8e359fa0 2022-10-13 stsp return request_packed_tag(tag, pack, idx, id);
1078 8e359fa0 2022-10-13 stsp static const struct got_error *
1079 8e359fa0 2022-10-13 stsp request_tag(struct got_tag_object **tag, struct got_repository *repo,
1080 8e359fa0 2022-10-13 stsp int fd, struct got_object_id *id)
1082 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
1083 8e359fa0 2022-10-13 stsp struct imsgbuf *ibuf;
1085 8e359fa0 2022-10-13 stsp ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].ibuf;
1087 8e359fa0 2022-10-13 stsp err = got_privsep_send_tag_req(ibuf, fd, id, -1);
1089 8e359fa0 2022-10-13 stsp return err;
1091 8e359fa0 2022-10-13 stsp return got_privsep_recv_tag(tag, ibuf);
1094 8e359fa0 2022-10-13 stsp static const struct got_error *
1095 8e359fa0 2022-10-13 stsp read_tag_privsep(struct got_tag_object **tag, int obj_fd,
1096 8e359fa0 2022-10-13 stsp struct got_object_id *id, struct got_repository *repo)
1098 8e359fa0 2022-10-13 stsp const struct got_error *err;
1100 8e359fa0 2022-10-13 stsp if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].imsg_fd != -1)
1101 8e359fa0 2022-10-13 stsp return request_tag(tag, repo, obj_fd, id);
1103 1d9e43b0 2022-10-13 stsp err = start_child(repo, GOT_REPO_PRIVSEP_CHILD_TAG);
1105 8e359fa0 2022-10-13 stsp return err;
1107 8e359fa0 2022-10-13 stsp return request_tag(tag, repo, obj_fd, id);
1110 8e359fa0 2022-10-13 stsp static const struct got_error *
1111 8e359fa0 2022-10-13 stsp open_tag(struct got_tag_object **tag, struct got_repository *repo,
1112 8e359fa0 2022-10-13 stsp struct got_object_id *id, int check_cache)
1114 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
1115 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
1117 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
1118 8e359fa0 2022-10-13 stsp struct got_object *obj = NULL;
1119 8e359fa0 2022-10-13 stsp int obj_type = GOT_OBJ_TYPE_ANY;
1121 8e359fa0 2022-10-13 stsp if (check_cache) {
1122 8e359fa0 2022-10-13 stsp *tag = got_repo_get_cached_tag(repo, id);
1123 8e359fa0 2022-10-13 stsp if (*tag != NULL) {
1124 8e359fa0 2022-10-13 stsp (*tag)->refcnt++;
1125 8e359fa0 2022-10-13 stsp return NULL;
1128 8e359fa0 2022-10-13 stsp *tag = NULL;
1130 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
1131 8e359fa0 2022-10-13 stsp if (err == NULL) {
1132 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
1134 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
1135 8e359fa0 2022-10-13 stsp packidx->path_packidx);
1137 8e359fa0 2022-10-13 stsp return err;
1139 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
1140 8e359fa0 2022-10-13 stsp if (pack == NULL) {
1141 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
1144 8e359fa0 2022-10-13 stsp goto done;
1147 8e359fa0 2022-10-13 stsp /* Beware of "lightweight" tags: Check object type first. */
1148 8e359fa0 2022-10-13 stsp err = read_packed_object_privsep(&obj, repo, pack, packidx,
1151 8e359fa0 2022-10-13 stsp goto done;
1152 8e359fa0 2022-10-13 stsp obj_type = obj->type;
1153 8e359fa0 2022-10-13 stsp got_object_close(obj);
1154 8e359fa0 2022-10-13 stsp if (obj_type != GOT_OBJ_TYPE_TAG) {
1155 8e359fa0 2022-10-13 stsp err = got_error(GOT_ERR_OBJ_TYPE);
1156 8e359fa0 2022-10-13 stsp goto done;
1158 8e359fa0 2022-10-13 stsp err = read_packed_tag_privsep(tag, pack, packidx, idx, id);
1159 8e359fa0 2022-10-13 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
1162 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&fd, id, repo);
1164 8e359fa0 2022-10-13 stsp return err;
1165 8e359fa0 2022-10-13 stsp err = got_object_read_header_privsep(&obj, id, repo, fd);
1167 8e359fa0 2022-10-13 stsp return err;
1168 8e359fa0 2022-10-13 stsp obj_type = obj->type;
1169 8e359fa0 2022-10-13 stsp got_object_close(obj);
1170 8e359fa0 2022-10-13 stsp if (obj_type != GOT_OBJ_TYPE_TAG)
1171 8e359fa0 2022-10-13 stsp return got_error(GOT_ERR_OBJ_TYPE);
1173 8e359fa0 2022-10-13 stsp err = got_object_open_loose_fd(&fd, id, repo);
1175 8e359fa0 2022-10-13 stsp return err;
1176 8e359fa0 2022-10-13 stsp err = read_tag_privsep(tag, fd, id, repo);
1179 8e359fa0 2022-10-13 stsp if (err == NULL) {
1180 8e359fa0 2022-10-13 stsp (*tag)->refcnt++;
1181 8e359fa0 2022-10-13 stsp err = got_repo_cache_tag(repo, id, *tag);
1184 8e359fa0 2022-10-13 stsp free(path_packfile);
1185 8e359fa0 2022-10-13 stsp return err;
1188 8e359fa0 2022-10-13 stsp const struct got_error *
1189 8e359fa0 2022-10-13 stsp got_object_open_as_tag(struct got_tag_object **tag,
1190 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object_id *id)
1192 8e359fa0 2022-10-13 stsp *tag = got_repo_get_cached_tag(repo, id);
1193 8e359fa0 2022-10-13 stsp if (*tag != NULL) {
1194 8e359fa0 2022-10-13 stsp (*tag)->refcnt++;
1195 8e359fa0 2022-10-13 stsp return NULL;
1198 8e359fa0 2022-10-13 stsp return open_tag(tag, repo, id, 0);
1201 8e359fa0 2022-10-13 stsp const struct got_error *
1202 8e359fa0 2022-10-13 stsp got_object_tag_open(struct got_tag_object **tag,
1203 8e359fa0 2022-10-13 stsp struct got_repository *repo, struct got_object *obj)
1205 8e359fa0 2022-10-13 stsp return open_tag(tag, repo, got_object_get_id(obj), 1);
1208 8e359fa0 2022-10-13 stsp const struct got_error *
1209 8e359fa0 2022-10-13 stsp got_traverse_packed_commits(struct got_object_id_queue *traversed_commits,
1210 8e359fa0 2022-10-13 stsp struct got_object_id *commit_id, const char *path,
1211 8e359fa0 2022-10-13 stsp struct got_repository *repo)
1213 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
1214 8e359fa0 2022-10-13 stsp struct got_pack *pack = NULL;
1215 8e359fa0 2022-10-13 stsp struct got_packidx *packidx = NULL;
1216 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
1217 8e359fa0 2022-10-13 stsp struct got_commit_object *changed_commit = NULL;
1218 494e2b9b 2024-03-27 stsp struct got_object_qid *changed_commit_qid = NULL;
1221 8e359fa0 2022-10-13 stsp err = got_repo_search_packidx(&packidx, &idx, repo, commit_id);
1222 8e359fa0 2022-10-13 stsp if (err) {
1223 8e359fa0 2022-10-13 stsp if (err->code != GOT_ERR_NO_OBJ)
1224 8e359fa0 2022-10-13 stsp return err;
1225 8e359fa0 2022-10-13 stsp return NULL;
1228 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
1229 8e359fa0 2022-10-13 stsp packidx->path_packidx);
1231 8e359fa0 2022-10-13 stsp return err;
1233 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
1234 8e359fa0 2022-10-13 stsp if (pack == NULL) {
1235 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
1237 8e359fa0 2022-10-13 stsp goto done;
1240 8e359fa0 2022-10-13 stsp if (pack->privsep_child == NULL) {
1241 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
1243 8e359fa0 2022-10-13 stsp goto done;
1246 8e359fa0 2022-10-13 stsp err = got_privsep_send_commit_traversal_request(
1247 8e359fa0 2022-10-13 stsp pack->privsep_child->ibuf, commit_id, idx, path);
1249 8e359fa0 2022-10-13 stsp goto done;
1251 8e359fa0 2022-10-13 stsp err = got_privsep_recv_traversed_commits(&changed_commit,
1252 494e2b9b 2024-03-27 stsp traversed_commits, pack->privsep_child->ibuf);
1254 8e359fa0 2022-10-13 stsp goto done;
1256 8e359fa0 2022-10-13 stsp if (changed_commit) {
1258 8e359fa0 2022-10-13 stsp * Cache the commit in which the path was changed.
1259 8e359fa0 2022-10-13 stsp * This commit might be opened again soon.
1261 8e359fa0 2022-10-13 stsp changed_commit->refcnt++;
1262 494e2b9b 2024-03-27 stsp changed_commit_qid = STAILQ_LAST(traversed_commits, got_object_qid, entry);
1263 494e2b9b 2024-03-27 stsp err = got_repo_cache_commit(repo, &changed_commit_qid->id,
1264 8e359fa0 2022-10-13 stsp changed_commit);
1265 8e359fa0 2022-10-13 stsp got_object_commit_close(changed_commit);
1268 8e359fa0 2022-10-13 stsp free(path_packfile);
1269 8e359fa0 2022-10-13 stsp return err;
1272 8e359fa0 2022-10-13 stsp const struct got_error *
1273 8e359fa0 2022-10-13 stsp got_object_enumerate(int *found_all_objects,
1274 8e359fa0 2022-10-13 stsp got_object_enumerate_commit_cb cb_commit,
1275 8e359fa0 2022-10-13 stsp got_object_enumerate_tree_cb cb_tree, void *cb_arg,
1276 8e359fa0 2022-10-13 stsp struct got_object_id **ours, int nours,
1277 8e359fa0 2022-10-13 stsp struct got_object_id **theirs, int ntheirs,
1278 8e359fa0 2022-10-13 stsp struct got_packidx *packidx, struct got_repository *repo)
1280 8e359fa0 2022-10-13 stsp const struct got_error *err = NULL;
1281 8e359fa0 2022-10-13 stsp struct got_pack *pack;
1282 8e359fa0 2022-10-13 stsp char *path_packfile = NULL;
1284 8e359fa0 2022-10-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
1285 8e359fa0 2022-10-13 stsp packidx->path_packidx);
1287 8e359fa0 2022-10-13 stsp return err;
1289 8e359fa0 2022-10-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
1290 8e359fa0 2022-10-13 stsp if (pack == NULL) {
1291 8e359fa0 2022-10-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
1293 8e359fa0 2022-10-13 stsp goto done;
1296 8e359fa0 2022-10-13 stsp if (pack->privsep_child == NULL) {
1297 8e359fa0 2022-10-13 stsp err = got_pack_start_privsep_child(pack, packidx);
1299 8e359fa0 2022-10-13 stsp goto done;
1302 8e359fa0 2022-10-13 stsp err = got_privsep_send_object_enumeration_request(
1303 8e359fa0 2022-10-13 stsp pack->privsep_child->ibuf);
1305 8e359fa0 2022-10-13 stsp goto done;
1307 8e359fa0 2022-10-13 stsp err = got_privsep_send_object_idlist(pack->privsep_child->ibuf,
1308 8e359fa0 2022-10-13 stsp ours, nours);
1310 8e359fa0 2022-10-13 stsp goto done;
1311 8e359fa0 2022-10-13 stsp err = got_privsep_send_object_idlist_done(pack->privsep_child->ibuf);
1313 8e359fa0 2022-10-13 stsp goto done;
1315 8e359fa0 2022-10-13 stsp err = got_privsep_send_object_idlist(pack->privsep_child->ibuf,
1316 8e359fa0 2022-10-13 stsp theirs, ntheirs);
1318 8e359fa0 2022-10-13 stsp goto done;
1319 8e359fa0 2022-10-13 stsp err = got_privsep_send_object_idlist_done(pack->privsep_child->ibuf);
1321 8e359fa0 2022-10-13 stsp goto done;
1323 8e359fa0 2022-10-13 stsp err = got_privsep_recv_enumerated_objects(found_all_objects,
1324 8e359fa0 2022-10-13 stsp pack->privsep_child->ibuf, cb_commit, cb_tree, cb_arg, repo);
1326 8e359fa0 2022-10-13 stsp free(path_packfile);
1327 8e359fa0 2022-10-13 stsp return err;