* Update pack header with object_count and compute new SHA1 for pack data * associated to pack_fd, and write that SHA1 at the end. That new SHA1 * is also returned in new_pack_sha1. * * If partial_pack_sha1 is non null, then the SHA1 of the existing pack * (without the header update) is computed and validated against the * one provided in partial_pack_sha1. The validation is performed at
| 389 | * interested in the resulting SHA1 of pack data above partial_pack_offset. |
| 390 | */ |
| 391 | void fixup_pack_header_footer(const struct git_hash_algo *hash_algo, |
| 392 | int pack_fd, |
| 393 | unsigned char *new_pack_hash, |
| 394 | const char *pack_name, |
| 395 | uint32_t object_count, |
| 396 | unsigned char *partial_pack_hash, |
| 397 | off_t partial_pack_offset) |
| 398 | { |
| 399 | int aligned_sz, buf_sz = 8 * 1024; |
| 400 | struct git_hash_ctx old_hash_ctx, new_hash_ctx; |
| 401 | struct pack_header hdr; |
| 402 | char *buf; |
| 403 | ssize_t read_result; |
| 404 | |
| 405 | hash_algo->init_fn(&old_hash_ctx); |
| 406 | hash_algo->init_fn(&new_hash_ctx); |
| 407 | |
| 408 | if (lseek(pack_fd, 0, SEEK_SET) != 0) |
| 409 | die_errno("Failed seeking to start of '%s'", pack_name); |
| 410 | read_result = read_in_full(pack_fd, &hdr, sizeof(hdr)); |
| 411 | if (read_result < 0) |
| 412 | die_errno("Unable to reread header of '%s'", pack_name); |
| 413 | else if (read_result != sizeof(hdr)) |
| 414 | die_errno("Unexpected short read for header of '%s'", |
| 415 | pack_name); |
| 416 | if (lseek(pack_fd, 0, SEEK_SET) != 0) |
| 417 | die_errno("Failed seeking to start of '%s'", pack_name); |
| 418 | git_hash_update(&old_hash_ctx, &hdr, sizeof(hdr)); |
| 419 | hdr.hdr_entries = htonl(object_count); |
| 420 | git_hash_update(&new_hash_ctx, &hdr, sizeof(hdr)); |
| 421 | write_or_die(pack_fd, &hdr, sizeof(hdr)); |
| 422 | partial_pack_offset -= sizeof(hdr); |
| 423 | |
| 424 | buf = xmalloc(buf_sz); |
| 425 | aligned_sz = buf_sz - sizeof(hdr); |
| 426 | for (;;) { |
| 427 | ssize_t m, n; |
| 428 | m = (partial_pack_hash && partial_pack_offset < aligned_sz) ? |
| 429 | partial_pack_offset : aligned_sz; |
| 430 | n = xread(pack_fd, buf, m); |
| 431 | if (!n) |
| 432 | break; |
| 433 | if (n < 0) |
| 434 | die_errno("Failed to checksum '%s'", pack_name); |
| 435 | git_hash_update(&new_hash_ctx, buf, n); |
| 436 | |
| 437 | aligned_sz -= n; |
| 438 | if (!aligned_sz) |
| 439 | aligned_sz = buf_sz; |
| 440 | |
| 441 | if (!partial_pack_hash) |
| 442 | continue; |
| 443 | |
| 444 | git_hash_update(&old_hash_ctx, buf, n); |
| 445 | partial_pack_offset -= n; |
| 446 | if (partial_pack_offset == 0) { |
| 447 | unsigned char hash[GIT_MAX_RAWSZ]; |
| 448 | git_hash_final(hash, &old_hash_ctx); |
no test coverage detected