source: branches/stable/mondo/src/common/libmondo-verify.c @ 1663

Last change on this file since 1663 was 1663, checked in by bruno, 12 years ago
  • Fix bug #197 (based on an initial patch of Scott Cummings)
  • Fix a bug where df was using locale to print messages and wasn't filtered correctly
  • mkdtemp checked in configure
  • reset_bkpinfo called as early as possible by both main program.
  • It creates a tmpdir cleanly with mkdtemp in setup_tmpdir subfunction, which takes in account TMPIR and TMP env var. Remains to see what tmpfs does and tests
  • configure.in should also be filtered.
  • Remove g_bkpinfo_DONTUSETHIS
  • remove bkpinfo also from header files
  • Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
  • 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.
  • /tmp => /var/log for mondorestore.log in mindi
  • Update linux terminfo to fix a color issue (Andree Leidenfrost)
  • Removes useless log file (Andree Leidenfrost)
  • replace vi with find_my_editor during restore (Andree Leidenfrost)
  • sync in bg in mindi (VMWare issue to look at)
  • mindi/mindi-busybox have a different version than mondo for pb
  • PB-SUF also added to spec file
  • Fix a bug for pb build (omission of PB-SUF declaration)

(merge -r1631:1662 $SVN_M/branches/2.2.5)

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