| 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 | } |