source: MondoRescue/branches/stable/mondo/src/common/libmondo-verify.c@ 1639

Last change on this file since 1639 was 1609, checked in by Bruno Cornec, 17 years ago

manual_cd_tray => manual_tray and usage of conf file for that field

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