2 13b2bc37 2022-10-23 stsp * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
4 13b2bc37 2022-10-23 stsp * Permission to use, copy, modify, and distribute this software for any
5 13b2bc37 2022-10-23 stsp * purpose with or without fee is hereby granted, provided that the above
6 13b2bc37 2022-10-23 stsp * copyright notice and this permission notice appear in all copies.
8 13b2bc37 2022-10-23 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 13b2bc37 2022-10-23 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 13b2bc37 2022-10-23 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 13b2bc37 2022-10-23 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 13b2bc37 2022-10-23 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 13b2bc37 2022-10-23 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 13b2bc37 2022-10-23 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 13b2bc37 2022-10-23 stsp #include <sys/queue.h>
18 13b2bc37 2022-10-23 stsp #include <sys/tree.h>
19 13b2bc37 2022-10-23 stsp #include <sys/stat.h>
21 13b2bc37 2022-10-23 stsp #include <errno.h>
22 13b2bc37 2022-10-23 stsp #include <limits.h>
23 13b2bc37 2022-10-23 stsp #include <sha1.h>
24 5822e79e 2023-02-23 op #include <sha2.h>
25 13b2bc37 2022-10-23 stsp #include <stdio.h>
26 13b2bc37 2022-10-23 stsp #include <stdlib.h>
27 13b2bc37 2022-10-23 stsp #include <string.h>
28 13b2bc37 2022-10-23 stsp #include <unistd.h>
30 13b2bc37 2022-10-23 stsp #include "got_error.h"
31 13b2bc37 2022-10-23 stsp #include "got_object.h"
32 13b2bc37 2022-10-23 stsp #include "got_repository.h"
33 13b2bc37 2022-10-23 stsp #include "got_path.h"
35 13b2bc37 2022-10-23 stsp #include "got_lib_delta.h"
36 13b2bc37 2022-10-23 stsp #include "got_lib_object.h"
37 13b2bc37 2022-10-23 stsp #include "got_lib_object_cache.h"
38 13b2bc37 2022-10-23 stsp #include "got_lib_object_parse.h"
39 13b2bc37 2022-10-23 stsp #include "got_lib_pack.h"
40 13b2bc37 2022-10-23 stsp #include "got_lib_repository.h"
42 13b2bc37 2022-10-23 stsp const struct got_error *
43 13b2bc37 2022-10-23 stsp got_object_open_packed(struct got_object **obj, struct got_object_id *id,
44 13b2bc37 2022-10-23 stsp struct got_repository *repo)
46 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
47 13b2bc37 2022-10-23 stsp struct got_pack *pack = NULL;
48 13b2bc37 2022-10-23 stsp struct got_packidx *packidx = NULL;
50 13b2bc37 2022-10-23 stsp char *path_packfile;
52 13b2bc37 2022-10-23 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
56 13b2bc37 2022-10-23 stsp err = got_packidx_get_packfile_path(&path_packfile,
57 13b2bc37 2022-10-23 stsp packidx->path_packidx);
61 13b2bc37 2022-10-23 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
62 13b2bc37 2022-10-23 stsp if (pack == NULL) {
63 13b2bc37 2022-10-23 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
68 13b2bc37 2022-10-23 stsp err = got_packfile_open_object(obj, pack, packidx, idx, id);
71 13b2bc37 2022-10-23 stsp (*obj)->refcnt++;
73 13b2bc37 2022-10-23 stsp err = got_repo_cache_object(repo, id, *obj);
75 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_OBJ_EXISTS ||
76 13b2bc37 2022-10-23 stsp err->code == GOT_ERR_OBJ_TOO_LARGE)
80 13b2bc37 2022-10-23 stsp free(path_packfile);
84 13b2bc37 2022-10-23 stsp const struct got_error *
85 13b2bc37 2022-10-23 stsp got_object_open_from_packfile(struct got_object **obj, struct got_object_id *id,
86 13b2bc37 2022-10-23 stsp struct got_pack *pack, struct got_packidx *packidx, int obj_idx,
87 13b2bc37 2022-10-23 stsp struct got_repository *repo)
89 13b2bc37 2022-10-23 stsp return got_error(GOT_ERR_NOT_IMPL);
92 13b2bc37 2022-10-23 stsp const struct got_error *
93 13b2bc37 2022-10-23 stsp got_object_read_raw_delta(uint64_t *base_size, uint64_t *result_size,
94 13b2bc37 2022-10-23 stsp off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
95 13b2bc37 2022-10-23 stsp off_t *delta_out_offset, struct got_object_id **base_id, int delta_cache_fd,
96 13b2bc37 2022-10-23 stsp struct got_packidx *packidx, int obj_idx, struct got_object_id *id,
97 13b2bc37 2022-10-23 stsp struct got_repository *repo)
99 13b2bc37 2022-10-23 stsp return got_error(GOT_ERR_NOT_IMPL);
102 13b2bc37 2022-10-23 stsp const struct got_error *
103 13b2bc37 2022-10-23 stsp got_object_open(struct got_object **obj, struct got_repository *repo,
104 13b2bc37 2022-10-23 stsp struct got_object_id *id)
106 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
109 13b2bc37 2022-10-23 stsp *obj = got_repo_get_cached_object(repo, id);
110 13b2bc37 2022-10-23 stsp if (*obj != NULL) {
111 13b2bc37 2022-10-23 stsp (*obj)->refcnt++;
112 13b2bc37 2022-10-23 stsp return NULL;
115 13b2bc37 2022-10-23 stsp err = got_object_open_packed(obj, id, repo);
117 13b2bc37 2022-10-23 stsp if (err->code != GOT_ERR_NO_OBJ)
118 13b2bc37 2022-10-23 stsp return err;
120 13b2bc37 2022-10-23 stsp return NULL;
122 13b2bc37 2022-10-23 stsp err = got_object_open_loose_fd(&fd, id, repo);
124 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_ERRNO && errno == ENOENT)
125 13b2bc37 2022-10-23 stsp err = got_error_no_obj(id);
126 13b2bc37 2022-10-23 stsp return err;
129 13b2bc37 2022-10-23 stsp err = got_object_read_header(obj, fd);
133 13b2bc37 2022-10-23 stsp memcpy(&(*obj)->id, id, sizeof((*obj)->id));
134 13b2bc37 2022-10-23 stsp (*obj)->refcnt++;
136 13b2bc37 2022-10-23 stsp err = got_repo_cache_object(repo, id, *obj);
138 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_OBJ_EXISTS ||
139 13b2bc37 2022-10-23 stsp err->code == GOT_ERR_OBJ_TOO_LARGE)
140 13b2bc37 2022-10-23 stsp err = NULL;
143 13b2bc37 2022-10-23 stsp if (close(fd) == -1 && err == NULL)
144 13b2bc37 2022-10-23 stsp err = got_error_from_errno("close");
145 13b2bc37 2022-10-23 stsp return err;
148 13b2bc37 2022-10-23 stsp static const struct got_error *
149 13b2bc37 2022-10-23 stsp wrap_fd(FILE **f, int wrapped_fd)
151 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
154 13b2bc37 2022-10-23 stsp if (ftruncate(wrapped_fd, 0L) == -1)
155 13b2bc37 2022-10-23 stsp return got_error_from_errno("ftruncate");
157 13b2bc37 2022-10-23 stsp if (lseek(wrapped_fd, 0L, SEEK_SET) == -1)
158 13b2bc37 2022-10-23 stsp return got_error_from_errno("lseek");
160 13b2bc37 2022-10-23 stsp fd = dup(wrapped_fd);
161 13b2bc37 2022-10-23 stsp if (fd == -1)
162 13b2bc37 2022-10-23 stsp return got_error_from_errno("dup");
164 13b2bc37 2022-10-23 stsp *f = fdopen(fd, "w+");
165 13b2bc37 2022-10-23 stsp if (*f == NULL) {
166 13b2bc37 2022-10-23 stsp err = got_error_from_errno("fdopen");
169 13b2bc37 2022-10-23 stsp return err;
172 13b2bc37 2022-10-23 stsp static const struct got_error *
173 13b2bc37 2022-10-23 stsp read_packed_object_raw(uint8_t **outbuf, off_t *size, size_t *hdrlen,
174 13b2bc37 2022-10-23 stsp int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
175 13b2bc37 2022-10-23 stsp struct got_object_id *id)
177 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
178 13b2bc37 2022-10-23 stsp uint64_t raw_size = 0;
179 13b2bc37 2022-10-23 stsp struct got_object *obj;
180 13b2bc37 2022-10-23 stsp FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
182 13b2bc37 2022-10-23 stsp *outbuf = NULL;
184 13b2bc37 2022-10-23 stsp *hdrlen = 0;
186 13b2bc37 2022-10-23 stsp err = got_packfile_open_object(&obj, pack, packidx, idx, id);
188 13b2bc37 2022-10-23 stsp return err;
190 13b2bc37 2022-10-23 stsp if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
191 13b2bc37 2022-10-23 stsp err = got_pack_get_max_delta_object_size(&raw_size, obj, pack);
195 13b2bc37 2022-10-23 stsp raw_size = obj->size;
197 13b2bc37 2022-10-23 stsp if (raw_size <= GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
198 13b2bc37 2022-10-23 stsp size_t len;
199 13b2bc37 2022-10-23 stsp err = got_packfile_extract_object_to_mem(outbuf, &len,
200 13b2bc37 2022-10-23 stsp obj, pack);
203 13b2bc37 2022-10-23 stsp *size = (off_t)len;
206 13b2bc37 2022-10-23 stsp * XXX This uses 3 file extra descriptors for no good reason.
207 13b2bc37 2022-10-23 stsp * We should have got_packfile_extract_object_to_fd().
209 13b2bc37 2022-10-23 stsp err = wrap_fd(&outfile, outfd);
212 13b2bc37 2022-10-23 stsp err = wrap_fd(&basefile, pack->basefd);
215 13b2bc37 2022-10-23 stsp err = wrap_fd(&accumfile, pack->accumfd);
218 13b2bc37 2022-10-23 stsp err = got_packfile_extract_object(pack, obj, outfile, basefile,
219 13b2bc37 2022-10-23 stsp accumfile);
222 95bdb85d 2023-01-09 stsp *size = obj->size;
225 13b2bc37 2022-10-23 stsp *hdrlen = obj->hdrlen;
227 13b2bc37 2022-10-23 stsp got_object_close(obj);
228 13b2bc37 2022-10-23 stsp if (outfile && fclose(outfile) == EOF && err == NULL)
229 13b2bc37 2022-10-23 stsp err = got_error_from_errno("fclose");
230 13b2bc37 2022-10-23 stsp if (basefile && fclose(basefile) == EOF && err == NULL)
231 13b2bc37 2022-10-23 stsp err = got_error_from_errno("fclose");
232 13b2bc37 2022-10-23 stsp if (accumfile && fclose(accumfile) == EOF && err == NULL)
233 13b2bc37 2022-10-23 stsp err = got_error_from_errno("fclose");
234 13b2bc37 2022-10-23 stsp return err;
238 13b2bc37 2022-10-23 stsp static void
239 13b2bc37 2022-10-23 stsp put_raw_object_tempfile(struct got_raw_object *obj)
241 13b2bc37 2022-10-23 stsp struct got_repository *repo = obj->close_arg;
243 13b2bc37 2022-10-23 stsp if (obj->tempfile_idx != -1)
244 13b2bc37 2022-10-23 stsp got_repo_temp_fds_put(obj->tempfile_idx, repo);
247 13b2bc37 2022-10-23 stsp /* *outfd must be initialized to -1 by caller */
248 13b2bc37 2022-10-23 stsp const struct got_error *
249 13b2bc37 2022-10-23 stsp got_object_raw_open(struct got_raw_object **obj, int *outfd,
250 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id)
252 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
253 13b2bc37 2022-10-23 stsp struct got_packidx *packidx = NULL;
254 3a975a9f 2023-01-09 stsp int idx, tempfd, tempfile_idx;
255 13b2bc37 2022-10-23 stsp uint8_t *outbuf = NULL;
256 13b2bc37 2022-10-23 stsp off_t size = 0;
257 13b2bc37 2022-10-23 stsp size_t hdrlen = 0;
258 13b2bc37 2022-10-23 stsp char *path_packfile = NULL;
260 13b2bc37 2022-10-23 stsp *obj = got_repo_get_cached_raw_object(repo, id);
261 13b2bc37 2022-10-23 stsp if (*obj != NULL) {
262 13b2bc37 2022-10-23 stsp (*obj)->refcnt++;
263 13b2bc37 2022-10-23 stsp return NULL;
266 3a975a9f 2023-01-09 stsp err = got_repo_temp_fds_get(&tempfd, &tempfile_idx, repo);
268 3a975a9f 2023-01-09 stsp return err;
270 13b2bc37 2022-10-23 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
271 13b2bc37 2022-10-23 stsp if (err == NULL) {
272 13b2bc37 2022-10-23 stsp struct got_pack *pack = NULL;
274 13b2bc37 2022-10-23 stsp err = got_packidx_get_packfile_path(&path_packfile,
275 13b2bc37 2022-10-23 stsp packidx->path_packidx);
279 13b2bc37 2022-10-23 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
280 13b2bc37 2022-10-23 stsp if (pack == NULL) {
281 13b2bc37 2022-10-23 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
286 13b2bc37 2022-10-23 stsp err = read_packed_object_raw(&outbuf, &size, &hdrlen,
287 3a975a9f 2023-01-09 stsp tempfd, pack, packidx, idx, id);
290 13b2bc37 2022-10-23 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
293 13b2bc37 2022-10-23 stsp err = got_object_open_loose_fd(&fd, id, repo);
296 13b2bc37 2022-10-23 stsp err = got_object_read_raw(&outbuf, &size, &hdrlen,
297 3a975a9f 2023-01-09 stsp GOT_DELTA_RESULT_SIZE_CACHED_MAX, tempfd, id, fd);
298 13b2bc37 2022-10-23 stsp if (close(fd) == -1 && err == NULL)
299 13b2bc37 2022-10-23 stsp err = got_error_from_errno("close");
304 3a975a9f 2023-01-09 stsp if (outbuf == NULL) {
305 3a975a9f 2023-01-09 stsp if (*outfd != -1) {
306 3a975a9f 2023-01-09 stsp err = got_error_msg(GOT_ERR_NOT_IMPL, "bad outfd");
311 3a975a9f 2023-01-09 stsp * Duplicate tempfile descriptor to allow use of
312 3a975a9f 2023-01-09 stsp * fdopen(3) inside got_object_raw_alloc().
314 3a975a9f 2023-01-09 stsp *outfd = dup(tempfd);
315 3a975a9f 2023-01-09 stsp if (*outfd == -1) {
316 3a975a9f 2023-01-09 stsp err = got_error_from_errno("dup");
321 60c140ae 2023-01-09 stsp err = got_object_raw_alloc(obj, outbuf, outfd,
322 60c140ae 2023-01-09 stsp GOT_DELTA_RESULT_SIZE_CACHED_MAX, hdrlen, size);
326 13b2bc37 2022-10-23 stsp err = got_repo_cache_raw_object(repo, id, *obj);
328 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_OBJ_EXISTS ||
329 13b2bc37 2022-10-23 stsp err->code == GOT_ERR_OBJ_TOO_LARGE)
330 13b2bc37 2022-10-23 stsp err = NULL;
333 13b2bc37 2022-10-23 stsp free(path_packfile);
335 13b2bc37 2022-10-23 stsp if (*obj) {
336 13b2bc37 2022-10-23 stsp got_object_raw_close(*obj);
337 13b2bc37 2022-10-23 stsp *obj = NULL;
339 13b2bc37 2022-10-23 stsp free(outbuf);
340 3a975a9f 2023-01-09 stsp got_repo_temp_fds_put(tempfile_idx, repo);
341 3a975a9f 2023-01-09 stsp if (*outfd != -1) {
342 3a975a9f 2023-01-09 stsp close(*outfd);
343 3a975a9f 2023-01-09 stsp *outfd = -1;
346 3a975a9f 2023-01-09 stsp if (((*obj)->f == NULL && (*obj)->fd == -1)) {
347 3a975a9f 2023-01-09 stsp /* This raw object is not backed by a file. */
348 3a975a9f 2023-01-09 stsp got_repo_temp_fds_put(tempfile_idx, repo);
349 3a975a9f 2023-01-09 stsp if (*outfd != -1) {
350 3a975a9f 2023-01-09 stsp close(*outfd);
351 3a975a9f 2023-01-09 stsp *outfd = -1;
354 3a975a9f 2023-01-09 stsp (*obj)->tempfile_idx = tempfile_idx;
355 3a975a9f 2023-01-09 stsp (*obj)->close_cb = put_raw_object_tempfile;
356 3a975a9f 2023-01-09 stsp (*obj)->close_arg = repo;
359 13b2bc37 2022-10-23 stsp return err;
362 13b2bc37 2022-10-23 stsp static const struct got_error *
363 13b2bc37 2022-10-23 stsp open_commit(struct got_commit_object **commit,
364 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id, int check_cache)
366 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
367 13b2bc37 2022-10-23 stsp struct got_packidx *packidx = NULL;
369 13b2bc37 2022-10-23 stsp char *path_packfile = NULL;
371 13b2bc37 2022-10-23 stsp if (check_cache) {
372 13b2bc37 2022-10-23 stsp *commit = got_repo_get_cached_commit(repo, id);
373 13b2bc37 2022-10-23 stsp if (*commit != NULL) {
374 13b2bc37 2022-10-23 stsp (*commit)->refcnt++;
375 13b2bc37 2022-10-23 stsp return NULL;
378 13b2bc37 2022-10-23 stsp *commit = NULL;
380 13b2bc37 2022-10-23 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
381 13b2bc37 2022-10-23 stsp if (err == NULL) {
382 13b2bc37 2022-10-23 stsp struct got_pack *pack = NULL;
383 13b2bc37 2022-10-23 stsp struct got_object *obj;
384 13b2bc37 2022-10-23 stsp uint8_t *buf;
385 13b2bc37 2022-10-23 stsp size_t len;
387 13b2bc37 2022-10-23 stsp err = got_packidx_get_packfile_path(&path_packfile,
388 13b2bc37 2022-10-23 stsp packidx->path_packidx);
390 13b2bc37 2022-10-23 stsp return err;
392 13b2bc37 2022-10-23 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
393 13b2bc37 2022-10-23 stsp if (pack == NULL) {
394 13b2bc37 2022-10-23 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
399 13b2bc37 2022-10-23 stsp err = got_packfile_open_object(&obj, pack, packidx, idx, id);
402 13b2bc37 2022-10-23 stsp err = got_packfile_extract_object_to_mem(&buf, &len,
403 13b2bc37 2022-10-23 stsp obj, pack);
404 13b2bc37 2022-10-23 stsp got_object_close(obj);
407 13b2bc37 2022-10-23 stsp err = got_object_parse_commit(commit, buf, len);
409 13b2bc37 2022-10-23 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
412 13b2bc37 2022-10-23 stsp err = got_object_open_loose_fd(&fd, id, repo);
414 13b2bc37 2022-10-23 stsp return err;
415 13b2bc37 2022-10-23 stsp err = got_object_read_commit(commit, fd, id, 0);
416 13b2bc37 2022-10-23 stsp if (close(fd) == -1 && err == NULL)
417 13b2bc37 2022-10-23 stsp err = got_error_from_errno("close");
419 13b2bc37 2022-10-23 stsp return err;
422 13b2bc37 2022-10-23 stsp if (err == NULL) {
423 13b2bc37 2022-10-23 stsp (*commit)->refcnt++;
424 13b2bc37 2022-10-23 stsp err = got_repo_cache_commit(repo, id, *commit);
426 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_OBJ_EXISTS ||
427 13b2bc37 2022-10-23 stsp err->code == GOT_ERR_OBJ_TOO_LARGE)
428 13b2bc37 2022-10-23 stsp err = NULL;
432 13b2bc37 2022-10-23 stsp free(path_packfile);
433 13b2bc37 2022-10-23 stsp return err;
436 13b2bc37 2022-10-23 stsp const struct got_error *
437 13b2bc37 2022-10-23 stsp got_object_open_as_commit(struct got_commit_object **commit,
438 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id)
440 13b2bc37 2022-10-23 stsp *commit = got_repo_get_cached_commit(repo, id);
441 13b2bc37 2022-10-23 stsp if (*commit != NULL) {
442 13b2bc37 2022-10-23 stsp (*commit)->refcnt++;
443 13b2bc37 2022-10-23 stsp return NULL;
446 13b2bc37 2022-10-23 stsp return open_commit(commit, repo, id, 0);
449 13b2bc37 2022-10-23 stsp const struct got_error *
450 13b2bc37 2022-10-23 stsp got_object_commit_open(struct got_commit_object **commit,
451 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object *obj)
453 13b2bc37 2022-10-23 stsp return open_commit(commit, repo, got_object_get_id(obj), 1);
456 13b2bc37 2022-10-23 stsp static const struct got_error *
457 13b2bc37 2022-10-23 stsp open_tree(struct got_tree_object **tree,
458 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id, int check_cache)
460 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
461 13b2bc37 2022-10-23 stsp struct got_packidx *packidx = NULL;
463 13b2bc37 2022-10-23 stsp char *path_packfile = NULL;
464 13b2bc37 2022-10-23 stsp struct got_parsed_tree_entry *entries = NULL;
465 13b2bc37 2022-10-23 stsp size_t nentries = 0, nentries_alloc = 0, i;
466 13b2bc37 2022-10-23 stsp uint8_t *buf = NULL;
468 13b2bc37 2022-10-23 stsp if (check_cache) {
469 13b2bc37 2022-10-23 stsp *tree = got_repo_get_cached_tree(repo, id);
470 13b2bc37 2022-10-23 stsp if (*tree != NULL) {
471 13b2bc37 2022-10-23 stsp (*tree)->refcnt++;
472 13b2bc37 2022-10-23 stsp return NULL;
475 13b2bc37 2022-10-23 stsp *tree = NULL;
477 13b2bc37 2022-10-23 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
478 13b2bc37 2022-10-23 stsp if (err == NULL) {
479 13b2bc37 2022-10-23 stsp struct got_pack *pack = NULL;
480 13b2bc37 2022-10-23 stsp struct got_object *obj;
481 13b2bc37 2022-10-23 stsp size_t len;
483 13b2bc37 2022-10-23 stsp err = got_packidx_get_packfile_path(&path_packfile,
484 13b2bc37 2022-10-23 stsp packidx->path_packidx);
486 13b2bc37 2022-10-23 stsp return err;
488 13b2bc37 2022-10-23 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
489 13b2bc37 2022-10-23 stsp if (pack == NULL) {
490 13b2bc37 2022-10-23 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
495 13b2bc37 2022-10-23 stsp err = got_packfile_open_object(&obj, pack, packidx, idx, id);
498 13b2bc37 2022-10-23 stsp err = got_packfile_extract_object_to_mem(&buf, &len,
499 13b2bc37 2022-10-23 stsp obj, pack);
500 13b2bc37 2022-10-23 stsp got_object_close(obj);
503 13b2bc37 2022-10-23 stsp err = got_object_parse_tree(&entries, &nentries,
504 13b2bc37 2022-10-23 stsp &nentries_alloc, buf, len);
507 13b2bc37 2022-10-23 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
510 13b2bc37 2022-10-23 stsp err = got_object_open_loose_fd(&fd, id, repo);
512 13b2bc37 2022-10-23 stsp return err;
513 13b2bc37 2022-10-23 stsp err = got_object_read_tree(&entries, &nentries,
514 13b2bc37 2022-10-23 stsp &nentries_alloc, &buf, fd, id);
515 13b2bc37 2022-10-23 stsp if (close(fd) == -1 && err == NULL)
516 13b2bc37 2022-10-23 stsp err = got_error_from_errno("close");
522 13b2bc37 2022-10-23 stsp *tree = malloc(sizeof(**tree));
523 13b2bc37 2022-10-23 stsp if (*tree == NULL) {
524 13b2bc37 2022-10-23 stsp err = got_error_from_errno("malloc");
527 13b2bc37 2022-10-23 stsp (*tree)->entries = calloc(nentries, sizeof(struct got_tree_entry));
528 13b2bc37 2022-10-23 stsp if ((*tree)->entries == NULL) {
529 13b2bc37 2022-10-23 stsp err = got_error_from_errno("malloc");
532 13b2bc37 2022-10-23 stsp (*tree)->nentries = nentries;
533 13b2bc37 2022-10-23 stsp (*tree)->refcnt = 0;
535 13b2bc37 2022-10-23 stsp for (i = 0; i < nentries; i++) {
536 13b2bc37 2022-10-23 stsp struct got_parsed_tree_entry *pe = &entries[i];
537 13b2bc37 2022-10-23 stsp struct got_tree_entry *te = &(*tree)->entries[i];
539 13b2bc37 2022-10-23 stsp if (strlcpy(te->name, pe->name,
540 13b2bc37 2022-10-23 stsp sizeof(te->name)) >= sizeof(te->name)) {
541 13b2bc37 2022-10-23 stsp err = got_error(GOT_ERR_NO_SPACE);
544 13b2bc37 2022-10-23 stsp memcpy(te->id.sha1, pe->id, SHA1_DIGEST_LENGTH);
545 13b2bc37 2022-10-23 stsp te->mode = pe->mode;
546 13b2bc37 2022-10-23 stsp te->idx = i;
549 13b2bc37 2022-10-23 stsp free(path_packfile);
550 13b2bc37 2022-10-23 stsp free(entries);
552 13b2bc37 2022-10-23 stsp if (err == NULL) {
553 13b2bc37 2022-10-23 stsp (*tree)->refcnt++;
554 13b2bc37 2022-10-23 stsp err = got_repo_cache_tree(repo, id, *tree);
556 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_OBJ_EXISTS ||
557 13b2bc37 2022-10-23 stsp err->code == GOT_ERR_OBJ_TOO_LARGE)
558 13b2bc37 2022-10-23 stsp err = NULL;
563 13b2bc37 2022-10-23 stsp free((*tree)->entries);
564 13b2bc37 2022-10-23 stsp free(*tree);
565 13b2bc37 2022-10-23 stsp *tree = NULL;
567 13b2bc37 2022-10-23 stsp return err;
570 13b2bc37 2022-10-23 stsp const struct got_error *
571 13b2bc37 2022-10-23 stsp got_object_open_as_tree(struct got_tree_object **tree,
572 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id)
574 13b2bc37 2022-10-23 stsp *tree = got_repo_get_cached_tree(repo, id);
575 13b2bc37 2022-10-23 stsp if (*tree != NULL) {
576 13b2bc37 2022-10-23 stsp (*tree)->refcnt++;
577 13b2bc37 2022-10-23 stsp return NULL;
580 13b2bc37 2022-10-23 stsp return open_tree(tree, repo, id, 0);
583 13b2bc37 2022-10-23 stsp const struct got_error *
584 13b2bc37 2022-10-23 stsp got_object_tree_open(struct got_tree_object **tree,
585 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object *obj)
587 13b2bc37 2022-10-23 stsp return open_tree(tree, repo, got_object_get_id(obj), 1);
590 13b2bc37 2022-10-23 stsp const struct got_error *
591 13b2bc37 2022-10-23 stsp got_object_open_as_blob(struct got_blob_object **blob,
592 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id, size_t blocksize,
595 13b2bc37 2022-10-23 stsp return got_error(GOT_ERR_NOT_IMPL);
598 13b2bc37 2022-10-23 stsp const struct got_error *
599 13b2bc37 2022-10-23 stsp got_object_blob_open(struct got_blob_object **blob,
600 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object *obj, size_t blocksize,
603 13b2bc37 2022-10-23 stsp return got_error(GOT_ERR_NOT_IMPL);
606 13b2bc37 2022-10-23 stsp static const struct got_error *
607 13b2bc37 2022-10-23 stsp open_tag(struct got_tag_object **tag, struct got_repository *repo,
608 13b2bc37 2022-10-23 stsp struct got_object_id *id, int check_cache)
610 13b2bc37 2022-10-23 stsp const struct got_error *err = NULL;
611 13b2bc37 2022-10-23 stsp struct got_packidx *packidx = NULL;
613 13b2bc37 2022-10-23 stsp char *path_packfile = NULL;
614 13b2bc37 2022-10-23 stsp struct got_object *obj = NULL;
615 13b2bc37 2022-10-23 stsp int obj_type = GOT_OBJ_TYPE_ANY;
617 13b2bc37 2022-10-23 stsp if (check_cache) {
618 13b2bc37 2022-10-23 stsp *tag = got_repo_get_cached_tag(repo, id);
619 13b2bc37 2022-10-23 stsp if (*tag != NULL) {
620 13b2bc37 2022-10-23 stsp (*tag)->refcnt++;
621 13b2bc37 2022-10-23 stsp return NULL;
624 13b2bc37 2022-10-23 stsp *tag = NULL;
626 13b2bc37 2022-10-23 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
627 13b2bc37 2022-10-23 stsp if (err == NULL) {
628 13b2bc37 2022-10-23 stsp struct got_pack *pack = NULL;
629 13b2bc37 2022-10-23 stsp uint8_t *buf = NULL;
630 13b2bc37 2022-10-23 stsp size_t len;
632 13b2bc37 2022-10-23 stsp err = got_packidx_get_packfile_path(&path_packfile,
633 13b2bc37 2022-10-23 stsp packidx->path_packidx);
635 13b2bc37 2022-10-23 stsp return err;
637 13b2bc37 2022-10-23 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
638 13b2bc37 2022-10-23 stsp if (pack == NULL) {
639 13b2bc37 2022-10-23 stsp err = got_repo_cache_pack(&pack, repo, path_packfile,
645 13b2bc37 2022-10-23 stsp /* Beware of "lightweight" tags: Check object type first. */
646 13b2bc37 2022-10-23 stsp err = got_packfile_open_object(&obj, pack, packidx, idx, id);
649 13b2bc37 2022-10-23 stsp obj_type = obj->type;
650 13b2bc37 2022-10-23 stsp if (obj_type != GOT_OBJ_TYPE_TAG) {
651 13b2bc37 2022-10-23 stsp err = got_error(GOT_ERR_OBJ_TYPE);
652 13b2bc37 2022-10-23 stsp got_object_close(obj);
655 13b2bc37 2022-10-23 stsp err = got_packfile_extract_object_to_mem(&buf, &len,
656 13b2bc37 2022-10-23 stsp obj, pack);
657 13b2bc37 2022-10-23 stsp got_object_close(obj);
660 13b2bc37 2022-10-23 stsp err = got_object_parse_tag(tag, buf, len);
662 13b2bc37 2022-10-23 stsp } else if (err->code == GOT_ERR_NO_OBJ) {
665 13b2bc37 2022-10-23 stsp err = got_object_open_loose_fd(&fd, id, repo);
667 13b2bc37 2022-10-23 stsp return err;
668 13b2bc37 2022-10-23 stsp err = got_object_read_header(&obj, fd);
669 13b2bc37 2022-10-23 stsp if (close(fd) == -1 && err == NULL)
670 13b2bc37 2022-10-23 stsp err = got_error_from_errno("close");
672 13b2bc37 2022-10-23 stsp return err;
673 13b2bc37 2022-10-23 stsp obj_type = obj->type;
674 13b2bc37 2022-10-23 stsp got_object_close(obj);
675 13b2bc37 2022-10-23 stsp if (obj_type != GOT_OBJ_TYPE_TAG)
676 13b2bc37 2022-10-23 stsp return got_error(GOT_ERR_OBJ_TYPE);
678 13b2bc37 2022-10-23 stsp err = got_object_open_loose_fd(&fd, id, repo);
680 13b2bc37 2022-10-23 stsp return err;
681 13b2bc37 2022-10-23 stsp err = got_object_read_tag(tag, fd, id, 0);
682 13b2bc37 2022-10-23 stsp if (close(fd) == -1 && err == NULL)
683 13b2bc37 2022-10-23 stsp err = got_error_from_errno("close");
685 13b2bc37 2022-10-23 stsp return err;
688 13b2bc37 2022-10-23 stsp if (err == NULL) {
689 13b2bc37 2022-10-23 stsp (*tag)->refcnt++;
690 13b2bc37 2022-10-23 stsp err = got_repo_cache_tag(repo, id, *tag);
692 13b2bc37 2022-10-23 stsp if (err->code == GOT_ERR_OBJ_EXISTS ||
693 13b2bc37 2022-10-23 stsp err->code == GOT_ERR_OBJ_TOO_LARGE)
694 13b2bc37 2022-10-23 stsp err = NULL;
698 13b2bc37 2022-10-23 stsp free(path_packfile);
699 13b2bc37 2022-10-23 stsp return err;
702 13b2bc37 2022-10-23 stsp const struct got_error *
703 13b2bc37 2022-10-23 stsp got_object_open_as_tag(struct got_tag_object **tag,
704 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object_id *id)
706 13b2bc37 2022-10-23 stsp *tag = got_repo_get_cached_tag(repo, id);
707 13b2bc37 2022-10-23 stsp if (*tag != NULL) {
708 13b2bc37 2022-10-23 stsp (*tag)->refcnt++;
709 13b2bc37 2022-10-23 stsp return NULL;
712 13b2bc37 2022-10-23 stsp return open_tag(tag, repo, id, 0);
715 13b2bc37 2022-10-23 stsp const struct got_error *
716 13b2bc37 2022-10-23 stsp got_object_tag_open(struct got_tag_object **tag,
717 13b2bc37 2022-10-23 stsp struct got_repository *repo, struct got_object *obj)
719 13b2bc37 2022-10-23 stsp return open_tag(tag, repo, got_object_get_id(obj), 1);