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

Last change on this file since 30 was 30, checked in by bcornec, 14 years ago

Id property added on files to allow for better conf. management

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