Blame


1 0a0a3048 2018-01-10 stsp /*
2 0a0a3048 2018-01-10 stsp * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
3 0a0a3048 2018-01-10 stsp *
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.
7 0a0a3048 2018-01-10 stsp *
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.
15 0a0a3048 2018-01-10 stsp */
16 0a0a3048 2018-01-10 stsp
17 0a0a3048 2018-01-10 stsp #include <sys/stat.h>
18 0a0a3048 2018-01-10 stsp
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>
25 0a0a3048 2018-01-10 stsp
26 0a0a3048 2018-01-10 stsp #include "got_error.h"
27 0a0a3048 2018-01-10 stsp #include "pack.h"
28 0a0a3048 2018-01-10 stsp
29 0a0a3048 2018-01-10 stsp static const struct got_error *
30 0a0a3048 2018-01-10 stsp verify_fanout_table(uint32_t *fanout_table)
31 0a0a3048 2018-01-10 stsp {
32 0a0a3048 2018-01-10 stsp int i;
33 0a0a3048 2018-01-10 stsp
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);
37 0a0a3048 2018-01-10 stsp }
38 0a0a3048 2018-01-10 stsp
39 0a0a3048 2018-01-10 stsp return NULL;
40 0a0a3048 2018-01-10 stsp }
41 0a0a3048 2018-01-10 stsp
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)
44 0a0a3048 2018-01-10 stsp {
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];
48 0a0a3048 2018-01-10 stsp char *dot;
49 0a0a3048 2018-01-10 stsp
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);
52 0a0a3048 2018-01-10 stsp
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);
59 0a0a3048 2018-01-10 stsp
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);
63 0a0a3048 2018-01-10 stsp
64 0a0a3048 2018-01-10 stsp }
65 0a0a3048 2018-01-10 stsp
66 0a0a3048 2018-01-10 stsp free(path_pack);
67 0a0a3048 2018-01-10 stsp *size = sb.st_size;
68 0a0a3048 2018-01-10 stsp return 0;
69 0a0a3048 2018-01-10 stsp }
70 0a0a3048 2018-01-10 stsp
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)
73 0a0a3048 2018-01-10 stsp {
74 0a0a3048 2018-01-10 stsp struct got_packidx_v2_hdr *p;
75 0a0a3048 2018-01-10 stsp FILE *f;
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];
80 0a0a3048 2018-01-10 stsp
81 0ebaf008 2018-01-10 stsp SHA1Init(&ctx);
82 0ebaf008 2018-01-10 stsp
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);
86 0a0a3048 2018-01-10 stsp
87 0a0a3048 2018-01-10 stsp err = get_packfile_size(&packfile_size, path);
88 0a0a3048 2018-01-10 stsp if (err)
89 0a0a3048 2018-01-10 stsp return err;
90 0a0a3048 2018-01-10 stsp
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);
94 0a0a3048 2018-01-10 stsp goto done;
95 0a0a3048 2018-01-10 stsp }
96 0a0a3048 2018-01-10 stsp
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);
100 0a0a3048 2018-01-10 stsp goto done;
101 0a0a3048 2018-01-10 stsp }
102 0a0a3048 2018-01-10 stsp
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);
105 0a0a3048 2018-01-10 stsp goto done;
106 0a0a3048 2018-01-10 stsp }
107 0a0a3048 2018-01-10 stsp
108 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)&p->magic, sizeof(p->magic));
109 0ebaf008 2018-01-10 stsp
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);
113 0a0a3048 2018-01-10 stsp goto done;
114 0a0a3048 2018-01-10 stsp }
115 0a0a3048 2018-01-10 stsp
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);
118 0a0a3048 2018-01-10 stsp goto done;
119 0a0a3048 2018-01-10 stsp }
120 0a0a3048 2018-01-10 stsp
121 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)&p->version, sizeof(p->version));
122 0ebaf008 2018-01-10 stsp
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);
126 0a0a3048 2018-01-10 stsp goto done;
127 0a0a3048 2018-01-10 stsp }
128 0a0a3048 2018-01-10 stsp
129 0a0a3048 2018-01-10 stsp err = verify_fanout_table(p->fanout_table);
130 0a0a3048 2018-01-10 stsp if (err)
131 0a0a3048 2018-01-10 stsp goto done;
132 0a0a3048 2018-01-10 stsp
133 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->fanout_table, sizeof(p->fanout_table));
134 0ebaf008 2018-01-10 stsp
135 0a0a3048 2018-01-10 stsp nobj = betoh32(p->fanout_table[0xff]);
136 0a0a3048 2018-01-10 stsp
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);
140 0a0a3048 2018-01-10 stsp goto done;
141 0a0a3048 2018-01-10 stsp }
142 0a0a3048 2018-01-10 stsp
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);
146 0a0a3048 2018-01-10 stsp goto done;
147 0a0a3048 2018-01-10 stsp }
148 0a0a3048 2018-01-10 stsp
149 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->sorted_ids,
150 0ebaf008 2018-01-10 stsp nobj * sizeof(*p->sorted_ids));
151 0ebaf008 2018-01-10 stsp
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);
155 0a0a3048 2018-01-10 stsp goto done;
156 0a0a3048 2018-01-10 stsp }
157 0a0a3048 2018-01-10 stsp
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);
161 0a0a3048 2018-01-10 stsp goto done;
162 0a0a3048 2018-01-10 stsp }
163 0a0a3048 2018-01-10 stsp
164 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->offsets, nobj * sizeof(*p->offsets));
165 0ebaf008 2018-01-10 stsp
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);
169 0a0a3048 2018-01-10 stsp goto done;
170 0a0a3048 2018-01-10 stsp }
171 0a0a3048 2018-01-10 stsp
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);
175 0a0a3048 2018-01-10 stsp goto done;
176 0a0a3048 2018-01-10 stsp }
177 0a0a3048 2018-01-10 stsp
178 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t *)p->crc32, nobj * sizeof(*p->crc32));
179 0ebaf008 2018-01-10 stsp
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;
183 0a0a3048 2018-01-10 stsp
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);
187 0a0a3048 2018-01-10 stsp goto done;
188 0a0a3048 2018-01-10 stsp }
189 0a0a3048 2018-01-10 stsp
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);
193 0a0a3048 2018-01-10 stsp goto done;
194 0a0a3048 2018-01-10 stsp }
195 0a0a3048 2018-01-10 stsp
196 0ebaf008 2018-01-10 stsp SHA1Update(&ctx, (uint8_t*)p->large_offsets,
197 0ebaf008 2018-01-10 stsp nobj * sizeof(*p->large_offsets));
198 0ebaf008 2018-01-10 stsp
199 0a0a3048 2018-01-10 stsp checksum:
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);
203 0a0a3048 2018-01-10 stsp goto done;
204 0a0a3048 2018-01-10 stsp }
205 0a0a3048 2018-01-10 stsp
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);
210 0a0a3048 2018-01-10 stsp done:
211 0a0a3048 2018-01-10 stsp fclose(f);
212 0a0a3048 2018-01-10 stsp if (err)
213 0a0a3048 2018-01-10 stsp got_packidx_close(p);
214 0a0a3048 2018-01-10 stsp else
215 0a0a3048 2018-01-10 stsp *packidx = p;
216 0a0a3048 2018-01-10 stsp return err;
217 0a0a3048 2018-01-10 stsp }
218 0a0a3048 2018-01-10 stsp
219 0a0a3048 2018-01-10 stsp void
220 0a0a3048 2018-01-10 stsp got_packidx_close(struct got_packidx_v2_hdr *packidx)
221 0a0a3048 2018-01-10 stsp {
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);
227 0a0a3048 2018-01-10 stsp }