source: branches/stable/mondo/src/common/libmondo-archive.c @ 1063

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