source: MondoRescue/branches/3.0/mondo/src/common/libmondo-archive.c

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