packfile: abstract away hash constant values

There are several instances of the constant 20 and 20-based values in the packfile code. Abstract away dependence on SHA-1 by using the values from the_hash_algo instead. Use unsigned values for temporary constants to provide the compiler with more information about what kinds of values it should expect. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed May 2, 2018 at 00:25 UTC 37fec86a8353106dad000d498df8251ea3547855
1 file changed +37 -29
packfile.c
+37 -29
@@ -84,6 +84,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
84 uint32_t version, nr, i, *index;
85 int fd = git_open(path);
86 struct stat st;
87 + const unsigned int hashsz = the_hash_algo->rawsz;
88
89 if (fd < 0)
90 return -1;
@@ -92,7 +93,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
93 return -1;
94 }
95 idx_size = xsize_t(st.st_size);
95 - if (idx_size < 4 * 256 + 20 + 20) {
96 + if (idx_size < 4 * 256 + hashsz + hashsz) {
97 close(fd);
98 return error("index file %s is too small", path);
99 }
@@ -129,11 +130,11 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
130 /*
131 * Total size:
132 * - 256 index entries 4 bytes each
132 - * - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
133 - * - 20-byte SHA1 of the packfile
134 - * - 20-byte SHA1 file checksum
133 + * - 24-byte entries * nr (object ID + 4-byte offset)
134 + * - hash of the packfile
135 + * - file checksum
136 */
136 - if (idx_size != 4*256 + nr * 24 + 20 + 20) {
137 + if (idx_size != 4*256 + nr * (hashsz + 4) + hashsz + hashsz) {
138 munmap(idx_map, idx_size);
139 return error("wrong index v1 file size in %s", path);
140 }
@@ -142,16 +143,16 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
143 * Minimum size:
144 * - 8 bytes of header
145 * - 256 index entries 4 bytes each
145 - * - 20-byte sha1 entry * nr
146 + * - object ID entry * nr
147 * - 4-byte crc entry * nr
148 * - 4-byte offset entry * nr
148 - * - 20-byte SHA1 of the packfile
149 - * - 20-byte SHA1 file checksum
149 + * - hash of the packfile
150 + * - file checksum
151 * And after the 4-byte offset table might be a
152 * variable sized table containing 8-byte entries
153 * for offsets larger than 2^31.
154 */
154 - unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
155 + unsigned long min_size = 8 + 4*256 + nr*(hashsz + 4 + 4) + hashsz + hashsz;
156 unsigned long max_size = min_size;
157 if (nr)
158 max_size += (nr - 1)*8;
@@ -444,10 +445,11 @@ static int open_packed_git_1(struct packed_git *p)
445 {
446 struct stat st;
447 struct pack_header hdr;
447 - unsigned char sha1[20];
448 - unsigned char *idx_sha1;
448 + unsigned char hash[GIT_MAX_RAWSZ];
449 + unsigned char *idx_hash;
450 long fd_flag;
451 ssize_t read_result;
452 + const unsigned hashsz = the_hash_algo->rawsz;
453
454 if (!p->index_data && open_pack_index(p))
455 return error("packfile %s index unavailable", p->pack_name);
@@ -507,15 +509,15 @@ static int open_packed_git_1(struct packed_git *p)
509 " while index indicates %"PRIu32" objects",
510 p->pack_name, ntohl(hdr.hdr_entries),
511 p->num_objects);
510 - if (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)
512 + if (lseek(p->pack_fd, p->pack_size - hashsz, SEEK_SET) == -1)
513 return error("end of packfile %s is unavailable", p->pack_name);
512 - read_result = read_in_full(p->pack_fd, sha1, sizeof(sha1));
514 + read_result = read_in_full(p->pack_fd, hash, hashsz);
515 if (read_result < 0)
516 return error_errno("error reading from %s", p->pack_name);
515 - if (read_result != sizeof(sha1))
517 + if (read_result != hashsz)
518 return error("packfile %s signature is unavailable", p->pack_name);
517 - idx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;
518 - if (hashcmp(sha1, idx_sha1))
519 + idx_hash = ((unsigned char *)p->index_data) + p->index_size - hashsz * 2;
520 + if (hashcmp(hash, idx_hash))
521 return error("packfile %s does not match index", p->pack_name);
522 return 0;
523 }
@@ -530,7 +532,7 @@ static int open_packed_git(struct packed_git *p)
532
533 static int in_window(struct pack_window *win, off_t offset)
534 {
533 - /* We must promise at least 20 bytes (one hash) after the
535 + /* We must promise at least one full hash after the
536 * offset is available from this window, otherwise the offset
537 * is not actually in this window and a different window (which
538 * has that one hash excess) must be used. This is to support
@@ -538,7 +540,7 @@ static int in_window(struct pack_window *win, off_t offset)
540 */
541 off_t win_off = win->offset;
542 return win_off <= offset
541 - && (offset + 20) <= (win_off + win->len);
543 + && (offset + the_hash_algo->rawsz) <= (win_off + win->len);
544 }
545
546 unsigned char *use_pack(struct packed_git *p,
@@ -555,7 +557,7 @@ unsigned char *use_pack(struct packed_git *p,
557 */
558 if (!p->pack_size && p->pack_fd == -1 && open_packed_git(p))
559 die("packfile %s cannot be accessed", p->pack_name);
558 - if (offset > (p->pack_size - 20))
560 + if (offset > (p->pack_size - the_hash_algo->rawsz))
561 die("offset beyond end of packfile (truncated pack?)");
562 if (offset < 0)
563 die(_("offset before end of packfile (broken .idx?)"));
@@ -675,7 +677,8 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)
677 p->pack_size = st.st_size;
678 p->pack_local = local;
679 p->mtime = st.st_mtime;
678 - if (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))
680 + if (path_len < the_hash_algo->hexsz ||
681 + get_sha1_hex(path + path_len - the_hash_algo->hexsz, p->sha1))
682 hashclr(p->sha1);
683 return p;
684 }
@@ -1028,7 +1031,8 @@ const struct packed_git *has_packed_and_bad(const unsigned char *sha1)
1031
1032 for (p = the_repository->objects->packed_git; p; p = p->next)
1033 for (i = 0; i < p->num_bad_objects; i++)
1031 - if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
1034 + if (!hashcmp(sha1,
1035 + p->bad_object_sha1 + the_hash_algo->rawsz * i))
1036 return p;
1037 return NULL;
1038 }
@@ -1066,7 +1070,7 @@ static off_t get_delta_base(struct packed_git *p,
1070 } else if (type == OBJ_REF_DELTA) {
1071 /* The base entry _must_ be in the same pack */
1072 base_offset = find_pack_entry_one(base_info, p);
1069 - *curpos += 20;
1073 + *curpos += the_hash_algo->rawsz;
1074 } else
1075 die("I am totally screwed");
1076 return base_offset;
@@ -1671,6 +1675,7 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32
1675 {
1676 const unsigned char *index_fanout = p->index_data;
1677 const unsigned char *index_lookup;
1678 + const unsigned int hashsz = the_hash_algo->rawsz;
1679 int index_lookup_width;
1680
1681 if (!index_fanout)
@@ -1678,10 +1683,10 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32
1683
1684 index_lookup = index_fanout + 4 * 256;
1685 if (p->index_version == 1) {
1681 - index_lookup_width = 24;
1686 + index_lookup_width = hashsz + 4;
1687 index_lookup += 4;
1688 } else {
1684 - index_lookup_width = 20;
1689 + index_lookup_width = hashsz;
1690 index_fanout += 8;
1691 index_lookup += 8;
1692 }
@@ -1694,6 +1699,7 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,
1699 uint32_t n)
1700 {
1701 const unsigned char *index = p->index_data;
1702 + const unsigned int hashsz = the_hash_algo->rawsz;
1703 if (!index) {
1704 if (open_pack_index(p))
1705 return NULL;
@@ -1703,10 +1709,10 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,
1709 return NULL;
1710 index += 4 * 256;
1711 if (p->index_version == 1) {
1706 - return index + 24 * n + 4;
1712 + return index + (hashsz + 4) * n + 4;
1713 } else {
1714 index += 8;
1709 - return index + 20 * n;
1715 + return index + hashsz * n;
1716 }
1717 }
1718
@@ -1738,12 +1744,13 @@ void check_pack_index_ptr(const struct packed_git *p, const void *vptr)
1744 off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
1745 {
1746 const unsigned char *index = p->index_data;
1747 + const unsigned int hashsz = the_hash_algo->rawsz;
1748 index += 4 * 256;
1749 if (p->index_version == 1) {
1743 - return ntohl(*((uint32_t *)(index + 24 * n)));
1750 + return ntohl(*((uint32_t *)(index + (hashsz + 4) * n)));
1751 } else {
1752 uint32_t off;
1746 - index += 8 + p->num_objects * (20 + 4);
1753 + index += 8 + p->num_objects * (hashsz + 4);
1754 off = ntohl(*((uint32_t *)(index + 4 * n)));
1755 if (!(off & 0x80000000))
1756 return off;
@@ -1814,7 +1821,8 @@ static int fill_pack_entry(const struct object_id *oid,
1821 if (p->num_bad_objects) {
1822 unsigned i;
1823 for (i = 0; i < p->num_bad_objects; i++)
1817 - if (!hashcmp(oid->hash, p->bad_object_sha1 + 20 * i))
1824 + if (!hashcmp(oid->hash,
1825 + p->bad_object_sha1 + the_hash_algo->rawsz * i))
1826 return 0;
1827 }
1828