File: | libexec/got-read-pack/got-read-pack.c |
Warning: | line 687, column 7 Array access (from variable 'path') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org> | |||
3 | * | |||
4 | * Permission to use, copy, modify, and distribute this software for any | |||
5 | * purpose with or without fee is hereby granted, provided that the above | |||
6 | * copyright notice and this permission notice appear in all copies. | |||
7 | * | |||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
15 | */ | |||
16 | ||||
17 | #include <sys/types.h> | |||
18 | #include <sys/queue.h> | |||
19 | #include <sys/uio.h> | |||
20 | #include <sys/time.h> | |||
21 | #include <sys/mman.h> | |||
22 | ||||
23 | #include <limits.h> | |||
24 | #include <signal.h> | |||
25 | #include <stdint.h> | |||
26 | #include <imsg.h> | |||
27 | #include <stdio.h> | |||
28 | #include <stdlib.h> | |||
29 | #include <string.h> | |||
30 | #include <sha1.h> | |||
31 | #include <unistd.h> | |||
32 | #include <zlib.h> | |||
33 | ||||
34 | #include "got_error.h" | |||
35 | #include "got_object.h" | |||
36 | #include "got_path.h" | |||
37 | ||||
38 | #include "got_lib_delta.h" | |||
39 | #include "got_lib_delta_cache.h" | |||
40 | #include "got_lib_object.h" | |||
41 | #include "got_lib_object_cache.h" | |||
42 | #include "got_lib_object_parse.h" | |||
43 | #include "got_lib_privsep.h" | |||
44 | #include "got_lib_pack.h" | |||
45 | ||||
46 | static volatile sig_atomic_t sigint_received; | |||
47 | ||||
48 | static void | |||
49 | catch_sigint(int signo) | |||
50 | { | |||
51 | sigint_received = 1; | |||
52 | } | |||
53 | ||||
54 | static const struct got_error * | |||
55 | open_object(struct got_object **obj, struct got_pack *pack, | |||
56 | struct got_packidx *packidx, int idx, struct got_object_id *id, | |||
57 | struct got_object_cache *objcache) | |||
58 | { | |||
59 | const struct got_error *err; | |||
60 | ||||
61 | err = got_packfile_open_object(obj, pack, packidx, idx, id); | |||
62 | if (err) | |||
63 | return err; | |||
64 | (*obj)->refcnt++; | |||
65 | ||||
66 | err = got_object_cache_add(objcache, id, *obj); | |||
67 | if (err) { | |||
68 | if (err->code == GOT_ERR_OBJ_EXISTS43 || | |||
69 | err->code == GOT_ERR_OBJ_TOO_LARGE78) | |||
70 | err = NULL((void *)0); | |||
71 | return err; | |||
72 | } | |||
73 | (*obj)->refcnt++; | |||
74 | return NULL((void *)0); | |||
75 | } | |||
76 | ||||
77 | static const struct got_error * | |||
78 | object_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack, | |||
79 | struct got_packidx *packidx, struct got_object_cache *objcache) | |||
80 | { | |||
81 | const struct got_error *err = NULL((void *)0); | |||
82 | struct got_imsg_packed_object iobj; | |||
83 | struct got_object *obj; | |||
84 | struct got_object_id id; | |||
85 | size_t datalen; | |||
86 | ||||
87 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
88 | if (datalen != sizeof(iobj)) | |||
89 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
90 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
91 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
92 | ||||
93 | obj = got_object_cache_get(objcache, &id); | |||
94 | if (obj) { | |||
95 | obj->refcnt++; | |||
96 | } else { | |||
97 | err = open_object(&obj, pack, packidx, iobj.idx, &id, | |||
98 | objcache); | |||
99 | if (err) | |||
100 | goto done; | |||
101 | } | |||
102 | ||||
103 | err = got_privsep_send_obj(ibuf, obj); | |||
104 | done: | |||
105 | got_object_close(obj); | |||
106 | return err; | |||
107 | } | |||
108 | ||||
109 | const struct got_error * | |||
110 | open_commit(struct got_commit_object **commit, struct got_pack *pack, | |||
111 | struct got_packidx *packidx, int obj_idx, struct got_object_id *id, | |||
112 | struct got_object_cache *objcache) | |||
113 | { | |||
114 | const struct got_error *err = NULL((void *)0); | |||
115 | struct got_object *obj = NULL((void *)0); | |||
116 | uint8_t *buf = NULL((void *)0); | |||
117 | size_t len; | |||
118 | ||||
119 | *commit = NULL((void *)0); | |||
120 | ||||
121 | obj = got_object_cache_get(objcache, id); | |||
122 | if (obj) { | |||
123 | obj->refcnt++; | |||
124 | } else { | |||
125 | err = open_object(&obj, pack, packidx, obj_idx, id, | |||
126 | objcache); | |||
127 | if (err) | |||
128 | return err; | |||
129 | } | |||
130 | ||||
131 | err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack); | |||
132 | if (err) | |||
133 | goto done; | |||
134 | ||||
135 | obj->size = len; | |||
136 | ||||
137 | err = got_object_parse_commit(commit, buf, len); | |||
138 | done: | |||
139 | got_object_close(obj); | |||
140 | free(buf); | |||
141 | return err; | |||
142 | } | |||
143 | ||||
144 | static const struct got_error * | |||
145 | commit_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack, | |||
146 | struct got_packidx *packidx, struct got_object_cache *objcache) | |||
147 | { | |||
148 | const struct got_error *err = NULL((void *)0); | |||
149 | struct got_imsg_packed_object iobj; | |||
150 | struct got_commit_object *commit = NULL((void *)0); | |||
151 | struct got_object_id id; | |||
152 | size_t datalen; | |||
153 | ||||
154 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
155 | if (datalen != sizeof(iobj)) | |||
156 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
157 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
158 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
159 | ||||
160 | err = open_commit(&commit, pack, packidx, iobj.idx, &id, objcache); | |||
161 | if (err) | |||
162 | goto done; | |||
163 | ||||
164 | err = got_privsep_send_commit(ibuf, commit); | |||
165 | done: | |||
166 | if (commit) | |||
167 | got_object_commit_close(commit); | |||
168 | if (err) { | |||
169 | if (err->code == GOT_ERR_PRIVSEP_PIPE37) | |||
170 | err = NULL((void *)0); | |||
171 | else | |||
172 | got_privsep_send_error(ibuf, err); | |||
173 | } | |||
174 | ||||
175 | return err; | |||
176 | } | |||
177 | ||||
178 | const struct got_error * | |||
179 | open_tree(uint8_t **buf, struct got_pathlist_head *entries, int *nentries, | |||
180 | struct got_pack *pack, struct got_packidx *packidx, int obj_idx, | |||
181 | struct got_object_id *id, struct got_object_cache *objcache) | |||
182 | { | |||
183 | const struct got_error *err = NULL((void *)0); | |||
184 | struct got_object *obj = NULL((void *)0); | |||
185 | size_t len; | |||
186 | ||||
187 | *buf = NULL((void *)0); | |||
188 | *nentries = 0; | |||
189 | ||||
190 | obj = got_object_cache_get(objcache, id); | |||
191 | if (obj) { | |||
192 | obj->refcnt++; | |||
193 | } else { | |||
194 | err = open_object(&obj, pack, packidx, obj_idx, id, | |||
195 | objcache); | |||
196 | if (err) | |||
197 | return err; | |||
198 | } | |||
199 | ||||
200 | err = got_packfile_extract_object_to_mem(buf, &len, obj, pack); | |||
201 | if (err) | |||
202 | goto done; | |||
203 | ||||
204 | obj->size = len; | |||
205 | ||||
206 | err = got_object_parse_tree(entries, nentries, *buf, len); | |||
207 | done: | |||
208 | got_object_close(obj); | |||
209 | if (err) { | |||
210 | free(*buf); | |||
211 | *buf = NULL((void *)0); | |||
212 | } | |||
213 | return err; | |||
214 | } | |||
215 | ||||
216 | static const struct got_error * | |||
217 | tree_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack, | |||
218 | struct got_packidx *packidx, struct got_object_cache *objcache) | |||
219 | { | |||
220 | const struct got_error *err = NULL((void *)0); | |||
221 | struct got_imsg_packed_object iobj; | |||
222 | struct got_pathlist_head entries; | |||
223 | int nentries = 0; | |||
224 | uint8_t *buf = NULL((void *)0); | |||
225 | struct got_object_id id; | |||
226 | size_t datalen; | |||
227 | ||||
228 | TAILQ_INIT(&entries)do { (&entries)->tqh_first = ((void *)0); (&entries )->tqh_last = &(&entries)->tqh_first; } while ( 0); | |||
229 | ||||
230 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
231 | if (datalen != sizeof(iobj)) | |||
232 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
233 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
234 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
235 | ||||
236 | err = open_tree(&buf, &entries, &nentries, pack, packidx, iobj.idx, | |||
237 | &id, objcache); | |||
238 | if (err) | |||
239 | return err; | |||
240 | ||||
241 | err = got_privsep_send_tree(ibuf, &entries, nentries); | |||
242 | got_object_parsed_tree_entries_free(&entries); | |||
243 | free(buf); | |||
244 | if (err) { | |||
245 | if (err->code == GOT_ERR_PRIVSEP_PIPE37) | |||
246 | err = NULL((void *)0); | |||
247 | else | |||
248 | got_privsep_send_error(ibuf, err); | |||
249 | } | |||
250 | ||||
251 | return err; | |||
252 | } | |||
253 | ||||
254 | static const struct got_error * | |||
255 | receive_file(FILE **f, struct imsgbuf *ibuf, int imsg_code) | |||
256 | { | |||
257 | const struct got_error *err; | |||
258 | struct imsg imsg; | |||
259 | size_t datalen; | |||
260 | ||||
261 | err = got_privsep_recv_imsg(&imsg, ibuf, 0); | |||
262 | if (err) | |||
263 | return err; | |||
264 | ||||
265 | if (imsg.hdr.type != imsg_code) { | |||
266 | err = got_error(GOT_ERR_PRIVSEP_MSG39); | |||
267 | goto done; | |||
268 | } | |||
269 | ||||
270 | datalen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
271 | if (datalen != 0) { | |||
272 | err = got_error(GOT_ERR_PRIVSEP_LEN36); | |||
273 | goto done; | |||
274 | } | |||
275 | if (imsg.fd == -1) { | |||
276 | err = got_error(GOT_ERR_PRIVSEP_NO_FD38); | |||
277 | goto done; | |||
278 | } | |||
279 | ||||
280 | *f = fdopen(imsg.fd, "w+"); | |||
281 | if (*f == NULL((void *)0)) { | |||
282 | err = got_error_from_errno("fdopen"); | |||
283 | close(imsg.fd); | |||
284 | goto done; | |||
285 | } | |||
286 | done: | |||
287 | imsg_free(&imsg); | |||
288 | return err; | |||
289 | } | |||
290 | ||||
291 | static const struct got_error * | |||
292 | blob_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack, | |||
293 | struct got_packidx *packidx, struct got_object_cache *objcache) | |||
294 | { | |||
295 | const struct got_error *err = NULL((void *)0); | |||
296 | struct got_imsg_packed_object iobj; | |||
297 | struct got_object *obj = NULL((void *)0); | |||
298 | FILE *outfile = NULL((void *)0), *basefile = NULL((void *)0), *accumfile = NULL((void *)0); | |||
299 | struct got_object_id id; | |||
300 | size_t datalen; | |||
301 | uint64_t blob_size; | |||
302 | uint8_t *buf = NULL((void *)0); | |||
303 | ||||
304 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
305 | if (datalen != sizeof(iobj)) | |||
306 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
307 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
308 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
309 | ||||
310 | obj = got_object_cache_get(objcache, &id); | |||
311 | if (obj) { | |||
312 | obj->refcnt++; | |||
313 | } else { | |||
314 | err = open_object(&obj, pack, packidx, iobj.idx, &id, | |||
315 | objcache); | |||
316 | if (err) | |||
317 | return err; | |||
318 | } | |||
319 | ||||
320 | err = receive_file(&outfile, ibuf, GOT_IMSG_BLOB_OUTFD); | |||
321 | if (err) | |||
322 | goto done; | |||
323 | err = receive_file(&basefile, ibuf, GOT_IMSG_TMPFD); | |||
324 | if (err) | |||
325 | goto done; | |||
326 | err = receive_file(&accumfile, ibuf, GOT_IMSG_TMPFD); | |||
327 | if (err) | |||
328 | goto done; | |||
329 | ||||
330 | if (obj->flags & GOT_OBJ_FLAG_DELTIFIED0x02) { | |||
331 | err = got_pack_get_max_delta_object_size(&blob_size, obj, pack); | |||
332 | if (err) | |||
333 | goto done; | |||
334 | } else | |||
335 | blob_size = obj->size; | |||
336 | ||||
337 | if (blob_size <= GOT_PRIVSEP_INLINE_BLOB_DATA_MAX(16384 - sizeof(struct imsg_hdr) - sizeof(struct got_imsg_blob ))) | |||
338 | err = got_packfile_extract_object_to_mem(&buf, &obj->size, | |||
339 | obj, pack); | |||
340 | else | |||
341 | err = got_packfile_extract_object(pack, obj, outfile, basefile, | |||
342 | accumfile); | |||
343 | if (err) | |||
344 | goto done; | |||
345 | ||||
346 | err = got_privsep_send_blob(ibuf, obj->size, obj->hdrlen, buf); | |||
347 | done: | |||
348 | free(buf); | |||
349 | if (outfile && fclose(outfile) == EOF(-1) && err == NULL((void *)0)) | |||
350 | err = got_error_from_errno("fclose"); | |||
351 | if (basefile && fclose(basefile) == EOF(-1) && err == NULL((void *)0)) | |||
352 | err = got_error_from_errno("fclose"); | |||
353 | if (accumfile && fclose(accumfile) == EOF(-1) && err == NULL((void *)0)) | |||
354 | err = got_error_from_errno("fclose"); | |||
355 | got_object_close(obj); | |||
356 | if (err && err->code != GOT_ERR_PRIVSEP_PIPE37) | |||
357 | got_privsep_send_error(ibuf, err); | |||
358 | ||||
359 | return err; | |||
360 | } | |||
361 | ||||
362 | static const struct got_error * | |||
363 | tag_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack, | |||
364 | struct got_packidx *packidx, struct got_object_cache *objcache) | |||
365 | { | |||
366 | const struct got_error *err = NULL((void *)0); | |||
367 | struct got_imsg_packed_object iobj; | |||
368 | struct got_object *obj = NULL((void *)0); | |||
369 | struct got_tag_object *tag = NULL((void *)0); | |||
370 | uint8_t *buf = NULL((void *)0); | |||
371 | size_t len; | |||
372 | struct got_object_id id; | |||
373 | size_t datalen; | |||
374 | ||||
375 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
376 | if (datalen != sizeof(iobj)) | |||
377 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
378 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
379 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
380 | ||||
381 | obj = got_object_cache_get(objcache, &id); | |||
382 | if (obj) { | |||
383 | obj->refcnt++; | |||
384 | } else { | |||
385 | err = open_object(&obj, pack, packidx, iobj.idx, &id, | |||
386 | objcache); | |||
387 | if (err) | |||
388 | return err; | |||
389 | } | |||
390 | ||||
391 | err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack); | |||
392 | if (err) | |||
393 | goto done; | |||
394 | ||||
395 | obj->size = len; | |||
396 | err = got_object_parse_tag(&tag, buf, len); | |||
397 | if (err) | |||
398 | goto done; | |||
399 | ||||
400 | err = got_privsep_send_tag(ibuf, tag); | |||
401 | done: | |||
402 | free(buf); | |||
403 | got_object_close(obj); | |||
404 | if (tag) | |||
405 | got_object_tag_close(tag); | |||
406 | if (err) { | |||
407 | if (err->code == GOT_ERR_PRIVSEP_PIPE37) | |||
408 | err = NULL((void *)0); | |||
409 | else | |||
410 | got_privsep_send_error(ibuf, err); | |||
411 | } | |||
412 | ||||
413 | return err; | |||
414 | } | |||
415 | ||||
416 | static struct got_parsed_tree_entry * | |||
417 | find_entry_by_name(struct got_pathlist_head *entries, int nentries, | |||
418 | const char *name, size_t len) | |||
419 | { | |||
420 | struct got_pathlist_entry *pe; | |||
421 | ||||
422 | /* Note that tree entries are sorted in strncmp() order. */ | |||
423 | TAILQ_FOREACH(pe, entries, entry)for((pe) = ((entries)->tqh_first); (pe) != ((void *)0); (pe ) = ((pe)->entry.tqe_next)) { | |||
424 | int cmp = strncmp(pe->path, name, len); | |||
425 | if (cmp < 0) | |||
426 | continue; | |||
427 | if (cmp > 0) | |||
428 | break; | |||
429 | if (pe->path[len] == '\0') | |||
430 | return (struct got_parsed_tree_entry *)pe->data; | |||
431 | } | |||
432 | return NULL((void *)0); | |||
433 | } | |||
434 | ||||
435 | const struct got_error * | |||
436 | tree_path_changed(int *changed, uint8_t **buf1, uint8_t **buf2, | |||
437 | struct got_pathlist_head *entries1, int *nentries1, | |||
438 | struct got_pathlist_head *entries2, int *nentries2, | |||
439 | const char *path, struct got_pack *pack, struct got_packidx *packidx, | |||
440 | struct imsgbuf *ibuf, struct got_object_cache *objcache) | |||
441 | { | |||
442 | const struct got_error *err = NULL((void *)0); | |||
443 | struct got_parsed_tree_entry *pte1 = NULL((void *)0), *pte2 = NULL((void *)0); | |||
444 | const char *seg, *s; | |||
445 | size_t seglen; | |||
446 | ||||
447 | *changed = 0; | |||
448 | ||||
449 | /* We not do support comparing the root path. */ | |||
450 | if (got_path_is_root_dir(path)) | |||
451 | return got_error_path(path, GOT_ERR_BAD_PATH4); | |||
452 | ||||
453 | s = path; | |||
454 | while (*s == '/') | |||
455 | s++; | |||
456 | seg = s; | |||
457 | seglen = 0; | |||
458 | while (*s) { | |||
459 | if (*s != '/') { | |||
460 | s++; | |||
461 | seglen++; | |||
462 | if (*s) | |||
463 | continue; | |||
464 | } | |||
465 | ||||
466 | pte1 = find_entry_by_name(entries1, *nentries1, seg, seglen); | |||
467 | if (pte1 == NULL((void *)0)) { | |||
468 | err = got_error(GOT_ERR_NO_OBJ17); | |||
469 | break; | |||
470 | } | |||
471 | ||||
472 | pte2 = find_entry_by_name(entries2, *nentries2, seg, seglen); | |||
473 | if (pte2 == NULL((void *)0)) { | |||
474 | *changed = 1; | |||
475 | break; | |||
476 | } | |||
477 | ||||
478 | if (pte1->mode != pte2->mode) { | |||
479 | *changed = 1; | |||
480 | break; | |||
481 | } | |||
482 | ||||
483 | if (memcmp(pte1->id, pte2->id, SHA1_DIGEST_LENGTH20) == 0) { | |||
484 | *changed = 0; | |||
485 | break; | |||
486 | } | |||
487 | ||||
488 | if (*s == '\0') { /* final path element */ | |||
489 | *changed = 1; | |||
490 | break; | |||
491 | } | |||
492 | ||||
493 | seg = s + 1; | |||
494 | s++; | |||
495 | seglen = 0; | |||
496 | if (*s) { | |||
497 | struct got_object_id id1, id2; | |||
498 | int idx; | |||
499 | ||||
500 | memcpy(id1.sha1, pte1->id, SHA1_DIGEST_LENGTH20); | |||
501 | idx = got_packidx_get_object_idx(packidx, &id1); | |||
502 | if (idx == -1) { | |||
503 | err = got_error_no_obj(&id1); | |||
504 | break; | |||
505 | } | |||
506 | got_object_parsed_tree_entries_free(entries1); | |||
507 | *nentries1 = 0; | |||
508 | free(*buf1); | |||
509 | *buf1 = NULL((void *)0); | |||
510 | err = open_tree(buf1, entries1, nentries1, pack, | |||
511 | packidx, idx, &id1, objcache); | |||
512 | pte1 = NULL((void *)0); | |||
513 | if (err) | |||
514 | break; | |||
515 | ||||
516 | memcpy(id2.sha1, pte2->id, SHA1_DIGEST_LENGTH20); | |||
517 | idx = got_packidx_get_object_idx(packidx, &id2); | |||
518 | if (idx == -1) { | |||
519 | err = got_error_no_obj(&id2); | |||
520 | break; | |||
521 | } | |||
522 | got_object_parsed_tree_entries_free(entries2); | |||
523 | *nentries2 = 0; | |||
524 | free(*buf2); | |||
525 | *buf2 = NULL((void *)0); | |||
526 | err = open_tree(buf2, entries2, nentries2, pack, | |||
527 | packidx, idx, &id2, objcache); | |||
528 | pte2 = NULL((void *)0); | |||
529 | if (err) | |||
530 | break; | |||
531 | } | |||
532 | } | |||
533 | ||||
534 | return err; | |||
535 | } | |||
536 | ||||
537 | static const struct got_error * | |||
538 | send_traversed_commits(struct got_object_id *commit_ids, size_t ncommits, | |||
539 | struct imsgbuf *ibuf) | |||
540 | { | |||
541 | const struct got_error *err; | |||
542 | struct ibuf *wbuf; | |||
543 | int i; | |||
544 | ||||
545 | wbuf = imsg_create(ibuf, GOT_IMSG_TRAVERSED_COMMITS, 0, 0, | |||
546 | sizeof(struct got_imsg_traversed_commits) + | |||
547 | ncommits * SHA1_DIGEST_LENGTH20); | |||
548 | if (wbuf == NULL((void *)0)) | |||
549 | return got_error_from_errno("imsg_create TRAVERSED_COMMITS"); | |||
550 | ||||
551 | if (imsg_add(wbuf, &ncommits, sizeof(ncommits)) == -1) { | |||
552 | err = got_error_from_errno("imsg_add TRAVERSED_COMMITS"); | |||
553 | ibuf_free(wbuf); | |||
554 | return err; | |||
555 | } | |||
556 | for (i = 0; i < ncommits; i++) { | |||
557 | struct got_object_id *id = &commit_ids[i]; | |||
558 | if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH20) == -1) { | |||
559 | err = got_error_from_errno( | |||
560 | "imsg_add TRAVERSED_COMMITS"); | |||
561 | ibuf_free(wbuf); | |||
562 | return err; | |||
563 | } | |||
564 | } | |||
565 | ||||
566 | wbuf->fd = -1; | |||
567 | imsg_close(ibuf, wbuf); | |||
568 | ||||
569 | return got_privsep_flush_imsg(ibuf); | |||
570 | } | |||
571 | ||||
572 | static const struct got_error * | |||
573 | send_commit_traversal_done(struct imsgbuf *ibuf) | |||
574 | { | |||
575 | if (imsg_compose(ibuf, GOT_IMSG_COMMIT_TRAVERSAL_DONE, 0, 0, -1, | |||
576 | NULL((void *)0), 0) == -1) | |||
577 | return got_error_from_errno("imsg_compose TRAVERSAL_DONE"); | |||
578 | ||||
579 | return got_privsep_flush_imsg(ibuf); | |||
580 | } | |||
581 | ||||
582 | ||||
583 | static const struct got_error * | |||
584 | commit_traversal_request(struct imsg *imsg, struct imsgbuf *ibuf, | |||
585 | struct got_pack *pack, struct got_packidx *packidx, | |||
586 | struct got_object_cache *objcache) | |||
587 | { | |||
588 | const struct got_error *err = NULL((void *)0); | |||
589 | struct got_imsg_packed_object iobj; | |||
590 | struct got_object_qid *pid; | |||
591 | struct got_commit_object *commit = NULL((void *)0), *pcommit = NULL((void *)0); | |||
592 | struct got_pathlist_head entries, pentries; | |||
593 | int nentries = 0, pnentries = 0; | |||
594 | struct got_object_id id; | |||
595 | size_t datalen, path_len; | |||
596 | char *path = NULL((void *)0); | |||
597 | const int min_alloc = 64; | |||
598 | int changed = 0, ncommits = 0, nallocated = 0; | |||
599 | struct got_object_id *commit_ids = NULL((void *)0); | |||
600 | ||||
601 | TAILQ_INIT(&entries)do { (&entries)->tqh_first = ((void *)0); (&entries )->tqh_last = &(&entries)->tqh_first; } while ( 0); | |||
602 | TAILQ_INIT(&pentries)do { (&pentries)->tqh_first = ((void *)0); (&pentries )->tqh_last = &(&pentries)->tqh_first; } while ( 0); | |||
603 | ||||
604 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
605 | if (datalen < sizeof(iobj)) | |||
606 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
607 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
608 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
609 | ||||
610 | path_len = datalen - sizeof(iobj) - 1; | |||
611 | if (path_len
| |||
612 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
613 | if (path_len > 0) { | |||
614 | path = imsg->data + sizeof(iobj); | |||
615 | if (path[path_len] != '\0') | |||
616 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
617 | } | |||
618 | ||||
619 | nallocated = min_alloc; | |||
620 | commit_ids = reallocarray(NULL((void *)0), nallocated, sizeof(*commit_ids)); | |||
621 | if (commit_ids == NULL((void *)0)) | |||
622 | return got_error_from_errno("reallocarray"); | |||
623 | ||||
624 | do { | |||
625 | const size_t max_datalen = MAX_IMSGSIZE16384 - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
626 | int idx; | |||
627 | ||||
628 | if (sigint_received) { | |||
629 | err = got_error(GOT_ERR_CANCELLED49); | |||
630 | goto done; | |||
631 | } | |||
632 | ||||
633 | if (commit
| |||
634 | idx = got_packidx_get_object_idx(packidx, &id); | |||
635 | if (idx == -1) | |||
636 | break; | |||
637 | err = open_commit(&commit, pack, packidx, | |||
638 | idx, &id, objcache); | |||
639 | if (err) { | |||
640 | if (err->code != GOT_ERR_NO_OBJ17) | |||
641 | goto done; | |||
642 | err = NULL((void *)0); | |||
643 | break; | |||
644 | } | |||
645 | } | |||
646 | ||||
647 | if (sizeof(struct got_imsg_traversed_commits) + | |||
648 | ncommits * SHA1_DIGEST_LENGTH20 >= max_datalen) { | |||
649 | err = send_traversed_commits(commit_ids, ncommits, | |||
650 | ibuf); | |||
651 | if (err) | |||
652 | goto done; | |||
653 | ncommits = 0; | |||
654 | } | |||
655 | ncommits++; | |||
656 | if (ncommits
| |||
657 | struct got_object_id *new; | |||
658 | nallocated += min_alloc; | |||
659 | new = reallocarray(commit_ids, nallocated, | |||
660 | sizeof(*commit_ids)); | |||
661 | if (new == NULL((void *)0)) { | |||
662 | err = got_error_from_errno("reallocarray"); | |||
663 | goto done; | |||
664 | } | |||
665 | commit_ids = new; | |||
666 | } | |||
667 | memcpy(commit_ids[ncommits - 1].sha1, id.sha1, | |||
668 | SHA1_DIGEST_LENGTH20); | |||
669 | ||||
670 | pid = SIMPLEQ_FIRST(&commit->parent_ids)((&commit->parent_ids)->sqh_first); | |||
671 | if (pid == NULL((void *)0)) | |||
672 | break; | |||
673 | ||||
674 | idx = got_packidx_get_object_idx(packidx, pid->id); | |||
675 | if (idx == -1) | |||
676 | break; | |||
677 | ||||
678 | err = open_commit(&pcommit, pack, packidx, idx, pid->id, | |||
679 | objcache); | |||
680 | if (err) { | |||
681 | if (err->code != GOT_ERR_NO_OBJ17) | |||
682 | goto done; | |||
683 | err = NULL((void *)0); | |||
684 | break; | |||
685 | } | |||
686 | ||||
687 | if (path[0] == '/' && path[1] == '\0') { | |||
| ||||
688 | if (got_object_id_cmp(pcommit->tree_id, | |||
689 | commit->tree_id) != 0) { | |||
690 | changed = 1; | |||
691 | break; | |||
692 | } | |||
693 | } else { | |||
694 | int pidx; | |||
695 | uint8_t *buf = NULL((void *)0), *pbuf = NULL((void *)0); | |||
696 | ||||
697 | idx = got_packidx_get_object_idx(packidx, | |||
698 | commit->tree_id); | |||
699 | if (idx == -1) | |||
700 | break; | |||
701 | pidx = got_packidx_get_object_idx(packidx, | |||
702 | pcommit->tree_id); | |||
703 | if (pidx == -1) | |||
704 | break; | |||
705 | ||||
706 | err = open_tree(&buf, &entries, &nentries, pack, | |||
707 | packidx, idx, commit->tree_id, objcache); | |||
708 | if (err) | |||
709 | goto done; | |||
710 | err = open_tree(&pbuf, &pentries, &pnentries, pack, | |||
711 | packidx, pidx, pcommit->tree_id, objcache); | |||
712 | if (err) { | |||
713 | free(buf); | |||
714 | goto done; | |||
715 | } | |||
716 | ||||
717 | err = tree_path_changed(&changed, &buf, &pbuf, | |||
718 | &entries, &nentries, &pentries, &pnentries, path, | |||
719 | pack, packidx, ibuf, objcache); | |||
720 | ||||
721 | got_object_parsed_tree_entries_free(&entries); | |||
722 | nentries = 0; | |||
723 | free(buf); | |||
724 | got_object_parsed_tree_entries_free(&pentries); | |||
725 | pnentries = 0; | |||
726 | free(pbuf); | |||
727 | if (err) { | |||
728 | if (err->code != GOT_ERR_NO_OBJ17) | |||
729 | goto done; | |||
730 | err = NULL((void *)0); | |||
731 | break; | |||
732 | } | |||
733 | } | |||
734 | ||||
735 | if (!changed) { | |||
736 | memcpy(id.sha1, pid->id->sha1, SHA1_DIGEST_LENGTH20); | |||
737 | got_object_commit_close(commit); | |||
738 | commit = pcommit; | |||
739 | pcommit = NULL((void *)0); | |||
740 | } | |||
741 | } while (!changed); | |||
742 | ||||
743 | if (ncommits > 0) { | |||
744 | err = send_traversed_commits(commit_ids, ncommits, ibuf); | |||
745 | if (err) | |||
746 | goto done; | |||
747 | ||||
748 | if (changed) { | |||
749 | err = got_privsep_send_commit(ibuf, commit); | |||
750 | if (err) | |||
751 | goto done; | |||
752 | } | |||
753 | } | |||
754 | err = send_commit_traversal_done(ibuf); | |||
755 | done: | |||
756 | free(commit_ids); | |||
757 | if (commit) | |||
758 | got_object_commit_close(commit); | |||
759 | if (pcommit) | |||
760 | got_object_commit_close(pcommit); | |||
761 | if (nentries != 0) | |||
762 | got_object_parsed_tree_entries_free(&entries); | |||
763 | if (pnentries != 0) | |||
764 | got_object_parsed_tree_entries_free(&pentries); | |||
765 | if (err) { | |||
766 | if (err->code == GOT_ERR_PRIVSEP_PIPE37) | |||
767 | err = NULL((void *)0); | |||
768 | else | |||
769 | got_privsep_send_error(ibuf, err); | |||
770 | } | |||
771 | ||||
772 | return err; | |||
773 | } | |||
774 | ||||
775 | static const struct got_error * | |||
776 | raw_object_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack, | |||
777 | struct got_packidx *packidx, struct got_object_cache *objcache) | |||
778 | { | |||
779 | const struct got_error *err = NULL((void *)0); | |||
780 | uint8_t *buf = NULL((void *)0); | |||
781 | uint64_t size = 0; | |||
782 | FILE *outfile = NULL((void *)0), *basefile = NULL((void *)0), *accumfile = NULL((void *)0); | |||
783 | struct got_imsg_packed_object iobj; | |||
784 | struct got_object *obj; | |||
785 | struct got_object_id id; | |||
786 | size_t datalen; | |||
787 | ||||
788 | datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
789 | if (datalen != sizeof(iobj)) | |||
790 | return got_error(GOT_ERR_PRIVSEP_LEN36); | |||
791 | memcpy(&iobj, imsg->data, sizeof(iobj)); | |||
792 | memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH20); | |||
793 | ||||
794 | obj = got_object_cache_get(objcache, &id); | |||
795 | if (obj) { | |||
796 | obj->refcnt++; | |||
797 | } else { | |||
798 | err = open_object(&obj, pack, packidx, iobj.idx, &id, | |||
799 | objcache); | |||
800 | if (err) | |||
801 | return err; | |||
802 | } | |||
803 | ||||
804 | err = receive_file(&outfile, ibuf, GOT_IMSG_RAW_OBJECT_OUTFD); | |||
805 | if (err) | |||
806 | return err; | |||
807 | err = receive_file(&basefile, ibuf, GOT_IMSG_TMPFD); | |||
808 | if (err) | |||
809 | goto done; | |||
810 | err = receive_file(&accumfile, ibuf, GOT_IMSG_TMPFD); | |||
811 | if (err) | |||
812 | goto done; | |||
813 | ||||
814 | if (obj->flags & GOT_OBJ_FLAG_DELTIFIED0x02) { | |||
815 | err = got_pack_get_max_delta_object_size(&size, obj, pack); | |||
816 | if (err) | |||
817 | goto done; | |||
818 | } else | |||
819 | size = obj->size; | |||
820 | ||||
821 | if (size <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX(16384 - sizeof(struct imsg_hdr) - sizeof(struct got_imsg_raw_obj ))) | |||
822 | err = got_packfile_extract_object_to_mem(&buf, &obj->size, | |||
823 | obj, pack); | |||
824 | else | |||
825 | err = got_packfile_extract_object(pack, obj, outfile, basefile, | |||
826 | accumfile); | |||
827 | if (err) | |||
828 | goto done; | |||
829 | ||||
830 | err = got_privsep_send_raw_obj(ibuf, size, obj->hdrlen, buf); | |||
831 | done: | |||
832 | free(buf); | |||
833 | if (outfile && fclose(outfile) == EOF(-1) && err == NULL((void *)0)) | |||
834 | err = got_error_from_errno("fclose"); | |||
835 | if (basefile && fclose(basefile) == EOF(-1) && err == NULL((void *)0)) | |||
836 | err = got_error_from_errno("fclose"); | |||
837 | if (accumfile && fclose(accumfile) == EOF(-1) && err == NULL((void *)0)) | |||
838 | err = got_error_from_errno("fclose"); | |||
839 | got_object_close(obj); | |||
840 | if (err && err->code != GOT_ERR_PRIVSEP_PIPE37) | |||
841 | got_privsep_send_error(ibuf, err); | |||
842 | ||||
843 | return err; | |||
844 | } | |||
845 | ||||
846 | ||||
847 | ||||
848 | static const struct got_error * | |||
849 | receive_packidx(struct got_packidx **packidx, struct imsgbuf *ibuf) | |||
850 | { | |||
851 | const struct got_error *err = NULL((void *)0); | |||
852 | struct imsg imsg; | |||
853 | struct got_imsg_packidx ipackidx; | |||
854 | size_t datalen; | |||
855 | struct got_packidx *p; | |||
856 | ||||
857 | *packidx = NULL((void *)0); | |||
858 | ||||
859 | err = got_privsep_recv_imsg(&imsg, ibuf, 0); | |||
860 | if (err) | |||
861 | return err; | |||
862 | ||||
863 | p = calloc(1, sizeof(*p)); | |||
864 | if (p == NULL((void *)0)) { | |||
865 | err = got_error_from_errno("calloc"); | |||
866 | goto done; | |||
867 | } | |||
868 | ||||
869 | if (imsg.hdr.type != GOT_IMSG_PACKIDX) { | |||
870 | err = got_error(GOT_ERR_PRIVSEP_MSG39); | |||
871 | goto done; | |||
872 | } | |||
873 | ||||
874 | if (imsg.fd == -1) { | |||
875 | err = got_error(GOT_ERR_PRIVSEP_NO_FD38); | |||
876 | goto done; | |||
877 | } | |||
878 | ||||
879 | datalen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
880 | if (datalen != sizeof(ipackidx)) { | |||
881 | err = got_error(GOT_ERR_PRIVSEP_LEN36); | |||
882 | goto done; | |||
883 | } | |||
884 | memcpy(&ipackidx, imsg.data, sizeof(ipackidx)); | |||
885 | ||||
886 | p->len = ipackidx.len; | |||
887 | p->fd = dup(imsg.fd); | |||
888 | if (p->fd == -1) { | |||
889 | err = got_error_from_errno("dup"); | |||
890 | goto done; | |||
891 | } | |||
892 | if (lseek(p->fd, 0, SEEK_SET0) == -1) { | |||
893 | err = got_error_from_errno("lseek"); | |||
894 | goto done; | |||
895 | } | |||
896 | ||||
897 | #ifndef GOT_PACK_NO_MMAP | |||
898 | p->map = mmap(NULL((void *)0), p->len, PROT_READ0x01, MAP_PRIVATE0x0002, p->fd, 0); | |||
899 | if (p->map == MAP_FAILED((void *)-1)) | |||
900 | p->map = NULL((void *)0); /* fall back to read(2) */ | |||
901 | #endif | |||
902 | err = got_packidx_init_hdr(p, 1); | |||
903 | done: | |||
904 | if (err) { | |||
905 | if (imsg.fd != -1) | |||
906 | close(imsg.fd); | |||
907 | got_packidx_close(p); | |||
908 | } else | |||
909 | *packidx = p; | |||
910 | imsg_free(&imsg); | |||
911 | return err; | |||
912 | } | |||
913 | ||||
914 | static const struct got_error * | |||
915 | receive_pack(struct got_pack **packp, struct imsgbuf *ibuf) | |||
916 | { | |||
917 | const struct got_error *err = NULL((void *)0); | |||
918 | struct imsg imsg; | |||
919 | struct got_imsg_pack ipack; | |||
920 | size_t datalen; | |||
921 | struct got_pack *pack; | |||
922 | ||||
923 | *packp = NULL((void *)0); | |||
924 | ||||
925 | err = got_privsep_recv_imsg(&imsg, ibuf, 0); | |||
926 | if (err) | |||
927 | return err; | |||
928 | ||||
929 | pack = calloc(1, sizeof(*pack)); | |||
930 | if (pack == NULL((void *)0)) { | |||
931 | err = got_error_from_errno("calloc"); | |||
932 | goto done; | |||
933 | } | |||
934 | ||||
935 | if (imsg.hdr.type != GOT_IMSG_PACK) { | |||
936 | err = got_error(GOT_ERR_PRIVSEP_MSG39); | |||
937 | goto done; | |||
938 | } | |||
939 | ||||
940 | if (imsg.fd == -1) { | |||
941 | err = got_error(GOT_ERR_PRIVSEP_NO_FD38); | |||
942 | goto done; | |||
943 | } | |||
944 | ||||
945 | datalen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
946 | if (datalen != sizeof(ipack)) { | |||
947 | err = got_error(GOT_ERR_PRIVSEP_LEN36); | |||
948 | goto done; | |||
949 | } | |||
950 | memcpy(&ipack, imsg.data, sizeof(ipack)); | |||
951 | ||||
952 | pack->filesize = ipack.filesize; | |||
953 | pack->fd = dup(imsg.fd); | |||
954 | if (pack->fd == -1) { | |||
955 | err = got_error_from_errno("dup"); | |||
956 | goto done; | |||
957 | } | |||
958 | if (lseek(pack->fd, 0, SEEK_SET0) == -1) { | |||
959 | err = got_error_from_errno("lseek"); | |||
960 | goto done; | |||
961 | } | |||
962 | pack->path_packfile = strdup(ipack.path_packfile); | |||
963 | if (pack->path_packfile == NULL((void *)0)) { | |||
964 | err = got_error_from_errno("strdup"); | |||
965 | goto done; | |||
966 | } | |||
967 | ||||
968 | pack->delta_cache = got_delta_cache_alloc(100, | |||
969 | GOT_DELTA_RESULT_SIZE_CACHED_MAX(8 * 1024 * 1024)); | |||
970 | if (pack->delta_cache == NULL((void *)0)) { | |||
971 | err = got_error_from_errno("got_delta_cache_alloc"); | |||
972 | goto done; | |||
973 | } | |||
974 | ||||
975 | #ifndef GOT_PACK_NO_MMAP | |||
976 | pack->map = mmap(NULL((void *)0), pack->filesize, PROT_READ0x01, MAP_PRIVATE0x0002, | |||
977 | pack->fd, 0); | |||
978 | if (pack->map == MAP_FAILED((void *)-1)) | |||
979 | pack->map = NULL((void *)0); /* fall back to read(2) */ | |||
980 | #endif | |||
981 | done: | |||
982 | if (err) { | |||
983 | if (imsg.fd != -1) | |||
984 | close(imsg.fd); | |||
985 | free(pack); | |||
986 | } else | |||
987 | *packp = pack; | |||
988 | imsg_free(&imsg); | |||
989 | return err; | |||
990 | } | |||
991 | ||||
992 | int | |||
993 | main(int argc, char *argv[]) | |||
994 | { | |||
995 | const struct got_error *err = NULL((void *)0); | |||
996 | struct imsgbuf ibuf; | |||
997 | struct imsg imsg; | |||
998 | struct got_packidx *packidx = NULL((void *)0); | |||
999 | struct got_pack *pack = NULL((void *)0); | |||
1000 | struct got_object_cache objcache; | |||
1001 | ||||
1002 | //static int attached; | |||
1003 | //while (!attached) sleep(1); | |||
1004 | ||||
1005 | signal(SIGINT2, catch_sigint); | |||
1006 | ||||
1007 | imsg_init(&ibuf, GOT_IMSG_FD_CHILD(2 + 1)); | |||
1008 | ||||
1009 | err = got_object_cache_init(&objcache, GOT_OBJECT_CACHE_TYPE_OBJ); | |||
1010 | if (err) { | |||
| ||||
1011 | err = got_error_from_errno("got_object_cache_init"); | |||
1012 | got_privsep_send_error(&ibuf, err); | |||
1013 | return 1; | |||
1014 | } | |||
1015 | ||||
1016 | #ifndef PROFILE | |||
1017 | /* revoke access to most system calls */ | |||
1018 | if (pledge("stdio recvfd", NULL((void *)0)) == -1) { | |||
1019 | err = got_error_from_errno("pledge"); | |||
1020 | got_privsep_send_error(&ibuf, err); | |||
1021 | return 1; | |||
1022 | } | |||
1023 | #endif | |||
1024 | ||||
1025 | err = receive_packidx(&packidx, &ibuf); | |||
1026 | if (err
| |||
1027 | got_privsep_send_error(&ibuf, err); | |||
1028 | return 1; | |||
1029 | } | |||
1030 | ||||
1031 | err = receive_pack(&pack, &ibuf); | |||
1032 | if (err
| |||
1033 | got_privsep_send_error(&ibuf, err); | |||
1034 | return 1; | |||
1035 | } | |||
1036 | ||||
1037 | for (;;) { | |||
1038 | imsg.fd = -1; | |||
1039 | ||||
1040 | if (sigint_received) { | |||
1041 | err = got_error(GOT_ERR_CANCELLED49); | |||
1042 | break; | |||
1043 | } | |||
1044 | ||||
1045 | err = got_privsep_recv_imsg(&imsg, &ibuf, 0); | |||
1046 | if (err) { | |||
1047 | if (err->code == GOT_ERR_PRIVSEP_PIPE37) | |||
1048 | err = NULL((void *)0); | |||
1049 | break; | |||
1050 | } | |||
1051 | ||||
1052 | if (imsg.hdr.type == GOT_IMSG_STOP) | |||
1053 | break; | |||
1054 | ||||
1055 | switch (imsg.hdr.type) { | |||
1056 | case GOT_IMSG_PACKED_OBJECT_REQUEST: | |||
1057 | err = object_request(&imsg, &ibuf, pack, packidx, | |||
1058 | &objcache); | |||
1059 | break; | |||
1060 | case GOT_IMSG_PACKED_RAW_OBJECT_REQUEST: | |||
1061 | err = raw_object_request(&imsg, &ibuf, pack, packidx, | |||
1062 | &objcache); | |||
1063 | break; | |||
1064 | case GOT_IMSG_COMMIT_REQUEST: | |||
1065 | err = commit_request(&imsg, &ibuf, pack, packidx, | |||
1066 | &objcache); | |||
1067 | break; | |||
1068 | case GOT_IMSG_TREE_REQUEST: | |||
1069 | err = tree_request(&imsg, &ibuf, pack, packidx, | |||
1070 | &objcache); | |||
1071 | break; | |||
1072 | case GOT_IMSG_BLOB_REQUEST: | |||
1073 | err = blob_request(&imsg, &ibuf, pack, packidx, | |||
1074 | &objcache); | |||
1075 | break; | |||
1076 | case GOT_IMSG_TAG_REQUEST: | |||
1077 | err = tag_request(&imsg, &ibuf, pack, packidx, | |||
1078 | &objcache); | |||
1079 | break; | |||
1080 | case GOT_IMSG_COMMIT_TRAVERSAL_REQUEST: | |||
1081 | err = commit_traversal_request(&imsg, &ibuf, pack, | |||
1082 | packidx, &objcache); | |||
1083 | break; | |||
1084 | default: | |||
1085 | err = got_error(GOT_ERR_PRIVSEP_MSG39); | |||
1086 | break; | |||
1087 | } | |||
1088 | ||||
1089 | if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL((void *)0)) | |||
1090 | err = got_error_from_errno("close"); | |||
1091 | imsg_free(&imsg); | |||
1092 | if (err) | |||
1093 | break; | |||
1094 | } | |||
1095 | ||||
1096 | if (packidx) | |||
1097 | got_packidx_close(packidx); | |||
1098 | if (pack) | |||
1099 | got_pack_close(pack); | |||
1100 | got_object_cache_close(&objcache); | |||
1101 | imsg_clear(&ibuf); | |||
1102 | if (err) { | |||
1103 | if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE37) { | |||
1104 | fprintf(stderr(&__sF[2]), "%s: %s\n", getprogname(), err->msg); | |||
1105 | got_privsep_send_error(&ibuf, err); | |||
1106 | } | |||
1107 | } | |||
1108 | if (close(GOT_IMSG_FD_CHILD(2 + 1)) == -1 && err == NULL((void *)0)) | |||
1109 | err = got_error_from_errno("close"); | |||
1110 | return err ? 1 : 0; | |||
1111 | } |