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

Last change on this file since 1817 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

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