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

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

Apply patch from Andree Leidenfrost, modified a bit to use bkpinfo->tmpdir instead of /tmp
or MINDI_CACHE when appropriate. Fix security issues in mondo
Thanks al ot Andree for catching all those issues.
Will not compile needs more work as bkpinfo->tmpdir isn't available everywhere
Should become a global in 3.x when only containing pointers.

  • Property svn:keywords set to Id
File size: 36.3 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 1644 2007-09-23 00:41:29Z 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 1644 2007-09-23 00:41:29Z 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/**
131 * Generate a list of the files that have changed, based on @c afio @c -r
132 * messages.
133 * @param changedfiles_fname Filename of the place to put a list of afio's reported changed.
134 * @param ignorefiles_fname Filename of a list of files to ignore (use "" if none).
135 * @param stderr_fname File containing afio's stderr output.
136 * @return The number of differences found (0 for a perfect backup).
137 * @bug This function seems orphaned.
138 * @ingroup utilityGroup
139 */
140long
141generate_list_of_changed_files(char *changedfiles_fname,
142 char *ignorefiles_fname, char *stderr_fname)
143{
144 /*@ buffer ********************************************************** */
145 char *command;
146 char *afio_found_changes;
147
148 /*@ int ************************************************************* */
149 int res = 0;
150
151 /*@ long ************************************************************ */
152 long afio_diffs = 0;
153
154 command = malloc(2000);
155 afio_found_changes = malloc(500);
156 assert_string_is_neither_NULL_nor_zerolength(changedfiles_fname);
157 assert_string_is_neither_NULL_nor_zerolength(ignorefiles_fname);
158 assert_string_is_neither_NULL_nor_zerolength(stderr_fname);
159
160 sprintf(afio_found_changes, "%s.afio", ignorefiles_fname);
161 paranoid_system("sync");
162
163/* sprintf (command,
164 "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",
165 stderr_fname, afio_found_changes);
166*/
167
168 log_msg(1, "Now scanning log file for 'afio: ' stuff");
169 sprintf(command,
170 "grep \"afio: \" %s | sed 's/afio: //' | grep -vE '^/dev/.*$' >> %s",
171 stderr_fname, afio_found_changes);
172 log_msg(2, command);
173 res = system(command);
174 if (res) {
175 log_msg(2, "Warning - failed to think");
176 }
177
178 log_msg(1, "Now scanning log file for 'star: ' stuff");
179 sprintf(command,
180 "grep \"star: \" %s | sed 's/star: //' | grep -vE '^/dev/.*$' >> %s",
181 stderr_fname, afio_found_changes);
182 log_msg(2, command);
183 res = system(command);
184 if (res) {
185 log_msg(2, "Warning - failed to think");
186 }
187// exclude_nonexistent_files (afio_found_changes);
188 afio_diffs = count_lines_in_file(afio_found_changes);
189 sprintf(command,
190 "sort %s %s %s | uniq -c | awk '{ if ($1==\"2\") {print $2;};}' | grep -v \"incheckentry xwait()\" > %s",
191 ignorefiles_fname, afio_found_changes, afio_found_changes,
192 changedfiles_fname);
193 log_msg(2, command);
194 paranoid_system(command);
195 paranoid_free(command);
196 paranoid_free(afio_found_changes);
197 return (afio_diffs);
198}
199
200
201/**
202 * @addtogroup LLverifyGroup
203 * @{
204 */
205/**
206 * Verify all afioballs stored on the inserted CD (or an ISO image).
207 * @param bkpinfo The backup information structure. @c bkpinfo->backup_media_type
208 * is used in this function, and the structure is also passed to verify_an_afioball_from_CD().
209 * @param mountpoint The location the CD/DVD/ISO is mounted on.
210 * @return The number of sets containing differences (0 for success).
211 */
212int verify_afioballs_on_CD(struct s_bkpinfo *bkpinfo, char *mountpoint)
213{
214
215 /*@ buffers ********************************************************* */
216 char *tmp;
217
218 /*@ int ************************************************************* */
219 int set_number = 0;
220 int retval = 0;
221 int total_sets = 0;
222 int percentage = 0;
223
224 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
225 assert(bkpinfo != NULL);
226 malloc_string(tmp);
227
228 for (set_number = 0;
229 set_number < 9999
230 &&
231 !does_file_exist(vfy_tball_fname
232 (bkpinfo, mountpoint, set_number));
233 set_number++);
234 if (!does_file_exist(vfy_tball_fname(bkpinfo, mountpoint, set_number))) {
235 return (0);
236 }
237
238 if (g_last_afioball_number != set_number - 1) {
239 if (set_number == 0) {
240 log_msg(1,
241 "Weird error in verify_afioballs_on_CD() but it's really a cosmetic error, nothing more");
242 } else {
243 retval++;
244 sprintf(tmp, "Warning - missing set(s) between %d and %d\n",
245 g_last_afioball_number, set_number - 1);
246 log_to_screen(tmp);
247 }
248 }
249 sprintf(tmp, "Verifying %s #%d's tarballs",
250 media_descriptor_string(bkpinfo->backup_media_type),
251 g_current_media_number);
252 open_evalcall_form(tmp);
253
254 for (total_sets = set_number;
255 does_file_exist(vfy_tball_fname(bkpinfo, mountpoint, total_sets));
256 total_sets++) {
257 log_msg(1, "total_sets = %d", total_sets);
258 }
259 for (;
260 does_file_exist(vfy_tball_fname(bkpinfo, mountpoint, set_number));
261 set_number++) {
262 percentage =
263 (set_number - g_last_afioball_number) * 100 / (total_sets -
264 g_last_afioball_number);
265 update_evalcall_form(percentage);
266 log_msg(1, "set = %d", set_number);
267 retval +=
268 verify_an_afioball_from_CD(bkpinfo,
269 vfy_tball_fname(bkpinfo, mountpoint,
270 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(struct s_bkpinfo *bkpinfo, 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(struct s_bkpinfo *bkpinfo, 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(struct s_bkpinfo *bkpinfo, char *tarball_fname)
634{
635
636 /*@ int ************************************************************* */
637 int res = 0;
638
639 assert(bkpinfo != NULL);
640 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
641
642 log_msg(1, "Verifying %s", tarball_fname);
643 if (!does_file_exist(tarball_fname)) {
644 fatal_error("Cannot verify nonexistent afioball");
645 }
646 res = verify_a_tarball(bkpinfo, tarball_fname);
647 return (res);
648}
649
650
651/**
652 * Verify one afioball from the opened tape/CD stream.
653 * Copies the file from tape to tmpdir and then calls verify_an_afioball().
654 * @param bkpinfo The backup information structure. Passed to verify_an_afioball().
655 * @param orig_fname The original filename of the afioball to verify.
656 * @param size The size of the afioball to verify.
657 * @return The return value of verify_an_afioball().
658 * @see verify_an_afioball
659 */
660int
661verify_an_afioball_from_stream(struct s_bkpinfo *bkpinfo, char *orig_fname,
662 long long size)
663{
664
665 /*@ int ************************************************************** */
666 int retval = 0;
667 int res = 0;
668
669 /*@ buffers ********************************************************** */
670 char *tmp;
671 char *tarball_fname;
672
673 /*@ pointers ********************************************************* */
674 char *p;
675
676 malloc_string(tmp);
677 malloc_string(tarball_fname);
678 assert(bkpinfo != NULL);
679 assert_string_is_neither_NULL_nor_zerolength(orig_fname);
680
681 p = strrchr(orig_fname, '/');
682 if (!p) {
683 p = orig_fname;
684 } else {
685 p++;
686 }
687 sprintf(tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);
688 paranoid_system(tmp);
689 sprintf(tarball_fname, "%s/tmpfs/temporary-%s", bkpinfo->tmpdir, p);
690 sprintf(tmp, "Temporarily copying file from tape to '%s'",
691 tarball_fname);
692/* log_it(tmp); */
693 read_file_from_stream_to_file(bkpinfo, tarball_fname, size);
694 res = verify_a_tarball(bkpinfo, tarball_fname);
695 if (res) {
696 sprintf(tmp,
697 "Afioball '%s' no longer matches your live filesystem", p);
698 log_msg(0, tmp);
699 retval++;
700 }
701 unlink(tarball_fname);
702 paranoid_free(tmp);
703 paranoid_free(tarball_fname);
704 return (retval);
705}
706
707
708/**
709 * Verify one biggiefile form the opened tape/CD stream.
710 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir is the only field used.
711 * @param biggie_fname The filename of the biggiefile to verify.
712 * @param size The size in bytes of said biggiefile.
713 * @return 0 for success (even if the file doesn't match); nonzero for a tape error.
714 */
715int
716verify_a_biggiefile_from_stream(struct s_bkpinfo *bkpinfo,
717 char *biggie_fname, long long size)
718{
719
720 /*@ int ************************************************************* */
721 int retval = 0;
722 int res = 0;
723 int current_slice_number = 0;
724 int ctrl_chr = '\0';
725
726 /*@ char ************************************************************ */
727 char *test_file;
728 char *biggie_cksum;
729 char *orig_cksum;
730 char *tmp;
731 char *slice_fnam;
732
733 /*@ pointers ******************************************************** */
734 char *p;
735
736 /*@ long long ******************************************************* */
737 long long slice_siz;
738
739 malloc_string(test_file);
740 malloc_string(biggie_cksum);
741 malloc_string(orig_cksum);
742 malloc_string(tmp);
743 malloc_string(slice_fnam);
744 assert(bkpinfo != NULL);
745 assert_string_is_neither_NULL_nor_zerolength(biggie_fname);
746
747 p = strrchr(biggie_fname, '/');
748 if (!p) {
749 p = biggie_fname;
750 } else {
751 p++;
752 }
753 sprintf(test_file, "%s/temporary-%s", bkpinfo->tmpdir, p);
754 sprintf(tmp,
755 "Temporarily copying biggiefile %s's slices from tape to '%s'",
756 p, test_file);
757/* log_it(tmp); */
758 for (res =
759 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr);
760 ctrl_chr != BLK_STOP_A_BIGGIE;
761 res =
762 read_header_block_from_stream(&slice_siz, slice_fnam,
763 &ctrl_chr)) {
764 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
765 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
766 }
767 res = read_file_from_stream_to_file(bkpinfo, test_file, slice_siz);
768 unlink(test_file);
769 res =
770 read_header_block_from_stream(&slice_siz, slice_fnam,
771 &ctrl_chr);
772 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
773 log_msg(2, "test_file = %s", test_file);
774 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
775 }
776 current_slice_number++;
777 retval += res;
778 }
779 strcpy(biggie_cksum, slice_fnam);
780 if (biggie_cksum[0] != '\0') {
781 strcpy(orig_cksum, calc_checksum_of_file(biggie_fname));
782 if (strcmp(biggie_cksum, orig_cksum)) {
783 sprintf(tmp, "orig cksum=%s; curr cksum=%s", biggie_cksum,
784 orig_cksum);
785 log_msg(2, tmp);
786 sprintf(tmp, "%s has changed on live filesystem",
787 biggie_fname);
788 log_to_screen(tmp);
789 sprintf(tmp, "echo \"%s\" >> %s/biggies.changed",
790 biggie_fname, bkpinfo->tmpdir);
791 system(tmp);
792 }
793 }
794 paranoid_free(test_file);
795 paranoid_free(biggie_cksum);
796 paranoid_free(orig_cksum);
797 paranoid_free(tmp);
798 paranoid_free(slice_fnam);
799 return (retval);
800}
801
802
803/**
804 * Verify all afioballs from the opened tape/CD stream.
805 * @param bkpinfo The backup information structure. Fields used:
806 * - @c bkpinfo->restore_path
807 * - @c bkpinfo->tmpdir
808 *
809 * @return 0 for success (even if there are differences); nonzero for a tape error.
810 */
811int verify_afioballs_from_stream(struct s_bkpinfo *bkpinfo)
812{
813 /*@ int ********************************************************** */
814 int retval = 0;
815 int res = 0;
816 long current_afioball_number = 0;
817 int ctrl_chr = 0;
818 int total_afioballs = 0;
819
820 /*@ buffers ***************************************************** */
821 char *tmp;
822 char *fname;
823 char *curr_xattr_list_fname;
824 char *curr_acl_list_fname;
825
826 /*@ long long *************************************************** */
827 long long size = 0;
828
829 assert(bkpinfo != NULL);
830 malloc_string(tmp);
831 malloc_string(fname);
832 malloc_string(curr_xattr_list_fname);
833 malloc_string(curr_acl_list_fname);
834
835 if (g_getfattr) {
836 sprintf(curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ,
837 bkpinfo->tmpdir);
838 }
839 if (g_getfacl) {
840 sprintf(curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ,
841 bkpinfo->tmpdir);
842 }
843 log_to_screen("Verifying regular archives on tape");
844 total_afioballs = get_last_filelist_number(bkpinfo) + 1;
845 open_progress_form("Verifying filesystem",
846 "I am verifying archives against your live filesystem now.",
847 "Please wait. This may take a couple of hours.", "",
848 total_afioballs);
849 res = read_header_block_from_stream(&size, fname, &ctrl_chr);
850 if (ctrl_chr != BLK_START_AFIOBALLS) {
851 iamhere("YOU SHOULD NOT GET HERE");
852 iamhere("Grabbing the EXAT files");
853 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
854 res =
855 read_EXAT_files_from_tape(bkpinfo, &size, fname, &ctrl_chr,
856 curr_xattr_list_fname,
857 curr_acl_list_fname);
858 }
859 }
860 if (ctrl_chr != BLK_START_AFIOBALLS) {
861 wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
862 }
863
864 for (res = read_header_block_from_stream(&size, fname, &ctrl_chr);
865 ctrl_chr != BLK_STOP_AFIOBALLS;
866 res = read_header_block_from_stream(&size, fname, &ctrl_chr)) {
867 if (g_getfattr) {
868 sprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ,
869 bkpinfo->tmpdir, current_afioball_number);
870 }
871 if (g_getfacl) {
872 sprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ,
873 bkpinfo->tmpdir, current_afioball_number);
874 }
875 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
876 iamhere("Reading EXAT files from tape");
877 res =
878 read_EXAT_files_from_tape(bkpinfo, &size, fname, &ctrl_chr,
879 curr_xattr_list_fname,
880 curr_acl_list_fname);
881 }
882 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
883 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
884 }
885 sprintf(tmp, "Verifying fileset #%ld", current_afioball_number);
886 /*log_it(tmp); */
887 update_progress_form(tmp);
888 res = verify_an_afioball_from_stream(bkpinfo, fname, size);
889 if (res) {
890 sprintf(tmp, "Afioball %ld differs from live filesystem",
891 current_afioball_number);
892 log_to_screen(tmp);
893 }
894 retval += res;
895 current_afioball_number++;
896 g_current_progress++;
897 res = read_header_block_from_stream(&size, fname, &ctrl_chr);
898 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
899 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
900 }
901 }
902 log_msg(1, "All done with afioballs");
903 close_progress_form();
904 paranoid_free(tmp);
905 paranoid_free(fname);
906 paranoid_free(curr_xattr_list_fname);
907 paranoid_free(curr_acl_list_fname);
908 return (retval);
909}
910
911/**
912 * Verify all biggiefiles on the opened CD/tape stream.
913 * @param bkpinfo The backup information structure. Fields used:
914 * - @c bkpinfo->restore_path
915 * - @c bkpinfo->tmpdir
916 *
917 * @return 0 for success (even if there are differences); nonzero for a tape error.
918 */
919int verify_biggiefiles_from_stream(struct s_bkpinfo *bkpinfo)
920{
921
922 /*@ int ************************************************************ */
923 int retval = 0;
924 int res = 0;
925 int ctrl_chr = 0;
926
927 /*@ long *********************************************************** */
928 long noof_biggiefiles = 0;
929 long current_biggiefile_number = 0;
930
931 /*@ buffers ******************************************************** */
932 char *tmp;
933 char *orig_fname, *logical_fname;
934 char *comment;
935 char *curr_xattr_list_fname;
936 char *curr_acl_list_fname;
937 /*@ pointers ******************************************************* */
938 char *p;
939
940 /*@ long long size ************************************************* */
941 long long size = 0;
942
943 assert(bkpinfo != NULL);
944 malloc_string(tmp);
945 malloc_string(orig_fname);
946 malloc_string(logical_fname);
947 malloc_string(comment);
948 malloc_string(curr_xattr_list_fname);
949 malloc_string(curr_acl_list_fname);
950
951 if (g_getfattr) {
952 sprintf(curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ,
953 bkpinfo->tmpdir);
954 }
955 if (g_getfacl) {
956 sprintf(curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ,
957 bkpinfo->tmpdir);
958 }
959 sprintf(comment, "Verifying all bigfiles.");
960 log_to_screen(comment);
961 sprintf(tmp, "%s/biggielist.txt", bkpinfo->tmpdir);
962// noof_biggiefiles = count_lines_in_file (tmp); // pointless
963 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr);
964 if (ctrl_chr != BLK_START_BIGGIEFILES) {
965 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
966 iamhere("Grabbing the EXAT biggiefiles");
967 res =
968 read_EXAT_files_from_tape(bkpinfo, &size, orig_fname,
969 &ctrl_chr, curr_xattr_list_fname,
970 curr_acl_list_fname);
971 }
972 }
973 if (ctrl_chr != BLK_START_BIGGIEFILES) {
974 wrong_marker(BLK_START_BIGGIEFILES, ctrl_chr);
975 }
976 noof_biggiefiles = (long) size;
977 log_msg(1, "noof_biggiefiles = %ld", noof_biggiefiles);
978 open_progress_form("Verifying big files", comment,
979 "Please wait. This may take some time.", "",
980 noof_biggiefiles);
981 for (res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr);
982 ctrl_chr != BLK_STOP_BIGGIEFILES;
983 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr))
984 {
985 if (ctrl_chr != BLK_START_A_NORMBIGGIE
986 && ctrl_chr != BLK_START_A_PIHBIGGIE) {
987 wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
988 }
989 p = strrchr(orig_fname, '/');
990 if (!p) {
991 p = orig_fname;
992 } else {
993 p++;
994 }
995 sprintf(comment, "Verifying bigfile #%ld (%ld K)",
996 current_biggiefile_number, (long) size >> 10);
997 update_progress_form(comment);
998 sprintf(logical_fname, "%s/%s", bkpinfo->restore_path, orig_fname);
999 res =
1000 verify_a_biggiefile_from_stream(bkpinfo, logical_fname, size);
1001 retval += res;
1002 current_biggiefile_number++;
1003 g_current_progress++;
1004 }
1005 close_progress_form();
1006 paranoid_free(orig_fname);
1007 paranoid_free(logical_fname);
1008 paranoid_free(curr_xattr_list_fname);
1009 paranoid_free(curr_acl_list_fname);
1010 paranoid_free(comment);
1011 paranoid_free(tmp);
1012 return (retval);
1013}
1014
1015/* @} - end of LLverifyGroup */
1016
1017
1018/**
1019 * Verify the CD indicated by @c g_current_media_number.
1020 * @param bkpinfo The backup information structure. Fields used:
1021 * - @c bkpinfo->isodir
1022 * - @c bkpinfo->prefix
1023 * - @c bkpinfo->manual_cd_tray
1024 * - @c bkpinfo->media_device
1025 * - @c bkpinfo->nfs_remote_dir
1026 * - @c bkpinfo->tmpdir
1027 * - @c bkpinfo->verify_data
1028 *
1029 * @return 0 for success (even if differences are found), nonzero for failure.
1030 * @ingroup verifyGroup
1031 */
1032int verify_cd_image(struct s_bkpinfo *bkpinfo)
1033{
1034
1035 /*@ int ************************************************************ */
1036 int retval = 0;
1037
1038 /*@ buffers ******************************************************** */
1039 char *mountpoint;
1040 char *command;
1041 char *tmp;
1042 char *fname;
1043#ifdef __FreeBSD__
1044 char mdd[32];
1045 char *mddevice = mdd;
1046 int ret = 0;
1047 int vndev = 2;
1048#else
1049//skip
1050#endif
1051
1052 command = malloc(2000);
1053 malloc_string(mountpoint);
1054 malloc_string(tmp);
1055 malloc_string(fname);
1056
1057 assert(bkpinfo != NULL);
1058
1059 sprintf(mountpoint, "%s/cdrom", bkpinfo->tmpdir);
1060 sprintf(fname, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->nfs_remote_dir,
1061 bkpinfo->prefix, g_current_media_number);
1062
1063 mkdir(mountpoint, 1777);
1064 sync();
1065 if (!does_file_exist(fname)) {
1066 sprintf(tmp,
1067 "%s not found; assuming you backed up to CD; verifying CD...",
1068 fname);
1069 log_msg(2, tmp);
1070 if (bkpinfo->manual_cd_tray) {
1071 popup_and_OK("Please push CD tray closed.");
1072 }
1073 if (find_and_mount_actual_cd(bkpinfo, mountpoint)) {
1074 log_to_screen("failed to mount actual CD");
1075 return (1);
1076 }
1077 } else {
1078 sprintf(tmp, "%s found; verifying ISO...", fname);
1079#ifdef __FreeBSD__
1080 ret = 0;
1081 vndev = 2;
1082 mddevice = make_vn(fname);
1083 if (ret) {
1084 sprintf(tmp, "make_vn of %s failed; unable to verify ISO\n",
1085 fname);
1086 log_to_screen(tmp);
1087 return (1);
1088 }
1089 sprintf(command, "mount_cd9660 %s %s", mddevice, mountpoint);
1090#else
1091 sprintf(command, "mount -o loop,ro -t iso9660 %s %s", fname,
1092 mountpoint);
1093#endif
1094 if (run_program_and_log_output(command, FALSE)) {
1095 sprintf(tmp, "%s failed; unable to mount ISO image\n",
1096 command);
1097 log_to_screen(tmp);
1098 return (1);
1099 }
1100 }
1101 log_msg(2, "OK, I've mounted the ISO/CD\n");
1102 sprintf(tmp, "%s/archives/NOT-THE-LAST", mountpoint);
1103 if (!does_file_exist(tmp)) {
1104 log_msg
1105 (2,
1106 "This is the last CD. I am therefore setting bkpinfo->verify_data to FALSE.");
1107 bkpinfo->verify_data = FALSE;
1108/*
1109 (a) It's an easy way to tell the calling subroutine that we've finished &
1110 there are no more CD's to be verified; (b) It stops the post-backup verifier
1111 from running after the per-CD verifier has run too.
1112*/
1113 }
1114 verify_afioballs_on_CD(bkpinfo, mountpoint);
1115 iamhere("before verify_all_slices");
1116 verify_all_slices_on_CD(bkpinfo, mountpoint);
1117
1118#ifdef __FreeBSD__
1119 ret = 0;
1120 sprintf(command, "umount %s", mountpoint);
1121 ret += system(command);
1122 ret += kick_vn(mddevice);
1123 if (ret)
1124#else
1125 sprintf(command, "umount %s", mountpoint);
1126 if (system(command))
1127#endif
1128 {
1129 sprintf(tmp, "%s failed; unable to unmount ISO image\n", command);
1130 log_to_screen(tmp);
1131 retval++;
1132 } else {
1133 log_msg(2, "OK, I've unmounted the ISO file\n");
1134 }
1135 if (!does_file_exist(fname)) {
1136 sprintf(command, "umount %s", bkpinfo->media_device);
1137 run_program_and_log_output(command, 2);
1138 if (!bkpinfo->please_dont_eject
1139 && eject_device(bkpinfo->media_device)) {
1140 log_msg(2, "Failed to eject CD-ROM drive");
1141 }
1142 }
1143 paranoid_free(command);
1144 paranoid_free(mountpoint);
1145 paranoid_free(tmp);
1146 paranoid_free(fname);
1147 return (retval);
1148}
1149
1150/**
1151 * Verify all backups on tape.
1152 * This should be done after the backup process has already closed the tape.
1153 * @param bkpinfo The backup information structure. Passed to various helper functions.
1154 * @return 0 for success (even if thee were differences), nonzero for failure.
1155 * @ingroup verifyGroup
1156 */
1157int verify_tape_backups(struct s_bkpinfo *bkpinfo)
1158{
1159
1160 /*@ int ************************************************************ */
1161 int retval = 0;
1162
1163 /*@ buffers ******************************************************** */
1164 char tmp[MAX_STR_LEN];
1165 char changed_files_fname[MAX_STR_LEN];
1166
1167 /*@ long *********************************************************** */
1168 long diffs = 0;
1169
1170 assert(bkpinfo != NULL);
1171
1172 log_msg(3, "verify_tape_backups --- starting");
1173 log_to_screen("Verifying backups");
1174 openin_tape(bkpinfo);
1175/* verify archives themselves */
1176 retval += verify_afioballs_from_stream(bkpinfo);
1177 retval += verify_biggiefiles_from_stream(bkpinfo);
1178/* find the final blocks */
1179 paranoid_system("sync");
1180 sleep(2);
1181 closein_tape(bkpinfo);
1182/* close tape; exit */
1183// fclose(g_tape_stream); <-- not needed; is handled by closein_tape()
1184 sprintf(tmp, "rm -f %s/biggies.changed %s/changed.files 2> /dev/null", bkpinfo->tmpdir, bkpinfo->tmpdir);
1185 paranoid_system(tmp);
1186 sprintf(changed_files_fname, "%s/changed.files", bkpinfo->tmpdir);
1187 sprintf(tmp,
1188 "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",
1189 (bkpinfo->use_star) ? "star" : "afio", MONDO_LOGFILE,
1190 changed_files_fname);
1191 log_msg(2, "Running command to derive list of changed files");
1192 log_msg(2, tmp);
1193 if (system(tmp)) {
1194 if (does_file_exist(changed_files_fname)
1195 && length_of_file(changed_files_fname) > 2) {
1196 log_to_screen
1197 ("Warning - unable to check logfile to derive list of changed files");
1198 } else {
1199 log_to_screen
1200 ("No differences found. Therefore, no 'changed.files' text file.");
1201 }
1202 }
1203 sprintf(tmp, "cat %s/biggies.changed >> %s", bkpinfo->tmpdir, changed_files_fname);
1204 paranoid_system(tmp);
1205
1206 diffs = count_lines_in_file(changed_files_fname);
1207 if (diffs > 0) {
1208 sprintf(tmp, "cp -f %s %s/changed.files", changed_files_fname,
1209 MINDI_CACHE);
1210 run_program_and_log_output(tmp, FALSE);
1211 sprintf(tmp,
1212 "%ld files differed from live filesystem; type less %s or less %s/changed.files to see",
1213 diffs, changed_files_fname, MINDI_CACHE);
1214 log_msg(0, tmp);
1215 log_to_screen("See "MINDI_CACHE"/changed.files for a list of nonmatching files.");
1216 log_to_screen("The files probably changed on filesystem, not on backup media.");
1217 // retval++;
1218 }
1219 return (retval);
1220}
1221
1222
1223
1224/**
1225 * Generate the filename of a tarball to verify.
1226 * @param bkpinfo The backup information structure. @c bkpinfo->zip_suffix is the only field used.
1227 * @param mountpoint The directory where the CD/DVD/ISO is mounted.
1228 * @param setno The afioball number to get the location of.
1229 * @return The absolute path to the afioball.
1230 * @note The returned string points to static data that will be overwritten with each call.
1231 * @ingroup stringGroup
1232 */
1233char *vfy_tball_fname(struct s_bkpinfo *bkpinfo, char *mountpoint,
1234 int setno)
1235{
1236 /*@ buffers ******************************************************* */
1237 static char output[MAX_STR_LEN];
1238
1239 assert(bkpinfo != NULL);
1240 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1241 sprintf(output, "%s/archives/%d.star.%s", mountpoint, setno,
1242 bkpinfo->zip_suffix);
1243 if (!does_file_exist(output)) {
1244 sprintf(output, "%s/archives/%d.afio.%s", mountpoint, setno,
1245 bkpinfo->zip_suffix);
1246 }
1247 return (output);
1248}
Note: See TracBrowser for help on using the repository browser.