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

Last change on this file since 75 was 75, checked in by andree, 19 years ago

Various changes to get archiving to NFS work in interactive mode. It
wasn't really like were were bugs, it appeared more like it was simply
not finished.

Side note: I believe that bkpinfo->isodir and bkpinfo->prefix were the
wrong way round in libmondo-archive.c and I've swapped them.

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