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 4efc8dcb 2023-08-29 thomas
17 4efc8dcb 2023-08-29 thomas #include "got_compat.h"
18 3efd8e31 2022-10-23 thomas
19 3efd8e31 2022-10-23 thomas #include <sys/queue.h>
20 3efd8e31 2022-10-23 thomas #include <sys/stat.h>
21 3efd8e31 2022-10-23 thomas
22 3efd8e31 2022-10-23 thomas #include <errno.h>
23 3efd8e31 2022-10-23 thomas #include <limits.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>
28 db642191 2024-03-30 thomas #include <zlib.h>
29 3efd8e31 2022-10-23 thomas
30 3efd8e31 2022-10-23 thomas #include "got_error.h"
31 3efd8e31 2022-10-23 thomas #include "got_object.h"
32 3efd8e31 2022-10-23 thomas #include "got_repository.h"
33 3efd8e31 2022-10-23 thomas #include "got_path.h"
34 3efd8e31 2022-10-23 thomas
35 3efd8e31 2022-10-23 thomas #include "got_lib_delta.h"
36 3efd8e31 2022-10-23 thomas #include "got_lib_object.h"
37 3efd8e31 2022-10-23 thomas #include "got_lib_object_cache.h"
38 3efd8e31 2022-10-23 thomas #include "got_lib_object_parse.h"
39 3efd8e31 2022-10-23 thomas #include "got_lib_pack.h"
40 3efd8e31 2022-10-23 thomas #include "got_lib_repository.h"
41 db642191 2024-03-30 thomas #include "got_lib_inflate.h"
42 db642191 2024-03-30 thomas #include "got_lib_hash.h"
43 3efd8e31 2022-10-23 thomas
44 3efd8e31 2022-10-23 thomas const struct got_error *
45 3efd8e31 2022-10-23 thomas got_object_open_packed(struct got_object **obj, struct got_object_id *id,
46 3efd8e31 2022-10-23 thomas struct got_repository *repo)
47 3efd8e31 2022-10-23 thomas {
48 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
49 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
50 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
51 3efd8e31 2022-10-23 thomas int idx;
52 3efd8e31 2022-10-23 thomas char *path_packfile;
53 3efd8e31 2022-10-23 thomas
54 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
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 err = got_packidx_get_packfile_path(&path_packfile,
59 3efd8e31 2022-10-23 thomas packidx->path_packidx);
60 3efd8e31 2022-10-23 thomas if (err)
61 3efd8e31 2022-10-23 thomas return err;
62 3efd8e31 2022-10-23 thomas
63 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
64 3efd8e31 2022-10-23 thomas if (pack == NULL) {
65 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
66 3efd8e31 2022-10-23 thomas if (err)
67 3efd8e31 2022-10-23 thomas goto done;
68 3efd8e31 2022-10-23 thomas }
69 3efd8e31 2022-10-23 thomas
70 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(obj, pack, packidx, idx, id);
71 3efd8e31 2022-10-23 thomas if (err)
72 3efd8e31 2022-10-23 thomas return err;
73 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
74 3efd8e31 2022-10-23 thomas
75 3efd8e31 2022-10-23 thomas err = got_repo_cache_object(repo, id, *obj);
76 3efd8e31 2022-10-23 thomas if (err) {
77 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
78 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
79 3efd8e31 2022-10-23 thomas err = NULL;
80 3efd8e31 2022-10-23 thomas }
81 3efd8e31 2022-10-23 thomas done:
82 3efd8e31 2022-10-23 thomas free(path_packfile);
83 3efd8e31 2022-10-23 thomas return err;
84 3efd8e31 2022-10-23 thomas }
85 3efd8e31 2022-10-23 thomas
86 3efd8e31 2022-10-23 thomas const struct got_error *
87 3efd8e31 2022-10-23 thomas got_object_open_from_packfile(struct got_object **obj, struct got_object_id *id,
88 3efd8e31 2022-10-23 thomas struct got_pack *pack, struct got_packidx *packidx, int obj_idx,
89 3efd8e31 2022-10-23 thomas struct got_repository *repo)
90 3efd8e31 2022-10-23 thomas {
91 6d7eb4f7 2023-04-04 thomas const struct got_error *err;
92 6d7eb4f7 2023-04-04 thomas
93 6d7eb4f7 2023-04-04 thomas *obj = got_repo_get_cached_object(repo, id);
94 6d7eb4f7 2023-04-04 thomas if (*obj != NULL) {
95 6d7eb4f7 2023-04-04 thomas (*obj)->refcnt++;
96 6d7eb4f7 2023-04-04 thomas return NULL;
97 6d7eb4f7 2023-04-04 thomas }
98 6d7eb4f7 2023-04-04 thomas
99 6d7eb4f7 2023-04-04 thomas err = got_packfile_open_object(obj, pack, packidx, obj_idx, id);
100 6d7eb4f7 2023-04-04 thomas if (err)
101 6d7eb4f7 2023-04-04 thomas return err;
102 6d7eb4f7 2023-04-04 thomas (*obj)->refcnt++;
103 6d7eb4f7 2023-04-04 thomas
104 6d7eb4f7 2023-04-04 thomas err = got_repo_cache_object(repo, id, *obj);
105 6d7eb4f7 2023-04-04 thomas if (err) {
106 6d7eb4f7 2023-04-04 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
107 6d7eb4f7 2023-04-04 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
108 6d7eb4f7 2023-04-04 thomas err = NULL;
109 6d7eb4f7 2023-04-04 thomas return err;
110 6d7eb4f7 2023-04-04 thomas }
111 6d7eb4f7 2023-04-04 thomas (*obj)->refcnt++;
112 6d7eb4f7 2023-04-04 thomas return NULL;
113 3efd8e31 2022-10-23 thomas }
114 3efd8e31 2022-10-23 thomas
115 3efd8e31 2022-10-23 thomas const struct got_error *
116 3efd8e31 2022-10-23 thomas got_object_read_raw_delta(uint64_t *base_size, uint64_t *result_size,
117 3efd8e31 2022-10-23 thomas off_t *delta_size, off_t *delta_compressed_size, off_t *delta_offset,
118 3efd8e31 2022-10-23 thomas off_t *delta_out_offset, struct got_object_id **base_id, int delta_cache_fd,
119 3efd8e31 2022-10-23 thomas struct got_packidx *packidx, int obj_idx, struct got_object_id *id,
120 3efd8e31 2022-10-23 thomas struct got_repository *repo)
121 3efd8e31 2022-10-23 thomas {
122 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_NOT_IMPL);
123 3efd8e31 2022-10-23 thomas }
124 3efd8e31 2022-10-23 thomas
125 3efd8e31 2022-10-23 thomas const struct got_error *
126 3efd8e31 2022-10-23 thomas got_object_open(struct got_object **obj, struct got_repository *repo,
127 3efd8e31 2022-10-23 thomas struct got_object_id *id)
128 3efd8e31 2022-10-23 thomas {
129 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
130 3efd8e31 2022-10-23 thomas int fd;
131 3efd8e31 2022-10-23 thomas
132 3efd8e31 2022-10-23 thomas *obj = got_repo_get_cached_object(repo, id);
133 3efd8e31 2022-10-23 thomas if (*obj != NULL) {
134 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
135 3efd8e31 2022-10-23 thomas return NULL;
136 3efd8e31 2022-10-23 thomas }
137 3efd8e31 2022-10-23 thomas
138 3efd8e31 2022-10-23 thomas err = got_object_open_packed(obj, id, repo);
139 3efd8e31 2022-10-23 thomas if (err) {
140 3efd8e31 2022-10-23 thomas if (err->code != GOT_ERR_NO_OBJ)
141 3efd8e31 2022-10-23 thomas return err;
142 3efd8e31 2022-10-23 thomas } else
143 3efd8e31 2022-10-23 thomas return NULL;
144 3efd8e31 2022-10-23 thomas
145 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
146 3efd8e31 2022-10-23 thomas if (err) {
147 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_ERRNO && errno == ENOENT)
148 3efd8e31 2022-10-23 thomas err = got_error_no_obj(id);
149 3efd8e31 2022-10-23 thomas return err;
150 3efd8e31 2022-10-23 thomas }
151 3efd8e31 2022-10-23 thomas
152 3efd8e31 2022-10-23 thomas err = got_object_read_header(obj, fd);
153 3efd8e31 2022-10-23 thomas if (err)
154 3efd8e31 2022-10-23 thomas goto done;
155 3efd8e31 2022-10-23 thomas
156 3efd8e31 2022-10-23 thomas memcpy(&(*obj)->id, id, sizeof((*obj)->id));
157 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
158 3efd8e31 2022-10-23 thomas
159 3efd8e31 2022-10-23 thomas err = got_repo_cache_object(repo, id, *obj);
160 3efd8e31 2022-10-23 thomas if (err) {
161 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
162 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
163 3efd8e31 2022-10-23 thomas err = NULL;
164 3efd8e31 2022-10-23 thomas }
165 3efd8e31 2022-10-23 thomas done:
166 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
167 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
168 3efd8e31 2022-10-23 thomas return err;
169 3efd8e31 2022-10-23 thomas }
170 3efd8e31 2022-10-23 thomas
171 3efd8e31 2022-10-23 thomas static const struct got_error *
172 3efd8e31 2022-10-23 thomas wrap_fd(FILE **f, int wrapped_fd)
173 3efd8e31 2022-10-23 thomas {
174 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
175 3efd8e31 2022-10-23 thomas int fd;
176 3efd8e31 2022-10-23 thomas
177 3efd8e31 2022-10-23 thomas if (ftruncate(wrapped_fd, 0L) == -1)
178 3efd8e31 2022-10-23 thomas return got_error_from_errno("ftruncate");
179 3efd8e31 2022-10-23 thomas
180 3efd8e31 2022-10-23 thomas if (lseek(wrapped_fd, 0L, SEEK_SET) == -1)
181 3efd8e31 2022-10-23 thomas return got_error_from_errno("lseek");
182 3efd8e31 2022-10-23 thomas
183 3efd8e31 2022-10-23 thomas fd = dup(wrapped_fd);
184 3efd8e31 2022-10-23 thomas if (fd == -1)
185 3efd8e31 2022-10-23 thomas return got_error_from_errno("dup");
186 3efd8e31 2022-10-23 thomas
187 3efd8e31 2022-10-23 thomas *f = fdopen(fd, "w+");
188 3efd8e31 2022-10-23 thomas if (*f == NULL) {
189 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fdopen");
190 3efd8e31 2022-10-23 thomas close(fd);
191 3efd8e31 2022-10-23 thomas }
192 3efd8e31 2022-10-23 thomas return err;
193 3efd8e31 2022-10-23 thomas }
194 3efd8e31 2022-10-23 thomas
195 3efd8e31 2022-10-23 thomas static const struct got_error *
196 3efd8e31 2022-10-23 thomas read_packed_object_raw(uint8_t **outbuf, off_t *size, size_t *hdrlen,
197 3efd8e31 2022-10-23 thomas int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
198 3efd8e31 2022-10-23 thomas struct got_object_id *id)
199 3efd8e31 2022-10-23 thomas {
200 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
201 3efd8e31 2022-10-23 thomas uint64_t raw_size = 0;
202 3efd8e31 2022-10-23 thomas struct got_object *obj;
203 3efd8e31 2022-10-23 thomas FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
204 3efd8e31 2022-10-23 thomas
205 3efd8e31 2022-10-23 thomas *outbuf = NULL;
206 3efd8e31 2022-10-23 thomas *size = 0;
207 3efd8e31 2022-10-23 thomas *hdrlen = 0;
208 3efd8e31 2022-10-23 thomas
209 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
210 3efd8e31 2022-10-23 thomas if (err)
211 3efd8e31 2022-10-23 thomas return err;
212 3efd8e31 2022-10-23 thomas
213 3efd8e31 2022-10-23 thomas if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
214 3efd8e31 2022-10-23 thomas err = got_pack_get_max_delta_object_size(&raw_size, obj, pack);
215 3efd8e31 2022-10-23 thomas if (err)
216 3efd8e31 2022-10-23 thomas goto done;
217 3efd8e31 2022-10-23 thomas } else
218 3efd8e31 2022-10-23 thomas raw_size = obj->size;
219 3efd8e31 2022-10-23 thomas
220 3efd8e31 2022-10-23 thomas if (raw_size <= GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
221 3efd8e31 2022-10-23 thomas size_t len;
222 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(outbuf, &len,
223 3efd8e31 2022-10-23 thomas obj, pack);
224 3efd8e31 2022-10-23 thomas if (err)
225 3efd8e31 2022-10-23 thomas goto done;
226 3efd8e31 2022-10-23 thomas *size = (off_t)len;
227 3efd8e31 2022-10-23 thomas } else {
228 3efd8e31 2022-10-23 thomas /*
229 3efd8e31 2022-10-23 thomas * XXX This uses 3 file extra descriptors for no good reason.
230 3efd8e31 2022-10-23 thomas * We should have got_packfile_extract_object_to_fd().
231 3efd8e31 2022-10-23 thomas */
232 3efd8e31 2022-10-23 thomas err = wrap_fd(&outfile, outfd);
233 3efd8e31 2022-10-23 thomas if (err)
234 3efd8e31 2022-10-23 thomas goto done;
235 3efd8e31 2022-10-23 thomas err = wrap_fd(&basefile, pack->basefd);
236 3efd8e31 2022-10-23 thomas if (err)
237 3efd8e31 2022-10-23 thomas goto done;
238 3efd8e31 2022-10-23 thomas err = wrap_fd(&accumfile, pack->accumfd);
239 3efd8e31 2022-10-23 thomas if (err)
240 3efd8e31 2022-10-23 thomas goto done;
241 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object(pack, obj, outfile, basefile,
242 3efd8e31 2022-10-23 thomas accumfile);
243 3efd8e31 2022-10-23 thomas if (err)
244 3efd8e31 2022-10-23 thomas goto done;
245 b296ac1c 2023-01-09 thomas *size = obj->size;
246 3efd8e31 2022-10-23 thomas }
247 3efd8e31 2022-10-23 thomas
248 3efd8e31 2022-10-23 thomas *hdrlen = obj->hdrlen;
249 3efd8e31 2022-10-23 thomas done:
250 3efd8e31 2022-10-23 thomas got_object_close(obj);
251 3efd8e31 2022-10-23 thomas if (outfile && fclose(outfile) == EOF && err == NULL)
252 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
253 3efd8e31 2022-10-23 thomas if (basefile && fclose(basefile) == EOF && err == NULL)
254 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
255 3efd8e31 2022-10-23 thomas if (accumfile && fclose(accumfile) == EOF && err == NULL)
256 3efd8e31 2022-10-23 thomas err = got_error_from_errno("fclose");
257 3efd8e31 2022-10-23 thomas return err;
258 3efd8e31 2022-10-23 thomas
259 3efd8e31 2022-10-23 thomas }
260 3efd8e31 2022-10-23 thomas
261 3efd8e31 2022-10-23 thomas static void
262 3efd8e31 2022-10-23 thomas put_raw_object_tempfile(struct got_raw_object *obj)
263 3efd8e31 2022-10-23 thomas {
264 3efd8e31 2022-10-23 thomas struct got_repository *repo = obj->close_arg;
265 3efd8e31 2022-10-23 thomas
266 3efd8e31 2022-10-23 thomas if (obj->tempfile_idx != -1)
267 3efd8e31 2022-10-23 thomas got_repo_temp_fds_put(obj->tempfile_idx, repo);
268 3efd8e31 2022-10-23 thomas }
269 3efd8e31 2022-10-23 thomas
270 3efd8e31 2022-10-23 thomas /* *outfd must be initialized to -1 by caller */
271 3efd8e31 2022-10-23 thomas const struct got_error *
272 3efd8e31 2022-10-23 thomas got_object_raw_open(struct got_raw_object **obj, int *outfd,
273 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
274 3efd8e31 2022-10-23 thomas {
275 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
276 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
277 ab9f7b87 2023-01-09 thomas int idx, tempfd, tempfile_idx;
278 3efd8e31 2022-10-23 thomas uint8_t *outbuf = NULL;
279 3efd8e31 2022-10-23 thomas off_t size = 0;
280 3efd8e31 2022-10-23 thomas size_t hdrlen = 0;
281 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
282 3efd8e31 2022-10-23 thomas
283 3efd8e31 2022-10-23 thomas *obj = got_repo_get_cached_raw_object(repo, id);
284 3efd8e31 2022-10-23 thomas if (*obj != NULL) {
285 3efd8e31 2022-10-23 thomas (*obj)->refcnt++;
286 3efd8e31 2022-10-23 thomas return NULL;
287 3efd8e31 2022-10-23 thomas }
288 3efd8e31 2022-10-23 thomas
289 ab9f7b87 2023-01-09 thomas err = got_repo_temp_fds_get(&tempfd, &tempfile_idx, repo);
290 ab9f7b87 2023-01-09 thomas if (err)
291 ab9f7b87 2023-01-09 thomas return err;
292 3efd8e31 2022-10-23 thomas
293 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
294 3efd8e31 2022-10-23 thomas if (err == NULL) {
295 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
296 3efd8e31 2022-10-23 thomas
297 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
298 3efd8e31 2022-10-23 thomas packidx->path_packidx);
299 3efd8e31 2022-10-23 thomas if (err)
300 3efd8e31 2022-10-23 thomas goto done;
301 3efd8e31 2022-10-23 thomas
302 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
303 3efd8e31 2022-10-23 thomas if (pack == NULL) {
304 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
305 3efd8e31 2022-10-23 thomas packidx);
306 3efd8e31 2022-10-23 thomas if (err)
307 3efd8e31 2022-10-23 thomas goto done;
308 3efd8e31 2022-10-23 thomas }
309 3efd8e31 2022-10-23 thomas err = read_packed_object_raw(&outbuf, &size, &hdrlen,
310 ab9f7b87 2023-01-09 thomas tempfd, pack, packidx, idx, id);
311 3efd8e31 2022-10-23 thomas if (err)
312 3efd8e31 2022-10-23 thomas goto done;
313 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
314 3efd8e31 2022-10-23 thomas int fd;
315 3efd8e31 2022-10-23 thomas
316 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
317 3efd8e31 2022-10-23 thomas if (err)
318 3efd8e31 2022-10-23 thomas goto done;
319 3efd8e31 2022-10-23 thomas err = got_object_read_raw(&outbuf, &size, &hdrlen,
320 ab9f7b87 2023-01-09 thomas GOT_DELTA_RESULT_SIZE_CACHED_MAX, tempfd, id, fd);
321 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
322 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
323 3efd8e31 2022-10-23 thomas if (err)
324 ab9f7b87 2023-01-09 thomas goto done;
325 ab9f7b87 2023-01-09 thomas }
326 ab9f7b87 2023-01-09 thomas
327 ab9f7b87 2023-01-09 thomas if (outbuf == NULL) {
328 ab9f7b87 2023-01-09 thomas if (*outfd != -1) {
329 ab9f7b87 2023-01-09 thomas err = got_error_msg(GOT_ERR_NOT_IMPL, "bad outfd");
330 ab9f7b87 2023-01-09 thomas goto done;
331 ab9f7b87 2023-01-09 thomas }
332 ab9f7b87 2023-01-09 thomas
333 ab9f7b87 2023-01-09 thomas /*
334 ab9f7b87 2023-01-09 thomas * Duplicate tempfile descriptor to allow use of
335 ab9f7b87 2023-01-09 thomas * fdopen(3) inside got_object_raw_alloc().
336 ab9f7b87 2023-01-09 thomas */
337 ab9f7b87 2023-01-09 thomas *outfd = dup(tempfd);
338 ab9f7b87 2023-01-09 thomas if (*outfd == -1) {
339 ab9f7b87 2023-01-09 thomas err = got_error_from_errno("dup");
340 3efd8e31 2022-10-23 thomas goto done;
341 ab9f7b87 2023-01-09 thomas }
342 3efd8e31 2022-10-23 thomas }
343 3efd8e31 2022-10-23 thomas
344 ebe6ec92 2023-01-09 thomas err = got_object_raw_alloc(obj, outbuf, outfd,
345 ebe6ec92 2023-01-09 thomas GOT_DELTA_RESULT_SIZE_CACHED_MAX, hdrlen, size);
346 3efd8e31 2022-10-23 thomas if (err)
347 3efd8e31 2022-10-23 thomas goto done;
348 3efd8e31 2022-10-23 thomas
349 3efd8e31 2022-10-23 thomas err = got_repo_cache_raw_object(repo, id, *obj);
350 3efd8e31 2022-10-23 thomas if (err) {
351 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
352 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
353 3efd8e31 2022-10-23 thomas err = NULL;
354 3efd8e31 2022-10-23 thomas }
355 3efd8e31 2022-10-23 thomas done:
356 3efd8e31 2022-10-23 thomas free(path_packfile);
357 3efd8e31 2022-10-23 thomas if (err) {
358 3efd8e31 2022-10-23 thomas if (*obj) {
359 3efd8e31 2022-10-23 thomas got_object_raw_close(*obj);
360 3efd8e31 2022-10-23 thomas *obj = NULL;
361 3efd8e31 2022-10-23 thomas }
362 3efd8e31 2022-10-23 thomas free(outbuf);
363 ab9f7b87 2023-01-09 thomas got_repo_temp_fds_put(tempfile_idx, repo);
364 ab9f7b87 2023-01-09 thomas if (*outfd != -1) {
365 ab9f7b87 2023-01-09 thomas close(*outfd);
366 ab9f7b87 2023-01-09 thomas *outfd = -1;
367 ab9f7b87 2023-01-09 thomas }
368 3efd8e31 2022-10-23 thomas } else {
369 ab9f7b87 2023-01-09 thomas if (((*obj)->f == NULL && (*obj)->fd == -1)) {
370 ab9f7b87 2023-01-09 thomas /* This raw object is not backed by a file. */
371 ab9f7b87 2023-01-09 thomas got_repo_temp_fds_put(tempfile_idx, repo);
372 ab9f7b87 2023-01-09 thomas if (*outfd != -1) {
373 ab9f7b87 2023-01-09 thomas close(*outfd);
374 ab9f7b87 2023-01-09 thomas *outfd = -1;
375 ab9f7b87 2023-01-09 thomas }
376 ab9f7b87 2023-01-09 thomas } else {
377 ab9f7b87 2023-01-09 thomas (*obj)->tempfile_idx = tempfile_idx;
378 ab9f7b87 2023-01-09 thomas (*obj)->close_cb = put_raw_object_tempfile;
379 ab9f7b87 2023-01-09 thomas (*obj)->close_arg = repo;
380 ab9f7b87 2023-01-09 thomas }
381 3efd8e31 2022-10-23 thomas }
382 3efd8e31 2022-10-23 thomas return err;
383 3efd8e31 2022-10-23 thomas }
384 3efd8e31 2022-10-23 thomas
385 3efd8e31 2022-10-23 thomas static const struct got_error *
386 3efd8e31 2022-10-23 thomas open_commit(struct got_commit_object **commit,
387 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, int check_cache)
388 3efd8e31 2022-10-23 thomas {
389 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
390 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
391 3efd8e31 2022-10-23 thomas int idx;
392 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
393 3efd8e31 2022-10-23 thomas
394 3efd8e31 2022-10-23 thomas if (check_cache) {
395 3efd8e31 2022-10-23 thomas *commit = got_repo_get_cached_commit(repo, id);
396 3efd8e31 2022-10-23 thomas if (*commit != NULL) {
397 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
398 3efd8e31 2022-10-23 thomas return NULL;
399 3efd8e31 2022-10-23 thomas }
400 3efd8e31 2022-10-23 thomas } else
401 3efd8e31 2022-10-23 thomas *commit = NULL;
402 3efd8e31 2022-10-23 thomas
403 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
404 3efd8e31 2022-10-23 thomas if (err == NULL) {
405 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
406 3efd8e31 2022-10-23 thomas struct got_object *obj;
407 3efd8e31 2022-10-23 thomas uint8_t *buf;
408 3efd8e31 2022-10-23 thomas size_t len;
409 3efd8e31 2022-10-23 thomas
410 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
411 3efd8e31 2022-10-23 thomas packidx->path_packidx);
412 3efd8e31 2022-10-23 thomas if (err)
413 3efd8e31 2022-10-23 thomas return err;
414 3efd8e31 2022-10-23 thomas
415 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
416 3efd8e31 2022-10-23 thomas if (pack == NULL) {
417 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
418 3efd8e31 2022-10-23 thomas packidx);
419 3efd8e31 2022-10-23 thomas if (err)
420 3efd8e31 2022-10-23 thomas goto done;
421 3efd8e31 2022-10-23 thomas }
422 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
423 3efd8e31 2022-10-23 thomas if (err)
424 3efd8e31 2022-10-23 thomas goto done;
425 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
426 3efd8e31 2022-10-23 thomas obj, pack);
427 3efd8e31 2022-10-23 thomas got_object_close(obj);
428 3efd8e31 2022-10-23 thomas if (err)
429 3efd8e31 2022-10-23 thomas goto done;
430 3efd8e31 2022-10-23 thomas err = got_object_parse_commit(commit, buf, len);
431 3efd8e31 2022-10-23 thomas free(buf);
432 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
433 3efd8e31 2022-10-23 thomas int fd;
434 3efd8e31 2022-10-23 thomas
435 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
436 3efd8e31 2022-10-23 thomas if (err)
437 3efd8e31 2022-10-23 thomas return err;
438 3efd8e31 2022-10-23 thomas err = got_object_read_commit(commit, fd, id, 0);
439 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
440 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
441 3efd8e31 2022-10-23 thomas if (err)
442 3efd8e31 2022-10-23 thomas return err;
443 3efd8e31 2022-10-23 thomas }
444 3efd8e31 2022-10-23 thomas
445 3efd8e31 2022-10-23 thomas if (err == NULL) {
446 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
447 3efd8e31 2022-10-23 thomas err = got_repo_cache_commit(repo, id, *commit);
448 3efd8e31 2022-10-23 thomas if (err) {
449 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
450 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
451 3efd8e31 2022-10-23 thomas err = NULL;
452 3efd8e31 2022-10-23 thomas }
453 3efd8e31 2022-10-23 thomas }
454 3efd8e31 2022-10-23 thomas done:
455 3efd8e31 2022-10-23 thomas free(path_packfile);
456 3efd8e31 2022-10-23 thomas return err;
457 3efd8e31 2022-10-23 thomas }
458 3efd8e31 2022-10-23 thomas
459 3efd8e31 2022-10-23 thomas const struct got_error *
460 3efd8e31 2022-10-23 thomas got_object_open_as_commit(struct got_commit_object **commit,
461 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
462 3efd8e31 2022-10-23 thomas {
463 3efd8e31 2022-10-23 thomas *commit = got_repo_get_cached_commit(repo, id);
464 3efd8e31 2022-10-23 thomas if (*commit != NULL) {
465 3efd8e31 2022-10-23 thomas (*commit)->refcnt++;
466 3efd8e31 2022-10-23 thomas return NULL;
467 3efd8e31 2022-10-23 thomas }
468 3efd8e31 2022-10-23 thomas
469 3efd8e31 2022-10-23 thomas return open_commit(commit, repo, id, 0);
470 3efd8e31 2022-10-23 thomas }
471 3efd8e31 2022-10-23 thomas
472 3efd8e31 2022-10-23 thomas const struct got_error *
473 3efd8e31 2022-10-23 thomas got_object_commit_open(struct got_commit_object **commit,
474 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
475 3efd8e31 2022-10-23 thomas {
476 3efd8e31 2022-10-23 thomas return open_commit(commit, repo, got_object_get_id(obj), 1);
477 3efd8e31 2022-10-23 thomas }
478 3efd8e31 2022-10-23 thomas
479 3efd8e31 2022-10-23 thomas static const struct got_error *
480 3efd8e31 2022-10-23 thomas open_tree(struct got_tree_object **tree,
481 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, int check_cache)
482 3efd8e31 2022-10-23 thomas {
483 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
484 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
485 3efd8e31 2022-10-23 thomas int idx;
486 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
487 3efd8e31 2022-10-23 thomas struct got_parsed_tree_entry *entries = NULL;
488 3efd8e31 2022-10-23 thomas size_t nentries = 0, nentries_alloc = 0, i;
489 3efd8e31 2022-10-23 thomas uint8_t *buf = NULL;
490 3efd8e31 2022-10-23 thomas
491 3efd8e31 2022-10-23 thomas if (check_cache) {
492 3efd8e31 2022-10-23 thomas *tree = got_repo_get_cached_tree(repo, id);
493 3efd8e31 2022-10-23 thomas if (*tree != NULL) {
494 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
495 3efd8e31 2022-10-23 thomas return NULL;
496 3efd8e31 2022-10-23 thomas }
497 3efd8e31 2022-10-23 thomas } else
498 3efd8e31 2022-10-23 thomas *tree = NULL;
499 3efd8e31 2022-10-23 thomas
500 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
501 3efd8e31 2022-10-23 thomas if (err == NULL) {
502 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
503 3efd8e31 2022-10-23 thomas struct got_object *obj;
504 3efd8e31 2022-10-23 thomas size_t len;
505 3efd8e31 2022-10-23 thomas
506 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
507 3efd8e31 2022-10-23 thomas packidx->path_packidx);
508 3efd8e31 2022-10-23 thomas if (err)
509 3efd8e31 2022-10-23 thomas return err;
510 3efd8e31 2022-10-23 thomas
511 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
512 3efd8e31 2022-10-23 thomas if (pack == NULL) {
513 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
514 3efd8e31 2022-10-23 thomas packidx);
515 3efd8e31 2022-10-23 thomas if (err)
516 3efd8e31 2022-10-23 thomas goto done;
517 3efd8e31 2022-10-23 thomas }
518 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
519 3efd8e31 2022-10-23 thomas if (err)
520 3efd8e31 2022-10-23 thomas goto done;
521 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
522 3efd8e31 2022-10-23 thomas obj, pack);
523 3efd8e31 2022-10-23 thomas got_object_close(obj);
524 3efd8e31 2022-10-23 thomas if (err)
525 3efd8e31 2022-10-23 thomas goto done;
526 3efd8e31 2022-10-23 thomas err = got_object_parse_tree(&entries, &nentries,
527 3efd8e31 2022-10-23 thomas &nentries_alloc, buf, len);
528 3efd8e31 2022-10-23 thomas if (err)
529 3efd8e31 2022-10-23 thomas goto done;
530 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
531 3efd8e31 2022-10-23 thomas int fd;
532 3efd8e31 2022-10-23 thomas
533 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
534 3efd8e31 2022-10-23 thomas if (err)
535 3efd8e31 2022-10-23 thomas return err;
536 3efd8e31 2022-10-23 thomas err = got_object_read_tree(&entries, &nentries,
537 3efd8e31 2022-10-23 thomas &nentries_alloc, &buf, fd, id);
538 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
539 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
540 3efd8e31 2022-10-23 thomas if (err)
541 3efd8e31 2022-10-23 thomas goto done;
542 3efd8e31 2022-10-23 thomas } else
543 3efd8e31 2022-10-23 thomas goto done;
544 3efd8e31 2022-10-23 thomas
545 3efd8e31 2022-10-23 thomas *tree = malloc(sizeof(**tree));
546 3efd8e31 2022-10-23 thomas if (*tree == 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)->entries = calloc(nentries, sizeof(struct got_tree_entry));
551 3efd8e31 2022-10-23 thomas if ((*tree)->entries == NULL) {
552 3efd8e31 2022-10-23 thomas err = got_error_from_errno("malloc");
553 3efd8e31 2022-10-23 thomas goto done;
554 3efd8e31 2022-10-23 thomas }
555 3efd8e31 2022-10-23 thomas (*tree)->nentries = nentries;
556 3efd8e31 2022-10-23 thomas (*tree)->refcnt = 0;
557 3efd8e31 2022-10-23 thomas
558 3efd8e31 2022-10-23 thomas for (i = 0; i < nentries; i++) {
559 3efd8e31 2022-10-23 thomas struct got_parsed_tree_entry *pe = &entries[i];
560 3efd8e31 2022-10-23 thomas struct got_tree_entry *te = &(*tree)->entries[i];
561 3efd8e31 2022-10-23 thomas
562 3efd8e31 2022-10-23 thomas if (strlcpy(te->name, pe->name,
563 3efd8e31 2022-10-23 thomas sizeof(te->name)) >= sizeof(te->name)) {
564 3efd8e31 2022-10-23 thomas err = got_error(GOT_ERR_NO_SPACE);
565 3efd8e31 2022-10-23 thomas goto done;
566 3efd8e31 2022-10-23 thomas }
567 3efd8e31 2022-10-23 thomas memcpy(te->id.sha1, pe->id, SHA1_DIGEST_LENGTH);
568 3efd8e31 2022-10-23 thomas te->mode = pe->mode;
569 3efd8e31 2022-10-23 thomas te->idx = i;
570 3efd8e31 2022-10-23 thomas }
571 3efd8e31 2022-10-23 thomas done:
572 3efd8e31 2022-10-23 thomas free(path_packfile);
573 3efd8e31 2022-10-23 thomas free(entries);
574 3efd8e31 2022-10-23 thomas free(buf);
575 3efd8e31 2022-10-23 thomas if (err == NULL) {
576 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
577 3efd8e31 2022-10-23 thomas err = got_repo_cache_tree(repo, id, *tree);
578 3efd8e31 2022-10-23 thomas if (err) {
579 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
580 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
581 3efd8e31 2022-10-23 thomas err = NULL;
582 3efd8e31 2022-10-23 thomas }
583 3efd8e31 2022-10-23 thomas }
584 3efd8e31 2022-10-23 thomas if (err) {
585 3efd8e31 2022-10-23 thomas if (*tree)
586 3efd8e31 2022-10-23 thomas free((*tree)->entries);
587 3efd8e31 2022-10-23 thomas free(*tree);
588 3efd8e31 2022-10-23 thomas *tree = NULL;
589 3efd8e31 2022-10-23 thomas }
590 3efd8e31 2022-10-23 thomas return err;
591 3efd8e31 2022-10-23 thomas }
592 3efd8e31 2022-10-23 thomas
593 3efd8e31 2022-10-23 thomas const struct got_error *
594 3efd8e31 2022-10-23 thomas got_object_open_as_tree(struct got_tree_object **tree,
595 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
596 3efd8e31 2022-10-23 thomas {
597 3efd8e31 2022-10-23 thomas *tree = got_repo_get_cached_tree(repo, id);
598 3efd8e31 2022-10-23 thomas if (*tree != NULL) {
599 3efd8e31 2022-10-23 thomas (*tree)->refcnt++;
600 3efd8e31 2022-10-23 thomas return NULL;
601 3efd8e31 2022-10-23 thomas }
602 3efd8e31 2022-10-23 thomas
603 3efd8e31 2022-10-23 thomas return open_tree(tree, repo, id, 0);
604 3efd8e31 2022-10-23 thomas }
605 3efd8e31 2022-10-23 thomas
606 3efd8e31 2022-10-23 thomas const struct got_error *
607 3efd8e31 2022-10-23 thomas got_object_tree_open(struct got_tree_object **tree,
608 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
609 3efd8e31 2022-10-23 thomas {
610 3efd8e31 2022-10-23 thomas return open_tree(tree, repo, got_object_get_id(obj), 1);
611 3efd8e31 2022-10-23 thomas }
612 db642191 2024-03-30 thomas
613 db642191 2024-03-30 thomas static const struct got_error *
614 db642191 2024-03-30 thomas read_packed_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen,
615 db642191 2024-03-30 thomas int outfd, struct got_pack *pack, struct got_packidx *packidx, int idx,
616 db642191 2024-03-30 thomas struct got_object_id *id, struct got_repository *repo)
617 db642191 2024-03-30 thomas {
618 db642191 2024-03-30 thomas const struct got_error *err = NULL;
619 db642191 2024-03-30 thomas struct got_object *obj;
620 db642191 2024-03-30 thomas FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
621 db642191 2024-03-30 thomas uint64_t blob_size;
622 db642191 2024-03-30 thomas
623 db642191 2024-03-30 thomas *hdrlen = 0;
624 db642191 2024-03-30 thomas
625 db642191 2024-03-30 thomas err = got_object_open_from_packfile(&obj, id, pack, packidx, idx,
626 db642191 2024-03-30 thomas repo);
627 db642191 2024-03-30 thomas if (err)
628 db642191 2024-03-30 thomas return err;
629 3efd8e31 2022-10-23 thomas
630 db642191 2024-03-30 thomas if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
631 db642191 2024-03-30 thomas err = got_pack_get_max_delta_object_size(&blob_size, obj,
632 db642191 2024-03-30 thomas pack);
633 db642191 2024-03-30 thomas if (err)
634 db642191 2024-03-30 thomas goto done;
635 db642191 2024-03-30 thomas } else
636 db642191 2024-03-30 thomas blob_size = obj->size;
637 db642191 2024-03-30 thomas
638 db642191 2024-03-30 thomas if (blob_size <= GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
639 db642191 2024-03-30 thomas err = got_packfile_extract_object_to_mem(outbuf, size,
640 db642191 2024-03-30 thomas obj, pack);
641 db642191 2024-03-30 thomas } else {
642 db642191 2024-03-30 thomas /*
643 db642191 2024-03-30 thomas * XXX This uses 3 file extra descriptors for no good reason.
644 db642191 2024-03-30 thomas * We should have got_packfile_extract_object_to_fd().
645 db642191 2024-03-30 thomas */
646 db642191 2024-03-30 thomas err = wrap_fd(&outfile, outfd);
647 db642191 2024-03-30 thomas if (err)
648 db642191 2024-03-30 thomas goto done;
649 db642191 2024-03-30 thomas err = wrap_fd(&basefile, pack->basefd);
650 db642191 2024-03-30 thomas if (err)
651 db642191 2024-03-30 thomas goto done;
652 db642191 2024-03-30 thomas err = wrap_fd(&accumfile, pack->accumfd);
653 db642191 2024-03-30 thomas if (err)
654 db642191 2024-03-30 thomas goto done;
655 db642191 2024-03-30 thomas err = got_packfile_extract_object(pack, obj, outfile, basefile,
656 db642191 2024-03-30 thomas accumfile);
657 db642191 2024-03-30 thomas if (err)
658 db642191 2024-03-30 thomas goto done;
659 db642191 2024-03-30 thomas *size = obj->size;
660 db642191 2024-03-30 thomas }
661 db642191 2024-03-30 thomas
662 db642191 2024-03-30 thomas /* XXX verify checksum? */
663 db642191 2024-03-30 thomas done:
664 db642191 2024-03-30 thomas got_object_close(obj);
665 db642191 2024-03-30 thomas if (outfile && fclose(outfile) == EOF && err == NULL)
666 db642191 2024-03-30 thomas err = got_error_from_errno("fclose");
667 db642191 2024-03-30 thomas if (basefile && fclose(basefile) == EOF && err == NULL)
668 db642191 2024-03-30 thomas err = got_error_from_errno("fclose");
669 db642191 2024-03-30 thomas if (accumfile && fclose(accumfile) == EOF && err == NULL)
670 db642191 2024-03-30 thomas err = got_error_from_errno("fclose");
671 db642191 2024-03-30 thomas return err;
672 db642191 2024-03-30 thomas }
673 db642191 2024-03-30 thomas
674 db642191 2024-03-30 thomas static const struct got_error *
675 db642191 2024-03-30 thomas read_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen, int outfd, int infd,
676 db642191 2024-03-30 thomas struct got_object_id *id, struct got_repository *repo)
677 db642191 2024-03-30 thomas {
678 db642191 2024-03-30 thomas const struct got_error *err = NULL;
679 db642191 2024-03-30 thomas struct got_object *obj = NULL;
680 db642191 2024-03-30 thomas FILE *f = NULL;
681 db642191 2024-03-30 thomas struct got_object_id expected_id;
682 db642191 2024-03-30 thomas struct got_inflate_checksum csum;
683 db642191 2024-03-30 thomas struct got_hash ctx;
684 db642191 2024-03-30 thomas
685 db642191 2024-03-30 thomas got_hash_init(&ctx, GOT_HASH_SHA1);
686 db642191 2024-03-30 thomas memset(&csum, 0, sizeof(csum));
687 db642191 2024-03-30 thomas csum.output_ctx = &ctx;
688 db642191 2024-03-30 thomas
689 db642191 2024-03-30 thomas memcpy(&expected_id, id, sizeof(expected_id));
690 db642191 2024-03-30 thomas
691 db642191 2024-03-30 thomas err = got_object_read_header(&obj, infd);
692 db642191 2024-03-30 thomas if (err)
693 db642191 2024-03-30 thomas goto done;
694 db642191 2024-03-30 thomas
695 db642191 2024-03-30 thomas if (lseek(infd, SEEK_SET, 0) == -1) {
696 db642191 2024-03-30 thomas err = got_error_from_errno("lseek");
697 db642191 2024-03-30 thomas goto done;
698 db642191 2024-03-30 thomas }
699 db642191 2024-03-30 thomas
700 db642191 2024-03-30 thomas f = fdopen(infd, "rb");
701 db642191 2024-03-30 thomas if (f == NULL) {
702 db642191 2024-03-30 thomas err = got_error_from_errno("fdopen");
703 db642191 2024-03-30 thomas goto done;
704 db642191 2024-03-30 thomas }
705 db642191 2024-03-30 thomas infd = -1;
706 db642191 2024-03-30 thomas
707 db642191 2024-03-30 thomas if (obj->size + obj->hdrlen <= GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
708 db642191 2024-03-30 thomas err = got_inflate_to_mem(outbuf, size, NULL, &csum, f);
709 db642191 2024-03-30 thomas if (err)
710 db642191 2024-03-30 thomas goto done;
711 db642191 2024-03-30 thomas } else {
712 db642191 2024-03-30 thomas err = got_inflate_to_fd(size, f, &csum, outfd);
713 db642191 2024-03-30 thomas if (err)
714 db642191 2024-03-30 thomas goto done;
715 db642191 2024-03-30 thomas }
716 db642191 2024-03-30 thomas
717 db642191 2024-03-30 thomas if (*size < obj->hdrlen) {
718 db642191 2024-03-30 thomas err = got_error(GOT_ERR_BAD_OBJ_HDR);
719 db642191 2024-03-30 thomas goto done;
720 db642191 2024-03-30 thomas }
721 db642191 2024-03-30 thomas
722 db642191 2024-03-30 thomas *hdrlen = obj->hdrlen;
723 db642191 2024-03-30 thomas
724 db642191 2024-03-30 thomas got_hash_final_object_id(&ctx, id);
725 db642191 2024-03-30 thomas if (got_object_id_cmp(&expected_id, id) != 0) {
726 db642191 2024-03-30 thomas err = got_error_checksum(&expected_id);
727 db642191 2024-03-30 thomas goto done;
728 db642191 2024-03-30 thomas }
729 db642191 2024-03-30 thomas done:
730 db642191 2024-03-30 thomas if (f && fclose(f) == EOF && err == NULL)
731 db642191 2024-03-30 thomas err = got_error_from_errno("fclose");
732 db642191 2024-03-30 thomas if (infd != -1 && close(infd) == -1 && err == NULL)
733 db642191 2024-03-30 thomas err = got_error_from_errno("close");
734 db642191 2024-03-30 thomas
735 db642191 2024-03-30 thomas return err;
736 db642191 2024-03-30 thomas }
737 db642191 2024-03-30 thomas
738 db642191 2024-03-30 thomas static const struct got_error *
739 db642191 2024-03-30 thomas open_blob(struct got_blob_object **blob, struct got_repository *repo,
740 db642191 2024-03-30 thomas struct got_object_id *id, size_t blocksize, int outfd)
741 db642191 2024-03-30 thomas {
742 db642191 2024-03-30 thomas const struct got_error *err = NULL;
743 db642191 2024-03-30 thomas struct got_packidx *packidx = NULL;
744 db642191 2024-03-30 thomas int idx, dfd = -1;
745 db642191 2024-03-30 thomas char *path_packfile = NULL;
746 db642191 2024-03-30 thomas uint8_t *outbuf;
747 db642191 2024-03-30 thomas size_t size, hdrlen;
748 db642191 2024-03-30 thomas struct stat sb;
749 db642191 2024-03-30 thomas
750 db642191 2024-03-30 thomas *blob = calloc(1, sizeof(**blob));
751 db642191 2024-03-30 thomas if (*blob == NULL)
752 db642191 2024-03-30 thomas return got_error_from_errno("calloc");
753 db642191 2024-03-30 thomas
754 db642191 2024-03-30 thomas (*blob)->read_buf = malloc(blocksize);
755 db642191 2024-03-30 thomas if ((*blob)->read_buf == NULL) {
756 db642191 2024-03-30 thomas err = got_error_from_errno("malloc");
757 db642191 2024-03-30 thomas goto done;
758 db642191 2024-03-30 thomas }
759 db642191 2024-03-30 thomas
760 db642191 2024-03-30 thomas if (ftruncate(outfd, 0L) == -1) {
761 db642191 2024-03-30 thomas err = got_error_from_errno("ftruncate");
762 db642191 2024-03-30 thomas goto done;
763 db642191 2024-03-30 thomas }
764 db642191 2024-03-30 thomas if (lseek(outfd, SEEK_SET, 0) == -1) {
765 db642191 2024-03-30 thomas err = got_error_from_errno("lseek");
766 db642191 2024-03-30 thomas goto done;
767 db642191 2024-03-30 thomas }
768 db642191 2024-03-30 thomas
769 db642191 2024-03-30 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
770 db642191 2024-03-30 thomas if (err == NULL) {
771 db642191 2024-03-30 thomas struct got_pack *pack = NULL;
772 db642191 2024-03-30 thomas
773 db642191 2024-03-30 thomas err = got_packidx_get_packfile_path(&path_packfile,
774 db642191 2024-03-30 thomas packidx->path_packidx);
775 db642191 2024-03-30 thomas if (err)
776 db642191 2024-03-30 thomas goto done;
777 db642191 2024-03-30 thomas
778 db642191 2024-03-30 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
779 db642191 2024-03-30 thomas if (pack == NULL) {
780 db642191 2024-03-30 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
781 db642191 2024-03-30 thomas packidx);
782 db642191 2024-03-30 thomas if (err)
783 db642191 2024-03-30 thomas goto done;
784 db642191 2024-03-30 thomas }
785 db642191 2024-03-30 thomas err = read_packed_blob(&outbuf, &size, &hdrlen, outfd,
786 db642191 2024-03-30 thomas pack, packidx, idx, id, repo);
787 db642191 2024-03-30 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
788 db642191 2024-03-30 thomas int infd;
789 db642191 2024-03-30 thomas
790 db642191 2024-03-30 thomas err = got_object_open_loose_fd(&infd, id, repo);
791 db642191 2024-03-30 thomas if (err)
792 db642191 2024-03-30 thomas goto done;
793 db642191 2024-03-30 thomas err = read_blob(&outbuf, &size, &hdrlen, outfd, infd,
794 db642191 2024-03-30 thomas id, repo);
795 db642191 2024-03-30 thomas }
796 db642191 2024-03-30 thomas if (err)
797 db642191 2024-03-30 thomas goto done;
798 db642191 2024-03-30 thomas
799 db642191 2024-03-30 thomas if (hdrlen > size) {
800 db642191 2024-03-30 thomas err = got_error(GOT_ERR_BAD_OBJ_HDR);
801 db642191 2024-03-30 thomas goto done;
802 db642191 2024-03-30 thomas }
803 db642191 2024-03-30 thomas
804 db642191 2024-03-30 thomas if (outbuf) {
805 db642191 2024-03-30 thomas (*blob)->f = fmemopen(outbuf, size, "rb");
806 db642191 2024-03-30 thomas if ((*blob)->f == NULL) {
807 db642191 2024-03-30 thomas err = got_error_from_errno("fmemopen");
808 db642191 2024-03-30 thomas free(outbuf);
809 db642191 2024-03-30 thomas goto done;
810 db642191 2024-03-30 thomas }
811 db642191 2024-03-30 thomas (*blob)->data = outbuf;
812 db642191 2024-03-30 thomas } else {
813 db642191 2024-03-30 thomas if (fstat(outfd, &sb) == -1) {
814 db642191 2024-03-30 thomas err = got_error_from_errno("fstat");
815 db642191 2024-03-30 thomas goto done;
816 db642191 2024-03-30 thomas }
817 db642191 2024-03-30 thomas
818 db642191 2024-03-30 thomas if (sb.st_size != size) {
819 db642191 2024-03-30 thomas err = got_error(GOT_ERR_PRIVSEP_LEN);
820 db642191 2024-03-30 thomas goto done;
821 db642191 2024-03-30 thomas }
822 db642191 2024-03-30 thomas
823 db642191 2024-03-30 thomas dfd = dup(outfd);
824 db642191 2024-03-30 thomas if (dfd == -1) {
825 db642191 2024-03-30 thomas err = got_error_from_errno("dup");
826 db642191 2024-03-30 thomas goto done;
827 db642191 2024-03-30 thomas }
828 db642191 2024-03-30 thomas
829 db642191 2024-03-30 thomas (*blob)->f = fdopen(dfd, "rb");
830 db642191 2024-03-30 thomas if ((*blob)->f == NULL) {
831 db642191 2024-03-30 thomas err = got_error_from_errno("fdopen");
832 db642191 2024-03-30 thomas close(dfd);
833 db642191 2024-03-30 thomas dfd = -1;
834 db642191 2024-03-30 thomas goto done;
835 db642191 2024-03-30 thomas }
836 db642191 2024-03-30 thomas }
837 db642191 2024-03-30 thomas
838 db642191 2024-03-30 thomas (*blob)->hdrlen = hdrlen;
839 db642191 2024-03-30 thomas (*blob)->blocksize = blocksize;
840 db642191 2024-03-30 thomas memcpy(&(*blob)->id, id, sizeof(*id));
841 db642191 2024-03-30 thomas
842 db642191 2024-03-30 thomas done:
843 db642191 2024-03-30 thomas free(path_packfile);
844 db642191 2024-03-30 thomas if (err) {
845 db642191 2024-03-30 thomas if (*blob) {
846 db642191 2024-03-30 thomas got_object_blob_close(*blob);
847 db642191 2024-03-30 thomas *blob = NULL;
848 db642191 2024-03-30 thomas }
849 db642191 2024-03-30 thomas }
850 db642191 2024-03-30 thomas return err;
851 db642191 2024-03-30 thomas }
852 db642191 2024-03-30 thomas
853 3efd8e31 2022-10-23 thomas const struct got_error *
854 3efd8e31 2022-10-23 thomas got_object_open_as_blob(struct got_blob_object **blob,
855 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id, size_t blocksize,
856 3efd8e31 2022-10-23 thomas int outfd)
857 3efd8e31 2022-10-23 thomas {
858 db642191 2024-03-30 thomas return open_blob(blob, repo, id, blocksize, outfd);
859 3efd8e31 2022-10-23 thomas }
860 3efd8e31 2022-10-23 thomas
861 3efd8e31 2022-10-23 thomas const struct got_error *
862 3efd8e31 2022-10-23 thomas got_object_blob_open(struct got_blob_object **blob,
863 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj, size_t blocksize,
864 3efd8e31 2022-10-23 thomas int outfd)
865 3efd8e31 2022-10-23 thomas {
866 db642191 2024-03-30 thomas return open_blob(blob, repo, got_object_get_id(obj), blocksize, outfd);
867 3efd8e31 2022-10-23 thomas }
868 3efd8e31 2022-10-23 thomas
869 3efd8e31 2022-10-23 thomas static const struct got_error *
870 3efd8e31 2022-10-23 thomas open_tag(struct got_tag_object **tag, struct got_repository *repo,
871 3efd8e31 2022-10-23 thomas struct got_object_id *id, int check_cache)
872 3efd8e31 2022-10-23 thomas {
873 3efd8e31 2022-10-23 thomas const struct got_error *err = NULL;
874 3efd8e31 2022-10-23 thomas struct got_packidx *packidx = NULL;
875 3efd8e31 2022-10-23 thomas int idx;
876 3efd8e31 2022-10-23 thomas char *path_packfile = NULL;
877 3efd8e31 2022-10-23 thomas struct got_object *obj = NULL;
878 3efd8e31 2022-10-23 thomas int obj_type = GOT_OBJ_TYPE_ANY;
879 3efd8e31 2022-10-23 thomas
880 3efd8e31 2022-10-23 thomas if (check_cache) {
881 3efd8e31 2022-10-23 thomas *tag = got_repo_get_cached_tag(repo, id);
882 3efd8e31 2022-10-23 thomas if (*tag != NULL) {
883 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
884 3efd8e31 2022-10-23 thomas return NULL;
885 3efd8e31 2022-10-23 thomas }
886 3efd8e31 2022-10-23 thomas } else
887 3efd8e31 2022-10-23 thomas *tag = NULL;
888 3efd8e31 2022-10-23 thomas
889 3efd8e31 2022-10-23 thomas err = got_repo_search_packidx(&packidx, &idx, repo, id);
890 3efd8e31 2022-10-23 thomas if (err == NULL) {
891 3efd8e31 2022-10-23 thomas struct got_pack *pack = NULL;
892 3efd8e31 2022-10-23 thomas uint8_t *buf = NULL;
893 3efd8e31 2022-10-23 thomas size_t len;
894 3efd8e31 2022-10-23 thomas
895 3efd8e31 2022-10-23 thomas err = got_packidx_get_packfile_path(&path_packfile,
896 3efd8e31 2022-10-23 thomas packidx->path_packidx);
897 3efd8e31 2022-10-23 thomas if (err)
898 3efd8e31 2022-10-23 thomas return err;
899 3efd8e31 2022-10-23 thomas
900 3efd8e31 2022-10-23 thomas pack = got_repo_get_cached_pack(repo, path_packfile);
901 3efd8e31 2022-10-23 thomas if (pack == NULL) {
902 3efd8e31 2022-10-23 thomas err = got_repo_cache_pack(&pack, repo, path_packfile,
903 3efd8e31 2022-10-23 thomas packidx);
904 3efd8e31 2022-10-23 thomas if (err)
905 3efd8e31 2022-10-23 thomas goto done;
906 3efd8e31 2022-10-23 thomas }
907 3efd8e31 2022-10-23 thomas
908 3efd8e31 2022-10-23 thomas /* Beware of "lightweight" tags: Check object type first. */
909 3efd8e31 2022-10-23 thomas err = got_packfile_open_object(&obj, pack, packidx, idx, id);
910 3efd8e31 2022-10-23 thomas if (err)
911 3efd8e31 2022-10-23 thomas goto done;
912 3efd8e31 2022-10-23 thomas obj_type = obj->type;
913 3efd8e31 2022-10-23 thomas if (obj_type != GOT_OBJ_TYPE_TAG) {
914 3efd8e31 2022-10-23 thomas err = got_error(GOT_ERR_OBJ_TYPE);
915 3efd8e31 2022-10-23 thomas got_object_close(obj);
916 3efd8e31 2022-10-23 thomas goto done;
917 3efd8e31 2022-10-23 thomas }
918 3efd8e31 2022-10-23 thomas err = got_packfile_extract_object_to_mem(&buf, &len,
919 3efd8e31 2022-10-23 thomas obj, pack);
920 3efd8e31 2022-10-23 thomas got_object_close(obj);
921 3efd8e31 2022-10-23 thomas if (err)
922 3efd8e31 2022-10-23 thomas goto done;
923 3efd8e31 2022-10-23 thomas err = got_object_parse_tag(tag, buf, len);
924 3efd8e31 2022-10-23 thomas free(buf);
925 3efd8e31 2022-10-23 thomas } else if (err->code == GOT_ERR_NO_OBJ) {
926 3efd8e31 2022-10-23 thomas int fd;
927 3efd8e31 2022-10-23 thomas
928 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
929 3efd8e31 2022-10-23 thomas if (err)
930 3efd8e31 2022-10-23 thomas return err;
931 3efd8e31 2022-10-23 thomas err = got_object_read_header(&obj, fd);
932 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
933 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
934 3efd8e31 2022-10-23 thomas if (err)
935 3efd8e31 2022-10-23 thomas return err;
936 3efd8e31 2022-10-23 thomas obj_type = obj->type;
937 3efd8e31 2022-10-23 thomas got_object_close(obj);
938 3efd8e31 2022-10-23 thomas if (obj_type != GOT_OBJ_TYPE_TAG)
939 3efd8e31 2022-10-23 thomas return got_error(GOT_ERR_OBJ_TYPE);
940 3efd8e31 2022-10-23 thomas
941 3efd8e31 2022-10-23 thomas err = got_object_open_loose_fd(&fd, id, repo);
942 3efd8e31 2022-10-23 thomas if (err)
943 3efd8e31 2022-10-23 thomas return err;
944 3efd8e31 2022-10-23 thomas err = got_object_read_tag(tag, fd, id, 0);
945 3efd8e31 2022-10-23 thomas if (close(fd) == -1 && err == NULL)
946 3efd8e31 2022-10-23 thomas err = got_error_from_errno("close");
947 3efd8e31 2022-10-23 thomas if (err)
948 3efd8e31 2022-10-23 thomas return err;
949 3efd8e31 2022-10-23 thomas }
950 3efd8e31 2022-10-23 thomas
951 3efd8e31 2022-10-23 thomas if (err == NULL) {
952 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
953 3efd8e31 2022-10-23 thomas err = got_repo_cache_tag(repo, id, *tag);
954 3efd8e31 2022-10-23 thomas if (err) {
955 3efd8e31 2022-10-23 thomas if (err->code == GOT_ERR_OBJ_EXISTS ||
956 3efd8e31 2022-10-23 thomas err->code == GOT_ERR_OBJ_TOO_LARGE)
957 3efd8e31 2022-10-23 thomas err = NULL;
958 3efd8e31 2022-10-23 thomas }
959 3efd8e31 2022-10-23 thomas }
960 3efd8e31 2022-10-23 thomas done:
961 3efd8e31 2022-10-23 thomas free(path_packfile);
962 3efd8e31 2022-10-23 thomas return err;
963 3efd8e31 2022-10-23 thomas }
964 3efd8e31 2022-10-23 thomas
965 3efd8e31 2022-10-23 thomas const struct got_error *
966 3efd8e31 2022-10-23 thomas got_object_open_as_tag(struct got_tag_object **tag,
967 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object_id *id)
968 3efd8e31 2022-10-23 thomas {
969 3efd8e31 2022-10-23 thomas *tag = got_repo_get_cached_tag(repo, id);
970 3efd8e31 2022-10-23 thomas if (*tag != NULL) {
971 3efd8e31 2022-10-23 thomas (*tag)->refcnt++;
972 3efd8e31 2022-10-23 thomas return NULL;
973 3efd8e31 2022-10-23 thomas }
974 3efd8e31 2022-10-23 thomas
975 3efd8e31 2022-10-23 thomas return open_tag(tag, repo, id, 0);
976 3efd8e31 2022-10-23 thomas }
977 3efd8e31 2022-10-23 thomas
978 3efd8e31 2022-10-23 thomas const struct got_error *
979 3efd8e31 2022-10-23 thomas got_object_tag_open(struct got_tag_object **tag,
980 3efd8e31 2022-10-23 thomas struct got_repository *repo, struct got_object *obj)
981 3efd8e31 2022-10-23 thomas {
982 3efd8e31 2022-10-23 thomas return open_tag(tag, repo, got_object_get_id(obj), 1);
983 3efd8e31 2022-10-23 thomas }