Blame


1 3efd8e31 2022-10-23 thomas /*
2 3efd8e31 2022-10-23 thomas * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
3 3efd8e31 2022-10-23 thomas *
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.
7 3efd8e31 2022-10-23 thomas *
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.
15 3efd8e31 2022-10-23 thomas */
16 3efd8e31 2022-10-23 thomas
17 3efd8e31 2022-10-23 thomas #include <sys/queue.h>
18 3efd8e31 2022-10-23 thomas #include <sys/stat.h>
19 3efd8e31 2022-10-23 thomas
20 3efd8e31 2022-10-23 thomas #include <errno.h>
21 3efd8e31 2022-10-23 thomas #include <limits.h>
22 3efd8e31 2022-10-23 thomas #include <stdio.h>
23 3efd8e31 2022-10-23 thomas #include <stdlib.h>
24 3efd8e31 2022-10-23 thomas #include <string.h>
25 3efd8e31 2022-10-23 thomas #include <unistd.h>
26 3efd8e31 2022-10-23 thomas
27 3efd8e31 2022-10-23 thomas #include "got_error.h"
28 3efd8e31 2022-10-23 thomas #include "got_object.h"
29 3efd8e31 2022-10-23 thomas #include "got_repository.h"
30 3efd8e31 2022-10-23 thomas #include "got_path.h"
31 3efd8e31 2022-10-23 thomas
32 3efd8e31 2022-10-23 thomas #include "got_lib_delta.h"
33 3efd8e31 2022-10-23 thomas #include "got_lib_object.h"
34 3efd8e31 2022-10-23 thomas #include "got_lib_object_cache.h"
35 3efd8e31 2022-10-23 thomas #include "got_lib_object_parse.h"
36 3efd8e31 2022-10-23 thomas #include "got_lib_pack.h"
37 3efd8e31 2022-10-23 thomas #include "got_lib_repository.h"
38 3efd8e31 2022-10-23 thomas
39 3efd8e31 2022-10-23 thomas const struct got_error *
40 3efd8e31 2022-10-23 thomas got_object_open_packed(struct got_object **obj, struct got_object_id *id,
41 3efd8e31 2022-10-23 thomas struct got_repository *repo)
42 3efd8e31 2022-10-23 thomas {
43 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
44 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
45 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
46 3efd8e31 2022-10-23 thomas int idx;
47 3efd8e31 2022-10-23 thomas char *path_packfile;
48 3efd8e31 2022-10-23 thomas
49 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
50 3efd8e31 2022-10-23 thomas if (err)
51 3efd8e31 2022-10-23 thomas return err;
52 3efd8e31 2022-10-23 thomas
53 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
54 3efd8e31 2022-10-23 thomas packidx->path_packidx);
55 3efd8e31 2022-10-23 thomas if (err)
56 3efd8e31 2022-10-23 thomas return err;
57 3efd8e31 2022-10-23 thomas
58 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
59 3efd8e31 2022-10-23 thomas if (pack == NULL) {
60 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
61 3efd8e31 2022-10-23 thomas if (err)
62 3efd8e31 2022-10-23 thomas goto done;
63 3efd8e31 2022-10-23 thomas }
64 3efd8e31 2022-10-23 thomas
65 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(obj, pack, packidx, idx, id);
66 3efd8e31 2022-10-23 thomas if (err)
67 3efd8e31 2022-10-23 thomas return err;
68 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
69 3efd8e31 2022-10-23 thomas
70 3efd8e31 2022-10-23 thomas err = got_repo_cache_object(repo, id, *obj);
71 3efd8e31 2022-10-23 thomas if (err) {
72 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
73 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
74 3efd8e31 2022-10-23 thomas err = NULL;
75 3efd8e31 2022-10-23 thomas }
76 3efd8e31 2022-10-23 thomas done:
77 3efd8e31 2022-10-23 thomas free(path_packfile);
78 3efd8e31 2022-10-23 thomas return err;
79 3efd8e31 2022-10-23 thomas }
80 3efd8e31 2022-10-23 thomas
81 3efd8e31 2022-10-23 thomas const struct got_error *
82 3efd8e31 2022-10-23 thomas got_object_open_from_packfile(struct got_object **obj, struct got_object_id *id,
83 3efd8e31 2022-10-23 thomas struct got_pack *pack, struct got_packidx *packidx, int obj_idx,
84 3efd8e31 2022-10-23 thomas struct got_repository *repo)
85 3efd8e31 2022-10-23 thomas {
86 6d7eb4f7 2023-04-04 thomas const struct got_error *err;
87 6d7eb4f7 2023-04-04 thomas
88 6d7eb4f7 2023-04-04 thomas *obj = got_repo_get_cached_object(repo, id);
89 6d7eb4f7 2023-04-04 thomas if (*obj != NULL) {
90 6d7eb4f7 2023-04-04 thomas (*obj)->refcnt++;
91 6d7eb4f7 2023-04-04 thomas return NULL;
92 6d7eb4f7 2023-04-04 thomas }
93 6d7eb4f7 2023-04-04 thomas
94 6d7eb4f7 2023-04-04 thomas err = got_packfile_open_object(obj, pack, packidx, obj_idx, id);
95 6d7eb4f7 2023-04-04 thomas if (err)
96 6d7eb4f7 2023-04-04 thomas return err;
97 6d7eb4f7 2023-04-04 thomas (*obj)->refcnt++;
98 6d7eb4f7 2023-04-04 thomas
99 6d7eb4f7 2023-04-04 thomas err = got_repo_cache_object(repo, id, *obj);
100 6d7eb4f7 2023-04-04 thomas if (err) {
101 6d7eb4f7 2023-04-04 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
102 6d7eb4f7 2023-04-04 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
103 6d7eb4f7 2023-04-04 thomas err = NULL;
104 6d7eb4f7 2023-04-04 thomas return err;
105 6d7eb4f7 2023-04-04 thomas }
106 6d7eb4f7 2023-04-04 thomas (*obj)->refcnt++;
107 6d7eb4f7 2023-04-04 thomas return NULL;
108 3efd8e31 2022-10-23 thomas }
109 3efd8e31 2022-10-23 thomas
110 3efd8e31 2022-10-23 thomas const struct got_error *
111 3efd8e31 2022-10-23 thomas got_object_read_raw_delta(uint64_t *base_size, uint64_t *result_size,
112 3efd8e31 2022-10-23 thomas off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
113 3efd8e31 2022-10-23 thomas off_t *delta_out_offset, struct got_object_id **base_id, int delta_cache_fd,
114 3efd8e31 2022-10-23 thomas struct got_packidx *packidx, int obj_idx, struct got_object_id *id,
115 3efd8e31 2022-10-23 thomas struct got_repository *repo)
116 3efd8e31 2022-10-23 thomas {
117 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
118 3efd8e31 2022-10-23 thomas }
119 3efd8e31 2022-10-23 thomas
120 3efd8e31 2022-10-23 thomas const struct got_error *
121 3efd8e31 2022-10-23 thomas got_object_open(struct got_object **obj, struct got_repository *repo,
122 3efd8e31 2022-10-23 thomas struct got_object_id *id)
123 3efd8e31 2022-10-23 thomas {
124 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
125 3efd8e31 2022-10-23 thomas int fd;
126 3efd8e31 2022-10-23 thomas
127 3efd8e31 2022-10-23 thomas *obj = got_repo_get_cached_object(repo, id);
128 3efd8e31 2022-10-23 thomas if (*obj != NULL) {
129 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
130 3efd8e31 2022-10-23 thomas return NULL;
131 3efd8e31 2022-10-23 thomas }
132 3efd8e31 2022-10-23 thomas
133 3efd8e31 2022-10-23 thomas err = got_object_open_packed(obj, id, repo);
134 3efd8e31 2022-10-23 thomas if (err) {
135 3efd8e31 2022-10-23 thomas if (err->code != GOT_ERR_NO_OBJ)
136 3efd8e31 2022-10-23 thomas return err;
137 3efd8e31 2022-10-23 thomas } else
138 3efd8e31 2022-10-23 thomas return NULL;
139 3efd8e31 2022-10-23 thomas
140 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
141 3efd8e31 2022-10-23 thomas if (err) {
142 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_ERRNO && errno == ENOENT)
143 3efd8e31 2022-10-23 thomas err = got_error_no_obj(id);
144 3efd8e31 2022-10-23 thomas return err;
145 3efd8e31 2022-10-23 thomas }
146 3efd8e31 2022-10-23 thomas
147 3efd8e31 2022-10-23 thomas err = got_object_read_header(obj, fd);
148 3efd8e31 2022-10-23 thomas if (err)
149 3efd8e31 2022-10-23 thomas goto done;
150 3efd8e31 2022-10-23 thomas
151 3efd8e31 2022-10-23 thomas memcpy(&(*obj)->id, id, sizeof((*obj)->id));
152 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
153 3efd8e31 2022-10-23 thomas
154 3efd8e31 2022-10-23 thomas err = got_repo_cache_object(repo, id, *obj);
155 3efd8e31 2022-10-23 thomas if (err) {
156 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
157 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
158 3efd8e31 2022-10-23 thomas err = NULL;
159 3efd8e31 2022-10-23 thomas }
160 3efd8e31 2022-10-23 thomas done:
161 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
162 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
163 3efd8e31 2022-10-23 thomas return err;
164 3efd8e31 2022-10-23 thomas }
165 3efd8e31 2022-10-23 thomas
166 3efd8e31 2022-10-23 thomas static const struct got_error *
167 3efd8e31 2022-10-23 thomas wrap_fd(FILE **f, int wrapped_fd)
168 3efd8e31 2022-10-23 thomas {
169 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
170 3efd8e31 2022-10-23 thomas int fd;
171 3efd8e31 2022-10-23 thomas
172 3efd8e31 2022-10-23 thomas if (ftruncate(wrapped_fd, 0L) == -1)
173 3efd8e31 2022-10-23 thomas return got_error_from_errno("ftruncate");
174 3efd8e31 2022-10-23 thomas
175 3efd8e31 2022-10-23 thomas if (lseek(wrapped_fd, 0L, SEEK_SET) == -1)
176 3efd8e31 2022-10-23 thomas return got_error_from_errno("lseek");
177 3efd8e31 2022-10-23 thomas
178 3efd8e31 2022-10-23 thomas fd = dup(wrapped_fd);
179 3efd8e31 2022-10-23 thomas if (fd == -1)
180 3efd8e31 2022-10-23 thomas return got_error_from_errno("dup");
181 3efd8e31 2022-10-23 thomas
182 3efd8e31 2022-10-23 thomas *f = fdopen(fd, "w+");
183 3efd8e31 2022-10-23 thomas if (*f == NULL) {
184 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fdopen");
185 3efd8e31 2022-10-23 thomas close(fd);
186 3efd8e31 2022-10-23 thomas }
187 3efd8e31 2022-10-23 thomas return err;
188 3efd8e31 2022-10-23 thomas }
189 3efd8e31 2022-10-23 thomas
190 3efd8e31 2022-10-23 thomas static const struct got_error *
191 3efd8e31 2022-10-23 thomas read_packed_object_raw(uint8_t **outbuf, off_t *size, size_t *hdrlen,
192 3efd8e31 2022-10-23 thomas int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
193 3efd8e31 2022-10-23 thomas struct got_object_id *id)
194 3efd8e31 2022-10-23 thomas {
195 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
196 3efd8e31 2022-10-23 thomas uint64_t raw_size = 0;
197 3efd8e31 2022-10-23 thomas struct got_object *obj;
198 3efd8e31 2022-10-23 thomas FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
199 3efd8e31 2022-10-23 thomas
200 3efd8e31 2022-10-23 thomas *outbuf = NULL;
201 3efd8e31 2022-10-23 thomas *size = 0;
202 3efd8e31 2022-10-23 thomas *hdrlen = 0;
203 3efd8e31 2022-10-23 thomas
204 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
205 3efd8e31 2022-10-23 thomas if (err)
206 3efd8e31 2022-10-23 thomas return err;
207 3efd8e31 2022-10-23 thomas
208 3efd8e31 2022-10-23 thomas if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
209 3efd8e31 2022-10-23 thomas err = got_pack_get_max_delta_object_size(&raw_size, obj, pack);
210 3efd8e31 2022-10-23 thomas if (err)
211 3efd8e31 2022-10-23 thomas goto done;
212 3efd8e31 2022-10-23 thomas } else
213 3efd8e31 2022-10-23 thomas raw_size = obj->size;
214 3efd8e31 2022-10-23 thomas
215 3efd8e31 2022-10-23 thomas if (raw_size <= GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
216 3efd8e31 2022-10-23 thomas size_t len;
217 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(outbuf, &len,
218 3efd8e31 2022-10-23 thomas obj, pack);
219 3efd8e31 2022-10-23 thomas if (err)
220 3efd8e31 2022-10-23 thomas goto done;
221 3efd8e31 2022-10-23 thomas *size = (off_t)len;
222 3efd8e31 2022-10-23 thomas } else {
223 3efd8e31 2022-10-23 thomas /*
224 3efd8e31 2022-10-23 thomas * XXX This uses 3 file extra descriptors for no good reason.
225 3efd8e31 2022-10-23 thomas * We should have got_packfile_extract_object_to_fd().
226 3efd8e31 2022-10-23 thomas */
227 3efd8e31 2022-10-23 thomas err = wrap_fd(&outfile, outfd);
228 3efd8e31 2022-10-23 thomas if (err)
229 3efd8e31 2022-10-23 thomas goto done;
230 3efd8e31 2022-10-23 thomas err = wrap_fd(&basefile, pack->basefd);
231 3efd8e31 2022-10-23 thomas if (err)
232 3efd8e31 2022-10-23 thomas goto done;
233 3efd8e31 2022-10-23 thomas err = wrap_fd(&accumfile, pack->accumfd);
234 3efd8e31 2022-10-23 thomas if (err)
235 3efd8e31 2022-10-23 thomas goto done;
236 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object(pack, obj, outfile, basefile,
237 3efd8e31 2022-10-23 thomas accumfile);
238 3efd8e31 2022-10-23 thomas if (err)
239 3efd8e31 2022-10-23 thomas goto done;
240 b296ac1c 2023-01-09 thomas *size = obj->size;
241 3efd8e31 2022-10-23 thomas }
242 3efd8e31 2022-10-23 thomas
243 3efd8e31 2022-10-23 thomas *hdrlen = obj->hdrlen;
244 3efd8e31 2022-10-23 thomas done:
245 3efd8e31 2022-10-23 thomas got_object_close(obj);
246 3efd8e31 2022-10-23 thomas if (outfile && fclose(outfile) == EOF && err == NULL)
247 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
248 3efd8e31 2022-10-23 thomas if (basefile && fclose(basefile) == EOF && err == NULL)
249 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
250 3efd8e31 2022-10-23 thomas if (accumfile && fclose(accumfile) == EOF && err == NULL)
251 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
252 3efd8e31 2022-10-23 thomas return err;
253 3efd8e31 2022-10-23 thomas
254 3efd8e31 2022-10-23 thomas }
255 3efd8e31 2022-10-23 thomas
256 3efd8e31 2022-10-23 thomas static void
257 3efd8e31 2022-10-23 thomas put_raw_object_tempfile(struct got_raw_object *obj)
258 3efd8e31 2022-10-23 thomas {
259 3efd8e31 2022-10-23 thomas struct got_repository *repo = obj->close_arg;
260 3efd8e31 2022-10-23 thomas
261 3efd8e31 2022-10-23 thomas if (obj->tempfile_idx != -1)
262 3efd8e31 2022-10-23 thomas got_repo_temp_fds_put(obj->tempfile_idx, repo);
263 3efd8e31 2022-10-23 thomas }
264 3efd8e31 2022-10-23 thomas
265 3efd8e31 2022-10-23 thomas /* *outfd must be initialized to -1 by caller */
266 3efd8e31 2022-10-23 thomas const struct got_error *
267 3efd8e31 2022-10-23 thomas got_object_raw_open(struct got_raw_object **obj, int *outfd,
268 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
269 3efd8e31 2022-10-23 thomas {
270 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
271 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
272 ab9f7b87 2023-01-09 thomas int idx, tempfd, tempfile_idx;
273 3efd8e31 2022-10-23 thomas uint8_t *outbuf = NULL;
274 3efd8e31 2022-10-23 thomas off_t size = 0;
275 3efd8e31 2022-10-23 thomas size_t hdrlen = 0;
276 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
277 3efd8e31 2022-10-23 thomas
278 3efd8e31 2022-10-23 thomas *obj = got_repo_get_cached_raw_object(repo, id);
279 3efd8e31 2022-10-23 thomas if (*obj != NULL) {
280 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
281 3efd8e31 2022-10-23 thomas return NULL;
282 3efd8e31 2022-10-23 thomas }
283 3efd8e31 2022-10-23 thomas
284 ab9f7b87 2023-01-09 thomas err = got_repo_temp_fds_get(&tempfd, &tempfile_idx, repo);
285 ab9f7b87 2023-01-09 thomas if (err)
286 ab9f7b87 2023-01-09 thomas return err;
287 3efd8e31 2022-10-23 thomas
288 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
289 3efd8e31 2022-10-23 thomas if (err == NULL) {
290 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
291 3efd8e31 2022-10-23 thomas
292 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
293 3efd8e31 2022-10-23 thomas packidx->path_packidx);
294 3efd8e31 2022-10-23 thomas if (err)
295 3efd8e31 2022-10-23 thomas goto done;
296 3efd8e31 2022-10-23 thomas
297 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
298 3efd8e31 2022-10-23 thomas if (pack == NULL) {
299 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
300 3efd8e31 2022-10-23 thomas packidx);
301 3efd8e31 2022-10-23 thomas if (err)
302 3efd8e31 2022-10-23 thomas goto done;
303 3efd8e31 2022-10-23 thomas }
304 3efd8e31 2022-10-23 thomas err = read_packed_object_raw(&outbuf, &size, &hdrlen,
305 ab9f7b87 2023-01-09 thomas tempfd, pack, packidx, idx, id);
306 3efd8e31 2022-10-23 thomas if (err)
307 3efd8e31 2022-10-23 thomas goto done;
308 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
309 3efd8e31 2022-10-23 thomas int fd;
310 3efd8e31 2022-10-23 thomas
311 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
312 3efd8e31 2022-10-23 thomas if (err)
313 3efd8e31 2022-10-23 thomas goto done;
314 3efd8e31 2022-10-23 thomas err = got_object_read_raw(&outbuf, &size, &hdrlen,
315 ab9f7b87 2023-01-09 thomas GOT_DELTA_RESULT_SIZE_CACHED_MAX, tempfd, id, fd);
316 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
317 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
318 3efd8e31 2022-10-23 thomas if (err)
319 ab9f7b87 2023-01-09 thomas goto done;
320 ab9f7b87 2023-01-09 thomas }
321 ab9f7b87 2023-01-09 thomas
322 ab9f7b87 2023-01-09 thomas if (outbuf == NULL) {
323 ab9f7b87 2023-01-09 thomas if (*outfd != -1) {
324 ab9f7b87 2023-01-09 thomas err = got_error_msg(GOT_ERR_NOT_IMPL, "bad outfd");
325 ab9f7b87 2023-01-09 thomas goto done;
326 ab9f7b87 2023-01-09 thomas }
327 ab9f7b87 2023-01-09 thomas
328 ab9f7b87 2023-01-09 thomas /*
329 ab9f7b87 2023-01-09 thomas * Duplicate tempfile descriptor to allow use of
330 ab9f7b87 2023-01-09 thomas * fdopen(3) inside got_object_raw_alloc().
331 ab9f7b87 2023-01-09 thomas */
332 ab9f7b87 2023-01-09 thomas *outfd = dup(tempfd);
333 ab9f7b87 2023-01-09 thomas if (*outfd == -1) {
334 ab9f7b87 2023-01-09 thomas err = got_error_from_errno("dup");
335 3efd8e31 2022-10-23 thomas goto done;
336 ab9f7b87 2023-01-09 thomas }
337 3efd8e31 2022-10-23 thomas }
338 3efd8e31 2022-10-23 thomas
339 ebe6ec92 2023-01-09 thomas err = got_object_raw_alloc(obj, outbuf, outfd,
340 ebe6ec92 2023-01-09 thomas GOT_DELTA_RESULT_SIZE_CACHED_MAX, hdrlen, size);
341 3efd8e31 2022-10-23 thomas if (err)
342 3efd8e31 2022-10-23 thomas goto done;
343 3efd8e31 2022-10-23 thomas
344 3efd8e31 2022-10-23 thomas err = got_repo_cache_raw_object(repo, id, *obj);
345 3efd8e31 2022-10-23 thomas if (err) {
346 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
347 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
348 3efd8e31 2022-10-23 thomas err = NULL;
349 3efd8e31 2022-10-23 thomas }
350 3efd8e31 2022-10-23 thomas done:
351 3efd8e31 2022-10-23 thomas free(path_packfile);
352 3efd8e31 2022-10-23 thomas if (err) {
353 3efd8e31 2022-10-23 thomas if (*obj) {
354 3efd8e31 2022-10-23 thomas got_object_raw_close(*obj);
355 3efd8e31 2022-10-23 thomas *obj = NULL;
356 3efd8e31 2022-10-23 thomas }
357 3efd8e31 2022-10-23 thomas free(outbuf);
358 ab9f7b87 2023-01-09 thomas got_repo_temp_fds_put(tempfile_idx, repo);
359 ab9f7b87 2023-01-09 thomas if (*outfd != -1) {
360 ab9f7b87 2023-01-09 thomas close(*outfd);
361 ab9f7b87 2023-01-09 thomas *outfd = -1;
362 ab9f7b87 2023-01-09 thomas }
363 3efd8e31 2022-10-23 thomas } else {
364 ab9f7b87 2023-01-09 thomas if (((*obj)->f == NULL && (*obj)->fd == -1)) {
365 ab9f7b87 2023-01-09 thomas /* This raw object is not backed by a file. */
366 ab9f7b87 2023-01-09 thomas got_repo_temp_fds_put(tempfile_idx, repo);
367 ab9f7b87 2023-01-09 thomas if (*outfd != -1) {
368 ab9f7b87 2023-01-09 thomas close(*outfd);
369 ab9f7b87 2023-01-09 thomas *outfd = -1;
370 ab9f7b87 2023-01-09 thomas }
371 ab9f7b87 2023-01-09 thomas } else {
372 ab9f7b87 2023-01-09 thomas (*obj)->tempfile_idx = tempfile_idx;
373 ab9f7b87 2023-01-09 thomas (*obj)->close_cb = put_raw_object_tempfile;
374 ab9f7b87 2023-01-09 thomas (*obj)->close_arg = repo;
375 ab9f7b87 2023-01-09 thomas }
376 3efd8e31 2022-10-23 thomas }
377 3efd8e31 2022-10-23 thomas return err;
378 3efd8e31 2022-10-23 thomas }
379 3efd8e31 2022-10-23 thomas
380 3efd8e31 2022-10-23 thomas static const struct got_error *
381 3efd8e31 2022-10-23 thomas open_commit(struct got_commit_object **commit,
382 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, int check_cache)
383 3efd8e31 2022-10-23 thomas {
384 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
385 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
386 3efd8e31 2022-10-23 thomas int idx;
387 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
388 3efd8e31 2022-10-23 thomas
389 3efd8e31 2022-10-23 thomas if (check_cache) {
390 3efd8e31 2022-10-23 thomas *commit = got_repo_get_cached_commit(repo, id);
391 3efd8e31 2022-10-23 thomas if (*commit != NULL) {
392 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
393 3efd8e31 2022-10-23 thomas return NULL;
394 3efd8e31 2022-10-23 thomas }
395 3efd8e31 2022-10-23 thomas } else
396 3efd8e31 2022-10-23 thomas *commit = NULL;
397 3efd8e31 2022-10-23 thomas
398 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
399 3efd8e31 2022-10-23 thomas if (err == NULL) {
400 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
401 3efd8e31 2022-10-23 thomas struct got_object *obj;
402 3efd8e31 2022-10-23 thomas uint8_t *buf;
403 3efd8e31 2022-10-23 thomas size_t len;
404 3efd8e31 2022-10-23 thomas
405 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
406 3efd8e31 2022-10-23 thomas packidx->path_packidx);
407 3efd8e31 2022-10-23 thomas if (err)
408 3efd8e31 2022-10-23 thomas return err;
409 3efd8e31 2022-10-23 thomas
410 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
411 3efd8e31 2022-10-23 thomas if (pack == NULL) {
412 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
413 3efd8e31 2022-10-23 thomas packidx);
414 3efd8e31 2022-10-23 thomas if (err)
415 3efd8e31 2022-10-23 thomas goto done;
416 3efd8e31 2022-10-23 thomas }
417 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
418 3efd8e31 2022-10-23 thomas if (err)
419 3efd8e31 2022-10-23 thomas goto done;
420 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
421 3efd8e31 2022-10-23 thomas obj, pack);
422 3efd8e31 2022-10-23 thomas got_object_close(obj);
423 3efd8e31 2022-10-23 thomas if (err)
424 3efd8e31 2022-10-23 thomas goto done;
425 3efd8e31 2022-10-23 thomas err = got_object_parse_commit(commit, buf, len);
426 3efd8e31 2022-10-23 thomas free(buf);
427 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
428 3efd8e31 2022-10-23 thomas int fd;
429 3efd8e31 2022-10-23 thomas
430 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
431 3efd8e31 2022-10-23 thomas if (err)
432 3efd8e31 2022-10-23 thomas return err;
433 3efd8e31 2022-10-23 thomas err = got_object_read_commit(commit, fd, id, 0);
434 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
435 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
436 3efd8e31 2022-10-23 thomas if (err)
437 3efd8e31 2022-10-23 thomas return err;
438 3efd8e31 2022-10-23 thomas }
439 3efd8e31 2022-10-23 thomas
440 3efd8e31 2022-10-23 thomas if (err == NULL) {
441 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
442 3efd8e31 2022-10-23 thomas err = got_repo_cache_commit(repo, id, *commit);
443 3efd8e31 2022-10-23 thomas if (err) {
444 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
445 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
446 3efd8e31 2022-10-23 thomas err = NULL;
447 3efd8e31 2022-10-23 thomas }
448 3efd8e31 2022-10-23 thomas }
449 3efd8e31 2022-10-23 thomas done:
450 3efd8e31 2022-10-23 thomas free(path_packfile);
451 3efd8e31 2022-10-23 thomas return err;
452 3efd8e31 2022-10-23 thomas }
453 3efd8e31 2022-10-23 thomas
454 3efd8e31 2022-10-23 thomas const struct got_error *
455 3efd8e31 2022-10-23 thomas got_object_open_as_commit(struct got_commit_object **commit,
456 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
457 3efd8e31 2022-10-23 thomas {
458 3efd8e31 2022-10-23 thomas *commit = got_repo_get_cached_commit(repo, id);
459 3efd8e31 2022-10-23 thomas if (*commit != NULL) {
460 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
461 3efd8e31 2022-10-23 thomas return NULL;
462 3efd8e31 2022-10-23 thomas }
463 3efd8e31 2022-10-23 thomas
464 3efd8e31 2022-10-23 thomas return open_commit(commit, repo, id, 0);
465 3efd8e31 2022-10-23 thomas }
466 3efd8e31 2022-10-23 thomas
467 3efd8e31 2022-10-23 thomas const struct got_error *
468 3efd8e31 2022-10-23 thomas got_object_commit_open(struct got_commit_object **commit,
469 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
470 3efd8e31 2022-10-23 thomas {
471 3efd8e31 2022-10-23 thomas return open_commit(commit, repo, got_object_get_id(obj), 1);
472 3efd8e31 2022-10-23 thomas }
473 3efd8e31 2022-10-23 thomas
474 3efd8e31 2022-10-23 thomas static const struct got_error *
475 3efd8e31 2022-10-23 thomas open_tree(struct got_tree_object **tree,
476 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, int check_cache)
477 3efd8e31 2022-10-23 thomas {
478 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
479 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
480 3efd8e31 2022-10-23 thomas int idx;
481 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
482 3efd8e31 2022-10-23 thomas struct got_parsed_tree_entry *entries = NULL;
483 3efd8e31 2022-10-23 thomas size_t nentries = 0, nentries_alloc = 0, i;
484 3efd8e31 2022-10-23 thomas uint8_t *buf = NULL;
485 3efd8e31 2022-10-23 thomas
486 3efd8e31 2022-10-23 thomas if (check_cache) {
487 3efd8e31 2022-10-23 thomas *tree = got_repo_get_cached_tree(repo, id);
488 3efd8e31 2022-10-23 thomas if (*tree != NULL) {
489 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
490 3efd8e31 2022-10-23 thomas return NULL;
491 3efd8e31 2022-10-23 thomas }
492 3efd8e31 2022-10-23 thomas } else
493 3efd8e31 2022-10-23 thomas *tree = NULL;
494 3efd8e31 2022-10-23 thomas
495 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
496 3efd8e31 2022-10-23 thomas if (err == NULL) {
497 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
498 3efd8e31 2022-10-23 thomas struct got_object *obj;
499 3efd8e31 2022-10-23 thomas size_t len;
500 3efd8e31 2022-10-23 thomas
501 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
502 3efd8e31 2022-10-23 thomas packidx->path_packidx);
503 3efd8e31 2022-10-23 thomas if (err)
504 3efd8e31 2022-10-23 thomas return err;
505 3efd8e31 2022-10-23 thomas
506 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
507 3efd8e31 2022-10-23 thomas if (pack == NULL) {
508 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
509 3efd8e31 2022-10-23 thomas packidx);
510 3efd8e31 2022-10-23 thomas if (err)
511 3efd8e31 2022-10-23 thomas goto done;
512 3efd8e31 2022-10-23 thomas }
513 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
514 3efd8e31 2022-10-23 thomas if (err)
515 3efd8e31 2022-10-23 thomas goto done;
516 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
517 3efd8e31 2022-10-23 thomas obj, pack);
518 3efd8e31 2022-10-23 thomas got_object_close(obj);
519 3efd8e31 2022-10-23 thomas if (err)
520 3efd8e31 2022-10-23 thomas goto done;
521 3efd8e31 2022-10-23 thomas err = got_object_parse_tree(&entries, &nentries,
522 3efd8e31 2022-10-23 thomas &nentries_alloc, buf, len);
523 3efd8e31 2022-10-23 thomas if (err)
524 3efd8e31 2022-10-23 thomas goto done;
525 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
526 3efd8e31 2022-10-23 thomas int fd;
527 3efd8e31 2022-10-23 thomas
528 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
529 3efd8e31 2022-10-23 thomas if (err)
530 3efd8e31 2022-10-23 thomas return err;
531 3efd8e31 2022-10-23 thomas err = got_object_read_tree(&entries, &nentries,
532 3efd8e31 2022-10-23 thomas &nentries_alloc, &buf, fd, id);
533 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
534 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
535 3efd8e31 2022-10-23 thomas if (err)
536 3efd8e31 2022-10-23 thomas goto done;
537 3efd8e31 2022-10-23 thomas } else
538 3efd8e31 2022-10-23 thomas goto done;
539 3efd8e31 2022-10-23 thomas
540 3efd8e31 2022-10-23 thomas *tree = malloc(sizeof(**tree));
541 3efd8e31 2022-10-23 thomas if (*tree == NULL) {
542 3efd8e31 2022-10-23 thomas err = got_error_from_errno("malloc");
543 3efd8e31 2022-10-23 thomas goto done;
544 3efd8e31 2022-10-23 thomas }
545 3efd8e31 2022-10-23 thomas (*tree)->entries = calloc(nentries, sizeof(struct got_tree_entry));
546 3efd8e31 2022-10-23 thomas if ((*tree)->entries == NULL) {
547 3efd8e31 2022-10-23 thomas err = got_error_from_errno("malloc");
548 3efd8e31 2022-10-23 thomas goto done;
549 3efd8e31 2022-10-23 thomas }
550 3efd8e31 2022-10-23 thomas (*tree)->nentries = nentries;
551 3efd8e31 2022-10-23 thomas (*tree)->refcnt = 0;
552 3efd8e31 2022-10-23 thomas
553 3efd8e31 2022-10-23 thomas for (i = 0; i < nentries; i++) {
554 3efd8e31 2022-10-23 thomas struct got_parsed_tree_entry *pe = &entries[i];
555 3efd8e31 2022-10-23 thomas struct got_tree_entry *te = &(*tree)->entries[i];
556 3efd8e31 2022-10-23 thomas
557 3efd8e31 2022-10-23 thomas if (strlcpy(te->name, pe->name,
558 3efd8e31 2022-10-23 thomas sizeof(te->name)) >= sizeof(te->name)) {
559 3efd8e31 2022-10-23 thomas err = got_error(GOT_ERR_NO_SPACE);
560 3efd8e31 2022-10-23 thomas goto done;
561 3efd8e31 2022-10-23 thomas }
562 3efd8e31 2022-10-23 thomas memcpy(te->id.sha1, pe->id, SHA1_DIGEST_LENGTH);
563 3efd8e31 2022-10-23 thomas te->mode = pe->mode;
564 3efd8e31 2022-10-23 thomas te->idx = i;
565 3efd8e31 2022-10-23 thomas }
566 3efd8e31 2022-10-23 thomas done:
567 3efd8e31 2022-10-23 thomas free(path_packfile);
568 3efd8e31 2022-10-23 thomas free(entries);
569 3efd8e31 2022-10-23 thomas free(buf);
570 3efd8e31 2022-10-23 thomas if (err == NULL) {
571 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
572 3efd8e31 2022-10-23 thomas err = got_repo_cache_tree(repo, id, *tree);
573 3efd8e31 2022-10-23 thomas if (err) {
574 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
575 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
576 3efd8e31 2022-10-23 thomas err = NULL;
577 3efd8e31 2022-10-23 thomas }
578 3efd8e31 2022-10-23 thomas }
579 3efd8e31 2022-10-23 thomas if (err) {
580 3efd8e31 2022-10-23 thomas if (*tree)
581 3efd8e31 2022-10-23 thomas free((*tree)->entries);
582 3efd8e31 2022-10-23 thomas free(*tree);
583 3efd8e31 2022-10-23 thomas *tree = NULL;
584 3efd8e31 2022-10-23 thomas }
585 3efd8e31 2022-10-23 thomas return err;
586 3efd8e31 2022-10-23 thomas }
587 3efd8e31 2022-10-23 thomas
588 3efd8e31 2022-10-23 thomas const struct got_error *
589 3efd8e31 2022-10-23 thomas got_object_open_as_tree(struct got_tree_object **tree,
590 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
591 3efd8e31 2022-10-23 thomas {
592 3efd8e31 2022-10-23 thomas *tree = got_repo_get_cached_tree(repo, id);
593 3efd8e31 2022-10-23 thomas if (*tree != NULL) {
594 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
595 3efd8e31 2022-10-23 thomas return NULL;
596 3efd8e31 2022-10-23 thomas }
597 3efd8e31 2022-10-23 thomas
598 3efd8e31 2022-10-23 thomas return open_tree(tree, repo, id, 0);
599 3efd8e31 2022-10-23 thomas }
600 3efd8e31 2022-10-23 thomas
601 3efd8e31 2022-10-23 thomas const struct got_error *
602 3efd8e31 2022-10-23 thomas got_object_tree_open(struct got_tree_object **tree,
603 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
604 3efd8e31 2022-10-23 thomas {
605 3efd8e31 2022-10-23 thomas return open_tree(tree, repo, got_object_get_id(obj), 1);
606 3efd8e31 2022-10-23 thomas }
607 3efd8e31 2022-10-23 thomas
608 3efd8e31 2022-10-23 thomas const struct got_error *
609 3efd8e31 2022-10-23 thomas got_object_open_as_blob(struct got_blob_object **blob,
610 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, size_t blocksize,
611 3efd8e31 2022-10-23 thomas int outfd)
612 3efd8e31 2022-10-23 thomas {
613 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
614 3efd8e31 2022-10-23 thomas }
615 3efd8e31 2022-10-23 thomas
616 3efd8e31 2022-10-23 thomas const struct got_error *
617 3efd8e31 2022-10-23 thomas got_object_blob_open(struct got_blob_object **blob,
618 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj, size_t blocksize,
619 3efd8e31 2022-10-23 thomas int outfd)
620 3efd8e31 2022-10-23 thomas {
621 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
622 3efd8e31 2022-10-23 thomas }
623 3efd8e31 2022-10-23 thomas
624 3efd8e31 2022-10-23 thomas static const struct got_error *
625 3efd8e31 2022-10-23 thomas open_tag(struct got_tag_object **tag, struct got_repository *repo,
626 3efd8e31 2022-10-23 thomas struct got_object_id *id, int check_cache)
627 3efd8e31 2022-10-23 thomas {
628 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
629 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
630 3efd8e31 2022-10-23 thomas int idx;
631 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
632 3efd8e31 2022-10-23 thomas struct got_object *obj = NULL;
633 3efd8e31 2022-10-23 thomas int obj_type = GOT_OBJ_TYPE_ANY;
634 3efd8e31 2022-10-23 thomas
635 3efd8e31 2022-10-23 thomas if (check_cache) {
636 3efd8e31 2022-10-23 thomas *tag = got_repo_get_cached_tag(repo, id);
637 3efd8e31 2022-10-23 thomas if (*tag != NULL) {
638 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
639 3efd8e31 2022-10-23 thomas return NULL;
640 3efd8e31 2022-10-23 thomas }
641 3efd8e31 2022-10-23 thomas } else
642 3efd8e31 2022-10-23 thomas *tag = NULL;
643 3efd8e31 2022-10-23 thomas
644 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
645 3efd8e31 2022-10-23 thomas if (err == NULL) {
646 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
647 3efd8e31 2022-10-23 thomas uint8_t *buf = NULL;
648 3efd8e31 2022-10-23 thomas size_t len;
649 3efd8e31 2022-10-23 thomas
650 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
651 3efd8e31 2022-10-23 thomas packidx->path_packidx);
652 3efd8e31 2022-10-23 thomas if (err)
653 3efd8e31 2022-10-23 thomas return err;
654 3efd8e31 2022-10-23 thomas
655 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
656 3efd8e31 2022-10-23 thomas if (pack == NULL) {
657 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
658 3efd8e31 2022-10-23 thomas packidx);
659 3efd8e31 2022-10-23 thomas if (err)
660 3efd8e31 2022-10-23 thomas goto done;
661 3efd8e31 2022-10-23 thomas }
662 3efd8e31 2022-10-23 thomas
663 3efd8e31 2022-10-23 thomas /* Beware of "lightweight" tags: Check object type first. */
664 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
665 3efd8e31 2022-10-23 thomas if (err)
666 3efd8e31 2022-10-23 thomas goto done;
667 3efd8e31 2022-10-23 thomas obj_type = obj->type;
668 3efd8e31 2022-10-23 thomas if (obj_type != GOT_OBJ_TYPE_TAG) {
669 3efd8e31 2022-10-23 thomas err = got_error(GOT_ERR_OBJ_TYPE);
670 3efd8e31 2022-10-23 thomas got_object_close(obj);
671 3efd8e31 2022-10-23 thomas goto done;
672 3efd8e31 2022-10-23 thomas }
673 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
674 3efd8e31 2022-10-23 thomas obj, pack);
675 3efd8e31 2022-10-23 thomas got_object_close(obj);
676 3efd8e31 2022-10-23 thomas if (err)
677 3efd8e31 2022-10-23 thomas goto done;
678 3efd8e31 2022-10-23 thomas err = got_object_parse_tag(tag, buf, len);
679 3efd8e31 2022-10-23 thomas free(buf);
680 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
681 3efd8e31 2022-10-23 thomas int fd;
682 3efd8e31 2022-10-23 thomas
683 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
684 3efd8e31 2022-10-23 thomas if (err)
685 3efd8e31 2022-10-23 thomas return err;
686 3efd8e31 2022-10-23 thomas err = got_object_read_header(&obj, fd);
687 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
688 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
689 3efd8e31 2022-10-23 thomas if (err)
690 3efd8e31 2022-10-23 thomas return err;
691 3efd8e31 2022-10-23 thomas obj_type = obj->type;
692 3efd8e31 2022-10-23 thomas got_object_close(obj);
693 3efd8e31 2022-10-23 thomas if (obj_type != GOT_OBJ_TYPE_TAG)
694 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_OBJ_TYPE);
695 3efd8e31 2022-10-23 thomas
696 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
697 3efd8e31 2022-10-23 thomas if (err)
698 3efd8e31 2022-10-23 thomas return err;
699 3efd8e31 2022-10-23 thomas err = got_object_read_tag(tag, fd, id, 0);
700 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
701 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
702 3efd8e31 2022-10-23 thomas if (err)
703 3efd8e31 2022-10-23 thomas return err;
704 3efd8e31 2022-10-23 thomas }
705 3efd8e31 2022-10-23 thomas
706 3efd8e31 2022-10-23 thomas if (err == NULL) {
707 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
708 3efd8e31 2022-10-23 thomas err = got_repo_cache_tag(repo, id, *tag);
709 3efd8e31 2022-10-23 thomas if (err) {
710 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
711 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
712 3efd8e31 2022-10-23 thomas err = NULL;
713 3efd8e31 2022-10-23 thomas }
714 3efd8e31 2022-10-23 thomas }
715 3efd8e31 2022-10-23 thomas done:
716 3efd8e31 2022-10-23 thomas free(path_packfile);
717 3efd8e31 2022-10-23 thomas return err;
718 3efd8e31 2022-10-23 thomas }
719 3efd8e31 2022-10-23 thomas
720 3efd8e31 2022-10-23 thomas const struct got_error *
721 3efd8e31 2022-10-23 thomas got_object_open_as_tag(struct got_tag_object **tag,
722 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
723 3efd8e31 2022-10-23 thomas {
724 3efd8e31 2022-10-23 thomas *tag = got_repo_get_cached_tag(repo, id);
725 3efd8e31 2022-10-23 thomas if (*tag != NULL) {
726 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
727 3efd8e31 2022-10-23 thomas return NULL;
728 3efd8e31 2022-10-23 thomas }
729 3efd8e31 2022-10-23 thomas
730 3efd8e31 2022-10-23 thomas return open_tag(tag, repo, id, 0);
731 3efd8e31 2022-10-23 thomas }
732 3efd8e31 2022-10-23 thomas
733 3efd8e31 2022-10-23 thomas const struct got_error *
734 3efd8e31 2022-10-23 thomas got_object_tag_open(struct got_tag_object **tag,
735 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
736 3efd8e31 2022-10-23 thomas {
737 3efd8e31 2022-10-23 thomas return open_tag(tag, repo, got_object_get_id(obj), 1);
738 3efd8e31 2022-10-23 thomas }