source: MondoRescue/branches/2.2.2/mondo/src/common/libmondo-archive.c@ 1315

Last change on this file since 1315 was 1315, checked in by Bruno Cornec, 17 years ago

Log files are now consistent: mondoarchive.log for mondoarchive (containing also mindi.log) and mondorestore.log for mondorestore (copied from /tmp (ram) to /var/log (disk) at the end of the restore)
One include has been created for each bianry containing only that declaration ofr the moment, but which will be extended to include all local definitions (ps_* e.g.)
Doc updated accordingly
LOGFILE in restore process is now passed in the environment and not duplicated anymore
LogIt is not redifined either
LOGFILE should be put in environment by mondoarchive for mindi's usage but that's a step left for later.

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