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

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

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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