source: MondoRescue/branches/3.0/mondo/src/common/libmondo-verify.c@ 3192

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