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 "../protocol2/blk.h"
11 : #include "../sbuf.h"
12 : #include "manio.h"
13 : #include "protocol2/champ_chooser/champ_chooser.h"
14 : #include "protocol2/dpth.h"
15 :
16 : #define MANIO_MODE_READ "rb"
17 : #define MANIO_MODE_WRITE "wb"
18 : #define MANIO_MODE_APPEND "ab"
19 :
20 13988 : static void man_off_t_free_content(man_off_t *offset)
21 : {
22 27976 : if(!offset) return;
23 13988 : free_w(&offset->fpath);
24 13988 : free_w(&offset->ppath);
25 : }
26 :
27 14016 : void man_off_t_free(man_off_t **offset)
28 : {
29 28032 : if(!offset || !*offset) return;
30 13742 : man_off_t_free_content(*offset);
31 13742 : free_v((void **)offset);
32 : }
33 :
34 : static man_off_t *man_off_t_alloc(void)
35 : {
36 13742 : return (man_off_t *)calloc_w(1, sizeof(man_off_t), __func__);
37 : }
38 :
39 11 : static int init_write_hooks(struct manio *manio,
40 : const char *hook_dir, const char *rmanifest)
41 : {
42 11 : if(!(manio->hook_dir=strdup_w(hook_dir, __func__))
43 11 : || !(manio->rmanifest=strdup_w(rmanifest, __func__))
44 11 : || !(manio->hook_sort=(uint64_t *)calloc_w(MANIFEST_SIG_MAX,
45 : sizeof(uint64_t), __func__)))
46 : return -1;
47 : return 0;
48 : }
49 :
50 11 : static int init_write_dindex(struct manio *manio, const char *dir)
51 : {
52 11 : if(!(manio->dindex_dir=strdup_w(dir, __func__))
53 11 : || !(manio->dindex_sort=(uint64_t *)calloc_w(MANIFEST_SIG_MAX,
54 : sizeof(uint64_t), __func__)))
55 : return -1;
56 : return 0;
57 : }
58 :
59 : static int is_single_file(struct manio *manio)
60 : {
61 1604 : return manio->protocol==PROTO_1 || manio->phase==1;
62 : }
63 :
64 1073 : static char *get_next_fpath(struct manio *manio, man_off_t *offset)
65 : {
66 : static char tmp[32];
67 2146 : if(is_single_file(manio))
68 428 : return strdup_w(manio->manifest, __func__);
69 645 : snprintf(tmp, sizeof(tmp), "%08" PRIX64, offset->fcount++);
70 645 : return prepend_s(manio->manifest, tmp);
71 : }
72 :
73 973 : static int manio_open_next_fpath(struct manio *manio)
74 : {
75 : static struct stat statp;
76 973 : man_off_t *offset=manio->offset;
77 :
78 973 : free_w(&offset->ppath);
79 973 : offset->ppath=offset->fpath;
80 973 : if(!(offset->fpath=get_next_fpath(manio, offset)))
81 : return -1;
82 :
83 973 : if(!strcmp(manio->mode, MANIO_MODE_READ)
84 1204 : && lstat(offset->fpath, &statp))
85 : return 0;
86 :
87 814 : if(build_path_w(offset->fpath))
88 : return -1;
89 814 : switch(manio->phase)
90 : {
91 : case 2:
92 630 : if(!(manio->fzp=fzp_open(offset->fpath,
93 630 : manio->mode))) return -1;
94 630 : return 0;
95 : case 1:
96 : case 3:
97 : default:
98 184 : if(!(manio->fzp=fzp_gzopen(offset->fpath,
99 184 : manio->mode))) return -1;
100 184 : return 0;
101 : }
102 : }
103 :
104 92 : static int manio_open_last_fpath(struct manio *manio)
105 : {
106 46 : int max=-1;
107 92 : if(is_single_file(manio))
108 10 : return manio_open_next_fpath(manio);
109 36 : if(get_highest_entry(manio->manifest, &max, 8))
110 : return -1;
111 36 : if(max<0) max=0;
112 36 : manio->offset->fcount=(uint64_t)max;
113 36 : return manio_open_next_fpath(manio);
114 : }
115 :
116 : static struct manio *manio_alloc(void)
117 : {
118 752 : return (struct manio *)calloc_w(1, sizeof(struct manio), __func__);
119 : }
120 :
121 752 : static struct manio *do_manio_open(const char *manifest, const char *mode,
122 : enum protocol protocol, int phase)
123 : {
124 752 : struct manio *manio=NULL;
125 752 : if(!(manio=manio_alloc())
126 752 : || !(manio->manifest=strdup_w(manifest, __func__))
127 752 : || !(manio->mode=strdup_w(mode, __func__))
128 1504 : || !(manio->offset=man_off_t_alloc()))
129 : goto error;
130 752 : manio->protocol=protocol;
131 752 : manio->phase=phase;
132 752 : if(!strcmp(manio->mode, MANIO_MODE_APPEND))
133 : {
134 46 : if(manio->phase!=2)
135 : {
136 0 : logp("manio append mode only works for phase 2.\n");
137 0 : logp("%s has phase: %d\n",
138 0 : manio->manifest, manio->phase);
139 0 : goto error;
140 : }
141 46 : if(manio_open_last_fpath(manio))
142 : goto error;
143 : }
144 : else
145 : {
146 706 : if(manio_open_next_fpath(manio))
147 : goto error;
148 : }
149 752 : return manio;
150 : error:
151 0 : manio_close(&manio);
152 0 : return NULL;
153 : }
154 :
155 36 : struct manio *manio_open(const char *manifest, const char *mode,
156 : enum protocol protocol)
157 : {
158 36 : return do_manio_open(manifest, mode, protocol, 0);
159 : }
160 :
161 143 : struct manio *manio_open_phase1(const char *manifest, const char *mode,
162 : enum protocol protocol)
163 : {
164 143 : return do_manio_open(manifest, mode, protocol, 1);
165 : }
166 :
167 554 : struct manio *manio_open_phase2(const char *manifest, const char *mode,
168 : enum protocol protocol)
169 : {
170 554 : return do_manio_open(manifest, mode, protocol, 2);
171 : }
172 :
173 19 : struct manio *manio_open_phase3(const char *manifest, const char *mode,
174 : enum protocol protocol, const char *rmanifest)
175 : {
176 19 : struct manio *manio=NULL;
177 :
178 19 : if(!(manio=do_manio_open(manifest, mode, protocol, 3)))
179 : goto end;
180 :
181 19 : if(protocol==PROTO_2 && rmanifest)
182 : {
183 11 : char *hooksdir=NULL;
184 11 : char *dindexdir=NULL;
185 11 : if(!(hooksdir=prepend_s(manifest, "hooks"))
186 11 : || !(dindexdir=prepend_s(manifest, "dindex"))
187 11 : || init_write_hooks(manio, hooksdir, rmanifest)
188 11 : || init_write_dindex(manio, dindexdir))
189 0 : manio_close(&manio);
190 11 : free_w(&hooksdir);
191 11 : free_w(&dindexdir);
192 : }
193 :
194 : end:
195 19 : return manio;
196 : }
197 :
198 752 : static void manio_free_content(struct manio *manio)
199 : {
200 1504 : if(!manio) return;
201 752 : man_off_t_free(&manio->offset);
202 752 : free_w(&manio->manifest);
203 752 : free_w(&manio->mode);
204 752 : free_w(&manio->rmanifest);
205 752 : free_w(&manio->hook_dir);
206 752 : free_v((void **)&manio->hook_sort);
207 752 : free_w(&manio->dindex_dir);
208 752 : free_v((void **)&manio->dindex_sort);
209 : memset(manio, 0, sizeof(struct manio));
210 : }
211 :
212 : #ifndef UTEST
213 : static
214 : #endif
215 36 : int write_hook_header(struct fzp *fzp, const char *rmanifest, const char *msg)
216 : {
217 36 : int ret=0;
218 36 : char *tmp=NULL;
219 36 : if(!(tmp=prepend_s(rmanifest, msg))
220 36 : || send_msg_fzp(fzp, CMD_MANIFEST, tmp, strlen(tmp)))
221 : ret=-1;
222 36 : free_w(&tmp);
223 36 : return ret;
224 : }
225 :
226 377847 : static int uint64_t_sort(const void *a, const void *b)
227 : {
228 377847 : uint64_t *x=(uint64_t *)a;
229 377847 : uint64_t *y=(uint64_t *)b;
230 377847 : if(*x>*y) return 1;
231 185793 : if(*x<*y) return -1;
232 0 : return 0;
233 : }
234 :
235 : static char *get_fcount_path(struct manio *manio)
236 : {
237 21 : return prepend_s(manio->manifest, "fcount");
238 : }
239 :
240 : // Backup phase4 needs to know the fcount, so leave a file behind that
241 : // contains it (otherwise phase4 will have to read and sort the directory
242 : // contents).
243 40 : static int manio_write_fcount(struct manio *manio)
244 : {
245 20 : int ret=-1;
246 20 : struct fzp *fzp=NULL;
247 20 : char *path=NULL;
248 :
249 40 : if(!(path=get_fcount_path(manio))
250 20 : || !(fzp=fzp_open(path, "wb")))
251 : goto end;
252 20 : if(fzp_printf(fzp, "%08" PRIX64 "\n", manio->offset->fcount)!=9)
253 : {
254 0 : logp("Short write when writing to %s\n", path);
255 0 : goto end;
256 : }
257 : ret=0;
258 : end:
259 20 : if(fzp_close(&fzp))
260 : {
261 0 : logp("Could not close file pointer to %s\n", path);
262 0 : ret=-1;
263 : }
264 20 : free_w(&path);
265 20 : return ret;
266 : }
267 :
268 2 : int manio_read_fcount(struct manio *manio)
269 : {
270 1 : int ret=-1;
271 : size_t s;
272 1 : struct fzp *fzp=NULL;
273 1 : char *path=NULL;
274 1 : char buf[16]="";
275 2 : if(!(path=get_fcount_path(manio))
276 1 : || !(fzp=fzp_open(path, "rb")))
277 : goto end;
278 1 : if(!fzp_gets(fzp, buf, sizeof(buf)))
279 : {
280 0 : logp("fzp_gets on %s failed\n", path);
281 0 : goto end;
282 : }
283 1 : s=strlen(buf);
284 1 : if(s!=9)
285 : {
286 0 : logp("data in %s is not the right length (%lu!=9)\n", path,
287 : (unsigned long)s);
288 0 : goto end;
289 : }
290 1 : manio->offset->fcount=strtoul(buf, NULL, 16);
291 1 : ret=0;
292 : end:
293 1 : fzp_close(&fzp);
294 1 : free_w(&path);
295 1 : return ret;
296 : }
297 :
298 1080 : static int sort_and_write_hooks(struct manio *manio)
299 : {
300 : int i;
301 1080 : int ret=-1;
302 1080 : struct fzp *fzp=NULL;
303 1080 : char msg[32]="";
304 1080 : char *path=NULL;
305 1080 : int hook_count=manio->hook_count;
306 1080 : uint64_t *hook_sort=manio->hook_sort;
307 1080 : if(!hook_sort) return 0;
308 :
309 20 : snprintf(msg, sizeof(msg), "%08" PRIX64, manio->offset->fcount-1);
310 20 : if(!(path=prepend_s(manio->hook_dir, msg))
311 20 : || build_path_w(path)
312 20 : || !(fzp=fzp_gzopen(path, MANIO_MODE_WRITE)))
313 : goto end;
314 :
315 20 : qsort(hook_sort, hook_count, sizeof(uint64_t), uint64_t_sort);
316 :
317 20 : if(write_hook_header(fzp, manio->rmanifest, msg)) goto end;
318 2208 : for(i=0; i<hook_count; i++)
319 : {
320 : // Do not bother with duplicates.
321 2208 : if(i && hook_sort[i]==hook_sort[i-1])
322 0 : continue;
323 :
324 2208 : if(to_fzp_fingerprint(fzp, hook_sort[i]))
325 : goto end;
326 : }
327 20 : if(fzp_close(&fzp))
328 : {
329 0 : logp("Error closing %s in %s: %s\n",
330 0 : path, __func__, strerror(errno));
331 0 : goto end;
332 : }
333 20 : if(manio_write_fcount(manio)) goto end;
334 20 : manio->hook_count=0;
335 20 : ret=0;
336 : end:
337 20 : fzp_close(&fzp);
338 20 : free_w(&path);
339 20 : return ret;
340 : }
341 :
342 1080 : static int sort_and_write_dindex(struct manio *manio)
343 : {
344 : int i;
345 1080 : int ret=-1;
346 1080 : struct fzp *fzp=NULL;
347 1080 : char msg[32]="";
348 1080 : char *path=NULL;
349 : struct iobuf wbuf;
350 : struct blk blk;
351 1080 : int dindex_count=manio->dindex_count;
352 1080 : uint64_t *dindex_sort=manio->dindex_sort;
353 1080 : if(!dindex_sort) return 0;
354 :
355 20 : snprintf(msg, sizeof(msg), "%08" PRIX64, manio->offset->fcount-1);
356 20 : if(!(path=prepend_s(manio->dindex_dir, msg))
357 20 : || build_path_w(path)
358 20 : || !(fzp=fzp_gzopen(path, MANIO_MODE_WRITE)))
359 : goto end;
360 :
361 20 : qsort(dindex_sort, dindex_count, sizeof(uint64_t), uint64_t_sort);
362 :
363 34899 : for(i=0; i<dindex_count; i++)
364 : {
365 : // Do not bother with duplicates.
366 34879 : if(i && dindex_sort[i]==dindex_sort[i-1])
367 0 : continue;
368 :
369 34879 : blk.savepath=dindex_sort[i];
370 34879 : blk_to_iobuf_savepath(&blk, &wbuf);
371 34879 : if(iobuf_send_msg_fzp(&wbuf, fzp)) return -1;
372 : }
373 20 : if(fzp_close(&fzp))
374 : {
375 0 : logp("Error closing %s in %s: %s\n",
376 0 : path, __func__, strerror(errno));
377 0 : goto end;
378 : }
379 20 : manio->dindex_count=0;
380 20 : ret=0;
381 : end:
382 20 : fzp_close(&fzp);
383 20 : free_w(&path);
384 20 : return ret;
385 : }
386 :
387 1080 : static int sort_and_write_hooks_and_dindex(struct manio *manio)
388 : {
389 2160 : return sort_and_write_hooks(manio)
390 1080 : || sort_and_write_dindex(manio);
391 : }
392 :
393 911 : int manio_close(struct manio **manio)
394 : {
395 911 : int ret=0;
396 : // int fd;
397 911 : if(!manio || !*manio) return ret;
398 752 : if(sort_and_write_hooks_and_dindex(*manio))
399 0 : ret=-1;
400 : /*
401 : There is no gzfileno()
402 : if((fd=fzp_fileno((*manio)->fzp))<0)
403 : {
404 : logp("Could not get fileno in %s for %s: %s\n", __func__,
405 : (*manio)->manifest, strerror(errno));
406 : ret=-1;
407 : }
408 : // Should probably have a flush before fsync too.
409 : if(fsync(fd))
410 : {
411 : logp("Error in fsync in %s for %s: %s\n", __func__,
412 : (*manio)->manifest, strerror(errno));
413 : ret=-1;
414 : }
415 : */
416 752 : if(fzp_close(&((*manio)->fzp)))
417 0 : ret=-1;
418 752 : sync();
419 752 : manio_free_content(*manio);
420 752 : free_v((void **)manio);
421 752 : return ret;
422 : }
423 :
424 : // Return -1 for error, 0 for stuff read OK, 1 for end of files.
425 115716 : int manio_read_with_blk(struct manio *manio,
426 : struct sbuf *sb, struct blk *blk, struct sdirs *sdirs)
427 : {
428 : while(1)
429 : {
430 115588 : if(!manio->fzp)
431 : {
432 178 : if(manio_open_next_fpath(manio)) goto error;
433 178 : if(!manio->fzp) return 1; // No more files to read.
434 : }
435 :
436 115458 : switch(sbuf_fill_from_file(sb, manio->fzp, blk,
437 : sdirs?sdirs->data:NULL))
438 : {
439 : case 0: return 0; // Got something.
440 : case 1: break; // Keep going.
441 : default: goto error; // Error.
442 : }
443 :
444 : // Reached the end of the current file.
445 : // Maybe there is another file to continue with.
446 285 : if(sort_and_write_hooks_and_dindex(manio)
447 285 : || fzp_close(&manio->fzp)) goto error;
448 :
449 570 : if(is_single_file(manio)) return 1;
450 : }
451 :
452 : error:
453 : return -1;
454 : }
455 :
456 54944 : int manio_read(struct manio *manio, struct sbuf *sb)
457 : {
458 54944 : return manio_read_with_blk(manio, sb, NULL, NULL);
459 : }
460 :
461 43 : static int reset_sig_count_and_close(struct manio *manio)
462 : {
463 43 : if(sort_and_write_hooks_and_dindex(manio)) return -1;
464 43 : if(fzp_close(&manio->fzp)) return -1;
465 43 : manio->sig_count=0;
466 43 : if(manio_open_next_fpath(manio)) return -1;
467 43 : return 0;
468 : }
469 :
470 : #ifndef UTEST
471 : static
472 : #endif
473 3574 : int manio_find_boundary(uint8_t *md5sum)
474 : {
475 : int i;
476 : uint8_t x;
477 : uint8_t y;
478 3574 : uint8_t b4=0;
479 :
480 : // I am currently making it look for four of the same consecutive
481 : // characters in the md5sum.
482 56854 : for(i=0; i<MD5_DIGEST_LENGTH-1; i++)
483 : {
484 53333 : x=md5sum[i]>>4;
485 53333 : y=md5sum[i]&0x0F;
486 53333 : if(x==y)
487 : {
488 3303 : if(x!=md5sum[i+1]>>4)
489 3106 : continue;
490 197 : if(i && x==b4)
491 : return 1;
492 175 : if(x==(md5sum[i+1]&0x0F))
493 : return 1;
494 : }
495 : b4=y;
496 : }
497 : return 0;
498 : }
499 :
500 : // After conditions are met, close the file currently being written to.
501 : // Allow the number of signatures to be vary between MANIFEST_SIG_MIN and
502 : // MANIFEST_SIG_MAX. This will hopefully allow fewer candidate manifests
503 : // generated, since the boundary will be able to vary.
504 187793 : static int check_sig_count(struct manio *manio, struct blk *blk)
505 : {
506 187793 : manio->sig_count++;
507 :
508 187793 : if(manio->sig_count<MANIFEST_SIG_MIN)
509 : return 0; // Not yet time to close.
510 :
511 3558 : if(manio->sig_count>=MANIFEST_SIG_MAX)
512 0 : return reset_sig_count_and_close(manio); // Time to close.
513 :
514 : // At this point, dynamically decide based on the current msg.
515 3558 : if(manio_find_boundary(blk->md5sum))
516 43 : return reset_sig_count_and_close(manio); // Time to close.
517 : return 0;
518 : }
519 :
520 187793 : static int write_sig_msg(struct manio *manio, struct blk *blk)
521 : {
522 : struct iobuf wbuf;
523 187793 : if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
524 187793 : blk_to_iobuf_sig_and_savepath(blk, &wbuf);
525 187793 : if(iobuf_send_msg_fzp(&wbuf, manio->fzp)) return -1;
526 187793 : return check_sig_count(manio, blk);
527 : }
528 :
529 187793 : int manio_write_sig_and_path(struct manio *manio, struct blk *blk)
530 : {
531 187793 : if(manio->protocol==PROTO_1) return 0;
532 187793 : if(manio->hook_sort && blk_fingerprint_is_hook(blk))
533 : {
534 : // Add to list of hooks for this manifest chunk.
535 2208 : manio->hook_sort[manio->hook_count++]=blk->fingerprint;
536 : }
537 187793 : if(manio->dindex_sort)
538 : {
539 35171 : uint64_t savepath=blk->savepath;
540 35171 : savepath &= 0xFFFFFFFFFFFF0000ULL;
541 : // Ignore obvious duplicates.
542 35171 : if(!manio->dindex_count
543 35152 : || manio->dindex_sort[manio->dindex_count-1]!=savepath)
544 : {
545 : // Add to list of dindexes for this manifest chunk.
546 34879 : manio->dindex_sort[manio->dindex_count++]=savepath;
547 : }
548 : }
549 187793 : return write_sig_msg(manio, blk);
550 : }
551 :
552 91872 : int manio_write_sbuf(struct manio *manio, struct sbuf *sb)
553 : {
554 91872 : if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
555 91872 : return sbuf_to_manifest(sb, manio->fzp);
556 : }
557 :
558 : // Return -1 on error, 0 on OK, 1 for srcmanio finished.
559 18 : int manio_copy_entry(struct sbuf *csb, struct sbuf *sb,
560 : struct manio *srcmanio, struct manio *dstmanio)
561 : {
562 : int ars;
563 : struct iobuf copy;
564 : struct blk *blk;
565 18 : if(!(blk=blk_alloc()))
566 : goto error;
567 :
568 : // Use the most recent stat for the new manifest.
569 18 : if(dstmanio)
570 : {
571 18 : if(manio_write_sbuf(dstmanio, sb)) goto error;
572 18 : if(dstmanio->protocol==PROTO_1)
573 : {
574 8 : sbuf_free_content(csb);
575 8 : blk_free(&blk);
576 8 : return 0;
577 : }
578 : }
579 :
580 10 : copy.len=csb->path.len;
581 10 : copy.cmd=csb->path.cmd;
582 10 : if(!(copy.buf=strdup_w(csb->path.buf, __func__)))
583 : goto error;
584 : while(1)
585 : {
586 30 : if((ars=manio_read_with_blk(srcmanio, csb,
587 : blk, NULL))<0) goto error;
588 30 : else if(ars>0)
589 : {
590 : // Finished.
591 5 : sbuf_free_content(csb);
592 5 : blk_free(&blk);
593 5 : iobuf_free_content(©);
594 5 : return 1;
595 : }
596 :
597 : // Got something.
598 25 : if(iobuf_pathcmp(&csb->path, ©))
599 : {
600 : // Found the next entry.
601 5 : iobuf_free_content(©);
602 5 : blk_free(&blk);
603 5 : return 0;
604 : }
605 20 : if(dstmanio)
606 : {
607 20 : if(!dstmanio->fzp
608 0 : && manio_open_next_fpath(dstmanio))
609 : goto error;
610 :
611 20 : if(csb->endfile.buf)
612 : {
613 10 : if(iobuf_send_msg_fzp(&csb->endfile,
614 : dstmanio->fzp)) goto error;
615 : }
616 : else
617 : {
618 : // Should have the next signature.
619 : // Write it to the destination manifest.
620 10 : if(manio_write_sig_and_path(dstmanio, blk))
621 : goto error;
622 : }
623 : }
624 : }
625 :
626 : error:
627 0 : blk_free(&blk);
628 0 : iobuf_free_content(©);
629 0 : return -1;
630 : }
631 :
632 0 : int manio_forward_through_sigs(struct sbuf *csb, struct manio *manio)
633 : {
634 : // Call manio_copy_entry with nothing to write to, so
635 : // that we forward through the sigs in manio.
636 0 : return manio_copy_entry(csb, NULL, manio, NULL);
637 : }
638 :
639 12990 : man_off_t *manio_tell(struct manio *manio)
640 : {
641 12990 : man_off_t *offset=NULL;
642 12990 : if(!manio->fzp)
643 : {
644 0 : logp("manio_tell called on null fzp\n");
645 0 : goto error;
646 : }
647 12990 : if(!(offset=man_off_t_alloc())
648 12990 : || !(offset->fpath=strdup_w(manio->offset->fpath, __func__))
649 12990 : || (offset->offset=fzp_tell(manio->fzp))<0)
650 : goto error;
651 12990 : offset->fcount=manio->offset->fcount;
652 12990 : return offset;
653 : error:
654 0 : man_off_t_free(&offset);
655 0 : return NULL;
656 : }
657 :
658 246 : int manio_seek(struct manio *manio, man_off_t *offset)
659 : {
660 246 : fzp_close(&manio->fzp);
661 246 : if(!(manio->fzp=fzp_gzopen(offset->fpath, manio->mode))
662 246 : || fzp_seek(manio->fzp, offset->offset, SEEK_SET))
663 : return -1;
664 246 : man_off_t_free_content(manio->offset);
665 246 : if(!(manio->offset->fpath=strdup_w(offset->fpath, __func__)))
666 : return -1;
667 246 : manio->offset->offset=offset->offset;
668 246 : manio->offset->fcount=offset->fcount;
669 246 : return 0;
670 : }
671 :
672 100 : static int remove_trailing_files(struct manio *manio, man_off_t *offset)
673 : {
674 100 : int ret=-1;
675 100 : char *fpath=NULL;
676 : struct stat statp;
677 : while(1)
678 : {
679 100 : free_w(&fpath);
680 100 : if(!(fpath=get_next_fpath(manio, offset)))
681 : goto end;
682 200 : if(lstat(fpath, &statp)) break;
683 0 : if(!S_ISREG(statp.st_mode))
684 : goto end;
685 0 : if(recursive_delete(fpath))
686 : goto end;
687 : }
688 : ret=0;
689 : end:
690 100 : free_w(&fpath);
691 100 : return ret;
692 : }
693 :
694 200 : int manio_close_and_truncate(struct manio **manio,
695 : man_off_t *offset, int compression)
696 : {
697 200 : int ret=-1;
698 200 : errno=0;
699 400 : if(!is_single_file(*manio)
700 100 : && remove_trailing_files(*manio, offset))
701 : goto end;
702 200 : if(manio_close(manio)) goto end;
703 200 : if(fzp_truncate(offset->fpath, FZP_FILE, offset->offset, compression))
704 : {
705 0 : logp("Could not fzp_truncate %s in %s(): %s\n",
706 : offset->fpath, __func__, strerror(errno));
707 0 : goto end;
708 : }
709 : ret=0;
710 : end:
711 200 : return ret;
712 : }
|