2 0a0a3048 2018-01-10 stsp * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
4 0a0a3048 2018-01-10 stsp * Permission to use, copy, modify, and distribute this software for any
5 0a0a3048 2018-01-10 stsp * purpose with or without fee is hereby granted, provided that the above
6 0a0a3048 2018-01-10 stsp * copyright notice and this permission notice appear in all copies.
8 0a0a3048 2018-01-10 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 0a0a3048 2018-01-10 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 0a0a3048 2018-01-10 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 0a0a3048 2018-01-10 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 0a0a3048 2018-01-10 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 0a0a3048 2018-01-10 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 0a0a3048 2018-01-10 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 0a0a3048 2018-01-10 stsp #include <sys/stat.h>
19 0a0a3048 2018-01-10 stsp #include <stdio.h>
20 0a0a3048 2018-01-10 stsp #include <stdlib.h>
21 0a0a3048 2018-01-10 stsp #include <string.h>
22 0a0a3048 2018-01-10 stsp #include <limits.h>
23 0a0a3048 2018-01-10 stsp #include <sha1.h>
24 0a0a3048 2018-01-10 stsp #include <endian.h>
26 0a0a3048 2018-01-10 stsp #include "got_error.h"
27 0a0a3048 2018-01-10 stsp #include "pack.h"
29 0a0a3048 2018-01-10 stsp static const struct got_error *
30 0a0a3048 2018-01-10 stsp verify_fanout_table(uint32_t *fanout_table)
34 0a0a3048 2018-01-10 stsp for (i = 0; i < 0xff - 1; i++) {
35 0a0a3048 2018-01-10 stsp if (fanout_table[i] > fanout_table[i + 1])
36 0a0a3048 2018-01-10 stsp return got_error(GOT_ERR_BAD_PACKIDX);
39 0a0a3048 2018-01-10 stsp return NULL;
42 0a0a3048 2018-01-10 stsp const struct got_error *
43 0a0a3048 2018-01-10 stsp get_packfile_size(size_t *size, const char *path_idx)
45 0a0a3048 2018-01-10 stsp struct stat sb;
46 0a0a3048 2018-01-10 stsp char *path_pack;
47 0a0a3048 2018-01-10 stsp char base_path[PATH_MAX];
50 0a0a3048 2018-01-10 stsp if (strlcpy(base_path, path_idx, PATH_MAX) > PATH_MAX)
51 0a0a3048 2018-01-10 stsp return got_error(GOT_ERR_NO_SPACE);
53 0a0a3048 2018-01-10 stsp dot = strrchr(base_path, '.');
54 0a0a3048 2018-01-10 stsp if (dot == NULL)
55 0a0a3048 2018-01-10 stsp return got_error(GOT_ERR_BAD_PATH);
56 0a0a3048 2018-01-10 stsp *dot = '\0';
57 0a0a3048 2018-01-10 stsp if (asprintf(&path_pack, "%s.pack", base_path) == -1)
58 0a0a3048 2018-01-10 stsp return got_error(GOT_ERR_NO_MEM);
60 0a0a3048 2018-01-10 stsp if (stat(path_pack, &sb) != 0) {
61 0a0a3048 2018-01-10 stsp free(path_pack);
62 0a0a3048 2018-01-10 stsp return got_error(GOT_ERR_IO);
66 0a0a3048 2018-01-10 stsp free(path_pack);
67 0a0a3048 2018-01-10 stsp *size = sb.st_size;
71 0a0a3048 2018-01-10 stsp const struct got_error *
72 0a0a3048 2018-01-10 stsp got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
74 0a0a3048 2018-01-10 stsp struct got_packidx_v2_hdr *p;
76 0a0a3048 2018-01-10 stsp const struct got_error *err = NULL;
77 0a0a3048 2018-01-10 stsp size_t n, nobj, packfile_size;
78 0ebaf008 2018-01-10 stsp SHA1_CTX ctx;
79 0ebaf008 2018-01-10 stsp uint8_t sha1[SHA1_DIGEST_LENGTH];
81 0ebaf008 2018-01-10 stsp SHA1Init(&ctx);
83 0a0a3048 2018-01-10 stsp f = fopen(path, "rb");
84 0a0a3048 2018-01-10 stsp if (f == NULL)
85 0a0a3048 2018-01-10 stsp return got_error(GOT_ERR_BAD_PATH);
87 0a0a3048 2018-01-10 stsp err = get_packfile_size(&packfile_size, path);
91 0a0a3048 2018-01-10 stsp p = calloc(1, sizeof(*p));
92 0a0a3048 2018-01-10 stsp if (p == NULL) {
93 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_NO_MEM);
97 0a0a3048 2018-01-10 stsp n = fread(&p->magic, sizeof(p->magic), 1, f);
98 0a0a3048 2018-01-10 stsp if (n != 1) {
99 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
103 0a0a3048 2018-01-10 stsp if (betoh32(p->magic) != GOT_PACKIDX_V2_MAGIC) {
104 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_BAD_PACKIDX);
108 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)&p->magic, sizeof(p->magic));
110 0a0a3048 2018-01-10 stsp n = fread(&p->version, sizeof(p->version), 1, f);
111 0a0a3048 2018-01-10 stsp if (n != 1) {
112 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
116 0a0a3048 2018-01-10 stsp if (betoh32(p->version) != GOT_PACKIDX_VERSION) {
117 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_BAD_PACKIDX);
121 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)&p->version, sizeof(p->version));
123 0a0a3048 2018-01-10 stsp n = fread(&p->fanout_table, sizeof(p->fanout_table), 1, f);
124 0a0a3048 2018-01-10 stsp if (n != 1) {
125 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
129 0a0a3048 2018-01-10 stsp err = verify_fanout_table(p->fanout_table);
133 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->fanout_table, sizeof(p->fanout_table));
135 0a0a3048 2018-01-10 stsp nobj = betoh32(p->fanout_table[0xff]);
137 0a0a3048 2018-01-10 stsp p->sorted_ids = calloc(nobj, sizeof(*p->sorted_ids));
138 0a0a3048 2018-01-10 stsp if (p->sorted_ids == NULL) {
139 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_NO_MEM);
143 0a0a3048 2018-01-10 stsp n = fread(p->sorted_ids, sizeof(*p->sorted_ids), nobj, f);
144 0a0a3048 2018-01-10 stsp if (n != nobj) {
145 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
149 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->sorted_ids,
150 0ebaf008 2018-01-10 stsp nobj * sizeof(*p->sorted_ids));
152 0a0a3048 2018-01-10 stsp p->offsets = calloc(nobj, sizeof(*p->offsets));
153 0a0a3048 2018-01-10 stsp if (p->offsets == NULL) {
154 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_NO_MEM);
158 0a0a3048 2018-01-10 stsp n = fread(p->offsets, sizeof(*p->offsets), nobj, f);
159 0a0a3048 2018-01-10 stsp if (n != nobj) {
160 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
164 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->offsets, nobj * sizeof(*p->offsets));
166 0a0a3048 2018-01-10 stsp p->crc32 = calloc(nobj, sizeof(*p->crc32));
167 0a0a3048 2018-01-10 stsp if (p->crc32 == NULL) {
168 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_NO_MEM);
172 0a0a3048 2018-01-10 stsp n = fread(p->crc32, sizeof(*p->crc32), nobj, f);
173 0a0a3048 2018-01-10 stsp if (n != nobj) {
174 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
178 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->crc32, nobj * sizeof(*p->crc32));
180 0a0a3048 2018-01-10 stsp /* Large file offsets are contained only in files > 2GB. */
181 b0517dd0 2018-01-10 stsp if (packfile_size <= 0x80000000)
182 0a0a3048 2018-01-10 stsp goto checksum;
184 0a0a3048 2018-01-10 stsp p->large_offsets = calloc(nobj, sizeof(*p->large_offsets));
185 0a0a3048 2018-01-10 stsp if (p->large_offsets == NULL) {
186 0a0a3048 2018-01-10 stsp err = got_error(GOT_ERR_NO_MEM);
190 0a0a3048 2018-01-10 stsp n = fread(p->large_offsets, sizeof(*p->large_offsets), nobj, f);
191 0a0a3048 2018-01-10 stsp if (n != nobj) {
192 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
196 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t*)p->large_offsets,
197 0ebaf008 2018-01-10 stsp nobj * sizeof(*p->large_offsets));
200 0a0a3048 2018-01-10 stsp n = fread(&p->trailer, sizeof(p->trailer), 1, f);
201 0a0a3048 2018-01-10 stsp if (n != 1) {
202 0a0a3048 2018-01-10 stsp err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
206 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, p->trailer.pack_file_sha1, SHA1_DIGEST_LENGTH);
207 0ebaf008 2018-01-10 stsp SHA1Final(sha1, &ctx);
208 0ebaf008 2018-01-10 stsp if (memcmp(p->trailer.pack_idx_sha1, sha1, SHA1_DIGEST_LENGTH) != 0)
209 0ebaf008 2018-01-10 stsp err = got_error(GOT_ERR_PACKIDX_CSUM);
213 0a0a3048 2018-01-10 stsp got_packidx_close(p);
215 0a0a3048 2018-01-10 stsp *packidx = p;
216 0a0a3048 2018-01-10 stsp return err;
220 0a0a3048 2018-01-10 stsp got_packidx_close(struct got_packidx_v2_hdr *packidx)
222 0a0a3048 2018-01-10 stsp free(packidx->sorted_ids);
223 0a0a3048 2018-01-10 stsp free(packidx->offsets);
224 0a0a3048 2018-01-10 stsp free(packidx->crc32);
225 0a0a3048 2018-01-10 stsp free(packidx->large_offsets);
226 0a0a3048 2018-01-10 stsp free(packidx);