source: trunk/mondo/mondo/common/libmondo-verify.c @ 507

Last change on this file since 507 was 507, checked in by bcornec, 13 years ago

merge -r489:506 $SVN_M/branches/stable

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