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

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

Compiler warning solved (M. Loiseleur again !)
Code displaced to ease memeory management in case of exit in libmondo-archive.c

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