source: MondoRescue/branches/3.2/mondo/src/mondorestore/mondo-rstr-tools.c@ 3292

Last change on this file since 3292 was 3292, checked in by Bruno Cornec, 10 years ago
  • Remove from mindi 2 functions replaced by perl code (ReadAllLink by mr-read-all-link and ProcessLDD by mr-process-ldd)
  • Redirect mindi execution to mondo log on the fly to try to improve percentage display with newt (not finished yet)
  • Introduce a new global var MINDI_LOGFILE and use it everywhere
  • Fix some memory free mising (thanks valgrind)
  • Remove a call to rpm to log packages - not portable
  • Works with valgrind locally to create images in dir
  • Property svn:keywords set to Id
File size: 73.8 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 3292 2014-05-27 15:53:14Z bruno $
3***************************************************************************/
4
5#include <pthread.h>
6#include <linux/fd.h>
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "mr_str.h"
10#include "../common/mondostructures.h"
11#include "../common/libmondo.h"
12#include "mr-externs.h"
13#include "mondo-rstr-tools.h"
14
15/**
16 * The biggielist stub (appended to the directory where all.tar.gz was unpacked).
17 */
18#define BIGGIELIST_TXT_STUB "tmp/biggielist.txt"
19
20/**
21 * The filelist stub (appended to the directory where all.tar.gz was unpacked).
22 */
23#define FILELIST_FULL_STUB "tmp/filelist.full.gz"
24
25/**
26 * The mountlist stub (appended to the directory where all.tar.gz was unpacked).
27 */
28#define MOUNTLIST_FNAME_STUB "tmp/mountlist.txt"
29
30/**
31 * The mondorestore.cfg stub (appended to the directory where all.tar.gz was unpacked).
32 */
33#define MONDO_CFG_FILE_STUB "tmp/mondorestore.cfg"
34/**
35 * The i-want-my-lvm stub
36 */
37#define IWANTMYLVM_STUB "tmp/i-want-my-lvm"
38
39extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
40extern bool g_I_have_just_nuked;
41/*
42extern char *g_tmpfs_mountpt;
43*/
44
45/**
46 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
47 */
48char *g_isodir_device;
49
50
51/**
52 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
53 */
54char *g_isodir_format;
55
56extern long g_current_progress, g_maximum_progress;
57extern char *g_biggielist_txt; // where 'biggielist.txt' is stored, on ramdisk / tempdir;
58 // biggielist.txt is the list of big files stored on the
59 // backup media set in question
60extern char *g_filelist_full; // filelist.full.gz is the list of all regular files
61 // (excluding big files) stored on the backup media set
62extern char *g_biggielist_pot; // list of big files which _could_ be restored, if the
63 // user chooses them
64extern char *g_filelist_imagedevs; // list of devices (e.g. /dev/hda1, /dev/sda5) which
65 // were archived as images, not just /dev entries
66 // ... e.g. NTFS, BeOS partitions
67extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
68 // restore only these
69extern char *g_mondo_cfg_file; // where mondorestore.cfg (the config file) is stored
70extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
71extern char *g_mondo_home; // homedir of Mondo; usually /usr/local/share/mondo
72
73extern t_bkptype g_backup_media_type;
74
75extern int g_partition_table_locked_up;
76extern char *MONDO_LOGFILE;
77
78/* Reference to global bkpinfo */
79extern struct s_bkpinfo *bkpinfo;
80
81/* Should we use or not extended attributes and acl when restoring */
82char *g_getfattr = NULL;
83char *g_getfacl = NULL;
84
85extern void kill_anything_like_this(char *str);
86extern int skip_obdr(void);
87extern int mount_media();
88extern int set_tape_block_size_with_mt(long internal_tape_block_size);
89
90/**
91* @addtogroup restoreUtilityGroup
92* @{
93*/
94/**
95* Free the malloc()s for the filename variables.
96*/
97void free_MR_global_filenames(void)
98{
99paranoid_free(g_biggielist_txt);
100paranoid_free(g_filelist_full);
101paranoid_free(g_filelist_imagedevs);
102paranoid_free(g_imagedevs_restthese);
103paranoid_free(g_mondo_cfg_file);
104paranoid_free(g_mountlist_fname);
105paranoid_free(g_mondo_home);
106/*
107paranoid_free(g_tmpfs_mountpt);
108*/
109paranoid_free(g_isodir_device);
110paranoid_free(g_isodir_format);
111
112}
113
114
115
116/**
117* Ask the user which imagedevs from the list contained in @p infname should
118* actually be restored.
119* @param infname The file containing a list of all imagedevs.
120* @param outfname The location of the output file containing the imagedevs the user wanted to restore.
121* @ingroup restoreUtilityGroup
122*/
123void ask_about_these_imagedevs(char *infname, char *outfname) {
124
125FILE *fin;
126FILE *fout;
127char *incoming = NULL;
128char *question = NULL;
129
130assert_string_is_neither_NULL_nor_zerolength(infname);
131assert_string_is_neither_NULL_nor_zerolength(outfname);
132
133if (!(fin = fopen(infname, "r"))) {
134 fatal_error("Cannot openin infname");
135}
136if (!(fout = fopen(outfname, "w"))) {
137 fatal_error("Cannot openin outfname");
138}
139for (mr_getline(incoming, fin); !feof(fin) && (incoming != NULL); mr_getline(incoming, fin)) {
140 mr_strip_spaces(incoming);
141
142 if (incoming[0] == '\0') {
143 mr_free(incoming);
144 continue;
145 }
146
147 mr_asprintf(question, "Should I restore the image of %s ?", incoming);
148
149 if (ask_me_yes_or_no(question)) {
150 fprintf(fout, "%s\n", incoming);
151 }
152 mr_free(incoming);
153}
154mr_free(incoming);
155mr_free(question);
156paranoid_fclose(fout);
157paranoid_fclose(fin);
158}
159
160/**************************************************************************
161*ASK_ABOUT_THESE_IMAGEDEVS *
162**************************************************************************/
163
164
165
166
167
168
169
170
171/**
172* Extract @c mondorestore.cfg and @c mountlist.txt from @p ramdisk_fname.
173* @param bkpinfo The backup information structure. @c tmpdir is the only field used.
174* @param ramdisk_fname The filename of the @b compressed ramdisk to look in.
175* @param output_cfg_file Where to put the configuration file extracted.
176* @param output_mountlist_file Where to put the mountlist file extracted.
177* @return 0 for success, nonzero for failure.
178* @ingroup restoreUtilityGroup
179*/
180
181/**
182* Keep trying to get mondorestore.cfg from the archive, until the user gives up.
183*/
184void get_cfg_file_from_archive_or_bust()
185{
186while (get_cfg_file_from_archive()) {
187 if (!ask_me_yes_or_no("Failed to find config file/archives. Choose another source?")) {
188 fatal_error("Could not find config file/archives. Aborting.");
189 }
190 interactively_obtain_media_parameters_from_user(FALSE);
191 }
192}
193
194
195/**
196* Determine whether @p list_fname contains a line containing @p f.
197* @param f The line to search for.
198* @param list_fname The file to search in.
199* @param preamble Ignore this beginning part of @p f ("" to disable).
200* @return TRUE if it's in the list, FALSE if it's not.
201*/
202bool is_file_in_list(char *f, char *list_fname, char *preamble)
203{
204
205char *command = NULL;
206char *file = NULL;
207char *tmp = NULL;
208int res;
209
210assert_string_is_neither_NULL_nor_zerolength(f);
211assert_string_is_neither_NULL_nor_zerolength(list_fname);
212assert(preamble != NULL);
213
214if (strncmp(preamble, f, strlen(preamble)) == 0) {
215 mr_asprintf(file, "%s", f + strlen(preamble));
216} else {
217 mr_asprintf(file, "%s", f);
218}
219if (file[0] == '/' && file[1] == '/') {
220 tmp = file;
221
222 mr_asprintf(file, "%s", tmp + 1);
223 mr_free(tmp);
224}
225log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
226mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
227mr_free(file);
228
229res = run_program_and_log_output(command, FALSE);
230mr_free(command);
231if (res) {
232 return (FALSE);
233} else {
234 return (TRUE);
235}
236}
237
238/**************************************************************************
239*END_IS_FILE_IN_LIST *
240**************************************************************************/
241
242/**
243 * Get information about the location of ISO images from the user.
244 * @param isodir_device Where to put the device (e.g. /dev/hda4) the user enters.
245 * @param isodir_format Where to put the format (e.g. ext2) the user enters.
246 * @param nuke_me_please Whether we're planning on nuking or not.
247 * @return TRUE if OK was pressed, FALSE otherwise.
248 */
249bool
250get_isodir_info(char *isodir_device, char *isodir_format,
251 struct s_bkpinfo *bkpinfo, bool nuke_me_please)
252{
253
254 bool HDD = FALSE;
255 /** initialize ********************************************************/
256
257 assert(isodir_device != NULL);
258 assert(isodir_format != NULL);
259 assert(bkpinfo->isodir != NULL);
260
261 log_it("bkpinfo->isodir = %s", bkpinfo->isodir);
262 isodir_format[0] = '\0';
263 if (isodir_device[0] == '\0') {
264 strcpy(isodir_device, "/dev/");
265 }
266 if (bkpinfo->isodir[0] == '\0') {
267 strcpy(bkpinfo->isodir, "/");
268 }
269 // TODO: Are we shure it does what it's expected to do here ?
270 if (does_file_exist("/tmp/NETFS-SERVER-MOUNT")) {
271 strcpy(isodir_device, last_line_of_file("/tmp/NETFS-SERVER-MOUNT"));
272 strcpy(isodir_format, "netfs");
273 strcpy(bkpinfo->isodir, last_line_of_file("/tmp/ISO-DIR"));
274 }
275 if (nuke_me_please) {
276 return (TRUE);
277 }
278
279 if (popup_and_get_string("ISO Mode - device", "On what device do the ISO files live?", isodir_device, MAX_STR_LEN / 4)) {
280 if (popup_and_get_string ("ISO Mode - format", "What is the disk format of the device? (Hit ENTER if you don't know.)", isodir_format, 16)) {
281 if (popup_with_buttons("Are you restoring from an external hard drive ?", "Yes", "No")) {
282 HDD = TRUE;
283 }
284 if (popup_and_get_string ("ISO Mode - path", "At what path on this device can the ISO files be found ?", bkpinfo->isodir, MAX_STR_LEN / 4)) {
285 strip_spaces(isodir_device);
286 strip_spaces(isodir_format);
287 strip_spaces(bkpinfo->isodir);
288 log_it("isodir_device = %s - isodir_format = %s - bkpinfo->isodir = %s", isodir_device, isodir_format, bkpinfo->isodir);
289 if (HDD) {
290 /* We need an additional param */
291 mr_asprintf(bkpinfo->subdir, "%s", bkpinfo->isodir);
292 strcpy(bkpinfo->isodir, "/tmp/isodir");
293 log_it("Now bkpinfo->isodir = %s and subdir = ", bkpinfo->isodir, bkpinfo->subdir);
294 }
295 return (TRUE);
296 }
297 }
298 }
299 return (FALSE);
300}
301
302
303/**
304* Set up an ISO backup.
305* @param bkpinfo The backup information structure. Fields used:
306* - @c bkpinfo->backup_media_type
307* - @c bkpinfo->disaster_recovery
308* - @c bkpinfo->isodir
309* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
310* @return 0 for success, nonzero for failure.
311*/
312int iso_fiddly_bits(bool nuke_me_please) {
313
314char *mount_isodir_command = NULL;
315char *command = NULL;
316char *mds = NULL;
317int retval = 0, i;
318
319g_ISO_restore_mode = TRUE;
320read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
321if (bkpinfo->disaster_recovery) {
322 /* Don't let this clobber an existing bkpinfo->isodir */
323 if (!bkpinfo->isodir[0]) {
324 strcpy(bkpinfo->isodir, "/tmp/isodir");
325 }
326 mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
327 run_program_and_log_output(command, 5);
328 mr_free(command);
329 log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
330}
331
332if (!get_isodir_info(g_isodir_device, g_isodir_format, bkpinfo, nuke_me_please)) {
333 return (1);
334}
335paranoid_system("umount -d " MNT_CDROM " 2> /dev/null"); /* just in case */
336
337if (is_this_device_mounted(g_isodir_device)) {
338 log_to_screen("WARNING - isodir is already mounted");
339} else {
340 mr_asprintf(mount_isodir_command, "mount %s", g_isodir_device);
341 if (strlen(g_isodir_format) > 1) {
342 mr_strcat(mount_isodir_command, " -t %s", g_isodir_format);
343 }
344
345 mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
346 run_program_and_log_output("df -m -P", FALSE);
347 log_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?", mount_isodir_command);
348 if (run_program_and_log_output(mount_isodir_command, FALSE)) {
349 popup_and_OK
350 ("Cannot mount the device where the ISO files are stored.");
351 return (1);
352 }
353 paranoid_free(mount_isodir_command);
354 log_to_screen
355 ("I have mounted the device where the ISO files are stored.");
356}
357if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
358 mount_media();
359}
360i = what_number_cd_is_this(); /* has the side-effect of calling mount_media() */
361mds = media_descriptor_string(bkpinfo->backup_media_type);
362mr_free(mds);
363
364log_msg(1, "%s #%d has been mounted via loopback mount", mds, i);
365if (i < 0) {
366 popup_and_OK("Cannot find ISO images in the directory you specified.");
367 retval = 1;
368}
369log_msg(2, "bkpinfo->isodir is now %s", bkpinfo->isodir);
370return (retval);
371}
372
373
374
375
376/**
377* Kill all Petris processes.
378*/
379void kill_petris(void) {
380 kill_anything_like_this("petris");
381}
382
383/**************************************************************************
384*END_KILL_PETRIS *
385**************************************************************************/
386
387
388/**
389 * Mount @p device at @p mpt as @p format.
390 * @param device The device (/dev entry) to mount.
391 * @param mpt The directory to mount it on.
392 * @param format The filesystem type of @p device.
393 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
394 * @return 0 for success, nonzero for failure.
395 */
396int mount_device(char *device, char *mpt, char *format, bool writeable)
397{
398int res = 0;
399
400/** malloc **/
401char *tmp = NULL;
402char *command = NULL;
403char *mountdir = NULL;
404char *mountpoint = NULL;
405char *additional_parameters = NULL;
406
407assert_string_is_neither_NULL_nor_zerolength(device);
408assert_string_is_neither_NULL_nor_zerolength(mpt);
409assert(format != NULL);
410
411 if (!strcmp(mpt, "/1")) {
412 mr_asprintf(mountpoint, "/");
413 log_msg(3, "Mommm! SME is being a dildo!");
414 } else {
415 mr_asprintf(mountpoint, "%s", mpt);
416 }
417
418 if (!strcmp(mountpoint, "lvm")) {
419 return (0);
420 }
421 if (!strcmp(mountpoint, "image")) {
422 return (0);
423 }
424 mr_asprintf(tmp, "Mounting device %s ", device);
425 log_msg(1, tmp);
426 /* Deal with additional params only if not /proc or /sys */
427 mr_asprintf(additional_parameters, "");
428 if (strcmp(format, "proc") && strcmp(format, "sys")) {
429 if (writeable) {
430 mr_strcat(additional_parameters, "-o rw");
431 } else {
432 mr_strcat(additional_parameters, "-o ro");
433 }
434 if (find_home_of_exe("setfattr")) {
435 mr_strcat(additional_parameters, ",user_xattr");
436 }
437 if (find_home_of_exe("setfacl")) {
438 mr_strcat(additional_parameters, ",acl");
439 }
440 }
441
442 if (!strcmp(mountpoint, "swap")) {
443 mr_asprintf(command, "swapon %s", device);
444 mr_asprintf(mountdir, "swap");
445 } else {
446 if (!strcmp(mountpoint, "/")) {
447 mr_asprintf(mountdir, "%s", MNT_RESTORING);
448 } else {
449 mr_asprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
450 }
451 mr_asprintf(command, "mkdir -p %s", mountdir);
452 run_program_and_log_output(command, FALSE);
453 mr_free(command);
454
455 mr_asprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE);
456 log_msg(2, "command='%s'", command);
457 }
458 mr_free(additional_parameters);
459
460 res = run_program_and_log_output(command, TRUE);
461 if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
462 log_msg(1, "Re-trying without the fancy extra parameters");
463 mr_free(command);
464 mr_asprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE);
465 res = run_program_and_log_output(command, TRUE);
466 }
467 if (res) {
468 log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir);
469 log_msg(1, "command was '%s'", command);
470 if (!strcmp(mountpoint, "swap")) {
471 log_to_screen(tmp);
472 } else {
473 log_msg(2, "Retrying w/o the '-t' switch");
474 mr_free(command);
475 mr_asprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE);
476 log_msg(2, "2nd command = '%s'", command);
477 res = run_program_and_log_output(command, TRUE);
478 if (res == 0) {
479 log_msg(1,
480 "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
481 } else {
482 log_to_screen(tmp);
483 }
484 }
485 }
486
487 if (res && !strcmp(mountpoint, "swap")) {
488 log_msg(2, "That's ok. It's just a swap partition.");
489 log_msg(2, "Non-fatal error. Returning 0.");
490 res = 0;
491 }
492
493mr_free(tmp);
494mr_free(command);
495mr_free(mountdir);
496mr_free(mountpoint);
497
498return (res);
499}
500/**************************************************************************
501 *END_MOUNT_DEVICE *
502**************************************************************************/
503
504
505/**
506 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
507 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
508 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
509 * @return The number of errors encountered (0 for success).
510 */
511int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable)
512{
513int retval = 0, lino, res;
514char *tmp = NULL;
515char *these_failed = NULL;
516struct mountlist_itself *mountlist = NULL;
517
518assert(p_external_copy_of_mountlist != NULL);
519mountlist = malloc(sizeof(struct mountlist_itself));
520memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
521 sizeof(struct mountlist_itself));
522 sort_mountlist_by_mountpoint(mountlist, 0);
523
524
525 mvaddstr_and_log_it(g_currentY, 0, "Mounting devices ");
526 open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries);
527
528 mr_asprintf(these_failed, "");
529 for (lino = 0; lino < mountlist->entries; lino++) {
530 if (!strcmp(mountlist->el[lino].device, "/proc")) {
531 log_msg(1, "Again with the /proc - why is this in your mountlist?");
532 } else if (is_this_device_mounted(mountlist->el[lino].device)) {
533 log_to_screen("%s is already mounted", mountlist->el[lino].device);
534 } else if (strcmp(mountlist->el[lino].mountpoint, "none")
535 && strcmp(mountlist->el[lino].mountpoint, "lvm")
536 && strcmp(mountlist->el[lino].mountpoint, "raid")
537 && strcmp(mountlist->el[lino].mountpoint, "image")) {
538 mr_asprintf(tmp, "Mounting %s", mountlist->el[lino].device);
539 update_progress_form(tmp);
540 mr_free(tmp);
541 res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, mountlist->el[lino].format, writeable);
542 retval += res;
543 if (res) {
544 mr_strcat(these_failed, "%s ",mountlist->el[lino].device);
545 }
546 }
547 g_current_progress++;
548 }
549 close_progress_form();
550 if (retval) {
551 if (g_partition_table_locked_up > 0) {
552 log_to_screen("fdisk's ictol() call to refresh its copy of the partition table causes the kernel to");
553 log_to_screen("lock up the partition table. You might have to reboot and use Interactive Mode to");
554 log_to_screen("format and restore *without* partitioning first. Sorry for the inconvenience.");
555 }
556 mr_asprintf(tmp, "Could not mount device(s) %s- shall I abort?", these_failed);
557
558 if (!ask_me_yes_or_no(tmp)) {
559 retval = 0;
560 log_to_screen("Continuing, although some device(s) failed to be mounted");
561 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
562 } else {
563 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
564 log_to_screen("Unable to mount some or all of your partitions.");
565 }
566 mr_free(tmp);
567 } else {
568 log_to_screen("All partitions were mounted OK.");
569 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
570 }
571 paranoid_free(these_failed);
572
573 /* Also mounting under MNT_RESTORING special FS */
574 (void)mount_device("/proc","/proc","proc",TRUE);
575 (void)mount_device("/sys","/sys","sysfs",TRUE);
576 run_program_and_log_output("df -m -P", 3);
577 paranoid_free(mountlist);
578 return (retval);
579}
580/**************************************************************************
581*END_MOUNT_ALL_DEVICES *
582**************************************************************************/
583
584
585/**
586* Fix some miscellaneous things in the filesystem so the system will come
587* up correctly on the first boot.
588*/
589void protect_against_braindead_sysadmins()
590{
591run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
592 FALSE);
593run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
594 FALSE);
595if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
596run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp",
597 FALSE);
598}
599run_program_and_log_output("mkdir -p " MNT_RESTORING
600 "/var/run/console", FALSE);
601run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null",
602 FALSE);
603run_program_and_log_output("cd " MNT_RESTORING
604 "; for i in `ls home/`; do echo \"Moving $i's spurious files to $i/.disabled\"; mkdir \"$i\"/.disabled ; mv -f \"$i\"/.DCOP* \"$i\"/.MCOP* \"$i\"/.*authority \"$i\"/.kde/tmp* \"$i\"/.kde/socket* \"$i\"/.disabled/ ; done",
605 TRUE);
606run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
607 TRUE);
608run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
609 TRUE);
610}
611
612/**************************************************************************
613*END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS *
614**************************************************************************/
615
616
617
618
619/**
620* Fill out @p bkpinfo based on @p cfg_file.
621* @param cfg_file The mondorestore.cfg file to read into @p bkpinfo.
622* @param bkpinfo The backup information structure to fill out with information
623* from @p cfg_file.
624* @return 0 for success, nonzero for failure.
625*/
626int read_cfg_file_into_bkpinfo(char *cfgf)
627{
628/** add mallocs **/
629char value[MAX_STR_LEN];
630char *tmp1 = NULL;
631char *envtmp1 = NULL;
632char *envtmp2 = NULL;
633char *command = NULL;
634char iso_mnt[MAX_STR_LEN];
635char iso_path[MAX_STR_LEN];
636char *old_isodir = NULL;
637char *cfg_file = NULL;
638t_bkptype media_specified_by_user;
639
640// assert_string_is_neither_NULL_nor_zerolength(cfg_file);
641assert(bkpinfo != NULL);
642assert(cfgf != NULL);
643log_it("Entering read_cfg_file_into_bkpinfo");
644
645if (!cfgf) {
646 mr_asprintf(cfg_file, "%s", g_mondo_cfg_file);
647} else {
648 mr_asprintf(cfg_file, "%s", cfgf);
649}
650
651media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
652
653if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
654 if (!strcmp(value, "cdstream")) {
655 bkpinfo->backup_media_type = cdstream;
656 } else if (!strcmp(value, "cdr")) {
657 bkpinfo->backup_media_type = cdr;
658 } else if (!strcmp(value, "cdrw")) {
659 bkpinfo->backup_media_type = cdrw;
660 } else if (!strcmp(value, "dvd")) {
661 bkpinfo->backup_media_type = dvd;
662 } else if (!strcmp(value, "usb")) {
663 bkpinfo->backup_media_type = usb;
664 bkpinfo->please_dont_eject = TRUE;
665 } else if (!strcmp(value, "iso")) {
666 bkpinfo->backup_media_type = iso;
667 if (am_I_in_disaster_recovery_mode()) {
668 /* Check to see if CD is already mounted before mounting it... */
669 if (!is_this_device_mounted("/dev/cdrom")) {
670 log_msg(2, "NB: CDROM device not mounted, mounting...");
671 run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1);
672 }
673 if (does_file_exist(MNT_CDROM"/archives/filelist.0")) {
674 bkpinfo->backup_media_type = cdr;
675 run_program_and_log_output("umount -d "MNT_CDROM, 1);
676 log_it("Re-jigging configuration AGAIN. CD-R, not ISO.");
677 }
678 }
679 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
680 strcpy(bkpinfo->prefix,value);
681 } else {
682 strcpy(bkpinfo->prefix,STD_PREFIX);
683 }
684 log_it("Setting Prefix to %s", bkpinfo->prefix);
685 } else if ((!strcmp(value, "netfs")) || (!strcmp(value, "nfs"))) {
686 /* Stay compatible with previous versions by allowing nfs as an entry here */
687 bkpinfo->backup_media_type = netfs;
688 bkpinfo->please_dont_eject = TRUE;
689 if (read_cfg_var(cfg_file, "netfs-proto", value) == 0) {
690 mr_asprintf(bkpinfo->netfs_proto,"%s", value);
691 } else {
692 /* For compatibility, force protocol in old nfs case to be transparent */
693 mr_asprintf(bkpinfo->netfs_proto, "nfs");
694 }
695 if (read_cfg_var(cfg_file, "netfs-server-user", value) == 0) {
696 mr_asprintf(bkpinfo->netfs_user,"%s", value);
697 }
698 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
699 strcpy(bkpinfo->prefix,value);
700 } else {
701 strcpy(bkpinfo->prefix,STD_PREFIX);
702 }
703 if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "pxe")) {
704 /* We need to override prefix value in PXE mode as it's
705 * already done in start-netfs */
706 envtmp1 = getenv("imgname");
707 if (envtmp1 == NULL) {
708 fatal_error("no imgname variable in environment");
709 }
710 strcpy(bkpinfo->prefix,envtmp1);
711 }
712 } else if (!strcmp(value, "tape")) {
713 bkpinfo->backup_media_type = tape;
714 } else if (!strcmp(value, "udev")) {
715 bkpinfo->backup_media_type = udev;
716 } else {
717 fatal_error("UNKNOWN bkp-media-type");
718 }
719} else {
720 fatal_error("backup-media-type not specified!");
721}
722
723if (bkpinfo->disaster_recovery) {
724 if (bkpinfo->backup_media_type == cdstream) {
725 sprintf(bkpinfo->media_device, "/dev/cdrom");
726 bkpinfo->media_size = 650; /* good guess */
727 } else if (bkpinfo->backup_media_type == usb) {
728 envtmp1 = getenv("MRUSBDEV");
729 if (envtmp1 == NULL) {
730 if (read_cfg_var(cfg_file, "usb-dev", value)) {
731 fatal_error("Cannot get USB device name from cfg file");
732 }
733 } else {
734 strcpy(value,envtmp1);
735 }
736 sprintf(bkpinfo->media_device, "%s1", value);
737 log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
738 } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
739 if (read_cfg_var(cfg_file, "media-dev", value)) {
740 fatal_error("Cannot get tape device name from cfg file");
741 }
742 strcpy(bkpinfo->media_device, value);
743 read_cfg_var(cfg_file, "media-size", value);
744 bkpinfo->media_size = atol(value);
745 log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
746 } else {
747 strcpy(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
748 bkpinfo->media_size = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
749 log_msg(2, "Backup medium is similar to CD-R[W]");
750 }
751} else {
752 log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
753}
754
755read_cfg_var(cfg_file, "use-star", value);
756if (strstr(value, "yes")) {
757 bkpinfo->use_star = TRUE;
758 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
759}
760
761read_cfg_var(cfg_file, "obdr", value);
762if (strstr(value, "TRUE")) {
763 bkpinfo->use_obdr = TRUE;
764 log_msg(1, "OBDR mode activated");
765}
766
767read_cfg_var(cfg_file, "acl", value);
768if (strstr(value, "TRUE")) {
769 mr_asprintf(g_getfacl,"setfacl");
770 log_msg(1, "We will restore ACLs");
771 if (! find_home_of_exe("setfacl")) {
772 log_msg(1, "Unable to restore ACLs as no setfacl found");
773 }
774}
775read_cfg_var(cfg_file, "xattr", value);
776if (strstr(value, "TRUE")) {
777 mr_asprintf(g_getfattr,"setfattr");
778 log_msg(1, "We will restore XATTRs");
779 if (! find_home_of_exe("setfattr")) {
780 log_msg(1, "Unable to restore XATTRs as no setfattr found");
781 }
782}
783
784if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
785 bkpinfo->internal_tape_block_size = atol(value);
786} else {
787 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
788}
789log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
790
791read_cfg_var(cfg_file, "use-lzma", value);
792if (strstr(value, "yes")) {
793 bkpinfo->use_lzma = TRUE;
794 bkpinfo->use_lzo = FALSE;
795 bkpinfo->use_gzip = FALSE;
796 strcpy(bkpinfo->zip_exe, "lzma");
797 strcpy(bkpinfo->zip_suffix, "lzma");
798}
799
800read_cfg_var(cfg_file, "use-lzo", value);
801if (strstr(value, "yes")) {
802 bkpinfo->use_lzma = FALSE;
803 bkpinfo->use_lzo = TRUE;
804 bkpinfo->use_gzip = FALSE;
805 strcpy(bkpinfo->zip_exe, "lzop");
806 strcpy(bkpinfo->zip_suffix, "lzo");
807}
808
809read_cfg_var(cfg_file, "use-gzip", value);
810if (strstr(value, "yes")) {
811 bkpinfo->use_lzma = FALSE;
812 bkpinfo->use_lzo = FALSE;
813 bkpinfo->use_gzip = TRUE;
814 strcpy(bkpinfo->zip_exe, "gzip");
815 strcpy(bkpinfo->zip_suffix, "gz");
816}
817
818read_cfg_var(cfg_file, "use-comp", value);
819if (strstr(value, "yes")) {
820 bkpinfo->use_lzma = FALSE;
821 bkpinfo->use_lzo = FALSE;
822 bkpinfo->use_gzip = FALSE;
823 strcpy(bkpinfo->zip_exe, "bzip2");
824 strcpy(bkpinfo->zip_suffix, "bz2");
825}
826
827value[0] = '\0';
828read_cfg_var(cfg_file, "differential", value);
829if (!strcmp(value, "yes") || !strcmp(value, "1")) {
830 bkpinfo->differential = TRUE;
831}
832log_msg(2, "differential var = '%s'", value);
833if (bkpinfo->differential) {
834 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
835} else {
836 log_msg(2, "This is a regular (full) backup");
837}
838
839read_cfg_var(cfg_file, "please-dont-eject", value);
840if (value[0] || strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "donteject")) {
841 bkpinfo->please_dont_eject = TRUE;
842 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
843}
844
845if (bkpinfo->backup_media_type == netfs) {
846 if (!cfgf) {
847 if (bkpinfo->netfs_mount) {
848 log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
849 }
850 if (bkpinfo->netfs_remote_dir != NULL) {
851 log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
852 }
853 log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
854 } else {
855 read_cfg_var(cfg_file, "netfs-server-mount", value);
856 mr_free(bkpinfo->netfs_mount);
857 mr_asprintf(bkpinfo->netfs_mount, "%s", value);
858 if (bkpinfo->netfs_mount != NULL) {
859 log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
860 }
861
862 read_cfg_var(cfg_file, "iso-dir", value);
863 mr_free(bkpinfo->netfs_remote_dir);
864 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", value);
865 if (bkpinfo->netfs_remote_dir != NULL) {
866 log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
867 }
868
869 if (bkpinfo->netfs_proto != NULL) {
870 log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
871 }
872 if (bkpinfo->netfs_user != NULL) {
873 log_msg(2, "netfs_user is %s", bkpinfo->netfs_user);
874 }
875 }
876 if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "pxe")) {
877 /* We need to override values in PXE mode as it's
878 * already done in start-netfs */
879 envtmp1 = getenv("netfsmount");
880 if (envtmp1 == NULL) {
881 fatal_error("no netfsmount variable in environment");
882 }
883 envtmp2 = getenv("dirimg");
884 if (envtmp2 == NULL) {
885 fatal_error("no dirimg variable in environment");
886 }
887 mr_free(bkpinfo->netfs_mount);
888 mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
889
890 mr_free(bkpinfo->netfs_remote_dir);
891 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
892 }
893} else if (bkpinfo->backup_media_type == iso) {
894 /* Patch by Conor Daly 23-june-2004
895 * to correctly mount iso-dev and set a sensible
896 * isodir in disaster recovery mode
897 */
898 mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
899 read_cfg_var(cfg_file, "iso-mnt", iso_mnt);
900 read_cfg_var(cfg_file, "iso-dir", iso_path);
901 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
902 if (!bkpinfo->isodir[0]) {
903 strcpy(bkpinfo->isodir, old_isodir);
904 }
905 if ((!bkpinfo->disaster_recovery) || (g_isodir_device[0] != '\0')) {
906 if (strcmp(old_isodir, bkpinfo->isodir)) {
907 log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
908 strcpy(bkpinfo->isodir, old_isodir);
909 }
910 }
911 mr_free(old_isodir);
912
913 if (g_isodir_device[0] == '\0') {
914 /* We don't want to loose our conf made earlier in iso_fiddly_bits
915 * so go here only if job not done already */
916 read_cfg_var(cfg_file, "iso-dev", g_isodir_device);
917 }
918
919 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
920
921 if (bkpinfo->disaster_recovery) {
922 if (is_this_device_mounted(g_isodir_device)) {
923 log_msg(2, "NB: isodir is already mounted");
924 /* Find out where it's mounted */
925 mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
926 log_it("command = %s", command);
927 log_it("res of it = %s", call_program_and_get_last_line_of_output(command));
928 sprintf(iso_mnt, "%s", call_program_and_get_last_line_of_output(command));
929 mr_free(command);
930 } else {
931 sprintf(iso_mnt, "/tmp/isodir");
932 mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
933 run_program_and_log_output(tmp1, 5);
934 mr_free(tmp1);
935
936 mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
937 if (run_program_and_log_output(tmp1, 3)) {
938 log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
939 bkpinfo->backup_media_type = cdr;
940 strcpy(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
941 bkpinfo->isodir[0] = iso_mnt[0] = iso_path[0] = '\0';
942 if (mount_media()) {
943 mr_free(tmp1);
944 fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
945 } else {
946 log_msg(1, "You backed up to disk, then burned some CDs.");
947 }
948 }
949 mr_free(tmp1);
950 }
951 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
952 /* except when already done in iso_fiddly_bits */
953 if ((bkpinfo->backup_media_type == iso) && (g_isodir_device[0] == '\0')) {
954 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
955 }
956 }
957}
958mr_free(cfg_file);
959
960if (media_specified_by_user != none) {
961 if (g_restoring_live_from_cd) {
962 if (bkpinfo->backup_media_type != media_specified_by_user) {
963 log_msg(2, "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
964 interactively_obtain_media_parameters_from_user(FALSE);
965 media_specified_by_user = bkpinfo->backup_media_type;
966 get_cfg_file_from_archive();
967 }
968 }
969 bkpinfo->backup_media_type = media_specified_by_user;
970}
971g_backup_media_type = bkpinfo->backup_media_type;
972return (0);
973
974}
975
976/**************************************************************************
977*END_READ_CFG_FILE_INTO_BKPINFO *
978**************************************************************************/
979
980
981
982
983/**
984 * Allow the user to edit the filelist and biggielist.
985 * The filelist is unlinked after it is read.
986 * @param bkpinfo The backup information structure. Fields used:
987 * - @c bkpinfo->backup_media_type
988 * - @c bkpinfo->isodir
989 * - @c bkpinfo->media_device
990 * - @c bkpinfo->tmpdir
991 * @return The filelist structure containing the information read from disk.
992 */
993struct
994s_node *process_filelist_and_biggielist()
995{
996struct s_node *filelist;
997
998char *command = NULL;
999char *tmp;
1000char *q;
1001int res = 0;
1002pid_t pid;
1003bool extract_mountlist_stub = FALSE;
1004
1005assert(bkpinfo != NULL);
1006malloc_string(tmp);
1007
1008/* If those files already exist, do not overwrite them later on */
1009if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
1010 extract_mountlist_stub = FALSE;
1011} else {
1012 extract_mountlist_stub = TRUE;
1013}
1014
1015if (does_file_exist(g_filelist_full)
1016&& does_file_exist(g_biggielist_txt)) {
1017 log_msg(1, "%s exists", g_filelist_full);
1018 log_msg(1, "%s exists", g_biggielist_txt);
1019 log_msg(2,
1020 "Filelist and biggielist already recovered from media. Yay!");
1021} else {
1022 if (getcwd(tmp, MAX_STR_LEN) == NULL) {
1023 // FIXME
1024 }
1025 if (chdir(bkpinfo->tmpdir)) {
1026 // FIXME
1027 }
1028 log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1029 log_to_screen("Extracting filelist and biggielist from media...");
1030 unlink("/tmp/filelist.full");
1031 unlink(FILELIST_FULL_STUB);
1032 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1033 mr_asprintf(command, "tar -b %ld -zxf %s ./%s ./%s ./%s ./%s ./%s", bkpinfo->internal_tape_block_size, bkpinfo->media_device, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB);
1034 log_msg(1, "tarcommand = %s", command);
1035 run_program_and_log_output(command, 1);
1036 mr_free(command);
1037
1038 if (!does_file_exist(FILELIST_FULL_STUB)) {
1039 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1040 log_msg(2, "pre-2.2.4 compatible mode on");
1041 mr_asprintf(command, "tar -b %ld -zxf %s %s %s %s %s %s", bkpinfo->internal_tape_block_size, bkpinfo->media_device, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB);
1042 log_msg(1, "tarcommand = %s", command);
1043 run_program_and_log_output(command, 1);
1044 mr_free(command);
1045 }
1046 } else {
1047 log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
1048 insist_on_this_cd_number(1);
1049 log_msg(2, "Back from iotcn");
1050 run_program_and_log_output("mount", 1);
1051 mr_asprintf(command, "tar -zxf %s/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MNT_CDROM, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB);
1052
1053 log_msg(1, "tarcommand = %s", command);
1054 run_program_and_log_output(command, 1);
1055 mr_free(command);
1056
1057 if (!does_file_exist(FILELIST_FULL_STUB)) {
1058 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1059 log_msg(2, "pre-2.2.4 compatible mode on");
1060 mr_asprintf(command, "tar -zxf %s/images/all.tar.gz %s %s %s %s %s", MNT_CDROM, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB);
1061
1062 log_msg(1, "tarcommand = %s", command);
1063 run_program_and_log_output(command, 1);
1064 mr_free(command);
1065 }
1066 if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1067 fatal_error("all.tar.gz did not include " BIGGIELIST_TXT_STUB);
1068 }
1069 if (!does_file_exist(FILELIST_FULL_STUB)) {
1070 fatal_error("all.tar.gz did not include " FILELIST_FULL_STUB);
1071 }
1072 }
1073 mr_asprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB, g_mondo_cfg_file);
1074 run_program_and_log_output(command, FALSE);
1075 mr_free(command);
1076
1077 mr_asprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir, BIGGIELIST_TXT_STUB, g_biggielist_txt);
1078 log_msg(1, "command = %s", command);
1079 paranoid_system(command);
1080 mr_free(command);
1081
1082 mr_asprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir, FILELIST_FULL_STUB, g_filelist_full);
1083 log_msg(1, "command = %s", command);
1084 paranoid_system(command);
1085 mr_free(command);
1086 }
1087
1088 if (am_I_in_disaster_recovery_mode()
1089 &&
1090 /* If it was there, do not overwrite it */
1091 (extract_mountlist_stub)
1092 &&
1093 ask_me_yes_or_no("Do you want to retrieve the mountlist as well?"))
1094 {
1095 mr_asprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir);
1096 paranoid_system(command);
1097 mr_free(command);
1098 }
1099
1100 if (chdir(tmp)) {
1101 // FIXME
1102 }
1103
1104 if (!does_file_exist(g_biggielist_txt)) {
1105 log_msg(1, "Warning - %s not found", g_biggielist_txt);
1106 }
1107 if (!does_file_exist(g_filelist_full)) {
1108 log_msg(1, "Warning - %s does not exist", g_filelist_full);
1109 }
1110
1111 log_msg(2, "Forking");
1112 pid = fork();
1113 switch (pid) {
1114 case -1:
1115 fatal_error("Forking error");
1116 break;
1117
1118 case 0:
1119 log_to_screen("Pre-processing filelist");
1120 if (!does_file_exist(g_biggielist_txt)) {
1121 mr_asprintf(command, "echo -n > %s", g_biggielist_txt);
1122 paranoid_system(command);
1123 mr_free(command);
1124 }
1125 mr_asprintf(command, "grep -E '^/dev/.*' %s > %s", g_biggielist_txt, g_filelist_imagedevs);
1126 paranoid_system(command);
1127 mr_free(command);
1128 exit(0);
1129 break;
1130
1131 default:
1132 open_evalcall_form("Pre-processing filelist");
1133 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1134 usleep(100000);
1135 update_evalcall_form(0);
1136 }
1137 }
1138 close_evalcall_form();
1139
1140 log_msg(3, "loading filelist");
1141 filelist = load_filelist(g_filelist_full);
1142 log_msg(3, "deleting original filelist");
1143 unlink(g_filelist_full);
1144 if (g_text_mode) {
1145 q = NULL;
1146 while (q == NULL) {
1147 printf("Restore which directory? --> ");
1148 mr_getline(q, stdin);
1149 }
1150 toggle_path_selection(filelist, q, TRUE);
1151 if (strlen(q) == 0) {
1152 res = 1;
1153 } else {
1154 res = 0;
1155 }
1156 mr_free(q);
1157 } else {
1158 res = edit_filelist(filelist);
1159 }
1160 if (res) {
1161 log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1162 free_filelist(filelist);
1163 return (NULL);
1164 }
1165 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1166 close_evalcall_form();
1167
1168 // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1169 // file. The filelist.full file already contains the filename of EVERY
1170 // file backed up - regular and biggie files.
1171
1172 // However, we do want to make sure the imagedevs selected by the user
1173 // are flagged for restoring.
1174 if (length_of_file(g_imagedevs_restthese) > 2) {
1175 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1176 TRUE);
1177 }
1178
1179 paranoid_free(tmp);
1180 return (filelist);
1181}
1182
1183/**************************************************************************
1184 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1185 **************************************************************************/
1186
1187
1188
1189
1190/**
1191 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1192 * The backup filename is the filename of the original with ".pristine" added.
1193 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1194 * @param filename The filename (absolute path) within @p path_root.
1195 * @return 0 for success, nonzero for failure.
1196 */
1197int backup_crucial_file(char *path_root, char *filename)
1198{
1199 char *tmp = NULL;
1200 char *command = NULL;
1201 int res;
1202
1203 assert(path_root != NULL);
1204 assert_string_is_neither_NULL_nor_zerolength(filename);
1205
1206 mr_asprintf(tmp, "%s/%s", path_root, filename);
1207 mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1208 mr_free(tmp);
1209
1210 res = run_program_and_log_output(command, 5);
1211 mr_free(command);
1212 return (res);
1213}
1214
1215void offer_to_make_initrd() {
1216
1217if (bkpinfo->restore_mode != nuke) {
1218 if (ask_me_yes_or_no
1219 ("You will now be able to re-generate your initrd.\nThis is especially useful if you changed of hardware configuration, cloned, made P2V, used multipath...\nDo you need to do it ?")) {
1220 log_msg(1,"Launching shell for manual initrd recreation");
1221 if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1222 popup_and_OK("You'll now be chrooted under your future / partition.\nEdit /etc/mkinitcpio.conf if needed and rebuild your initrd with the kernel preset name e.g.\nmkinitcpio -p kernel26\nThen type exit to finish.\n");
1223 } else {
1224 popup_and_OK("You'll now be chrooted under your future / partition.\nGo under /boot and rebuild your init(rd|ramfs) with\nmkinitrd -f -v initrd-2.x.y.img 2.x.y e.g.\nor initramfs, dracut, ... Then type exit to finish.");
1225 }
1226 mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1227 if (!g_text_mode) {
1228 newtSuspend();
1229 }
1230 paranoid_system("chroot " MNT_RESTORING);
1231 if (!g_text_mode) {
1232 newtResume();
1233 }
1234 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1235 } else {
1236 return;
1237 }
1238} else {
1239 log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1240 log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1241}
1242}
1243
1244
1245/**
1246 * Install the user's boot loader in the MBR.
1247 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1248 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1249 * @return 0 for success, nonzero for failure.
1250 */
1251int run_boot_loader(bool offer_to_hack_scripts)
1252{
1253 int res;
1254 int retval = 0;
1255
1256 /** malloc *******/
1257 char *device = NULL;
1258 char *name = NULL;
1259 char *cmd = NULL;
1260
1261 malloc_string(device);
1262 malloc_string(name);
1263
1264 /* In order to have a working bootloader, we need to have all devices
1265 * ready in the chroot. If they are not there (udev) then copy them from
1266 * the current /dev location
1267 */
1268 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1269 run_program_and_log_output(cmd, 3);
1270 paranoid_free(cmd);
1271
1272 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1273 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1274 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1275 backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
1276 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1277 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1278 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1279 backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
1280 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1281 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1282 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1283 log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1284 sync();
1285
1286 offer_to_make_initrd();
1287 if (!strcmp(name, "LILO")) {
1288 res = run_lilo(offer_to_hack_scripts);
1289 } else if (!strcmp(name, "ELILO")) {
1290 res = run_elilo(offer_to_hack_scripts);
1291 } else if (!strcmp(name, "GRUB")) {
1292 res = run_grub(offer_to_hack_scripts, device);
1293 } else if (!strcmp(name, "RAW")) {
1294 res = run_raw_mbr(offer_to_hack_scripts, device);
1295 }
1296#ifdef __FreeBSD__
1297 else if (!strcmp(name, "BOOT0")) {
1298 mr_asprintf(tmp, "boot0cfg -B %s", device);
1299 res = run_program_and_log_output(tmp, FALSE);
1300 paranoid_free(tmp);
1301 } else {
1302 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1303 if (!system(tmp)) {
1304 mr_free(tmp);
1305 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1306 res = run_program_and_log_output(tmp, 3);
1307 } else {
1308 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1309 }
1310 mr_free(tmp);
1311 }
1312#else
1313 else {
1314 log_to_screen
1315 ("Unable to determine type of boot loader. Defaulting to LILO.");
1316 res = run_lilo(offer_to_hack_scripts);
1317 }
1318#endif
1319 retval += res;
1320 if (res) {
1321 log_to_screen("Your boot loader returned an error");
1322 } else {
1323 log_to_screen("Your boot loader ran OK");
1324 }
1325 paranoid_free(device);
1326 paranoid_free(name);
1327 return (retval);
1328}
1329
1330/**************************************************************************
1331 *END_ RUN_BOOT_LOADER *
1332 **************************************************************************/
1333
1334
1335
1336/**
1337 * Attempt to find the user's editor.
1338 * @return The editor found ("vi" if none could be found).
1339 * @note The returned string points to static storage that will be overwritten with each call.
1340 */
1341char *find_my_editor(void) {
1342
1343 static char output[MAX_STR_LEN];
1344 if (find_home_of_exe("pico")) {
1345 strcpy(output, "pico");
1346 } else if (find_home_of_exe("nano")) {
1347 strcpy(output, "nano");
1348 } else if (find_home_of_exe("e3em")) {
1349 strcpy(output, "e3em");
1350 } else if (find_home_of_exe("e3vi")) {
1351 strcpy(output, "e3vi");
1352 } else {
1353 strcpy(output, "vi");
1354 }
1355 if (!find_home_of_exe(output)) {
1356 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1357 }
1358 return (output);
1359}
1360
1361
1362/**
1363 * Install GRUB on @p bd.
1364 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1365 * @param bd The boot device where GRUB is installed.
1366 * @return 0 for success, nonzero for failure.
1367 */
1368int run_grub(bool offer_to_run_stabgrub, char *bd)
1369{
1370 /** malloc **/
1371 char *command = NULL;
1372 char *boot_device = NULL;
1373 char *tmp = NULL;
1374 char *editor = NULL;
1375
1376 bool done;
1377 int res = 0; /* FALSE */
1378 bool mntlistchg = FALSE;
1379 FILE *fin = NULL;
1380
1381 malloc_string(boot_device);
1382
1383 assert_string_is_neither_NULL_nor_zerolength(bd);
1384 strcpy(boot_device, bd);
1385
1386 if (offer_to_run_stabgrub
1387 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1388 /* interactive mode */
1389 mvaddstr_and_log_it(g_currentY,
1390 0,
1391 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
1392 /* Did we changed the mountlist ? If yes, then force editing conf files */
1393 if ((fin = fopen(MONDO_MNTLISTCHG, "r")) != NULL) {
1394 mntlistchg = TRUE;
1395 }
1396 for (done = FALSE; !done;) {
1397 popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4);
1398 /* Only try to adapt grub here first if the mountlist wasn't changed before */
1399 if (! mntlistchg) {
1400 mr_asprintf(command, "stabgrub-me %s", boot_device);
1401 res = run_program_and_log_output(command, 1);
1402 mr_free(command);
1403 }
1404
1405 if ((res) || (mntlistchg)) {
1406 if (res) {
1407 popup_and_OK("GRUB installation failed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
1408 } else {
1409 popup_and_OK("The mountlist was changed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
1410 }
1411 if (!g_text_mode) {
1412 newtSuspend();
1413 }
1414 mr_asprintf(editor, "%s", find_my_editor());
1415 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1416 paranoid_system(tmp);
1417 mr_free(tmp);
1418
1419 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1420 paranoid_system(tmp);
1421 mr_free(tmp);
1422
1423 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1424 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1425 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1426 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1427 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/grub.cfg")) {
1428 mr_asprintf(tmp, "chroot %s %s /boot/grub2/grub.cfg", MNT_RESTORING, editor);
1429 }
1430 paranoid_system(tmp);
1431 mr_free(tmp);
1432
1433 if (does_file_exist(MNT_RESTORING"/boot/grub/device.map")) {
1434 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1435 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/device.map")) {
1436 mr_asprintf(tmp, "chroot %s %s /boot/grub2/device.map", MNT_RESTORING, editor);
1437 }
1438 paranoid_system(tmp);
1439 mr_free(tmp);
1440 mr_free(editor);
1441
1442 if (!g_text_mode) {
1443 newtResume();
1444 }
1445 mr_asprintf(command, "stabgrub-me %s", boot_device);
1446 res = run_program_and_log_output(command, 1);
1447 mr_free(command);
1448
1449 if (res) {
1450 popup_and_OK("GRUB installation failed. Please fix the conf files so that a manual install using 'grub-install' or similar command works. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1451 newtSuspend();
1452 paranoid_system("chroot " MNT_RESTORING);
1453 newtResume();
1454 popup_and_OK("Thank you.");
1455 } else {
1456 popup_and_OK("GRUB is now installed correctly");
1457 done = TRUE;
1458 }
1459 } else {
1460 done = TRUE;
1461 }
1462 }
1463 } else {
1464 /* nuke mode */
1465 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1466 log_msg(1, "Yay! grub-MR found...");
1467 mr_asprintf(command, "grub-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1468 log_msg(1, "command = %s", command);
1469 } else {
1470 mr_asprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device);
1471 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1472 }
1473 mvaddstr_and_log_it(g_currentY, 0, "Running GRUB... ");
1474 log_it("%s",command);
1475 res = run_program_and_log_output(command, 1);
1476 mr_free(command);
1477
1478 if (res) {
1479 popup_and_OK
1480 ("Because of bugs in GRUB's own installer, GRUB was not installed properly. Please install the boot loader manually now, using this chroot()'ed shell prompt. Type 'exit' when you have finished.");
1481 newtSuspend();
1482 paranoid_system("chroot " MNT_RESTORING);
1483 newtResume();
1484 popup_and_OK("Thank you.");
1485 }
1486 }
1487 if (res) {
1488 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1489 log_to_screen
1490 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1491 log_msg(1, "Type:-");
1492 log_msg(1, " mount-me");
1493 log_msg(1, " chroot " MNT_RESTORING);
1494 log_msg(1, " mount /boot");
1495 log_msg(1, " grub-install '(hd0)'");
1496 log_msg(1, " exit");
1497 log_msg(1, " unmount-me");
1498 log_msg(1,
1499 "If you're really stuck, please e-mail the mailing list.");
1500 } else {
1501 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1502 }
1503 paranoid_free(boot_device);
1504
1505 return (res);
1506}
1507
1508/**************************************************************************
1509 *END_RUN_GRUB *
1510 **************************************************************************/
1511
1512
1513/**
1514 * Install ELILO on the user's boot drive (determined by elilo.conf).
1515 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1516 * @return 0 for success, nonzero for failure.
1517 */
1518int run_elilo(bool offer_to_run_stabelilo)
1519{
1520 /** malloc **/
1521 char *command = NULL;
1522 char *tmp = NULL;
1523 char *editor = NULL;
1524
1525 int res;
1526 int done;
1527
1528 if (offer_to_run_stabelilo
1529 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1530
1531 /* interactive mode */
1532 {
1533 mvaddstr_and_log_it(g_currentY,
1534 0,
1535 "Modifying fstab and elilo.conf... ");
1536 mr_asprintf(command, "stabelilo-me");
1537 res = run_program_and_log_output(command, 3);
1538 mr_free(command);
1539
1540 if (res) {
1541 popup_and_OK
1542 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1543 for (done = FALSE; !done;) {
1544 if (!g_text_mode) {
1545 newtSuspend();
1546 }
1547 mr_asprintf(editor, "%s", find_my_editor());
1548
1549 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1550 paranoid_system(tmp);
1551 mr_free(tmp);
1552
1553 mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1554 paranoid_system(tmp);
1555 mr_free(tmp);
1556 mr_free(editor);
1557
1558 if (!g_text_mode) {
1559 newtResume();
1560 }
1561// newtCls();
1562 if (ask_me_yes_or_no("Edit them again?")) {
1563 continue;
1564 }
1565 done = TRUE;
1566 }
1567 } else {
1568 log_to_screen("elilo.conf and fstab were modified OK");
1569 }
1570 } else
1571 /* nuke mode */
1572 {
1573 res = TRUE;
1574 }
1575 return (res);
1576}
1577
1578/**************************************************************************
1579 *END_RUN_ELILO *
1580 **************************************************************************/
1581
1582
1583/**
1584 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1585 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1586 * @return 0 for success, nonzero for failure.
1587 */
1588int run_lilo(bool offer_to_run_stablilo)
1589{
1590 /** malloc **/
1591 char *command = NULL;
1592 char *tmp = NULL;
1593 char *editor = NULL;
1594
1595 int res;
1596 int done;
1597 bool run_lilo_M = FALSE;
1598
1599 if (!run_program_and_log_output
1600 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1601 run_lilo_M = TRUE;
1602 }
1603
1604 if (offer_to_run_stablilo
1605 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1606
1607 /* interactive mode */
1608 {
1609 mvaddstr_and_log_it(g_currentY,
1610 0,
1611 "Modifying fstab and lilo.conf, and running LILO... ");
1612 mr_asprintf(command, "stablilo-me");
1613 res = run_program_and_log_output(command, 3);
1614 mr_free(command);
1615
1616 if (res) {
1617 popup_and_OK
1618 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1619 for (done = FALSE; !done;) {
1620 if (!g_text_mode) {
1621 newtSuspend();
1622 }
1623 mr_asprintf(editor, "%s", find_my_editor());
1624
1625 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1626 paranoid_system(tmp);
1627 mr_free(tmp);
1628
1629 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1630 paranoid_system(tmp);
1631 mr_free(tmp);
1632 mr_free(editor);
1633
1634 if (!g_text_mode) {
1635 newtResume();
1636 }
1637// newtCls();
1638 if (ask_me_yes_or_no("Edit them again?")) {
1639 continue;
1640 }
1641 res =
1642 run_program_and_log_output("chroot " MNT_RESTORING
1643 " lilo -L", 3);
1644 if (res) {
1645 res =
1646 run_program_and_log_output("chroot " MNT_RESTORING
1647 " lilo", 3);
1648 }
1649 if (res) {
1650 done =
1651 ask_me_yes_or_no
1652 ("LILO failed. Re-edit system files?");
1653 } else {
1654 done = TRUE;
1655 }
1656 }
1657 } else {
1658 log_to_screen("lilo.conf and fstab were modified OK");
1659 }
1660 } else
1661 /* nuke mode */
1662 {
1663 mvaddstr_and_log_it(g_currentY,
1664 0,
1665 "Running LILO... ");
1666 res =
1667 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1668 3);
1669 if (res) {
1670 res =
1671 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1672 3);
1673 }
1674 if (res) {
1675 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1676 log_to_screen
1677 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1678 } else {
1679 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1680 }
1681 }
1682 if (run_lilo_M) {
1683 run_program_and_log_output("chroot " MNT_RESTORING
1684 " lilo -M /dev/hda", 3);
1685 run_program_and_log_output("chroot " MNT_RESTORING
1686 " lilo -M /dev/sda", 3);
1687 }
1688 return (res);
1689}
1690
1691/**************************************************************************
1692 *END_RUN_LILO *
1693 **************************************************************************/
1694
1695
1696/**
1697 * Install a raw MBR onto @p bd.
1698 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1699 * @param bd The device to copy the stored MBR to.
1700 * @return 0 for success, nonzero for failure.
1701 */
1702int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1703{
1704 /** malloc **/
1705 char *command = NULL;
1706 char *boot_device = NULL;
1707 char *tmp = NULL;
1708 char *editor;
1709 int res;
1710 int done;
1711
1712 malloc_string(boot_device);
1713 assert_string_is_neither_NULL_nor_zerolength(bd);
1714
1715 strcpy(boot_device, bd);
1716
1717 if (offer_to_hack_scripts
1718 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1719 /* interactive mode */
1720 mvaddstr_and_log_it(g_currentY, 0,
1721 "Modifying fstab and restoring MBR... ");
1722 for (done = FALSE; !done;) {
1723 if (!run_program_and_log_output("which vi", FALSE)) {
1724 popup_and_OK("You will now edit fstab");
1725 if (!g_text_mode) {
1726 newtSuspend();
1727 }
1728 mr_asprintf(editor, "%s", find_my_editor());
1729 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1730 mr_free(editor);
1731
1732 paranoid_system(tmp);
1733 mr_free(tmp);
1734 if (!g_text_mode) {
1735 newtResume();
1736 }
1737 }
1738 popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4);
1739 mr_asprintf(command, "stabraw-me %s", boot_device);
1740 res = run_program_and_log_output(command, 3);
1741 mr_free(command);
1742
1743 if (res) {
1744 done = ask_me_yes_or_no("Modifications failed. Re-try?");
1745 } else {
1746 done = TRUE;
1747 }
1748 }
1749 } else {
1750 /* nuke mode */
1751 mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1752 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1753
1754 mvaddstr_and_log_it(g_currentY, 0,
1755 "Restoring MBR... ");
1756 res = run_program_and_log_output(command, 3);
1757 mr_free(command);
1758 }
1759 if (res) {
1760 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1761 log_to_screen
1762 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1763 } else {
1764 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1765 }
1766 paranoid_free(boot_device);
1767 return (res);
1768}
1769
1770/**************************************************************************
1771 *END_RUN_RAW_MBR *
1772 **************************************************************************/
1773
1774
1775
1776/**
1777 * malloc() and set sensible defaults for the mondorestore filename variables.
1778 * @param bkpinfo The backup information structure. Fields used:
1779 * - @c bkpinfo->tmpdir
1780 * - @c bkpinfo->disaster_recovery
1781 */
1782void setup_MR_global_filenames()
1783{
1784 char *temppath;
1785
1786 assert(bkpinfo != NULL);
1787
1788 malloc_string(g_biggielist_txt);
1789 malloc_string(g_filelist_full);
1790 malloc_string(g_filelist_imagedevs);
1791 malloc_string(g_imagedevs_restthese);
1792 malloc_string(g_mondo_cfg_file);
1793 malloc_string(g_mountlist_fname);
1794 malloc_string(g_mondo_home);
1795 malloc_string(g_isodir_device);
1796 malloc_string(g_isodir_format);
1797
1798 temppath = bkpinfo->tmpdir;
1799
1800 sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1801 sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1802 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1803// sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1804 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1805 temppath);
1806 if (bkpinfo->disaster_recovery) {
1807 sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1808 sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1809 } else {
1810 sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1811 sprintf(g_mountlist_fname, "%s/%s", temppath,
1812 MOUNTLIST_FNAME_STUB);
1813 }
1814}
1815
1816/**************************************************************************
1817 *END_SET_GLOBAL_FILENAME *
1818 **************************************************************************/
1819
1820
1821/**
1822 * Copy @p input_file (containing the result of a compare) to @p output_file,
1823 * deleting spurious "changes" along the way.
1824 * @param output_file The output file to write with spurious changes removed.
1825 * @param input_file The input file, a list of changed files created by a compare.
1826 */
1827void streamline_changes_file(char *output_file, char *input_file)
1828{
1829 FILE *fin;
1830 FILE *fout;
1831 char *incoming = NULL;
1832
1833 assert_string_is_neither_NULL_nor_zerolength(output_file);
1834 assert_string_is_neither_NULL_nor_zerolength(input_file);
1835
1836 if (!(fin = fopen(input_file, "r"))) {
1837 log_OS_error(input_file);
1838 return;
1839 }
1840 if (!(fout = fopen(output_file, "w"))) {
1841 fatal_error("cannot open output_file");
1842 }
1843 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
1844 if (strncmp(incoming, "etc/adjtime", 11)
1845 && strncmp(incoming, "etc/mtab", 8)
1846 && strncmp(incoming, "tmp/", 4)
1847 && strncmp(incoming, "boot/map", 8)
1848 && !strstr(incoming, "incheckentry")
1849 && strncmp(incoming, "etc/mail/statistics", 19)
1850 && strncmp(incoming, "var/", 4))
1851 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1852 mr_free(incoming);
1853 }
1854 mr_free(incoming);
1855 paranoid_fclose(fout);
1856 paranoid_fclose(fin);
1857}
1858
1859/**************************************************************************
1860 *END_STREAMLINE_CHANGES_FILE *
1861 **************************************************************************/
1862
1863
1864/**
1865 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1866 */
1867void twenty_seconds_til_yikes()
1868{
1869 int i;
1870 /* MALLOC * */
1871 char *tmp = NULL;
1872
1873 if (does_file_exist("/tmp/NOPAUSE")) {
1874 return;
1875 }
1876 open_progress_form("CAUTION",
1877 "Be advised: I am about to ERASE your hard disk(s)!",
1878 "You may press Ctrl+Alt+Del to abort safely.",
1879 "", 20);
1880 for (i = 0; i < 20; i++) {
1881 g_current_progress = i;
1882 mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1883 update_progress_form(tmp);
1884 mr_free(tmp);
1885 sleep(1);
1886 }
1887 close_progress_form();
1888}
1889
1890/**************************************************************************
1891 *END_TWENTY_SECONDS_TIL_YIKES *
1892 **************************************************************************/
1893
1894
1895/**
1896 * Unmount all devices in @p p_external_copy_of_mountlist.
1897 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1898 * @return 0 for success, nonzero for failure.
1899 */
1900int unmount_all_devices(struct mountlist_itself
1901 *p_external_copy_of_mountlist)
1902{
1903 struct mountlist_itself *mountlist;
1904 int retval = 0, lino, res = 0, i;
1905 char *command = NULL;
1906 char *tmp = NULL;
1907
1908 assert(p_external_copy_of_mountlist != NULL);
1909
1910 mountlist = malloc(sizeof(struct mountlist_itself));
1911 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1912 sizeof(struct mountlist_itself));
1913 sort_mountlist_by_mountpoint(mountlist, 0);
1914
1915 run_program_and_log_output("df -m -P", 3);
1916 mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices ");
1917 open_progress_form("Unmounting devices",
1918 "Unmounting all devices that were mounted,",
1919 "in preparation for the post-restoration reboot.",
1920 "", mountlist->entries);
1921 if (chdir("/")) {
1922 // FIXME
1923 }
1924 for (i = 0;
1925 i < 10
1926 &&
1927 run_program_and_log_output
1928 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1929 i++) {
1930 sleep(1);
1931 log_msg(2, "Waiting for buffer() to finish");
1932 }
1933
1934 sync();
1935
1936 mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1937 if (run_program_and_log_output(tmp, FALSE)) {
1938 log_msg(1,
1939 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1940 }
1941 paranoid_free(tmp);
1942 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1943 run_program_and_log_output("mkdir -p " MNT_RESTORING
1944 "/mnt/.boot.d", 5);
1945 }
1946
1947 /* Unmounting the local /proc and /sys first */
1948 run_program_and_log_output("umount -d " MNT_RESTORING "/proc",3);
1949 run_program_and_log_output("umount -d " MNT_RESTORING "/sys",3);
1950
1951 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1952 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1953 continue;
1954 }
1955 mr_asprintf(tmp, "Unmounting device %s ", mountlist->el[lino].device);
1956 update_progress_form(tmp);
1957
1958 if (is_this_device_mounted(mountlist->el[lino].device)) {
1959 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1960 mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
1961 } else {
1962 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1963 mr_asprintf(command, "umount -d %s/", MNT_RESTORING);
1964 log_msg(3,
1965 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1966 } else {
1967 mr_asprintf(command, "umount -d " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
1968
1969 /* To support latest Ubuntu where /var is a separate FS
1970 * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1971 * we need to create some dirs under the real / before unmounting it */
1972 if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1973 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1974 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
1975 }
1976 }
1977 }
1978 log_msg(10, "The 'umount' command is '%s'", command);
1979 res = run_program_and_log_output(command, 3);
1980 mr_free(command);
1981 } else {
1982 mr_strcat(tmp, "...not mounted anyway :-) OK");
1983 res = 0;
1984 }
1985 g_current_progress++;
1986 if (res) {
1987 mr_strcat(tmp, "...Failed");
1988 retval++;
1989 log_to_screen(tmp);
1990 } else {
1991 log_msg(2, tmp);
1992 }
1993 paranoid_free(tmp);
1994 }
1995 close_progress_form();
1996 if (retval) {
1997 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1998 } else {
1999 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2000 }
2001 if (retval) {
2002 log_to_screen("Unable to unmount some of your partitions.");
2003 } else {
2004 log_to_screen("All partitions were unmounted OK.");
2005 }
2006 free(mountlist);
2007 return (retval);
2008}
2009
2010/**************************************************************************
2011 *END_UNMOUNT_ALL_DEVICES *
2012 **************************************************************************/
2013
2014/**
2015 * Extract mondorestore.cfg and the mountlist from the tape inserted
2016 * to the ./tmp/ directory.
2017 * @param dev The tape device to read from.
2018 * @return 0 for success, nonzero for failure.
2019 */
2020int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2021{
2022 char *command = NULL;
2023 int res = 0;
2024
2025 if (bkpinfo->use_obdr) {
2026 skip_obdr();
2027 } else {
2028 // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2029 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
2030 }
2031
2032 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2033 log_msg(2, "command = '%s'", command);
2034 res = run_program_and_log_output(command, -1);
2035 mr_free(command);
2036
2037 if (res != 0) {
2038 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2039 res = 0;
2040 } else {
2041 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2042 log_msg(2, "pre-2.2.4 compatible mode on");
2043 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2044 log_msg(2, "command = '%s'", command);
2045 res = run_program_and_log_output(command, -1);
2046 mr_free(command);
2047 if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
2048 res = 0;
2049 }
2050 }
2051 }
2052 paranoid_free(command);
2053 return (res);
2054}
2055
2056
2057/**
2058 * Get the configuration file from the floppy, tape, or CD.
2059 * @param bkpinfo The backup information structure. Fields used:
2060 * - @c bkpinfo->backup_media_type
2061 * - @c bkpinfo->media_device
2062 * - @c bkpinfo->tmpdir
2063 * @return 0 for success, nonzero for failure.
2064 */
2065int get_cfg_file_from_archive()
2066{
2067 int retval = 0;
2068
2069 /** malloc *****/
2070 char *command = NULL;
2071 char *cfg_file = NULL;
2072 char *tmp = NULL;
2073 char *mountpt = NULL;
2074 char *mountlist_file = NULL;
2075 bool extract_mountlist_stub = FALSE;
2076 bool extract_i_want_my_lvm = FALSE;
2077
2078 bool try_plan_B;
2079
2080 assert(bkpinfo != NULL);
2081 log_msg(2, "gcffa --- starting");
2082 log_to_screen("I'm thinking...");
2083 mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2084 if (chdir(bkpinfo->tmpdir)) {
2085 // FIXME
2086 }
2087 mr_asprintf(cfg_file, "%s", MONDO_CFG_FILE_STUB);
2088 unlink(cfg_file); // cfg_file[] is missing the '/' at the start, FYI, by intent
2089 mr_free(cfg_file);
2090
2091 unlink(FILELIST_FULL_STUB);
2092 unlink(BIGGIELIST_TXT_STUB);
2093 mr_asprintf(command, "mkdir -p %s", mountpt);
2094 run_program_and_log_output(command, FALSE);
2095 mr_free(command);
2096
2097 mr_asprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2098 mr_asprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2099 log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2100 mr_free(mountpt);
2101
2102 if (!does_file_exist(cfg_file)) {
2103 log_msg(2, "gcffa --- we don't have cfg file yet.");
2104 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2105 try_plan_B = TRUE;
2106 } else {
2107 log_msg(2, "gcffa --- calling mount_media now :)");
2108 if (!mount_media()) {
2109 log_msg(2, "gcffa --- managed to mount CD; so, no need for Plan B");
2110 try_plan_B = FALSE;
2111 } else {
2112 try_plan_B = TRUE;
2113 }
2114 if (what_number_cd_is_this() > 1) {
2115 insist_on_this_cd_number((g_current_media_number = 1));
2116 }
2117 }
2118 if (try_plan_B) {
2119 log_msg(2, "gcffa --- OK, switching to Plan B");
2120 if (chdir(bkpinfo->tmpdir)) {
2121 // FIXME
2122 }
2123 run_program_and_log_output("mkdir -p tmp", FALSE);
2124
2125 if (strlen(bkpinfo->media_device) == 0) {
2126 strcpy(bkpinfo->media_device, "/dev/st0");
2127 log_msg(2, "media_device is blank; assuming %s");
2128 }
2129 mr_asprintf(tmp, "%s", bkpinfo->media_device);
2130 if (extract_cfg_file_and_mountlist_from_tape_dev
2131 (bkpinfo->media_device)) {
2132 strcpy(bkpinfo->media_device, "/dev/st0");
2133 if (extract_cfg_file_and_mountlist_from_tape_dev
2134 (bkpinfo->media_device)) {
2135 strcpy(bkpinfo->media_device, "/dev/osst0");
2136 if (extract_cfg_file_and_mountlist_from_tape_dev
2137 (bkpinfo->media_device)) {
2138 strcpy(bkpinfo->media_device, "/dev/ht0");
2139 if (extract_cfg_file_and_mountlist_from_tape_dev
2140 (bkpinfo->media_device)) {
2141 log_msg(3,
2142 "I tried lots of devices but none worked.");
2143 strcpy(bkpinfo->media_device, tmp);
2144 }
2145 }
2146 }
2147 }
2148 mr_free(tmp);
2149
2150 if (!does_file_exist("tmp/mondorestore.cfg")) {
2151 log_to_screen("Cannot find config info on media");
2152 return (1);
2153 }
2154 } else {
2155 if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
2156 extract_mountlist_stub = FALSE;
2157 } else {
2158 extract_mountlist_stub = TRUE;
2159 }
2160 if (does_file_exist("/"IWANTMYLVM_STUB)) {
2161 extract_i_want_my_lvm = FALSE;
2162 } else {
2163 extract_i_want_my_lvm = TRUE;
2164 }
2165
2166 log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2167 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
2168 run_program_and_log_output(command, TRUE);
2169 mr_free(command);
2170
2171 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2172 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2173 log_msg(2, "pre-2.2.4 compatible mode on");
2174 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
2175 run_program_and_log_output(command, TRUE);
2176 mr_free(command);
2177 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2178 fatal_error
2179 ("Please reinsert the disk/CD and try again.");
2180 }
2181 }
2182 }
2183 }
2184 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2185 log_msg(1, "gcffa --- great! We've got the config file");
2186 mr_asprintf(tmp, "%s/%s", call_program_and_get_last_line_of_output("pwd"), MONDO_CFG_FILE_STUB);
2187 mr_asprintf(command, "cp -f %s %s", tmp, cfg_file);
2188 log_it("%s",command);
2189 if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {
2190 log_msg(1,
2191 "... but an error occurred when I tried to move it to %s",
2192 cfg_file);
2193 } else {
2194 log_msg(1, "... and I moved it successfully to %s", cfg_file);
2195 }
2196 mr_free(command);
2197
2198 mr_asprintf(command, "cp -f %s/%s %s", call_program_and_get_last_line_of_output("pwd"), MOUNTLIST_FNAME_STUB, mountlist_file);
2199 log_it("%s",command);
2200 if (extract_mountlist_stub) {
2201 if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {
2202 log_msg(1, "Failed to get mountlist");
2203 } else {
2204 log_msg(1, "Got mountlist too");
2205 mr_free(command);
2206 mr_asprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname);
2207 if (run_program_and_log_output(command, 1)) {
2208 log_msg(1, "Failed to copy mountlist to /tmp");
2209 } else {
2210 log_msg(1, "Copied mountlist to /tmp as well OK");
2211 mr_free(command);
2212 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2213 run_program_and_log_output(command, 1);
2214 }
2215 }
2216 }
2217 mr_free(command);
2218 mr_free(tmp);
2219 }
2220
2221 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
2222 if (!does_file_exist(cfg_file)) {
2223 log_it("%s",cfg_file);
2224 log_msg(1, "%s not found", cfg_file);
2225 log_to_screen("Oh dear. Unable to recover configuration file from boot disk");
2226 return (1);
2227 }
2228
2229 log_to_screen("Recovered mondorestore.cfg");
2230 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2231 log_to_screen("...but not mountlist.txt - a pity, really...");
2232 } else {
2233 /* Is this code really useful ??? */
2234 if (extract_mountlist_stub) {
2235 mr_asprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2236 run_program_and_log_output(command, FALSE);
2237 mr_free(command);
2238 }
2239 }
2240
2241 mr_asprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2242 mr_free(cfg_file);
2243
2244 run_program_and_log_output(command, FALSE);
2245 mr_free(command);
2246
2247 if (extract_mountlist_stub) {
2248 mr_asprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2249 run_program_and_log_output(command, FALSE);
2250 mr_free(command);
2251 }
2252 mr_free(mountlist_file);
2253
2254 mr_asprintf(command, "cp -f etc/raidtab /etc/");
2255 run_program_and_log_output(command, FALSE);
2256 mr_free(command);
2257
2258 if (extract_i_want_my_lvm) {
2259 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2260 run_program_and_log_output(command, FALSE);
2261 mr_free(command);
2262 }
2263 g_backup_media_type = bkpinfo->backup_media_type;
2264 return (retval);
2265}
2266
2267/**************************************************************************
2268 *END_GET_CFG_FILE_FROM_ARCHIVE *
2269 **************************************************************************/
2270
2271/* @} - end restoreUtilityGroup */
2272
2273void wait_until_software_raids_are_prepped(char *mdstat_file, int wait_for_percentage)
2274{
2275 struct raidlist_itself *raidlist;
2276 int unfinished_mdstat_devices = 9999;
2277 int i = 0;
2278 char *screen_message = NULL;
2279
2280 raidlist = malloc(sizeof(struct raidlist_itself));
2281
2282 assert(wait_for_percentage <= 100);
2283 log_it("wait_until_software_raids_are_prepped");
2284 while (unfinished_mdstat_devices > 0) {
2285 // FIXME: Prefix '/dev/' should really be dynamic!
2286 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2287 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2288 log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2289 return;
2290 }
2291 for (unfinished_mdstat_devices = 0; i <= raidlist->entries; i++) {
2292 if (raidlist->el[i].progress < wait_for_percentage) {
2293 unfinished_mdstat_devices++;
2294 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2295 {
2296 continue;
2297 }
2298 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2299 mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
2300 open_evalcall_form(screen_message);
2301 mr_free(screen_message);
2302
2303 while (raidlist->el[i].progress < wait_for_percentage) {
2304 log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2305 update_evalcall_form(raidlist->el[i].progress);
2306 sleep(2);
2307 // FIXME: Prefix '/dev/' should really be dynamic!
2308 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2309 break;
2310 }
2311 }
2312 close_evalcall_form();
2313 }
2314 }
2315 }
2316 paranoid_free(raidlist);
2317}
Note: See TracBrowser for help on using the repository browser.