source: branches/2.04_berlios/mondo/mondo/common/libmondo-archive.c @ 99

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

Apply patch from Andree Leidenfrost <aleidenf_AT_bigpond.net.au>
(-r72:75 of trunk) for :
+ correcting NFS handling in interactive mode
+ growisofs and sudo pb

  • Property svn:keywords set to Id
File size: 118.7 KB
Line 
1/* libmondo-archive.c
2   $Id: libmondo-archive.c 99 2005-11-04 23:51:05Z bcornec $
3
4subroutines to handle the archiving of files
5
6
7
807/14
9- moved all ACL, xattr stuff here from libmondo-filelist.c
10
1107/12
12- when trying to find boot loader, look for /boot's /dev, not just /'s dev
13
1407/10
15- better detection of changed files
16- added ACL, xattr support for afio
17
1806/17
19- backup with partimagehack if NTFS device; dd, if non-NTFS device
20
2106/14
22- use mondorescue.iso instead of mindi.iso
23
2404/28
25- cleaned up if/then architecture-specific stuff re: CD-R(W)s
26
2704/03
28- added star support
29
3003/12
31- modified offer_to_write_floppies() to support dual-disk boot/root thing
32
3301/20/2004
34- reformat dvd twice if necessary
35
3612/01/2003
37- added pause_for_N_seconds(5, "Letting DVD drive settle");
38
3911/23
40- added #define DVDRWFORMAT
41
4211/20
43- use --no-emul-boot -b isolinux.bin instead of -b mindi-boot.2880.img
44
4510/23
46- wipe DVD at start, whether or not disk is DVD-RW; this is
47  just a test, to see why dvd+rw-format followed by growiosfs
48  locks up the drive
49- use the singlethreaded make_afioballs_and_images_OLD()
50  instead of the multithreaded make_afioballs_and_images()
51  if backing up to tape
52
5310/21
54- if backing up to dvd, look for relevant tools;
55  abort if missing
56
5710/15
58- UI tweaks
59
6010/10
61- eject/inject DVD after wiping it
62
6309/27
64- pause_and_ask_for_cdr() will now blank DVD if necessary
65
6609/26
67- proper reporting of media type in displayed strings
68  (i.e. DVD if DVD, CD if CD, etc.)
69 
7009/25
71- add DVD support
72
7309/23
74- malloc/free global strings in new subroutines - malloc_libmondo_global_strings()
75  and free_libmondo_global_strings() - which are in libmondo-tools.c
76
7709/15
78- changed a bunch of char[MAX_STR_LEN]'s to char*; malloc; free;
79
8009/14
81- cosmetic bug re: call to 'which dvdrecord'
82
8309/09
84- copy `locate isolinux.bin | tail -n1` to CD before calling mkisfso
85  if file is missing (in which case, bug in Mindi.pl!)
86- reduced noof_threads from 3 to 2
87- fixed cosmetic bug in make_slices_and_images()
88
8909/02
90- fixed cosmetic bug in verify_data()
91
9205/01 - 08/31
93- added partimagehack hooks
94- make twice as many archives at once as before
95- fixed syntax error re: system(xxx,FALSE)
96- unmount CD-ROM before burning (necessary for RH8/9)
97- only ask for new media if sensible
98- fixed mondoarchive -Vi multi-CD verify bug (Tom Mortell)
99- use single-threaded make_afioballs_and_images() if FreeBSD
100- fixed bug on line 476 (Joshua Oreman)
101- re-enabled the pause, for people w/ weird CD-ROM drives
102- added Joshua Oreman's FreeBSD patches
103- don't listen to please_dont_eject_when_restoring
104  ...after all, we're not restoring :)
105
10604/01 - 04/30
107- cleaned up archive_this_fileset()
108- decreased ARCH_THREADS from 3 to 2
109- pause_and_ask_for_cd() --- calls retract_CD_tray_and_defeat_autorun()
110- call assert() and log_OS_error() in various places
111- cleaned up code a bit
112- increased ARCH_THREADS from 2 to 3
113- misc clean-up (Tom Mortell)
114
11503/15/2003
116- fixed problem w/ multi-ISO verify cycle (Tom Mortell)
117
11811/01 - 12/31/2002
119- removed references to make_afioballs_and_images_OLD()
120- added some error-checking to make_afioballs_in_background
121- make_iso_and_go_on() now copies Mondo's autorun file to CD
122- set scratchdir dir to 1744 when burning CD
123- cleaned up code a bit
124- in call_mindi_...(), gracefully handle the user's input
125  if they specify the boot loader but not the boot device
126- offer to abort if GRUB is boot loader and /dev/md* is
127  the boot device (bug in grub-install)
128- if boot loader is R then write RAW as bootloader.name
129- multithreaded make_afioballs_and_images()
130- fixed slice_up_file_etc() for 0-compression users
131- line 1198: added call to is_this_file_compressed() to stop
132  slice_up_file_etc() from compressing files which are
133  already compressed
134- other hackery related to the above enhancement
135- afio no longer forcibly compresses all files (i.e. I dropped
136  the -U following suggestions from users); let's see if
137  it works :)
138
13910/01 - 10/31
140- mondoarchive (with no parameters) wasn't working
141  if user said yes when asked if BurnProof drive; FIXED
142- if manual CD tray and writing to ISO's then prompt
143  for each & every new CD
144- moved a lot of subroutines here
145  from mondo-archive.c and mondo-floppies.c
146
14709/01 - 09/30
148- if CD not burned OK then don't try to verify
149- change 64k to TAPE_BLOCK_SIZE
150- run_program_and_log_output() now takes boolean operator to specify
151  whether it will log its activities in the event of _success_
152- orig_vfy_flag_val added to write_iso_and_go_on, to restore bkpinfo->verify_data's
153  value if altered by verify_cd_image()
154
15508/01 - 08/31
156- use data structure to store the fname, checksum, mods & perms of each bigfile
157  ... biggiestruct :)
158- bigger tmp[]'s in a few places
159- cleaned up the (user-friendly) counting of biggiefiles a bit
160- if media_size[N]<=0 then catch it & abort, unless it's tape,
161  in which case, allow it
162- cleaned up a lot of log_it() calls
163- fixed NULL filename-related bug in can_we_fit_these_files_on_media()
164- deleted can_we_fit.....() subroutine because it was causing problems
165  --- moved its code into the one subroutine which called it
166- created [08/01/2002]
167*/
168
169/**
170 * @file
171 * Functions to handle backing up data.
172 * This is the main file (at least the longest one) in libmondo.
173 */
174
175#include "../common/my-stuff.h"
176#include "../common/mondostructures.h"
177#include "libmondo-string-EXT.h"
178#include "libmondo-stream-EXT.h"
179#include "libmondo-devices-EXT.h"
180#include "libmondo-tools-EXT.h"
181#include "libmondo-gui-EXT.h"
182#include "libmondo-fork-EXT.h"
183#include "libmondo-files-EXT.h"
184#include "libmondo-filelist-EXT.h"
185#include "libmondo-tools-EXT.h"
186#include "libmondo-verify-EXT.h"
187#include "libmondo-archive.h"
188#include "lib-common-externs.h"
189#include <sys/sem.h>
190#include <sys/types.h>
191#include <sys/ipc.h>
192#include <stdarg.h>
193#define DVDRWFORMAT 1
194
195
196
197/** @def DEFAULT_1722MB_DISK The default 1.722M floppy disk to write images to. */
198/** @def BACKUP_1722MB_DISK  The 1.722M floppy disk to try if the default fails. */
199
200#ifdef __FreeBSD__
201    #define DEFAULT_1722MB_DISK "/dev/fd0.1722"
202    #define BACKUP_1722MB_DISK "/dev/fd0.1722"
203#else
204    #define DEFAULT_1722MB_DISK "/dev/fd0u1722"
205    #define BACKUP_1722MB_DISK "/dev/fd0H1722"
206#ifndef _SEMUN_H
207    #define _SEMUN_H
208
209    /**
210     * The semaphore union, provided only in case the user's system doesn't.
211     */
212    union semun {
213      int val;
214      struct semid_ds *buf;
215      unsigned short int *array;
216      struct seminfo *__buf;
217    };
218#endif
219#endif /* __FreeBSD__ */
220
221/*@unused@*/
222//static char cvsid[] = "$Id: libmondo-archive.c 99 2005-11-04 23:51:05Z bcornec $";
223
224/* *************************** external global vars ******************/
225extern int g_current_media_number;
226extern int g_currentY;
227extern bool g_text_mode;
228extern bool g_exiting;
229extern long g_current_progress;
230extern FILE*g_tape_stream;
231extern long long g_tape_posK;
232extern char *g_mondo_home;
233extern char *g_tmpfs_mountpt;
234extern bool g_cd_recovery;
235extern char *g_serial_string;
236
237/**
238 * @addtogroup globalGroup
239 * @{
240 */
241/**
242 * The current backup media type in use.
243 */
244t_bkptype g_backup_media_type=none;
245
246/**
247 * Incremented by each archival thread when it starts up. After that,
248 * this is the number of threads running.
249 */
250int g_current_thread_no = 0;
251
252/* @} - end of globalGroup */
253
254extern int g_noof_rows;
255
256/* Semaphore-related code */
257
258static int set_semvalue(void);
259static void del_semvalue(void);
260static int semaphore_p(void);
261static int semaphore_v(void);
262
263static int g_sem_id;
264static int g_sem_key;
265
266
267
268
269/**
270 * Initialize the semaphore.
271 * @see del_semvalue
272 * @see semaphore_p
273 * @see semaphore_v
274 * @return 1 for success, 0 for failure.
275 */
276static int set_semvalue(void) // initializes semaphore
277{
278  union semun sem_union;
279  sem_union.val = 1;
280  if (semctl(g_sem_id, 0, SETVAL, sem_union) == -1) { return(0); }
281  return(1);
282}
283
284/**
285 * Frees (deletes) the semaphore. Failure is indicated by a log
286 * message.
287 * @see set_semvalue
288 */
289static void del_semvalue(void) // deletes semaphore
290{
291  union semun sem_union;
292
293  if (semctl(g_sem_id, 0, IPC_RMID, sem_union) == -1)
294    { log_msg (3, "Failed to delete semaphore"); }
295}
296
297/**
298 * Acquire (increment) the semaphore (change status to P).
299 * @return 1 for success, 0 for failure.
300 * @see semaphore_v
301 */
302static int semaphore_p(void) // changes status to 'P' (waiting)
303{
304  struct sembuf sem_b;
305
306  sem_b.sem_num = 0;
307  sem_b.sem_op = -1; // P()
308  sem_b.sem_flg = SEM_UNDO;
309  if (semop(g_sem_id, &sem_b, 1) == -1)
310    { log_msg(3, "semaphore_p failed"); return(0); }
311  return(1);
312}
313
314/**
315 * Free (decrement) the semaphore (change status to V).
316 * @return 1 for success, 0 for failure.
317 */
318static int semaphore_v(void) // changes status to 'V' (free)
319{
320  struct sembuf sem_b;
321
322  sem_b.sem_num = 0;
323  sem_b.sem_op = 1; // V()
324  sem_b.sem_flg = SEM_UNDO;
325  if (semop(g_sem_id, &sem_b, 1) == -1)
326    { log_msg(3, "semaphore_v failed"); return(0); }
327  return(1);
328}
329
330
331//------------------------------------------------------
332
333
334/**
335 * Size in megabytes of the buffer afforded to the executable "buffer".
336 * This figure is used when we calculate how much data we have probably 'lost'
337 * when writing off the end of tape N, so that we can then figure out how much
338 * data we must recreate & write to the start of tape N+1.
339 */
340extern int g_tape_buffer_size_MB;
341
342
343
344
345int
346archive_this_fileset_with_star (struct s_bkpinfo *bkpinfo, char *filelist, char *fname,
347          int setno)
348{
349  int retval = 0;
350  unsigned int res = 0;
351  int tries = 0;
352  char *command;
353  char *zipparams;
354  char *tmp;
355  char *p;
356 
357  malloc_string(command);
358  malloc_string(zipparams);
359  malloc_string(tmp);
360
361  if (!does_file_exist (filelist))
362    {
363      sprintf (tmp, "(archive_this_fileset) - filelist %s does not exist", filelist);
364      log_to_screen (tmp);
365      return (1);
366    }
367
368  sprintf(tmp, "echo hi > %s 2> /dev/null", fname);
369  if (system(tmp))
370    {
371      fatal_error("Unable to write tarball to scratchdir");
372    }
373 
374  sprintf(command, "star H=star list=%s -c " STAR_ACL_SZ " file=%s", filelist, fname);
375  if (bkpinfo->use_lzo) { fatal_error("Can't use lzop"); }
376  if (bkpinfo->compression_level > 0)
377    {
378      strcat(command, " -bz");
379    }
380  sprintf(command+strlen(command), " 2>> %s", MONDO_LOGFILE);
381  log_msg(4, "command = '%s'", command);
382   
383  for(res=99,tries=0; tries<3 && res!=0; tries++)
384    {
385      log_msg(5, "command='%s'", command);
386      res = system (command);
387      strcpy(tmp, last_line_of_file(MONDO_LOGFILE));
388      log_msg(1, "res=%d; tmp='%s'", res, tmp);
389      if (bkpinfo->use_star && (res==254 || res==65024) && strstr(tmp, "star: Processed all possible files") && tries>0)
390    {
391      log_msg(1, "Star returned nonfatal error"); 
392      res=0;
393    }
394      if (res)
395        {
396          log_OS_error (command);
397      p = strstr(command, "-acl ");
398      if (p)
399        {
400          p[0]=p[1]=p[2]=p[3]=' ';
401              log_msg(1,"new command = '%s'", command);
402        }
403      else
404        {
405              log_msg (3, "Attempt #%d failed. Pausing 3 seconds and retrying...", tries+1);
406          sleep(3);
407        }
408        }
409    }
410  retval += res;
411  if (retval) { log_msg (3, "Failed to write set %d", setno); }
412  else if (tries>1) { log_msg( 3,"Succeeded in writing set %d, on try #%d", setno, tries); }
413
414  paranoid_free(command);
415  paranoid_free(zipparams);
416  paranoid_free(tmp);
417  return (retval);
418}
419
420
421/**
422 * Call @c afio to archive the filelist @c filelist to the file @c fname.
423 *
424 * @param bkpinfo The backup information structure. Fields used:
425 * - @c compression_level
426 * - @c scratchdir (only verifies existence)
427 * - @c tmpdir (only verifies existence)
428 * - @c zip_exe
429 * - @c zip_suffix
430 * @param filelist The path to a file containing a list of files to be archived
431 * in this fileset.
432 * @param fname The output file to archive to.
433 * @param setno This fileset number.
434 * @return The number of errors encountered (0 for success).
435 * @ingroup LLarchiveGroup
436 */
437int
438archive_this_fileset (struct s_bkpinfo *bkpinfo, char *filelist, char *fname,
439          int setno)
440{
441
442        /*@ int ****************************************************************/
443  int retval = 0;
444  int res = 0;
445  int i = 0;
446  int tries = 0;
447  static int free_ramdisk_space = 9999;
448
449    /*@ buffers *************************************************************/
450  char *command;
451  char *zipparams;
452  char *tmp;
453
454  assert(bkpinfo!=NULL);
455  assert_string_is_neither_NULL_nor_zerolength(filelist);
456  assert_string_is_neither_NULL_nor_zerolength(fname);
457 
458  if (bkpinfo->compression_level > 0 && bkpinfo->use_star)
459    {
460      return(archive_this_fileset_with_star(bkpinfo, filelist, fname, setno));
461    }
462 
463  malloc_string(command);
464  malloc_string(zipparams);
465  malloc_string(tmp);
466 
467  if (!does_file_exist (filelist))
468    {
469      sprintf (tmp, "(archive_this_fileset) - filelist %s does not exist", filelist);
470      log_to_screen (tmp);
471      return (1);
472    }
473  sprintf(tmp, "echo hi > %s 2> /dev/null", fname);
474  if (system(tmp))
475    {
476      fatal_error("Unable to write tarball to scratchdir");
477    }
478
479 
480  if (bkpinfo->compression_level > 0)
481    {
482      sprintf (tmp, "%s/do-not-compress-these", g_mondo_home);
483      //       -b %ld, TAPE_BLOCK_SIZE
484      sprintf (zipparams, "-Z -P %s -G %d -T 3k", bkpinfo->zip_exe, bkpinfo->compression_level);
485      if (does_file_exist(tmp))
486    { strcat (zipparams, " -E "); strcat (zipparams, tmp); }
487      else
488    { log_msg(3, "%s not found. Cannot exclude zipfiles, etc.", tmp); }
489    }
490  else
491    {
492      zipparams[0] = '\0';
493    }
494
495//  make_hole_for_file(fname);
496
497  if (!does_file_exist(bkpinfo->tmpdir)) { log_OS_error("tmpdir not found"); fatal_error("tmpdir not found"); }
498  if (!does_file_exist(bkpinfo->scratchdir)) { log_OS_error("scratchdir not found"); fatal_error("scratchdir not found"); }
499  sprintf (command, "rm -f %s %s. %s.gz %s.%s", fname, fname, fname, fname,
500       bkpinfo->zip_suffix);
501  paranoid_system (command);
502
503  sprintf (command, "cat %s | afio -o -b %ld -M 16m %s %s 2>> %s", filelist, TAPE_BLOCK_SIZE, zipparams, fname, MONDO_LOGFILE);
504
505  sprintf(tmp, "echo hi > %s 2> /dev/null", fname);
506  if (system(tmp))
507    {
508      fatal_error("Unable to write tarball to scratchdir");
509    }
510
511  for(res=99,tries=0; tries<3 && res!=0; tries++)
512    {
513      log_msg(5, "command='%s'", command);
514      res = system (command);
515      if (res)
516        {
517          log_OS_error (command);
518          log_msg (3, "Attempt #%d failed. Pausing 3 seconds and retrying...", tries+1);
519          sleep(3);
520        }
521    }
522  retval += res;
523  if (retval) { log_msg (3, "Failed to write set %d", setno); }
524  else if (tries>1) { log_msg( 3,"Succeeded in writing set %d, on try #%d", setno, tries); }
525
526  if (g_tmpfs_mountpt[0] != '\0') {
527      i = atoi( call_program_and_get_last_line_of_output ("df -m | grep dev/shm | grep -v none | tr -s ' ' '\t' | cut -f4"));
528      if (i>0)
529      {
530          if (free_ramdisk_space > i)
531          {
532              free_ramdisk_space = i;
533              log_msg (2, "min(free_ramdisk_space) is now %d", free_ramdisk_space);
534              if (free_ramdisk_space < 10)
535              {
536                  fatal_error ("Please increase PPCFG_RAMDISK_SIZE in my-stuff.h to increase size of ramdisk ");
537              }
538          }
539      }
540  }
541  paranoid_free(command);
542  paranoid_free(zipparams);
543  paranoid_free(tmp);
544  return (retval);
545}
546
547
548
549
550
551
552/**
553 * Wrapper function for all the backup commands.
554 * Calls these other functions: @c prepare_filelist(),
555 * @c call_filelist_chopper(), @c copy_mondo_and_mindi_stuff_to_scratchdir(),
556 * @c call_mindi_to_supply_boot_disks(), @c do_that_initial_phase(),
557 * @c make_those_afios_phase(), @c make_those_slices_phase(), and
558 * @c do_that_final_phase(). If anything fails before @c do_that_initial_phase(),
559 * @c fatal_error is called with a suitable message.
560 * @param bkpinfo The backup information structure. Uses most fields.
561 * @return The number of non-fatal errors encountered (0 for success).
562 * @ingroup archiveGroup
563 */
564int backup_data(struct s_bkpinfo *bkpinfo)
565{
566int retval=0, res=0;
567char *tmp;
568
569  assert(bkpinfo!=NULL);
570  set_g_cdrom_and_g_dvd_to_bkpinfo_value(bkpinfo);
571   malloc_string(tmp);
572      if (bkpinfo->backup_media_type == dvd)
573        {
574#ifdef DVDRWFORMAT
575      if (!find_home_of_exe("dvd+rw-format")) { fatal_error("Cannot find dvd+rw-format. Please install it or fix your PATH."); }
576#endif
577      if (!find_home_of_exe("growisofs")) { fatal_error("Cannot find growisofs. Please install it or fix your PATH."); }
578    }
579
580      if ((res=prepare_filelist (bkpinfo))) /* generate scratchdir/filelist.full */
581        { fatal_error ("Failed to generate filelist catalog"); }
582      if (call_filelist_chopper (bkpinfo)) { fatal_error("Failed to run filelist chopper"); }
583
584/*
585      sprintf(tmp, "wc -l %s/archives/filelist.full > %s/archives/filelist.count",bkpinfo->scratchdir, bkpinfo->scratchdir);
586      if (run_program_and_log_output(tmp, 2))
587        { fatal_error("Failed to count filelist.full"); }
588*/
589      sprintf(tmp, "gzip -9 %s/archives/filelist.full", bkpinfo->scratchdir);
590      if (run_program_and_log_output(tmp, 2))
591        { fatal_error("Failed to gzip filelist.full"); }
592      sprintf(tmp, "cp -f %s/archives/*list*.gz %s", bkpinfo->scratchdir, bkpinfo->tmpdir);
593      if (run_program_and_log_output(tmp, 2))
594        { fatal_error("Failed to copy to tmpdir"); }
595
596      copy_mondo_and_mindi_stuff_to_scratchdir (bkpinfo); // payload, too, if it exists
597#if __FreeBSD__ == 5
598      strcpy (bkpinfo->kernel_path, "/boot/kernel/kernel");
599#elif __FreeBSD__ == 4
600      strcpy (bkpinfo->kernel_path, "/kernel");
601#elif linux
602      if (figure_out_kernel_path_interactively_if_necessary(bkpinfo->kernel_path))
603        { fatal_error ("Kernel not found. Please specify manually with the '-k' switch."); }
604#else
605#error "I don't know about this system!"
606#endif
607      if ((res = call_mindi_to_supply_boot_disks (bkpinfo)))
608    { fatal_error ("Failed to generate boot+data disks"); }
609      retval += do_that_initial_phase (bkpinfo); // prepare
610      sprintf(tmp, "rm -f %s/images/*.iso", bkpinfo->scratchdir);
611      run_program_and_log_output(tmp, 1);
612      retval += make_those_afios_phase (bkpinfo); // backup regular files
613      retval += make_those_slices_phase (bkpinfo); // backup BIG files
614      retval += do_that_final_phase (bkpinfo); // clean up
615      log_msg (1, "Creation of archives... complete.");
616      if (bkpinfo->verify_data) { sleep(2); }
617      paranoid_free(tmp);
618      return(retval);
619}
620
621
622
623
624/**
625 * Call Mindi to generate boot and data disks.
626 * @note This binds correctly to the new Perl version of mindi.
627 * @param bkpinfo The backup information structure. Fields used:
628 * - @c backup_media_type
629 * - @c boot_loader
630 * - @c boot_device
631 * - @c compression_level
632 * - @c differential
633 * - @c exclude_paths
634 * - @c image_devs
635 * - @c kernel_path
636 * - @c make_cd_use_lilo
637 * - @c media_device
638 * - @c media_size
639 * - @c nonbootable_backup
640 * - @c scratchdir
641 * - @c tmpdir
642 * - @c use_lzo
643 *
644 * @return The number of errors encountered (0 for success)
645 * @bug The code to automagically determine the boot drive
646 * is messy and system-dependent. In particular, it breaks
647 * for Linux RAID and LVM users.
648 * @ingroup MLarchiveGroup
649 */
650int
651call_mindi_to_supply_boot_disks (struct s_bkpinfo *bkpinfo)
652{
653    /*@ buffer *************************************************************/
654  char *tmp;
655        char *scratchdir;
656    char *command;
657    char *use_lzo_sz;
658        char *use_comp_sz;
659    char *use_star_sz;
660    char *bootldr_str;
661    char *tape_device;
662    char *last_filelist_number;
663    char *broken_bios_sz;
664    char *cd_recovery_sz;
665    char *tape_size_sz;
666    char *devs_to_exclude;
667        char *use_lilo_sz;
668        char *value;
669    char *bootdev;
670
671
672
673    /*@ char ***************************************************************/
674    char ch = '\0';
675   
676    /*@ long     ***********************************************************/
677  long lines_in_filelist = 0;
678
679    /*@ int     **************************************************************/
680  int res   = 0;
681  long estimated_total_noof_slices = 0;
682
683  assert(bkpinfo!=NULL);
684  command = malloc(1200);
685malloc_string ( tmp );
686malloc_string ( scratchdir );
687malloc_string ( use_lzo_sz );
688malloc_string ( use_star_sz );
689malloc_string ( use_comp_sz );
690malloc_string ( bootldr_str );
691malloc_string ( tape_device );
692malloc_string ( last_filelist_number );
693malloc_string ( broken_bios_sz );
694malloc_string ( cd_recovery_sz );
695malloc_string ( tape_size_sz );
696malloc_string ( devs_to_exclude );
697malloc_string ( use_lilo_sz ); /* BCO: shared between LILO/ELILO */
698malloc_string ( value );
699malloc_string ( bootdev );
700
701  strcpy( scratchdir, bkpinfo->scratchdir);
702  sprintf (tmp,
703       "echo \"%s\" | tr -s ' ' '\n' | grep -x \"/dev/.*\" | tr -s '\n' ' ' | awk '{print $0\"\\n\";}'",
704       bkpinfo->exclude_paths);
705  strcpy (devs_to_exclude, call_program_and_get_last_line_of_output (tmp));
706  sprintf (tmp, "devs_to_exclude = '%s'", devs_to_exclude);
707  log_msg (2, tmp);
708  mvaddstr_and_log_it (g_currentY, 0,
709               "Calling MINDI to create boot+data disks");
710  sprintf (tmp, "%s/filelist.full", bkpinfo->tmpdir);
711  if (!does_file_exist(tmp))
712    {
713      sprintf(tmp, "%s/tmpfs/filelist.full", bkpinfo->tmpdir);
714      if (!does_file_exist(tmp))
715        { fatal_error("Cannot find filelist.full, so I cannot count its lines"); }
716    }
717  lines_in_filelist = count_lines_in_file (tmp);
718  sprintf (tmp, "%s/LAST-FILELIST-NUMBER", bkpinfo->tmpdir);
719  strcpy (last_filelist_number, last_line_of_file (tmp));
720  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
721    {
722      sprintf (tape_size_sz, "%ld", bkpinfo->media_size[1]);
723      strcpy (tape_device, bkpinfo->media_device);
724    }
725  else
726    {
727      tape_size_sz[0] = '\0';
728      tape_device[0] = '\0';
729    }
730  if (bkpinfo->use_lzo)
731    {
732      strcpy (use_lzo_sz, "yes");
733    }
734  else
735    {
736      strcpy (use_lzo_sz, "no");
737    }
738  if (bkpinfo->use_star)
739    { strcpy( use_star_sz, "yes"); }
740  else
741    { strcpy( use_star_sz, "no"); }
742   
743  if (bkpinfo->compression_level>0)
744    {
745      strcpy (use_comp_sz, "yes");
746    }
747  else
748    {
749      strcpy (use_comp_sz, "no");
750    }
751
752  strcpy (broken_bios_sz, "yes");   /* assume so */
753  if (g_cd_recovery)
754    {
755      strcpy (cd_recovery_sz, "yes");
756    }
757  else
758    {
759      strcpy (cd_recovery_sz, "no");
760    }
761  if (bkpinfo->make_cd_use_lilo)
762    {
763      strcpy (use_lilo_sz, "yes");
764    }
765  else
766    {
767      strcpy (use_lilo_sz, "no");
768    }
769
770  if (!bkpinfo->nonbootable_backup && (bkpinfo->boot_loader == '\0' || bkpinfo->boot_device[0] == '\0'))
771    {
772
773#ifdef __FreeBSD__
774    strcpy (bootdev, call_program_and_get_last_line_of_output
775        ("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
776    if (!bootdev[0])
777      {
778        strcpy (bootdev, call_program_and_get_last_line_of_output
779        ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
780      }
781#else
782    strcpy (bootdev, call_program_and_get_last_line_of_output
783            ("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
784    if (strstr(bootdev, "/dev/cciss/")) {
785         strcpy (bootdev, call_program_and_get_last_line_of_output
786            ("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | cut -dp -f1"));
787         }
788    if (!bootdev[0])
789      {
790        strcpy (bootdev, call_program_and_get_last_line_of_output
791            ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
792       if (strstr(bootdev, "/dev/cciss/")) {
793            strcpy (bootdev, call_program_and_get_last_line_of_output
794               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | cut -dp -f1"));
795            }
796      }
797#endif
798    if (bootdev[0])
799        ch = which_boot_loader (bootdev);
800    else
801        ch = 'U';
802      if (bkpinfo->boot_loader != '\0')
803        {
804          sprintf (tmp, "User specified boot loader. It is '%c'.",
805               bkpinfo->boot_loader);
806          log_msg (2, tmp);
807        }
808      else
809        {
810          bkpinfo->boot_loader = ch;
811        }
812      if (bkpinfo->boot_device[0] != '\0')
813        {
814          sprintf (tmp, "User specified boot device. It is '%s'.",
815               bkpinfo->boot_device);
816          log_msg (2, tmp);
817        }
818      else
819        {
820          strcpy (bkpinfo->boot_device, bootdev);
821        }
822    }
823
824  if (
825#ifdef __FreeBSD__
826      bkpinfo->boot_loader != 'B' && bkpinfo->boot_loader != 'D' &&
827#endif
828#ifdef __IA64__
829      bkpinfo->boot_loader != 'E' &&
830#endif
831      bkpinfo->boot_loader != 'L' && bkpinfo->boot_loader != 'G' && bkpinfo->boot_loader != 'R' && !bkpinfo->nonbootable_backup)
832    {
833      fatal_error
834    ("Please specify your boot loader and device, e.g. -l GRUB -f /dev/hda. Type 'man mondoarchive' to read the manual.");
835    }
836  if (bkpinfo->boot_loader == 'L')
837    {
838      strcpy (bootldr_str, "LILO");
839      if (!does_file_exist("/etc/lilo.conf"))
840        { fatal_error("The de facto standard location for your boot loader's config file is /etc/lilo.conf but I cannot find it there. What is wrong with your Linux distribution?"); }
841    }
842  else if (bkpinfo->boot_loader == 'G')
843    {
844      strcpy (bootldr_str, "GRUB");
845      if (!does_file_exist("/etc/grub.conf") && does_file_exist("/boot/grub/grub.conf"))
846    {
847      run_program_and_log_output("ln -sf /boot/grub/grub.conf /etc/grub.conf", 5);
848    }
849      /* Detect Debian's grub config file */
850      else if (!does_file_exist("/etc/grub.conf") && does_file_exist("/boot/grub/menu.lst"))
851        {
852          run_program_and_log_output("ln -s /boot/grub/menu.lst /etc/grub.conf", 5);
853        }
854      if (!does_file_exist("/etc/grub.conf"))
855    { fatal_error("The de facto standard location for your boot loader's config file is /etc/grub.conf but I cannot find it there. What is wrong with your Linux distribution? Try 'ln -s /boot/grub/menu.lst /etc/grub.conf'..."); }
856    }
857  else if (bkpinfo->boot_loader == 'E')
858    {
859      strcpy (bootldr_str, "ELILO");
860      /* BCO: fix it for SuSE, Debian, Mandrake, ... */
861      if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/redhat/elilo.conf"))
862    {
863      run_program_and_log_output("ln -sf /boot/efi/efi/redhat/elilo.conf /etc/elilo.conf", 5);
864    }
865      if (!does_file_exist("/etc/elilo.conf"))
866    { fatal_error("The de facto mondo standard location for your boot loader's config file is /etc/elilo.conf but I cannot find it there. What is wrong with your Linux distribution? Try finding it under /boot/efi and do 'ln -s /boot/efi/..../elilo.conf /etc/elilo.conf'"); }
867    }
868  else if (bkpinfo->boot_loader == 'R')
869    {
870      strcpy (bootldr_str, "RAW");
871    }
872#ifdef __FreeBSD__
873  else if (bkpinfo->boot_loader == 'D')
874      {
875      strcpy (bootldr_str, "DD");
876      }
877
878  else if (bkpinfo->boot_loader == 'B')
879      {
880      strcpy (bootldr_str, "BOOT0");
881      }
882#endif
883  else
884    {
885      strcpy (bootldr_str, "unknown");
886    }
887  sprintf (tmp, "Your boot loader is %s and it boots from %s", bootldr_str,
888       bkpinfo->boot_device);
889  log_to_screen (tmp);
890  sprintf (tmp, "%s/BOOTLOADER.DEVICE", bkpinfo->tmpdir);
891  if (write_one_liner_data_file (tmp, bkpinfo->boot_device)) { log_msg(1, "%ld: Unable to write one-liner boot device", __LINE__); }
892  switch(bkpinfo->backup_media_type)
893    {
894      case cdr: strcpy(value, "cdr"); break;
895      case cdrw: strcpy(value, "cdrw"); break;
896      case cdstream: strcpy(value, "cdstream"); break;
897      case tape: strcpy(value, "tape"); break;
898      case udev: strcpy(value, "udev"); break;
899      case iso: strcpy(value, "iso"); break;
900      case nfs: strcpy(value, "nfs"); break;
901      case dvd: strcpy(value, "dvd"); break;
902      default: fatal_error("Unknown backup_media_type");
903    }
904  sprintf (tmp, "%s/BACKUP-MEDIA-TYPE", bkpinfo->tmpdir);
905  if (write_one_liner_data_file (tmp, value)) { res++; log_msg(1, "%ld: Unable to write one-liner backup-media-type", __LINE__); }
906  log_to_screen(bkpinfo->tmpdir);
907  sprintf (tmp, "%s/BOOTLOADER.NAME", bkpinfo->tmpdir);
908  if (write_one_liner_data_file (tmp, bootldr_str)) { res++; log_msg(1, "%ld: Unable to write one-liner bootloader.name", __LINE__); }
909  sprintf (tmp, "%s/DIFFERENTIAL", bkpinfo->tmpdir);
910  if (bkpinfo->differential)
911    {
912      res+=write_one_liner_data_file (tmp, "1");
913    }
914  else
915    {
916      res+=write_one_liner_data_file (tmp, "0");
917    }
918
919  estimated_total_noof_slices =
920    size_of_all_biggiefiles_K (bkpinfo) / bkpinfo->optimal_set_size + 1;
921/* add nfs stuff here? */
922  sprintf (command, "mkdir -p %s/images", bkpinfo->scratchdir);
923  if (system (command)) { res++; log_OS_error("Unable to make images directory"); }
924  sprintf (command, "mkdir -p %s%s", bkpinfo->scratchdir, MNT_FLOPPY);
925  if (system (command)) { res++; log_OS_error("Unable to make mnt floppy directory"); }
926  sprintf (tmp, "BTW, I'm telling Mindi your kernel is '%s'",
927       bkpinfo->kernel_path);
928
929  log_msg(1, "lines_in_filelist = %ld", lines_in_filelist);
930
931  sprintf (command,
932/*     "mindi --custom 2=%s 3=%s/images 4=\"%s\" 5=\"%s\" \
9336=\"%s\" 7=%ld 8=\"%s\" 9=\"%s\" 10=\"%s\" \
93411=\"%s\" 12=%s 13=%ld 14=\"%s\" 15=\"%s\" 16=\"%s\" 17=\"%s\" 18=%ld 19=%d",*/
935       
936       
937    "mindi --custom %s %s/images \"%s\" \"%s\" \
938\"%s\" %ld \"%s\" \"%s\" \"%s\" \
939\"%s\" %s %ld \"%s\" \"%s\" \"%s\" \"%s\" %ld %d",
940
941       bkpinfo->tmpdir,         // parameter #2
942       bkpinfo->scratchdir,     // parameter #3
943       bkpinfo->kernel_path,    // parameter #4
944       tape_device,         // parameter #5
945       tape_size_sz,        // parameter #6
946       lines_in_filelist,       // parameter #7 (INT)
947       use_lzo_sz,          // parameter #8
948       cd_recovery_sz,      // parameter #9
949       bkpinfo->image_devs,     // parameter #10
950       broken_bios_sz,      // parameter #11
951       last_filelist_number,    // parameter #12 (STRING)
952       estimated_total_noof_slices, // parameter #13 (INT)
953       devs_to_exclude,         // parameter #14
954       use_comp_sz,         // parameter #15
955       use_lilo_sz,         // parameter #16
956       use_star_sz,         // parameter #17
957       bkpinfo->internal_tape_block_size, // parameter #18 (LONG)
958       bkpinfo->differential);  // parameter #19 (INT)
959     
960// Watch it! This next line adds a parameter...
961  if (bkpinfo->nonbootable_backup) { strcat(command, " NONBOOTABLE"); }
962  log_msg (2, command);
963
964//  popup_and_OK("Pausing");
965 
966  res = run_program_and_log_to_screen (command, "Generating boot+data disks");
967  if (bkpinfo->nonbootable_backup) { res=0; } // hack
968  if (!res)
969    {
970      log_to_screen ("Boot+data disks were created OK");
971      sprintf (command, "mkdir -p /root/images/mindi/");
972      log_msg (2, command);
973      run_program_and_log_output (command, FALSE);
974      sprintf (command, "cp -f %s/images/mindi.iso /root/images/mindi/mondorescue.iso",
975           bkpinfo->scratchdir);
976      log_msg (2, command);
977      run_program_and_log_output (command, FALSE);
978      if (bkpinfo->nonbootable_backup)
979        {
980          sprintf(command, "cp -f %s/all.tar.gz %s/images", bkpinfo->tmpdir, bkpinfo->scratchdir);
981          if (system(command)) { fatal_error("Unable to create temporary duff tarball"); }
982        }
983      sprintf(command, "cp -f %s/mindi-*oot*.img %s/images", bkpinfo->tmpdir, bkpinfo->scratchdir);
984      sprintf (tmp, "cp -f %s/images/all.tar.gz %s", bkpinfo->scratchdir, bkpinfo->tmpdir);
985      if (system (tmp)) { fatal_error ("Cannot find all.tar.gz in tmpdir"); }
986      if (res) { mvaddstr_and_log_it (g_currentY++, 74, "Errors."); }
987      else {  mvaddstr_and_log_it (g_currentY++, 74, "Done."); }
988    }
989  else
990    {
991      log_to_screen ("Mindi failed to create your boot+data disks.");
992      sprintf (command, "cat %s | grep \"Fatal error\"", "/var/log/mindi.log");
993      strcpy (tmp, call_program_and_get_last_line_of_output (command));
994      if (strlen (tmp) > 1)
995        {
996          log_to_screen (tmp);
997        }
998    }
999  paranoid_free(tmp); paranoid_free(use_lzo_sz); paranoid_free(scratchdir);
1000  paranoid_free(use_comp_sz); paranoid_free(bootldr_str); paranoid_free(tape_device);
1001  paranoid_free(last_filelist_number); paranoid_free(broken_bios_sz); paranoid_free(cd_recovery_sz);
1002  paranoid_free(tape_size_sz); paranoid_free(devs_to_exclude); paranoid_free(use_lilo_sz); paranoid_free(value);
1003  paranoid_free(bootdev); paranoid_free(command); paranoid_free(use_star_sz);
1004  return (res);
1005}
1006
1007
1008
1009/**
1010 * Maximum number of filesets allowed in this function.
1011 */
1012#define MAX_NOOF_SETS_HERE 32767
1013
1014/**
1015 * Offset of the bkpinfo pointer (in bytes) from the
1016 * buffer passed to create_afio_files_in_background.
1017 */
1018#define BKPINFO_LOC_OFFSET (16+MAX_NOOF_SETS_HERE/8+16)
1019
1020/**
1021 * Main function for each @c afio thread.
1022 * @param inbuf A transfer block containing:
1023 * - @c p_last_set_archived: [offset 0] pointer to an @c int
1024 *   containing the last set archived.
1025 * - @c p_archival_threads_running: [offset 4] pointer to an @c int
1026 *   containing the number of archival threads currently running.
1027 * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing
1028 *   the next set that should be archived.
1029 * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a
1030 *   bit array, where each bit corresponds to a filelist (1=needs
1031 *   to be archived, 0=archived).
1032 * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information
1033 *   structure. Fields used:
1034 *   - @c tmpdir
1035 *   - @c zip_suffix
1036 *
1037 * Any of the above may be modified by the caller at any time.
1038 *
1039 * @bug Assumes @c int pointers are 4 bytes.
1040 * @see archive_this_fileset
1041 * @see make_afioballs_and_images
1042 * @return NULL, always.
1043 * @ingroup LLarchiveGroup
1044 */
1045void *create_afio_files_in_background(void*inbuf)
1046{
1047  long int archiving_set_no;
1048  char *archiving_filelist_fname;
1049  char * archiving_afioball_fname;
1050  char *curr_xattr_list_fname;
1051  char *curr_acl_list_fname;
1052   
1053  struct s_bkpinfo*bkpinfo;
1054  char *tmp;
1055  int res=0, retval=0;
1056  int *p_archival_threads_running;
1057  int *p_last_set_archived;
1058  int *p_next_set_to_archive;
1059  char *p_list_of_fileset_flags;
1060  int this_thread_no = g_current_thread_no++;
1061
1062  malloc_string(curr_xattr_list_fname);
1063  malloc_string(curr_acl_list_fname);
1064  malloc_string(archiving_filelist_fname);
1065  malloc_string(archiving_afioball_fname);
1066  malloc_string(tmp);
1067  p_last_set_archived = (int*)inbuf;
1068  p_archival_threads_running = (int*)(inbuf+4);
1069  p_next_set_to_archive = (int*)(inbuf+8);
1070  p_list_of_fileset_flags = (char*)(inbuf+12);
1071  bkpinfo = (struct s_bkpinfo*)(inbuf+BKPINFO_LOC_OFFSET);
1072
1073  sprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);
1074  for (archiving_set_no = 0; does_file_exist (archiving_filelist_fname);
1075       sprintf (archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir,
1076        archiving_set_no))
1077    {
1078      if (g_exiting)
1079    { fatal_error("Execution run aborted (pthread)"); }
1080      if (archiving_set_no >= MAX_NOOF_SETS_HERE)
1081    { fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please."); }
1082      if (!semaphore_p()) { log_msg(3, "P sem failed (pid=%d)", (int)getpid()); fatal_error("Cannot get semaphore P"); }
1083      if (archiving_set_no < *p_next_set_to_archive)
1084    {
1085      archiving_set_no= *p_next_set_to_archive; 
1086    }
1087      *p_next_set_to_archive = *p_next_set_to_archive + 1;
1088      if (!semaphore_v()) { fatal_error("Cannot get semaphore V"); }
1089
1090      /* backup this set of files */
1091      sprintf (archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ,bkpinfo->tmpdir,
1092               archiving_set_no, bkpinfo->zip_suffix);
1093      sprintf (archiving_filelist_fname, FILELIST_FNAME_RAW_SZ,bkpinfo->tmpdir,
1094           archiving_set_no);
1095      if (!does_file_exist(archiving_filelist_fname))
1096    {
1097      log_msg (3, "%s[%d:%d] - well, I would archive %d, except that it doesn't exist. I'll stop now.", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
1098      break;
1099    }
1100
1101      sprintf (tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no-ARCH_BUFFER_NUM, bkpinfo->zip_suffix);
1102      if (does_file_exist(tmp))
1103    {
1104      log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no);
1105      while (does_file_exist(tmp))
1106        {
1107          sleep(1);
1108        }
1109      log_msg(4, "[%d] - continuing", getpid());
1110    }
1111   
1112      log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
1113      sprintf (curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
1114      sprintf (curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
1115      get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname);
1116      get_acl_list(archiving_filelist_fname, curr_acl_list_fname);
1117     
1118      log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
1119      res = archive_this_fileset (bkpinfo, archiving_filelist_fname,
1120                  archiving_afioball_fname,
1121                  archiving_set_no);
1122      retval += res;
1123
1124      if (res)
1125    {
1126      sprintf (tmp,
1127           "Errors occurred while archiving set %ld. Please review logs.",
1128           archiving_set_no);
1129      log_to_screen (tmp);
1130    }
1131      if (!semaphore_p()) { fatal_error("Cannot get semaphore P"); }
1132
1133      set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5);
1134
1135      if (*p_last_set_archived < archiving_set_no)
1136    { *p_last_set_archived = archiving_set_no; } // finished archiving this one
1137
1138      if (!semaphore_v()) { fatal_error("Cannot get semaphore V"); }
1139      log_msg(4, "%s[%d:%d] - archived %d OK", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
1140      archiving_set_no ++;
1141    }
1142  if (!semaphore_p()) { fatal_error("Cannot get semaphore P"); }
1143  (*p_archival_threads_running) --;
1144  if (!semaphore_v()) { fatal_error("Cannot get semaphore V"); }
1145  log_msg(3, "%s[%d:%d] - exiting", FORTY_SPACES, getpid(), this_thread_no);
1146  paranoid_free(archiving_filelist_fname);
1147  paranoid_free(archiving_afioball_fname);
1148  paranoid_free(curr_xattr_list_fname);
1149  paranoid_free(curr_acl_list_fname);
1150  paranoid_free(tmp);
1151  pthread_exit(NULL);
1152}
1153
1154
1155
1156
1157
1158/**
1159 * Finalize the backup.
1160 * For streaming backups, this writes the closing block
1161 * to the stream. For CD-based backups, this creates
1162 * the final ISO image.
1163 * @param bkpinfo The backup information structure, used only
1164 * for the @c backup_media_type.
1165 * @ingroup MLarchiveGroup
1166 */
1167int
1168do_that_final_phase (struct s_bkpinfo *bkpinfo)
1169{
1170
1171    /*@ int ***************************************/
1172  int res = 0;
1173  int retval = 0;
1174
1175    /*@ buffers ***********************************/
1176
1177  assert(bkpinfo!=NULL);
1178  mvaddstr_and_log_it (g_currentY, 0, "Writing any remaining data to media         ");
1179
1180  log_msg (1, "Closing tape/CD ... ");
1181  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
1182    /* write tape/cdstream */
1183    {
1184      closeout_tape(bkpinfo);
1185    }
1186  else
1187    /* write final ISO */
1188    {
1189      res = write_final_iso_if_necessary (bkpinfo);
1190      retval += res;
1191      if (res)
1192    {
1193      log_msg (1, "write_final_iso_if_necessary returned an error");
1194    }
1195    }
1196  log_msg (2, "Fork is exiting ... ");
1197
1198  mvaddstr_and_log_it (g_currentY++, 74, "Done.");
1199
1200  /* final stuff */
1201  if (retval)
1202    {
1203      mvaddstr_and_log_it (g_currentY++, 74, "Errors.");
1204    }
1205  else
1206    {
1207      mvaddstr_and_log_it (g_currentY++, 74, "Done.");
1208    }
1209
1210  return (retval);
1211}
1212
1213
1214/**
1215 * Initialize the backup.
1216 * Does the following:
1217 * - Sets up the serial number.
1218 * - For streaming backups, opens the tape stream and writes the data disks
1219 *   and backup headers.
1220 * - For CD-based backups, wipes the ISOs in the target directory.
1221 *
1222 * @param bkpinfo The backup information structure. Fields used:
1223 * - @c backup_media_type
1224 * - @c cdrw_speed
1225 * - @c prefix
1226 * - @c isodir
1227 * - @c media_device
1228 * - @c scratchdir
1229 * - @c tmpdir
1230 * @return The number of errors encountered (0 for success).
1231 * @ingroup MLarchiveGroup
1232 */
1233int
1234do_that_initial_phase (struct s_bkpinfo *bkpinfo)
1235{
1236    /*@ int ****************************************/
1237  int retval = 0;
1238
1239    /*@ buffers ************************************/
1240  char*command, *tmpfile, *data_disks_file;
1241   
1242  assert(bkpinfo!=NULL);
1243  malloc_string(command);
1244  malloc_string(tmpfile);
1245  malloc_string(data_disks_file);
1246  sprintf (data_disks_file, "%s/all.tar.gz", bkpinfo->tmpdir);
1247
1248  snprintf (g_serial_string, MAX_STR_LEN-1,
1249        call_program_and_get_last_line_of_output("dd \
1250if=/dev/urandom bs=16 count=1 2> /dev/null | \
1251hexdump | tr -s ' ' '0' | head -n1"));
1252  strip_spaces(g_serial_string);
1253  strcat(g_serial_string, "...word.");
1254  log_msg(2, "g_serial_string = '%s'", g_serial_string);
1255  assert(strlen(g_serial_string) < MAX_STR_LEN);
1256
1257  sprintf(tmpfile, "%s/archives/SERIAL-STRING", bkpinfo->scratchdir);
1258  if (write_one_liner_data_file (tmpfile, g_serial_string)) { log_msg(1, "%ld: Failed to write serial string", __LINE__); }
1259
1260  mvaddstr_and_log_it (g_currentY, 0, "Preparing to archive your data");
1261  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
1262    {
1263      if (bkpinfo->backup_media_type == cdstream)
1264        {
1265          openout_cdstream (bkpinfo->media_device, bkpinfo->cdrw_speed);
1266        }
1267      else
1268        {
1269          openout_tape (bkpinfo->media_device, bkpinfo->internal_tape_block_size);  /* sets g_tape_stream */
1270        }
1271      if (!g_tape_stream)
1272    {
1273      fatal_error ("Cannot open backup (streaming) device");
1274    }
1275      log_msg (1, "Backup (stream) opened OK");
1276      write_data_disks_to_stream (data_disks_file);
1277    }
1278  else
1279    {
1280      log_msg (1, "Backing up to CD's");
1281    }
1282
1283  sprintf (command, "rm -f %s/%s/%s-[1-9]*.iso", bkpinfo->isodir,
1284                        bkpinfo->nfs_remote_dir, bkpinfo->prefix);
1285  paranoid_system (command);
1286  wipe_archives (bkpinfo->scratchdir);
1287  mvaddstr_and_log_it (g_currentY++, 74, "Done.");
1288  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
1289    {
1290      write_header_block_to_stream (0, "start-of-tape", BLK_START_OF_TAPE);
1291      write_header_block_to_stream (0, "start-of-backup", BLK_START_OF_BACKUP);
1292    }
1293  paranoid_free(command);
1294  paranoid_free(tmpfile);
1295  paranoid_free(data_disks_file);
1296  return (retval);
1297}
1298
1299
1300/**
1301 * Calls floppy-formatting @c cmd and tracks its progress if possible.
1302 *
1303 * @param cmd The command to run (e.g. @c fdformat @c /dev/fd0).
1304 * @param title The human-friendly description of the floppy you are writing.
1305 * This will be used as the title in the progress bar window. Example:
1306 * "Formatting disk /dev/fd0".
1307 * @see format_disk
1308 * @return The exit code of fdformat/superformat.
1309 */
1310int
1311format_disk_SUB (char *cmd, char *title)
1312{
1313
1314    /*@ int ****************************************************************/
1315  int res = 0;
1316    int percentage = 0;
1317    int maxtracks = 0;
1318    int trackno = 0;
1319    int last_trkno = 0;
1320
1321    /*@ buffers ************************************************************/
1322  char *command;
1323  char *tempfile;
1324
1325    /*@ pointers ***********************************************************/
1326  FILE *pin;
1327
1328  assert_string_is_neither_NULL_nor_zerolength(cmd);
1329  assert_string_is_neither_NULL_nor_zerolength(title);
1330
1331  malloc_string(command);
1332  malloc_string(tempfile);
1333#ifdef __FreeBSD__
1334/* Ugh. FreeBSD fdformat prints out this pretty progress indicator that's
1335   impossible to parse. It looks like
1336   VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVF-------------------
1337   where V means verified, E means error, F means formatted, and - means
1338   not done yet.
1339*/
1340    return (run_program_and_log_to_screen (cmd, title));
1341#endif
1342
1343/* if Debian then do bog-standard superformat; don't be pretty */
1344  if (strstr (cmd, "superformat"))
1345    {
1346      return (run_program_and_log_to_screen (cmd, title));
1347    }
1348/* if not Debian then go ahead & use fdformat */
1349  strcpy (tempfile,
1350      call_program_and_get_last_line_of_output
1351      ("mktemp -q /tmp/mondo.XXXXXXXX"));
1352  sprintf (command, "%s >> %s 2>> %s; rm -f %s", cmd, tempfile, tempfile,
1353       tempfile);
1354  log_msg (3, command);
1355  open_evalcall_form (title);
1356  if (!(pin = popen (command, "r")))
1357    {
1358      log_OS_error ("fmt err");
1359      return (1);
1360    }
1361  if (strstr (command, "1722"))
1362    {
1363      maxtracks = 82;
1364    }
1365  else
1366    {
1367      maxtracks = 80;
1368    }
1369  for (sleep (1); does_file_exist (tempfile); sleep (1))
1370    {
1371      trackno = get_trackno_from_logfile (tempfile);
1372      if (trackno < 0 || trackno > 80)
1373    {
1374      log_msg (1, "Weird track#");
1375      continue;
1376    }
1377      percentage = trackno * 100 / maxtracks;
1378      if (trackno <= 5 && last_trkno > 40)
1379    {
1380      close_evalcall_form ();
1381      strcpy (title, "Verifying format");
1382      open_evalcall_form (title);
1383    }
1384      last_trkno = trackno;
1385      update_evalcall_form (percentage);
1386    }
1387  close_evalcall_form ();
1388  if (pclose (pin)) { res++; log_OS_error("Unable to pclose"); }
1389  unlink (tempfile);
1390  paranoid_free(command);
1391  paranoid_free(tempfile);
1392  return (res);
1393}
1394
1395/**
1396 * Wrapper around @c format_disk_SUB().
1397 * This function calls @c format_disk_SUB() with a @c device of its @c device
1398 * parameter and a @c title of Formatting disk @c device. If the format
1399 * fails, the user will be given the option of retrying.
1400 *
1401 * @param device The floppy drive to write to.
1402 * @see format_disk_SUB
1403 * @return The exit code of fdformat/superformat.
1404 * @ingroup deviceGroup
1405 */
1406int
1407format_disk (char *device)
1408{
1409   
1410    /*@ int ***************************************************************/
1411  int res = 0;
1412
1413    /*@ buffer ************************************************************/
1414  char *command;
1415  char *title;
1416 
1417
1418  assert_string_is_neither_NULL_nor_zerolength(device);
1419  malloc_string(title);
1420  command = malloc(1000);
1421  if (!system ("which superformat > /dev/null 2> /dev/null"))
1422    {
1423      sprintf (command, "superformat %s", device);
1424    }
1425  else
1426    {
1427#ifdef __FreeBSD__
1428      sprintf (command, "fdformat -y %s", device);
1429#else
1430      sprintf (command, "fdformat %s", device);
1431#endif
1432    }
1433  sprintf (title, "Formatting disk %s", device);
1434  while ((res = format_disk_SUB (command, title)))
1435    {
1436      if (!ask_me_yes_or_no ("Failed to format disk. Retry?"))
1437    {
1438      return (res);
1439    }
1440    }
1441  paranoid_free(title);
1442  paranoid_free(command);
1443  return (res);
1444}
1445
1446/**
1447 * Get the <tt>N</tt>th bit of @c array.
1448 * @param array The bit-array (as a @c char pointer).
1449 * @param N The number of the bit you want.
1450 * @return TRUE (bit is set) or FALSE (bit is not set).
1451 * @see set_bit_N_of_array
1452 * @ingroup utilityGroup
1453 */
1454bool get_bit_N_of_array(char*array, int N)
1455{
1456  int element_number;
1457  int bit_number;
1458  int mask;
1459 
1460  element_number = N / 8;
1461  bit_number = N % 8;
1462  mask = 1 << bit_number;
1463  if (array[element_number] & mask)
1464    { return(TRUE); }
1465  else
1466    { return(FALSE); }
1467}
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477/**
1478 * @addtogroup LLarchiveGroup
1479 * @{
1480 */
1481/**
1482 * Start up threads to archive your files.
1483 *
1484 * This function starts @c ARCH_THREADS threads,
1485 * each starting execution in @c create_afio_files_in_background().
1486 * Each thread will archive individual filesets, based on the
1487 * pointers passed to it and continually updated, until all files
1488 * have been backed up. This function coordinates the threads
1489 * and copies their output to the @c scratchdir.
1490 *
1491 * @param bkpinfo The backup information structure. Fields used:
1492 * - @c backup_media_type
1493 * - @c scratchdir
1494 * - @c tmpdir
1495 * - @c zip_suffix
1496 *
1497 * @return The number of errors encountered (0 for success)
1498 */
1499int
1500make_afioballs_and_images (struct s_bkpinfo *bkpinfo)
1501{
1502
1503    /*@ int ***************************************************/
1504  int retval = 0;
1505  long int storing_set_no = 0;
1506  int res = 0;
1507  bool done_storing=FALSE;
1508  char *result_str;
1509  char *transfer_block;
1510  void*vp;
1511  void**pvp;
1512
1513    /*@ buffers ***********************************************/
1514  char *storing_filelist_fname;
1515  char *storing_afioball_fname;
1516  char *tmp;
1517  char *media_usage_comment;
1518  pthread_t archival_thread[ARCH_THREADS];
1519  char *p_list_of_fileset_flags;
1520  int *p_archival_threads_running;
1521  int *p_last_set_archived;
1522  int *p_next_set_to_archive;
1523  int noof_threads;
1524  int i;
1525  char *curr_xattr_list_fname;
1526  char *curr_acl_list_fname;
1527  int misc_counter_that_is_not_important=0; 
1528 
1529  log_msg(8, "here");
1530  assert(bkpinfo!=NULL);
1531  tmp = malloc(MAX_STR_LEN*2);
1532  malloc_string(result_str);
1533  malloc_string(curr_xattr_list_fname);
1534  malloc_string(curr_acl_list_fname);
1535  malloc_string(storing_filelist_fname);
1536  malloc_string(media_usage_comment);
1537  malloc_string(storing_afioball_fname);
1538  transfer_block = malloc(sizeof(struct s_bkpinfo)+BKPINFO_LOC_OFFSET+64);
1539  memset((void*)transfer_block, 0, sizeof(struct s_bkpinfo)+BKPINFO_LOC_OFFSET+64);
1540  p_last_set_archived = (int*)transfer_block;
1541  p_archival_threads_running = (int*)(transfer_block+4);
1542  p_next_set_to_archive = (int*)(transfer_block+8);
1543  p_list_of_fileset_flags = (char*)(transfer_block+12);
1544  memcpy((void*)(transfer_block+BKPINFO_LOC_OFFSET), (void*)bkpinfo, sizeof(struct s_bkpinfo));
1545  pvp=&vp;
1546  vp=(void*)result_str;
1547  *p_archival_threads_running = 0;
1548  *p_last_set_archived = -1;
1549  *p_next_set_to_archive = 0;
1550  sprintf (tmp, "%s/archives/filelist.full", bkpinfo->scratchdir);
1551  log_to_screen ("Archiving regular files");
1552  log_msg (5, "Go, Shorty. It's your birthday.");
1553  open_progress_form ("Backing up filesystem",
1554              "I am backing up your live filesystem now.",
1555              "Please wait. This may take a couple of hours.",
1556              "Working...", get_last_filelist_number (bkpinfo) + 1);
1557
1558  log_msg (5, "We're gonna party like it's your birthday.");
1559
1560  srand((unsigned int)getpid());
1561  g_sem_key = 1234+random()%30000;
1562  if ((g_sem_id = semget((key_t)g_sem_key, 1, IPC_CREAT|S_IREAD|S_IWRITE))==-1)
1563    { fatal_error("MABAI - unable to semget"); }
1564  if (!set_semvalue())
1565    { fatal_error("Unable to init semaphore"); } // initialize semaphore
1566  for(noof_threads=0; noof_threads<ARCH_THREADS; noof_threads++)
1567    {
1568      log_msg(8, "Creating thread #%d", noof_threads);
1569      (*p_archival_threads_running) ++;
1570      if ((res = pthread_create(&archival_thread[noof_threads], NULL, create_afio_files_in_background, (void*)transfer_block)))
1571    { fatal_error("Unable to create an archival thread"); }
1572    }
1573
1574  log_msg(8, "About to enter while() loop");
1575  while(!done_storing)
1576    {
1577      if (g_exiting) { fatal_error("Execution run aborted (main loop)"); }
1578      if (*p_archival_threads_running == 0 && *p_last_set_archived == storing_set_no-1)
1579    {
1580      log_msg(2, "No archival threads are running. The last stored set was %d and I'm looking for %d. Take off your make-up; the party's over... :-)", *p_last_set_archived, storing_set_no);
1581      done_storing = TRUE;
1582    }
1583      else if (!get_bit_N_of_array(p_list_of_fileset_flags, storing_set_no))
1584    {
1585      misc_counter_that_is_not_important = (misc_counter_that_is_not_important+1) % 5;
1586      if (!misc_counter_that_is_not_important)
1587        { update_progress_form (media_usage_comment); }
1588      sleep(1);
1589    }
1590      else
1591    // store set N
1592    {
1593      sprintf (storing_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir,
1594           storing_set_no);
1595      sprintf (storing_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir,
1596           storing_set_no, bkpinfo->zip_suffix);
1597          sprintf (curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, storing_set_no);
1598          sprintf (curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, storing_set_no);
1599
1600      log_msg (2, "Storing set %d", storing_set_no);
1601      while(!does_file_exist(storing_filelist_fname) || !does_file_exist(storing_afioball_fname))
1602        {
1603          log_msg (2, "Warning - either %s or %s doesn't exist yet. I'll pause 5 secs.", storing_filelist_fname, storing_afioball_fname);
1604          sleep(5);
1605        }
1606      strcpy (media_usage_comment, percent_media_full_comment (bkpinfo));
1607      /* copy to CD (scratchdir) ... and an actual CD-R if necessary */
1608      if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
1609        {
1610              register_in_tape_catalog(fileset, storing_set_no, -1, storing_afioball_fname);
1611          maintain_collection_of_recent_archives(bkpinfo->tmpdir, storing_afioball_fname);
1612          iamhere("Writing EXAT files");
1613              res += write_EXAT_files_to_tape(bkpinfo, curr_xattr_list_fname, curr_acl_list_fname);
1614// archives themselves
1615          res += move_files_to_stream (bkpinfo, storing_afioball_fname, NULL);
1616        }
1617      else
1618        {
1619          res = move_files_to_cd (bkpinfo, storing_filelist_fname, curr_xattr_list_fname, curr_acl_list_fname, storing_afioball_fname, NULL);
1620        }
1621      retval += res;
1622      g_current_progress++;
1623      update_progress_form (media_usage_comment);
1624      if (res)
1625        {
1626          sprintf (tmp, "Failed to add archive %ld's files to CD dir\n",
1627               storing_set_no);
1628          log_to_screen (tmp);
1629          fatal_error
1630        ("Is your hard disk full? If not, please send the author the logfile.");
1631        }
1632      storing_set_no++;
1633      //      sleep(2);
1634    }
1635    }
1636  close_progress_form ();
1637
1638  sprintf (tmp, "Your regular files have been archived ");
1639  log_msg(2, "Joining background threads to foreground thread");
1640  for(i=0; i<noof_threads; i++)
1641    {
1642      pthread_join(archival_thread[i], pvp);
1643      log_msg(3, "Thread %d of %d: closed OK", i+1, noof_threads);
1644    }
1645  del_semvalue();
1646  log_msg (2, "Done.");
1647  if (retval)
1648    {
1649      strcat (tmp, "(with errors).");
1650    }
1651  else
1652    {
1653      strcat (tmp, "successfully.");
1654    }
1655  log_to_screen (tmp);
1656  paranoid_free(transfer_block);
1657  paranoid_free(result_str);
1658  paranoid_free(storing_filelist_fname);
1659  paranoid_free(media_usage_comment);
1660  paranoid_free(storing_afioball_fname);
1661  paranoid_free(curr_xattr_list_fname);
1662  paranoid_free(curr_acl_list_fname);
1663  return (retval);
1664}
1665
1666
1667void pause_for_N_seconds(int how_long, char*msg)
1668{
1669  int i;
1670  open_evalcall_form(msg);
1671  for(i=0; i<how_long; i++)
1672    {
1673      update_evalcall_form((int) ( (100.0/(float)(how_long)*i) ) );
1674      sleep(1);
1675    }
1676  close_evalcall_form();
1677}
1678
1679
1680
1681
1682/**
1683 * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir.
1684 *
1685 * @param bkpinfo The backup information structure. Fields used:
1686 * - @c backup_media_type
1687 * - @c call_after_iso
1688 * - @c call_before_iso
1689 * - @c call_burn_iso
1690 * - @c call_make_iso
1691 * - @c make_cd_use_lilo
1692 * - @c manual_cd_tray
1693 * - @c nonbootable_backup
1694 * - @c scratchdir
1695 *
1696 * @param destfile Where to put the generated ISO image.
1697 * @return The number of errors encountered (0 for success)
1698 */
1699int
1700make_iso_fs (struct s_bkpinfo *bkpinfo, char *destfile)
1701{
1702    /*@ int ***********************************************/
1703  int retval = 0;
1704  int res;
1705
1706    /*@ buffers *******************************************/
1707  char *tmp;
1708  char *old_pwd;
1709  char *result_sz;
1710  char *message_to_screen;
1711  char *sz_blank_disk;
1712  char *fnam;
1713  char *tmp2;
1714  char *tmp3;
1715  bool cd_is_mountable;
1716
1717  malloc_string(old_pwd);
1718  malloc_string(result_sz);
1719  malloc_string(message_to_screen);
1720  malloc_string(sz_blank_disk);
1721  malloc_string(fnam);
1722  tmp = malloc(1200);
1723  tmp2 =malloc(1200);
1724  tmp3 =malloc(1200);
1725  assert(bkpinfo!=NULL);
1726  assert_string_is_neither_NULL_nor_zerolength(destfile);
1727
1728  sprintf(tmp, "%s/isolinux.bin", bkpinfo->scratchdir);
1729  sprintf(tmp2,"%s/isolinux.bin", bkpinfo->tmpdir);
1730  if (does_file_exist(tmp))
1731    {
1732      sprintf(tmp3, "cp -f %s %s", tmp, tmp2);
1733      paranoid_system(tmp3);
1734    }
1735  if (!does_file_exist(tmp) && does_file_exist(tmp2))
1736    {
1737      sprintf(tmp3, "cp -f %s %s", tmp2, tmp);
1738      paranoid_system(tmp3);
1739    }
1740  /*
1741  if (!does_file_exist(tmp))
1742    {
1743      log_msg (2, "Silly bug in Mindi.pl; workaround in progress...");
1744      strcpy(fnam, call_program_and_get_last_line_of_output("locate isolinux.bin | tail -n1"));
1745      if (strlen(fnam)>0 && does_file_exist(fnam))
1746        {
1747          sprintf(tmp, "cp -f %s %s", fnam, bkpinfo->scratchdir);
1748          res = run_program_and_log_output(tmp, FALSE);
1749        }
1750      else
1751        {
1752      res = 1;
1753    }
1754      if (res)
1755    {
1756      log_msg (2, "Could not work around silly bug in Mindi.pl - sorry! Isolinux.bin missing");
1757    }
1758    }
1759  */
1760  free(tmp2);
1761  free(tmp3);
1762  tmp2 = NULL;
1763  tmp3 = NULL;
1764  if (bkpinfo->backup_media_type == iso && bkpinfo->manual_cd_tray)
1765    {
1766      popup_and_OK("Please insert new media and press Enter.");
1767    }
1768
1769  log_msg (2, "make_iso_fs --- scratchdir=%s --- destfile=%s",
1770       bkpinfo->scratchdir, destfile);
1771  (void) getcwd (old_pwd, MAX_STR_LEN - 1);
1772  sprintf (tmp, "chmod 744 %s", bkpinfo->scratchdir);
1773  run_program_and_log_output(tmp, FALSE);
1774  chdir (bkpinfo->scratchdir);
1775
1776  if (bkpinfo->call_before_iso[0] != '\0')
1777    {
1778      sprintf (message_to_screen, "Running pre-ISO call for CD#%d",
1779           g_current_media_number);
1780      res =
1781    eval_call_to_make_ISO (bkpinfo, bkpinfo->call_before_iso, destfile,
1782           g_current_media_number, MONDO_LOGFILE, message_to_screen);
1783      if (res)
1784    {
1785      strcat (message_to_screen, "...failed");
1786    }
1787      else
1788    {
1789      strcat (message_to_screen, "...OK");
1790    }
1791      log_to_screen (message_to_screen);
1792      retval += res;
1793    }
1794
1795  if (bkpinfo->call_make_iso[0] != '\0')
1796    {
1797      log_msg(2, "bkpinfo->call_make_iso = %s", bkpinfo->call_make_iso);
1798      sprintf (tmp, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);
1799      sprintf (message_to_screen, "Making an ISO (%s #%d)",
1800               media_descriptor_string(bkpinfo->backup_media_type),
1801           g_current_media_number);
1802
1803      pause_and_ask_for_cdr (2, &cd_is_mountable);  /* if g_current_media_number >= 2 then pause & ask */
1804      if (retval)
1805         {
1806       log_to_screen("Serious error(s) occurred already. I shan't try to write to media.");
1807         }
1808      else
1809         {
1810       res =
1811        eval_call_to_make_ISO (bkpinfo, bkpinfo->call_make_iso, bkpinfo->scratchdir,
1812           g_current_media_number, MONDO_LOGFILE, message_to_screen);
1813          if (res)
1814            {
1815              log_to_screen ("%s...failed to write", message_to_screen);
1816           }
1817          else
1818            {
1819              log_to_screen ("%s...OK", message_to_screen);
1820          if (!run_program_and_log_output("tail -n10 /var/log/mondo-archive.log | fgrep \":-(\"", 1))
1821            {
1822          log_to_screen("Despite nonfatal errors, growisofs confirms the write was successful.");
1823        }
1824            }
1825          retval += res;
1826#ifdef DVDRWFORMAT
1827          sprintf(tmp, "cat %s | tail -n8 | grep \"blank=full.*dvd-compat.*DAO\"", MONDO_LOGFILE);
1828      if (g_backup_media_type == dvd && (res || !run_program_and_log_output(tmp, 1)))
1829            {
1830          log_to_screen("Failed to write to disk. I shall blank it and then try again.");
1831          sleep(5);
1832          system("sync");
1833              pause_for_N_seconds(5, "Letting DVD drive settle");
1834
1835// dvd+rw-format --- OPTION 2
1836          if (!bkpinfo->please_dont_eject)
1837        {
1838          log_to_screen("Ejecting media to clear drive status.");
1839          eject_device(bkpinfo->media_device);
1840          inject_device(bkpinfo->media_device);
1841        }
1842              pause_for_N_seconds(5, "Letting DVD drive settle");
1843          sprintf(sz_blank_disk, "dvd+rw-format %s", bkpinfo->media_device);
1844          log_msg(3, "sz_blank_disk = '%s'", sz_blank_disk);
1845              res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
1846          if (res)
1847            {
1848          log_to_screen("Warning - format failed. (Was it a DVD-R?) Sleeping for 5 seconds to take a breath...");
1849                  pause_for_N_seconds(5, "Letting DVD drive settle... and trying again.");
1850                  res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
1851                  if (res) { log_to_screen("Format failed a second time."); }
1852        }
1853          else { log_to_screen("Format succeeded. Sleeping for 5 seconds to take a breath..."); }
1854              pause_for_N_seconds(5, "Letting DVD drive settle");
1855          if (!bkpinfo->please_dont_eject)
1856        {
1857          log_to_screen("Ejecting media to clear drive status.");
1858          eject_device(bkpinfo->media_device);
1859          inject_device(bkpinfo->media_device);
1860        }
1861              pause_for_N_seconds(5, "Letting DVD drive settle");
1862          res = eval_call_to_make_ISO (bkpinfo, bkpinfo->call_make_iso, bkpinfo->scratchdir,
1863           g_current_media_number, MONDO_LOGFILE, message_to_screen);
1864          retval += res;
1865          if (!bkpinfo->please_dont_eject)
1866        {
1867          log_to_screen("Ejecting media.");
1868          eject_device(bkpinfo->media_device);
1869        }
1870          if (res)
1871            { log_to_screen("Dagnabbit. It still failed."); }
1872          else
1873            { log_to_screen("OK, this time I successfully backed up to DVD."); }
1874        }
1875#endif
1876      if (g_backup_media_type == dvd && !bkpinfo->please_dont_eject)
1877        { eject_device(bkpinfo->media_device); }
1878     }
1879    }
1880  else
1881    {
1882      sprintf (message_to_screen, "Running mkisofs to make %s #%d",
1883           media_descriptor_string(bkpinfo->backup_media_type),
1884           g_current_media_number);
1885      log_msg (1, message_to_screen);
1886      sprintf (result_sz, "Call to mkisofs to make ISO (%s #%d) ",
1887            media_descriptor_string(bkpinfo->backup_media_type),
1888            g_current_media_number);
1889      if (bkpinfo->nonbootable_backup)
1890        {
1891          log_msg (1, "Making nonbootable backup");
1892// FIXME --- change mkisofs string to MONDO_MKISOFS_NONBOOTABLE and add ' .' at end
1893          res =
1894        eval_call_to_make_ISO (bkpinfo,
1895           "mkisofs -o _ISO_ -r -p MondoRescue -publisher www.mondorescue.org -A Mondo_Rescue_GPL -V _CD#_ .",
1896           destfile, g_current_media_number, MONDO_LOGFILE,
1897           message_to_screen);
1898        }
1899      else
1900        {
1901          log_msg (1, "Making bootable backup");
1902
1903#ifdef __FreeBSD__
1904          bkpinfo->make_cd_use_lilo = TRUE;
1905#endif
1906
1907
1908          log_msg(1, "make_cd_use_lilo is actually %d", bkpinfo->make_cd_use_lilo);
1909          if (bkpinfo->make_cd_use_lilo)
1910            {
1911              log_msg(1, "make_cd_use_lilo = TRUE");
1912// FIXME --- change mkisofs string to MONDO_MKISOFS_REGULAR_SYSLINUX/LILO depending on bkpinfo->make_cd_usE_lilo
1913// and add ' .' at end
1914#ifdef __IA64__
1915              log_msg(1, "IA64 --> elilo");
1916              res =
1917                eval_call_to_make_ISO (bkpinfo,
1918                    //-b images/mindi-boot.2880.img
1919            "mkisofs -no-emul-boot -b images/mindi-bootroot."IA64_BOOT_SIZE".img -c boot.cat -o _ISO_ -J -r -p MondoRescue -publisher www.mondorescue.org -A Mondo_Rescue_GPL -V _CD#_ .",
1920                    destfile, g_current_media_number, MONDO_LOGFILE,
1921                    message_to_screen);
1922#else
1923// FIXME --- change mkisofs string to MONDO_MKISOFS_REGULAR_SYSLINUX/LILO depending on bkpinfo->make_cd_usE_lilo
1924// and add ' .' at end
1925          log_msg(1, "Non-ia64 --> lilo");
1926              res =
1927                eval_call_to_make_ISO (bkpinfo,
1928                    "mkisofs -b images/mindi-bootroot.2880.img -c boot.cat -o _ISO_ -J -r -p MondoRescue -publisher www.mondorescue.org -A Mondo_Rescue_GPL -V _CD#_ .",
1929                    destfile, g_current_media_number, MONDO_LOGFILE,
1930                    message_to_screen);
1931#endif
1932            }
1933          else
1934            {
1935              log_msg(1, "make_cd_use_lilo = FALSE");
1936          log_msg(1, "Isolinux");
1937              res =
1938            eval_call_to_make_ISO (bkpinfo,
1939                   "mkisofs -no-emul-boot -b isolinux.bin -boot-load-size 4 -boot-info-table -c boot.cat -o _ISO_ -J -r -p MondoRescue -publisher www.mondorescue.org -A Mondo_Rescue_GPL -V _CD#_ .",
1940           destfile, g_current_media_number, MONDO_LOGFILE,
1941           message_to_screen);
1942            }
1943        }
1944      if (res)
1945    {
1946      strcat (result_sz, "...failed");
1947    }
1948      else
1949    {
1950      strcat (result_sz, "...OK");
1951    }
1952      log_to_screen (result_sz);
1953      retval += res;
1954    }
1955
1956  if (bkpinfo->backup_media_type == cdr || bkpinfo->backup_media_type == cdrw)
1957    {
1958      if (is_this_device_mounted(bkpinfo->media_device))
1959        {
1960          log_msg (2, "Warning - %s mounted. I'm unmounting it before I burn to it.", bkpinfo->media_device);
1961          sprintf(tmp, "umount %s", bkpinfo->media_device);
1962          run_program_and_log_output(tmp, FALSE);
1963        }
1964    }
1965
1966  if (bkpinfo->call_burn_iso[0] != '\0')
1967    {
1968      log_msg (2, "bkpinfo->call_burn_iso = %s", bkpinfo->call_burn_iso);
1969      sprintf (message_to_screen, "Burning %s #%d",
1970            media_descriptor_string(bkpinfo->backup_media_type),
1971           g_current_media_number);
1972      pause_and_ask_for_cdr (2, &cd_is_mountable);
1973      res =
1974    eval_call_to_make_ISO (bkpinfo, bkpinfo->call_burn_iso, destfile,
1975           g_current_media_number, MONDO_LOGFILE, message_to_screen);
1976      if (res)
1977    {
1978      strcat (message_to_screen, "...failed");
1979    }
1980      else
1981    {
1982      strcat (message_to_screen, "...OK");
1983    }
1984      log_to_screen (message_to_screen);
1985      retval += res;
1986    }
1987
1988  if (bkpinfo->call_after_iso[0] != '\0')
1989    {
1990      sprintf (message_to_screen, "Running post-ISO call (%s #%d)",
1991            media_descriptor_string(bkpinfo->backup_media_type),
1992           g_current_media_number);
1993      res =
1994    eval_call_to_make_ISO (bkpinfo, bkpinfo->call_after_iso, destfile,
1995           g_current_media_number, MONDO_LOGFILE, message_to_screen);
1996      if (res)
1997    {
1998      strcat (message_to_screen, "...failed");
1999    }
2000      else
2001    {
2002      strcat (message_to_screen, "...OK");
2003    }
2004      log_to_screen (message_to_screen);
2005      retval += res;
2006    }
2007
2008  chdir (old_pwd);
2009  if (retval)
2010    {
2011      log_msg (1, "WARNING - make_iso_fs returned an error");
2012    }
2013  paranoid_free(old_pwd);
2014  paranoid_free(result_sz);
2015  paranoid_free(message_to_screen);
2016  paranoid_free(sz_blank_disk);
2017  paranoid_free(fnam);
2018  paranoid_free(tmp);
2019  return (retval);
2020}
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030bool is_dev_an_NTFS_dev(char *bigfile_fname)
2031{
2032  char *tmp;
2033  char *command;
2034  malloc_string(tmp);
2035  malloc_string(command);
2036  sprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | strings | head -n1", bigfile_fname);
2037  log_msg(1, "command = '%s'", command);
2038  strcpy(tmp, call_program_and_get_last_line_of_output(command));
2039  log_msg(1, "--> tmp = '%s'", tmp);
2040  if (strstr(tmp, "NTFS"))
2041    { iamhere("TRUE"); return(TRUE); }
2042  else
2043    { iamhere("FALSE"); return(FALSE); }
2044}
2045
2046
2047/**
2048 * Back up big files by chopping them up.
2049 * This function backs up all "big" files (where "big" depends
2050 * on your backup media) in "chunks" (whose size again depends
2051 * on your media).
2052 *
2053 * @param bkpinfo The backup information structure. Fields used:
2054 * - @c backup_media_type
2055 * - @c optimal_set_size
2056 * @param biggielist_fname The path to a file containing a list of
2057 * all "big" files.
2058 * @return The number of errors encountered (0 for success)
2059 * @see slice_up_file_etc
2060 */
2061int
2062make_slices_and_images (struct s_bkpinfo *bkpinfo, char *biggielist_fname)
2063{
2064
2065    /*@ pointers ********************************************/
2066  FILE *fin;
2067  char *p;
2068
2069    /*@ buffers *********************************************/
2070  char *tmp;
2071  char *bigfile_fname;
2072  char *sz_devfile;
2073  char *partimagehack_fifo = NULL;
2074    /*@ long ************************************************/
2075  long biggie_file_number = 0;
2076  long noof_biggie_files = 0;
2077  long estimated_total_noof_slices = 0;
2078
2079    /*@ int *************************************************/
2080  int retval = 0;
2081  int res = 0;
2082  pid_t pid;
2083  FILE*ftmp=NULL;
2084  bool delete_when_done; 
2085  bool use_partimagehack;
2086    /*@ long long *******************************************/
2087  long long biggie_fsize;
2088
2089  assert(bkpinfo!=NULL);
2090  assert_string_is_neither_NULL_nor_zerolength(biggielist_fname);
2091
2092  malloc_string(tmp);
2093  malloc_string(bigfile_fname);
2094  malloc_string(sz_devfile);
2095  estimated_total_noof_slices =
2096    size_of_all_biggiefiles_K (bkpinfo) / bkpinfo->optimal_set_size + 1;
2097
2098  log_msg (1, "size of all biggiefiles = %ld",
2099       size_of_all_biggiefiles_K (bkpinfo));
2100  log_msg (1, "estimated_total_noof_slices = %ld KB / %ld KB = %ld",
2101       size_of_all_biggiefiles_K (bkpinfo), bkpinfo->optimal_set_size,
2102       estimated_total_noof_slices);
2103
2104  if (length_of_file (biggielist_fname) < 6)
2105    {
2106      log_msg (1, "No biggiefiles; fair enough...");
2107      return (0);
2108    }
2109  sprintf (tmp, "I am now backing up all large files.");
2110  log_to_screen (tmp);
2111  noof_biggie_files = count_lines_in_file (biggielist_fname);
2112  open_progress_form ("Backing up big files", tmp,
2113              "Please wait. This may take some time.", "",
2114              estimated_total_noof_slices);
2115  if (!(fin = fopen (biggielist_fname, "r"))) { log_OS_error("Unable to openin biggielist"); return(1); }
2116  for (fgets (bigfile_fname, MAX_STR_LEN, fin); !feof (fin);
2117       fgets (bigfile_fname, MAX_STR_LEN, fin), biggie_file_number++)
2118    {
2119      use_partimagehack = FALSE;
2120      if (bigfile_fname[strlen (bigfile_fname) - 1] < 32)
2121    {
2122      bigfile_fname[strlen (bigfile_fname) - 1] = '\0';
2123    }
2124      biggie_fsize = length_of_file (bigfile_fname);
2125      delete_when_done = FALSE;
2126     
2127      if (!does_file_exist (bigfile_fname))
2128    {
2129          ftmp = fopen(bigfile_fname, "w");
2130      paranoid_fclose(ftmp);
2131      sprintf (tmp, "bigfile %s was deleted - creating a dummy", bigfile_fname);
2132      delete_when_done = TRUE;
2133    }
2134      else
2135        {
2136// Call partimagehack if it's a /dev entry (i.e. a partition to be imaged)
2137          log_msg (2, "bigfile_fname = %s", bigfile_fname);
2138      use_partimagehack = FALSE;
2139      if (!strncmp ( bigfile_fname, "/dev/", 5) && is_dev_an_NTFS_dev(bigfile_fname))
2140            {
2141          use_partimagehack = TRUE;
2142          log_msg (2, "Calling partimagehack in background because %s is an NTFS partition", bigfile_fname);
2143              sprintf(sz_devfile, "/tmp/%d.%d.000", (int)(random()%32768), (int)(random()%32768));
2144          mkfifo(sz_devfile, 0x770);
2145          partimagehack_fifo = sz_devfile;
2146              switch(pid=fork())
2147                {
2148                  case -1: fatal_error("Fork failure");
2149              case 0:
2150            log_msg (2, "CHILD - fip - calling feed_into_partimage(%s, %s)", bigfile_fname, sz_devfile);
2151            res=feed_into_partimage(bigfile_fname, sz_devfile);
2152            exit(res);
2153            break;
2154                  default:
2155            log_msg (2, "feed_into_partimage() called in background --- pid=%ld", (long int)(pid));
2156                }
2157        }
2158// Otherwise, use good old 'dd' and 'bzip2'
2159          else
2160        {
2161          sz_devfile[0] = '\0';
2162          partimagehack_fifo = NULL;
2163        }
2164
2165// Whether partition or biggiefile, just do your thang :-)
2166      sprintf (tmp, "Bigfile #%ld is '%s' (%ld KB)", biggie_file_number+1,
2167           bigfile_fname, (long) biggie_fsize >> 10);
2168          if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2169        {
2170          write_header_block_to_stream (biggie_fsize, bigfile_fname,
2171                      use_partimagehack?BLK_START_A_PIHBIGGIE:BLK_START_A_NORMBIGGIE);
2172        }
2173      res =
2174        slice_up_file_etc (bkpinfo, bigfile_fname, partimagehack_fifo,
2175            biggie_file_number, noof_biggie_files, use_partimagehack);
2176          if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2177        {
2178          write_header_block_to_stream (0,
2179                      calc_checksum_of_file
2180                      (bigfile_fname), BLK_STOP_A_BIGGIE);
2181        }
2182      retval += res;
2183      p = strrchr (bigfile_fname, '/');
2184      if (p)
2185        {
2186          p++;
2187        }
2188      else
2189        {
2190          p = bigfile_fname;
2191        }
2192      sprintf (tmp, "Archiving %s ... ", bigfile_fname);
2193      if (res)
2194        {
2195          strcat (tmp, "Failed!");
2196        }
2197      else
2198        {
2199          strcat (tmp, "OK");
2200        }
2201      if (delete_when_done)
2202        { unlink(bigfile_fname); delete_when_done=FALSE; }
2203    }
2204#ifndef _XWIN
2205      if (!g_text_mode) { newtDrawRootText (0, g_noof_rows - 2, tmp); newtRefresh (); }
2206#endif
2207    }
2208  log_msg (1, "Finished backing up bigfiles");
2209  log_msg (1, "estimated slices = %ld; actual slices = %ld",
2210       estimated_total_noof_slices, g_current_progress);
2211  close_progress_form ();
2212  paranoid_fclose(fin);
2213  paranoid_free(tmp);
2214  paranoid_free(bigfile_fname);
2215  paranoid_free(sz_devfile);
2216  return (retval);
2217}
2218
2219
2220
2221
2222/**
2223 * Single-threaded version of @c make_afioballs_and_images().
2224 * @see make_afioballs_and_images
2225 */
2226int
2227make_afioballs_and_images_OLD (struct s_bkpinfo *bkpinfo)
2228{
2229
2230    /*@ int ***************************************************/
2231  int retval = 0;
2232  long int curr_set_no = 0;
2233  int res = 0;
2234 
2235    /*@ buffers ***********************************************/
2236  char *curr_filelist_fname;
2237  char *curr_afioball_fname;
2238  char *curr_xattr_list_fname;
2239  char *curr_acl_list_fname;
2240  char *tmp;
2241  char *media_usage_comment;
2242 
2243  malloc_string(curr_afioball_fname);
2244  malloc_string(media_usage_comment);
2245  malloc_string(curr_filelist_fname);
2246  malloc_string(curr_xattr_list_fname);
2247  malloc_string(curr_acl_list_fname);
2248 
2249  tmp = malloc(MAX_STR_LEN*2);
2250 
2251  sprintf (tmp, "%s/archives/filelist.full", bkpinfo->scratchdir);
2252
2253  log_to_screen ("Archiving regular files");
2254
2255  open_progress_form ("Backing up filesystem",
2256              "I am backing up your live filesystem now.",
2257              "Please wait. This may take a couple of hours.",
2258              "Working...", get_last_filelist_number (bkpinfo) + 1);
2259
2260  sprintf (curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);
2261
2262  for (curr_set_no = 0; does_file_exist (curr_filelist_fname);
2263       sprintf (curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir,
2264        ++curr_set_no))
2265    {
2266      /* backup this set of files */
2267      sprintf (curr_filelist_fname,  FILELIST_FNAME_RAW_SZ,  bkpinfo->tmpdir, curr_set_no);
2268      sprintf (curr_afioball_fname, AFIOBALL_FNAME_RAW_SZ,bkpinfo->tmpdir,
2269               curr_set_no, bkpinfo->zip_suffix);
2270     
2271      log_msg (1, "EXAT'g set %ld", curr_set_no);
2272      sprintf (curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);
2273      sprintf (curr_acl_list_fname,   ACL_LIST_FNAME_RAW_SZ,   bkpinfo->tmpdir, curr_set_no);
2274      get_fattr_list(curr_filelist_fname, curr_xattr_list_fname);
2275      get_acl_list(curr_filelist_fname, curr_acl_list_fname);
2276     
2277      log_msg (1, "Archiving set %ld", curr_set_no);
2278      res =
2279    archive_this_fileset (bkpinfo, curr_filelist_fname, curr_afioball_fname, curr_set_no);
2280      retval += res;
2281      if (res)
2282    {
2283      sprintf (tmp,
2284           "Errors occurred while archiving set %ld. Perhaps your live filesystem changed?",
2285           curr_set_no);
2286      log_to_screen (tmp);
2287    }
2288
2289      strcpy (media_usage_comment, percent_media_full_comment (bkpinfo));
2290
2291      /* copy to CD (scratchdir) ... and an actual CD-R if necessary */
2292      if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2293        {
2294              register_in_tape_catalog(fileset, curr_set_no, -1, curr_afioball_fname);
2295              maintain_collection_of_recent_archives(bkpinfo->tmpdir, curr_afioball_fname);
2296          iamhere("Writing EXAT files");
2297              res += write_EXAT_files_to_tape(bkpinfo, curr_xattr_list_fname, curr_acl_list_fname);
2298// archives themselves
2299              res = move_files_to_stream (bkpinfo, curr_afioball_fname, NULL);
2300        }
2301      else
2302        {
2303          res = move_files_to_cd (bkpinfo, curr_filelist_fname, curr_xattr_list_fname, curr_acl_list_fname, curr_afioball_fname, NULL);
2304        }
2305      retval += res;
2306      g_current_progress++;
2307      update_progress_form (media_usage_comment);
2308
2309      if (res)
2310    {
2311      sprintf (tmp, "Failed to add archive %ld's files to CD dir\n",
2312           curr_set_no);
2313      log_to_screen (tmp);
2314      fatal_error
2315        ("Is your hard disk is full? If not, please send the author the logfile.");
2316    }
2317    }
2318  close_progress_form ();
2319  sprintf (tmp, "Your regular files have been archived ");
2320  if (retval)
2321    {
2322      strcat (tmp, "(with errors).");
2323    }
2324  else
2325    {
2326      strcat (tmp, "successfully.");
2327    }
2328  log_to_screen (tmp);
2329  paranoid_free(tmp);
2330  paranoid_free(curr_filelist_fname);
2331  paranoid_free(curr_afioball_fname);
2332  paranoid_free(media_usage_comment);
2333  paranoid_free(curr_xattr_list_fname);
2334  paranoid_free(curr_acl_list_fname);
2335  return (retval);
2336}
2337
2338/* @} - end of LLarchiveGroup */ 
2339 
2340 
2341/**
2342 * Wrapper around @c make_afioballs_and_images().
2343 * @param bkpinfo the backup information structure. Only the
2344 * @c backup_media_type field is used within this function.
2345 * @return return code of make_afioballs_and_images
2346 * @see make_afioballs_and_images
2347 * @ingroup MLarchiveGroup
2348 */
2349int
2350make_those_afios_phase (struct s_bkpinfo *bkpinfo)
2351{
2352    /*@ int ********************************************/
2353  int res = 0;
2354  int retval = 0;
2355
2356  assert(bkpinfo!=NULL);
2357
2358  mvaddstr_and_log_it (g_currentY, 0, "Archiving regular files to media          ");
2359
2360  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2361    {
2362      write_header_block_to_stream (0, "start-of-afioballs",
2363                  BLK_START_AFIOBALLS);
2364#if __FreeBSD__ == 5
2365      log_msg (1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0");
2366      res = make_afioballs_and_images_OLD (bkpinfo);
2367#else
2368      res = make_afioballs_and_images_OLD (bkpinfo);
2369#endif
2370      write_header_block_to_stream (0, "stop-afioballs", BLK_STOP_AFIOBALLS);
2371    }
2372  else
2373    {
2374      res = make_afioballs_and_images (bkpinfo);
2375    }
2376
2377  retval += res;
2378  if (res)
2379    {
2380      mvaddstr_and_log_it (g_currentY++, 74, "Errors.");
2381      log_msg (1, "make_afioballs_and_images returned an error");
2382    }
2383  else
2384    {
2385      mvaddstr_and_log_it (g_currentY++, 74, "Done.");
2386    }
2387  return (retval);
2388}
2389
2390/**
2391 * Wrapper around @c make_slices_and_images().
2392 * @param bkpinfo The backup information structure. Fields used:
2393 * - @c backup_media_type
2394 * - @c scratchdir
2395 * - @c tmpdir
2396 * @return The number of errors encountered (0 for success)
2397 * @ingroup MLarchiveGroup
2398 */
2399int
2400make_those_slices_phase (struct s_bkpinfo *bkpinfo)
2401{
2402
2403    /*@ int ******************************************************/
2404  int res = 0;
2405  int retval = 0;
2406
2407    /*@ buffers ***************************************************/
2408  char *biggielist;
2409  char *command;
2410  char *blah;
2411  char *xattr_fname;
2412  char *acl_fname;
2413 
2414  assert(bkpinfo!=NULL);
2415  /* slice big files */
2416  malloc_string(blah);
2417  malloc_string(biggielist);
2418  malloc_string(xattr_fname);
2419  malloc_string(acl_fname);
2420  command = malloc(1200);
2421  mvaddstr_and_log_it (g_currentY, 0, "Archiving large files to media           ");
2422  sprintf (biggielist, "%s/archives/biggielist.txt", bkpinfo->scratchdir);
2423  sprintf (xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2424  sprintf (acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2425 
2426  sprintf (command, "cp %s/biggielist.txt %s", bkpinfo->tmpdir, biggielist);
2427  paranoid_system(command);
2428  sprintf (blah, "biggielist = %s", biggielist);
2429  log_msg (2, blah);
2430 
2431  if (!does_file_exist (biggielist))
2432    {
2433      log_msg (1, "BTW, the biggielist does not exist");
2434    }
2435
2436  get_fattr_list(biggielist, xattr_fname);
2437  get_acl_list(biggielist, acl_fname);
2438  sprintf (command, "cp %s %s/archives/", xattr_fname, bkpinfo->scratchdir);
2439  paranoid_system(command);
2440  sprintf (command, "cp %s %s/archives/", acl_fname, bkpinfo->scratchdir);
2441  paranoid_system(command);
2442
2443  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2444    {
2445      res += write_EXAT_files_to_tape(bkpinfo, xattr_fname, acl_fname);
2446      sprintf (blah, "%ld", count_lines_in_file (biggielist));
2447      write_header_block_to_stream (0, blah, BLK_START_BIGGIEFILES);
2448    }
2449  res = make_slices_and_images (bkpinfo, biggielist);
2450  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2451    {
2452      write_header_block_to_stream (0, "end-of-biggiefiles",
2453                  BLK_STOP_BIGGIEFILES);
2454    }
2455  retval += res;
2456  if (res)
2457    {
2458      log_msg (1, "make_slices_and_images returned an error");
2459      mvaddstr_and_log_it (g_currentY++, 74, "Errors.");
2460    }
2461  else
2462    {
2463      mvaddstr_and_log_it (g_currentY++, 74, "Done.");
2464    }
2465  paranoid_free(blah);
2466  paranoid_free(biggielist);
2467  paranoid_free(command);
2468  paranoid_free(xattr_fname);
2469  paranoid_free(acl_fname);
2470  return (retval);
2471}
2472
2473
2474
2475/**
2476 * @addtogroup LLarchiveGroup
2477 * @{
2478 */
2479/**
2480 * Function pointer to an appropriate @c move_files_to_cd routine.
2481 * You can set this to your own function (for example, one to
2482 * transfer files over the network) or leave it as is.
2483 */
2484int (*move_files_to_cd) (struct s_bkpinfo *, char *, ...) = _move_files_to_cd;
2485
2486/**
2487 * Move some files to the ISO scratch directory.
2488 * This function moves files specified as parameters, into the directory
2489 * @c bkpinfo->scratchdir, where the files that will be stored on the next
2490 * CD are waiting.
2491 *
2492 * @param bkpinfo The backup information structure. Fields used:
2493 * - @c media_size
2494 * - @c scratchdir
2495 * @param files_to_add The files to add to the scratchdir.
2496 * @warning The list of @c files_to_add must be terminated with @c NULL.
2497 * @note If and when the space occupied by the scratchdir would exceed
2498 * the capacity of the current CD,
2499 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the
2500 * scratchdir is emptied.
2501 *
2502 * @return The number of errors encountered (0 for success)
2503 */
2504int
2505_move_files_to_cd (struct s_bkpinfo *bkpinfo,
2506         char *files_to_add, ...)
2507{
2508
2509    /*@ int *************************************************************/
2510  int retval = 0;
2511    int res = 0;
2512
2513    /*@ buffers *********************************************************/
2514  char *tmp,
2515       *curr_file, *cf;
2516
2517    /*@ long *************************************************************/
2518  va_list ap;
2519  long long would_occupy;
2520
2521  assert(bkpinfo!=NULL);
2522  malloc_string(curr_file);
2523  tmp = malloc(1200);
2524  would_occupy = space_occupied_by_cd (bkpinfo->scratchdir);
2525  va_start(ap, files_to_add); // initialize the variable arguments
2526  for(cf = files_to_add; cf!=NULL; cf=va_arg(ap, char*))
2527    {
2528      if (!cf) {continue;}
2529      strcpy(curr_file, cf);
2530      if (!does_file_exist (curr_file))
2531    {
2532      log_msg (1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file);
2533    }
2534      else
2535        {
2536      log_msg (8, "Trying to add file %s to CD", curr_file);
2537          would_occupy += length_of_file (curr_file) / 1024;
2538        }
2539    }
2540  va_end(ap);
2541
2542  if (bkpinfo->media_size[g_current_media_number]<=0) { fatal_error( "move_files_to_cd() - unknown media size"); }
2543  if (would_occupy / 1024 > bkpinfo->media_size[g_current_media_number])
2544    {
2545      res = write_iso_and_go_on (bkpinfo, FALSE);   /* FALSE because this is not the last CD we'll write */
2546      retval += res;
2547      if (res)
2548    {
2549      log_msg (1, "WARNING - write_iso_and_go_on returned an error");
2550    }
2551    }
2552
2553  va_start(ap, files_to_add); // initialize the variable arguments
2554  for(cf = files_to_add; cf!=NULL; cf=va_arg(ap, char*))
2555    {
2556      if (!cf) {continue;}
2557      strcpy(curr_file, cf);
2558
2559      sprintf (tmp, "mv -f %s %s/archives/", curr_file,
2560           bkpinfo->scratchdir);
2561      res = run_program_and_log_output (tmp, 5);
2562      retval += res;
2563      if (res)
2564    {
2565      log_msg (1, "(move_files_to_cd) '%s' failed", tmp);
2566    }
2567      else
2568        {
2569      log_msg (8, "Moved %s to CD OK", tmp);
2570    }
2571      //      unlink (curr_file);
2572    }
2573  va_end(ap);
2574
2575  if (retval)
2576    {
2577      log_msg (1, "Warning - errors occurred while I was adding files to CD dir");
2578    }
2579  paranoid_free(tmp);
2580  paranoid_free(curr_file);
2581  return (retval);
2582}
2583
2584/* @} - end of LLarchiveGroup */
2585
2586
2587
2588
2589
2590
2591
2592
2593/**
2594 * Offer to write boot and data disk images to 3.5" floppy disks.
2595 * @param bkpinfo The backup information structure. Only the
2596 * @c backup_media_type field is used in this function.
2597 * @param imagesdir The directory containing the floppy images (usually
2598 * /root/images/mindi).
2599 *
2600 * @return The number of errors encountered (0 for success)
2601 * @see write_image_to_floppy
2602 * @see format_disk
2603 * @ingroup MLarchiveGroup
2604 */
2605int
2606offer_to_write_floppies (struct s_bkpinfo *bkpinfo, char *imagesdir)
2607{
2608    /*@ buffer *************************************************************/
2609  char *tmp;
2610    char *comment;
2611    char *bootdisk_dev;
2612    char *datadisk_dev;
2613    char *bootdisk_file;
2614    char *rootdisk_file;
2615
2616    /*@ int ****************************************************************/
2617  int i = 0;
2618    int res = 0;
2619
2620    /*@ bool ***************************************************************/
2621  bool format_first;
2622  bool root_disk_exists=FALSE;
2623
2624  malloc_string(tmp);
2625  malloc_string(comment);
2626  malloc_string(bootdisk_dev);
2627  malloc_string(datadisk_dev);
2628  malloc_string(rootdisk_file);
2629  malloc_string(bootdisk_file);
2630  assert(bkpinfo!=NULL);
2631  assert_string_is_neither_NULL_nor_zerolength(imagesdir);
2632
2633
2634  if (!ask_me_yes_or_no
2635      ("Write boot and data disk images to 3.5\" floppy disks?"))
2636    {
2637      return (0);
2638    }
2639  if (does_device_exist (DEFAULT_1722MB_DISK))
2640    {
2641#ifdef __FreeBSD__
2642 // tell the system that this is a 1.72m floppy
2643      system ("/usr/sbin/fdcontrol -F 1722 /dev/fd0.1722");
2644#endif
2645      strcpy (bootdisk_dev, DEFAULT_1722MB_DISK);
2646    }
2647  else if (does_device_exist (BACKUP_1722MB_DISK))
2648    {
2649      sprintf (bootdisk_dev, "/dev/fd0H1722");
2650    }
2651  else
2652    {
2653      log_msg( 1, "Warning - can't find a 1.72MB floppy device *sigh*" );
2654      strcpy(bootdisk_dev, DEFAULT_1722MB_DISK);
2655//      return (1);
2656    }
2657  strcpy (datadisk_dev, "/dev/fd0");
2658  if (!does_device_exist (datadisk_dev))
2659    {
2660      log_msg( 1, "Warning - can't find a 1.44MB floppy device *sigh*" );
2661      strcpy(datadisk_dev, "/dev/fd0");
2662//      return (1);
2663    }
2664  format_first =
2665    ask_me_yes_or_no
2666    ("Do you want me to format the disks before I write to them?");
2667
2668/* boot disk */
2669  if (ask_me_OK_or_cancel ("About to write boot disk"))
2670    {
2671      log_to_screen ("Writing boot floppy");
2672#ifdef __FreeBSD__
2673      sprintf (tmp, "%s/mindi-kern.1722.img", imagesdir);
2674      if (format_first) { format_disk (bootdisk_dev); }
2675      res += write_image_to_floppy (bootdisk_dev, tmp);
2676      if (ask_me_OK_or_cancel ("About to write 1.44MB mfsroot disk"))
2677        {
2678          log_to_screen ("Writing mfsroot floppy");
2679          if (format_first) { format_disk (datadisk_dev); }
2680          sprintf (tmp, "%s/mindi-mfsroot.1440.img", imagesdir);
2681          write_image_to_floppy (datadisk_dev, tmp);
2682        }
2683#else
2684      sprintf (bootdisk_file, "%s/mindi-bootroot.1722.img", imagesdir);
2685      if (does_file_exist(bootdisk_file))
2686        {
2687          if (format_first) { format_disk (bootdisk_dev); }
2688      res += write_image_to_floppy (bootdisk_dev, bootdisk_file);
2689        }
2690      else
2691        {
2692      sprintf (bootdisk_file, "%s/mindi-boot.1440.img", imagesdir);
2693      sprintf (rootdisk_file, "%s/mindi-root.1440.img", imagesdir);
2694      root_disk_exists = TRUE;
2695      if (!does_file_exist(rootdisk_file) || !does_file_exist(bootdisk_file))
2696        {
2697          popup_and_OK("Cannot write boot/root floppies. Files not found.");
2698          log_to_screen("Failed to find boot/root floppy images. Oh dear.");
2699          return(1);
2700        }
2701      if (format_first) { format_disk (datadisk_dev); }
2702        /*
2703          sprintf(tmp, "cat %s > %s", bootdisk_file, datadisk_dev);
2704          res += run_external_binary_with_percentage_indicator_NEW("Writing boot floppy", tmp);
2705        */
2706      res += write_image_to_floppy (datadisk_dev, bootdisk_file);
2707      if (ask_me_OK_or_cancel ("About to write root disk"))
2708        {
2709          log_to_screen ("Writing root floppy");
2710          if (format_first) { format_disk (datadisk_dev); }
2711          sprintf(tmp, "cat %s > %s", rootdisk_file, datadisk_dev);
2712          log_msg(1, "tmp = '%s'", tmp);
2713          res += run_external_binary_with_percentage_indicator_NEW("Writing root floppy", tmp);
2714//              res += write_image_to_floppy (datadisk_dev, rootdisk_file);
2715        }
2716        }
2717#endif
2718    }
2719  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2720    {
2721      log_to_screen
2722    ("FYI, the data disks are stored on tape/CD for your convenience.");
2723      return (0);
2724    }
2725  for (i = 1; i < 99; i++)
2726    {
2727      sprintf (tmp, "%s/mindi-data-%d.img", imagesdir, i);
2728      log_msg (3, tmp);
2729      if (!does_file_exist (tmp))
2730    {
2731      log_msg (3, "...not found");
2732      break;
2733    }
2734      sprintf (comment, "About to write data disk #%d", i);
2735      if (ask_me_OK_or_cancel (comment))
2736    {
2737      sprintf (comment, "Writing data disk #%3d", i);
2738      log_to_screen (comment);
2739      if (format_first)
2740        {
2741          res += format_disk (datadisk_dev);
2742        }
2743      res += write_image_to_floppy (datadisk_dev, tmp);
2744    }
2745    }
2746  paranoid_free(tmp);
2747  paranoid_free(comment);
2748  paranoid_free(bootdisk_dev);
2749  paranoid_free(datadisk_dev);
2750  return (res);
2751}
2752
2753
2754
2755
2756
2757
2758
2759
2760/**
2761 * Wrapper around @c offer_to_write_floppies().
2762 * @param bkpinfo The backup information structure. Used only
2763 * in the call to @c offer_to_write_floppies().
2764 * @return 0 if the boot floppies were found (not necessarily written OK),
2765 * 1 otherwise.
2766 * @see offer_to_write_floppies
2767 * @ingroup MLarchiveGroup
2768 */
2769
2770int offer_to_write_boot_floppies_to_physical_disks(struct s_bkpinfo *bkpinfo)
2771{
2772int res=0;
2773
2774  assert(bkpinfo!=NULL);
2775
2776      mvaddstr_and_log_it (g_currentY, 0,
2777               "Writing boot+data floppy images to disk");
2778
2779      if (!bkpinfo->nonbootable_backup) {
2780#ifdef __FreeBSD__
2781      if (!does_file_exist ("/root/images/mindi/mindi-kern.1722.img"))
2782#else
2783      if (!does_file_exist ("/root/images/mindi/mindi-bootroot.1722.img") &&
2784          !does_file_exist ("/root/images/mindi/mindi-boot.1440.img"))
2785#endif
2786      {
2787          mvaddstr_and_log_it (g_currentY++, 74, "No Imgs");
2788          if (does_file_exist ("/root/images/mindi/mondorescue.iso"))
2789          {
2790              popup_and_OK
2791              ("Boot+data floppy creation failed. However, FYI, you may burn /root/images/mindi/mondorescue.iso to a CD and boot from that instead if you wish.");
2792              res++;
2793          }
2794      }
2795      else
2796      {
2797          offer_to_write_floppies (bkpinfo, "/root/images/mindi");
2798          mvaddstr_and_log_it (g_currentY++, 74, "Done.");
2799      }
2800      } else {
2801      popup_and_OK ("Since you opted for a nonbootable backup, no boot floppies were created.");
2802      }
2803     
2804  return(res);
2805}
2806
2807
2808
2809
2810/**
2811 * @addtogroup LLarchiveGroup
2812 * @{
2813 */
2814/**
2815 * Function pointer to an appropriate @c move_files_to_stream routine.
2816 * You can set this to your own function (for example, one to
2817 * transfer files over the network) or leave it as is.
2818 */
2819int (*move_files_to_stream) (struct s_bkpinfo *, char *, ...) = _move_files_to_stream;
2820
2821/**
2822 * Copy some files to tape.
2823 * This function copies the files specified as parameters into the tape stream.
2824 *
2825 * @param bkpinfo The backup information structure. Used only in the call to
2826 * @c write_file_to_stream_from_file().
2827 *
2828 * @param files_to_add The files to copy to the tape stream.
2829 * @warning The list of @c files_to_add must be terminated with @c NULL.
2830 * @note Files may be split across multiple tapes if necessary.
2831 *
2832 * @return The number of errors encountered (0 for success)
2833 */
2834int
2835_move_files_to_stream (struct s_bkpinfo *bkpinfo,
2836         char *files_to_add, ...)
2837{
2838
2839    /*@ int *************************************************************/
2840  int retval = 0;
2841    int res = 0;
2842    /*@ buffers *********************************************************/
2843
2844    /*@ char ************************************************************/
2845    char start_chr;
2846    char stop_chr;
2847        char *curr_file, *cf;
2848    /*@ long long *******************************************************/
2849  long long length_of_incoming_file = 0;
2850  t_archtype type;
2851  va_list ap;
2852
2853  assert(bkpinfo!=NULL);
2854  malloc_string(curr_file);
2855  va_start(ap, files_to_add);
2856  for(cf = files_to_add; cf!=NULL; cf=va_arg(ap, char*))
2857    {
2858      if (!cf) {continue;}
2859      strcpy(curr_file, cf);
2860      if (!does_file_exist (curr_file))
2861        {
2862          log_msg (1, 
2863           "Warning - you're trying to add a non-existent file - '%s' to the tape",
2864           curr_file);
2865        }
2866/* create header chars */
2867      start_chr = BLK_START_AN_AFIO_OR_SLICE;
2868      stop_chr = BLK_STOP_AN_AFIO_OR_SLICE;
2869/* ask for new tape if necessary */
2870      length_of_incoming_file = length_of_file (curr_file);
2871      write_header_block_to_stream (length_of_incoming_file, curr_file,
2872                  start_chr);
2873      if (strstr(curr_file, ".afio.") || strstr(curr_file, ".star."))
2874    { type = fileset; }
2875      else if (strstr(curr_file, "slice")) 
2876    { type = biggieslice; }
2877      else
2878    { type = other; }
2879      res = write_file_to_stream_from_file (bkpinfo, curr_file);
2880      retval += res;
2881      unlink (curr_file);
2882/* write closing header */
2883      write_header_block_to_stream (0, "finished-writing-file", stop_chr);
2884    }
2885  va_end(ap);
2886
2887  if (retval)
2888    {
2889      log_msg (1, "Warning - errors occurred while I was adding file to tape");
2890    }
2891  paranoid_free(curr_file);
2892  return (retval);
2893}
2894
2895/* @} - end of LLarchiveGroup */
2896
2897
2898
2899/**
2900 * @addtogroup utilityGroup
2901 * @{
2902 */
2903/**
2904 * Make sure the user has a valid CD-R(W) in the CD drive.
2905 * @param cdrw_dev Set to the CD-R(W) device checked.
2906 * @param keep_looping If TRUE, keep pestering user until they insist
2907 * or insert a correct CD; if FALSE, only check once.
2908 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't).
2909 */
2910int interrogate_disk_currently_in_cdrw_drive(char*cdrw_dev, bool keep_looping)
2911{
2912  char *tmp;
2913  int res=0;
2914  char *bkp;
2915  char *cdrecord;
2916
2917  malloc_string(tmp);
2918  malloc_string(bkp);
2919  malloc_string(cdrecord);
2920  strcpy(bkp, cdrw_dev);
2921  if (find_cdrw_device(cdrw_dev))
2922    {
2923      strcpy(cdrw_dev, bkp);
2924    }
2925  else
2926    {
2927      if (!system("which cdrecord > /dev/null 2> /dev/null"))
2928        { sprintf(cdrecord, "cdrecord dev=%s -atip", cdrw_dev); }
2929      else if (!system("which dvdrecord > /dev/null 2> /dev/null"))
2930        { sprintf(cdrecord, "cdrecord dev=%s -atip", cdrw_dev); }
2931      else
2932        { cdrecord[0] = '\0'; log_msg(2, "Oh well. I guess I'll just pray then."); }
2933      if (cdrecord[0])
2934        {
2935         if (!keep_looping)
2936           {
2937             retract_CD_tray_and_defeat_autorun();
2938             res = run_program_and_log_output(cdrecord, 5);
2939           }
2940         else
2941           {
2942             while((res=run_program_and_log_output(cdrecord, 5)))
2943               {
2944                 retract_CD_tray_and_defeat_autorun();
2945                 if (ask_me_yes_or_no("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?"))
2946                   { log_msg(1, "Well, he insisted..."); break; }
2947               }
2948            }
2949        }
2950    }
2951//  retract_CD_tray_and_defeat_autorun();
2952  paranoid_free(tmp);
2953  paranoid_free(cdrecord);
2954  paranoid_free(bkp);
2955  return(res);
2956}
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966/**
2967 * Asks the user to put a CD-R(W) in the drive.
2968 * @param ask_for_one_if_more_than_this (unused)
2969 * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.
2970 */
2971void
2972pause_and_ask_for_cdr (int ask_for_one_if_more_than_this, bool*pmountable)
2973{
2974
2975    /*@ buffers **********************************************/
2976  char *tmp;
2977  char *szmsg;
2978  char *cdrom_dev;
2979  char *cdrw_dev;
2980  char *our_serial_str;
2981  bool ok_go_ahead_burn_it;
2982  int cd_number = -1;
2983  int attempt_to_mount_returned_this=999;
2984  char *mtpt;
2985  char *szcdno;
2986  char *szserfname;
2987  char *szunmount;
2988
2989  malloc_string(tmp);
2990  malloc_string(szmsg);
2991  malloc_string(cdrom_dev);
2992  malloc_string(cdrw_dev);
2993  malloc_string(mtpt);
2994  malloc_string(szcdno);
2995  malloc_string(szserfname);
2996  malloc_string(our_serial_str);
2997  malloc_string(szunmount);
2998
2999  sprintf(szmsg, "I am about to burn %s #%d", media_descriptor_string(g_backup_media_type), g_current_media_number);
3000  log_to_screen(szmsg);
3001  if (g_current_media_number < ask_for_one_if_more_than_this)
3002    { return; }
3003 log_to_screen("Scanning CD-ROM drive...");
3004  sprintf(mtpt, "/tmp/cd.mtpt.%ld.%ld", (long int)random(), (long int)random());
3005  make_hole_for_dir(mtpt);
3006
3007gotos_make_me_puke:
3008  ok_go_ahead_burn_it = TRUE;
3009  if (!find_cdrom_device(cdrom_dev, FALSE))
3010    {
3011/* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird
3012      log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );
3013      retract_CD_tray_and_defeat_autorun();
3014*/
3015      sprintf(tmp, "umount %s", cdrom_dev);
3016      run_program_and_log_output(tmp, 1);
3017      sprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);
3018      sprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);
3019      sprintf(szunmount, "umount %s", mtpt);
3020      cd_number = -1;
3021      our_serial_str[0] = '\0';
3022      sprintf(tmp, "mount %s %s", cdrom_dev, mtpt);
3023      if ((attempt_to_mount_returned_this=run_program_and_log_output(tmp, 1)))
3024        {
3025      log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);
3026      log_to_screen("If there's a CD/DVD in the drive, it's blank.");
3027     /*
3028      if (interrogate_disk_currently_in_cdrw_drive(cdrw_dev, FALSE))
3029        {
3030              ok_go_ahead_burn_it = FALSE;
3031              log_to_screen("There isn't a writable CD/DVD in the drive.");
3032        }
3033      else
3034        {
3035          log_to_screen("Confirmed. There is a blank CD/DVD in the drive.");
3036        }
3037     */
3038        }
3039      else if (!does_file_exist(szcdno) || !does_file_exist(szserfname))
3040        {
3041      log_to_screen("%s has data on it but it's probably not a Mondo CD.", media_descriptor_string(g_backup_media_type));
3042        }
3043      else
3044    {
3045      log_to_screen("%s found in drive. It's a Mondo disk.", media_descriptor_string(g_backup_media_type));
3046          cd_number = atoi(last_line_of_file(szcdno));
3047          sprintf(tmp, "cat %s 2> /dev/null", szserfname);
3048          strcpy(our_serial_str, call_program_and_get_last_line_of_output(tmp));
3049      // FIXME - should be able to use last_line_of_file(), surely?
3050        }
3051      run_program_and_log_output(szunmount, 1);
3052      log_msg(2, "paafcd: cd_number = %d", cd_number);
3053      log_msg(2, "our serial str = %s; g_serial_string = %s", our_serial_str, g_serial_string);
3054      if (cd_number > 0 && !strcmp(our_serial_str, g_serial_string))
3055        {
3056      log_msg(2, "This %s is part of this backup set!", media_descriptor_string(g_backup_media_type));
3057          ok_go_ahead_burn_it = FALSE;
3058          if (cd_number == g_current_media_number-1)
3059            { log_to_screen("I think you've left the previous %s in the drive.", media_descriptor_string(g_backup_media_type)); }
3060          else
3061            { log_to_screen("Please remove this %s. It is part of the backup set you're making now.", media_descriptor_string(g_backup_media_type)); }
3062        }
3063      else
3064        {
3065      log_to_screen("...but not part of _our_ backup set.");
3066    }
3067    }
3068  else
3069    {
3070      log_msg(2, "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", media_descriptor_string(g_backup_media_type));
3071      if (interrogate_disk_currently_in_cdrw_drive(cdrw_dev, FALSE))
3072        {
3073          ok_go_ahead_burn_it = FALSE;
3074          log_to_screen("There isn't a writable %s in the drive.", media_descriptor_string(g_backup_media_type));
3075        }
3076    }
3077
3078/*
3079  if (g_current_media_number > ask_for_one_if_more_than_this)
3080    {
3081      ok_go_ahead_burn_it = FALSE;
3082      log_it("paafcd: %d > %d, so I'll definitely pause.", g_current_media_number > ask_for_one_if_more_than_this);
3083    }
3084*/
3085
3086  if (!ok_go_ahead_burn_it)
3087    {
3088      eject_device(cdrom_dev);
3089      sprintf (tmp,
3090           "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.",
3091            media_descriptor_string(g_backup_media_type),
3092           g_current_media_number,
3093           media_descriptor_string(g_backup_media_type));
3094      popup_and_OK (tmp);
3095      goto gotos_make_me_puke;
3096    }
3097  else
3098    {
3099      log_msg(2, "paafcd: OK, going ahead and burning it.");
3100    }
3101
3102  log_msg (2,"paafcd: OK, I assume I have a blank/reusable %s in the drive...", media_descriptor_string(g_backup_media_type));
3103
3104  //  if (ask_for_one_if_more_than_this>1) { popup_and_OK(szmsg); }
3105
3106  log_to_screen ("Proceeding w/ %s in drive.", media_descriptor_string(g_backup_media_type));
3107  paranoid_free(tmp);
3108  paranoid_free(szmsg);
3109  paranoid_free(cdrom_dev);
3110  paranoid_free(cdrw_dev);
3111  paranoid_free(mtpt);
3112  paranoid_free(szcdno);
3113  paranoid_free(szserfname);
3114  paranoid_free(our_serial_str);
3115  paranoid_free(szunmount);
3116  if (pmountable)
3117    {
3118      if (attempt_to_mount_returned_this)
3119        { *pmountable = FALSE; }
3120      else
3121        { *pmountable = TRUE; }
3122    }
3123
3124}
3125
3126
3127
3128
3129
3130
3131
3132
3133/**
3134 * Set the <tt>N</tt>th bit of @c array to @c true_or_false.
3135 * @param array The bit array (as a @c char pointer).
3136 * @param N The bit number to set or reset.
3137 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.
3138 * @see get_bit_N_of_array
3139 */
3140void set_bit_N_of_array(char*array, int N, bool true_or_false)
3141{
3142  int bit_number;
3143  int mask, orig_val, to_add;
3144  int element_number;
3145
3146  assert(array!=NULL);
3147
3148  element_number = N / 8;
3149  bit_number = N % 8;
3150  to_add = (1 << bit_number);
3151  mask = 255 - to_add;
3152  orig_val = array[element_number] & mask;
3153  //  log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);
3154  if (true_or_false) { array[element_number] = orig_val | to_add; }
3155}
3156
3157/* @} - end of utilityGroup */
3158
3159
3160
3161
3162
3163
3164
3165
3166/**
3167 * Chop up @c filename.
3168 * @param bkpinfo The backup information structure. Fields used:
3169 * - @c backup_media_type
3170 * - @c compression_level
3171 * - @c optimal_set_size
3172 * - @c tmpdir
3173 * - @c use_lzo
3174 * - @c zip_exe
3175 * - @c zip_suffix
3176 *
3177 * @param biggie_filename The file to chop up.
3178 * @param partimagehack_fifo The FIFO to partimagehack if this is an imagedev, NULL otherwise.
3179 * @param biggie_file_number The sequence number of this biggie file (starting from 0).
3180 * @param noof_biggie_files The number of biggie files there are total.
3181 * @return The number of errors encountered (0 for success)
3182 * @see make_slices_and_images
3183 * @ingroup LLarchiveGroup
3184 */
3185int
3186slice_up_file_etc (struct s_bkpinfo *bkpinfo, char *biggie_filename, char *partimagehack_fifo,
3187           long biggie_file_number, long noof_biggie_files, bool use_partimagehack)
3188{
3189
3190    /*@ buffers ***************************************************/
3191  char *tmp, *checksum_line, *command;
3192  char *tempblock;
3193  char *curr_slice_fname_uncompressed;
3194  char *curr_slice_fname_compressed;
3195  char *file_to_archive;
3196  char *file_to_openin;
3197    /*@ pointers ***************************************************/
3198  char *pB;
3199  FILE *fin, *fout;
3200
3201    /*@ bool *******************************************************/
3202  bool finished = FALSE;
3203
3204    /*@ long *******************************************************/
3205  size_t blksize = 0;
3206  long slice_num = 0;
3207  long i;
3208  long optimal_set_size;
3209  bool should_I_compress_slices;
3210  char *suffix; // for compressed slices
3211
3212    /*@ long long ***************************************************/
3213  long long totalread = 0;
3214  long long totallength = 0;
3215  long long length;
3216
3217  /*@ int *********************************************************/
3218  int retval = 0;
3219  int res = 0;
3220
3221    /*@ structures ***************************************************/
3222  struct s_filename_and_lstat_info biggiestruct;
3223//  struct stat statbuf;
3224
3225  assert(bkpinfo!=NULL);
3226  assert_string_is_neither_NULL_nor_zerolength(biggie_filename);
3227  malloc_string(tmp);
3228  malloc_string(checksum_line);
3229  malloc_string(curr_slice_fname_uncompressed);
3230  malloc_string(curr_slice_fname_compressed);
3231  malloc_string(file_to_archive);
3232  malloc_string(suffix);
3233  command = malloc(MAX_STR_LEN*8);
3234
3235  biggiestruct.for_backward_compatibility = '\n';
3236  biggiestruct.use_partimagehack = use_partimagehack;
3237  if (!(tempblock = (char*)malloc(256*1024))) { fatal_error("malloc error 256*1024"); }
3238  optimal_set_size = bkpinfo->optimal_set_size;
3239  if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0)
3240    {
3241      suffix[0] = '\0';
3242      //      log_it("%s is indeed compressed :-)", filename);
3243      should_I_compress_slices = FALSE;
3244    }
3245  else
3246    {
3247      strcpy(suffix, bkpinfo->zip_suffix);
3248      should_I_compress_slices = TRUE;
3249    }
3250
3251  if (optimal_set_size < 999)
3252    {
3253      fatal_error ("bkpinfo->optimal_set_size is insanely small");
3254    }
3255  if (partimagehack_fifo)
3256    {
3257      file_to_openin = partimagehack_fifo;
3258      strcpy (checksum_line, "IGNORE");
3259      log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);
3260    }
3261  else
3262    {
3263      file_to_openin = biggie_filename;
3264      sprintf (command, "md5sum \"%s\"", biggie_filename);
3265      if (!(fin = popen (command, "r"))) { log_OS_error("Unable to popen-in command"); return(1); }
3266      (void) fgets (checksum_line, MAX_STR_LEN, fin);
3267      pclose (fin);
3268    }
3269  lstat (biggie_filename, &biggiestruct.properties);
3270  strcpy (biggiestruct.filename, biggie_filename);
3271  pB = strchr(checksum_line, ' ');
3272  if (!pB) { pB = strchr(checksum_line, '\t'); }
3273  if (pB) { *pB='\0'; }
3274  strcpy (biggiestruct.checksum, checksum_line);
3275
3276  strcpy (tmp, slice_fname (biggie_file_number, 0, bkpinfo->tmpdir, ""));
3277  fout = fopen (tmp, "w");
3278  (void) fwrite((void*)&biggiestruct, 1, sizeof(biggiestruct), fout);
3279  paranoid_fclose (fout);
3280  totallength = length_of_file (biggie_filename);
3281  length      = totallength / optimal_set_size / 1024;
3282  log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);
3283  if (!(fin = fopen(file_to_openin, "r")))
3284    {
3285      log_OS_error("Unable to openin biggie_filename");
3286      sprintf (tmp, "Cannot archive bigfile '%s': not found", biggie_filename);
3287      log_to_screen (tmp);
3288      paranoid_free(tempblock);
3289      paranoid_free(tmp);
3290      paranoid_free(checksum_line);
3291      paranoid_free(command); 
3292      return (1);
3293    }
3294  if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3295    { res = move_files_to_stream (bkpinfo, slice_fname (biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL); }
3296  else
3297    { res = move_files_to_cd (bkpinfo, slice_fname (biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL); }
3298  i = bkpinfo->optimal_set_size / 256;
3299  for (slice_num = 1; !finished; slice_num++)
3300    {
3301      strcpy (curr_slice_fname_uncompressed,
3302          slice_fname (biggie_file_number, slice_num, bkpinfo->tmpdir,
3303               ""));
3304      strcpy (curr_slice_fname_compressed,
3305          slice_fname (biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));
3306
3307      strcpy (tmp, percent_media_full_comment (bkpinfo));
3308      update_progress_form (tmp);
3309      if (!(fout = fopen (curr_slice_fname_uncompressed, "w"))) { log_OS_error(curr_slice_fname_uncompressed); return(1); }
3310      if ( (i == bkpinfo->optimal_set_size / 256) && (totalread < 1.1 * totallength) )
3311    {
3312      for (i = 0; i < bkpinfo->optimal_set_size / 256; i++)
3313        {
3314          blksize = fread (tempblock, 1, 256 * 1024, fin);
3315          if (blksize > 0)
3316        {
3317          totalread = totalread + blksize;
3318          (void) fwrite (tempblock, 1, blksize, fout);
3319        }
3320          else
3321        {
3322          break;
3323        }
3324        }
3325    }
3326      else
3327    {
3328      i = 0;
3329    }
3330      paranoid_fclose (fout);
3331      if (i > 0) // length_of_file (curr_slice_fname_uncompressed)
3332    {
3333      if (!does_file_exist (curr_slice_fname_uncompressed))
3334        {
3335          log_msg (2, 
3336               "Warning - '%s' doesn't exist. How can I compress slice?",
3337               curr_slice_fname_uncompressed);
3338        }
3339          if (should_I_compress_slices && bkpinfo->compression_level>0)
3340            {
3341          sprintf (command, "%s -%d %s", bkpinfo->zip_exe,
3342           bkpinfo->compression_level, curr_slice_fname_uncompressed);
3343              log_msg (2, command);
3344          if ((res = system (command))) { log_OS_error(command); }
3345          //          did_I_compress_slice = TRUE;
3346            }
3347          else
3348            {
3349              sprintf (command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);
3350              res=0; // don't do it :)
3351          //          did_I_compress_slice = FALSE;
3352            }
3353      retval += res;
3354      if (res)
3355        {
3356          log_msg (2, "Failed to compress the slice");
3357        }
3358      if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed))
3359        {
3360          unlink (curr_slice_fname_uncompressed);
3361        }
3362      if (res)
3363        {
3364          sprintf (tmp, "Problem with slice # %ld", slice_num);
3365        }
3366      else
3367        {
3368          sprintf (tmp,
3369               "%s - Bigfile #%ld, slice #%ld compressed OK          ",
3370               biggie_filename, biggie_file_number + 1, slice_num);
3371        }
3372#ifndef _XWIN
3373      if (!g_text_mode)
3374        {
3375          newtDrawRootText (0, g_noof_rows - 2, tmp);
3376          newtRefresh ();
3377        }
3378      else
3379        {
3380          log_msg (2, tmp);
3381        }
3382#else
3383        log_msg(2, tmp);
3384#endif
3385        strcpy(file_to_archive, curr_slice_fname_compressed);
3386      g_current_progress++;
3387    }
3388      else /* if i==0 then ... */
3389    {
3390      finished = TRUE;
3391      strcpy (file_to_archive, curr_slice_fname_uncompressed);
3392          if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3393        {
3394          break;
3395        }
3396    }
3397
3398      if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3399        {
3400          register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);
3401          maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);
3402      res = move_files_to_stream (bkpinfo, file_to_archive, NULL); 
3403    }
3404      else
3405        {
3406      res = move_files_to_cd (bkpinfo, file_to_archive, NULL); 
3407    }
3408      retval += res;
3409      if (res)
3410    {
3411      sprintf (tmp,
3412           "Failed to add slice %ld of bigfile %ld to scratchdir",
3413           slice_num, biggie_file_number+1);
3414      log_to_screen (tmp);
3415      fatal_error
3416        ("Hard disk full. You should have bought a bigger one.");
3417    }
3418    }
3419  paranoid_fclose (fin);
3420  sprintf (tmp, "Sliced bigfile #%ld", biggie_file_number + 1);
3421  if (retval)
3422    {
3423      strcat (tmp, "...FAILED");
3424    }
3425  else
3426    {
3427      strcat (tmp, "...OK!");
3428    }
3429  log_msg (1, tmp);
3430  paranoid_free(tempblock);
3431  paranoid_free(tmp);
3432  paranoid_free(checksum_line);
3433  paranoid_free(command); 
3434  paranoid_free(curr_slice_fname_uncompressed);
3435  paranoid_free(curr_slice_fname_compressed);
3436  paranoid_free(file_to_archive);
3437  paranoid_free(suffix);
3438  return (retval);
3439}
3440
3441
3442
3443
3444
3445
3446/**
3447 * Remove the archives in @c d.
3448 * This could possibly include any of:
3449 * - all afioballs (compressed and not)
3450 * - all filelists
3451 * - all slices
3452 * - all checksums
3453 * - a zero filler file
3454 *
3455 * @param d The directory to wipe the archives from.
3456 * @ingroup utilityGroup
3457 */
3458void
3459wipe_archives (char *d)
3460{
3461    /*@ buffers **********************************************/
3462  char *tmp;
3463  char *dir;
3464
3465  malloc_string(tmp);
3466  malloc_string(dir);
3467  assert_string_is_neither_NULL_nor_zerolength(d);
3468
3469  sprintf (dir, "%s/archives", d);
3470  sprintf (tmp, "find %s -name '*.afio*' -exec rm -f '{}' \\;", dir);
3471  run_program_and_log_output(tmp, FALSE);
3472  sprintf (tmp, "find %s -name '*list.[0-9]*' -exec rm -f '{}' \\;", dir);
3473  run_program_and_log_output(tmp, FALSE);
3474  sprintf (tmp, "find %s -name 'slice*' -exec rm -f '{}' \\;", dir);
3475  run_program_and_log_output(tmp, FALSE);
3476  sprintf (tmp, "rm -f %s/cklist*", dir);
3477  run_program_and_log_output(tmp, FALSE);
3478  sprintf (tmp, "rm -f %s/zero", dir);
3479  run_program_and_log_output(tmp, FALSE);
3480  log_msg(1, "Wiped %s's archives", dir);
3481  sprintf (tmp, "ls -l %s", dir);
3482  run_program_and_log_output (tmp, FALSE);
3483  paranoid_free(tmp);
3484  paranoid_free(dir);
3485}
3486
3487
3488
3489/**
3490 * @addtogroup LLarchiveGroup
3491 * @{
3492 */
3493/**
3494 * Write the final ISO image.
3495 * @param bkpinfo The backup information structure. Used only
3496 * in the call to @c write_iso_and_go_on().
3497 * @return The number of errors encountered (0 for success)
3498 * @see write_iso_and_go_on
3499 * @see make_iso_fs
3500 * @bug The final ISO is written even if there are no files on it. In practice,
3501 * however, this occurs rarely.
3502 */
3503int
3504write_final_iso_if_necessary (struct s_bkpinfo *bkpinfo)
3505{
3506    /*@ int ******************************************************/
3507  int res;
3508
3509    /*@ buffers ***************************************************/
3510  char *tmp;
3511
3512  malloc_string(tmp);
3513  assert(bkpinfo!=NULL);
3514
3515// I should really check if there are any slices or tarballs to be copied to CD-R(W)'s; the odds are approx. 1 in a million that there are no files here, so I'll just go ahead & make one more CD anyway
3516
3517  sprintf(tmp, "Writing the final ISO");
3518  log_msg(2, tmp);
3519  center_string (tmp, 80);
3520#ifndef _XWIN
3521  if (!g_text_mode)
3522    {
3523      newtPushHelpLine (tmp);
3524    }
3525#endif
3526  res = write_iso_and_go_on (bkpinfo, TRUE);
3527#ifndef _XWIN
3528  if (!g_text_mode)
3529    {
3530      newtPopHelpLine ();
3531    }
3532#endif
3533  log_msg (2, "Returning from writing final ISO (res=%d)", res);
3534  paranoid_free(tmp);
3535  return (res);
3536}
3537
3538
3539/**
3540 * Write an ISO image to <tt>[bkpinfo->isodir]/bkpinfo->prefix-[g_current_media_number].iso</tt>.
3541 * @param bkpinfo The backup information structure. Fields used:
3542 * - @c backup_media_type
3543 * - @c prefix
3544 * - @c isodir
3545 * - @c manual_cd_tray
3546 * - @c media_size
3547 * - @c nfs_mount
3548 * - @c nfs_remote_dir
3549 * - @c scratchdir
3550 * - @c verify_data
3551 *
3552 * @param last_cd If TRUE, this is the last CD to write; if FALSE, it's not.
3553 * @return The number of errors encountered (0 for success)
3554 * @see make_iso_fs
3555 */
3556int
3557write_iso_and_go_on (struct s_bkpinfo *bkpinfo, bool last_cd)
3558{
3559    /*@ pointers *****************************************************/
3560  FILE *fout;
3561
3562    /*@ buffers ******************************************************/
3563  char *tmp;
3564  char *cdno_fname;
3565  char *lastcd_fname;
3566  char *isofile;
3567
3568    /*@ bool *********************************************************/
3569  bool that_one_was_ok;
3570  bool using_nfs;
3571  bool orig_vfy_flag_val;
3572
3573    /*@ int ************************************************************/
3574  int res = 0;
3575
3576  malloc_string(tmp);
3577  malloc_string(cdno_fname);
3578  malloc_string(lastcd_fname);
3579  malloc_string(isofile);
3580 
3581  assert(bkpinfo!=NULL);
3582  orig_vfy_flag_val = bkpinfo->verify_data;
3583  if (bkpinfo->media_size[g_current_media_number]<=0) { fatal_error( "write_iso_and_go_on() - unknown media size"); }
3584
3585  if (strlen (bkpinfo->nfs_mount) > 1)
3586    {
3587      using_nfs = TRUE;
3588    }
3589  else
3590    {
3591      using_nfs = FALSE;
3592    }
3593  log_msg (1, "OK, time to make %s #%d", media_descriptor_string(bkpinfo->backup_media_type), g_current_media_number);
3594
3595  /* label the ISO with its number */
3596
3597  sprintf (cdno_fname, "%s/archives/THIS-CD-NUMBER", bkpinfo->scratchdir);
3598  fout = fopen (cdno_fname, "w");
3599  fprintf (fout, "%d", g_current_media_number);
3600  paranoid_fclose (fout);
3601
3602  sprintf (tmp, "cp -f %s/autorun %s/", g_mondo_home, bkpinfo->scratchdir);
3603  if (run_program_and_log_output(tmp, FALSE))
3604    { log_msg(2, "Warning - unable to copy autorun to scratchdir"); }
3605
3606  /* last CD or not? Label accordingly */
3607  sprintf (lastcd_fname, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);
3608  if (last_cd)
3609    {
3610      unlink (lastcd_fname);
3611      log_msg (2, "OK, you're telling me this is the last CD. Fair enough.");
3612    }
3613  else
3614    {
3615      fout = fopen (lastcd_fname, "w");
3616      fprintf (fout,
3617           "You're listening to 90.3 WPLN, Nashville Public Radio.\n");
3618      paranoid_fclose (fout);
3619    }
3620  if (space_occupied_by_cd (bkpinfo->scratchdir) / 1024 > bkpinfo->media_size[g_current_media_number])
3621    {
3622      sprintf (tmp,
3623           "Warning! CD is too big. It occupies %ld KB, which is more than the %ld KB allowed.",
3624           (long) space_occupied_by_cd (bkpinfo->scratchdir),
3625           (long) bkpinfo->media_size[g_current_media_number]);
3626      log_to_screen (tmp);
3627    }
3628  sprintf (isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->nfs_remote_dir,
3629           bkpinfo->prefix, g_current_media_number);
3630  for (that_one_was_ok = FALSE; !that_one_was_ok;)
3631    {
3632      res = make_iso_fs (bkpinfo, isofile);
3633      if (g_current_media_number==1 && !res && ( bkpinfo->backup_media_type == cdr || bkpinfo->backup_media_type == cdrw) )
3634        {
3635          if (find_cdrom_device(tmp, FALSE)) // make sure find_cdrom_device() finds, records CD-R's loc
3636            { log_msg(3, "*Sigh* Mike, I hate your computer."); bkpinfo->manual_cd_tray = TRUE; } // if it can't be found then force pausing
3637          else
3638            { log_msg(3, "Great. Found Mike's CD-ROM drive."); }
3639        }
3640      if (bkpinfo->verify_data && !res)
3641    {
3642      log_to_screen
3643        ("Please reboot from the 1st CD in Compare Mode, as a precaution.");
3644      chdir ("/");
3645      iamhere("Before calling verify_cd_image()");
3646      res += verify_cd_image (bkpinfo);
3647      iamhere("After calling verify_cd_image()");
3648    }
3649      if (!res)
3650    {
3651      that_one_was_ok = TRUE;
3652    }
3653      else
3654    {
3655      sprintf (tmp, "Failed to burn %s #%d. Retry?",
3656            media_descriptor_string(bkpinfo->backup_media_type), 
3657           g_current_media_number);
3658      res = ask_me_yes_or_no (tmp);
3659      if (!res)
3660        {
3661          if (ask_me_yes_or_no ("Abort the backup?"))
3662        {
3663          fatal_error ("FAILED TO BACKUP");
3664        }
3665          else
3666        {
3667          break;
3668        }
3669        }
3670      else
3671        {
3672          log_msg (2, "Retrying, at user's request...");
3673          res = 0;
3674        }
3675    }
3676    }
3677/*
3678  if (using_nfs)
3679    {
3680      sprintf(tmp,"mv -f %s %s/%s/", isofile, bkpinfo->isodir, bkpinfo->nfs_remote_dir);
3681      if (run_program_and_log_output(tmp, FALSE))
3682        { log_to_screen("Unable to move ISO to NFS dir"); }
3683    }
3684*/
3685  g_current_media_number++;
3686  if (g_current_media_number > MAX_NOOF_MEDIA) { fatal_error("Too many CD-R(W)'s. Use tape or net."); }
3687  wipe_archives (bkpinfo->scratchdir);
3688  sprintf (tmp, "rm -Rf %s/images/*gz %s/images/*data*img",
3689       bkpinfo->scratchdir, bkpinfo->scratchdir);
3690  if (system (tmp))
3691    {
3692      log_msg
3693    (2, "Error occurred when I tried to delete the redundant IMGs and GZs");
3694    }
3695
3696  if (last_cd)
3697    {
3698      log_msg (2, "This was your last CD.");
3699    }
3700  else
3701    {
3702      log_msg (2, "Continuing to backup your data...");
3703    }
3704
3705  bkpinfo->verify_data = orig_vfy_flag_val;
3706  paranoid_free(tmp);
3707  paranoid_free(cdno_fname);
3708  paranoid_free(lastcd_fname);
3709  paranoid_free(isofile);
3710  return (0);
3711}
3712
3713/* @} - end of LLarchiveGroup */
3714
3715
3716
3717
3718/**
3719 * Verify the user's data.
3720 * @param bkpinfo The backup information structure. Fields used:
3721 * - @c backup_data
3722 * - @c backup_media_type
3723 * - @c media_device
3724 * - @c verify_data
3725 *
3726 * @return The number of errors encountered (0 for success)
3727 * @ingroup verifyGroup
3728 */
3729int verify_data(struct s_bkpinfo *bkpinfo)
3730{
3731    int res=0, retval=0, cdno=0;
3732    char *tmp;
3733    long diffs=0;
3734
3735  malloc_string(tmp);
3736  assert(bkpinfo!=NULL); 
3737      if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3738    {
3739      chdir ("/");
3740      mvaddstr_and_log_it (g_currentY, 0,
3741                   "Verifying archives against live filesystem");
3742      if (bkpinfo->backup_media_type == cdstream)
3743        {
3744          strcpy (bkpinfo->media_device, "/dev/cdrom");
3745        }
3746      verify_tape_backups (bkpinfo);
3747      mvaddstr_and_log_it (g_currentY++, 74, "Done.");
3748    }
3749      else if (bkpinfo->backup_data)
3750    //bkpinfo->backup_media_type == cdrw || bkpinfo->backup_media_type == cdr))
3751        {
3752          log_msg (2, "Not verifying again. Per-CD/ISO verification already carried out.");
3753          paranoid_system("cat /tmp/changed.files.* > /tmp/changed.files 2> /dev/null");
3754        }
3755      else
3756    {
3757          g_current_media_number = cdno;
3758      if (bkpinfo->backup_media_type != iso)
3759        {
3760          find_cdrom_device(bkpinfo->media_device, FALSE); // replace 0,0,0 with /dev/cdrom
3761        }
3762      chdir ("/");
3763      for (cdno = 1;
3764           cdno < 99 && bkpinfo->verify_data;
3765           cdno++)
3766        {
3767          if (cdno != g_current_media_number)
3768            {
3769          log_msg (2, "Warning - had to change g_current_media_number from %d to %d", g_current_media_number, cdno);
3770          g_current_media_number = cdno;
3771        }       
3772          if (bkpinfo->backup_media_type != iso)
3773        {
3774          insist_on_this_cd_number (bkpinfo, cdno);
3775        }
3776          res = verify_cd_image (bkpinfo); // sets verify_data to FALSE if it's time to stop verifying
3777          retval += res;
3778          if (res)
3779        {
3780          sprintf (tmp,
3781               "Warnings/errors were reported while checking %s #%d",
3782               media_descriptor_string(bkpinfo->backup_media_type),
3783               g_current_media_number);
3784          log_to_screen (tmp);
3785
3786        }
3787        }
3788/*
3789      sprintf (tmp,
3790           "cat %s | grep \"afio: \" | cut -d'\"' -f2 | sort -u | awk '{print \"/\"$0;};' | tr -s '/' '/' | grep -vx \"/afio:.*\" > /tmp/changed.files",
3791           MONDO_LOGFILE);
3792      system (tmp);
3793*/
3794          sprintf (tmp,
3795       "cat %s | grep \"afio: \" | sed 's/afio: //' | grep -vx \"/dev/.*\" >> /tmp/changed.files",
3796       MONDO_LOGFILE);
3797      system (tmp);
3798         
3799      sprintf (tmp,
3800       "cat %s | grep \"star: \" | sed 's/star: //' | grep -vx \"/dev/.*\" >> /tmp/changed.files",
3801       MONDO_LOGFILE);
3802      system (tmp);
3803          run_program_and_log_output("umount "MNT_CDROM, FALSE);
3804//    if (bkpinfo->backup_media_type != iso && !bkpinfo->please_dont_eject_when_restoring)
3805//{
3806          eject_device(bkpinfo->media_device);
3807//}
3808    }
3809      diffs = count_lines_in_file ("/tmp/changed.files");
3810
3811      if (diffs > 0)
3812    {
3813          if (retval==0) { retval=(int)(-diffs); }
3814    }
3815  paranoid_free(tmp);
3816 return(retval);
3817}
3818
3819
3820
3821
3822
3823/**
3824 * @addtogroup utilityGroup
3825 * @{
3826 */
3827/**
3828 * Write an image to a real 3.5" floppy disk.
3829 * @param device The device to write to (e.g. @c /dev/fd0)
3830 * @param datafile The image to write to @p device.
3831 * @return The number of errors encountered (0 for success)
3832 * @see write_image_to_floppy
3833 */
3834int
3835write_image_to_floppy_SUB (char *device, char *datafile)
3836{
3837    /*@ int ****************************************************************/
3838  int res = 0;
3839    int percentage = 0;
3840    int blockno = 0;
3841    int maxblocks =0;
3842
3843    /*@ buffers*************************************************************/
3844  char *tmp;
3845    char blk[1024];
3846    char *title;
3847
3848    /*@ pointers ***********************************************************/
3849    char *p;
3850  FILE *fout, *fin;
3851
3852
3853  malloc_string(tmp);
3854  malloc_string(title);
3855  /* pretty stuff */
3856  if (!(p = strrchr (datafile, '/')))
3857    {
3858      p = datafile;
3859    }
3860  else
3861    {
3862      p++;
3863    }
3864  sprintf (title, "Writing %s to floppy", p);
3865  open_evalcall_form (title);
3866  /* functional stuff */
3867  for (p = device + strlen (device); p != device && isdigit (*(p - 1)); p--);
3868  maxblocks = atoi (p);
3869  if (!maxblocks) { maxblocks = 1440; }
3870  sprintf (tmp, "maxblocks = %d; p=%s", maxblocks, p);
3871  log_msg (2, tmp);
3872  /* copy data from image to floppy */
3873  if (!(fin = fopen (datafile, "r")))
3874    {
3875      log_OS_error ("Cannot open img");
3876      return (1);
3877    }
3878  if (!(fout = fopen (device, "w")))
3879    {
3880      log_OS_error ("Cannot open fdd");
3881      return (1);
3882    }
3883  for (blockno = 0; blockno < maxblocks; blockno++)
3884    {
3885      percentage = blockno * 100 / maxblocks;
3886      if (fread (blk, 1, 1024, fin) != 1024)
3887    {
3888      if (feof(fin)) 
3889        {
3890          log_msg(1, "img read err - img ended prematurely - non-fatal error");
3891          sleep(3);
3892          return(res);
3893        }
3894      res++;
3895      log_to_screen ("img read err");
3896    }
3897      if (fwrite (blk, 1, 1024, fout) != 1024)
3898    {
3899      res++;
3900      log_to_screen ("fdd write err");
3901    }
3902      if (((blockno + 1) % 128) == 0)
3903    {
3904      paranoid_system ("sync"); /* fflush doesn't work; dunno why */
3905      update_evalcall_form (percentage);
3906    }
3907    }
3908  paranoid_fclose (fin);
3909  paranoid_fclose(fout);
3910  paranoid_free(tmp);
3911  paranoid_free(title);
3912  close_evalcall_form ();
3913  return (res);
3914}
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924/**
3925 * Wrapper around @c write_image_to_floppy_SUB().
3926 * This function, unlike @c write_image_to_floppy_SUB(),
3927 * gives the user the opportunity to retry if the write fails.
3928 * @see write_image_to_floppy_SUB
3929 */
3930int
3931write_image_to_floppy (char *device, char *datafile)
3932{
3933    /*@ int ***************************************************************/
3934  int res   = 0;
3935
3936  assert_string_is_neither_NULL_nor_zerolength(device);
3937  assert_string_is_neither_NULL_nor_zerolength(datafile);
3938
3939  while ((res = write_image_to_floppy_SUB (device, datafile)))
3940    {
3941      if (!ask_me_yes_or_no ("Failed to write image to floppy. Retry?"))
3942    {
3943      return (res);
3944    }
3945    }
3946  return (res);
3947}
3948
3949/* @} - end of utilityGroup */
3950
Note: See TracBrowser for help on using the repository browser.