Blame


1 93658fb9 2020-03-18 stsp /*
2 93658fb9 2020-03-18 stsp * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
3 93658fb9 2020-03-18 stsp *
4 93658fb9 2020-03-18 stsp * Permission to use, copy, modify, and distribute this software for any
5 93658fb9 2020-03-18 stsp * purpose with or without fee is hereby granted, provided that the above
6 93658fb9 2020-03-18 stsp * copyright notice and this permission notice appear in all copies.
7 93658fb9 2020-03-18 stsp *
8 93658fb9 2020-03-18 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 93658fb9 2020-03-18 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 93658fb9 2020-03-18 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 93658fb9 2020-03-18 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 93658fb9 2020-03-18 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 93658fb9 2020-03-18 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 93658fb9 2020-03-18 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 93658fb9 2020-03-18 stsp */
16 93658fb9 2020-03-18 stsp
17 93658fb9 2020-03-18 stsp #include <sys/queue.h>
18 93658fb9 2020-03-18 stsp #include <sys/stat.h>
19 93658fb9 2020-03-18 stsp #include <sys/syslimits.h>
20 93658fb9 2020-03-18 stsp #include <sys/time.h>
21 93658fb9 2020-03-18 stsp #include <sys/types.h>
22 93658fb9 2020-03-18 stsp #include <sys/uio.h>
23 93658fb9 2020-03-18 stsp
24 93658fb9 2020-03-18 stsp #include <stdint.h>
25 93658fb9 2020-03-18 stsp #include <errno.h>
26 93658fb9 2020-03-18 stsp #include <imsg.h>
27 93658fb9 2020-03-18 stsp #include <limits.h>
28 93658fb9 2020-03-18 stsp #include <signal.h>
29 93658fb9 2020-03-18 stsp #include <stdio.h>
30 93658fb9 2020-03-18 stsp #include <stdlib.h>
31 93658fb9 2020-03-18 stsp #include <string.h>
32 93658fb9 2020-03-18 stsp #include <ctype.h>
33 93658fb9 2020-03-18 stsp #include <sha1.h>
34 93658fb9 2020-03-18 stsp #include <fcntl.h>
35 93658fb9 2020-03-18 stsp #include <zlib.h>
36 93658fb9 2020-03-18 stsp #include <err.h>
37 93658fb9 2020-03-18 stsp #include <assert.h>
38 93658fb9 2020-03-18 stsp #include <dirent.h>
39 93658fb9 2020-03-18 stsp
40 93658fb9 2020-03-18 stsp #include "got_error.h"
41 93658fb9 2020-03-18 stsp #include "got_object.h"
42 93658fb9 2020-03-18 stsp
43 93658fb9 2020-03-18 stsp #include "got_lib_sha1.h"
44 93658fb9 2020-03-18 stsp #include "got_lib_delta.h"
45 93658fb9 2020-03-18 stsp #include "got_lib_inflate.h"
46 93658fb9 2020-03-18 stsp #include "got_lib_object.h"
47 93658fb9 2020-03-18 stsp #include "got_lib_object_parse.h"
48 93658fb9 2020-03-18 stsp #include "got_lib_object_idset.h"
49 93658fb9 2020-03-18 stsp #include "got_lib_privsep.h"
50 93658fb9 2020-03-18 stsp
51 93658fb9 2020-03-18 stsp typedef struct Cinfo Cinfo;
52 93658fb9 2020-03-18 stsp typedef struct Tinfo Tinfo;
53 93658fb9 2020-03-18 stsp typedef struct Object Object;
54 93658fb9 2020-03-18 stsp typedef struct Pack Pack;
55 93658fb9 2020-03-18 stsp typedef struct Buf Buf;
56 93658fb9 2020-03-18 stsp typedef struct Dirent Dirent;
57 93658fb9 2020-03-18 stsp typedef struct Idxent Idxent;
58 93658fb9 2020-03-18 stsp typedef struct Ols Ols;
59 93658fb9 2020-03-18 stsp
60 93658fb9 2020-03-18 stsp enum {
61 93658fb9 2020-03-18 stsp /* 5k objects should be enough */
62 93658fb9 2020-03-18 stsp Cachemax = 5*1024,
63 93658fb9 2020-03-18 stsp Pathmax = 512,
64 93658fb9 2020-03-18 stsp Hashsz = 20,
65 93658fb9 2020-03-18 stsp Pktmax = 65536,
66 93658fb9 2020-03-18 stsp
67 93658fb9 2020-03-18 stsp Nproto = 16,
68 93658fb9 2020-03-18 stsp Nport = 16,
69 93658fb9 2020-03-18 stsp Nhost = 256,
70 93658fb9 2020-03-18 stsp Npath = 128,
71 93658fb9 2020-03-18 stsp Nrepo = 64,
72 93658fb9 2020-03-18 stsp Nbranch = 32,
73 93658fb9 2020-03-18 stsp };
74 93658fb9 2020-03-18 stsp
75 93658fb9 2020-03-18 stsp typedef enum Type {
76 93658fb9 2020-03-18 stsp GNone = 0,
77 93658fb9 2020-03-18 stsp GCommit = 1,
78 93658fb9 2020-03-18 stsp GTree = 2,
79 93658fb9 2020-03-18 stsp GBlob = 3,
80 93658fb9 2020-03-18 stsp GTag = 4,
81 93658fb9 2020-03-18 stsp GOdelta = 6,
82 93658fb9 2020-03-18 stsp GRdelta = 7,
83 93658fb9 2020-03-18 stsp } Type;
84 93658fb9 2020-03-18 stsp
85 93658fb9 2020-03-18 stsp enum {
86 93658fb9 2020-03-18 stsp Cloaded = 1 << 0,
87 93658fb9 2020-03-18 stsp Cidx = 1 << 1,
88 93658fb9 2020-03-18 stsp Ccache = 1 << 2,
89 93658fb9 2020-03-18 stsp Cexist = 1 << 3,
90 93658fb9 2020-03-18 stsp Cparsed = 1 << 5,
91 93658fb9 2020-03-18 stsp };
92 93658fb9 2020-03-18 stsp
93 93658fb9 2020-03-18 stsp struct Dirent {
94 93658fb9 2020-03-18 stsp char *name;
95 93658fb9 2020-03-18 stsp int modref;
96 93658fb9 2020-03-18 stsp int mode;
97 93658fb9 2020-03-18 stsp struct got_object_id h;
98 93658fb9 2020-03-18 stsp };
99 93658fb9 2020-03-18 stsp
100 93658fb9 2020-03-18 stsp struct Object {
101 93658fb9 2020-03-18 stsp /* Git data */
102 93658fb9 2020-03-18 stsp struct got_object_id hash;
103 93658fb9 2020-03-18 stsp Type type;
104 93658fb9 2020-03-18 stsp
105 93658fb9 2020-03-18 stsp /* Cache */
106 93658fb9 2020-03-18 stsp int id;
107 93658fb9 2020-03-18 stsp int flag;
108 93658fb9 2020-03-18 stsp int refs;
109 93658fb9 2020-03-18 stsp Object *next;
110 93658fb9 2020-03-18 stsp Object *prev;
111 93658fb9 2020-03-18 stsp
112 93658fb9 2020-03-18 stsp /* For indexing */
113 93658fb9 2020-03-18 stsp off_t off;
114 93658fb9 2020-03-18 stsp off_t len;
115 93658fb9 2020-03-18 stsp uint32_t crc;
116 93658fb9 2020-03-18 stsp
117 93658fb9 2020-03-18 stsp /* Everything below here gets cleared */
118 93658fb9 2020-03-18 stsp char *all;
119 93658fb9 2020-03-18 stsp char *data;
120 93658fb9 2020-03-18 stsp /* size excludes header */
121 93658fb9 2020-03-18 stsp off_t size;
122 93658fb9 2020-03-18 stsp
123 93658fb9 2020-03-18 stsp union {
124 93658fb9 2020-03-18 stsp Cinfo *commit;
125 93658fb9 2020-03-18 stsp Tinfo *tree;
126 93658fb9 2020-03-18 stsp };
127 93658fb9 2020-03-18 stsp };
128 93658fb9 2020-03-18 stsp
129 93658fb9 2020-03-18 stsp struct Tinfo {
130 93658fb9 2020-03-18 stsp /* Tree */
131 93658fb9 2020-03-18 stsp Dirent *ent;
132 93658fb9 2020-03-18 stsp int nent;
133 93658fb9 2020-03-18 stsp };
134 93658fb9 2020-03-18 stsp
135 93658fb9 2020-03-18 stsp struct Cinfo {
136 93658fb9 2020-03-18 stsp /* Commit */
137 93658fb9 2020-03-18 stsp struct got_object_id *parent;
138 93658fb9 2020-03-18 stsp int nparent;
139 93658fb9 2020-03-18 stsp struct got_object_id tree;
140 93658fb9 2020-03-18 stsp char *author;
141 93658fb9 2020-03-18 stsp char *committer;
142 93658fb9 2020-03-18 stsp char *msg;
143 93658fb9 2020-03-18 stsp int nmsg;
144 93658fb9 2020-03-18 stsp off_t ctime;
145 93658fb9 2020-03-18 stsp off_t mtime;
146 93658fb9 2020-03-18 stsp };
147 93658fb9 2020-03-18 stsp
148 93658fb9 2020-03-18 stsp typedef struct Buf Buf;
149 93658fb9 2020-03-18 stsp
150 93658fb9 2020-03-18 stsp struct Buf {
151 93658fb9 2020-03-18 stsp int len;
152 93658fb9 2020-03-18 stsp int sz;
153 93658fb9 2020-03-18 stsp char *data;
154 93658fb9 2020-03-18 stsp };
155 93658fb9 2020-03-18 stsp
156 93658fb9 2020-03-18 stsp static int readpacked(FILE *, Object *, int);
157 93658fb9 2020-03-18 stsp static Object *readidxobject(FILE *, struct got_object_id, int);
158 93658fb9 2020-03-18 stsp
159 93658fb9 2020-03-18 stsp struct got_object_idset *objcache;
160 93658fb9 2020-03-18 stsp int next_object_id;
161 93658fb9 2020-03-18 stsp Object *lruhead;
162 93658fb9 2020-03-18 stsp Object *lrutail;
163 93658fb9 2020-03-18 stsp int ncache;
164 93658fb9 2020-03-18 stsp
165 93658fb9 2020-03-18 stsp #define GETBE16(b)\
166 93658fb9 2020-03-18 stsp ((((b)[0] & 0xFFul) << 8) | \
167 93658fb9 2020-03-18 stsp (((b)[1] & 0xFFul) << 0))
168 93658fb9 2020-03-18 stsp
169 93658fb9 2020-03-18 stsp #define GETBE32(b)\
170 93658fb9 2020-03-18 stsp ((((b)[0] & 0xFFul) << 24) | \
171 93658fb9 2020-03-18 stsp (((b)[1] & 0xFFul) << 16) | \
172 93658fb9 2020-03-18 stsp (((b)[2] & 0xFFul) << 8) | \
173 93658fb9 2020-03-18 stsp (((b)[3] & 0xFFul) << 0))
174 93658fb9 2020-03-18 stsp #define GETBE64(b)\
175 93658fb9 2020-03-18 stsp ((((b)[0] & 0xFFull) << 56) | \
176 93658fb9 2020-03-18 stsp (((b)[1] & 0xFFull) << 48) | \
177 93658fb9 2020-03-18 stsp (((b)[2] & 0xFFull) << 40) | \
178 93658fb9 2020-03-18 stsp (((b)[3] & 0xFFull) << 32) | \
179 93658fb9 2020-03-18 stsp (((b)[4] & 0xFFull) << 24) | \
180 93658fb9 2020-03-18 stsp (((b)[5] & 0xFFull) << 16) | \
181 93658fb9 2020-03-18 stsp (((b)[6] & 0xFFull) << 8) | \
182 93658fb9 2020-03-18 stsp (((b)[7] & 0xFFull) << 0))
183 93658fb9 2020-03-18 stsp
184 93658fb9 2020-03-18 stsp #define PUTBE16(b, n)\
185 93658fb9 2020-03-18 stsp do{ \
186 93658fb9 2020-03-18 stsp (b)[0] = (n) >> 8; \
187 93658fb9 2020-03-18 stsp (b)[1] = (n) >> 0; \
188 93658fb9 2020-03-18 stsp } while(0)
189 93658fb9 2020-03-18 stsp
190 93658fb9 2020-03-18 stsp #define PUTBE32(b, n)\
191 93658fb9 2020-03-18 stsp do{ \
192 93658fb9 2020-03-18 stsp (b)[0] = (n) >> 24; \
193 93658fb9 2020-03-18 stsp (b)[1] = (n) >> 16; \
194 93658fb9 2020-03-18 stsp (b)[2] = (n) >> 8; \
195 93658fb9 2020-03-18 stsp (b)[3] = (n) >> 0; \
196 93658fb9 2020-03-18 stsp } while(0)
197 93658fb9 2020-03-18 stsp
198 93658fb9 2020-03-18 stsp #define PUTBE64(b, n)\
199 93658fb9 2020-03-18 stsp do{ \
200 93658fb9 2020-03-18 stsp (b)[0] = (n) >> 56; \
201 93658fb9 2020-03-18 stsp (b)[1] = (n) >> 48; \
202 93658fb9 2020-03-18 stsp (b)[2] = (n) >> 40; \
203 93658fb9 2020-03-18 stsp (b)[3] = (n) >> 32; \
204 93658fb9 2020-03-18 stsp (b)[4] = (n) >> 24; \
205 93658fb9 2020-03-18 stsp (b)[5] = (n) >> 16; \
206 93658fb9 2020-03-18 stsp (b)[6] = (n) >> 8; \
207 93658fb9 2020-03-18 stsp (b)[7] = (n) >> 0; \
208 93658fb9 2020-03-18 stsp } while(0)
209 93658fb9 2020-03-18 stsp
210 93658fb9 2020-03-18 stsp static int
211 93658fb9 2020-03-18 stsp charval(int c, int *err)
212 93658fb9 2020-03-18 stsp {
213 93658fb9 2020-03-18 stsp if(c >= '0' && c <= '9')
214 93658fb9 2020-03-18 stsp return c - '0';
215 93658fb9 2020-03-18 stsp if(c >= 'a' && c <= 'f')
216 93658fb9 2020-03-18 stsp return c - 'a' + 10;
217 93658fb9 2020-03-18 stsp if(c >= 'A' && c <= 'F')
218 93658fb9 2020-03-18 stsp return c - 'A' + 10;
219 93658fb9 2020-03-18 stsp *err = 1;
220 93658fb9 2020-03-18 stsp return -1;
221 93658fb9 2020-03-18 stsp }
222 93658fb9 2020-03-18 stsp
223 93658fb9 2020-03-18 stsp static int
224 93658fb9 2020-03-18 stsp hparse(struct got_object_id *h, char *b)
225 93658fb9 2020-03-18 stsp {
226 93658fb9 2020-03-18 stsp int i, err;
227 93658fb9 2020-03-18 stsp
228 93658fb9 2020-03-18 stsp err = 0;
229 93658fb9 2020-03-18 stsp for(i = 0; i < sizeof(h->sha1); i++){
230 93658fb9 2020-03-18 stsp err = 0;
231 93658fb9 2020-03-18 stsp h->sha1[i] = 0;
232 93658fb9 2020-03-18 stsp h->sha1[i] |= ((charval(b[2*i], &err) & 0xf) << 4);
233 93658fb9 2020-03-18 stsp h->sha1[i] |= ((charval(b[2*i+1], &err)& 0xf) << 0);
234 93658fb9 2020-03-18 stsp if(err)
235 93658fb9 2020-03-18 stsp return -1;
236 93658fb9 2020-03-18 stsp }
237 93658fb9 2020-03-18 stsp return 0;
238 93658fb9 2020-03-18 stsp }
239 93658fb9 2020-03-18 stsp
240 93658fb9 2020-03-18 stsp static void *
241 93658fb9 2020-03-18 stsp emalloc(size_t n)
242 93658fb9 2020-03-18 stsp {
243 93658fb9 2020-03-18 stsp void *v;
244 93658fb9 2020-03-18 stsp
245 93658fb9 2020-03-18 stsp v = calloc(n, 1);
246 93658fb9 2020-03-18 stsp if(v == NULL)
247 93658fb9 2020-03-18 stsp err(1, "malloc:");
248 93658fb9 2020-03-18 stsp return v;
249 93658fb9 2020-03-18 stsp }
250 93658fb9 2020-03-18 stsp
251 93658fb9 2020-03-18 stsp static void *
252 93658fb9 2020-03-18 stsp erealloc(void *p, ulong n)
253 93658fb9 2020-03-18 stsp {
254 93658fb9 2020-03-18 stsp void *v;
255 93658fb9 2020-03-18 stsp
256 93658fb9 2020-03-18 stsp v = realloc(p, n);
257 93658fb9 2020-03-18 stsp if(v == NULL)
258 93658fb9 2020-03-18 stsp err(1, "realloc:");
259 93658fb9 2020-03-18 stsp memset(v, 0, n);
260 93658fb9 2020-03-18 stsp return v;
261 93658fb9 2020-03-18 stsp }
262 93658fb9 2020-03-18 stsp
263 93658fb9 2020-03-18 stsp static int
264 93658fb9 2020-03-18 stsp hasheq(struct got_object_id *a, struct got_object_id *b)
265 93658fb9 2020-03-18 stsp {
266 93658fb9 2020-03-18 stsp return memcmp(a->sha1, b->sha1, sizeof(a->sha1)) == 0;
267 93658fb9 2020-03-18 stsp }
268 93658fb9 2020-03-18 stsp
269 93658fb9 2020-03-18 stsp static char *
270 93658fb9 2020-03-18 stsp typestr(int t)
271 93658fb9 2020-03-18 stsp {
272 93658fb9 2020-03-18 stsp char *types[] = {
273 93658fb9 2020-03-18 stsp "???",
274 93658fb9 2020-03-18 stsp "commit",
275 93658fb9 2020-03-18 stsp "tree",
276 93658fb9 2020-03-18 stsp "blob",
277 93658fb9 2020-03-18 stsp "tag",
278 93658fb9 2020-03-18 stsp "odelta",
279 93658fb9 2020-03-18 stsp "rdelta",
280 93658fb9 2020-03-18 stsp };
281 93658fb9 2020-03-18 stsp if (t < 0 || t >= sizeof(types)/sizeof(types[0]))
282 93658fb9 2020-03-18 stsp abort();
283 93658fb9 2020-03-18 stsp return types[t];
284 93658fb9 2020-03-18 stsp }
285 93658fb9 2020-03-18 stsp
286 93658fb9 2020-03-18 stsp static char *
287 93658fb9 2020-03-18 stsp hashfmt(char *out, size_t nout, struct got_object_id *h)
288 93658fb9 2020-03-18 stsp {
289 93658fb9 2020-03-18 stsp int i, n, c0, c1;
290 93658fb9 2020-03-18 stsp char *p;
291 93658fb9 2020-03-18 stsp
292 93658fb9 2020-03-18 stsp if (nout < 2*sizeof(h->sha1) + 1)
293 93658fb9 2020-03-18 stsp return NULL;
294 93658fb9 2020-03-18 stsp p = out;
295 93658fb9 2020-03-18 stsp for(i = 0; i < sizeof(h->sha1); i++){
296 93658fb9 2020-03-18 stsp n = (h->sha1[i] >> 4) & 0xf;
297 93658fb9 2020-03-18 stsp c0 = (n >= 10) ? n-10 + 'a' : n + '0';
298 93658fb9 2020-03-18 stsp n = h->sha1[i] & 0xf;
299 93658fb9 2020-03-18 stsp c1 = (n >= 10) ? n-10 + 'a' : n + '0';
300 93658fb9 2020-03-18 stsp *p++ = c0;
301 93658fb9 2020-03-18 stsp *p++ = c1;
302 93658fb9 2020-03-18 stsp }
303 93658fb9 2020-03-18 stsp *p++ = 0;
304 93658fb9 2020-03-18 stsp return out;
305 93658fb9 2020-03-18 stsp }
306 93658fb9 2020-03-18 stsp
307 93658fb9 2020-03-18 stsp static void
308 93658fb9 2020-03-18 stsp clear(Object *o)
309 93658fb9 2020-03-18 stsp {
310 93658fb9 2020-03-18 stsp if(!o)
311 93658fb9 2020-03-18 stsp return;
312 93658fb9 2020-03-18 stsp
313 93658fb9 2020-03-18 stsp assert(o->refs == 0);
314 93658fb9 2020-03-18 stsp assert((o->flag & Ccache) == 0);
315 93658fb9 2020-03-18 stsp assert(o->flag & Cloaded);
316 93658fb9 2020-03-18 stsp switch(o->type){
317 93658fb9 2020-03-18 stsp case GCommit:
318 93658fb9 2020-03-18 stsp if(!o->commit)
319 93658fb9 2020-03-18 stsp break;
320 93658fb9 2020-03-18 stsp free(o->commit->parent);
321 93658fb9 2020-03-18 stsp free(o->commit->author);
322 93658fb9 2020-03-18 stsp free(o->commit->committer);
323 93658fb9 2020-03-18 stsp free(o->commit);
324 93658fb9 2020-03-18 stsp o->commit = NULL;
325 93658fb9 2020-03-18 stsp break;
326 93658fb9 2020-03-18 stsp case GTree:
327 93658fb9 2020-03-18 stsp if(!o->tree)
328 93658fb9 2020-03-18 stsp break;
329 93658fb9 2020-03-18 stsp free(o->tree->ent);
330 93658fb9 2020-03-18 stsp free(o->tree);
331 93658fb9 2020-03-18 stsp o->tree = NULL;
332 93658fb9 2020-03-18 stsp break;
333 93658fb9 2020-03-18 stsp default:
334 93658fb9 2020-03-18 stsp break;
335 93658fb9 2020-03-18 stsp }
336 93658fb9 2020-03-18 stsp
337 93658fb9 2020-03-18 stsp free(o->all);
338 93658fb9 2020-03-18 stsp o->all = NULL;
339 93658fb9 2020-03-18 stsp o->data = NULL;
340 93658fb9 2020-03-18 stsp o->flag &= ~Cloaded;
341 93658fb9 2020-03-18 stsp }
342 93658fb9 2020-03-18 stsp
343 93658fb9 2020-03-18 stsp static void
344 93658fb9 2020-03-18 stsp unref(Object *o)
345 93658fb9 2020-03-18 stsp {
346 93658fb9 2020-03-18 stsp if(!o)
347 93658fb9 2020-03-18 stsp return;
348 93658fb9 2020-03-18 stsp o->refs--;
349 93658fb9 2020-03-18 stsp if(!o->refs)
350 93658fb9 2020-03-18 stsp clear(o);
351 93658fb9 2020-03-18 stsp }
352 93658fb9 2020-03-18 stsp
353 93658fb9 2020-03-18 stsp static Object*
354 93658fb9 2020-03-18 stsp ref(Object *o)
355 93658fb9 2020-03-18 stsp {
356 93658fb9 2020-03-18 stsp o->refs++;
357 93658fb9 2020-03-18 stsp return o;
358 93658fb9 2020-03-18 stsp }
359 93658fb9 2020-03-18 stsp
360 93658fb9 2020-03-18 stsp static void
361 93658fb9 2020-03-18 stsp cache(Object *o)
362 93658fb9 2020-03-18 stsp {
363 93658fb9 2020-03-18 stsp char buf[41];
364 93658fb9 2020-03-18 stsp Object *p;
365 93658fb9 2020-03-18 stsp
366 93658fb9 2020-03-18 stsp hashfmt(buf, sizeof(buf), &o->hash);
367 93658fb9 2020-03-18 stsp if(o == lruhead)
368 93658fb9 2020-03-18 stsp return;
369 93658fb9 2020-03-18 stsp if(o == lrutail)
370 93658fb9 2020-03-18 stsp lrutail = lrutail->prev;
371 93658fb9 2020-03-18 stsp if(!(o->flag & Cexist)){
372 93658fb9 2020-03-18 stsp got_object_idset_add(objcache, &o->hash, o);
373 93658fb9 2020-03-18 stsp o->id = next_object_id++;
374 93658fb9 2020-03-18 stsp o->flag |= Cexist;
375 93658fb9 2020-03-18 stsp }
376 93658fb9 2020-03-18 stsp if(o->prev)
377 93658fb9 2020-03-18 stsp o->prev->next = o->next;
378 93658fb9 2020-03-18 stsp if(o->next)
379 93658fb9 2020-03-18 stsp o->next->prev = o->prev;
380 93658fb9 2020-03-18 stsp if(lrutail == o){
381 93658fb9 2020-03-18 stsp lrutail = o->prev;
382 93658fb9 2020-03-18 stsp lrutail->next = NULL;
383 93658fb9 2020-03-18 stsp }else if(!lrutail)
384 93658fb9 2020-03-18 stsp lrutail = o;
385 93658fb9 2020-03-18 stsp if(lruhead)
386 93658fb9 2020-03-18 stsp lruhead->prev = o;
387 93658fb9 2020-03-18 stsp o->next = lruhead;
388 93658fb9 2020-03-18 stsp o->prev = NULL;
389 93658fb9 2020-03-18 stsp lruhead = o;
390 93658fb9 2020-03-18 stsp
391 93658fb9 2020-03-18 stsp if(!(o->flag & Ccache)){
392 93658fb9 2020-03-18 stsp o->flag |= Ccache;
393 93658fb9 2020-03-18 stsp ref(o);
394 93658fb9 2020-03-18 stsp ncache++;
395 93658fb9 2020-03-18 stsp }
396 93658fb9 2020-03-18 stsp while(ncache > Cachemax){
397 93658fb9 2020-03-18 stsp p = lrutail;
398 93658fb9 2020-03-18 stsp lrutail = p->prev;
399 93658fb9 2020-03-18 stsp lrutail->next = NULL;
400 93658fb9 2020-03-18 stsp p->flag &= ~Ccache;
401 93658fb9 2020-03-18 stsp p->prev = NULL;
402 93658fb9 2020-03-18 stsp p->next = NULL;
403 93658fb9 2020-03-18 stsp unref(p);
404 93658fb9 2020-03-18 stsp ncache--;
405 93658fb9 2020-03-18 stsp }
406 93658fb9 2020-03-18 stsp }
407 93658fb9 2020-03-18 stsp
408 93658fb9 2020-03-18 stsp static int
409 93658fb9 2020-03-18 stsp preadbe32(FILE *b, int *v, off_t off)
410 93658fb9 2020-03-18 stsp {
411 93658fb9 2020-03-18 stsp char buf[4];
412 93658fb9 2020-03-18 stsp
413 93658fb9 2020-03-18 stsp if(fseek(b, off, 0) == -1)
414 93658fb9 2020-03-18 stsp return -1;
415 93658fb9 2020-03-18 stsp if(fread(buf, 1, sizeof(buf), b) == -1)
416 93658fb9 2020-03-18 stsp return -1;
417 93658fb9 2020-03-18 stsp *v = GETBE32(buf);
418 93658fb9 2020-03-18 stsp
419 93658fb9 2020-03-18 stsp return 0;
420 93658fb9 2020-03-18 stsp }
421 93658fb9 2020-03-18 stsp static int
422 93658fb9 2020-03-18 stsp preadbe64(FILE *b, off_t *v, off_t off)
423 93658fb9 2020-03-18 stsp {
424 93658fb9 2020-03-18 stsp char buf[8];
425 93658fb9 2020-03-18 stsp
426 93658fb9 2020-03-18 stsp if(fseek(b, off, 0) == -1)
427 93658fb9 2020-03-18 stsp return -1;
428 93658fb9 2020-03-18 stsp if(fread(buf, 1, sizeof(buf), b) == -1)
429 93658fb9 2020-03-18 stsp return -1;
430 93658fb9 2020-03-18 stsp *v = GETBE64(buf);
431 93658fb9 2020-03-18 stsp return 0;
432 93658fb9 2020-03-18 stsp }
433 93658fb9 2020-03-18 stsp
434 93658fb9 2020-03-18 stsp static int
435 93658fb9 2020-03-18 stsp readvint(char *p, char **pp)
436 93658fb9 2020-03-18 stsp {
437 93658fb9 2020-03-18 stsp int i, n, c;
438 93658fb9 2020-03-18 stsp
439 93658fb9 2020-03-18 stsp i = 0;
440 93658fb9 2020-03-18 stsp n = 0;
441 93658fb9 2020-03-18 stsp do {
442 93658fb9 2020-03-18 stsp c = *p++;
443 93658fb9 2020-03-18 stsp n |= (c & 0x7f) << i;
444 93658fb9 2020-03-18 stsp i += 7;
445 93658fb9 2020-03-18 stsp } while (c & 0x80);
446 93658fb9 2020-03-18 stsp *pp = p;
447 93658fb9 2020-03-18 stsp
448 93658fb9 2020-03-18 stsp return n;
449 93658fb9 2020-03-18 stsp }
450 93658fb9 2020-03-18 stsp
451 93658fb9 2020-03-18 stsp static int
452 93658fb9 2020-03-18 stsp applydelta(Object *dst, Object *base, char *d, int nd)
453 93658fb9 2020-03-18 stsp {
454 93658fb9 2020-03-18 stsp char *r, *b, *ed, *er;
455 93658fb9 2020-03-18 stsp int n, nr, c;
456 93658fb9 2020-03-18 stsp off_t o, l;
457 93658fb9 2020-03-18 stsp
458 93658fb9 2020-03-18 stsp ed = d + nd;
459 93658fb9 2020-03-18 stsp b = base->data;
460 93658fb9 2020-03-18 stsp n = readvint(d, &d);
461 93658fb9 2020-03-18 stsp if(n != base->size){
462 93658fb9 2020-03-18 stsp fprintf(stderr, "mismatched source size");
463 93658fb9 2020-03-18 stsp return -1;
464 93658fb9 2020-03-18 stsp }
465 93658fb9 2020-03-18 stsp
466 93658fb9 2020-03-18 stsp nr = readvint(d, &d);
467 93658fb9 2020-03-18 stsp r = emalloc(nr + 64);
468 93658fb9 2020-03-18 stsp n = snprintf(r, 64, "%s %d", typestr(base->type), nr) + 1;
469 93658fb9 2020-03-18 stsp dst->all = r;
470 93658fb9 2020-03-18 stsp dst->type = base->type;
471 93658fb9 2020-03-18 stsp dst->data = r + n;
472 93658fb9 2020-03-18 stsp dst->size = nr;
473 93658fb9 2020-03-18 stsp er = dst->data + nr;
474 93658fb9 2020-03-18 stsp r = dst->data;
475 93658fb9 2020-03-18 stsp
476 93658fb9 2020-03-18 stsp while(1){
477 93658fb9 2020-03-18 stsp if(d == ed)
478 93658fb9 2020-03-18 stsp break;
479 93658fb9 2020-03-18 stsp c = *d++;
480 93658fb9 2020-03-18 stsp if(!c){
481 93658fb9 2020-03-18 stsp fprintf(stderr, "bad delta encoding");
482 93658fb9 2020-03-18 stsp return -1;
483 93658fb9 2020-03-18 stsp }
484 93658fb9 2020-03-18 stsp /* copy from base */
485 93658fb9 2020-03-18 stsp if(c & 0x80){
486 93658fb9 2020-03-18 stsp o = 0;
487 93658fb9 2020-03-18 stsp l = 0;
488 93658fb9 2020-03-18 stsp /* Offset in base */
489 93658fb9 2020-03-18 stsp if(c & 0x01 && d != ed) o |= (*d++ << 0) & 0x000000ff;
490 93658fb9 2020-03-18 stsp if(c & 0x02 && d != ed) o |= (*d++ << 8) & 0x0000ff00;
491 93658fb9 2020-03-18 stsp if(c & 0x04 && d != ed) o |= (*d++ << 16) & 0x00ff0000;
492 93658fb9 2020-03-18 stsp if(c & 0x08 && d != ed) o |= (*d++ << 24) & 0xff000000;
493 93658fb9 2020-03-18 stsp
494 93658fb9 2020-03-18 stsp /* Length to copy */
495 93658fb9 2020-03-18 stsp if(c & 0x10 && d != ed) l |= (*d++ << 0) & 0x0000ff;
496 93658fb9 2020-03-18 stsp if(c & 0x20 && d != ed) l |= (*d++ << 8) & 0x00ff00;
497 93658fb9 2020-03-18 stsp if(c & 0x40 && d != ed) l |= (*d++ << 16) & 0xff0000;
498 93658fb9 2020-03-18 stsp if(l == 0) l = 0x10000;
499 93658fb9 2020-03-18 stsp
500 93658fb9 2020-03-18 stsp assert(o + l <= base->size);
501 93658fb9 2020-03-18 stsp memmove(r, b + o, l);
502 93658fb9 2020-03-18 stsp r += l;
503 93658fb9 2020-03-18 stsp /* inline data */
504 93658fb9 2020-03-18 stsp }else{
505 93658fb9 2020-03-18 stsp memmove(r, d, c);
506 93658fb9 2020-03-18 stsp d += c;
507 93658fb9 2020-03-18 stsp r += c;
508 93658fb9 2020-03-18 stsp }
509 93658fb9 2020-03-18 stsp
510 93658fb9 2020-03-18 stsp }
511 93658fb9 2020-03-18 stsp if(r != er){
512 93658fb9 2020-03-18 stsp fprintf(stderr, "truncated delta (%zd)", er - r);
513 93658fb9 2020-03-18 stsp return -1;
514 93658fb9 2020-03-18 stsp }
515 93658fb9 2020-03-18 stsp
516 93658fb9 2020-03-18 stsp return nr;
517 93658fb9 2020-03-18 stsp }
518 93658fb9 2020-03-18 stsp
519 93658fb9 2020-03-18 stsp static int
520 93658fb9 2020-03-18 stsp readrdelta(FILE *f, Object *o, int nd, int flag)
521 93658fb9 2020-03-18 stsp {
522 93658fb9 2020-03-18 stsp const struct got_error *e;
523 93658fb9 2020-03-18 stsp struct got_object_id h;
524 93658fb9 2020-03-18 stsp Object *b;
525 93658fb9 2020-03-18 stsp uint8_t *d;
526 93658fb9 2020-03-18 stsp size_t n;
527 93658fb9 2020-03-18 stsp
528 93658fb9 2020-03-18 stsp d = NULL;
529 93658fb9 2020-03-18 stsp if(fread(h.sha1, 1, sizeof(h.sha1), f) != sizeof(h.sha1))
530 93658fb9 2020-03-18 stsp goto error;
531 93658fb9 2020-03-18 stsp if(hasheq(&o->hash, &h))
532 93658fb9 2020-03-18 stsp goto error;
533 93658fb9 2020-03-18 stsp if ((e = got_inflate_to_mem(&d, &n, f)) != NULL)
534 93658fb9 2020-03-18 stsp goto error;
535 93658fb9 2020-03-18 stsp o->len = ftello(f) - o->off;
536 93658fb9 2020-03-18 stsp if(d == NULL || n != nd)
537 93658fb9 2020-03-18 stsp goto error;
538 93658fb9 2020-03-18 stsp if((b = readidxobject(f, h, flag)) == NULL)
539 93658fb9 2020-03-18 stsp goto error;
540 93658fb9 2020-03-18 stsp if(applydelta(o, b, d, n) == -1)
541 93658fb9 2020-03-18 stsp goto error;
542 93658fb9 2020-03-18 stsp free(d);
543 93658fb9 2020-03-18 stsp return 0;
544 93658fb9 2020-03-18 stsp error:
545 93658fb9 2020-03-18 stsp free(d);
546 93658fb9 2020-03-18 stsp return -1;
547 93658fb9 2020-03-18 stsp }
548 93658fb9 2020-03-18 stsp
549 93658fb9 2020-03-18 stsp static int
550 93658fb9 2020-03-18 stsp readodelta(FILE *f, Object *o, off_t nd, off_t p, int flag)
551 93658fb9 2020-03-18 stsp {
552 93658fb9 2020-03-18 stsp Object b;
553 93658fb9 2020-03-18 stsp uint8_t *d;
554 93658fb9 2020-03-18 stsp off_t r;
555 93658fb9 2020-03-18 stsp size_t n;
556 93658fb9 2020-03-18 stsp int c;
557 93658fb9 2020-03-18 stsp
558 93658fb9 2020-03-18 stsp r = 0;
559 93658fb9 2020-03-18 stsp d = NULL;
560 93658fb9 2020-03-18 stsp while(1){
561 93658fb9 2020-03-18 stsp if((c = fgetc(f)) == -1)
562 93658fb9 2020-03-18 stsp goto error;
563 93658fb9 2020-03-18 stsp r |= c & 0x7f;
564 93658fb9 2020-03-18 stsp if (!(c & 0x80))
565 93658fb9 2020-03-18 stsp break;
566 93658fb9 2020-03-18 stsp r++;
567 93658fb9 2020-03-18 stsp r <<= 7;
568 93658fb9 2020-03-18 stsp }while(c & 0x80);
569 93658fb9 2020-03-18 stsp
570 93658fb9 2020-03-18 stsp if(r > p){
571 93658fb9 2020-03-18 stsp fprintf(stderr, "junk offset -%lld (from %lld)", r, p);
572 93658fb9 2020-03-18 stsp goto error;
573 93658fb9 2020-03-18 stsp }
574 93658fb9 2020-03-18 stsp
575 93658fb9 2020-03-18 stsp if (got_inflate_to_mem(&d, &n, f) == NULL)
576 93658fb9 2020-03-18 stsp goto error;
577 93658fb9 2020-03-18 stsp o->len = ftello(f) - o->off;
578 93658fb9 2020-03-18 stsp if(d == NULL || n != nd)
579 93658fb9 2020-03-18 stsp goto error;
580 93658fb9 2020-03-18 stsp if(fseek(f, p - r, 0) == -1)
581 93658fb9 2020-03-18 stsp goto error;
582 93658fb9 2020-03-18 stsp if(readpacked(f, &b, flag) == -1)
583 93658fb9 2020-03-18 stsp goto error;
584 93658fb9 2020-03-18 stsp if(applydelta(o, &b, d, nd) == -1)
585 93658fb9 2020-03-18 stsp goto error;
586 93658fb9 2020-03-18 stsp free(d);
587 93658fb9 2020-03-18 stsp return 0;
588 93658fb9 2020-03-18 stsp error:
589 93658fb9 2020-03-18 stsp free(d);
590 93658fb9 2020-03-18 stsp return -1;
591 93658fb9 2020-03-18 stsp }
592 93658fb9 2020-03-18 stsp
593 93658fb9 2020-03-18 stsp static int
594 93658fb9 2020-03-18 stsp readpacked(FILE *f, Object *o, int flag)
595 93658fb9 2020-03-18 stsp {
596 93658fb9 2020-03-18 stsp const struct got_error *e;
597 93658fb9 2020-03-18 stsp int c, s, n;
598 93658fb9 2020-03-18 stsp off_t l, p;
599 93658fb9 2020-03-18 stsp size_t ndata;
600 93658fb9 2020-03-18 stsp uint8_t *data;
601 93658fb9 2020-03-18 stsp Type t;
602 93658fb9 2020-03-18 stsp Buf b;
603 93658fb9 2020-03-18 stsp
604 93658fb9 2020-03-18 stsp p = ftello(f);
605 93658fb9 2020-03-18 stsp c = fgetc(f);
606 93658fb9 2020-03-18 stsp if(c == -1)
607 93658fb9 2020-03-18 stsp return -1;
608 93658fb9 2020-03-18 stsp l = c & 0xf;
609 93658fb9 2020-03-18 stsp s = 4;
610 93658fb9 2020-03-18 stsp t = (c >> 4) & 0x7;
611 93658fb9 2020-03-18 stsp if(!t){
612 93658fb9 2020-03-18 stsp fprintf(stderr, "unknown type for byte %x", c);
613 93658fb9 2020-03-18 stsp return -1;
614 93658fb9 2020-03-18 stsp }
615 93658fb9 2020-03-18 stsp while(c & 0x80){
616 93658fb9 2020-03-18 stsp if((c = fgetc(f)) == -1)
617 93658fb9 2020-03-18 stsp return -1;
618 93658fb9 2020-03-18 stsp l |= (c & 0x7f) << s;
619 93658fb9 2020-03-18 stsp s += 7;
620 93658fb9 2020-03-18 stsp }
621 93658fb9 2020-03-18 stsp
622 93658fb9 2020-03-18 stsp switch(t){
623 93658fb9 2020-03-18 stsp default:
624 93658fb9 2020-03-18 stsp fprintf(stderr, "invalid object at %lld", ftello(f));
625 93658fb9 2020-03-18 stsp return -1;
626 93658fb9 2020-03-18 stsp case GCommit:
627 93658fb9 2020-03-18 stsp case GTree:
628 93658fb9 2020-03-18 stsp case GTag:
629 93658fb9 2020-03-18 stsp case GBlob:
630 93658fb9 2020-03-18 stsp b.sz = 64 + l;
631 93658fb9 2020-03-18 stsp
632 93658fb9 2020-03-18 stsp b.data = emalloc(b.sz);
633 93658fb9 2020-03-18 stsp n = snprintf(b.data, 64, "%s %lld", typestr(t), l) + 1;
634 93658fb9 2020-03-18 stsp b.len = n;
635 93658fb9 2020-03-18 stsp e = got_inflate_to_mem(&data, &ndata, f);
636 93658fb9 2020-03-18 stsp if (e != NULL || n + ndata >= b.sz) {
637 93658fb9 2020-03-18 stsp free(b.data);
638 93658fb9 2020-03-18 stsp return -1;
639 93658fb9 2020-03-18 stsp }
640 93658fb9 2020-03-18 stsp memcpy(b.data + n, data, ndata);
641 93658fb9 2020-03-18 stsp o->len = ftello(f) - o->off;
642 93658fb9 2020-03-18 stsp o->type = t;
643 93658fb9 2020-03-18 stsp o->all = b.data;
644 93658fb9 2020-03-18 stsp o->data = b.data + n;
645 93658fb9 2020-03-18 stsp o->size = ndata;
646 93658fb9 2020-03-18 stsp free(data);
647 93658fb9 2020-03-18 stsp break;
648 93658fb9 2020-03-18 stsp case GOdelta:
649 93658fb9 2020-03-18 stsp if(readodelta(f, o, l, p, flag) == -1)
650 93658fb9 2020-03-18 stsp return -1;
651 93658fb9 2020-03-18 stsp break;
652 93658fb9 2020-03-18 stsp case GRdelta:
653 93658fb9 2020-03-18 stsp if(readrdelta(f, o, l, flag) == -1)
654 93658fb9 2020-03-18 stsp return -1;
655 93658fb9 2020-03-18 stsp break;
656 93658fb9 2020-03-18 stsp }
657 93658fb9 2020-03-18 stsp o->flag |= Cloaded|flag;
658 93658fb9 2020-03-18 stsp return 0;
659 93658fb9 2020-03-18 stsp }
660 93658fb9 2020-03-18 stsp
661 93658fb9 2020-03-18 stsp static int
662 93658fb9 2020-03-18 stsp readloose(FILE *f, Object *o, int flag)
663 93658fb9 2020-03-18 stsp {
664 93658fb9 2020-03-18 stsp struct { char *tag; int type; } *p, types[] = {
665 93658fb9 2020-03-18 stsp {"blob", GBlob},
666 93658fb9 2020-03-18 stsp {"tree", GTree},
667 93658fb9 2020-03-18 stsp {"commit", GCommit},
668 93658fb9 2020-03-18 stsp {"tag", GTag},
669 93658fb9 2020-03-18 stsp {NULL},
670 93658fb9 2020-03-18 stsp };
671 93658fb9 2020-03-18 stsp char *s, *e;
672 93658fb9 2020-03-18 stsp uint8_t *d;
673 93658fb9 2020-03-18 stsp off_t sz;
674 93658fb9 2020-03-18 stsp size_t n;
675 93658fb9 2020-03-18 stsp int l;
676 93658fb9 2020-03-18 stsp
677 93658fb9 2020-03-18 stsp if (got_inflate_to_mem(&d, &n, f) != NULL)
678 93658fb9 2020-03-18 stsp return -1;
679 93658fb9 2020-03-18 stsp
680 93658fb9 2020-03-18 stsp s = (char *)d;
681 93658fb9 2020-03-18 stsp o->type = GNone;
682 93658fb9 2020-03-18 stsp for(p = types; p->tag; p++){
683 93658fb9 2020-03-18 stsp l = strlen(p->tag);
684 93658fb9 2020-03-18 stsp if(strncmp(s, p->tag, l) == 0){
685 93658fb9 2020-03-18 stsp s += l;
686 93658fb9 2020-03-18 stsp o->type = p->type;
687 93658fb9 2020-03-18 stsp while(!isspace(*s))
688 93658fb9 2020-03-18 stsp s++;
689 93658fb9 2020-03-18 stsp break;
690 93658fb9 2020-03-18 stsp }
691 93658fb9 2020-03-18 stsp }
692 93658fb9 2020-03-18 stsp if(o->type == GNone){
693 93658fb9 2020-03-18 stsp free(o->data);
694 93658fb9 2020-03-18 stsp return -1;
695 93658fb9 2020-03-18 stsp }
696 93658fb9 2020-03-18 stsp sz = strtol(s, &e, 0);
697 93658fb9 2020-03-18 stsp if(e == s || *e++ != 0){
698 93658fb9 2020-03-18 stsp fprintf(stderr, "malformed object header");
699 93658fb9 2020-03-18 stsp goto error;
700 93658fb9 2020-03-18 stsp }
701 93658fb9 2020-03-18 stsp if(sz != n - (e - (char *)d)){
702 93658fb9 2020-03-18 stsp fprintf(stderr, "mismatched sizes");
703 93658fb9 2020-03-18 stsp goto error;
704 93658fb9 2020-03-18 stsp }
705 93658fb9 2020-03-18 stsp o->size = sz;
706 93658fb9 2020-03-18 stsp o->data = e;
707 93658fb9 2020-03-18 stsp o->all = d;
708 93658fb9 2020-03-18 stsp o->flag |= Cloaded|flag;
709 93658fb9 2020-03-18 stsp return 0;
710 93658fb9 2020-03-18 stsp
711 93658fb9 2020-03-18 stsp error:
712 93658fb9 2020-03-18 stsp free(d);
713 93658fb9 2020-03-18 stsp return -1;
714 93658fb9 2020-03-18 stsp }
715 93658fb9 2020-03-18 stsp
716 93658fb9 2020-03-18 stsp static off_t
717 93658fb9 2020-03-18 stsp searchindex(FILE *f, struct got_object_id h)
718 93658fb9 2020-03-18 stsp {
719 93658fb9 2020-03-18 stsp int lo, hi, idx, i, nent;
720 93658fb9 2020-03-18 stsp off_t o, oo;
721 93658fb9 2020-03-18 stsp struct got_object_id hh;
722 93658fb9 2020-03-18 stsp
723 93658fb9 2020-03-18 stsp o = 8;
724 93658fb9 2020-03-18 stsp /*
725 93658fb9 2020-03-18 stsp * Read the fanout table. The fanout table
726 93658fb9 2020-03-18 stsp * contains 256 entries, corresponsding to
727 93658fb9 2020-03-18 stsp * the first byte of the hash. Each entry
728 93658fb9 2020-03-18 stsp * is a 4 byte big endian integer, containing
729 93658fb9 2020-03-18 stsp * the total number of entries with a leading
730 93658fb9 2020-03-18 stsp * byte <= the table index, allowing us to
731 93658fb9 2020-03-18 stsp * rapidly do a binary search on them.
732 93658fb9 2020-03-18 stsp */
733 93658fb9 2020-03-18 stsp if (h.sha1[0] == 0){
734 93658fb9 2020-03-18 stsp lo = 0;
735 93658fb9 2020-03-18 stsp if(preadbe32(f, &hi, o) == -1)
736 93658fb9 2020-03-18 stsp goto err;
737 93658fb9 2020-03-18 stsp } else {
738 93658fb9 2020-03-18 stsp o += h.sha1[0]*4 - 4;
739 93658fb9 2020-03-18 stsp if(preadbe32(f, &lo, o + 0) == -1)
740 93658fb9 2020-03-18 stsp goto err;
741 93658fb9 2020-03-18 stsp if(preadbe32(f, &hi, o + 4) == -1)
742 93658fb9 2020-03-18 stsp goto err;
743 93658fb9 2020-03-18 stsp }
744 93658fb9 2020-03-18 stsp if(hi == lo)
745 93658fb9 2020-03-18 stsp goto notfound;
746 93658fb9 2020-03-18 stsp if(preadbe32(f, &nent, 8 + 255*4) == -1)
747 93658fb9 2020-03-18 stsp goto err;
748 93658fb9 2020-03-18 stsp
749 93658fb9 2020-03-18 stsp /*
750 93658fb9 2020-03-18 stsp * Now that we know the range of hashes that the
751 93658fb9 2020-03-18 stsp * entry may exist in, read them in so we can do
752 93658fb9 2020-03-18 stsp * a bsearch.
753 93658fb9 2020-03-18 stsp */
754 93658fb9 2020-03-18 stsp idx = -1;
755 93658fb9 2020-03-18 stsp fseek(f, Hashsz*lo + 8 + 256*4, 0);
756 93658fb9 2020-03-18 stsp for(i = 0; i < hi - lo; i++){
757 93658fb9 2020-03-18 stsp if(fread(hh.sha1, 1, sizeof(hh.sha1), f) == -1)
758 93658fb9 2020-03-18 stsp goto err;
759 93658fb9 2020-03-18 stsp if(hasheq(&hh, &h))
760 93658fb9 2020-03-18 stsp idx = lo + i;
761 93658fb9 2020-03-18 stsp }
762 93658fb9 2020-03-18 stsp if(idx == -1)
763 93658fb9 2020-03-18 stsp goto notfound;
764 93658fb9 2020-03-18 stsp
765 93658fb9 2020-03-18 stsp
766 93658fb9 2020-03-18 stsp /*
767 93658fb9 2020-03-18 stsp * We found the entry. If it's 32 bits, then we
768 93658fb9 2020-03-18 stsp * can just return the oset, otherwise the 32
769 93658fb9 2020-03-18 stsp * bit entry contains the oset to the 64 bit
770 93658fb9 2020-03-18 stsp * entry.
771 93658fb9 2020-03-18 stsp */
772 93658fb9 2020-03-18 stsp oo = 8; /* Header */
773 93658fb9 2020-03-18 stsp oo += 256*4; /* Fanout table */
774 93658fb9 2020-03-18 stsp oo += Hashsz*nent; /* Hashes */
775 93658fb9 2020-03-18 stsp oo += 4*nent; /* Checksums */
776 93658fb9 2020-03-18 stsp oo += 4*idx; /* Offset offset */
777 93658fb9 2020-03-18 stsp if(preadbe32(f, &i, oo) == -1)
778 93658fb9 2020-03-18 stsp goto err;
779 93658fb9 2020-03-18 stsp o = i & 0xffffffff;
780 93658fb9 2020-03-18 stsp if(o & (1ull << 31)){
781 93658fb9 2020-03-18 stsp o &= 0x7fffffff;
782 93658fb9 2020-03-18 stsp if(preadbe64(f, &o, o) == -1)
783 93658fb9 2020-03-18 stsp goto err;
784 93658fb9 2020-03-18 stsp }
785 93658fb9 2020-03-18 stsp return o;
786 93658fb9 2020-03-18 stsp
787 93658fb9 2020-03-18 stsp err:
788 93658fb9 2020-03-18 stsp fprintf(stderr, "unable to read packfile\n");
789 93658fb9 2020-03-18 stsp return -1;
790 93658fb9 2020-03-18 stsp notfound:
791 93658fb9 2020-03-18 stsp {
792 93658fb9 2020-03-18 stsp char hstr[41];
793 93658fb9 2020-03-18 stsp hashfmt(hstr, sizeof(hstr), &h);
794 93658fb9 2020-03-18 stsp fprintf(stdout, "could not find object %s\n", hstr);
795 93658fb9 2020-03-18 stsp }
796 93658fb9 2020-03-18 stsp return -1;
797 93658fb9 2020-03-18 stsp }
798 93658fb9 2020-03-18 stsp
799 93658fb9 2020-03-18 stsp /*
800 93658fb9 2020-03-18 stsp * Scans for non-empty word, copying it into buf.
801 93658fb9 2020-03-18 stsp * Strips off word, leading, and trailing space
802 93658fb9 2020-03-18 stsp * from input.
803 93658fb9 2020-03-18 stsp *
804 93658fb9 2020-03-18 stsp * Returns -1 on empty string or error, leaving
805 93658fb9 2020-03-18 stsp * input unmodified.
806 93658fb9 2020-03-18 stsp */
807 93658fb9 2020-03-18 stsp static int
808 93658fb9 2020-03-18 stsp scanword(char **str, int *nstr, char *buf, int nbuf)
809 93658fb9 2020-03-18 stsp {
810 93658fb9 2020-03-18 stsp char *p;
811 93658fb9 2020-03-18 stsp int n, r;
812 93658fb9 2020-03-18 stsp
813 93658fb9 2020-03-18 stsp r = -1;
814 93658fb9 2020-03-18 stsp p = *str;
815 93658fb9 2020-03-18 stsp n = *nstr;
816 93658fb9 2020-03-18 stsp while(n && isblank(*p)){
817 93658fb9 2020-03-18 stsp n--;
818 93658fb9 2020-03-18 stsp p++;
819 93658fb9 2020-03-18 stsp }
820 93658fb9 2020-03-18 stsp
821 93658fb9 2020-03-18 stsp for(; n && *p && !isspace(*p); p++, n--){
822 93658fb9 2020-03-18 stsp r = 0;
823 93658fb9 2020-03-18 stsp *buf++ = *p;
824 93658fb9 2020-03-18 stsp nbuf--;
825 93658fb9 2020-03-18 stsp if(nbuf == 0)
826 93658fb9 2020-03-18 stsp return -1;
827 93658fb9 2020-03-18 stsp }
828 93658fb9 2020-03-18 stsp while(n && isblank(*p)){
829 93658fb9 2020-03-18 stsp n--;
830 93658fb9 2020-03-18 stsp p++;
831 93658fb9 2020-03-18 stsp }
832 93658fb9 2020-03-18 stsp *buf = 0;
833 93658fb9 2020-03-18 stsp *str = p;
834 93658fb9 2020-03-18 stsp *nstr = n;
835 93658fb9 2020-03-18 stsp return r;
836 93658fb9 2020-03-18 stsp }
837 93658fb9 2020-03-18 stsp
838 93658fb9 2020-03-18 stsp static void
839 93658fb9 2020-03-18 stsp nextline(char **str, int *nstr)
840 93658fb9 2020-03-18 stsp {
841 93658fb9 2020-03-18 stsp char *s;
842 93658fb9 2020-03-18 stsp
843 93658fb9 2020-03-18 stsp if((s = strchr(*str, '\n')) != NULL){
844 93658fb9 2020-03-18 stsp *nstr -= s - *str + 1;
845 93658fb9 2020-03-18 stsp *str = s + 1;
846 93658fb9 2020-03-18 stsp }
847 93658fb9 2020-03-18 stsp }
848 93658fb9 2020-03-18 stsp
849 93658fb9 2020-03-18 stsp static int
850 93658fb9 2020-03-18 stsp parseauthor(char **str, int *nstr, char **name, off_t *time)
851 93658fb9 2020-03-18 stsp {
852 93658fb9 2020-03-18 stsp return 0;
853 93658fb9 2020-03-18 stsp }
854 93658fb9 2020-03-18 stsp
855 93658fb9 2020-03-18 stsp static void
856 93658fb9 2020-03-18 stsp parsecommit(Object *o)
857 93658fb9 2020-03-18 stsp {
858 93658fb9 2020-03-18 stsp char *p, *t, buf[128];
859 93658fb9 2020-03-18 stsp int np;
860 93658fb9 2020-03-18 stsp
861 93658fb9 2020-03-18 stsp p = o->data;
862 93658fb9 2020-03-18 stsp np = o->size;
863 93658fb9 2020-03-18 stsp o->commit = emalloc(sizeof(Cinfo));
864 93658fb9 2020-03-18 stsp while(1){
865 93658fb9 2020-03-18 stsp if(scanword(&p, &np, buf, sizeof(buf)) == -1)
866 93658fb9 2020-03-18 stsp break;
867 93658fb9 2020-03-18 stsp if(strcmp(buf, "tree") == 0){
868 93658fb9 2020-03-18 stsp if(scanword(&p, &np, buf, sizeof(buf)) == -1)
869 93658fb9 2020-03-18 stsp errx(1, "invalid commit: tree missing");
870 93658fb9 2020-03-18 stsp if(hparse(&o->commit->tree, buf) == -1)
871 93658fb9 2020-03-18 stsp errx(1, "invalid commit: garbled tree");
872 93658fb9 2020-03-18 stsp }else if(strcmp(buf, "parent") == 0){
873 93658fb9 2020-03-18 stsp if(scanword(&p, &np, buf, sizeof(buf)) == -1)
874 93658fb9 2020-03-18 stsp errx(1, "invalid commit: missing parent");
875 93658fb9 2020-03-18 stsp o->commit->parent = realloc(o->commit->parent, ++o->commit->nparent * sizeof(struct got_object_id));
876 93658fb9 2020-03-18 stsp if(!o->commit->parent)
877 93658fb9 2020-03-18 stsp err(1, "unable to malloc: ");
878 93658fb9 2020-03-18 stsp if(hparse(&o->commit->parent[o->commit->nparent - 1], buf) == -1)
879 93658fb9 2020-03-18 stsp errx(1, "invalid commit: garbled parent");
880 93658fb9 2020-03-18 stsp }else if(strcmp(buf, "author") == 0){
881 93658fb9 2020-03-18 stsp parseauthor(&p, &np, &o->commit->author, &o->commit->mtime);
882 93658fb9 2020-03-18 stsp }else if(strcmp(buf, "committer") == 0){
883 93658fb9 2020-03-18 stsp parseauthor(&p, &np, &o->commit->committer, &o->commit->ctime);
884 93658fb9 2020-03-18 stsp }else if(strcmp(buf, "gpgsig") == 0){
885 93658fb9 2020-03-18 stsp /* just drop it */
886 93658fb9 2020-03-18 stsp if((t = strstr(p, "-----END PGP SIGNATURE-----")) == NULL)
887 93658fb9 2020-03-18 stsp errx(1, "malformed gpg signature");
888 93658fb9 2020-03-18 stsp np -= t - p;
889 93658fb9 2020-03-18 stsp p = t;
890 93658fb9 2020-03-18 stsp }
891 93658fb9 2020-03-18 stsp nextline(&p, &np);
892 93658fb9 2020-03-18 stsp }
893 93658fb9 2020-03-18 stsp while (np && isspace(*p)) {
894 93658fb9 2020-03-18 stsp p++;
895 93658fb9 2020-03-18 stsp np--;
896 93658fb9 2020-03-18 stsp }
897 93658fb9 2020-03-18 stsp o->commit->msg = p;
898 93658fb9 2020-03-18 stsp o->commit->nmsg = np;
899 93658fb9 2020-03-18 stsp }
900 93658fb9 2020-03-18 stsp
901 93658fb9 2020-03-18 stsp static void
902 93658fb9 2020-03-18 stsp parsetree(Object *o)
903 93658fb9 2020-03-18 stsp {
904 93658fb9 2020-03-18 stsp char *p, buf[256];
905 93658fb9 2020-03-18 stsp int np, nn, m;
906 93658fb9 2020-03-18 stsp Dirent *t;
907 93658fb9 2020-03-18 stsp
908 93658fb9 2020-03-18 stsp p = o->data;
909 93658fb9 2020-03-18 stsp np = o->size;
910 93658fb9 2020-03-18 stsp o->tree = emalloc(sizeof(Tinfo));
911 93658fb9 2020-03-18 stsp while(np > 0){
912 93658fb9 2020-03-18 stsp if(scanword(&p, &np, buf, sizeof(buf)) == -1)
913 93658fb9 2020-03-18 stsp break;
914 93658fb9 2020-03-18 stsp o->tree->ent = erealloc(o->tree->ent, ++o->tree->nent * sizeof(Dirent));
915 93658fb9 2020-03-18 stsp t = &o->tree->ent[o->tree->nent - 1];
916 93658fb9 2020-03-18 stsp memset(t, 0, sizeof(Dirent));
917 93658fb9 2020-03-18 stsp m = strtol(buf, NULL, 8);
918 93658fb9 2020-03-18 stsp /* FIXME: symlinks and other BS */
919 93658fb9 2020-03-18 stsp if(m == 0160000){
920 93658fb9 2020-03-18 stsp t->mode |= S_IFDIR;
921 93658fb9 2020-03-18 stsp t->modref = 1;
922 93658fb9 2020-03-18 stsp }
923 93658fb9 2020-03-18 stsp t->mode = m & 0777;
924 93658fb9 2020-03-18 stsp if(m & 0040000)
925 93658fb9 2020-03-18 stsp t->mode |= S_IFDIR;
926 93658fb9 2020-03-18 stsp t->name = p;
927 93658fb9 2020-03-18 stsp nn = strlen(p) + 1;
928 93658fb9 2020-03-18 stsp p += nn;
929 93658fb9 2020-03-18 stsp np -= nn;
930 93658fb9 2020-03-18 stsp if(np < sizeof(t->h.sha1))
931 93658fb9 2020-03-18 stsp errx(1, "malformed tree, remaining %d (%s)", np, p);
932 93658fb9 2020-03-18 stsp memcpy(t->h.sha1, p, sizeof(t->h.sha1));
933 93658fb9 2020-03-18 stsp p += sizeof(t->h.sha1);
934 93658fb9 2020-03-18 stsp np -= sizeof(t->h.sha1);
935 93658fb9 2020-03-18 stsp }
936 93658fb9 2020-03-18 stsp }
937 93658fb9 2020-03-18 stsp
938 93658fb9 2020-03-18 stsp void
939 93658fb9 2020-03-18 stsp parseobject(Object *o)
940 93658fb9 2020-03-18 stsp {
941 93658fb9 2020-03-18 stsp if(o->flag & Cparsed)
942 93658fb9 2020-03-18 stsp return;
943 93658fb9 2020-03-18 stsp switch(o->type){
944 93658fb9 2020-03-18 stsp case GTree: parsetree(o); break;
945 93658fb9 2020-03-18 stsp case GCommit: parsecommit(o); break;
946 93658fb9 2020-03-18 stsp //case GTag: parsetag(o); break;
947 93658fb9 2020-03-18 stsp default: break;
948 93658fb9 2020-03-18 stsp }
949 93658fb9 2020-03-18 stsp o->flag |= Cparsed;
950 93658fb9 2020-03-18 stsp }
951 93658fb9 2020-03-18 stsp
952 93658fb9 2020-03-18 stsp static Object*
953 93658fb9 2020-03-18 stsp readidxobject(FILE *idx, struct got_object_id h, int flag)
954 93658fb9 2020-03-18 stsp {
955 93658fb9 2020-03-18 stsp char path[Pathmax];
956 93658fb9 2020-03-18 stsp char hbuf[41];
957 93658fb9 2020-03-18 stsp FILE *f;
958 93658fb9 2020-03-18 stsp Object *obj;
959 93658fb9 2020-03-18 stsp int l, n;
960 93658fb9 2020-03-18 stsp off_t o;
961 93658fb9 2020-03-18 stsp struct dirent *ent;
962 93658fb9 2020-03-18 stsp DIR *d;
963 93658fb9 2020-03-18 stsp
964 93658fb9 2020-03-18 stsp
965 93658fb9 2020-03-18 stsp if ((obj = got_object_idset_lookup_data(objcache, &h))) {
966 93658fb9 2020-03-18 stsp if(obj->flag & Cloaded)
967 93658fb9 2020-03-18 stsp return obj;
968 93658fb9 2020-03-18 stsp if(obj->flag & Cidx){
969 93658fb9 2020-03-18 stsp assert(idx != NULL);
970 93658fb9 2020-03-18 stsp o = ftello(idx);
971 93658fb9 2020-03-18 stsp if(fseek(idx, obj->off, 0) == -1)
972 93658fb9 2020-03-18 stsp errx(1, "could not seek to object offset");
973 93658fb9 2020-03-18 stsp if(readpacked(idx, obj, flag) == -1)
974 93658fb9 2020-03-18 stsp errx(1, "could not reload object");
975 93658fb9 2020-03-18 stsp if(fseek(idx, o, 0) == -1)
976 93658fb9 2020-03-18 stsp errx(1, "could not restore offset");
977 93658fb9 2020-03-18 stsp cache(obj);
978 93658fb9 2020-03-18 stsp return obj;
979 93658fb9 2020-03-18 stsp }
980 93658fb9 2020-03-18 stsp }
981 93658fb9 2020-03-18 stsp
982 93658fb9 2020-03-18 stsp d = NULL;
983 93658fb9 2020-03-18 stsp /* We're not putting it in the cache yet... */
984 93658fb9 2020-03-18 stsp obj = emalloc(sizeof(Object));
985 93658fb9 2020-03-18 stsp obj->id = next_object_id + 1;
986 93658fb9 2020-03-18 stsp obj->hash = h;
987 93658fb9 2020-03-18 stsp
988 93658fb9 2020-03-18 stsp hashfmt(hbuf, sizeof(hbuf), &h);
989 93658fb9 2020-03-18 stsp snprintf(path, sizeof(path), ".git/objects/%c%c/%s", hbuf[0], hbuf[1], hbuf + 2);
990 93658fb9 2020-03-18 stsp if((f = fopen(path, "r")) != NULL){
991 93658fb9 2020-03-18 stsp if(readloose(f, obj, flag) == -1)
992 93658fb9 2020-03-18 stsp goto error;
993 93658fb9 2020-03-18 stsp fclose(f);
994 93658fb9 2020-03-18 stsp parseobject(obj);
995 93658fb9 2020-03-18 stsp hashfmt(hbuf, sizeof(hbuf), &obj->hash);
996 93658fb9 2020-03-18 stsp fprintf(stderr, "object %s cached", hbuf);
997 93658fb9 2020-03-18 stsp cache(obj);
998 93658fb9 2020-03-18 stsp return obj;
999 93658fb9 2020-03-18 stsp }
1000 93658fb9 2020-03-18 stsp
1001 93658fb9 2020-03-18 stsp o = -1;
1002 93658fb9 2020-03-18 stsp if ((d = opendir(".git/objects/pack")) == NULL)
1003 93658fb9 2020-03-18 stsp err(1, "open pack dir");
1004 93658fb9 2020-03-18 stsp while ((ent = readdir(d)) != NULL) {
1005 93658fb9 2020-03-18 stsp l = strlen(ent->d_name);
1006 93658fb9 2020-03-18 stsp if(l > 4 && strcmp(ent->d_name + l - 4, ".idx") != 0)
1007 93658fb9 2020-03-18 stsp continue;
1008 93658fb9 2020-03-18 stsp snprintf(path, sizeof(path), ".git/objects/pack/%s", ent->d_name);
1009 93658fb9 2020-03-18 stsp if((f = fopen(path, "r")) == NULL)
1010 93658fb9 2020-03-18 stsp continue;
1011 93658fb9 2020-03-18 stsp o = searchindex(f, h);
1012 93658fb9 2020-03-18 stsp fclose(f);
1013 93658fb9 2020-03-18 stsp if(o == -1)
1014 93658fb9 2020-03-18 stsp continue;
1015 93658fb9 2020-03-18 stsp break;
1016 93658fb9 2020-03-18 stsp }
1017 93658fb9 2020-03-18 stsp closedir(d);
1018 93658fb9 2020-03-18 stsp
1019 93658fb9 2020-03-18 stsp if (o == -1)
1020 93658fb9 2020-03-18 stsp goto error;
1021 93658fb9 2020-03-18 stsp
1022 93658fb9 2020-03-18 stsp if((n = snprintf(path, sizeof(path), "%s", path)) >= sizeof(path) - 4)
1023 93658fb9 2020-03-18 stsp goto error;
1024 93658fb9 2020-03-18 stsp memcpy(path + n - 4, ".pack", 6);
1025 93658fb9 2020-03-18 stsp if((f = fopen(path, "r")) == NULL)
1026 93658fb9 2020-03-18 stsp goto error;
1027 93658fb9 2020-03-18 stsp if(fseek(f, o, 0) == -1)
1028 93658fb9 2020-03-18 stsp goto error;
1029 93658fb9 2020-03-18 stsp if(readpacked(f, obj, flag) == -1)
1030 93658fb9 2020-03-18 stsp goto error;
1031 93658fb9 2020-03-18 stsp fclose(f);
1032 93658fb9 2020-03-18 stsp parseobject(obj);
1033 93658fb9 2020-03-18 stsp cache(obj);
1034 93658fb9 2020-03-18 stsp return obj;
1035 93658fb9 2020-03-18 stsp error:
1036 93658fb9 2020-03-18 stsp free(obj);
1037 93658fb9 2020-03-18 stsp return NULL;
1038 93658fb9 2020-03-18 stsp }
1039 93658fb9 2020-03-18 stsp
1040 93658fb9 2020-03-18 stsp Object*
1041 93658fb9 2020-03-18 stsp readobject(struct got_object_id h)
1042 93658fb9 2020-03-18 stsp {
1043 93658fb9 2020-03-18 stsp Object *o;
1044 93658fb9 2020-03-18 stsp
1045 93658fb9 2020-03-18 stsp o = readidxobject(NULL, h, 0);
1046 93658fb9 2020-03-18 stsp if(o)
1047 93658fb9 2020-03-18 stsp ref(o);
1048 93658fb9 2020-03-18 stsp return o;
1049 93658fb9 2020-03-18 stsp }
1050 93658fb9 2020-03-18 stsp
1051 93658fb9 2020-03-18 stsp int
1052 93658fb9 2020-03-18 stsp objcmp(const void *pa, const void *pb)
1053 93658fb9 2020-03-18 stsp {
1054 93658fb9 2020-03-18 stsp Object *a, *b;
1055 93658fb9 2020-03-18 stsp
1056 93658fb9 2020-03-18 stsp a = *(Object**)pa;
1057 93658fb9 2020-03-18 stsp b = *(Object**)pb;
1058 93658fb9 2020-03-18 stsp return memcmp(a->hash.sha1, b->hash.sha1, sizeof(a->hash.sha1));
1059 93658fb9 2020-03-18 stsp }
1060 93658fb9 2020-03-18 stsp
1061 93658fb9 2020-03-18 stsp static int
1062 93658fb9 2020-03-18 stsp hwrite(FILE *b, void *buf, int len, SHA1_CTX *ctx)
1063 93658fb9 2020-03-18 stsp {
1064 93658fb9 2020-03-18 stsp SHA1Update(ctx, buf, len);
1065 93658fb9 2020-03-18 stsp return fwrite(buf, 1, len, b);
1066 93658fb9 2020-03-18 stsp }
1067 93658fb9 2020-03-18 stsp
1068 93658fb9 2020-03-18 stsp static uint32_t
1069 93658fb9 2020-03-18 stsp objectcrc(FILE *f, Object *o)
1070 93658fb9 2020-03-18 stsp {
1071 93658fb9 2020-03-18 stsp char buf[8096];
1072 93658fb9 2020-03-18 stsp int n, r;
1073 93658fb9 2020-03-18 stsp
1074 93658fb9 2020-03-18 stsp o->crc = 0;
1075 93658fb9 2020-03-18 stsp fseek(f, o->off, 0);
1076 93658fb9 2020-03-18 stsp for(n = o->len; n > 0; n -= r){
1077 93658fb9 2020-03-18 stsp r = fread(buf, 1, n > sizeof(buf) ? sizeof(buf) : n, f);
1078 93658fb9 2020-03-18 stsp if(r == -1)
1079 93658fb9 2020-03-18 stsp return -1;
1080 93658fb9 2020-03-18 stsp if(r == 0)
1081 93658fb9 2020-03-18 stsp return 0;
1082 93658fb9 2020-03-18 stsp o->crc = crc32(o->crc, buf, r);
1083 93658fb9 2020-03-18 stsp }
1084 93658fb9 2020-03-18 stsp return 0;
1085 93658fb9 2020-03-18 stsp }
1086 93658fb9 2020-03-18 stsp
1087 93658fb9 2020-03-18 stsp int
1088 279090e1 2020-03-18 stsp indexpack(int packfd, int idxfd, struct got_object_id *packhash)
1089 93658fb9 2020-03-18 stsp {
1090 93658fb9 2020-03-18 stsp char hdr[4*3], buf[8];
1091 93658fb9 2020-03-18 stsp int nobj, nvalid, nbig, n, i, step;
1092 93658fb9 2020-03-18 stsp Object *o, **objects;
1093 93658fb9 2020-03-18 stsp char *valid;
1094 93658fb9 2020-03-18 stsp SHA1_CTX ctx, objctx;
1095 93658fb9 2020-03-18 stsp FILE *f;
1096 93658fb9 2020-03-18 stsp struct got_object_id h;
1097 93658fb9 2020-03-18 stsp int c;
1098 93658fb9 2020-03-18 stsp
1099 93658fb9 2020-03-18 stsp if ((f = fdopen(packfd, "r")) == NULL)
1100 93658fb9 2020-03-18 stsp return -1;
1101 93658fb9 2020-03-18 stsp if (fseek(f, 0, SEEK_SET) == -1)
1102 93658fb9 2020-03-18 stsp return -1;
1103 93658fb9 2020-03-18 stsp if (fread(hdr, 1, sizeof(hdr), f) != sizeof(hdr)) {
1104 93658fb9 2020-03-18 stsp fprintf(stderr, "short read on header");
1105 93658fb9 2020-03-18 stsp return -1;
1106 93658fb9 2020-03-18 stsp }
1107 93658fb9 2020-03-18 stsp if (memcmp(hdr, "PACK\0\0\0\2", 8) != 0) {
1108 93658fb9 2020-03-18 stsp fprintf(stderr, "invalid header");
1109 93658fb9 2020-03-18 stsp return -1;
1110 93658fb9 2020-03-18 stsp }
1111 93658fb9 2020-03-18 stsp
1112 93658fb9 2020-03-18 stsp nvalid = 0;
1113 93658fb9 2020-03-18 stsp nobj = GETBE32(hdr + 8);
1114 93658fb9 2020-03-18 stsp objects = calloc(nobj, sizeof(Object*));
1115 93658fb9 2020-03-18 stsp valid = calloc(nobj, sizeof(char));
1116 93658fb9 2020-03-18 stsp step = nobj/100;
1117 93658fb9 2020-03-18 stsp if(!step)
1118 93658fb9 2020-03-18 stsp step++;
1119 93658fb9 2020-03-18 stsp while (nvalid != nobj) {
1120 93658fb9 2020-03-18 stsp fprintf(stderr, "indexing (%d/%d):", nvalid, nobj);
1121 93658fb9 2020-03-18 stsp n = 0;
1122 93658fb9 2020-03-18 stsp for (i = 0; i < nobj; i++) {
1123 93658fb9 2020-03-18 stsp if (valid[i]) {
1124 93658fb9 2020-03-18 stsp n++;
1125 93658fb9 2020-03-18 stsp continue;
1126 93658fb9 2020-03-18 stsp }
1127 93658fb9 2020-03-18 stsp if (i % step == 0)
1128 93658fb9 2020-03-18 stsp fprintf(stderr, ".");
1129 93658fb9 2020-03-18 stsp if (!objects[i]) {
1130 93658fb9 2020-03-18 stsp o = emalloc(sizeof(Object));
1131 93658fb9 2020-03-18 stsp o->off = ftello(f);
1132 93658fb9 2020-03-18 stsp objects[i] = o;
1133 93658fb9 2020-03-18 stsp }
1134 93658fb9 2020-03-18 stsp o = objects[i];
1135 93658fb9 2020-03-18 stsp fseek(f, o->off, 0);
1136 93658fb9 2020-03-18 stsp if (readpacked(f, o, Cidx) == 0){
1137 93658fb9 2020-03-18 stsp SHA1Init(&objctx);
1138 93658fb9 2020-03-18 stsp SHA1Update(&objctx, (uint8_t*)o->all, o->size + strlen(o->all) + 1);
1139 93658fb9 2020-03-18 stsp SHA1Final(o->hash.sha1, &objctx);
1140 93658fb9 2020-03-18 stsp cache(o);
1141 93658fb9 2020-03-18 stsp valid[i] = 1;
1142 93658fb9 2020-03-18 stsp n++;
1143 93658fb9 2020-03-18 stsp }
1144 93658fb9 2020-03-18 stsp if(objectcrc(f, o) == -1)
1145 93658fb9 2020-03-18 stsp return -1;
1146 93658fb9 2020-03-18 stsp }
1147 93658fb9 2020-03-18 stsp fprintf(stderr, "\n");
1148 93658fb9 2020-03-18 stsp if (n == nvalid) {
1149 93658fb9 2020-03-18 stsp errx(1, "fix point reached too early: %d/%d", nvalid, nobj);
1150 93658fb9 2020-03-18 stsp goto error;
1151 93658fb9 2020-03-18 stsp }
1152 93658fb9 2020-03-18 stsp nvalid = n;
1153 93658fb9 2020-03-18 stsp }
1154 93658fb9 2020-03-18 stsp fclose(f);
1155 93658fb9 2020-03-18 stsp
1156 93658fb9 2020-03-18 stsp SHA1Init(&ctx);
1157 93658fb9 2020-03-18 stsp qsort(objects, nobj, sizeof(Object*), objcmp);
1158 93658fb9 2020-03-18 stsp if((f = fdopen(idxfd, "w")) == NULL)
1159 93658fb9 2020-03-18 stsp return -1;
1160 93658fb9 2020-03-18 stsp if(hwrite(f, "\xfftOc\x00\x00\x00\x02", 8, &ctx) != 8)
1161 93658fb9 2020-03-18 stsp goto error;
1162 93658fb9 2020-03-18 stsp /* fanout table */
1163 93658fb9 2020-03-18 stsp c = 0;
1164 93658fb9 2020-03-18 stsp for(i = 0; i < 256; i++){
1165 93658fb9 2020-03-18 stsp while(c < nobj && (objects[c]->hash.sha1[0] & 0xff) <= i)
1166 93658fb9 2020-03-18 stsp c++;
1167 93658fb9 2020-03-18 stsp PUTBE32(buf, c);
1168 93658fb9 2020-03-18 stsp hwrite(f, buf, 4, &ctx);
1169 93658fb9 2020-03-18 stsp }
1170 93658fb9 2020-03-18 stsp for(i = 0; i < nobj; i++){
1171 93658fb9 2020-03-18 stsp o = objects[i];
1172 93658fb9 2020-03-18 stsp hwrite(f, o->hash.sha1, sizeof(o->hash.sha1), &ctx);
1173 93658fb9 2020-03-18 stsp }
1174 93658fb9 2020-03-18 stsp
1175 93658fb9 2020-03-18 stsp /* pointless, nothing uses this */
1176 93658fb9 2020-03-18 stsp for(i = 0; i < nobj; i++){
1177 93658fb9 2020-03-18 stsp PUTBE32(buf, objects[i]->crc);
1178 93658fb9 2020-03-18 stsp hwrite(f, buf, 4, &ctx);
1179 93658fb9 2020-03-18 stsp }
1180 93658fb9 2020-03-18 stsp
1181 93658fb9 2020-03-18 stsp nbig = 0;
1182 93658fb9 2020-03-18 stsp for(i = 0; i < nobj; i++){
1183 93658fb9 2020-03-18 stsp if(objects[i]->off <= (1ull<<31))
1184 93658fb9 2020-03-18 stsp PUTBE32(buf, objects[i]->off);
1185 93658fb9 2020-03-18 stsp else
1186 93658fb9 2020-03-18 stsp PUTBE32(buf, (1ull << 31) | nbig++);
1187 93658fb9 2020-03-18 stsp hwrite(f, buf, 4, &ctx);
1188 93658fb9 2020-03-18 stsp }
1189 93658fb9 2020-03-18 stsp for(i = 0; i < nobj; i++){
1190 93658fb9 2020-03-18 stsp if(objects[i]->off > (1ull<<31)){
1191 93658fb9 2020-03-18 stsp PUTBE64(buf, objects[i]->off);
1192 93658fb9 2020-03-18 stsp hwrite(f, buf, 8, &ctx);
1193 93658fb9 2020-03-18 stsp }
1194 93658fb9 2020-03-18 stsp }
1195 279090e1 2020-03-18 stsp hwrite(f, packhash->sha1, sizeof(packhash->sha1), &ctx);
1196 93658fb9 2020-03-18 stsp SHA1Final(h.sha1, &ctx);
1197 93658fb9 2020-03-18 stsp fwrite(h.sha1, 1, sizeof(h.sha1), f);
1198 93658fb9 2020-03-18 stsp
1199 93658fb9 2020-03-18 stsp free(objects);
1200 93658fb9 2020-03-18 stsp free(valid);
1201 93658fb9 2020-03-18 stsp fclose(f);
1202 93658fb9 2020-03-18 stsp return 0;
1203 93658fb9 2020-03-18 stsp
1204 93658fb9 2020-03-18 stsp error:
1205 93658fb9 2020-03-18 stsp free(objects);
1206 93658fb9 2020-03-18 stsp free(valid);
1207 93658fb9 2020-03-18 stsp fclose(f);
1208 93658fb9 2020-03-18 stsp return -1;
1209 93658fb9 2020-03-18 stsp }
1210 93658fb9 2020-03-18 stsp
1211 93658fb9 2020-03-18 stsp int
1212 93658fb9 2020-03-18 stsp main(int argc, char **argv)
1213 93658fb9 2020-03-18 stsp {
1214 93658fb9 2020-03-18 stsp const struct got_error *err = NULL;
1215 93658fb9 2020-03-18 stsp struct got_object_id packhash;
1216 93658fb9 2020-03-18 stsp struct imsgbuf ibuf;
1217 93658fb9 2020-03-18 stsp struct imsg imsg;
1218 93658fb9 2020-03-18 stsp int packfd, idxfd;
1219 93658fb9 2020-03-18 stsp
1220 93658fb9 2020-03-18 stsp objcache = got_object_idset_alloc();
1221 93658fb9 2020-03-18 stsp imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
1222 93658fb9 2020-03-18 stsp if((err = got_privsep_recv_imsg(&imsg, &ibuf, 0)) != 0) {
1223 93658fb9 2020-03-18 stsp if (err->code == GOT_ERR_PRIVSEP_PIPE)
1224 93658fb9 2020-03-18 stsp err = NULL;
1225 93658fb9 2020-03-18 stsp goto done;
1226 93658fb9 2020-03-18 stsp }
1227 93658fb9 2020-03-18 stsp if (imsg.hdr.type == GOT_IMSG_STOP)
1228 93658fb9 2020-03-18 stsp goto done;
1229 93658fb9 2020-03-18 stsp if (imsg.hdr.type != GOT_IMSG_IDXPACK_REQUEST) {
1230 93658fb9 2020-03-18 stsp err = got_error(GOT_ERR_PRIVSEP_MSG);
1231 93658fb9 2020-03-18 stsp goto done;
1232 93658fb9 2020-03-18 stsp }
1233 93658fb9 2020-03-18 stsp if (imsg.hdr.len - IMSG_HEADER_SIZE != SHA1_DIGEST_LENGTH) {
1234 93658fb9 2020-03-18 stsp err = got_error(GOT_ERR_PRIVSEP_LEN);
1235 93658fb9 2020-03-18 stsp goto done;
1236 93658fb9 2020-03-18 stsp }
1237 93658fb9 2020-03-18 stsp packfd = imsg.fd;
1238 93658fb9 2020-03-18 stsp memcpy(packhash.sha1, imsg.data, SHA1_DIGEST_LENGTH);
1239 93658fb9 2020-03-18 stsp
1240 93658fb9 2020-03-18 stsp if((err = got_privsep_recv_imsg(&imsg, &ibuf, 0)) != 0) {
1241 93658fb9 2020-03-18 stsp if (err->code == GOT_ERR_PRIVSEP_PIPE)
1242 93658fb9 2020-03-18 stsp err = NULL;
1243 93658fb9 2020-03-18 stsp goto done;
1244 93658fb9 2020-03-18 stsp }
1245 93658fb9 2020-03-18 stsp if (imsg.hdr.type == GOT_IMSG_STOP)
1246 93658fb9 2020-03-18 stsp goto done;
1247 93658fb9 2020-03-18 stsp if (imsg.hdr.type != GOT_IMSG_TMPFD) {
1248 93658fb9 2020-03-18 stsp err = got_error(GOT_ERR_PRIVSEP_MSG);
1249 93658fb9 2020-03-18 stsp goto done;
1250 93658fb9 2020-03-18 stsp }
1251 93658fb9 2020-03-18 stsp if (imsg.hdr.len - IMSG_HEADER_SIZE != 0) {
1252 93658fb9 2020-03-18 stsp err = got_error(GOT_ERR_PRIVSEP_LEN);
1253 93658fb9 2020-03-18 stsp goto done;
1254 93658fb9 2020-03-18 stsp }
1255 93658fb9 2020-03-18 stsp idxfd = imsg.fd;
1256 93658fb9 2020-03-18 stsp
1257 279090e1 2020-03-18 stsp indexpack(packfd, idxfd, &packhash);
1258 93658fb9 2020-03-18 stsp done:
1259 93658fb9 2020-03-18 stsp if(err != NULL)
1260 93658fb9 2020-03-18 stsp got_privsep_send_error(&ibuf, err);
1261 93658fb9 2020-03-18 stsp else
1262 93658fb9 2020-03-18 stsp err = got_privsep_send_index_pack_done(&ibuf);
1263 93658fb9 2020-03-18 stsp if(err != NULL) {
1264 93658fb9 2020-03-18 stsp fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
1265 93658fb9 2020-03-18 stsp got_privsep_send_error(&ibuf, err);
1266 93658fb9 2020-03-18 stsp }
1267 93658fb9 2020-03-18 stsp
1268 93658fb9 2020-03-18 stsp exit(0);
1269 93658fb9 2020-03-18 stsp }