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

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

Integration of a big patch from rene-marc dolhen <rmd_at_mecreant.org> to support internationalization with gettext.

  • 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 497 2006-04-27 22:34:03Z 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 497 2006-04-27 22:34:03Z 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->isodir, bkpinfo->nfs_remote_dir,
1023 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.