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

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