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

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

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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