source: MondoRescue/branches/3.1/mondo/src/mondorestore/mondo-rstr-tools.c@ 3147

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