source: MondoRescue/branches/2.05/mondo/mondo/common/libmondo-verify.c@ 128

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

indent on all the C code

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