2 3efd8e31 2022-10-23 thomas * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
4 3efd8e31 2022-10-23 thomas * Permission to use, copy, modify, and distribute this software for any
5 3efd8e31 2022-10-23 thomas * purpose with or without fee is hereby granted, provided that the above
6 3efd8e31 2022-10-23 thomas * copyright notice and this permission notice appear in all copies.
8 3efd8e31 2022-10-23 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 3efd8e31 2022-10-23 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 3efd8e31 2022-10-23 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 3efd8e31 2022-10-23 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 3efd8e31 2022-10-23 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 3efd8e31 2022-10-23 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 3efd8e31 2022-10-23 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 3efd8e31 2022-10-23 thomas #include <sys/queue.h>
18 3efd8e31 2022-10-23 thomas #include <sys/tree.h>
19 3efd8e31 2022-10-23 thomas #include <sys/stat.h>
21 3efd8e31 2022-10-23 thomas #include <errno.h>
22 3efd8e31 2022-10-23 thomas #include <limits.h>
23 3efd8e31 2022-10-23 thomas #include <sha1.h>
24 3efd8e31 2022-10-23 thomas #include <stdio.h>
25 3efd8e31 2022-10-23 thomas #include <stdlib.h>
26 3efd8e31 2022-10-23 thomas #include <string.h>
27 3efd8e31 2022-10-23 thomas #include <unistd.h>
29 3efd8e31 2022-10-23 thomas #include "got_error.h"
30 3efd8e31 2022-10-23 thomas #include "got_object.h"
31 3efd8e31 2022-10-23 thomas #include "got_repository.h"
32 3efd8e31 2022-10-23 thomas #include "got_path.h"
34 3efd8e31 2022-10-23 thomas #include "got_lib_delta.h"
35 3efd8e31 2022-10-23 thomas #include "got_lib_object.h"
36 3efd8e31 2022-10-23 thomas #include "got_lib_object_cache.h"
37 3efd8e31 2022-10-23 thomas #include "got_lib_object_parse.h"
38 3efd8e31 2022-10-23 thomas #include "got_lib_pack.h"
39 3efd8e31 2022-10-23 thomas #include "got_lib_repository.h"
41 3efd8e31 2022-10-23 thomas const struct got_error *
42 3efd8e31 2022-10-23 thomas got_object_open_packed(struct got_object **obj, struct got_object_id *id,
43 3efd8e31 2022-10-23 thomas struct got_repository *repo)
45 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
46 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
47 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
49 3efd8e31 2022-10-23 thomas char *path_packfile;
51 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
53 3efd8e31 2022-10-23 thomas return err;
55 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
56 3efd8e31 2022-10-23 thomas packidx->path_packidx);
58 3efd8e31 2022-10-23 thomas return err;
60 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
61 3efd8e31 2022-10-23 thomas if (pack == NULL) {
62 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
64 3efd8e31 2022-10-23 thomas goto done;
67 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(obj, pack, packidx, idx, id);
69 3efd8e31 2022-10-23 thomas return err;
70 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
72 3efd8e31 2022-10-23 thomas err = got_repo_cache_object(repo, id, *obj);
73 3efd8e31 2022-10-23 thomas if (err) {
74 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
75 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
76 3efd8e31 2022-10-23 thomas err = NULL;
79 3efd8e31 2022-10-23 thomas free(path_packfile);
80 3efd8e31 2022-10-23 thomas return err;
83 3efd8e31 2022-10-23 thomas const struct got_error *
84 3efd8e31 2022-10-23 thomas got_object_open_from_packfile(struct got_object **obj, struct got_object_id *id,
85 3efd8e31 2022-10-23 thomas struct got_pack *pack, struct got_packidx *packidx, int obj_idx,
86 3efd8e31 2022-10-23 thomas struct got_repository *repo)
88 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
91 3efd8e31 2022-10-23 thomas const struct got_error *
92 3efd8e31 2022-10-23 thomas got_object_read_raw_delta(uint64_t *base_size, uint64_t *result_size,
93 3efd8e31 2022-10-23 thomas off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
94 3efd8e31 2022-10-23 thomas off_t *delta_out_offset, struct got_object_id **base_id, int delta_cache_fd,
95 3efd8e31 2022-10-23 thomas struct got_packidx *packidx, int obj_idx, struct got_object_id *id,
96 3efd8e31 2022-10-23 thomas struct got_repository *repo)
98 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
101 3efd8e31 2022-10-23 thomas const struct got_error *
102 3efd8e31 2022-10-23 thomas got_object_open(struct got_object **obj, struct got_repository *repo,
103 3efd8e31 2022-10-23 thomas struct got_object_id *id)
105 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
108 3efd8e31 2022-10-23 thomas *obj = got_repo_get_cached_object(repo, id);
109 3efd8e31 2022-10-23 thomas if (*obj != NULL) {
110 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
111 3efd8e31 2022-10-23 thomas return NULL;
114 3efd8e31 2022-10-23 thomas err = got_object_open_packed(obj, id, repo);
115 3efd8e31 2022-10-23 thomas if (err) {
116 3efd8e31 2022-10-23 thomas if (err->code != GOT_ERR_NO_OBJ)
117 3efd8e31 2022-10-23 thomas return err;
119 3efd8e31 2022-10-23 thomas return NULL;
121 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
122 3efd8e31 2022-10-23 thomas if (err) {
123 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_ERRNO && errno == ENOENT)
124 3efd8e31 2022-10-23 thomas err = got_error_no_obj(id);
125 3efd8e31 2022-10-23 thomas return err;
128 3efd8e31 2022-10-23 thomas err = got_object_read_header(obj, fd);
130 3efd8e31 2022-10-23 thomas goto done;
132 3efd8e31 2022-10-23 thomas memcpy(&(*obj)->id, id, sizeof((*obj)->id));
133 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
135 3efd8e31 2022-10-23 thomas err = got_repo_cache_object(repo, id, *obj);
136 3efd8e31 2022-10-23 thomas if (err) {
137 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
138 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
139 3efd8e31 2022-10-23 thomas err = NULL;
142 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
143 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
144 3efd8e31 2022-10-23 thomas return err;
147 3efd8e31 2022-10-23 thomas static const struct got_error *
148 3efd8e31 2022-10-23 thomas wrap_fd(FILE **f, int wrapped_fd)
150 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
153 3efd8e31 2022-10-23 thomas if (ftruncate(wrapped_fd, 0L) == -1)
154 3efd8e31 2022-10-23 thomas return got_error_from_errno("ftruncate");
156 3efd8e31 2022-10-23 thomas if (lseek(wrapped_fd, 0L, SEEK_SET) == -1)
157 3efd8e31 2022-10-23 thomas return got_error_from_errno("lseek");
159 3efd8e31 2022-10-23 thomas fd = dup(wrapped_fd);
160 3efd8e31 2022-10-23 thomas if (fd == -1)
161 3efd8e31 2022-10-23 thomas return got_error_from_errno("dup");
163 3efd8e31 2022-10-23 thomas *f = fdopen(fd, "w+");
164 3efd8e31 2022-10-23 thomas if (*f == NULL) {
165 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fdopen");
166 3efd8e31 2022-10-23 thomas close(fd);
168 3efd8e31 2022-10-23 thomas return err;
171 3efd8e31 2022-10-23 thomas static const struct got_error *
172 3efd8e31 2022-10-23 thomas read_packed_object_raw(uint8_t **outbuf, off_t *size, size_t *hdrlen,
173 3efd8e31 2022-10-23 thomas int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
174 3efd8e31 2022-10-23 thomas struct got_object_id *id)
176 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
177 3efd8e31 2022-10-23 thomas uint64_t raw_size = 0;
178 3efd8e31 2022-10-23 thomas struct got_object *obj;
179 3efd8e31 2022-10-23 thomas FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
181 3efd8e31 2022-10-23 thomas *outbuf = NULL;
182 3efd8e31 2022-10-23 thomas *size = 0;
183 3efd8e31 2022-10-23 thomas *hdrlen = 0;
185 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
187 3efd8e31 2022-10-23 thomas return err;
189 3efd8e31 2022-10-23 thomas if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
190 3efd8e31 2022-10-23 thomas err = got_pack_get_max_delta_object_size(&raw_size, obj, pack);
192 3efd8e31 2022-10-23 thomas goto done;
194 3efd8e31 2022-10-23 thomas raw_size = obj->size;
196 3efd8e31 2022-10-23 thomas if (raw_size <= GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
197 3efd8e31 2022-10-23 thomas size_t len;
198 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(outbuf, &len,
199 3efd8e31 2022-10-23 thomas obj, pack);
201 3efd8e31 2022-10-23 thomas goto done;
202 3efd8e31 2022-10-23 thomas *size = (off_t)len;
205 3efd8e31 2022-10-23 thomas * XXX This uses 3 file extra descriptors for no good reason.
206 3efd8e31 2022-10-23 thomas * We should have got_packfile_extract_object_to_fd().
208 3efd8e31 2022-10-23 thomas err = wrap_fd(&outfile, outfd);
210 3efd8e31 2022-10-23 thomas goto done;
211 3efd8e31 2022-10-23 thomas err = wrap_fd(&basefile, pack->basefd);
213 3efd8e31 2022-10-23 thomas goto done;
214 3efd8e31 2022-10-23 thomas err = wrap_fd(&accumfile, pack->accumfd);
216 3efd8e31 2022-10-23 thomas goto done;
217 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object(pack, obj, outfile, basefile,
218 3efd8e31 2022-10-23 thomas accumfile);
220 3efd8e31 2022-10-23 thomas goto done;
221 b296ac1c 2023-01-09 thomas *size = obj->size;
224 3efd8e31 2022-10-23 thomas *hdrlen = obj->hdrlen;
226 3efd8e31 2022-10-23 thomas got_object_close(obj);
227 3efd8e31 2022-10-23 thomas if (outfile && fclose(outfile) == EOF && err == NULL)
228 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
229 3efd8e31 2022-10-23 thomas if (basefile && fclose(basefile) == EOF && err == NULL)
230 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
231 3efd8e31 2022-10-23 thomas if (accumfile && fclose(accumfile) == EOF && err == NULL)
232 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
233 3efd8e31 2022-10-23 thomas return err;
237 3efd8e31 2022-10-23 thomas static void
238 3efd8e31 2022-10-23 thomas put_raw_object_tempfile(struct got_raw_object *obj)
240 3efd8e31 2022-10-23 thomas struct got_repository *repo = obj->close_arg;
242 3efd8e31 2022-10-23 thomas if (obj->tempfile_idx != -1)
243 3efd8e31 2022-10-23 thomas got_repo_temp_fds_put(obj->tempfile_idx, repo);
246 3efd8e31 2022-10-23 thomas /* *outfd must be initialized to -1 by caller */
247 3efd8e31 2022-10-23 thomas const struct got_error *
248 3efd8e31 2022-10-23 thomas got_object_raw_open(struct got_raw_object **obj, int *outfd,
249 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
251 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
252 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
253 3efd8e31 2022-10-23 thomas int idx, tempfile_idx = -1;
254 3efd8e31 2022-10-23 thomas uint8_t *outbuf = NULL;
255 3efd8e31 2022-10-23 thomas off_t size = 0;
256 3efd8e31 2022-10-23 thomas size_t hdrlen = 0;
257 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
259 3efd8e31 2022-10-23 thomas *obj = got_repo_get_cached_raw_object(repo, id);
260 3efd8e31 2022-10-23 thomas if (*obj != NULL) {
261 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
262 3efd8e31 2022-10-23 thomas return NULL;
265 3efd8e31 2022-10-23 thomas if (*outfd == -1) {
266 3efd8e31 2022-10-23 thomas int tempfd;
268 3efd8e31 2022-10-23 thomas err = got_repo_temp_fds_get(&tempfd, &tempfile_idx, repo);
270 3efd8e31 2022-10-23 thomas return err;
272 3efd8e31 2022-10-23 thomas /* Duplicate tempfile descriptor to allow use of fdopen(3). */
273 3efd8e31 2022-10-23 thomas *outfd = dup(tempfd);
274 3efd8e31 2022-10-23 thomas if (*outfd == -1) {
275 3efd8e31 2022-10-23 thomas got_repo_temp_fds_put(tempfile_idx, repo);
276 3efd8e31 2022-10-23 thomas return got_error_from_errno("dup");
280 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
281 3efd8e31 2022-10-23 thomas if (err == NULL) {
282 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
284 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
285 3efd8e31 2022-10-23 thomas packidx->path_packidx);
287 3efd8e31 2022-10-23 thomas goto done;
289 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
290 3efd8e31 2022-10-23 thomas if (pack == NULL) {
291 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
292 3efd8e31 2022-10-23 thomas packidx);
294 3efd8e31 2022-10-23 thomas goto done;
296 3efd8e31 2022-10-23 thomas err = read_packed_object_raw(&outbuf, &size, &hdrlen,
297 3efd8e31 2022-10-23 thomas *outfd, pack, packidx, idx, id);
299 3efd8e31 2022-10-23 thomas goto done;
300 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
303 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
305 3efd8e31 2022-10-23 thomas goto done;
306 3efd8e31 2022-10-23 thomas err = got_object_read_raw(&outbuf, &size, &hdrlen,
307 3efd8e31 2022-10-23 thomas GOT_DELTA_RESULT_SIZE_CACHED_MAX, *outfd, id, fd);
308 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
309 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
311 3efd8e31 2022-10-23 thomas goto done;
314 3efd8e31 2022-10-23 thomas err = got_object_raw_alloc(obj, outbuf, outfd, hdrlen, size);
316 3efd8e31 2022-10-23 thomas goto done;
318 3efd8e31 2022-10-23 thomas err = got_repo_cache_raw_object(repo, id, *obj);
319 3efd8e31 2022-10-23 thomas if (err) {
320 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
321 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
322 3efd8e31 2022-10-23 thomas err = NULL;
325 3efd8e31 2022-10-23 thomas free(path_packfile);
326 3efd8e31 2022-10-23 thomas if (err) {
327 3efd8e31 2022-10-23 thomas if (*obj) {
328 3efd8e31 2022-10-23 thomas got_object_raw_close(*obj);
329 3efd8e31 2022-10-23 thomas *obj = NULL;
331 3efd8e31 2022-10-23 thomas free(outbuf);
332 3efd8e31 2022-10-23 thomas if (tempfile_idx != -1)
333 3efd8e31 2022-10-23 thomas got_repo_temp_fds_put(tempfile_idx, repo);
335 3efd8e31 2022-10-23 thomas (*obj)->tempfile_idx = tempfile_idx;
336 3efd8e31 2022-10-23 thomas (*obj)->close_cb = put_raw_object_tempfile;
337 3efd8e31 2022-10-23 thomas (*obj)->close_arg = repo;
339 3efd8e31 2022-10-23 thomas return err;
342 3efd8e31 2022-10-23 thomas static const struct got_error *
343 3efd8e31 2022-10-23 thomas open_commit(struct got_commit_object **commit,
344 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, int check_cache)
346 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
347 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
349 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
351 3efd8e31 2022-10-23 thomas if (check_cache) {
352 3efd8e31 2022-10-23 thomas *commit = got_repo_get_cached_commit(repo, id);
353 3efd8e31 2022-10-23 thomas if (*commit != NULL) {
354 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
355 3efd8e31 2022-10-23 thomas return NULL;
358 3efd8e31 2022-10-23 thomas *commit = NULL;
360 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
361 3efd8e31 2022-10-23 thomas if (err == NULL) {
362 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
363 3efd8e31 2022-10-23 thomas struct got_object *obj;
364 3efd8e31 2022-10-23 thomas uint8_t *buf;
365 3efd8e31 2022-10-23 thomas size_t len;
367 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
368 3efd8e31 2022-10-23 thomas packidx->path_packidx);
370 3efd8e31 2022-10-23 thomas return err;
372 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
373 3efd8e31 2022-10-23 thomas if (pack == NULL) {
374 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
375 3efd8e31 2022-10-23 thomas packidx);
377 3efd8e31 2022-10-23 thomas goto done;
379 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
381 3efd8e31 2022-10-23 thomas goto done;
382 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
383 3efd8e31 2022-10-23 thomas obj, pack);
384 3efd8e31 2022-10-23 thomas got_object_close(obj);
386 3efd8e31 2022-10-23 thomas goto done;
387 3efd8e31 2022-10-23 thomas err = got_object_parse_commit(commit, buf, len);
388 3efd8e31 2022-10-23 thomas free(buf);
389 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
392 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
394 3efd8e31 2022-10-23 thomas return err;
395 3efd8e31 2022-10-23 thomas err = got_object_read_commit(commit, fd, id, 0);
396 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
397 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
399 3efd8e31 2022-10-23 thomas return err;
402 3efd8e31 2022-10-23 thomas if (err == NULL) {
403 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
404 3efd8e31 2022-10-23 thomas err = got_repo_cache_commit(repo, id, *commit);
405 3efd8e31 2022-10-23 thomas if (err) {
406 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
407 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
408 3efd8e31 2022-10-23 thomas err = NULL;
412 3efd8e31 2022-10-23 thomas free(path_packfile);
413 3efd8e31 2022-10-23 thomas return err;
416 3efd8e31 2022-10-23 thomas const struct got_error *
417 3efd8e31 2022-10-23 thomas got_object_open_as_commit(struct got_commit_object **commit,
418 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
420 3efd8e31 2022-10-23 thomas *commit = got_repo_get_cached_commit(repo, id);
421 3efd8e31 2022-10-23 thomas if (*commit != NULL) {
422 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
423 3efd8e31 2022-10-23 thomas return NULL;
426 3efd8e31 2022-10-23 thomas return open_commit(commit, repo, id, 0);
429 3efd8e31 2022-10-23 thomas const struct got_error *
430 3efd8e31 2022-10-23 thomas got_object_commit_open(struct got_commit_object **commit,
431 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
433 3efd8e31 2022-10-23 thomas return open_commit(commit, repo, got_object_get_id(obj), 1);
436 3efd8e31 2022-10-23 thomas static const struct got_error *
437 3efd8e31 2022-10-23 thomas open_tree(struct got_tree_object **tree,
438 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, int check_cache)
440 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
441 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
443 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
444 3efd8e31 2022-10-23 thomas struct got_parsed_tree_entry *entries = NULL;
445 3efd8e31 2022-10-23 thomas size_t nentries = 0, nentries_alloc = 0, i;
446 3efd8e31 2022-10-23 thomas uint8_t *buf = NULL;
448 3efd8e31 2022-10-23 thomas if (check_cache) {
449 3efd8e31 2022-10-23 thomas *tree = got_repo_get_cached_tree(repo, id);
450 3efd8e31 2022-10-23 thomas if (*tree != NULL) {
451 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
452 3efd8e31 2022-10-23 thomas return NULL;
455 3efd8e31 2022-10-23 thomas *tree = NULL;
457 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
458 3efd8e31 2022-10-23 thomas if (err == NULL) {
459 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
460 3efd8e31 2022-10-23 thomas struct got_object *obj;
461 3efd8e31 2022-10-23 thomas size_t len;
463 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
464 3efd8e31 2022-10-23 thomas packidx->path_packidx);
466 3efd8e31 2022-10-23 thomas return err;
468 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
469 3efd8e31 2022-10-23 thomas if (pack == NULL) {
470 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
471 3efd8e31 2022-10-23 thomas packidx);
473 3efd8e31 2022-10-23 thomas goto done;
475 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
477 3efd8e31 2022-10-23 thomas goto done;
478 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
479 3efd8e31 2022-10-23 thomas obj, pack);
480 3efd8e31 2022-10-23 thomas got_object_close(obj);
482 3efd8e31 2022-10-23 thomas goto done;
483 3efd8e31 2022-10-23 thomas err = got_object_parse_tree(&entries, &nentries,
484 3efd8e31 2022-10-23 thomas &nentries_alloc, buf, len);
486 3efd8e31 2022-10-23 thomas goto done;
487 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
490 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
492 3efd8e31 2022-10-23 thomas return err;
493 3efd8e31 2022-10-23 thomas err = got_object_read_tree(&entries, &nentries,
494 3efd8e31 2022-10-23 thomas &nentries_alloc, &buf, fd, id);
495 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
496 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
498 3efd8e31 2022-10-23 thomas goto done;
500 3efd8e31 2022-10-23 thomas goto done;
502 3efd8e31 2022-10-23 thomas *tree = malloc(sizeof(**tree));
503 3efd8e31 2022-10-23 thomas if (*tree == NULL) {
504 3efd8e31 2022-10-23 thomas err = got_error_from_errno("malloc");
505 3efd8e31 2022-10-23 thomas goto done;
507 3efd8e31 2022-10-23 thomas (*tree)->entries = calloc(nentries, sizeof(struct got_tree_entry));
508 3efd8e31 2022-10-23 thomas if ((*tree)->entries == NULL) {
509 3efd8e31 2022-10-23 thomas err = got_error_from_errno("malloc");
510 3efd8e31 2022-10-23 thomas goto done;
512 3efd8e31 2022-10-23 thomas (*tree)->nentries = nentries;
513 3efd8e31 2022-10-23 thomas (*tree)->refcnt = 0;
515 3efd8e31 2022-10-23 thomas for (i = 0; i < nentries; i++) {
516 3efd8e31 2022-10-23 thomas struct got_parsed_tree_entry *pe = &entries[i];
517 3efd8e31 2022-10-23 thomas struct got_tree_entry *te = &(*tree)->entries[i];
519 3efd8e31 2022-10-23 thomas if (strlcpy(te->name, pe->name,
520 3efd8e31 2022-10-23 thomas sizeof(te->name)) >= sizeof(te->name)) {
521 3efd8e31 2022-10-23 thomas err = got_error(GOT_ERR_NO_SPACE);
522 3efd8e31 2022-10-23 thomas goto done;
524 3efd8e31 2022-10-23 thomas memcpy(te->id.sha1, pe->id, SHA1_DIGEST_LENGTH);
525 3efd8e31 2022-10-23 thomas te->mode = pe->mode;
526 3efd8e31 2022-10-23 thomas te->idx = i;
529 3efd8e31 2022-10-23 thomas free(path_packfile);
530 3efd8e31 2022-10-23 thomas free(entries);
531 3efd8e31 2022-10-23 thomas free(buf);
532 3efd8e31 2022-10-23 thomas if (err == NULL) {
533 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
534 3efd8e31 2022-10-23 thomas err = got_repo_cache_tree(repo, id, *tree);
535 3efd8e31 2022-10-23 thomas if (err) {
536 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
537 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
538 3efd8e31 2022-10-23 thomas err = NULL;
541 3efd8e31 2022-10-23 thomas if (err) {
542 3efd8e31 2022-10-23 thomas if (*tree)
543 3efd8e31 2022-10-23 thomas free((*tree)->entries);
544 3efd8e31 2022-10-23 thomas free(*tree);
545 3efd8e31 2022-10-23 thomas *tree = NULL;
547 3efd8e31 2022-10-23 thomas return err;
550 3efd8e31 2022-10-23 thomas const struct got_error *
551 3efd8e31 2022-10-23 thomas got_object_open_as_tree(struct got_tree_object **tree,
552 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
554 3efd8e31 2022-10-23 thomas *tree = got_repo_get_cached_tree(repo, id);
555 3efd8e31 2022-10-23 thomas if (*tree != NULL) {
556 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
557 3efd8e31 2022-10-23 thomas return NULL;
560 3efd8e31 2022-10-23 thomas return open_tree(tree, repo, id, 0);
563 3efd8e31 2022-10-23 thomas const struct got_error *
564 3efd8e31 2022-10-23 thomas got_object_tree_open(struct got_tree_object **tree,
565 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
567 3efd8e31 2022-10-23 thomas return open_tree(tree, repo, got_object_get_id(obj), 1);
570 3efd8e31 2022-10-23 thomas const struct got_error *
571 3efd8e31 2022-10-23 thomas got_object_open_as_blob(struct got_blob_object **blob,
572 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, size_t blocksize,
573 3efd8e31 2022-10-23 thomas int outfd)
575 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
578 3efd8e31 2022-10-23 thomas const struct got_error *
579 3efd8e31 2022-10-23 thomas got_object_blob_open(struct got_blob_object **blob,
580 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj, size_t blocksize,
581 3efd8e31 2022-10-23 thomas int outfd)
583 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
586 3efd8e31 2022-10-23 thomas static const struct got_error *
587 3efd8e31 2022-10-23 thomas open_tag(struct got_tag_object **tag, struct got_repository *repo,
588 3efd8e31 2022-10-23 thomas struct got_object_id *id, int check_cache)
590 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
591 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
593 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
594 3efd8e31 2022-10-23 thomas struct got_object *obj = NULL;
595 3efd8e31 2022-10-23 thomas int obj_type = GOT_OBJ_TYPE_ANY;
597 3efd8e31 2022-10-23 thomas if (check_cache) {
598 3efd8e31 2022-10-23 thomas *tag = got_repo_get_cached_tag(repo, id);
599 3efd8e31 2022-10-23 thomas if (*tag != NULL) {
600 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
601 3efd8e31 2022-10-23 thomas return NULL;
604 3efd8e31 2022-10-23 thomas *tag = NULL;
606 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
607 3efd8e31 2022-10-23 thomas if (err == NULL) {
608 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
609 3efd8e31 2022-10-23 thomas uint8_t *buf = NULL;
610 3efd8e31 2022-10-23 thomas size_t len;
612 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
613 3efd8e31 2022-10-23 thomas packidx->path_packidx);
615 3efd8e31 2022-10-23 thomas return err;
617 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
618 3efd8e31 2022-10-23 thomas if (pack == NULL) {
619 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
620 3efd8e31 2022-10-23 thomas packidx);
622 3efd8e31 2022-10-23 thomas goto done;
625 3efd8e31 2022-10-23 thomas /* Beware of "lightweight" tags: Check object type first. */
626 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
628 3efd8e31 2022-10-23 thomas goto done;
629 3efd8e31 2022-10-23 thomas obj_type = obj->type;
630 3efd8e31 2022-10-23 thomas if (obj_type != GOT_OBJ_TYPE_TAG) {
631 3efd8e31 2022-10-23 thomas err = got_error(GOT_ERR_OBJ_TYPE);
632 3efd8e31 2022-10-23 thomas got_object_close(obj);
633 3efd8e31 2022-10-23 thomas goto done;
635 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
636 3efd8e31 2022-10-23 thomas obj, pack);
637 3efd8e31 2022-10-23 thomas got_object_close(obj);
639 3efd8e31 2022-10-23 thomas goto done;
640 3efd8e31 2022-10-23 thomas err = got_object_parse_tag(tag, buf, len);
641 3efd8e31 2022-10-23 thomas free(buf);
642 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
645 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
647 3efd8e31 2022-10-23 thomas return err;
648 3efd8e31 2022-10-23 thomas err = got_object_read_header(&obj, fd);
649 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
650 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
652 3efd8e31 2022-10-23 thomas return err;
653 3efd8e31 2022-10-23 thomas obj_type = obj->type;
654 3efd8e31 2022-10-23 thomas got_object_close(obj);
655 3efd8e31 2022-10-23 thomas if (obj_type != GOT_OBJ_TYPE_TAG)
656 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_OBJ_TYPE);
658 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
660 3efd8e31 2022-10-23 thomas return err;
661 3efd8e31 2022-10-23 thomas err = got_object_read_tag(tag, fd, id, 0);
662 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
663 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
665 3efd8e31 2022-10-23 thomas return err;
668 3efd8e31 2022-10-23 thomas if (err == NULL) {
669 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
670 3efd8e31 2022-10-23 thomas err = got_repo_cache_tag(repo, id, *tag);
671 3efd8e31 2022-10-23 thomas if (err) {
672 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
673 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
674 3efd8e31 2022-10-23 thomas err = NULL;
678 3efd8e31 2022-10-23 thomas free(path_packfile);
679 3efd8e31 2022-10-23 thomas return err;
682 3efd8e31 2022-10-23 thomas const struct got_error *
683 3efd8e31 2022-10-23 thomas got_object_open_as_tag(struct got_tag_object **tag,
684 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
686 3efd8e31 2022-10-23 thomas *tag = got_repo_get_cached_tag(repo, id);
687 3efd8e31 2022-10-23 thomas if (*tag != NULL) {
688 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
689 3efd8e31 2022-10-23 thomas return NULL;
692 3efd8e31 2022-10-23 thomas return open_tag(tag, repo, id, 0);
695 3efd8e31 2022-10-23 thomas const struct got_error *
696 3efd8e31 2022-10-23 thomas got_object_tag_open(struct got_tag_object **tag,
697 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
699 3efd8e31 2022-10-23 thomas return open_tag(tag, repo, got_object_get_id(obj), 1);