source: MondoRescue/branches/2.2.5/mondo/src/common/libmondo-verify.c@ 1647

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

Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
Should solve the tmpdir issue from previous rev.
May still not compile

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