source: MondoRescue/branches/stable/mondo/mondo/common/libmondo-archive.c@ 541

Last change on this file since 541 was 541, checked in by bcornec, 18 years ago

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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