Line data Source code
1 : #include "../burp.h"
2 : #include "../alloc.h"
3 : #include "../cmd.h"
4 : #include "../fsops.h"
5 : #include "../fzp.h"
6 : #include "../hexmap.h"
7 : #include "../log.h"
8 : #include "../msg.h"
9 : #include "../prepend.h"
10 : #include "../sbuf.h"
11 : #include "manio.h"
12 :
13 : static void man_off_t_free_content(man_off_t *offset)
14 : {
15 123 : if(!offset) return;
16 7829 : free_w(&offset->fpath);
17 7829 : free_w(&offset->ppath);
18 : }
19 :
20 7846 : void man_off_t_free(man_off_t **offset)
21 : {
22 7846 : if(!offset || !*offset) return;
23 15412 : man_off_t_free_content(*offset);
24 7706 : free_v((void **)offset);
25 : }
26 :
27 : static man_off_t *man_off_t_alloc(void)
28 : {
29 7706 : return (man_off_t *)calloc_w(1, sizeof(man_off_t), __func__);
30 : }
31 :
32 : static char *get_next_fpath(struct manio *manio, man_off_t *offset)
33 : {
34 363 : return strdup_w(manio->manifest, __func__);
35 : }
36 :
37 363 : static int manio_open_next_fpath(struct manio *manio)
38 : {
39 : static struct stat statp;
40 363 : man_off_t *offset=manio->offset;
41 :
42 363 : free_w(&offset->ppath);
43 363 : offset->ppath=offset->fpath;
44 726 : if(!(offset->fpath=get_next_fpath(manio, offset)))
45 : return -1;
46 :
47 363 : if(!strcmp(manio->mode, MANIO_MODE_READ)
48 410 : && lstat(offset->fpath, &statp))
49 : return 0;
50 :
51 351 : if(build_path_w(offset->fpath))
52 : return -1;
53 351 : switch(manio->phase)
54 : {
55 : case 2:
56 273 : if(!(manio->fzp=fzp_open(offset->fpath,
57 273 : manio->mode))) return -1;
58 273 : return 0;
59 : case 1:
60 : case 3:
61 : default:
62 78 : if(!(manio->fzp=fzp_gzopen(offset->fpath,
63 78 : manio->mode))) return -1;
64 78 : return 0;
65 : }
66 : }
67 :
68 : static int manio_open_last_fpath(struct manio *manio)
69 : {
70 20 : return manio_open_next_fpath(manio);
71 : }
72 :
73 : static struct manio *manio_alloc(void)
74 : {
75 357 : return (struct manio *)calloc_w(1, sizeof(struct manio), __func__);
76 : }
77 :
78 357 : static struct manio *do_manio_open(const char *manifest, const char *mode,
79 : int phase)
80 : {
81 357 : struct manio *manio=NULL;
82 357 : if(!(manio=manio_alloc())
83 357 : || !(manio->manifest=strdup_w(manifest, __func__))
84 357 : || !(manio->mode=strdup_w(mode, __func__))
85 714 : || !(manio->offset=man_off_t_alloc()))
86 : goto error;
87 357 : manio->phase=phase;
88 357 : if(!strcmp(manio->mode, MANIO_MODE_APPEND))
89 : {
90 20 : if(manio->phase!=2)
91 : {
92 0 : logp("manio append mode only works for phase 2.\n");
93 0 : logp("%s has phase: %d\n",
94 0 : manio->manifest, manio->phase);
95 0 : goto error;
96 : }
97 40 : if(manio_open_last_fpath(manio))
98 : goto error;
99 : }
100 : else
101 : {
102 337 : if(manio_open_next_fpath(manio))
103 : goto error;
104 : }
105 357 : return manio;
106 : error:
107 0 : manio_close(&manio);
108 0 : return NULL;
109 : }
110 :
111 12 : struct manio *manio_open(const char *manifest, const char *mode)
112 : {
113 12 : return do_manio_open(manifest, mode, 0);
114 : }
115 :
116 63 : struct manio *manio_open_phase1(const char *manifest, const char *mode)
117 : {
118 63 : return do_manio_open(manifest, mode, 1);
119 : }
120 :
121 273 : struct manio *manio_open_phase2(const char *manifest, const char *mode)
122 : {
123 273 : return do_manio_open(manifest, mode, 2);
124 : }
125 :
126 9 : struct manio *manio_open_phase3(const char *manifest, const char *mode,
127 : const char *rmanifest)
128 : {
129 9 : return do_manio_open(manifest, mode, 3);
130 : }
131 :
132 357 : static void manio_free_content(struct manio *manio)
133 : {
134 357 : if(!manio) return;
135 357 : man_off_t_free(&manio->offset);
136 357 : free_w(&manio->manifest);
137 357 : free_w(&manio->mode);
138 357 : free_w(&manio->rmanifest);
139 357 : free_w(&manio->hook_dir);
140 357 : free_v((void **)&manio->hook_sort);
141 357 : free_w(&manio->dindex_dir);
142 357 : free_v((void **)&manio->dindex_sort);
143 357 : memset(manio, 0, sizeof(struct manio));
144 : }
145 :
146 : static char *get_fcount_path(struct manio *manio)
147 : {
148 0 : return prepend_s(manio->manifest, "fcount");
149 : }
150 :
151 0 : int manio_read_fcount(struct manio *manio)
152 : {
153 0 : int ret=-1;
154 : size_t s;
155 0 : struct fzp *fzp=NULL;
156 0 : char *path=NULL;
157 0 : char buf[16]="";
158 0 : if(!(path=get_fcount_path(manio))
159 0 : || !(fzp=fzp_open(path, "rb")))
160 : goto end;
161 0 : if(!fzp_gets(fzp, buf, sizeof(buf)))
162 : {
163 0 : logp("fzp_gets on %s failed\n", path);
164 0 : goto end;
165 : }
166 0 : s=strlen(buf);
167 0 : if(s!=9)
168 : {
169 0 : logp("data in %s is not the right length (%lu!=9)\n", path,
170 : (unsigned long)s);
171 0 : goto end;
172 : }
173 0 : manio->offset->fcount=strtoul(buf, NULL, 16);
174 0 : ret=0;
175 : end:
176 0 : fzp_close(&fzp);
177 0 : free_w(&path);
178 0 : return ret;
179 : }
180 :
181 430 : int manio_close(struct manio **manio)
182 : {
183 430 : int ret=0;
184 : // int fd;
185 430 : if(!manio || !*manio) return ret;
186 : /*
187 : There is no gzfileno()
188 : if((fd=fzp_fileno((*manio)->fzp))<0)
189 : {
190 : logp("Could not get fileno in %s for %s: %s\n", __func__,
191 : (*manio)->manifest, strerror(errno));
192 : ret=-1;
193 : }
194 : // Should probably have a flush before fsync too.
195 : if(fsync(fd))
196 : {
197 : logp("Error in fsync in %s for %s: %s\n", __func__,
198 : (*manio)->manifest, strerror(errno));
199 : ret=-1;
200 : }
201 : */
202 357 : if(fzp_close(&((*manio)->fzp)))
203 0 : ret=-1;
204 357 : sync();
205 357 : manio_free_content(*manio);
206 357 : free_v((void **)manio);
207 357 : return ret;
208 : }
209 :
210 : // Return -1 for error, 0 for stuff read OK, 1 for end of files.
211 13581 : int manio_read(struct manio *manio, struct sbuf *sb)
212 : {
213 : while(1)
214 : {
215 13581 : if(!manio->fzp)
216 : {
217 6 : if(manio_open_next_fpath(manio)) goto error;
218 6 : if(!manio->fzp) return 1; // No more files to read.
219 : }
220 :
221 13575 : switch(sbuf_fill_from_file(sb, manio->fzp))
222 : {
223 : case 0: return 0; // Got something.
224 : case 1: break; // Keep going.
225 : default: goto error; // Error.
226 : }
227 :
228 : // Reached the end of the current file.
229 : // Maybe there is another file to continue with.
230 107 : if(fzp_close(&manio->fzp)) goto error;
231 : return 1;
232 : }
233 :
234 : error:
235 : return -1;
236 : }
237 :
238 11932 : int manio_write_sbuf(struct manio *manio, struct sbuf *sb)
239 : {
240 11932 : if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
241 11932 : return sbuf_to_manifest(sb, manio->fzp);
242 : }
243 :
244 84 : int manio_write_cntr(struct manio *manio, struct sbuf *sb,
245 : enum cntr_manio what)
246 : {
247 84 : if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
248 84 : return sbuf_to_manifest_cntr(sb, manio->fzp, what);
249 : }
250 :
251 : // Return -1 on error, 0 on OK, 1 for srcmanio finished.
252 8 : int manio_copy_entry(struct sbuf *csb, struct sbuf *sb,
253 : struct manio *srcmanio, struct manio *dstmanio,
254 : const char *seed_src, const char *seed_dst)
255 : {
256 : int ars;
257 : struct iobuf copy1;
258 : struct iobuf copy2;
259 8 : memset(©1, 0, sizeof(copy1));
260 8 : memset(©2, 0, sizeof(copy2));
261 :
262 : // Use the most recent stat for the new manifest.
263 8 : if(dstmanio)
264 : {
265 8 : int e=0;
266 : struct iobuf save1;
267 : struct iobuf save2;
268 8 : memset(&save1, 0, sizeof(save1));
269 8 : memset(&save2, 0, sizeof(save2));
270 :
271 : // When seeding, adjust the prefixes, but we need to remember
272 : // the original too.
273 8 : if(seed_src && seed_dst)
274 : {
275 0 : char *tmp=sb->path.buf+strlen(seed_src);
276 0 : if(!(copy1.buf=strdup_w(seed_dst, __func__)))
277 : goto error;
278 0 : if(astrcat(©1.buf, "/", __func__))
279 : goto error;
280 0 : if(*tmp=='/')
281 0 : tmp++;
282 0 : if(astrcat(©1.buf, tmp, __func__))
283 : goto error;
284 0 : copy1.len=strlen(copy1.buf);
285 0 : copy1.cmd=sb->path.cmd;
286 :
287 0 : if(sb->protocol1->datapth.buf
288 0 : && !strncmp(sb->protocol1->datapth.buf,
289 : TREE_DIR, strlen(TREE_DIR)))
290 : {
291 0 : tmp=sb->protocol1->datapth.buf
292 : +strlen(TREE_DIR)
293 0 : +strlen(seed_src);
294 0 : if(*tmp=='/')
295 0 : tmp++;
296 0 : if(!(copy2.buf=strdup_w(TREE_DIR, __func__)))
297 : goto error;
298 0 : if(*seed_dst!='/'
299 0 : && astrcat(©2.buf, "/", __func__))
300 : goto error;
301 0 : if(astrcat(©2.buf, seed_dst, __func__)
302 0 : || astrcat(©2.buf, "/", __func__)
303 0 : || astrcat(©2.buf, tmp, __func__))
304 : goto error;
305 0 : copy2.len=strlen(copy2.buf);
306 0 : copy2.cmd=sb->protocol1->datapth.cmd;
307 : }
308 :
309 0 : save1=sb->path;
310 0 : sb->path=copy1;
311 :
312 0 : if(copy2.buf)
313 : {
314 0 : save2=sb->protocol1->datapth;
315 0 : sb->protocol1->datapth=copy2;
316 : }
317 : }
318 8 : e=manio_write_sbuf(dstmanio, sb);
319 8 : if(copy1.buf)
320 : {
321 0 : sb->path=save1;
322 0 : iobuf_free_content(©1);
323 : }
324 8 : if(copy2.buf)
325 : {
326 0 : sb->protocol1->datapth=save2;
327 0 : iobuf_free_content(©2);
328 : }
329 8 : if(e)
330 : goto error;
331 :
332 8 : sbuf_free_content(csb);
333 8 : return 0;
334 : }
335 :
336 0 : copy1.len=csb->path.len;
337 0 : copy1.cmd=csb->path.cmd;
338 0 : if(!(copy1.buf=strdup_w(csb->path.buf, __func__)))
339 : goto error;
340 : while(1)
341 : {
342 0 : if((ars=manio_read(srcmanio, csb))<0)
343 : goto error;
344 0 : else if(ars>0)
345 : {
346 : // Finished.
347 0 : sbuf_free_content(csb);
348 0 : iobuf_free_content(©1);
349 0 : return 1;
350 : }
351 :
352 : // Got something.
353 0 : if(iobuf_pathcmp(&csb->path, ©1))
354 : {
355 : // Found the next entry.
356 0 : iobuf_free_content(©1);
357 0 : return 0;
358 : }
359 : if(dstmanio)
360 : {
361 : if(!dstmanio->fzp
362 : && manio_open_next_fpath(dstmanio))
363 : goto error;
364 :
365 : if(csb->endfile.buf)
366 : {
367 : if(iobuf_send_msg_fzp(&csb->endfile,
368 : dstmanio->fzp)) goto error;
369 : }
370 : }
371 : }
372 :
373 : error:
374 0 : iobuf_free_content(©1);
375 0 : iobuf_free_content(©2);
376 0 : return -1;
377 : }
378 :
379 0 : int manio_forward_through_sigs(struct sbuf *csb, struct manio *manio)
380 : {
381 : // Call manio_copy_entry with nothing to write to, so
382 : // that we forward through the sigs in manio.
383 0 : return manio_copy_entry(csb, NULL, manio, NULL, NULL, NULL);
384 : }
385 :
386 7349 : man_off_t *manio_tell(struct manio *manio)
387 : {
388 7349 : man_off_t *offset=NULL;
389 7349 : if(!manio->fzp)
390 : {
391 0 : logp("%s called on null fzp\n", __func__);
392 0 : if(manio->offset && manio->offset->fpath)
393 0 : logp("manio->offset->fpath: %s\n",
394 : manio->offset->fpath);
395 : goto error;
396 : }
397 7349 : if(!(offset=man_off_t_alloc())
398 7349 : || !(offset->fpath=strdup_w(manio->offset->fpath, __func__))
399 7349 : || (offset->offset=fzp_tell(manio->fzp))<0)
400 : goto error;
401 7349 : offset->fcount=manio->offset->fcount;
402 7349 : return offset;
403 : error:
404 0 : man_off_t_free(&offset);
405 0 : return NULL;
406 : }
407 :
408 123 : int manio_seek(struct manio *manio, man_off_t *offset)
409 : {
410 123 : fzp_close(&manio->fzp);
411 123 : if(!(manio->fzp=fzp_gzopen(offset->fpath, manio->mode))
412 123 : || fzp_seek(manio->fzp, offset->offset, SEEK_SET))
413 : return -1;
414 246 : man_off_t_free_content(manio->offset);
415 123 : if(!(manio->offset->fpath=strdup_w(offset->fpath, __func__)))
416 : return -1;
417 123 : manio->offset->offset=offset->offset;
418 123 : manio->offset->fcount=offset->fcount;
419 123 : return 0;
420 : }
421 :
422 100 : int manio_close_and_truncate(struct manio **manio,
423 : man_off_t *offset, int compression)
424 : {
425 100 : int ret=-1;
426 100 : errno=0;
427 100 : if(manio_close(manio)) goto end;
428 100 : if(fzp_truncate(offset->fpath, FZP_FILE, offset->offset, compression))
429 : {
430 0 : logp("Could not fzp_truncate %s in %s(): %s\n",
431 : offset->fpath, __func__, strerror(errno));
432 0 : goto end;
433 : }
434 : ret=0;
435 : end:
436 100 : return ret;
437 : }
|