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

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

WARNING: Not tested yet ! Will be stabilized in next hours.
this patch changes the interface between mindi and mondo.
Everything is now managed through either MONDO_CACHE/mondo-restore.cfg
and MONDO_CACHE/mindi.conf (an additional configuration file)
This removes all the one line files NFS-*, ... that where used
in an anarchic way. Now everything computed by mondo is
under mondo-restore.cfg and everything related to mindi in mindi.conf

Still needed are the removal of the 2 parameters to mindi,
but that will be done after when a clear line is drawn between
where files are put by each tool.

MONDO_TMP and MINDI_TMP should be reserved for temporary files
MONDO_CACHE and MINDI_CACHE for end results and communication
between tools.
These changes were made in order to prepare the USB support in mondo

A first step in the right direction, but still some work to do
before it's working again.
Testers please be warned.

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