source: MondoRescue/branches/3.3/mondo/src/common/libmondo-archive.c@ 3891

Last change on this file since 3891 was 3891, checked in by Bruno Cornec, 4 months ago

Typo

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