source: MondoRescue/trunk/mondo/mondo/common/libmondo-verify.c@ 687

Last change on this file since 687 was 507, checked in by bcornec, 18 years ago

merge -r489:506 $SVN_M/branches/stable

  • Property svn:keywords set to Id
File size: 32.7 KB
Line 
1/* $Id: libmondo-verify.c 507 2006-04-30 00:04:16Z bcornec $ */
2
3/**
4 * @file
5 * Functions for verifying backups (booted from hard drive, not CD).
6 */
7
8#include "my-stuff.h"
9#include "mondostructures.h"
10#include "libmondo-verify.h"
11#include "newt-specific-EXT.h"
12#include "libmondo-files-EXT.h"
13#include "libmondo-fork-EXT.h"
14#include "libmondo-stream-EXT.h"
15#include "libmondo-string-EXT.h"
16#include "libmondo-devices-EXT.h"
17#include "libmondo-tools-EXT.h"
18
19/*@unused@*/
20//static char cvsid[] = "$Id: libmondo-verify.c 507 2006-04-30 00:04:16Z bcornec $";
21
22char *vfy_tball_fname(struct s_bkpinfo *, char *, int);
23
24
25/**
26 * The number of the most recently verified afioball.
27 * @ingroup globalGroup
28 */
29int g_last_afioball_number = -1;
30
31
32/**
33 * Generate a list of the files that have changed, based on @c afio @c -r
34 * messages.
35 * @param changedfiles_fname Filename of the place to put a list of afio's reported changed.
36 * @param ignorefiles_fname Filename of a list of files to ignore (use "" if none).
37 * @param stderr_fname File containing afio's stderr output.
38 * @return The number of differences found (0 for a perfect backup).
39 * @bug This function seems orphaned.
40 * @ingroup utilityGroup
41 */
42long
43generate_list_of_changed_files(char *changedfiles_fname,
44 char *ignorefiles_fname, char *stderr_fname)
45{
46 /*@ buffer ********************************************************** */
47 char *command;
48 char *afio_found_changes;
49
50 /*@ int ************************************************************* */
51 int res = 0;
52
53 /*@ long ************************************************************ */
54 long afio_diffs = 0;
55
56 assert_string_is_neither_NULL_nor_zerolength(changedfiles_fname);
57 assert_string_is_neither_NULL_nor_zerolength(ignorefiles_fname);
58 assert_string_is_neither_NULL_nor_zerolength(stderr_fname);
59
60 asprintf(&afio_found_changes, "%s.afio", ignorefiles_fname);
61 paranoid_system("sync");
62
63/* sprintf (command,
64 "grep \"afio: \" %s | awk '{j=substr($0,8); i=index(j,\": \");printf \"/%%s\\n\",substr(j,1,i-2);}' | sort -u | grep -v \"incheckentry.*xwait\" | grep -vx \"/afio:.*\" | grep -vx \"/dev/.*\" > %s",
65 stderr_fname, afio_found_changes);
66*/
67
68 log_msg(1, "Now scanning log file for 'afio: ' stuff");
69 asprintf(&command,
70 "grep \"afio: \" %s | sed 's/afio: //' | grep -vx \"/dev/.*\" >> %s",
71 stderr_fname, afio_found_changes);
72 log_msg(2, command);
73 res = system(command);
74 paranoid_free(command);
75 if (res) {
76 log_msg(2, "Warning - failed to think");
77 }
78
79 log_msg(1, "Now scanning log file for 'star: ' stuff");
80 asprintf(&command,
81 "grep \"star: \" %s | sed 's/star: //' | grep -vx \"/dev/.*\" >> %s",
82 stderr_fname, afio_found_changes);
83 log_msg(2, command);
84 res = system(command);
85 paranoid_free(command);
86 if (res) {
87 log_msg(2, "Warning - failed to think");
88 }
89// exclude_nonexistent_files (afio_found_changes);
90 afio_diffs = count_lines_in_file(afio_found_changes);
91 asprintf(&command,
92 "sort %s %s %s | uniq -c | awk '{ if ($1==\"2\") {print $2;};}' | grep -v \"incheckentry xwait()\" > %s",
93 ignorefiles_fname, afio_found_changes, afio_found_changes,
94 changedfiles_fname);
95 log_msg(2, command);
96 paranoid_system(command);
97 paranoid_free(command);
98 paranoid_free(afio_found_changes);
99 return (afio_diffs);
100}
101
102
103/**
104 * @addtogroup LLverifyGroup
105 * @{
106 */
107/**
108 * Verify all afioballs stored on the inserted CD (or an ISO image).
109 * @param bkpinfo The backup information structure. @c bkpinfo->backup_media_type
110 * is used in this function, and the structure is also passed to verify_an_afioball_from_CD().
111 * @param mountpoint The location the CD/DVD/ISO is mounted on.
112 * @return The number of sets containing differences (0 for success).
113 */
114int verify_afioballs_on_CD(struct s_bkpinfo *bkpinfo, char *mountpoint)
115{
116
117 /*@ buffers ********************************************************* */
118 char *tmp;
119
120 /*@ int ************************************************************* */
121 int set_number = 0;
122 int retval = 0;
123 int total_sets = 0;
124 int percentage = 0;
125
126 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
127 assert(bkpinfo != NULL);
128
129 for (set_number = 0;
130 set_number < 9999
131 &&
132 !does_file_exist(vfy_tball_fname
133 (bkpinfo, mountpoint, set_number));
134 set_number++);
135 if (!does_file_exist(vfy_tball_fname(bkpinfo, mountpoint, set_number))) {
136 return (0);
137 }
138
139 if (g_last_afioball_number != set_number - 1) {
140 if (set_number == 0) {
141 log_msg(1,
142 "Weird error in verify_afioballs_on_CD() but it's really a cosmetic error, nothing more");
143 } else {
144 retval++;
145 asprintf(&tmp, "Warning - missing set(s) between %d and %d\n",
146 g_last_afioball_number, set_number - 1);
147 log_to_screen(tmp);
148 paranoid_free(tmp);
149 }
150 }
151 asprintf(&tmp, "Verifying %s #%d's tarballs",
152 media_descriptor_string(bkpinfo->backup_media_type),
153 g_current_media_number);
154 open_evalcall_form(tmp);
155 paranoid_free(tmp);
156
157 for (total_sets = set_number;
158 does_file_exist(vfy_tball_fname(bkpinfo, mountpoint, total_sets));
159 total_sets++) {
160 log_msg(1, "total_sets = %d", total_sets);
161 }
162 for (;
163 does_file_exist(vfy_tball_fname(bkpinfo, mountpoint, set_number));
164 set_number++) {
165 percentage =
166 (set_number - g_last_afioball_number) * 100 / (total_sets -
167 g_last_afioball_number);
168 update_evalcall_form(percentage);
169 log_msg(1, "set = %d", set_number);
170 retval +=
171 verify_an_afioball_from_CD(bkpinfo,
172 vfy_tball_fname(bkpinfo, mountpoint,
173 set_number));
174 }
175 g_last_afioball_number = set_number - 1;
176 close_evalcall_form();
177 return (retval);
178}
179
180
181/**
182 * Verify all slices stored on the inserted CD (or a mounted ISO image).
183 * @param bkpinfo The backup information structure. Fields used:
184 * - @c compression_level
185 * - @c restore_path
186 * - @c use_lzo
187 * - @c zip_exe
188 * - @c zip_suffix
189 * @param mtpt The mountpoint the CD/DVD/ISO is mounted on.
190 * @return The number of differences (0 for perfect biggiefiles).
191 */
192int verify_all_slices_on_CD(struct s_bkpinfo *bkpinfo, char *mtpt)
193{
194
195 /*@ buffer ********************************************************** */
196 char *tmp;
197 char *mountpoint;
198// char ca, cb;
199 char *command;
200 char *sz_exe;
201 static char *bufblkA = NULL;
202 static char *bufblkB = NULL;
203 const long maxbufsize = 65536L;
204 long currsizA = 0;
205 long currsizB = 0;
206 long j;
207
208 /*@ long ************************************************************ */
209 long bigfile_num = 0;
210 long slice_num = -1;
211 int res;
212
213 static FILE *forig = NULL;
214 static struct s_filename_and_lstat_info biggiestruct;
215 static long last_bigfile_num = -1;
216 static long last_slice_num = -1;
217 FILE *pin;
218 FILE *fin;
219 int retval = 0;
220// long long outlen;
221
222 malloc_string(sz_exe);
223 if (!bufblkA) {
224 if (!(bufblkA = malloc(maxbufsize))) {
225 fatal_error("Cannot malloc bufblkA");
226 }
227 }
228 if (!bufblkB) {
229 if (!(bufblkB = malloc(maxbufsize))) {
230 fatal_error("Cannot malloc bufblkB");
231 }
232 }
233
234 assert(bkpinfo != NULL);
235 assert_string_is_neither_NULL_nor_zerolength(mtpt);
236
237 if (bkpinfo->compression_level > 0) {
238 if (bkpinfo->use_lzo) {
239 asprintf(&sz_exe, "lzop");
240 } else {
241 asprintf(&sz_exe, "bzip2");
242 }
243 } else {
244 asprintf(&sz_exe, " ");
245 }
246
247 iamhere("before vsbf");
248 asprintf(&tmp, "Verifying %s#%d's big files",
249 media_descriptor_string(bkpinfo->backup_media_type),
250 g_current_media_number);
251 open_evalcall_form(tmp);
252 paranoid_free(tmp);
253 iamhere("after vsbf");
254 asprintf(&mountpoint, "%s/archives", mtpt);
255 if (last_bigfile_num == -1) {
256 bigfile_num = 0;
257 slice_num = 0;
258 } else if (slice_num == 0) {
259 bigfile_num = last_bigfile_num + 1;
260 slice_num = 0;
261 } else {
262 bigfile_num = last_bigfile_num;
263 slice_num = last_slice_num + 1;
264 }
265 while (does_file_exist
266 (slice_fname
267 (bigfile_num, slice_num, mountpoint, bkpinfo->zip_suffix))
268 ||
269 does_file_exist(slice_fname
270 (bigfile_num, slice_num, mountpoint, ""))) {
271// handle slices until end of CD
272 if (slice_num == 0) {
273 log_msg(2, "ISO=%d bigfile=%ld --START--",
274 g_current_media_number, bigfile_num);
275 if (!
276 (fin =
277 fopen(slice_fname(bigfile_num, slice_num, mountpoint, ""),
278 "r"))) {
279 log_msg(2, "Cannot open bigfile's info file");
280 } else {
281 if (fread
282 ((void *) &biggiestruct, 1, sizeof(biggiestruct),
283 fin) < sizeof(biggiestruct)) {
284 log_msg(2, "Unable to get biggiestruct");
285 }
286 paranoid_fclose(fin);
287 }
288 asprintf(&tmp, "%s/%s", bkpinfo->restore_path,
289 biggiestruct.filename);
290 log_msg(2, "Opening biggiefile #%ld - '%s'", bigfile_num, tmp);
291 if (!(forig = fopen(tmp, "r"))) {
292 log_msg(2, "Failed to open bigfile. Darn.");
293 retval++;
294 }
295 paranoid_free(tmp);
296
297 slice_num++;
298 } else if (does_file_exist
299 (slice_fname(bigfile_num, slice_num, mountpoint, ""))) {
300 log_msg(2, "ISO=%d bigfile=%ld ---END---",
301 g_current_media_number, bigfile_num);
302 bigfile_num++;
303 paranoid_fclose(forig);
304 slice_num = 0;
305 } else {
306 log_msg(2, "ISO=%d bigfile=%ld slice=%ld \r",
307 g_current_media_number, bigfile_num, slice_num);
308 if (bkpinfo->compression_level > 0) {
309 asprintf(&command, "%s -dc %s 2>> %s", sz_exe,
310 slice_fname(bigfile_num, slice_num, mountpoint,
311 bkpinfo->zip_suffix),
312 MONDO_LOGFILE);
313 } else {
314 asprintf(&command, "cat %s",
315 slice_fname(bigfile_num, slice_num, mountpoint,
316 bkpinfo->zip_suffix));
317 }
318 if ((pin = popen(command, "r"))) {
319 res = 0;
320 while (!feof(pin)) {
321 currsizA = fread(bufblkA, 1, maxbufsize, pin);
322 if (currsizA <= 0) {
323 break;
324 }
325 currsizB = fread(bufblkB, 1, currsizA, forig);
326 if (currsizA != currsizB) {
327 res++;
328 } else {
329 for (j = 0;
330 j < currsizA && bufblkA[j] == bufblkB[j];
331 j++);
332 if (j < currsizA) {
333 res++;
334 }
335 }
336 }
337 paranoid_pclose(pin);
338 if (res && !strncmp(biggiestruct.filename, " /dev/", 5)) {
339 log_msg(3,
340 "Ignoring differences between %s and live filesystem because it's a device and therefore the archives are stored via ntfsclone, not dd.",
341 biggiestruct.filename);
342 log_msg(3,
343 "If you really want verification for %s, please contact the devteam and offer an incentive.",
344 biggiestruct.filename);
345 res = 0;
346 }
347 if (res) {
348 log_msg(0,
349 "afio: \"%s\": Corrupt biggie file, says libmondo-archive.c",
350 biggiestruct.filename);
351 retval++;
352 }
353 }
354 paranoid_free(command);
355 slice_num++;
356 }
357 }
358 paranoid_free(mountpoint);
359 paranoid_free(sz_exe);
360
361 last_bigfile_num = bigfile_num;
362 last_slice_num = slice_num - 1;
363 if (last_slice_num < 0) {
364 last_bigfile_num--;
365 }
366 close_evalcall_form();
367 if (bufblkA) {
368 paranoid_free(bufblkA);
369 }
370 if (bufblkB) {
371 paranoid_free(bufblkB);
372 }
373 return (0);
374}
375
376
377/**
378 * Verify one afioball from the CD.
379 * You should be changed to the root directory (/) for this to work.
380 * @param bkpinfo The backup information structure. Fields used:
381 * - @c bkpinfo->use_lzo
382 * - @c bkpinfo->tmpdir
383 * - @c bkpinfo->zip_exe
384 * - @c bkpinfo->zip_suffix
385 * @param tarball_fname The filename of the afioball to verify.
386 * @return 0, always.
387 */
388int verify_a_tarball(struct s_bkpinfo *bkpinfo, char *tarball_fname)
389{
390 /*@ buffers ********************************************************* */
391 char *command;
392 char *outlog;
393 char *tmp = NULL;
394 // char *p;
395
396 /*@ pointers ******************************************************* */
397 FILE *pin;
398
399 size_t n = 0;
400
401 /*@ long *********************************************************** */
402 long diffs = 0;
403 /* getcwd(old_pwd,MAX_STR_LEN-1); */
404
405 assert(bkpinfo != NULL);
406 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
407
408 log_it("Verifying fileset '%s'", tarball_fname);
409
410 /* chdir("/"); */
411 asprintf(&outlog, "%s/afio.log", bkpinfo->tmpdir);
412
413 /* if programmer forgot to say which compression thingy to use then find out */
414 if (strstr(tarball_fname, ".lzo")
415 && strcmp(bkpinfo->zip_suffix, "lzo")) {
416 log_msg(2, "OK, I'm going to start using lzop.");
417 strcpy(bkpinfo->zip_exe, "lzop");
418 strcpy(bkpinfo->zip_suffix, "lzo");
419 bkpinfo->use_lzo = TRUE;
420 }
421 if (strstr(tarball_fname, ".bz2")
422 && strcmp(bkpinfo->zip_suffix, "bz2")) {
423 log_msg(2, "OK, I'm going to start using bzip2.");
424 strcpy(bkpinfo->zip_exe, "bzip2");
425 strcpy(bkpinfo->zip_suffix, "bz2");
426 bkpinfo->use_lzo = FALSE;
427 }
428 unlink(outlog);
429 if (strstr(tarball_fname, ".star")) {
430 bkpinfo->use_star = TRUE;
431 if (strstr(tarball_fname, ".bz2"))
432 asprintf(&command,
433 "star -diff diffopts=mode,size,data file=%s %s >> %s 2>> %s",
434 tarball_fname,
435 (strstr(tarball_fname, ".bz2")) ? "-bz" : " ", outlog,
436 outlog);
437 } else {
438 bkpinfo->use_star = FALSE;
439 asprintf(&command, "afio -r -P %s -Z %s >> %s 2>> %s",
440 bkpinfo->zip_exe, tarball_fname, outlog, outlog);
441 }
442 log_msg(6, "command=%s", command);
443 paranoid_system(command);
444 paranoid_free(command);
445
446 if (length_of_file(outlog) < 10) {
447 asprintf(&command, "cat %s >> %s", outlog, MONDO_LOGFILE);
448 } else {
449 asprintf(&command, "cut -d':' -f%d %s | sort -u",
450 (bkpinfo->use_star) ? 1 : 2, outlog);
451 pin = popen(command, "r");
452 if (pin) {
453 for (getline(&tmp, &n, pin); !feof(pin);
454 getline(&tmp, &n, pin)) {
455 if (bkpinfo->use_star) {
456 if (!strstr(tmp, "diffopts=")) {
457 while (strlen(tmp) > 0
458 && tmp[strlen(tmp) - 1] < 32) {
459 tmp[strlen(tmp) - 1] = '\0';
460 }
461 if (strchr(tmp, '/')) {
462 if (!diffs) {
463 log_msg(0, "'%s' - differences found",
464 tarball_fname);
465 }
466 log_msg(0, "star: /%s",
467 strip_afio_output_line(tmp));
468 diffs++;
469 }
470 }
471 } else {
472 if (!diffs) {
473 log_msg(0, "'%s' - differences found",
474 tarball_fname);
475 }
476 log_msg(0, "afio: /%s", strip_afio_output_line(tmp));
477 diffs++;
478 }
479 }
480 paranoid_pclose(pin);
481 paranoid_free(tmp);
482 } else {
483 log_OS_error(command);
484 }
485 }
486 paranoid_free(outlog);
487 paranoid_free(command);
488
489 /* chdir(old_pwd); */
490 // sprintf (tmp, "uniq -u %s >> %s", "/tmp/mondo-verify.err", MONDO_LOGFILE);
491 // paranoid_system (tmp);
492 // unlink ("/tmp/mondo-verify.err");
493 return (0);
494}
495
496
497/**
498 * Verify one afioball from the CD.
499 * Checks for existence (calls fatal_error() if it does not exist) and
500 * then calls verify_an_afioball().
501 * @param bkpinfo The backup information structure. Passed to verify_an_afioball().
502 * @param tarball_fname The filename of the afioball to verify.
503 * @return The return value of verify_an_afioball().
504 * @see verify_an_afioball
505 */
506int
507verify_an_afioball_from_CD(struct s_bkpinfo *bkpinfo, char *tarball_fname)
508{
509
510 /*@ int ************************************************************* */
511 int res = 0;
512
513 assert(bkpinfo != NULL);
514 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
515
516 log_msg(1, "Verifying %s", tarball_fname);
517 if (!does_file_exist(tarball_fname)) {
518 fatal_error("Cannot verify nonexistent afioball");
519 }
520 res = verify_a_tarball(bkpinfo, tarball_fname);
521 return (res);
522}
523
524
525/**
526 * Verify one afioball from the opened tape/CD stream.
527 * Copies the file from tape to tmpdir and then calls verify_an_afioball().
528 * @param bkpinfo The backup information structure. Passed to verify_an_afioball().
529 * @param orig_fname The original filename of the afioball to verify.
530 * @param size The size of the afioball to verify.
531 * @return The return value of verify_an_afioball().
532 * @see verify_an_afioball
533 */
534int
535verify_an_afioball_from_stream(struct s_bkpinfo *bkpinfo, char *orig_fname,
536 long long size)
537{
538
539 /*@ int ************************************************************** */
540 int retval = 0;
541 int res = 0;
542
543 /*@ buffers ********************************************************** */
544 char *tmp;
545 char *tarball_fname;
546
547 /*@ pointers ********************************************************* */
548 char *p;
549
550 assert(bkpinfo != NULL);
551 assert_string_is_neither_NULL_nor_zerolength(orig_fname);
552
553 p = strrchr(orig_fname, '/');
554 if (!p) {
555 p = orig_fname;
556 } else {
557 p++;
558 }
559 asprintf(&tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);
560 paranoid_system(tmp);
561 paranoid_free(tmp);
562
563 asprintf(&tarball_fname, "%s/tmpfs/temporary-%s", bkpinfo->tmpdir, p);
564 /* BERLIOS : useless
565 asprintf(&tmp, "Temporarily copying file from tape to '%s'",
566 tarball_fname);
567 log_it(tmp);
568 paranoid_free(tmp);
569 */
570 read_file_from_stream_to_file(bkpinfo, tarball_fname, size);
571 res = verify_a_tarball(bkpinfo, tarball_fname);
572 if (res) {
573 asprintf(&tmp,
574 "Afioball '%s' no longer matches your live filesystem",
575 p);
576 log_msg(0, tmp);
577 paranoid_free(tmp);
578 retval++;
579 }
580 unlink(tarball_fname);
581 paranoid_free(tarball_fname);
582 return (retval);
583}
584
585
586/**
587 * Verify one biggiefile form the opened tape/CD stream.
588 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir is the only field used.
589 * @param biggie_fname The filename of the biggiefile to verify.
590 * @param size The size in bytes of said biggiefile.
591 * @return 0 for success (even if the file doesn't match); nonzero for a tape error.
592 */
593int
594verify_a_biggiefile_from_stream(struct s_bkpinfo *bkpinfo,
595 char *biggie_fname, long long size)
596{
597
598 /*@ int ************************************************************* */
599 int retval = 0;
600 int res = 0;
601 int current_slice_number = 0;
602 int ctrl_chr = '\0';
603
604 /*@ char ************************************************************ */
605 char *test_file;
606 char *biggie_cksum;
607 char *orig_cksum;
608 char *tmp;
609 char *slice_fnam = (char *) &res;
610
611 /*@ pointers ******************************************************** */
612 char *p;
613
614 /*@ long long ******************************************************* */
615 long long slice_siz;
616
617 assert(bkpinfo != NULL);
618 assert_string_is_neither_NULL_nor_zerolength(biggie_fname);
619
620 p = strrchr(biggie_fname, '/');
621 if (!p) {
622 p = biggie_fname;
623 } else {
624 p++;
625 }
626 asprintf(&test_file, "%s/temporary-%s", bkpinfo->tmpdir, p);
627 asprintf(&tmp,
628 "Temporarily copying biggiefile %s's slices from tape to '%s'",
629 p, test_file);
630 log_it(tmp);
631 paranoid_free(tmp);
632 for (res =
633 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr);
634 ctrl_chr != BLK_STOP_A_BIGGIE;
635 res =
636 read_header_block_from_stream(&slice_siz, slice_fnam,
637 &ctrl_chr)) {
638 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
639 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
640 }
641 res = read_file_from_stream_to_file(bkpinfo, test_file, slice_siz);
642 unlink(test_file);
643 paranoid_free(slice_fnam);
644 slice_fnam = (char *) &res;
645 res =
646 read_header_block_from_stream(&slice_siz, slice_fnam,
647 &ctrl_chr);
648 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
649 log_msg(2, "test_file = %s", test_file);
650 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
651 }
652 current_slice_number++;
653 retval += res;
654 paranoid_free(slice_fnam);
655 slice_fnam = (char *) &res;
656 }
657 paranoid_free(test_file);
658
659 asprintf(&biggie_cksum, slice_fnam);
660 paranoid_free(slice_fnam);
661
662 if (biggie_cksum[0] != '\0') {
663 orig_cksum = calc_checksum_of_file(biggie_fname);
664 if (strcmp(biggie_cksum, orig_cksum)) {
665 asprintf(&tmp, "orig cksum=%s; curr cksum=%s", biggie_cksum,
666 orig_cksum);
667 log_msg(2, tmp);
668 paranoid_free(tmp);
669
670 asprintf(&tmp, _("%s has changed on live filesystem"),
671 biggie_fname);
672 log_to_screen(tmp);
673 paranoid_free(tmp);
674
675 asprintf(&tmp, "echo \"%s\" >> /tmp/biggies.changed",
676 biggie_fname);
677 system(tmp);
678 paranoid_free(tmp);
679 }
680 paranoid_free(orig_cksum);
681 }
682 paranoid_free(biggie_cksum);
683
684 return (retval);
685}
686
687
688/**
689 * Verify all afioballs from the opened tape/CD stream.
690 * @param bkpinfo The backup information structure. Fields used:
691 * - @c bkpinfo->restore_path
692 * - @c bkpinfo->tmpdir
693 *
694 * @return 0 for success (even if there are differences); nonzero for a tape error.
695 */
696int verify_afioballs_from_stream(struct s_bkpinfo *bkpinfo)
697{
698 /*@ int ********************************************************** */
699 int retval = 0;
700 int res = 0;
701 long current_afioball_number = 0;
702 int ctrl_chr = 0;
703 int total_afioballs = 0;
704
705 /*@ buffers ***************************************************** */
706 char *tmp;
707 char *fname = (char *) &res; /* Should NOT be NULL */
708 char *curr_xattr_list_fname;
709 char *curr_acl_list_fname;
710
711 /*@ long long *************************************************** */
712 long long size = 0;
713
714 assert(bkpinfo != NULL);
715
716 asprintf(&curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ,
717 bkpinfo->tmpdir);
718 asprintf(&curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ,
719 bkpinfo->tmpdir);
720 log_to_screen(_("Verifying regular archives on tape"));
721 total_afioballs = get_last_filelist_number(bkpinfo) + 1;
722 open_progress_form(_("Verifying filesystem"),
723 _("I am verifying archives against your live filesystem now."),
724 _("Please wait. This may take a couple of hours."), "",
725 total_afioballs);
726 res = read_header_block_from_stream(&size, NULL, &ctrl_chr);
727 if (ctrl_chr != BLK_START_AFIOBALLS) {
728 iamhere("YOU SHOULD NOT GET HERE");
729 iamhere("Grabbing the EXAT files");
730 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
731 res =
732 read_EXAT_files_from_tape(bkpinfo, &size, NULL, &ctrl_chr,
733 curr_xattr_list_fname,
734 curr_acl_list_fname);
735 }
736 }
737 if (ctrl_chr != BLK_START_AFIOBALLS) {
738 wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
739 }
740 paranoid_free(curr_xattr_list_fname);
741 paranoid_free(curr_acl_list_fname);
742
743 for (res = read_header_block_from_stream(&size, fname, &ctrl_chr);
744 ctrl_chr != BLK_STOP_AFIOBALLS;
745 res = read_header_block_from_stream(&size, fname, &ctrl_chr)) {
746 asprintf(&curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ,
747 bkpinfo->tmpdir, current_afioball_number);
748 asprintf(&curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ,
749 bkpinfo->tmpdir, current_afioball_number);
750 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
751 iamhere("Reading EXAT files from tape");
752 paranoid_free(fname);
753 fname = (char *) &res;
754 res =
755 read_EXAT_files_from_tape(bkpinfo, &size, fname, &ctrl_chr,
756 curr_xattr_list_fname,
757 curr_acl_list_fname);
758 }
759 paranoid_free(curr_xattr_list_fname);
760 paranoid_free(curr_acl_list_fname);
761
762 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
763 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
764 }
765 asprintf(&tmp, "Verifying fileset #%ld", current_afioball_number);
766 /*log_it(tmp); */
767 update_progress_form(tmp);
768 paranoid_free(tmp);
769
770 res = verify_an_afioball_from_stream(bkpinfo, fname, size);
771 if (res) {
772 asprintf(&tmp, _("Afioball %ld differs from live filesystem"),
773 current_afioball_number);
774 log_to_screen(tmp);
775 paranoid_free(tmp);
776 }
777 retval += res;
778 current_afioball_number++;
779 g_current_progress++;
780 paranoid_free(fname);
781 fname = (char *) &res;
782 res = read_header_block_from_stream(&size, fname, &ctrl_chr);
783 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
784 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
785 }
786 paranoid_free(fname);
787 fname = (char *) &res;
788 }
789 log_msg(1, "All done with afioballs");
790 close_progress_form();
791 paranoid_free(fname);
792 return (retval);
793}
794
795
796/**
797 * Verify all biggiefiles on the opened CD/tape stream.
798 * @param bkpinfo The backup information structure. Fields used:
799 * - @c bkpinfo->restore_path
800 * - @c bkpinfo->tmpdir
801 *
802 * @return 0 for success (even if there are differences); nonzero for a tape error.
803 */
804int verify_biggiefiles_from_stream(struct s_bkpinfo *bkpinfo)
805{
806
807 /*@ int ************************************************************ */
808 int retval = 0;
809 int res = 0;
810 int ctrl_chr = 0;
811
812 /*@ long *********************************************************** */
813 long noof_biggiefiles = 0;
814 long current_biggiefile_number = 0;
815
816 /*@ buffers ******************************************************** */
817 char *orig_fname = (char *) &ctrl_chr; /* Should NOT be NULL */
818 char *logical_fname;
819 char *comment;
820 char *curr_xattr_list_fname;
821 char *curr_acl_list_fname;
822 /*@ pointers ******************************************************* */
823 char *p;
824
825 /*@ long long size ************************************************* */
826 long long size = 0;
827
828 assert(bkpinfo != NULL);
829
830 asprintf(&curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ,
831 bkpinfo->tmpdir);
832 asprintf(&curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ,
833 bkpinfo->tmpdir);
834 asprintf(&comment, "Verifying all bigfiles.");
835 log_to_screen(comment);
836 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr);
837 if (ctrl_chr != BLK_START_BIGGIEFILES) {
838 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
839 iamhere("Grabbing the EXAT biggiefiles");
840 paranoid_free(orig_fname);
841 orig_fname = (char *) &ctrl_chr;
842 res =
843 read_EXAT_files_from_tape(bkpinfo, &size, orig_fname,
844 &ctrl_chr, curr_xattr_list_fname,
845 curr_acl_list_fname);
846 }
847 }
848 paranoid_free(curr_xattr_list_fname);
849 paranoid_free(curr_acl_list_fname);
850 paranoid_free(orig_fname);
851 orig_fname = (char *) &ctrl_chr;
852
853 if (ctrl_chr != BLK_START_BIGGIEFILES) {
854 wrong_marker(BLK_START_BIGGIEFILES, ctrl_chr);
855 }
856 noof_biggiefiles = (long) size;
857 log_msg(1, "noof_biggiefiles = %ld", noof_biggiefiles);
858 open_progress_form(_("Verifying big files"), comment,
859 _("Please wait. This may take some time."), "",
860 noof_biggiefiles);
861 paranoid_free(comment);
862
863 for (res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr);
864 ctrl_chr != BLK_STOP_BIGGIEFILES;
865 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr))
866 {
867 if (ctrl_chr != BLK_START_A_NORMBIGGIE
868 && ctrl_chr != BLK_START_A_PIHBIGGIE) {
869 wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
870 }
871 p = strrchr(orig_fname, '/');
872 if (!p) {
873 p = orig_fname;
874 } else {
875 p++;
876 }
877 asprintf(&comment, _("Verifying bigfile #%ld (%ld K)"),
878 current_biggiefile_number, (long) size >> 10);
879 update_progress_form(comment);
880 paranoid_free(comment);
881
882 asprintf(&logical_fname, "%s/%s", bkpinfo->restore_path,
883 orig_fname);
884 res =
885 verify_a_biggiefile_from_stream(bkpinfo, logical_fname, size);
886 paranoid_free(logical_fname);
887 retval += res;
888 current_biggiefile_number++;
889 g_current_progress++;
890 paranoid_free(orig_fname);
891 orig_fname = (char *) &ctrl_chr;
892 }
893 close_progress_form();
894 return (retval);
895}
896
897/* @} - end of LLverifyGroup */
898
899
900/**
901 * Verify the CD indicated by @c g_current_media_number.
902 * @param bkpinfo The backup information structure. Fields used:
903 * - @c bkpinfo->isodir
904 * - @c bkpinfo->prefix
905 * - @c bkpinfo->manual_cd_tray
906 * - @c bkpinfo->media_device
907 * - @c bkpinfo->nfs_remote_dir
908 * - @c bkpinfo->tmpdir
909 * - @c bkpinfo->verify_data
910 *
911 * @return 0 for success (even if differences are found), nonzero for failure.
912 * @ingroup verifyGroup
913 */
914int verify_cd_image(struct s_bkpinfo *bkpinfo)
915{
916
917 /*@ int ************************************************************ */
918 int retval = 0;
919
920 /*@ buffers ******************************************************** */
921 char *mountpoint;
922 char *command;
923 char *tmp;
924 char *fname;
925#ifdef __FreeBSD__
926 char mdd[32];
927 char *mddevice = mdd;
928 int ret = 0;
929 int vndev = 2;
930#else
931//skip
932#endif
933
934 assert(bkpinfo != NULL);
935
936 asprintf(&mountpoint, "%s/cdrom", bkpinfo->tmpdir);
937 asprintf(&fname, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->nfs_remote_dir,
938 bkpinfo->prefix, g_current_media_number);
939
940 mkdir(mountpoint, 1777);
941 sync();
942 if (!does_file_exist(fname)) {
943 asprintf(&tmp,
944 "%s not found; assuming you backed up to CD; verifying CD...",
945 fname);
946 log_msg(2, tmp);
947 paranoid_free(tmp);
948
949 if (bkpinfo->manual_cd_tray) {
950 popup_and_OK(_("Please push CD tray closed."));
951 }
952 if (find_and_mount_actual_cd(bkpinfo, mountpoint)) {
953 log_to_screen(_("failed to mount actual CD"));
954 return (1);
955 }
956 } else {
957 asprintf(&tmp, "%s found; verifying ISO...", fname);
958 log_to_screen(tmp);
959 paranoid_free(tmp);
960#ifdef __FreeBSD__
961 ret = 0;
962 vndev = 2;
963 mddevice = make_vn(fname);
964 if (ret) {
965 asprintf(&tmp, _("make_vn of %s failed; unable to verify ISO\n"),
966 fname);
967 log_to_screen(tmp);
968 paranoid_free(tmp);
969 return (1);
970 }
971 asprintf(&command, "mount_cd9660 %s %s", mddevice, mountpoint);
972#else
973 asprintf(&command, "mount -o loop,ro -t iso9660 %s %s", fname,
974 mountpoint);
975#endif
976 if (run_program_and_log_output(command, FALSE)) {
977 asprintf(&tmp, _("%s failed; unable to mount ISO image\n"),
978 command);
979 log_to_screen(tmp);
980 paranoid_free(tmp);
981 return (1);
982 }
983 paranoid_free(command);
984 }
985 log_msg(2, "OK, I've mounted the ISO/CD\n");
986 asprintf(&tmp, "%s/archives/NOT-THE-LAST", mountpoint);
987 if (!does_file_exist(tmp)) {
988 log_msg
989 (2,
990 "This is the last CD. I am therefore setting bkpinfo->verify_data to FALSE.");
991 bkpinfo->verify_data = FALSE;
992/*
993 (a) It's an easy way to tell the calling subroutine that we've finished &
994 there are no more CD's to be verified; (b) It stops the post-backup verifier
995 from running after the per-CD verifier has run too.
996*/
997 }
998 paranoid_free(tmp);
999
1000 verify_afioballs_on_CD(bkpinfo, mountpoint);
1001 iamhere("before verify_all_slices");
1002 verify_all_slices_on_CD(bkpinfo, mountpoint);
1003
1004#ifdef __FreeBSD__
1005 ret = 0;
1006 asprintf(&command, "umount %s", mountpoint);
1007 ret += system(command);
1008
1009 ret += kick_vn(mddevice);
1010 if (ret)
1011#else
1012 asprintf(&command, "umount %s", mountpoint);
1013
1014 if (system(command))
1015#endif
1016 {
1017 asprintf(&tmp, "%s failed; unable to unmount ISO image\n",
1018 command);
1019 log_to_screen(tmp);
1020 paranoid_free(tmp);
1021 retval++;
1022 } else {
1023 log_msg(2, "OK, I've unmounted the ISO file\n");
1024 }
1025 paranoid_free(command);
1026 paranoid_free(mountpoint);
1027
1028 if (!does_file_exist(fname)) {
1029 asprintf(&command, "umount %s", bkpinfo->media_device);
1030 run_program_and_log_output(command, 2);
1031 paranoid_free(command);
1032
1033 if (!bkpinfo->please_dont_eject
1034 && eject_device(bkpinfo->media_device)) {
1035 log_msg(2, "Failed to eject CD-ROM drive");
1036 }
1037 }
1038 paranoid_free(fname);
1039 return (retval);
1040}
1041
1042
1043/**
1044 * Verify all backups on tape.
1045 * This should be done after the backup process has already closed the tape.
1046 * @param bkpinfo The backup information structure. Passed to various helper functions.
1047 * @return 0 for success (even if thee were differences), nonzero for failure.
1048 * @ingroup verifyGroup
1049 */
1050int verify_tape_backups(struct s_bkpinfo *bkpinfo)
1051{
1052
1053 /*@ int ************************************************************ */
1054 int retval = 0;
1055
1056 /*@ buffers ******************************************************** */
1057 char *tmp;
1058 char *changed_files_fname;
1059
1060 /*@ long *********************************************************** */
1061 long diffs = 0;
1062
1063 assert(bkpinfo != NULL);
1064
1065 log_msg(3, "verify_tape_backups --- starting");
1066 log_to_screen(_("Verifying backups"));
1067 openin_tape(bkpinfo);
1068
1069 /* verify archives themselves */
1070 retval += verify_afioballs_from_stream(bkpinfo);
1071 retval += verify_biggiefiles_from_stream(bkpinfo);
1072
1073 /* find the final blocks */
1074 paranoid_system("sync");
1075 sleep(2);
1076 closein_tape(bkpinfo);
1077
1078 /* close tape; exit */
1079 // fclose(g_tape_stream); <-- not needed; is handled by closein_tape()
1080 paranoid_system
1081 ("rm -f /tmp/biggies.changed /tmp/changed.files.[0-9]* 2> /dev/null");
1082 asprintf(&changed_files_fname, "/tmp/changed.files.%d",
1083 (int) (random() % 32767));
1084 asprintf(&tmp,
1085 "grep -x \"%s:.*\" %s | cut -d'\"' -f2 | sort -u | awk '{print \"/\"$0;};' | tr -s '/' '/' | grep -v \"(total of\" | grep -v \"incheckentry.*xwait\" | grep -vx \"/afio:.*\" | grep -vx \"dev/.*\" > %s",
1086 (bkpinfo->use_star) ? "star" : "afio", MONDO_LOGFILE,
1087 changed_files_fname);
1088 log_msg(2, "Running command to derive list of changed files");
1089 log_msg(2, tmp);
1090 if (system(tmp)) {
1091 if (does_file_exist(changed_files_fname)
1092 && length_of_file(changed_files_fname) > 2) {
1093 log_to_screen
1094 (_("Warning - unable to check logfile to derive list of changed files"));
1095 } else {
1096 log_to_screen
1097 (_("No differences found. Therefore, no 'changed.files' text file."));
1098 }
1099 }
1100 paranoid_free(tmp);
1101
1102 asprintf(&tmp, "cat /tmp/biggies.changed >> %s", changed_files_fname);
1103 paranoid_system(tmp);
1104 paranoid_free(tmp);
1105
1106 diffs = count_lines_in_file(changed_files_fname);
1107 if (diffs > 0) {
1108 asprintf(&tmp, "cp -f %s %s", changed_files_fname,
1109 "/tmp/changed.files");
1110 run_program_and_log_output(tmp, FALSE);
1111 paranoid_free(tmp);
1112
1113 asprintf(&tmp,
1114 "%ld files differed from live filesystem; type less %s or less %s to see",
1115 diffs, changed_files_fname, "/tmp/changed.files");
1116 log_msg(0, tmp);
1117 paranoid_free(tmp);
1118
1119 log_to_screen
1120 (_("See /tmp/changed.files for a list of nonmatching files."));
1121 log_to_screen
1122 (_("The files probably changed on filesystem, not on backup media."));
1123 // retval++;
1124 }
1125 paranoid_free(changed_files_fname);
1126 return (retval);
1127}
1128
1129
1130/**
1131 * Generate the filename of a tarball to verify.
1132 * @param bkpinfo The backup information structure. @c bkpinfo->zip_suffix is the only field used.
1133 * @param mountpoint The directory where the CD/DVD/ISO is mounted.
1134 * @param setno The afioball number to get the location of.
1135 * @return The absolute path to the afioball.
1136 * @note The returned string points to static data that will be overwritten with each call.
1137 * @ingroup stringGroup
1138 */
1139char *vfy_tball_fname(struct s_bkpinfo *bkpinfo, char *mountpoint,
1140 int setno)
1141{
1142 /*@ buffers ******************************************************* */
1143 static char *output;
1144
1145 assert(bkpinfo != NULL);
1146 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1147 asprintf(&output, "%s/archives/%d.star.%s", mountpoint, setno,
1148 bkpinfo->zip_suffix);
1149 if (!does_file_exist(output)) {
1150 paranoid_free(output);
1151 asprintf(&output, "%s/archives/%d.afio.%s", mountpoint, setno,
1152 bkpinfo->zip_suffix);
1153 }
1154 return (output);
1155}
Note: See TracBrowser for help on using the repository browser.