source: MondoRescue/branches/2.2.10/mondo/src/common/libmondo-archive.c@ 2508

Last change on this file since 2508 was 2508, checked in by Bruno Cornec, 14 years ago

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


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