source: MondoRescue/trunk/mondo/mondo/common/libmondo-archive.c@ 20

Last change on this file since 20 was 20, checked in by bcornec, 19 years ago

-p option added

File size: 118.7 KB
Line 
1/* libmondo-archive.c
2 $Id: libmondo-archive.c,v 1.19 2004/06/21 20:20:36 hugo Exp $
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,v 1.19 2004/06/21 20:20:36 hugo Exp $";
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-[1-9]*.iso", bkpinfo->prefix, bkpinfo->isodir);
1284 paranoid_system (command);
1285 wipe_archives (bkpinfo->scratchdir);
1286 mvaddstr_and_log_it (g_currentY++, 74, "Done.");
1287 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
1288 {
1289 write_header_block_to_stream (0, "start-of-tape", BLK_START_OF_TAPE);
1290 write_header_block_to_stream (0, "start-of-backup", BLK_START_OF_BACKUP);
1291 }
1292 paranoid_free(command);
1293 paranoid_free(tmpfile);
1294 paranoid_free(data_disks_file);
1295 return (retval);
1296}
1297
1298
1299/**
1300 * Calls floppy-formatting @c cmd and tracks its progress if possible.
1301 *
1302 * @param cmd The command to run (e.g. @c fdformat @c /dev/fd0).
1303 * @param title The human-friendly description of the floppy you are writing.
1304 * This will be used as the title in the progress bar window. Example:
1305 * "Formatting disk /dev/fd0".
1306 * @see format_disk
1307 * @return The exit code of fdformat/superformat.
1308 */
1309int
1310format_disk_SUB (char *cmd, char *title)
1311{
1312
1313 /*@ int ****************************************************************/
1314 int res = 0;
1315 int percentage = 0;
1316 int maxtracks = 0;
1317 int trackno = 0;
1318 int last_trkno = 0;
1319
1320 /*@ buffers ************************************************************/
1321 char *command;
1322 char *tempfile;
1323
1324 /*@ pointers ***********************************************************/
1325 FILE *pin;
1326
1327 assert_string_is_neither_NULL_nor_zerolength(cmd);
1328 assert_string_is_neither_NULL_nor_zerolength(title);
1329
1330 malloc_string(command);
1331 malloc_string(tempfile);
1332#ifdef __FreeBSD__
1333/* Ugh. FreeBSD fdformat prints out this pretty progress indicator that's
1334 impossible to parse. It looks like
1335 VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVF-------------------
1336 where V means verified, E means error, F means formatted, and - means
1337 not done yet.
1338*/
1339 return (run_program_and_log_to_screen (cmd, title));
1340#endif
1341
1342/* if Debian then do bog-standard superformat; don't be pretty */
1343 if (strstr (cmd, "superformat"))
1344 {
1345 return (run_program_and_log_to_screen (cmd, title));
1346 }
1347/* if not Debian then go ahead & use fdformat */
1348 strcpy (tempfile,
1349 call_program_and_get_last_line_of_output
1350 ("mktemp -q /tmp/mondo.XXXXXXXX"));
1351 sprintf (command, "%s >> %s 2>> %s; rm -f %s", cmd, tempfile, tempfile,
1352 tempfile);
1353 log_msg (3, command);
1354 open_evalcall_form (title);
1355 if (!(pin = popen (command, "r")))
1356 {
1357 log_OS_error ("fmt err");
1358 return (1);
1359 }
1360 if (strstr (command, "1722"))
1361 {
1362 maxtracks = 82;
1363 }
1364 else
1365 {
1366 maxtracks = 80;
1367 }
1368 for (sleep (1); does_file_exist (tempfile); sleep (1))
1369 {
1370 trackno = get_trackno_from_logfile (tempfile);
1371 if (trackno < 0 || trackno > 80)
1372 {
1373 log_msg (1, "Weird track#");
1374 continue;
1375 }
1376 percentage = trackno * 100 / maxtracks;
1377 if (trackno <= 5 && last_trkno > 40)
1378 {
1379 close_evalcall_form ();
1380 strcpy (title, "Verifying format");
1381 open_evalcall_form (title);
1382 }
1383 last_trkno = trackno;
1384 update_evalcall_form (percentage);
1385 }
1386 close_evalcall_form ();
1387 if (pclose (pin)) { res++; log_OS_error("Unable to pclose"); }
1388 unlink (tempfile);
1389 paranoid_free(command);
1390 paranoid_free(tempfile);
1391 return (res);
1392}
1393
1394/**
1395 * Wrapper around @c format_disk_SUB().
1396 * This function calls @c format_disk_SUB() with a @c device of its @c device
1397 * parameter and a @c title of Formatting disk @c device. If the format
1398 * fails, the user will be given the option of retrying.
1399 *
1400 * @param device The floppy drive to write to.
1401 * @see format_disk_SUB
1402 * @return The exit code of fdformat/superformat.
1403 * @ingroup deviceGroup
1404 */
1405int
1406format_disk (char *device)
1407{
1408
1409 /*@ int ***************************************************************/
1410 int res = 0;
1411
1412 /*@ buffer ************************************************************/
1413 char *command;
1414 char *title;
1415
1416
1417 assert_string_is_neither_NULL_nor_zerolength(device);
1418 malloc_string(title);
1419 command = malloc(1000);
1420 if (!system ("which superformat > /dev/null 2> /dev/null"))
1421 {
1422 sprintf (command, "superformat %s", device);
1423 }
1424 else
1425 {
1426#ifdef __FreeBSD__
1427 sprintf (command, "fdformat -y %s", device);
1428#else
1429 sprintf (command, "fdformat %s", device);
1430#endif
1431 }
1432 sprintf (title, "Formatting disk %s", device);
1433 while ((res = format_disk_SUB (command, title)))
1434 {
1435 if (!ask_me_yes_or_no ("Failed to format disk. Retry?"))
1436 {
1437 return (res);
1438 }
1439 }
1440 paranoid_free(title);
1441 paranoid_free(command);
1442 return (res);
1443}
1444
1445/**
1446 * Get the <tt>N</tt>th bit of @c array.
1447 * @param array The bit-array (as a @c char pointer).
1448 * @param N The number of the bit you want.
1449 * @return TRUE (bit is set) or FALSE (bit is not set).
1450 * @see set_bit_N_of_array
1451 * @ingroup utilityGroup
1452 */
1453bool get_bit_N_of_array(char*array, int N)
1454{
1455 int element_number;
1456 int bit_number;
1457 int mask;
1458
1459 element_number = N / 8;
1460 bit_number = N % 8;
1461 mask = 1 << bit_number;
1462 if (array[element_number] & mask)
1463 { return(TRUE); }
1464 else
1465 { return(FALSE); }
1466}
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476/**
1477 * @addtogroup LLarchiveGroup
1478 * @{
1479 */
1480/**
1481 * Start up threads to archive your files.
1482 *
1483 * This function starts @c ARCH_THREADS threads,
1484 * each starting execution in @c create_afio_files_in_background().
1485 * Each thread will archive individual filesets, based on the
1486 * pointers passed to it and continually updated, until all files
1487 * have been backed up. This function coordinates the threads
1488 * and copies their output to the @c scratchdir.
1489 *
1490 * @param bkpinfo The backup information structure. Fields used:
1491 * - @c backup_media_type
1492 * - @c scratchdir
1493 * - @c tmpdir
1494 * - @c zip_suffix
1495 *
1496 * @return The number of errors encountered (0 for success)
1497 */
1498int
1499make_afioballs_and_images (struct s_bkpinfo *bkpinfo)
1500{
1501
1502 /*@ int ***************************************************/
1503 int retval = 0;
1504 long int storing_set_no = 0;
1505 int res = 0;
1506 bool done_storing=FALSE;
1507 char *result_str;
1508 char *transfer_block;
1509 void*vp;
1510 void**pvp;
1511
1512 /*@ buffers ***********************************************/
1513 char *storing_filelist_fname;
1514 char *storing_afioball_fname;
1515 char *tmp;
1516 char *media_usage_comment;
1517 pthread_t archival_thread[ARCH_THREADS];
1518 char *p_list_of_fileset_flags;
1519 int *p_archival_threads_running;
1520 int *p_last_set_archived;
1521 int *p_next_set_to_archive;
1522 int noof_threads;
1523 int i;
1524 char *curr_xattr_list_fname;
1525 char *curr_acl_list_fname;
1526 int misc_counter_that_is_not_important=0;
1527
1528 log_msg(8, "here");
1529 assert(bkpinfo!=NULL);
1530 tmp = malloc(MAX_STR_LEN*2);
1531 malloc_string(result_str);
1532 malloc_string(curr_xattr_list_fname);
1533 malloc_string(curr_acl_list_fname);
1534 malloc_string(storing_filelist_fname);
1535 malloc_string(media_usage_comment);
1536 malloc_string(storing_afioball_fname);
1537 transfer_block = malloc(sizeof(struct s_bkpinfo)+BKPINFO_LOC_OFFSET+64);
1538 memset((void*)transfer_block, 0, sizeof(struct s_bkpinfo)+BKPINFO_LOC_OFFSET+64);
1539 p_last_set_archived = (int*)transfer_block;
1540 p_archival_threads_running = (int*)(transfer_block+4);
1541 p_next_set_to_archive = (int*)(transfer_block+8);
1542 p_list_of_fileset_flags = (char*)(transfer_block+12);
1543 memcpy((void*)(transfer_block+BKPINFO_LOC_OFFSET), (void*)bkpinfo, sizeof(struct s_bkpinfo));
1544 pvp=&vp;
1545 vp=(void*)result_str;
1546 *p_archival_threads_running = 0;
1547 *p_last_set_archived = -1;
1548 *p_next_set_to_archive = 0;
1549 sprintf (tmp, "%s/archives/filelist.full", bkpinfo->scratchdir);
1550 log_to_screen ("Archiving regular files");
1551 log_msg (5, "Go, Shorty. It's your birthday.");
1552 open_progress_form ("Backing up filesystem",
1553 "I am backing up your live filesystem now.",
1554 "Please wait. This may take a couple of hours.",
1555 "Working...", get_last_filelist_number (bkpinfo) + 1);
1556
1557 log_msg (5, "We're gonna party like it's your birthday.");
1558
1559 srand((unsigned int)getpid());
1560 g_sem_key = 1234+random()%30000;
1561 if ((g_sem_id = semget((key_t)g_sem_key, 1, IPC_CREAT|S_IREAD|S_IWRITE))==-1)
1562 { fatal_error("MABAI - unable to semget"); }
1563 if (!set_semvalue())
1564 { fatal_error("Unable to init semaphore"); } // initialize semaphore
1565 for(noof_threads=0; noof_threads<ARCH_THREADS; noof_threads++)
1566 {
1567 log_msg(8, "Creating thread #%d", noof_threads);
1568 (*p_archival_threads_running) ++;
1569 if ((res = pthread_create(&archival_thread[noof_threads], NULL, create_afio_files_in_background, (void*)transfer_block)))
1570 { fatal_error("Unable to create an archival thread"); }
1571 }
1572
1573 log_msg(8, "About to enter while() loop");
1574 while(!done_storing)
1575 {
1576 if (g_exiting) { fatal_error("Execution run aborted (main loop)"); }
1577 if (*p_archival_threads_running == 0 && *p_last_set_archived == storing_set_no-1)
1578 {
1579 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);
1580 done_storing = TRUE;
1581 }
1582 else if (!get_bit_N_of_array(p_list_of_fileset_flags, storing_set_no))
1583 {
1584 misc_counter_that_is_not_important = (misc_counter_that_is_not_important+1) % 5;
1585 if (!misc_counter_that_is_not_important)
1586 { update_progress_form (media_usage_comment); }
1587 sleep(1);
1588 }
1589 else
1590 // store set N
1591 {
1592 sprintf (storing_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir,
1593 storing_set_no);
1594 sprintf (storing_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir,
1595 storing_set_no, bkpinfo->zip_suffix);
1596 sprintf (curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, storing_set_no);
1597 sprintf (curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, storing_set_no);
1598
1599 log_msg (2, "Storing set %d", storing_set_no);
1600 while(!does_file_exist(storing_filelist_fname) || !does_file_exist(storing_afioball_fname))
1601 {
1602 log_msg (2, "Warning - either %s or %s doesn't exist yet. I'll pause 5 secs.", storing_filelist_fname, storing_afioball_fname);
1603 sleep(5);
1604 }
1605 strcpy (media_usage_comment, percent_media_full_comment (bkpinfo));
1606 /* copy to CD (scratchdir) ... and an actual CD-R if necessary */
1607 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
1608 {
1609 register_in_tape_catalog(fileset, storing_set_no, -1, storing_afioball_fname);
1610 maintain_collection_of_recent_archives(bkpinfo->tmpdir, storing_afioball_fname);
1611 iamhere("Writing EXAT files");
1612 res += write_EXAT_files_to_tape(bkpinfo, curr_xattr_list_fname, curr_acl_list_fname);
1613// archives themselves
1614 res += move_files_to_stream (bkpinfo, storing_afioball_fname, NULL);
1615 }
1616 else
1617 {
1618 res = move_files_to_cd (bkpinfo, storing_filelist_fname, curr_xattr_list_fname, curr_acl_list_fname, storing_afioball_fname, NULL);
1619 }
1620 retval += res;
1621 g_current_progress++;
1622 update_progress_form (media_usage_comment);
1623 if (res)
1624 {
1625 sprintf (tmp, "Failed to add archive %ld's files to CD dir\n",
1626 storing_set_no);
1627 log_to_screen (tmp);
1628 fatal_error
1629 ("Is your hard disk full? If not, please send the author the logfile.");
1630 }
1631 storing_set_no++;
1632 // sleep(2);
1633 }
1634 }
1635 close_progress_form ();
1636
1637 sprintf (tmp, "Your regular files have been archived ");
1638 log_msg(2, "Joining background threads to foreground thread");
1639 for(i=0; i<noof_threads; i++)
1640 {
1641 pthread_join(archival_thread[i], pvp);
1642 log_msg(3, "Thread %d of %d: closed OK", i+1, noof_threads);
1643 }
1644 del_semvalue();
1645 log_msg (2, "Done.");
1646 if (retval)
1647 {
1648 strcat (tmp, "(with errors).");
1649 }
1650 else
1651 {
1652 strcat (tmp, "successfully.");
1653 }
1654 log_to_screen (tmp);
1655 paranoid_free(transfer_block);
1656 paranoid_free(result_str);
1657 paranoid_free(storing_filelist_fname);
1658 paranoid_free(media_usage_comment);
1659 paranoid_free(storing_afioball_fname);
1660 paranoid_free(curr_xattr_list_fname);
1661 paranoid_free(curr_acl_list_fname);
1662 return (retval);
1663}
1664
1665
1666void pause_for_N_seconds(int how_long, char*msg)
1667{
1668 int i;
1669 open_evalcall_form(msg);
1670 for(i=0; i<how_long; i++)
1671 {
1672 update_evalcall_form((int) ( (100.0/(float)(how_long)*i) ) );
1673 sleep(1);
1674 }
1675 close_evalcall_form();
1676}
1677
1678
1679
1680
1681/**
1682 * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir.
1683 *
1684 * @param bkpinfo The backup information structure. Fields used:
1685 * - @c backup_media_type
1686 * - @c call_after_iso
1687 * - @c call_before_iso
1688 * - @c call_burn_iso
1689 * - @c call_make_iso
1690 * - @c make_cd_use_lilo
1691 * - @c manual_cd_tray
1692 * - @c nonbootable_backup
1693 * - @c scratchdir
1694 *
1695 * @param destfile Where to put the generated ISO image.
1696 * @return The number of errors encountered (0 for success)
1697 */
1698int
1699make_iso_fs (struct s_bkpinfo *bkpinfo, char *destfile)
1700{
1701 /*@ int ***********************************************/
1702 int retval = 0;
1703 int res;
1704
1705 /*@ buffers *******************************************/
1706 char *tmp;
1707 char *old_pwd;
1708 char *result_sz;
1709 char *message_to_screen;
1710 char *sz_blank_disk;
1711 char *fnam;
1712 char *tmp2;
1713 char *tmp3;
1714 bool cd_is_mountable;
1715
1716 malloc_string(old_pwd);
1717 malloc_string(result_sz);
1718 malloc_string(message_to_screen);
1719 malloc_string(sz_blank_disk);
1720 malloc_string(fnam);
1721 tmp = malloc(1200);
1722 tmp2 =malloc(1200);
1723 tmp3 =malloc(1200);
1724 assert(bkpinfo!=NULL);
1725 assert_string_is_neither_NULL_nor_zerolength(destfile);
1726
1727 sprintf(tmp, "%s/isolinux.bin", bkpinfo->scratchdir);
1728 sprintf(tmp2,"%s/isolinux.bin", bkpinfo->tmpdir);
1729 if (does_file_exist(tmp))
1730 {
1731 sprintf(tmp3, "cp -f %s %s", tmp, tmp2);
1732 paranoid_system(tmp3);
1733 }
1734 if (!does_file_exist(tmp) && does_file_exist(tmp2))
1735 {
1736 sprintf(tmp3, "cp -f %s %s", tmp2, tmp);
1737 paranoid_system(tmp3);
1738 }
1739 /*
1740 if (!does_file_exist(tmp))
1741 {
1742 log_msg (2, "Silly bug in Mindi.pl; workaround in progress...");
1743 strcpy(fnam, call_program_and_get_last_line_of_output("locate isolinux.bin | tail -n1"));
1744 if (strlen(fnam)>0 && does_file_exist(fnam))
1745 {
1746 sprintf(tmp, "cp -f %s %s", fnam, bkpinfo->scratchdir);
1747 res = run_program_and_log_output(tmp, FALSE);
1748 }
1749 else
1750 {
1751 res = 1;
1752 }
1753 if (res)
1754 {
1755 log_msg (2, "Could not work around silly bug in Mindi.pl - sorry! Isolinux.bin missing");
1756 }
1757 }
1758 */
1759 free(tmp2);
1760 free(tmp3);
1761 tmp2 = NULL;
1762 tmp3 = NULL;
1763 if (bkpinfo->backup_media_type == iso && bkpinfo->manual_cd_tray)
1764 {
1765 popup_and_OK("Please insert new media and press Enter.");
1766 }
1767
1768 log_msg (2, "make_iso_fs --- scratchdir=%s --- destfile=%s",
1769 bkpinfo->scratchdir, destfile);
1770 (void) getcwd (old_pwd, MAX_STR_LEN - 1);
1771 sprintf (tmp, "chmod 744 %s", bkpinfo->scratchdir);
1772 run_program_and_log_output(tmp, FALSE);
1773 chdir (bkpinfo->scratchdir);
1774
1775 if (bkpinfo->call_before_iso[0] != '\0')
1776 {
1777 sprintf (message_to_screen, "Running pre-ISO call for CD#%d",
1778 g_current_media_number);
1779 res =
1780 eval_call_to_make_ISO (bkpinfo, bkpinfo->call_before_iso, destfile,
1781 g_current_media_number, MONDO_LOGFILE, message_to_screen);
1782 if (res)
1783 {
1784 strcat (message_to_screen, "...failed");
1785 }
1786 else
1787 {
1788 strcat (message_to_screen, "...OK");
1789 }
1790 log_to_screen (message_to_screen);
1791 retval += res;
1792 }
1793
1794 if (bkpinfo->call_make_iso[0] != '\0')
1795 {
1796 log_msg(2, "bkpinfo->call_make_iso = %s", bkpinfo->call_make_iso);
1797 sprintf (tmp, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);
1798 sprintf (message_to_screen, "Making an ISO (%s #%d)",
1799 media_descriptor_string(bkpinfo->backup_media_type),
1800 g_current_media_number);
1801
1802 pause_and_ask_for_cdr (2, &cd_is_mountable); /* if g_current_media_number >= 2 then pause & ask */
1803 if (retval)
1804 {
1805 log_to_screen("Serious error(s) occurred already. I shan't try to write to media.");
1806 }
1807 else
1808 {
1809 res =
1810 eval_call_to_make_ISO (bkpinfo, bkpinfo->call_make_iso, bkpinfo->scratchdir,
1811 g_current_media_number, MONDO_LOGFILE, message_to_screen);
1812 if (res)
1813 {
1814 log_to_screen ("%s...failed to write", message_to_screen);
1815 }
1816 else
1817 {
1818 log_to_screen ("%s...OK", message_to_screen);
1819 if (!run_program_and_log_output("tail -n10 /var/log/mondo-archive.log | fgrep \":-(\"", 1))
1820 {
1821 log_to_screen("Despite nonfatal errors, growisofs confirms the write was successful.");
1822 }
1823 }
1824 retval += res;
1825#ifdef DVDRWFORMAT
1826 sprintf(tmp, "cat %s | tail -n8 | grep \"blank=full.*dvd-compat.*DAO\"", MONDO_LOGFILE);
1827 if (g_backup_media_type == dvd && (res || !run_program_and_log_output(tmp, 1)))
1828 {
1829 log_to_screen("Failed to write to disk. I shall blank it and then try again.");
1830 sleep(5);
1831 system("sync");
1832 pause_for_N_seconds(5, "Letting DVD drive settle");
1833
1834// dvd+rw-format --- OPTION 2
1835 if (!bkpinfo->please_dont_eject)
1836 {
1837 log_to_screen("Ejecting media to clear drive status.");
1838 eject_device(bkpinfo->media_device);
1839 inject_device(bkpinfo->media_device);
1840 }
1841 pause_for_N_seconds(5, "Letting DVD drive settle");
1842 sprintf(sz_blank_disk, "dvd+rw-format %s", bkpinfo->media_device);
1843 log_msg(3, "sz_blank_disk = '%s'", sz_blank_disk);
1844 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
1845 if (res)
1846 {
1847 log_to_screen("Warning - format failed. (Was it a DVD-R?) Sleeping for 5 seconds to take a breath...");
1848 pause_for_N_seconds(5, "Letting DVD drive settle... and trying again.");
1849 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
1850 if (res) { log_to_screen("Format failed a second time."); }
1851 }
1852 else { log_to_screen("Format succeeded. Sleeping for 5 seconds to take a breath..."); }
1853 pause_for_N_seconds(5, "Letting DVD drive settle");
1854 if (!bkpinfo->please_dont_eject)
1855 {
1856 log_to_screen("Ejecting media to clear drive status.");
1857 eject_device(bkpinfo->media_device);
1858 inject_device(bkpinfo->media_device);
1859 }
1860 pause_for_N_seconds(5, "Letting DVD drive settle");
1861 res = eval_call_to_make_ISO (bkpinfo, bkpinfo->call_make_iso, bkpinfo->scratchdir,
1862 g_current_media_number, MONDO_LOGFILE, message_to_screen);
1863 retval += res;
1864 if (!bkpinfo->please_dont_eject)
1865 {
1866 log_to_screen("Ejecting media.");
1867 eject_device(bkpinfo->media_device);
1868 }
1869 if (res)
1870 { log_to_screen("Dagnabbit. It still failed."); }
1871 else
1872 { log_to_screen("OK, this time I successfully backed up to DVD."); }
1873 }
1874#endif
1875 if (g_backup_media_type == dvd && !bkpinfo->please_dont_eject)
1876 { eject_device(bkpinfo->media_device); }
1877 }
1878 }
1879 else
1880 {
1881 sprintf (message_to_screen, "Running mkisofs to make %s #%d",
1882 media_descriptor_string(bkpinfo->backup_media_type),
1883 g_current_media_number);
1884 log_msg (1, message_to_screen);
1885 sprintf (result_sz, "Call to mkisofs to make ISO (%s #%d) ",
1886 media_descriptor_string(bkpinfo->backup_media_type),
1887 g_current_media_number);
1888 if (bkpinfo->nonbootable_backup)
1889 {
1890 log_msg (1, "Making nonbootable backup");
1891// FIXME --- change mkisofs string to MONDO_MKISOFS_NONBOOTABLE and add ' .' at end
1892 res =
1893 eval_call_to_make_ISO (bkpinfo,
1894 "mkisofs -o _ISO_ -r -p MondoRescue -publisher www.mondorescue.org -A Mondo_Rescue_GPL -V _CD#_ .",
1895 destfile, g_current_media_number, MONDO_LOGFILE,
1896 message_to_screen);
1897 }
1898 else
1899 {
1900 log_msg (1, "Making bootable backup");
1901
1902#ifdef __FreeBSD__
1903 bkpinfo->make_cd_use_lilo = TRUE;
1904#endif
1905
1906
1907 log_msg(1, "make_cd_use_lilo is actually %d", bkpinfo->make_cd_use_lilo);
1908 if (bkpinfo->make_cd_use_lilo)
1909 {
1910 log_msg(1, "make_cd_use_lilo = TRUE");
1911// FIXME --- change mkisofs string to MONDO_MKISOFS_REGULAR_SYSLINUX/LILO depending on bkpinfo->make_cd_usE_lilo
1912// and add ' .' at end
1913#ifdef __IA64__
1914 log_msg(1, "IA64 --> elilo");
1915 res =
1916 eval_call_to_make_ISO (bkpinfo,
1917 //-b images/mindi-boot.2880.img
1918 "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#_ .",
1919 destfile, g_current_media_number, MONDO_LOGFILE,
1920 message_to_screen);
1921#else
1922// FIXME --- change mkisofs string to MONDO_MKISOFS_REGULAR_SYSLINUX/LILO depending on bkpinfo->make_cd_usE_lilo
1923// and add ' .' at end
1924 log_msg(1, "Non-ia64 --> lilo");
1925 res =
1926 eval_call_to_make_ISO (bkpinfo,
1927 "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#_ .",
1928 destfile, g_current_media_number, MONDO_LOGFILE,
1929 message_to_screen);
1930#endif
1931 }
1932 else
1933 {
1934 log_msg(1, "make_cd_use_lilo = FALSE");
1935 log_msg(1, "Isolinux");
1936 res =
1937 eval_call_to_make_ISO (bkpinfo,
1938 "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#_ .",
1939 destfile, g_current_media_number, MONDO_LOGFILE,
1940 message_to_screen);
1941 }
1942 }
1943 if (res)
1944 {
1945 strcat (result_sz, "...failed");
1946 }
1947 else
1948 {
1949 strcat (result_sz, "...OK");
1950 }
1951 log_to_screen (result_sz);
1952 retval += res;
1953 }
1954
1955 if (bkpinfo->backup_media_type == cdr || bkpinfo->backup_media_type == cdrw)
1956 {
1957 if (is_this_device_mounted(bkpinfo->media_device))
1958 {
1959 log_msg (2, "Warning - %s mounted. I'm unmounting it before I burn to it.", bkpinfo->media_device);
1960 sprintf(tmp, "umount %s", bkpinfo->media_device);
1961 run_program_and_log_output(tmp, FALSE);
1962 }
1963 }
1964
1965 if (bkpinfo->call_burn_iso[0] != '\0')
1966 {
1967 log_msg (2, "bkpinfo->call_burn_iso = %s", bkpinfo->call_burn_iso);
1968 sprintf (message_to_screen, "Burning %s #%d",
1969 media_descriptor_string(bkpinfo->backup_media_type),
1970 g_current_media_number);
1971 pause_and_ask_for_cdr (2, &cd_is_mountable);
1972 res =
1973 eval_call_to_make_ISO (bkpinfo, bkpinfo->call_burn_iso, destfile,
1974 g_current_media_number, MONDO_LOGFILE, message_to_screen);
1975 if (res)
1976 {
1977 strcat (message_to_screen, "...failed");
1978 }
1979 else
1980 {
1981 strcat (message_to_screen, "...OK");
1982 }
1983 log_to_screen (message_to_screen);
1984 retval += res;
1985 }
1986
1987 if (bkpinfo->call_after_iso[0] != '\0')
1988 {
1989 sprintf (message_to_screen, "Running post-ISO call (%s #%d)",
1990 media_descriptor_string(bkpinfo->backup_media_type),
1991 g_current_media_number);
1992 res =
1993 eval_call_to_make_ISO (bkpinfo, bkpinfo->call_after_iso, destfile,
1994 g_current_media_number, MONDO_LOGFILE, message_to_screen);
1995 if (res)
1996 {
1997 strcat (message_to_screen, "...failed");
1998 }
1999 else
2000 {
2001 strcat (message_to_screen, "...OK");
2002 }
2003 log_to_screen (message_to_screen);
2004 retval += res;
2005 }
2006
2007 chdir (old_pwd);
2008 if (retval)
2009 {
2010 log_msg (1, "WARNING - make_iso_fs returned an error");
2011 }
2012 paranoid_free(old_pwd);
2013 paranoid_free(result_sz);
2014 paranoid_free(message_to_screen);
2015 paranoid_free(sz_blank_disk);
2016 paranoid_free(fnam);
2017 paranoid_free(tmp);
2018 return (retval);
2019}
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029bool is_dev_an_NTFS_dev(char *bigfile_fname)
2030{
2031 char *tmp;
2032 char *command;
2033 malloc_string(tmp);
2034 malloc_string(command);
2035 sprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | strings | head -n1", bigfile_fname);
2036 log_msg(1, "command = '%s'", command);
2037 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2038 log_msg(1, "--> tmp = '%s'", tmp);
2039 if (strstr(tmp, "NTFS"))
2040 { iamhere("TRUE"); return(TRUE); }
2041 else
2042 { iamhere("FALSE"); return(FALSE); }
2043}
2044
2045
2046/**
2047 * Back up big files by chopping them up.
2048 * This function backs up all "big" files (where "big" depends
2049 * on your backup media) in "chunks" (whose size again depends
2050 * on your media).
2051 *
2052 * @param bkpinfo The backup information structure. Fields used:
2053 * - @c backup_media_type
2054 * - @c optimal_set_size
2055 * @param biggielist_fname The path to a file containing a list of
2056 * all "big" files.
2057 * @return The number of errors encountered (0 for success)
2058 * @see slice_up_file_etc
2059 */
2060int
2061make_slices_and_images (struct s_bkpinfo *bkpinfo, char *biggielist_fname)
2062{
2063
2064 /*@ pointers ********************************************/
2065 FILE *fin;
2066 char *p;
2067
2068 /*@ buffers *********************************************/
2069 char *tmp;
2070 char *bigfile_fname;
2071 char *sz_devfile;
2072 char *partimagehack_fifo = NULL;
2073 /*@ long ************************************************/
2074 long biggie_file_number = 0;
2075 long noof_biggie_files = 0;
2076 long estimated_total_noof_slices = 0;
2077
2078 /*@ int *************************************************/
2079 int retval = 0;
2080 int res = 0;
2081 pid_t pid;
2082 FILE*ftmp=NULL;
2083 bool delete_when_done;
2084 bool use_partimagehack;
2085 /*@ long long *******************************************/
2086 long long biggie_fsize;
2087
2088 assert(bkpinfo!=NULL);
2089 assert_string_is_neither_NULL_nor_zerolength(biggielist_fname);
2090
2091 malloc_string(tmp);
2092 malloc_string(bigfile_fname);
2093 malloc_string(sz_devfile);
2094 estimated_total_noof_slices =
2095 size_of_all_biggiefiles_K (bkpinfo) / bkpinfo->optimal_set_size + 1;
2096
2097 log_msg (1, "size of all biggiefiles = %ld",
2098 size_of_all_biggiefiles_K (bkpinfo));
2099 log_msg (1, "estimated_total_noof_slices = %ld KB / %ld KB = %ld",
2100 size_of_all_biggiefiles_K (bkpinfo), bkpinfo->optimal_set_size,
2101 estimated_total_noof_slices);
2102
2103 if (length_of_file (biggielist_fname) < 6)
2104 {
2105 log_msg (1, "No biggiefiles; fair enough...");
2106 return (0);
2107 }
2108 sprintf (tmp, "I am now backing up all large files.");
2109 log_to_screen (tmp);
2110 noof_biggie_files = count_lines_in_file (biggielist_fname);
2111 open_progress_form ("Backing up big files", tmp,
2112 "Please wait. This may take some time.", "",
2113 estimated_total_noof_slices);
2114 if (!(fin = fopen (biggielist_fname, "r"))) { log_OS_error("Unable to openin biggielist"); return(1); }
2115 for (fgets (bigfile_fname, MAX_STR_LEN, fin); !feof (fin);
2116 fgets (bigfile_fname, MAX_STR_LEN, fin), biggie_file_number++)
2117 {
2118 use_partimagehack = FALSE;
2119 if (bigfile_fname[strlen (bigfile_fname) - 1] < 32)
2120 {
2121 bigfile_fname[strlen (bigfile_fname) - 1] = '\0';
2122 }
2123 biggie_fsize = length_of_file (bigfile_fname);
2124 delete_when_done = FALSE;
2125
2126 if (!does_file_exist (bigfile_fname))
2127 {
2128 ftmp = fopen(bigfile_fname, "w");
2129 paranoid_fclose(ftmp);
2130 sprintf (tmp, "bigfile %s was deleted - creating a dummy", bigfile_fname);
2131 delete_when_done = TRUE;
2132 }
2133 else
2134 {
2135// Call partimagehack if it's a /dev entry (i.e. a partition to be imaged)
2136 log_msg (2, "bigfile_fname = %s", bigfile_fname);
2137 use_partimagehack = FALSE;
2138 if (!strncmp ( bigfile_fname, "/dev/", 5) && is_dev_an_NTFS_dev(bigfile_fname))
2139 {
2140 use_partimagehack = TRUE;
2141 log_msg (2, "Calling partimagehack in background because %s is an NTFS partition", bigfile_fname);
2142 sprintf(sz_devfile, "/tmp/%d.%d.000", (int)(random()%32768), (int)(random()%32768));
2143 mkfifo(sz_devfile, 0x770);
2144 partimagehack_fifo = sz_devfile;
2145 switch(pid=fork())
2146 {
2147 case -1: fatal_error("Fork failure");
2148 case 0:
2149 log_msg (2, "CHILD - fip - calling feed_into_partimage(%s, %s)", bigfile_fname, sz_devfile);
2150 res=feed_into_partimage(bigfile_fname, sz_devfile);
2151 exit(res);
2152 break;
2153 default:
2154 log_msg (2, "feed_into_partimage() called in background --- pid=%ld", (long int)(pid));
2155 }
2156 }
2157// Otherwise, use good old 'dd' and 'bzip2'
2158 else
2159 {
2160 sz_devfile[0] = '\0';
2161 partimagehack_fifo = NULL;
2162 }
2163
2164// Whether partition or biggiefile, just do your thang :-)
2165 sprintf (tmp, "Bigfile #%ld is '%s' (%ld KB)", biggie_file_number+1,
2166 bigfile_fname, (long) biggie_fsize >> 10);
2167 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2168 {
2169 write_header_block_to_stream (biggie_fsize, bigfile_fname,
2170 use_partimagehack?BLK_START_A_PIHBIGGIE:BLK_START_A_NORMBIGGIE);
2171 }
2172 res =
2173 slice_up_file_etc (bkpinfo, bigfile_fname, partimagehack_fifo,
2174 biggie_file_number, noof_biggie_files, use_partimagehack);
2175 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2176 {
2177 write_header_block_to_stream (0,
2178 calc_checksum_of_file
2179 (bigfile_fname), BLK_STOP_A_BIGGIE);
2180 }
2181 retval += res;
2182 p = strrchr (bigfile_fname, '/');
2183 if (p)
2184 {
2185 p++;
2186 }
2187 else
2188 {
2189 p = bigfile_fname;
2190 }
2191 sprintf (tmp, "Archiving %s ... ", bigfile_fname);
2192 if (res)
2193 {
2194 strcat (tmp, "Failed!");
2195 }
2196 else
2197 {
2198 strcat (tmp, "OK");
2199 }
2200 if (delete_when_done)
2201 { unlink(bigfile_fname); delete_when_done=FALSE; }
2202 }
2203#ifndef _XWIN
2204 if (!g_text_mode) { newtDrawRootText (0, g_noof_rows - 2, tmp); newtRefresh (); }
2205#endif
2206 }
2207 log_msg (1, "Finished backing up bigfiles");
2208 log_msg (1, "estimated slices = %ld; actual slices = %ld",
2209 estimated_total_noof_slices, g_current_progress);
2210 close_progress_form ();
2211 paranoid_fclose(fin);
2212 paranoid_free(tmp);
2213 paranoid_free(bigfile_fname);
2214 paranoid_free(sz_devfile);
2215 return (retval);
2216}
2217
2218
2219
2220
2221/**
2222 * Single-threaded version of @c make_afioballs_and_images().
2223 * @see make_afioballs_and_images
2224 */
2225int
2226make_afioballs_and_images_OLD (struct s_bkpinfo *bkpinfo)
2227{
2228
2229 /*@ int ***************************************************/
2230 int retval = 0;
2231 long int curr_set_no = 0;
2232 int res = 0;
2233
2234 /*@ buffers ***********************************************/
2235 char *curr_filelist_fname;
2236 char *curr_afioball_fname;
2237 char *curr_xattr_list_fname;
2238 char *curr_acl_list_fname;
2239 char *tmp;
2240 char *media_usage_comment;
2241
2242 malloc_string(curr_afioball_fname);
2243 malloc_string(media_usage_comment);
2244 malloc_string(curr_filelist_fname);
2245 malloc_string(curr_xattr_list_fname);
2246 malloc_string(curr_acl_list_fname);
2247
2248 tmp = malloc(MAX_STR_LEN*2);
2249
2250 sprintf (tmp, "%s/archives/filelist.full", bkpinfo->scratchdir);
2251
2252 log_to_screen ("Archiving regular files");
2253
2254 open_progress_form ("Backing up filesystem",
2255 "I am backing up your live filesystem now.",
2256 "Please wait. This may take a couple of hours.",
2257 "Working...", get_last_filelist_number (bkpinfo) + 1);
2258
2259 sprintf (curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);
2260
2261 for (curr_set_no = 0; does_file_exist (curr_filelist_fname);
2262 sprintf (curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir,
2263 ++curr_set_no))
2264 {
2265 /* backup this set of files */
2266 sprintf (curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);
2267 sprintf (curr_afioball_fname, AFIOBALL_FNAME_RAW_SZ,bkpinfo->tmpdir,
2268 curr_set_no, bkpinfo->zip_suffix);
2269
2270 log_msg (1, "EXAT'g set %ld", curr_set_no);
2271 sprintf (curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);
2272 sprintf (curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);
2273 get_fattr_list(curr_filelist_fname, curr_xattr_list_fname);
2274 get_acl_list(curr_filelist_fname, curr_acl_list_fname);
2275
2276 log_msg (1, "Archiving set %ld", curr_set_no);
2277 res =
2278 archive_this_fileset (bkpinfo, curr_filelist_fname, curr_afioball_fname, curr_set_no);
2279 retval += res;
2280 if (res)
2281 {
2282 sprintf (tmp,
2283 "Errors occurred while archiving set %ld. Perhaps your live filesystem changed?",
2284 curr_set_no);
2285 log_to_screen (tmp);
2286 }
2287
2288 strcpy (media_usage_comment, percent_media_full_comment (bkpinfo));
2289
2290 /* copy to CD (scratchdir) ... and an actual CD-R if necessary */
2291 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2292 {
2293 register_in_tape_catalog(fileset, curr_set_no, -1, curr_afioball_fname);
2294 maintain_collection_of_recent_archives(bkpinfo->tmpdir, curr_afioball_fname);
2295 iamhere("Writing EXAT files");
2296 res += write_EXAT_files_to_tape(bkpinfo, curr_xattr_list_fname, curr_acl_list_fname);
2297// archives themselves
2298 res = move_files_to_stream (bkpinfo, curr_afioball_fname, NULL);
2299 }
2300 else
2301 {
2302 res = move_files_to_cd (bkpinfo, curr_filelist_fname, curr_xattr_list_fname, curr_acl_list_fname, curr_afioball_fname, NULL);
2303 }
2304 retval += res;
2305 g_current_progress++;
2306 update_progress_form (media_usage_comment);
2307
2308 if (res)
2309 {
2310 sprintf (tmp, "Failed to add archive %ld's files to CD dir\n",
2311 curr_set_no);
2312 log_to_screen (tmp);
2313 fatal_error
2314 ("Is your hard disk is full? If not, please send the author the logfile.");
2315 }
2316 }
2317 close_progress_form ();
2318 sprintf (tmp, "Your regular files have been archived ");
2319 if (retval)
2320 {
2321 strcat (tmp, "(with errors).");
2322 }
2323 else
2324 {
2325 strcat (tmp, "successfully.");
2326 }
2327 log_to_screen (tmp);
2328 paranoid_free(tmp);
2329 paranoid_free(curr_filelist_fname);
2330 paranoid_free(curr_afioball_fname);
2331 paranoid_free(media_usage_comment);
2332 paranoid_free(curr_xattr_list_fname);
2333 paranoid_free(curr_acl_list_fname);
2334 return (retval);
2335}
2336
2337/* @} - end of LLarchiveGroup */
2338
2339
2340/**
2341 * Wrapper around @c make_afioballs_and_images().
2342 * @param bkpinfo the backup information structure. Only the
2343 * @c backup_media_type field is used within this function.
2344 * @return return code of make_afioballs_and_images
2345 * @see make_afioballs_and_images
2346 * @ingroup MLarchiveGroup
2347 */
2348int
2349make_those_afios_phase (struct s_bkpinfo *bkpinfo)
2350{
2351 /*@ int ********************************************/
2352 int res = 0;
2353 int retval = 0;
2354
2355 assert(bkpinfo!=NULL);
2356
2357 mvaddstr_and_log_it (g_currentY, 0, "Archiving regular files to media ");
2358
2359 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2360 {
2361 write_header_block_to_stream (0, "start-of-afioballs",
2362 BLK_START_AFIOBALLS);
2363#if __FreeBSD__ == 5
2364 log_msg (1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0");
2365 res = make_afioballs_and_images_OLD (bkpinfo);
2366#else
2367 res = make_afioballs_and_images_OLD (bkpinfo);
2368#endif
2369 write_header_block_to_stream (0, "stop-afioballs", BLK_STOP_AFIOBALLS);
2370 }
2371 else
2372 {
2373 res = make_afioballs_and_images (bkpinfo);
2374 }
2375
2376 retval += res;
2377 if (res)
2378 {
2379 mvaddstr_and_log_it (g_currentY++, 74, "Errors.");
2380 log_msg (1, "make_afioballs_and_images returned an error");
2381 }
2382 else
2383 {
2384 mvaddstr_and_log_it (g_currentY++, 74, "Done.");
2385 }
2386 return (retval);
2387}
2388
2389/**
2390 * Wrapper around @c make_slices_and_images().
2391 * @param bkpinfo The backup information structure. Fields used:
2392 * - @c backup_media_type
2393 * - @c scratchdir
2394 * - @c tmpdir
2395 * @return The number of errors encountered (0 for success)
2396 * @ingroup MLarchiveGroup
2397 */
2398int
2399make_those_slices_phase (struct s_bkpinfo *bkpinfo)
2400{
2401
2402 /*@ int ******************************************************/
2403 int res = 0;
2404 int retval = 0;
2405
2406 /*@ buffers ***************************************************/
2407 char *biggielist;
2408 char *command;
2409 char *blah;
2410 char *xattr_fname;
2411 char *acl_fname;
2412
2413 assert(bkpinfo!=NULL);
2414 /* slice big files */
2415 malloc_string(blah);
2416 malloc_string(biggielist);
2417 malloc_string(xattr_fname);
2418 malloc_string(acl_fname);
2419 command = malloc(1200);
2420 mvaddstr_and_log_it (g_currentY, 0, "Archiving large files to media ");
2421 sprintf (biggielist, "%s/archives/biggielist.txt", bkpinfo->scratchdir);
2422 sprintf (xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2423 sprintf (acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2424
2425 sprintf (command, "cp %s/biggielist.txt %s", bkpinfo->tmpdir, biggielist);
2426 paranoid_system(command);
2427 sprintf (blah, "biggielist = %s", biggielist);
2428 log_msg (2, blah);
2429
2430 if (!does_file_exist (biggielist))
2431 {
2432 log_msg (1, "BTW, the biggielist does not exist");
2433 }
2434
2435 get_fattr_list(biggielist, xattr_fname);
2436 get_acl_list(biggielist, acl_fname);
2437 sprintf (command, "cp %s %s/archives/", xattr_fname, bkpinfo->scratchdir);
2438 paranoid_system(command);
2439 sprintf (command, "cp %s %s/archives/", acl_fname, bkpinfo->scratchdir);
2440 paranoid_system(command);
2441
2442 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2443 {
2444 res += write_EXAT_files_to_tape(bkpinfo, xattr_fname, acl_fname);
2445 sprintf (blah, "%ld", count_lines_in_file (biggielist));
2446 write_header_block_to_stream (0, blah, BLK_START_BIGGIEFILES);
2447 }
2448 res = make_slices_and_images (bkpinfo, biggielist);
2449 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2450 {
2451 write_header_block_to_stream (0, "end-of-biggiefiles",
2452 BLK_STOP_BIGGIEFILES);
2453 }
2454 retval += res;
2455 if (res)
2456 {
2457 log_msg (1, "make_slices_and_images returned an error");
2458 mvaddstr_and_log_it (g_currentY++, 74, "Errors.");
2459 }
2460 else
2461 {
2462 mvaddstr_and_log_it (g_currentY++, 74, "Done.");
2463 }
2464 paranoid_free(blah);
2465 paranoid_free(biggielist);
2466 paranoid_free(command);
2467 paranoid_free(xattr_fname);
2468 paranoid_free(acl_fname);
2469 return (retval);
2470}
2471
2472
2473
2474/**
2475 * @addtogroup LLarchiveGroup
2476 * @{
2477 */
2478/**
2479 * Function pointer to an appropriate @c move_files_to_cd routine.
2480 * You can set this to your own function (for example, one to
2481 * transfer files over the network) or leave it as is.
2482 */
2483int (*move_files_to_cd) (struct s_bkpinfo *, char *, ...) = _move_files_to_cd;
2484
2485/**
2486 * Move some files to the ISO scratch directory.
2487 * This function moves files specified as parameters, into the directory
2488 * @c bkpinfo->scratchdir, where the files that will be stored on the next
2489 * CD are waiting.
2490 *
2491 * @param bkpinfo The backup information structure. Fields used:
2492 * - @c media_size
2493 * - @c scratchdir
2494 * @param files_to_add The files to add to the scratchdir.
2495 * @warning The list of @c files_to_add must be terminated with @c NULL.
2496 * @note If and when the space occupied by the scratchdir would exceed
2497 * the capacity of the current CD,
2498 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the
2499 * scratchdir is emptied.
2500 *
2501 * @return The number of errors encountered (0 for success)
2502 */
2503int
2504_move_files_to_cd (struct s_bkpinfo *bkpinfo,
2505 char *files_to_add, ...)
2506{
2507
2508 /*@ int *************************************************************/
2509 int retval = 0;
2510 int res = 0;
2511
2512 /*@ buffers *********************************************************/
2513 char *tmp,
2514 *curr_file, *cf;
2515
2516 /*@ long *************************************************************/
2517 va_list ap;
2518 long long would_occupy;
2519
2520 assert(bkpinfo!=NULL);
2521 malloc_string(curr_file);
2522 tmp = malloc(1200);
2523 would_occupy = space_occupied_by_cd (bkpinfo->scratchdir);
2524 va_start(ap, files_to_add); // initialize the variable arguments
2525 for(cf = files_to_add; cf!=NULL; cf=va_arg(ap, char*))
2526 {
2527 if (!cf) {continue;}
2528 strcpy(curr_file, cf);
2529 if (!does_file_exist (curr_file))
2530 {
2531 log_msg (1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file);
2532 }
2533 else
2534 {
2535 log_msg (8, "Trying to add file %s to CD", curr_file);
2536 would_occupy += length_of_file (curr_file) / 1024;
2537 }
2538 }
2539 va_end(ap);
2540
2541 if (bkpinfo->media_size[g_current_media_number]<=0) { fatal_error( "move_files_to_cd() - unknown media size"); }
2542 if (would_occupy / 1024 > bkpinfo->media_size[g_current_media_number])
2543 {
2544 res = write_iso_and_go_on (bkpinfo, FALSE); /* FALSE because this is not the last CD we'll write */
2545 retval += res;
2546 if (res)
2547 {
2548 log_msg (1, "WARNING - write_iso_and_go_on returned an error");
2549 }
2550 }
2551
2552 va_start(ap, files_to_add); // initialize the variable arguments
2553 for(cf = files_to_add; cf!=NULL; cf=va_arg(ap, char*))
2554 {
2555 if (!cf) {continue;}
2556 strcpy(curr_file, cf);
2557
2558 sprintf (tmp, "mv -f %s %s/archives/", curr_file,
2559 bkpinfo->scratchdir);
2560 res = run_program_and_log_output (tmp, 5);
2561 retval += res;
2562 if (res)
2563 {
2564 log_msg (1, "(move_files_to_cd) '%s' failed", tmp);
2565 }
2566 else
2567 {
2568 log_msg (8, "Moved %s to CD OK", tmp);
2569 }
2570 // unlink (curr_file);
2571 }
2572 va_end(ap);
2573
2574 if (retval)
2575 {
2576 log_msg (1, "Warning - errors occurred while I was adding files to CD dir");
2577 }
2578 paranoid_free(tmp);
2579 paranoid_free(curr_file);
2580 return (retval);
2581}
2582
2583/* @} - end of LLarchiveGroup */
2584
2585
2586
2587
2588
2589
2590
2591
2592/**
2593 * Offer to write boot and data disk images to 3.5" floppy disks.
2594 * @param bkpinfo The backup information structure. Only the
2595 * @c backup_media_type field is used in this function.
2596 * @param imagesdir The directory containing the floppy images (usually
2597 * /root/images/mindi).
2598 *
2599 * @return The number of errors encountered (0 for success)
2600 * @see write_image_to_floppy
2601 * @see format_disk
2602 * @ingroup MLarchiveGroup
2603 */
2604int
2605offer_to_write_floppies (struct s_bkpinfo *bkpinfo, char *imagesdir)
2606{
2607 /*@ buffer *************************************************************/
2608 char *tmp;
2609 char *comment;
2610 char *bootdisk_dev;
2611 char *datadisk_dev;
2612 char *bootdisk_file;
2613 char *rootdisk_file;
2614
2615 /*@ int ****************************************************************/
2616 int i = 0;
2617 int res = 0;
2618
2619 /*@ bool ***************************************************************/
2620 bool format_first;
2621 bool root_disk_exists=FALSE;
2622
2623 malloc_string(tmp);
2624 malloc_string(comment);
2625 malloc_string(bootdisk_dev);
2626 malloc_string(datadisk_dev);
2627 malloc_string(rootdisk_file);
2628 malloc_string(bootdisk_file);
2629 assert(bkpinfo!=NULL);
2630 assert_string_is_neither_NULL_nor_zerolength(imagesdir);
2631
2632
2633 if (!ask_me_yes_or_no
2634 ("Write boot and data disk images to 3.5\" floppy disks?"))
2635 {
2636 return (0);
2637 }
2638 if (does_device_exist (DEFAULT_1722MB_DISK))
2639 {
2640#ifdef __FreeBSD__
2641 // tell the system that this is a 1.72m floppy
2642 system ("/usr/sbin/fdcontrol -F 1722 /dev/fd0.1722");
2643#endif
2644 strcpy (bootdisk_dev, DEFAULT_1722MB_DISK);
2645 }
2646 else if (does_device_exist (BACKUP_1722MB_DISK))
2647 {
2648 sprintf (bootdisk_dev, "/dev/fd0H1722");
2649 }
2650 else
2651 {
2652 log_msg( 1, "Warning - can't find a 1.72MB floppy device *sigh*" );
2653 strcpy(bootdisk_dev, DEFAULT_1722MB_DISK);
2654// return (1);
2655 }
2656 strcpy (datadisk_dev, "/dev/fd0");
2657 if (!does_device_exist (datadisk_dev))
2658 {
2659 log_msg( 1, "Warning - can't find a 1.44MB floppy device *sigh*" );
2660 strcpy(datadisk_dev, "/dev/fd0");
2661// return (1);
2662 }
2663 format_first =
2664 ask_me_yes_or_no
2665 ("Do you want me to format the disks before I write to them?");
2666
2667/* boot disk */
2668 if (ask_me_OK_or_cancel ("About to write boot disk"))
2669 {
2670 log_to_screen ("Writing boot floppy");
2671#ifdef __FreeBSD__
2672 sprintf (tmp, "%s/mindi-kern.1722.img", imagesdir);
2673 if (format_first) { format_disk (bootdisk_dev); }
2674 res += write_image_to_floppy (bootdisk_dev, tmp);
2675 if (ask_me_OK_or_cancel ("About to write 1.44MB mfsroot disk"))
2676 {
2677 log_to_screen ("Writing mfsroot floppy");
2678 if (format_first) { format_disk (datadisk_dev); }
2679 sprintf (tmp, "%s/mindi-mfsroot.1440.img", imagesdir);
2680 write_image_to_floppy (datadisk_dev, tmp);
2681 }
2682#else
2683 sprintf (bootdisk_file, "%s/mindi-bootroot.1722.img", imagesdir);
2684 if (does_file_exist(bootdisk_file))
2685 {
2686 if (format_first) { format_disk (bootdisk_dev); }
2687 res += write_image_to_floppy (bootdisk_dev, bootdisk_file);
2688 }
2689 else
2690 {
2691 sprintf (bootdisk_file, "%s/mindi-boot.1440.img", imagesdir);
2692 sprintf (rootdisk_file, "%s/mindi-root.1440.img", imagesdir);
2693 root_disk_exists = TRUE;
2694 if (!does_file_exist(rootdisk_file) || !does_file_exist(bootdisk_file))
2695 {
2696 popup_and_OK("Cannot write boot/root floppies. Files not found.");
2697 log_to_screen("Failed to find boot/root floppy images. Oh dear.");
2698 return(1);
2699 }
2700 if (format_first) { format_disk (datadisk_dev); }
2701 /*
2702 sprintf(tmp, "cat %s > %s", bootdisk_file, datadisk_dev);
2703 res += run_external_binary_with_percentage_indicator_NEW("Writing boot floppy", tmp);
2704 */
2705 res += write_image_to_floppy (datadisk_dev, bootdisk_file);
2706 if (ask_me_OK_or_cancel ("About to write root disk"))
2707 {
2708 log_to_screen ("Writing root floppy");
2709 if (format_first) { format_disk (datadisk_dev); }
2710 sprintf(tmp, "cat %s > %s", rootdisk_file, datadisk_dev);
2711 log_msg(1, "tmp = '%s'", tmp);
2712 res += run_external_binary_with_percentage_indicator_NEW("Writing root floppy", tmp);
2713// res += write_image_to_floppy (datadisk_dev, rootdisk_file);
2714 }
2715 }
2716#endif
2717 }
2718 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
2719 {
2720 log_to_screen
2721 ("FYI, the data disks are stored on tape/CD for your convenience.");
2722 return (0);
2723 }
2724 for (i = 1; i < 99; i++)
2725 {
2726 sprintf (tmp, "%s/mindi-data-%d.img", imagesdir, i);
2727 log_msg (3, tmp);
2728 if (!does_file_exist (tmp))
2729 {
2730 log_msg (3, "...not found");
2731 break;
2732 }
2733 sprintf (comment, "About to write data disk #%d", i);
2734 if (ask_me_OK_or_cancel (comment))
2735 {
2736 sprintf (comment, "Writing data disk #%3d", i);
2737 log_to_screen (comment);
2738 if (format_first)
2739 {
2740 res += format_disk (datadisk_dev);
2741 }
2742 res += write_image_to_floppy (datadisk_dev, tmp);
2743 }
2744 }
2745 paranoid_free(tmp);
2746 paranoid_free(comment);
2747 paranoid_free(bootdisk_dev);
2748 paranoid_free(datadisk_dev);
2749 return (res);
2750}
2751
2752
2753
2754
2755
2756
2757
2758
2759/**
2760 * Wrapper around @c offer_to_write_floppies().
2761 * @param bkpinfo The backup information structure. Used only
2762 * in the call to @c offer_to_write_floppies().
2763 * @return 0 if the boot floppies were found (not necessarily written OK),
2764 * 1 otherwise.
2765 * @see offer_to_write_floppies
2766 * @ingroup MLarchiveGroup
2767 */
2768
2769int offer_to_write_boot_floppies_to_physical_disks(struct s_bkpinfo *bkpinfo)
2770{
2771int res=0;
2772
2773 assert(bkpinfo!=NULL);
2774
2775 mvaddstr_and_log_it (g_currentY, 0,
2776 "Writing boot+data floppy images to disk");
2777
2778 if (!bkpinfo->nonbootable_backup) {
2779#ifdef __FreeBSD__
2780 if (!does_file_exist ("/root/images/mindi/mindi-kern.1722.img"))
2781#else
2782 if (!does_file_exist ("/root/images/mindi/mindi-bootroot.1722.img") &&
2783 !does_file_exist ("/root/images/mindi/mindi-boot.1440.img"))
2784#endif
2785 {
2786 mvaddstr_and_log_it (g_currentY++, 74, "No Imgs");
2787 if (does_file_exist ("/root/images/mindi/mondorescue.iso"))
2788 {
2789 popup_and_OK
2790 ("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.");
2791 res++;
2792 }
2793 }
2794 else
2795 {
2796 offer_to_write_floppies (bkpinfo, "/root/images/mindi");
2797 mvaddstr_and_log_it (g_currentY++, 74, "Done.");
2798 }
2799 } else {
2800 popup_and_OK ("Since you opted for a nonbootable backup, no boot floppies were created.");
2801 }
2802
2803 return(res);
2804}
2805
2806
2807
2808
2809/**
2810 * @addtogroup LLarchiveGroup
2811 * @{
2812 */
2813/**
2814 * Function pointer to an appropriate @c move_files_to_stream routine.
2815 * You can set this to your own function (for example, one to
2816 * transfer files over the network) or leave it as is.
2817 */
2818int (*move_files_to_stream) (struct s_bkpinfo *, char *, ...) = _move_files_to_stream;
2819
2820/**
2821 * Copy some files to tape.
2822 * This function copies the files specified as parameters into the tape stream.
2823 *
2824 * @param bkpinfo The backup information structure. Used only in the call to
2825 * @c write_file_to_stream_from_file().
2826 *
2827 * @param files_to_add The files to copy to the tape stream.
2828 * @warning The list of @c files_to_add must be terminated with @c NULL.
2829 * @note Files may be split across multiple tapes if necessary.
2830 *
2831 * @return The number of errors encountered (0 for success)
2832 */
2833int
2834_move_files_to_stream (struct s_bkpinfo *bkpinfo,
2835 char *files_to_add, ...)
2836{
2837
2838 /*@ int *************************************************************/
2839 int retval = 0;
2840 int res = 0;
2841 /*@ buffers *********************************************************/
2842
2843 /*@ char ************************************************************/
2844 char start_chr;
2845 char stop_chr;
2846 char *curr_file, *cf;
2847 /*@ long long *******************************************************/
2848 long long length_of_incoming_file = 0;
2849 t_archtype type;
2850 va_list ap;
2851
2852 assert(bkpinfo!=NULL);
2853 malloc_string(curr_file);
2854 va_start(ap, files_to_add);
2855 for(cf = files_to_add; cf!=NULL; cf=va_arg(ap, char*))
2856 {
2857 if (!cf) {continue;}
2858 strcpy(curr_file, cf);
2859 if (!does_file_exist (curr_file))
2860 {
2861 log_msg (1,
2862 "Warning - you're trying to add a non-existent file - '%s' to the tape",
2863 curr_file);
2864 }
2865/* create header chars */
2866 start_chr = BLK_START_AN_AFIO_OR_SLICE;
2867 stop_chr = BLK_STOP_AN_AFIO_OR_SLICE;
2868/* ask for new tape if necessary */
2869 length_of_incoming_file = length_of_file (curr_file);
2870 write_header_block_to_stream (length_of_incoming_file, curr_file,
2871 start_chr);
2872 if (strstr(curr_file, ".afio.") || strstr(curr_file, ".star."))
2873 { type = fileset; }
2874 else if (strstr(curr_file, "slice"))
2875 { type = biggieslice; }
2876 else
2877 { type = other; }
2878 res = write_file_to_stream_from_file (bkpinfo, curr_file);
2879 retval += res;
2880 unlink (curr_file);
2881/* write closing header */
2882 write_header_block_to_stream (0, "finished-writing-file", stop_chr);
2883 }
2884 va_end(ap);
2885
2886 if (retval)
2887 {
2888 log_msg (1, "Warning - errors occurred while I was adding file to tape");
2889 }
2890 paranoid_free(curr_file);
2891 return (retval);
2892}
2893
2894/* @} - end of LLarchiveGroup */
2895
2896
2897
2898/**
2899 * @addtogroup utilityGroup
2900 * @{
2901 */
2902/**
2903 * Make sure the user has a valid CD-R(W) in the CD drive.
2904 * @param cdrw_dev Set to the CD-R(W) device checked.
2905 * @param keep_looping If TRUE, keep pestering user until they insist
2906 * or insert a correct CD; if FALSE, only check once.
2907 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't).
2908 */
2909int interrogate_disk_currently_in_cdrw_drive(char*cdrw_dev, bool keep_looping)
2910{
2911 char *tmp;
2912 int res=0;
2913 char *bkp;
2914 char *cdrecord;
2915
2916 malloc_string(tmp);
2917 malloc_string(bkp);
2918 malloc_string(cdrecord);
2919 strcpy(bkp, cdrw_dev);
2920 if (find_cdrw_device(cdrw_dev))
2921 {
2922 strcpy(cdrw_dev, bkp);
2923 }
2924 else
2925 {
2926 if (!system("which cdrecord > /dev/null 2> /dev/null"))
2927 { sprintf(cdrecord, "cdrecord dev=%s -atip", cdrw_dev); }
2928 else if (!system("which dvdrecord > /dev/null 2> /dev/null"))
2929 { sprintf(cdrecord, "cdrecord dev=%s -atip", cdrw_dev); }
2930 else
2931 { cdrecord[0] = '\0'; log_msg(2, "Oh well. I guess I'll just pray then."); }
2932 if (cdrecord[0])
2933 {
2934 if (!keep_looping)
2935 {
2936 retract_CD_tray_and_defeat_autorun();
2937 res = run_program_and_log_output(cdrecord, 5);
2938 }
2939 else
2940 {
2941 while((res=run_program_and_log_output(cdrecord, 5)))
2942 {
2943 retract_CD_tray_and_defeat_autorun();
2944 if (ask_me_yes_or_no("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?"))
2945 { log_msg(1, "Well, he insisted..."); break; }
2946 }
2947 }
2948 }
2949 }
2950// retract_CD_tray_and_defeat_autorun();
2951 paranoid_free(tmp);
2952 paranoid_free(cdrecord);
2953 paranoid_free(bkp);
2954 return(res);
2955}
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965/**
2966 * Asks the user to put a CD-R(W) in the drive.
2967 * @param ask_for_one_if_more_than_this (unused)
2968 * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.
2969 */
2970void
2971pause_and_ask_for_cdr (int ask_for_one_if_more_than_this, bool*pmountable)
2972{
2973
2974 /*@ buffers **********************************************/
2975 char *tmp;
2976 char *szmsg;
2977 char *cdrom_dev;
2978 char *cdrw_dev;
2979 char *our_serial_str;
2980 bool ok_go_ahead_burn_it;
2981 int cd_number = -1;
2982 int attempt_to_mount_returned_this=999;
2983 char *mtpt;
2984 char *szcdno;
2985 char *szserfname;
2986 char *szunmount;
2987
2988 malloc_string(tmp);
2989 malloc_string(szmsg);
2990 malloc_string(cdrom_dev);
2991 malloc_string(cdrw_dev);
2992 malloc_string(mtpt);
2993 malloc_string(szcdno);
2994 malloc_string(szserfname);
2995 malloc_string(our_serial_str);
2996 malloc_string(szunmount);
2997
2998 sprintf(szmsg, "I am about to burn %s #%d", media_descriptor_string(g_backup_media_type), g_current_media_number);
2999 log_to_screen(szmsg);
3000 if (g_current_media_number < ask_for_one_if_more_than_this)
3001 { return; }
3002 log_to_screen("Scanning CD-ROM drive...");
3003 sprintf(mtpt, "/tmp/cd.mtpt.%ld.%ld", (long int)random(), (long int)random());
3004 make_hole_for_dir(mtpt);
3005
3006gotos_make_me_puke:
3007 ok_go_ahead_burn_it = TRUE;
3008 if (!find_cdrom_device(cdrom_dev, FALSE))
3009 {
3010/* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird
3011 log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );
3012 retract_CD_tray_and_defeat_autorun();
3013*/
3014 sprintf(tmp, "umount %s", cdrom_dev);
3015 run_program_and_log_output(tmp, 1);
3016 sprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);
3017 sprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);
3018 sprintf(szunmount, "umount %s", mtpt);
3019 cd_number = -1;
3020 our_serial_str[0] = '\0';
3021 sprintf(tmp, "mount %s %s", cdrom_dev, mtpt);
3022 if ((attempt_to_mount_returned_this=run_program_and_log_output(tmp, 1)))
3023 {
3024 log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);
3025 log_to_screen("If there's a CD/DVD in the drive, it's blank.");
3026 /*
3027 if (interrogate_disk_currently_in_cdrw_drive(cdrw_dev, FALSE))
3028 {
3029 ok_go_ahead_burn_it = FALSE;
3030 log_to_screen("There isn't a writable CD/DVD in the drive.");
3031 }
3032 else
3033 {
3034 log_to_screen("Confirmed. There is a blank CD/DVD in the drive.");
3035 }
3036 */
3037 }
3038 else if (!does_file_exist(szcdno) || !does_file_exist(szserfname))
3039 {
3040 log_to_screen("%s has data on it but it's probably not a Mondo CD.", media_descriptor_string(g_backup_media_type));
3041 }
3042 else
3043 {
3044 log_to_screen("%s found in drive. It's a Mondo disk.", media_descriptor_string(g_backup_media_type));
3045 cd_number = atoi(last_line_of_file(szcdno));
3046 sprintf(tmp, "cat %s 2> /dev/null", szserfname);
3047 strcpy(our_serial_str, call_program_and_get_last_line_of_output(tmp));
3048 // FIXME - should be able to use last_line_of_file(), surely?
3049 }
3050 run_program_and_log_output(szunmount, 1);
3051 log_msg(2, "paafcd: cd_number = %d", cd_number);
3052 log_msg(2, "our serial str = %s; g_serial_string = %s", our_serial_str, g_serial_string);
3053 if (cd_number > 0 && !strcmp(our_serial_str, g_serial_string))
3054 {
3055 log_msg(2, "This %s is part of this backup set!", media_descriptor_string(g_backup_media_type));
3056 ok_go_ahead_burn_it = FALSE;
3057 if (cd_number == g_current_media_number-1)
3058 { log_to_screen("I think you've left the previous %s in the drive.", media_descriptor_string(g_backup_media_type)); }
3059 else
3060 { 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)); }
3061 }
3062 else
3063 {
3064 log_to_screen("...but not part of _our_ backup set.");
3065 }
3066 }
3067 else
3068 {
3069 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));
3070 if (interrogate_disk_currently_in_cdrw_drive(cdrw_dev, FALSE))
3071 {
3072 ok_go_ahead_burn_it = FALSE;
3073 log_to_screen("There isn't a writable %s in the drive.", media_descriptor_string(g_backup_media_type));
3074 }
3075 }
3076
3077/*
3078 if (g_current_media_number > ask_for_one_if_more_than_this)
3079 {
3080 ok_go_ahead_burn_it = FALSE;
3081 log_it("paafcd: %d > %d, so I'll definitely pause.", g_current_media_number > ask_for_one_if_more_than_this);
3082 }
3083*/
3084
3085 if (!ok_go_ahead_burn_it)
3086 {
3087 eject_device(cdrom_dev);
3088 sprintf (tmp,
3089 "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.",
3090 media_descriptor_string(g_backup_media_type),
3091 g_current_media_number,
3092 media_descriptor_string(g_backup_media_type));
3093 popup_and_OK (tmp);
3094 goto gotos_make_me_puke;
3095 }
3096 else
3097 {
3098 log_msg(2, "paafcd: OK, going ahead and burning it.");
3099 }
3100
3101 log_msg (2,"paafcd: OK, I assume I have a blank/reusable %s in the drive...", media_descriptor_string(g_backup_media_type));
3102
3103 // if (ask_for_one_if_more_than_this>1) { popup_and_OK(szmsg); }
3104
3105 log_to_screen ("Proceeding w/ %s in drive.", media_descriptor_string(g_backup_media_type));
3106 paranoid_free(tmp);
3107 paranoid_free(szmsg);
3108 paranoid_free(cdrom_dev);
3109 paranoid_free(cdrw_dev);
3110 paranoid_free(mtpt);
3111 paranoid_free(szcdno);
3112 paranoid_free(szserfname);
3113 paranoid_free(our_serial_str);
3114 paranoid_free(szunmount);
3115 if (pmountable)
3116 {
3117 if (attempt_to_mount_returned_this)
3118 { *pmountable = FALSE; }
3119 else
3120 { *pmountable = TRUE; }
3121 }
3122
3123}
3124
3125
3126
3127
3128
3129
3130
3131
3132/**
3133 * Set the <tt>N</tt>th bit of @c array to @c true_or_false.
3134 * @param array The bit array (as a @c char pointer).
3135 * @param N The bit number to set or reset.
3136 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.
3137 * @see get_bit_N_of_array
3138 */
3139void set_bit_N_of_array(char*array, int N, bool true_or_false)
3140{
3141 int bit_number;
3142 int mask, orig_val, to_add;
3143 int element_number;
3144
3145 assert(array!=NULL);
3146
3147 element_number = N / 8;
3148 bit_number = N % 8;
3149 to_add = (1 << bit_number);
3150 mask = 255 - to_add;
3151 orig_val = array[element_number] & mask;
3152 // log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);
3153 if (true_or_false) { array[element_number] = orig_val | to_add; }
3154}
3155
3156/* @} - end of utilityGroup */
3157
3158
3159
3160
3161
3162
3163
3164
3165/**
3166 * Chop up @c filename.
3167 * @param bkpinfo The backup information structure. Fields used:
3168 * - @c backup_media_type
3169 * - @c compression_level
3170 * - @c optimal_set_size
3171 * - @c tmpdir
3172 * - @c use_lzo
3173 * - @c zip_exe
3174 * - @c zip_suffix
3175 *
3176 * @param biggie_filename The file to chop up.
3177 * @param partimagehack_fifo The FIFO to partimagehack if this is an imagedev, NULL otherwise.
3178 * @param biggie_file_number The sequence number of this biggie file (starting from 0).
3179 * @param noof_biggie_files The number of biggie files there are total.
3180 * @return The number of errors encountered (0 for success)
3181 * @see make_slices_and_images
3182 * @ingroup LLarchiveGroup
3183 */
3184int
3185slice_up_file_etc (struct s_bkpinfo *bkpinfo, char *biggie_filename, char *partimagehack_fifo,
3186 long biggie_file_number, long noof_biggie_files, bool use_partimagehack)
3187{
3188
3189 /*@ buffers ***************************************************/
3190 char *tmp, *checksum_line, *command;
3191 char *tempblock;
3192 char *curr_slice_fname_uncompressed;
3193 char *curr_slice_fname_compressed;
3194 char *file_to_archive;
3195 char *file_to_openin;
3196 /*@ pointers ***************************************************/
3197 char *pB;
3198 FILE *fin, *fout;
3199
3200 /*@ bool *******************************************************/
3201 bool finished = FALSE;
3202
3203 /*@ long *******************************************************/
3204 size_t blksize = 0;
3205 long slice_num = 0;
3206 long i;
3207 long optimal_set_size;
3208 bool should_I_compress_slices;
3209 char *suffix; // for compressed slices
3210
3211 /*@ long long ***************************************************/
3212 long long totalread = 0;
3213 long long totallength = 0;
3214 long long length;
3215
3216 /*@ int *********************************************************/
3217 int retval = 0;
3218 int res = 0;
3219
3220 /*@ structures ***************************************************/
3221 struct s_filename_and_lstat_info biggiestruct;
3222// struct stat statbuf;
3223
3224 assert(bkpinfo!=NULL);
3225 assert_string_is_neither_NULL_nor_zerolength(biggie_filename);
3226 malloc_string(tmp);
3227 malloc_string(checksum_line);
3228 malloc_string(curr_slice_fname_uncompressed);
3229 malloc_string(curr_slice_fname_compressed);
3230 malloc_string(file_to_archive);
3231 malloc_string(suffix);
3232 command = malloc(MAX_STR_LEN*8);
3233
3234 biggiestruct.for_backward_compatibility = '\n';
3235 biggiestruct.use_partimagehack = use_partimagehack;
3236 if (!(tempblock = (char*)malloc(256*1024))) { fatal_error("malloc error 256*1024"); }
3237 optimal_set_size = bkpinfo->optimal_set_size;
3238 if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0)
3239 {
3240 suffix[0] = '\0';
3241 // log_it("%s is indeed compressed :-)", filename);
3242 should_I_compress_slices = FALSE;
3243 }
3244 else
3245 {
3246 strcpy(suffix, bkpinfo->zip_suffix);
3247 should_I_compress_slices = TRUE;
3248 }
3249
3250 if (optimal_set_size < 999)
3251 {
3252 fatal_error ("bkpinfo->optimal_set_size is insanely small");
3253 }
3254 if (partimagehack_fifo)
3255 {
3256 file_to_openin = partimagehack_fifo;
3257 strcpy (checksum_line, "IGNORE");
3258 log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);
3259 }
3260 else
3261 {
3262 file_to_openin = biggie_filename;
3263 sprintf (command, "md5sum \"%s\"", biggie_filename);
3264 if (!(fin = popen (command, "r"))) { log_OS_error("Unable to popen-in command"); return(1); }
3265 (void) fgets (checksum_line, MAX_STR_LEN, fin);
3266 pclose (fin);
3267 }
3268 lstat (biggie_filename, &biggiestruct.properties);
3269 strcpy (biggiestruct.filename, biggie_filename);
3270 pB = strchr(checksum_line, ' ');
3271 if (!pB) { pB = strchr(checksum_line, '\t'); }
3272 if (pB) { *pB='\0'; }
3273 strcpy (biggiestruct.checksum, checksum_line);
3274
3275 strcpy (tmp, slice_fname (biggie_file_number, 0, bkpinfo->tmpdir, ""));
3276 fout = fopen (tmp, "w");
3277 (void) fwrite((void*)&biggiestruct, 1, sizeof(biggiestruct), fout);
3278 paranoid_fclose (fout);
3279 totallength = length_of_file (biggie_filename);
3280 length = totallength / optimal_set_size / 1024;
3281 log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);
3282 if (!(fin = fopen(file_to_openin, "r")))
3283 {
3284 log_OS_error("Unable to openin biggie_filename");
3285 sprintf (tmp, "Cannot archive bigfile '%s': not found", biggie_filename);
3286 log_to_screen (tmp);
3287 paranoid_free(tempblock);
3288 paranoid_free(tmp);
3289 paranoid_free(checksum_line);
3290 paranoid_free(command);
3291 return (1);
3292 }
3293 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3294 { res = move_files_to_stream (bkpinfo, slice_fname (biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL); }
3295 else
3296 { res = move_files_to_cd (bkpinfo, slice_fname (biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL); }
3297 i = bkpinfo->optimal_set_size / 256;
3298 for (slice_num = 1; !finished; slice_num++)
3299 {
3300 strcpy (curr_slice_fname_uncompressed,
3301 slice_fname (biggie_file_number, slice_num, bkpinfo->tmpdir,
3302 ""));
3303 strcpy (curr_slice_fname_compressed,
3304 slice_fname (biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));
3305
3306 strcpy (tmp, percent_media_full_comment (bkpinfo));
3307 update_progress_form (tmp);
3308 if (!(fout = fopen (curr_slice_fname_uncompressed, "w"))) { log_OS_error(curr_slice_fname_uncompressed); return(1); }
3309 if ( (i == bkpinfo->optimal_set_size / 256) && (totalread < 1.1 * totallength) )
3310 {
3311 for (i = 0; i < bkpinfo->optimal_set_size / 256; i++)
3312 {
3313 blksize = fread (tempblock, 1, 256 * 1024, fin);
3314 if (blksize > 0)
3315 {
3316 totalread = totalread + blksize;
3317 (void) fwrite (tempblock, 1, blksize, fout);
3318 }
3319 else
3320 {
3321 break;
3322 }
3323 }
3324 }
3325 else
3326 {
3327 i = 0;
3328 }
3329 paranoid_fclose (fout);
3330 if (i > 0) // length_of_file (curr_slice_fname_uncompressed)
3331 {
3332 if (!does_file_exist (curr_slice_fname_uncompressed))
3333 {
3334 log_msg (2,
3335 "Warning - '%s' doesn't exist. How can I compress slice?",
3336 curr_slice_fname_uncompressed);
3337 }
3338 if (should_I_compress_slices && bkpinfo->compression_level>0)
3339 {
3340 sprintf (command, "%s -%d %s", bkpinfo->zip_exe,
3341 bkpinfo->compression_level, curr_slice_fname_uncompressed);
3342 log_msg (2, command);
3343 if ((res = system (command))) { log_OS_error(command); }
3344 // did_I_compress_slice = TRUE;
3345 }
3346 else
3347 {
3348 sprintf (command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);
3349 res=0; // don't do it :)
3350 // did_I_compress_slice = FALSE;
3351 }
3352 retval += res;
3353 if (res)
3354 {
3355 log_msg (2, "Failed to compress the slice");
3356 }
3357 if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed))
3358 {
3359 unlink (curr_slice_fname_uncompressed);
3360 }
3361 if (res)
3362 {
3363 sprintf (tmp, "Problem with slice # %ld", slice_num);
3364 }
3365 else
3366 {
3367 sprintf (tmp,
3368 "%s - Bigfile #%ld, slice #%ld compressed OK ",
3369 biggie_filename, biggie_file_number + 1, slice_num);
3370 }
3371#ifndef _XWIN
3372 if (!g_text_mode)
3373 {
3374 newtDrawRootText (0, g_noof_rows - 2, tmp);
3375 newtRefresh ();
3376 }
3377 else
3378 {
3379 log_msg (2, tmp);
3380 }
3381#else
3382 log_msg(2, tmp);
3383#endif
3384 strcpy(file_to_archive, curr_slice_fname_compressed);
3385 g_current_progress++;
3386 }
3387 else /* if i==0 then ... */
3388 {
3389 finished = TRUE;
3390 strcpy (file_to_archive, curr_slice_fname_uncompressed);
3391 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3392 {
3393 break;
3394 }
3395 }
3396
3397 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3398 {
3399 register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);
3400 maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);
3401 res = move_files_to_stream (bkpinfo, file_to_archive, NULL);
3402 }
3403 else
3404 {
3405 res = move_files_to_cd (bkpinfo, file_to_archive, NULL);
3406 }
3407 retval += res;
3408 if (res)
3409 {
3410 sprintf (tmp,
3411 "Failed to add slice %ld of bigfile %ld to scratchdir",
3412 slice_num, biggie_file_number+1);
3413 log_to_screen (tmp);
3414 fatal_error
3415 ("Hard disk full. You should have bought a bigger one.");
3416 }
3417 }
3418 paranoid_fclose (fin);
3419 sprintf (tmp, "Sliced bigfile #%ld", biggie_file_number + 1);
3420 if (retval)
3421 {
3422 strcat (tmp, "...FAILED");
3423 }
3424 else
3425 {
3426 strcat (tmp, "...OK!");
3427 }
3428 log_msg (1, tmp);
3429 paranoid_free(tempblock);
3430 paranoid_free(tmp);
3431 paranoid_free(checksum_line);
3432 paranoid_free(command);
3433 paranoid_free(curr_slice_fname_uncompressed);
3434 paranoid_free(curr_slice_fname_compressed);
3435 paranoid_free(file_to_archive);
3436 paranoid_free(suffix);
3437 return (retval);
3438}
3439
3440
3441
3442
3443
3444
3445/**
3446 * Remove the archives in @c d.
3447 * This could possibly include any of:
3448 * - all afioballs (compressed and not)
3449 * - all filelists
3450 * - all slices
3451 * - all checksums
3452 * - a zero filler file
3453 *
3454 * @param d The directory to wipe the archives from.
3455 * @ingroup utilityGroup
3456 */
3457void
3458wipe_archives (char *d)
3459{
3460 /*@ buffers **********************************************/
3461 char *tmp;
3462 char *dir;
3463
3464 malloc_string(tmp);
3465 malloc_string(dir);
3466 assert_string_is_neither_NULL_nor_zerolength(d);
3467
3468 sprintf (dir, "%s/archives", d);
3469 sprintf (tmp, "find %s -name '*.afio*' -exec rm -f '{}' \\;", dir);
3470 run_program_and_log_output(tmp, FALSE);
3471 sprintf (tmp, "find %s -name '*list.[0-9]*' -exec rm -f '{}' \\;", dir);
3472 run_program_and_log_output(tmp, FALSE);
3473 sprintf (tmp, "find %s -name 'slice*' -exec rm -f '{}' \\;", dir);
3474 run_program_and_log_output(tmp, FALSE);
3475 sprintf (tmp, "rm -f %s/cklist*", dir);
3476 run_program_and_log_output(tmp, FALSE);
3477 sprintf (tmp, "rm -f %s/zero", dir);
3478 run_program_and_log_output(tmp, FALSE);
3479 log_msg(1, "Wiped %s's archives", dir);
3480 sprintf (tmp, "ls -l %s", dir);
3481 run_program_and_log_output (tmp, FALSE);
3482 paranoid_free(tmp);
3483 paranoid_free(dir);
3484}
3485
3486
3487
3488/**
3489 * @addtogroup LLarchiveGroup
3490 * @{
3491 */
3492/**
3493 * Write the final ISO image.
3494 * @param bkpinfo The backup information structure. Used only
3495 * in the call to @c write_iso_and_go_on().
3496 * @return The number of errors encountered (0 for success)
3497 * @see write_iso_and_go_on
3498 * @see make_iso_fs
3499 * @bug The final ISO is written even if there are no files on it. In practice,
3500 * however, this occurs rarely.
3501 */
3502int
3503write_final_iso_if_necessary (struct s_bkpinfo *bkpinfo)
3504{
3505 /*@ int ******************************************************/
3506 int res;
3507
3508 /*@ buffers ***************************************************/
3509 char *tmp;
3510
3511 malloc_string(tmp);
3512 assert(bkpinfo!=NULL);
3513
3514// 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
3515
3516 sprintf(tmp, "Writing the final ISO");
3517 log_msg(2, tmp);
3518 center_string (tmp, 80);
3519#ifndef _XWIN
3520 if (!g_text_mode)
3521 {
3522 newtPushHelpLine (tmp);
3523 }
3524#endif
3525 res = write_iso_and_go_on (bkpinfo, TRUE);
3526#ifndef _XWIN
3527 if (!g_text_mode)
3528 {
3529 newtPopHelpLine ();
3530 }
3531#endif
3532 log_msg (2, "Returning from writing final ISO (res=%d)", res);
3533 paranoid_free(tmp);
3534 return (res);
3535}
3536
3537
3538/**
3539 * Write an ISO image to <tt>[bkpinfo->isodir]/bkpinfo->prefix-[g_current_media_number].iso</tt>.
3540 * @param bkpinfo The backup information structure. Fields used:
3541 * - @c backup_media_type
3542 * - @c prefix
3543 * - @c isodir
3544 * - @c manual_cd_tray
3545 * - @c media_size
3546 * - @c nfs_mount
3547 * - @c nfs_remote_dir
3548 * - @c scratchdir
3549 * - @c verify_data
3550 *
3551 * @param last_cd If TRUE, this is the last CD to write; if FALSE, it's not.
3552 * @return The number of errors encountered (0 for success)
3553 * @see make_iso_fs
3554 */
3555int
3556write_iso_and_go_on (struct s_bkpinfo *bkpinfo, bool last_cd)
3557{
3558 /*@ pointers *****************************************************/
3559 FILE *fout;
3560
3561 /*@ buffers ******************************************************/
3562 char *tmp;
3563 char *cdno_fname;
3564 char *lastcd_fname;
3565 char *isofile;
3566
3567 /*@ bool *********************************************************/
3568 bool that_one_was_ok;
3569 bool using_nfs;
3570 bool orig_vfy_flag_val;
3571
3572 /*@ int ************************************************************/
3573 int res = 0;
3574
3575 malloc_string(tmp);
3576 malloc_string(cdno_fname);
3577 malloc_string(lastcd_fname);
3578 malloc_string(isofile);
3579
3580 assert(bkpinfo!=NULL);
3581 orig_vfy_flag_val = bkpinfo->verify_data;
3582 if (bkpinfo->media_size[g_current_media_number]<=0) { fatal_error( "write_iso_and_go_on() - unknown media size"); }
3583
3584 if (strlen (bkpinfo->nfs_mount) > 1)
3585 {
3586 using_nfs = TRUE;
3587 }
3588 else
3589 {
3590 using_nfs = FALSE;
3591 }
3592 log_msg (1, "OK, time to make %s #%d", media_descriptor_string(bkpinfo->backup_media_type), g_current_media_number);
3593
3594 /* label the ISO with its number */
3595
3596 sprintf (cdno_fname, "%s/archives/THIS-CD-NUMBER", bkpinfo->scratchdir);
3597 fout = fopen (cdno_fname, "w");
3598 fprintf (fout, "%d", g_current_media_number);
3599 paranoid_fclose (fout);
3600
3601 sprintf (tmp, "cp -f %s/autorun %s/", g_mondo_home, bkpinfo->scratchdir);
3602 if (run_program_and_log_output(tmp, FALSE))
3603 { log_msg(2, "Warning - unable to copy autorun to scratchdir"); }
3604
3605 /* last CD or not? Label accordingly */
3606 sprintf (lastcd_fname, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);
3607 if (last_cd)
3608 {
3609 unlink (lastcd_fname);
3610 log_msg (2, "OK, you're telling me this is the last CD. Fair enough.");
3611 }
3612 else
3613 {
3614 fout = fopen (lastcd_fname, "w");
3615 fprintf (fout,
3616 "You're listening to 90.3 WPLN, Nashville Public Radio.\n");
3617 paranoid_fclose (fout);
3618 }
3619 if (space_occupied_by_cd (bkpinfo->scratchdir) / 1024 > bkpinfo->media_size[g_current_media_number])
3620 {
3621 sprintf (tmp,
3622 "Warning! CD is too big. It occupies %ld KB, which is more than the %ld KB allowed.",
3623 (long) space_occupied_by_cd (bkpinfo->scratchdir),
3624 (long) bkpinfo->media_size[g_current_media_number]);
3625 log_to_screen (tmp);
3626 }
3627 sprintf (isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->nfs_remote_dir,
3628 bkpinfo->prefix, g_current_media_number);
3629 for (that_one_was_ok = FALSE; !that_one_was_ok;)
3630 {
3631 res = make_iso_fs (bkpinfo, isofile);
3632 if (g_current_media_number==1 && !res && ( bkpinfo->backup_media_type == cdr || bkpinfo->backup_media_type == cdrw) )
3633 {
3634 if (find_cdrom_device(tmp, FALSE)) // make sure find_cdrom_device() finds, records CD-R's loc
3635 { log_msg(3, "*Sigh* Mike, I hate your computer."); bkpinfo->manual_cd_tray = TRUE; } // if it can't be found then force pausing
3636 else
3637 { log_msg(3, "Great. Found Mike's CD-ROM drive."); }
3638 }
3639 if (bkpinfo->verify_data && !res)
3640 {
3641 log_to_screen
3642 ("Please reboot from the 1st CD in Compare Mode, as a precaution.");
3643 chdir ("/");
3644 iamhere("Before calling verify_cd_image()");
3645 res += verify_cd_image (bkpinfo);
3646 iamhere("After calling verify_cd_image()");
3647 }
3648 if (!res)
3649 {
3650 that_one_was_ok = TRUE;
3651 }
3652 else
3653 {
3654 sprintf (tmp, "Failed to burn %s #%d. Retry?",
3655 media_descriptor_string(bkpinfo->backup_media_type),
3656 g_current_media_number);
3657 res = ask_me_yes_or_no (tmp);
3658 if (!res)
3659 {
3660 if (ask_me_yes_or_no ("Abort the backup?"))
3661 {
3662 fatal_error ("FAILED TO BACKUP");
3663 }
3664 else
3665 {
3666 break;
3667 }
3668 }
3669 else
3670 {
3671 log_msg (2, "Retrying, at user's request...");
3672 res = 0;
3673 }
3674 }
3675 }
3676/*
3677 if (using_nfs)
3678 {
3679 sprintf(tmp,"mv -f %s %s/%s/", isofile, bkpinfo->isodir, bkpinfo->nfs_remote_dir);
3680 if (run_program_and_log_output(tmp, FALSE))
3681 { log_to_screen("Unable to move ISO to NFS dir"); }
3682 }
3683*/
3684 g_current_media_number++;
3685 if (g_current_media_number > MAX_NOOF_MEDIA) { fatal_error("Too many CD-R(W)'s. Use tape or net."); }
3686 wipe_archives (bkpinfo->scratchdir);
3687 sprintf (tmp, "rm -Rf %s/images/*gz %s/images/*data*img",
3688 bkpinfo->scratchdir, bkpinfo->scratchdir);
3689 if (system (tmp))
3690 {
3691 log_msg
3692 (2, "Error occurred when I tried to delete the redundant IMGs and GZs");
3693 }
3694
3695 if (last_cd)
3696 {
3697 log_msg (2, "This was your last CD.");
3698 }
3699 else
3700 {
3701 log_msg (2, "Continuing to backup your data...");
3702 }
3703
3704 bkpinfo->verify_data = orig_vfy_flag_val;
3705 paranoid_free(tmp);
3706 paranoid_free(cdno_fname);
3707 paranoid_free(lastcd_fname);
3708 paranoid_free(isofile);
3709 return (0);
3710}
3711
3712/* @} - end of LLarchiveGroup */
3713
3714
3715
3716
3717/**
3718 * Verify the user's data.
3719 * @param bkpinfo The backup information structure. Fields used:
3720 * - @c backup_data
3721 * - @c backup_media_type
3722 * - @c media_device
3723 * - @c verify_data
3724 *
3725 * @return The number of errors encountered (0 for success)
3726 * @ingroup verifyGroup
3727 */
3728int verify_data(struct s_bkpinfo *bkpinfo)
3729{
3730 int res=0, retval=0, cdno=0;
3731 char *tmp;
3732 long diffs=0;
3733
3734 malloc_string(tmp);
3735 assert(bkpinfo!=NULL);
3736 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type))
3737 {
3738 chdir ("/");
3739 mvaddstr_and_log_it (g_currentY, 0,
3740 "Verifying archives against live filesystem");
3741 if (bkpinfo->backup_media_type == cdstream)
3742 {
3743 strcpy (bkpinfo->media_device, "/dev/cdrom");
3744 }
3745 verify_tape_backups (bkpinfo);
3746 mvaddstr_and_log_it (g_currentY++, 74, "Done.");
3747 }
3748 else if (bkpinfo->backup_data)
3749 //bkpinfo->backup_media_type == cdrw || bkpinfo->backup_media_type == cdr))
3750 {
3751 log_msg (2, "Not verifying again. Per-CD/ISO verification already carried out.");
3752 paranoid_system("cat /tmp/changed.files.* > /tmp/changed.files 2> /dev/null");
3753 }
3754 else
3755 {
3756 g_current_media_number = cdno;
3757 if (bkpinfo->backup_media_type != iso)
3758 {
3759 find_cdrom_device(bkpinfo->media_device, FALSE); // replace 0,0,0 with /dev/cdrom
3760 }
3761 chdir ("/");
3762 for (cdno = 1;
3763 cdno < 99 && bkpinfo->verify_data;
3764 cdno++)
3765 {
3766 if (cdno != g_current_media_number)
3767 {
3768 log_msg (2, "Warning - had to change g_current_media_number from %d to %d", g_current_media_number, cdno);
3769 g_current_media_number = cdno;
3770 }
3771 if (bkpinfo->backup_media_type != iso)
3772 {
3773 insist_on_this_cd_number (bkpinfo, cdno);
3774 }
3775 res = verify_cd_image (bkpinfo); // sets verify_data to FALSE if it's time to stop verifying
3776 retval += res;
3777 if (res)
3778 {
3779 sprintf (tmp,
3780 "Warnings/errors were reported while checking %s #%d",
3781 media_descriptor_string(bkpinfo->backup_media_type),
3782 g_current_media_number);
3783 log_to_screen (tmp);
3784
3785 }
3786 }
3787/*
3788 sprintf (tmp,
3789 "cat %s | grep \"afio: \" | cut -d'\"' -f2 | sort -u | awk '{print \"/\"$0;};' | tr -s '/' '/' | grep -vx \"/afio:.*\" > /tmp/changed.files",
3790 MONDO_LOGFILE);
3791 system (tmp);
3792*/
3793 sprintf (tmp,
3794 "cat %s | grep \"afio: \" | sed 's/afio: //' | grep -vx \"/dev/.*\" >> /tmp/changed.files",
3795 MONDO_LOGFILE);
3796 system (tmp);
3797
3798 sprintf (tmp,
3799 "cat %s | grep \"star: \" | sed 's/star: //' | grep -vx \"/dev/.*\" >> /tmp/changed.files",
3800 MONDO_LOGFILE);
3801 system (tmp);
3802 run_program_and_log_output("umount "MNT_CDROM, FALSE);
3803// if (bkpinfo->backup_media_type != iso && !bkpinfo->please_dont_eject_when_restoring)
3804//{
3805 eject_device(bkpinfo->media_device);
3806//}
3807 }
3808 diffs = count_lines_in_file ("/tmp/changed.files");
3809
3810 if (diffs > 0)
3811 {
3812 if (retval==0) { retval=(int)(-diffs); }
3813 }
3814 paranoid_free(tmp);
3815 return(retval);
3816}
3817
3818
3819
3820
3821
3822/**
3823 * @addtogroup utilityGroup
3824 * @{
3825 */
3826/**
3827 * Write an image to a real 3.5" floppy disk.
3828 * @param device The device to write to (e.g. @c /dev/fd0)
3829 * @param datafile The image to write to @p device.
3830 * @return The number of errors encountered (0 for success)
3831 * @see write_image_to_floppy
3832 */
3833int
3834write_image_to_floppy_SUB (char *device, char *datafile)
3835{
3836 /*@ int ****************************************************************/
3837 int res = 0;
3838 int percentage = 0;
3839 int blockno = 0;
3840 int maxblocks =0;
3841
3842 /*@ buffers*************************************************************/
3843 char *tmp;
3844 char blk[1024];
3845 char *title;
3846
3847 /*@ pointers ***********************************************************/
3848 char *p;
3849 FILE *fout, *fin;
3850
3851
3852 malloc_string(tmp);
3853 malloc_string(title);
3854 /* pretty stuff */
3855 if (!(p = strrchr (datafile, '/')))
3856 {
3857 p = datafile;
3858 }
3859 else
3860 {
3861 p++;
3862 }
3863 sprintf (title, "Writing %s to floppy", p);
3864 open_evalcall_form (title);
3865 /* functional stuff */
3866 for (p = device + strlen (device); p != device && isdigit (*(p - 1)); p--);
3867 maxblocks = atoi (p);
3868 if (!maxblocks) { maxblocks = 1440; }
3869 sprintf (tmp, "maxblocks = %d; p=%s", maxblocks, p);
3870 log_msg (2, tmp);
3871 /* copy data from image to floppy */
3872 if (!(fin = fopen (datafile, "r")))
3873 {
3874 log_OS_error ("Cannot open img");
3875 return (1);
3876 }
3877 if (!(fout = fopen (device, "w")))
3878 {
3879 log_OS_error ("Cannot open fdd");
3880 return (1);
3881 }
3882 for (blockno = 0; blockno < maxblocks; blockno++)
3883 {
3884 percentage = blockno * 100 / maxblocks;
3885 if (fread (blk, 1, 1024, fin) != 1024)
3886 {
3887 if (feof(fin))
3888 {
3889 log_msg(1, "img read err - img ended prematurely - non-fatal error");
3890 sleep(3);
3891 return(res);
3892 }
3893 res++;
3894 log_to_screen ("img read err");
3895 }
3896 if (fwrite (blk, 1, 1024, fout) != 1024)
3897 {
3898 res++;
3899 log_to_screen ("fdd write err");
3900 }
3901 if (((blockno + 1) % 128) == 0)
3902 {
3903 paranoid_system ("sync"); /* fflush doesn't work; dunno why */
3904 update_evalcall_form (percentage);
3905 }
3906 }
3907 paranoid_fclose (fin);
3908 paranoid_fclose(fout);
3909 paranoid_free(tmp);
3910 paranoid_free(title);
3911 close_evalcall_form ();
3912 return (res);
3913}
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923/**
3924 * Wrapper around @c write_image_to_floppy_SUB().
3925 * This function, unlike @c write_image_to_floppy_SUB(),
3926 * gives the user the opportunity to retry if the write fails.
3927 * @see write_image_to_floppy_SUB
3928 */
3929int
3930write_image_to_floppy (char *device, char *datafile)
3931{
3932 /*@ int ***************************************************************/
3933 int res = 0;
3934
3935 assert_string_is_neither_NULL_nor_zerolength(device);
3936 assert_string_is_neither_NULL_nor_zerolength(datafile);
3937
3938 while ((res = write_image_to_floppy_SUB (device, datafile)))
3939 {
3940 if (!ask_me_yes_or_no ("Failed to write image to floppy. Retry?"))
3941 {
3942 return (res);
3943 }
3944 }
3945 return (res);
3946}
3947
3948/* @} - end of utilityGroup */
3949
Note: See TracBrowser for help on using the repository browser.