source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondo-rstr-tools.c@ 2704

Last change on this file since 2704 was 2704, checked in by Bruno Cornec, 13 years ago

r4180@localhost: bruno | 2011-01-27 10:26:41 +0100

  • Fix multiple port issues from 2.2.9 that prevented mindi to work
  • Change interface of call_program_and_get_last_line_of_output to allow not logging (call to mindi)
  • Status is working boot, but NFS interface broken due to conf file issues
  • Property svn:keywords set to Id
File size: 61.9 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 2704 2011-01-27 18:31:24Z 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;
82
83assert_string_is_neither_NULL_nor_zerolength(infname);
84assert_string_is_neither_NULL_nor_zerolength(outfname);
85
86if (!(fin = fopen(infname, "r"))) {
87 fatal_error("Cannot openin infname");
88}
89if (!(fout = fopen(outfname, "w"))) {
90 fatal_error("Cannot openin outfname");
91}
92for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
93 mr_strip_spaces(incoming);
94
95 if (incoming[0] == '\0') {
96 mr_free(incoming);
97 continue;
98 }
99
100 mr_asprintf(question, "Should I restore the image of %s ?", incoming);
101
102 if (ask_me_yes_or_no(question)) {
103 fprintf(fout, "%s\n", incoming);
104 }
105 mr_free(incoming);
106}
107mr_free(incoming);
108mr_free(question);
109paranoid_fclose(fout);
110paranoid_fclose(fin);
111}
112
113/**************************************************************************
114*ASK_ABOUT_THESE_IMAGEDEVS *
115**************************************************************************/
116
117/**
118* Determine whether @p list_fname contains a line containing @p f.
119* @param f The line to search for.
120* @param list_fname The file to search in.
121* @param preamble Ignore this beginning part of @p f ("" to disable).
122* @return TRUE if it's in the list, FALSE if it's not.
123*/
124bool is_file_in_list(char *f, char *list_fname, char *preamble)
125{
126
127char *command = NULL;
128char *file = NULL;
129char *tmp = NULL;
130int res;
131
132assert_string_is_neither_NULL_nor_zerolength(f);
133assert_string_is_neither_NULL_nor_zerolength(list_fname);
134assert(preamble != NULL);
135
136if (strncmp(preamble, f, strlen(preamble)) == 0) {
137 mr_asprintf(file, "%s", f + strlen(preamble));
138} else {
139 mr_asprintf(file, "%s", f);
140}
141if (file[0] == '/' && file[1] == '/') {
142 mr_asprintf(tmp, "%s", file);
143 mr_free(file);
144
145 mr_asprintf(file, "%s", tmp + 1);
146 mr_free(tmp);
147}
148log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
149mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
150mr_free(file);
151
152res = run_program_and_log_output(command, FALSE);
153mr_free(command);
154if (res) {
155 return (FALSE);
156} else {
157 return (TRUE);
158}
159}
160
161/**************************************************************************
162*END_IS_FILE_IN_LIST *
163**************************************************************************/
164
165
166
167/**
168* Set up an ISO backup.
169* @param bkpinfo The backup information structure. Fields used:
170* - @c bkpinfo->backup_media_type
171* - @c bkpinfo->disaster_recovery
172* - @c bkpinfo->isodir
173* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
174* @return 0 for success, nonzero for failure.
175*/
176int iso_fiddly_bits(bool nuke_me_please)
177{
178 char *mount_isodir_command = NULL;
179 char *command = NULL;
180 char *mds = NULL;
181 int retval = 0, i;
182 bool already_mounted = FALSE;
183 char *isodir_format = NULL;
184
185g_ISO_restore_mode = TRUE;
186mr_free(g_isodir_device);
187g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
188if (bkpinfo->disaster_recovery) {
189 /* Patch Conor Daly 26-june-2004
190 * Don't let this clobber an existing bkpinfo->isodir */
191 if (!bkpinfo->isodir[0]) {
192 mr_free(bkpinfo->isodir);
193 mr_asprintf(bkpinfo->isodir, "/tmp/isodir");
194 }
195 /* End patch */
196 mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
197 run_program_and_log_output(command, 5);
198 mr_free(command);
199 log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
200}
201
202/* g_isodir_device is passed and modified in this function - memory is managed correctly in it */
203if (!get_isodir_info(g_isodir_device, isodir_format, bkpinfo->isodir, nuke_me_please)) {
204 mr_free(isodir_format);
205 return (1);
206}
207paranoid_system("umount "MNT_CDROM" 2> /dev/null"); /* just in case */
208
209if (is_this_device_mounted(g_isodir_device)) {
210 log_to_screen("WARNING - isodir is already mounted");
211 already_mounted = TRUE;
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 "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 "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_proto);
705 if ((value = read_cfg_var(cfg_file, "netfs-proto")) == 0) {
706 mr_asprintf(bkpinfo->netfs_proto, "%s", value);
707 } else {
708 /* For compatibility, force protocol in old nfs case to be transparent */
709 mr_asprintf(bkpinfo->netfs_proto, "nfs");
710 }
711 mr_free(value);
712
713 mr_free(bkpinfo->prefix);
714 if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
715 mr_asprintf(bkpinfo->prefix, "%s", value);
716 } else {
717 mr_asprintf(bkpinfo->prefix, "%s", STD_PREFIX);
718 }
719 mr_free(value);
720
721 tmp = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
722 if (strstr(tmp, "pxe")) {
723 /* We need to override prefix value in PXE mode as it's
724 * already done in start-netfs */
725 envtmp1 = getenv("imgname");
726 if (envtmp1 == NULL) {
727 fatal_error("no imgname variable in environment");
728 }
729 mr_free(bkpinfo->prefix);
730 mr_asprintf(bkpinfo->prefix, "%s", envtmp1);
731 }
732 mr_free(tmp);
733
734 } else if (!strcmp(value, "tape")) {
735 bkpinfo->backup_media_type = tape;
736 } else if (!strcmp(value, "udev")) {
737 bkpinfo->backup_media_type = udev;
738 } else {
739 fatal_error("UNKNOWN bkp-media-type");
740 }
741} else {
742 fatal_error("backup-media-type not specified!");
743}
744mr_free(value);
745
746if (bkpinfo->disaster_recovery) {
747 if (bkpinfo->backup_media_type == cdstream) {
748 mr_free(bkpinfo->media_device);
749 mr_asprintf(bkpinfo->media_device, "/dev/cdrom");
750 bkpinfo->media_size[0] = 1999 * 1024;
751 bkpinfo->media_size[1] = 650; /* good guess */
752 } else if (bkpinfo->backup_media_type == usb) {
753 envtmp1 = getenv("MRUSBDEV");
754 if (envtmp1 == NULL) {
755 if ((value = read_cfg_var(cfg_file, "usb-dev")) == NULL) {
756 fatal_error("Cannot get USB device name from cfg file");
757 }
758 } else {
759 mr_asprintf(value,"%s", envtmp1);
760 }
761 mr_free(bkpinfo->media_device);
762 mr_asprintf(bkpinfo->media_device, "%s1", value);
763 mr_free(value);
764 log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
765 } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
766 if ((value = read_cfg_var(cfg_file, "media-dev")) == NULL) {
767 fatal_error("Cannot get tape device name from cfg file");
768 }
769 mr_free(bkpinfo->media_device);
770 bkpinfo->media_device = value;
771
772 value = read_cfg_var(cfg_file, "media-size");
773 if (value != NULL) {
774 bkpinfo->media_size[1] = atol(value);
775 mr_free(value);
776 } else {
777 bkpinfo->media_size[1] = 0L;
778 }
779 log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
780 } else {
781 mr_free(bkpinfo->media_device);
782 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
783 bkpinfo->media_size[0] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
784 bkpinfo->media_size[1] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
785 log_msg(2, "Backup medium is CD-R[W]");
786 }
787} else {
788 log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
789}
790
791value = read_cfg_var(cfg_file, "use-star");
792if (value && strstr(value, "yes")) {
793 bkpinfo->use_star = TRUE;
794 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
795}
796mr_free(value);
797
798value = read_cfg_var(cfg_file, "obdr");
799if (value && strstr(value, "TRUE")) {
800 bkpinfo->use_obdr = TRUE;
801 log_msg(1, "OBDR mode activated");
802}
803mr_free(value);
804
805value = read_cfg_var(cfg_file, "acl");
806if (value && strstr(value, "TRUE")) {
807 mr_asprintf(g_getfacl,"setfacl");
808 log_msg(1, "We will restore ACLs");
809 tmp = find_home_of_exe("setfacl");
810 if (!tmp) {
811 log_msg(1, "Unable to restore ACLs as no setfacl found");
812 }
813 mr_free(tmp);
814}
815mr_free(value);
816
817value = read_cfg_var(cfg_file, "xattr");
818if (value && strstr(value, "TRUE")) {
819 mr_asprintf(g_getfattr,"setfattr");
820 log_msg(1, "We will restore XATTRs");
821 tmp = find_home_of_exe("setfattr");
822 if (!tmp) {
823 log_msg(1, "Unable to restore XATTRs as no setfattr found");
824 }
825 mr_free(tmp);
826}
827mr_free(value);
828
829value = read_cfg_var(cfg_file, "internal-tape-block-size");
830if (value != NULL) {
831 bkpinfo->internal_tape_block_size = atol(value);
832} else {
833 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
834}
835log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
836mr_free(value);
837
838value = read_cfg_var(cfg_file, "use-lzma");
839if (value && strstr(value, "yes")) {
840 bkpinfo->use_lzma = TRUE;
841 bkpinfo->use_lzo = FALSE;
842 bkpinfo->use_gzip = FALSE;
843 mr_free(bkpinfo->zip_exe);
844 mr_asprintf(bkpinfo->zip_exe, "lzma");
845 mr_free(bkpinfo->zip_suffix);
846 mr_asprintf(bkpinfo->zip_suffix, "lzma");
847}
848mr_free(value);
849
850value = read_cfg_var(cfg_file, "use-lzo");
851if (value && strstr(value, "yes")) {
852 bkpinfo->use_lzma = FALSE;
853 bkpinfo->use_lzo = TRUE;
854 bkpinfo->use_gzip = FALSE;
855 mr_free(bkpinfo->zip_exe);
856 mr_asprintf(bkpinfo->zip_exe, "lzop");
857 mr_free(bkpinfo->zip_suffix);
858 mr_asprintf(bkpinfo->zip_suffix, "lzo");
859}
860mr_free(value);
861
862value = read_cfg_var(cfg_file, "use-gzip");
863if (value && strstr(value, "yes")) {
864 bkpinfo->use_lzma = FALSE;
865 bkpinfo->use_lzo = FALSE;
866 bkpinfo->use_gzip = TRUE;
867 mr_free(bkpinfo->zip_exe);
868 mr_asprintf(bkpinfo->zip_exe, "gzip");
869 mr_free(bkpinfo->zip_suffix);
870 mr_asprintf(bkpinfo->zip_suffix, "gz");
871}
872mr_free(value);
873
874value = read_cfg_var(cfg_file, "use-comp");
875if (value && strstr(value, "yes")) {
876 bkpinfo->use_lzma = FALSE;
877 bkpinfo->use_lzo = FALSE;
878 bkpinfo->use_gzip = FALSE;
879 mr_free(bkpinfo->zip_exe);
880 mr_asprintf(bkpinfo->zip_exe, "bzip2");
881 mr_free(bkpinfo->zip_suffix);
882 mr_asprintf(bkpinfo->zip_suffix, "bz2");
883}
884mr_free(value);
885
886if (bkpinfo->zip_exe == NULL) {
887 mr_asprintf(bkpinfo->zip_exe, "none");
888}
889if (bkpinfo->zip_suffix == NULL) {
890 mr_asprintf(bkpinfo->zip_suffix, "");
891}
892
893value = read_cfg_var(cfg_file, "differential");
894if (value && (!strcmp(value, "yes") || !strcmp(value, "1"))) {
895 bkpinfo->differential = TRUE;
896}
897log_msg(2, "differential var = '%s'", value);
898mr_free(value);
899if (bkpinfo->differential) {
900 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
901} else {
902 log_msg(2, "This is a regular (full) backup");
903}
904
905tmp = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "please-dont-eject");
906tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
907if (tmp || strstr(tmp1, "donteject")) {
908 bkpinfo->please_dont_eject = TRUE;
909 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
910}
911mr_free(tmp);
912mr_free(tmp1);
913
914if (bkpinfo->backup_media_type == netfs) {
915 if (!cfgf) {
916 if (bkpinfo->netfs_mount) {
917 log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
918 }
919 if (bkpinfo->netfs_remote_dir) {
920 log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
921 }
922 log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
923 } else {
924 mr_free(bkpinfo->netfs_mount);
925 bkpinfo->netfs_mount = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-mount");
926
927 mr_free(bkpinfo->netfs_remote_dir);
928 bkpinfo->netfs_remote_dir = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-path");
929
930 if (bkpinfo->netfs_mount != NULL) {
931 log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
932 }
933 if (bkpinfo->netfs_remote_dir != NULL) {
934 log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
935 }
936 if (bkpinfo->netfs_proto != NULL) {
937 log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
938 }
939 }
940 tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
941 if (strstr(tmp1, "pxe")) {
942 mr_free(tmp1);
943 /* We need to override values in PXE mode as it's
944 * already done in start-netfs */
945 envtmp1 = getenv("netfsmount");
946 if (envtmp1 == NULL) {
947 fatal_error("no netfsmount variable in environment");
948 }
949 envtmp2 = getenv("dirimg");
950 if (envtmp2 == NULL) {
951 fatal_error("no dirimg variable in environment");
952 }
953 mr_free(bkpinfo->netfs_mount);
954 mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
955
956 mr_free(bkpinfo->netfs_remote_dir);
957 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
958 } else {
959 mr_free(tmp1);
960 }
961
962} else if (bkpinfo->backup_media_type == iso) {
963 /* Patch by Conor Daly 23-june-2004
964 * to correctly mount iso-dev and set a sensible
965 * isodir in disaster recovery mode
966 */
967 mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
968 iso_mnt = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-mnt");
969 iso_path = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "isodir");
970 mr_free(bkpinfo->isodir);
971 mr_asprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
972 mr_free(iso_mnt);
973
974 if (!bkpinfo->isodir[0]) {
975 mr_free(bkpinfo->isodir);
976 bkpinfo->isodir = old_isodir;
977 } else {
978 mr_free(old_isodir);
979 }
980 if (!bkpinfo->disaster_recovery) {
981 if (strcmp(old_isodir, bkpinfo->isodir)) {
982 log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
983 mr_free(bkpinfo->isodir);
984 bkpinfo->isodir = old_isodir;
985 } else {
986 mr_free(old_isodir);
987 }
988 }
989 mr_free(g_isodir_device);
990 g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
991 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
992
993 if (bkpinfo->disaster_recovery) {
994 if (is_this_device_mounted(g_isodir_device)) {
995 log_msg(2, "NB: isodir is already mounted");
996 /* Find out where it's mounted */
997 mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
998 log_it("command = %s", command);
999 iso_mnt = call_program_and_get_last_line_of_output(command,TRUE);
1000 log_it("res of it = %s", iso_mnt);
1001 mr_free(command);
1002 } else {
1003 mr_asprintf(iso_mnt, "/tmp/isodir");
1004 mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
1005 run_program_and_log_output(tmp1, 5);
1006 mr_free(tmp1);
1007
1008 mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
1009 if (run_program_and_log_output(tmp1, 3)) {
1010 log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
1011 bkpinfo->backup_media_type = cdr;
1012 mr_free(bkpinfo->media_device);
1013 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
1014 if (mount_media()) {
1015 mr_free(tmp1);
1016 fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
1017 } else {
1018 log_msg(1, "You backed up to disk, then burned some CDs.");
1019 }
1020 }
1021 mr_free(tmp1);
1022 }
1023 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1024 if (bkpinfo->backup_media_type == iso) {
1025 mr_free(bkpinfo->isodir);
1026 mr_asprintf(tmp1, "%s%s", iso_mnt, iso_path);
1027 bkpinfo->isodir = tmp1;
1028 }
1029 mr_free(iso_mnt);
1030 }
1031 mr_free(iso_path);
1032}
1033
1034if (media_specified_by_user != none) {
1035 if (! bkpinfo->disaster_recovery) {
1036 if (bkpinfo->backup_media_type != media_specified_by_user) {
1037 log_msg(2,
1038 "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1039 interactively_obtain_media_parameters_from_user(FALSE);
1040 media_specified_by_user = bkpinfo->backup_media_type;
1041 get_cfg_file_from_initrd();
1042 }
1043 }
1044 bkpinfo->backup_media_type = media_specified_by_user;
1045}
1046g_backup_media_type = bkpinfo->backup_media_type;
1047paranoid_free(value);
1048return (0);
1049
1050}
1051
1052/**************************************************************************
1053*END_READ_CFG_FILE_INTO_BKPINFO *
1054**************************************************************************/
1055
1056
1057
1058
1059/**
1060 * Allow the user to edit the filelist and biggielist.
1061 * The filelist is unlinked after it is read.
1062 * @param bkpinfo The backup information structure. Fields used:
1063 * - @c bkpinfo->backup_media_type
1064 * - @c bkpinfo->isodir
1065 * - @c bkpinfo->media_device
1066 * - @c bkpinfo->tmpdir
1067 * @return The filelist structure containing the information read from disk.
1068 */
1069struct
1070s_node *process_filelist_and_biggielist()
1071{
1072struct s_node *filelist;
1073
1074char *command = NULL;
1075char *tmp;
1076char *tmp1 = NULL;
1077int res = 0;
1078pid_t pid;
1079
1080assert(bkpinfo != NULL);
1081malloc_string(tmp);
1082
1083 getcwd(tmp, MAX_STR_LEN);
1084 chdir(bkpinfo->tmpdir);
1085 log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1086 log_to_screen("Extracting filelist and biggielist from media...");
1087 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1088 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);
1089 log_msg(1, "tarcommand = %s", command);
1090 run_program_and_log_output(command, 1);
1091 mr_free(command);
1092
1093 } else {
1094 log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
1095 insist_on_this_cd_number(1);
1096 log_msg(2, "Back from iotcn");
1097 run_program_and_log_output("mount", 1);
1098 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");
1099
1100 log_msg(1, "tarcommand = %s", command);
1101 run_program_and_log_output(command, 1);
1102 mr_free(command);
1103
1104 if (!does_file_exist(MINDI_CACHE"/biggielist.txt")) {
1105 fatal_error("all.tar.gz did not include "MINDI_CACHE"/biggielist.txt");
1106 }
1107 if (!does_file_exist(MINDI_CACHE"/filelist.full.gz")) {
1108 fatal_error("all.tar.gz did not include "MINDI_CACHE"/filelist.full.gz");
1109 }
1110 }
1111 chdir(tmp);
1112
1113 log_msg(2, "Forking");
1114 pid = fork();
1115 switch (pid) {
1116 case -1:
1117 fatal_error("Forking error");
1118 break;
1119
1120 case 0:
1121 log_to_screen("Pre-processing filelist");
1122 mr_asprintf(command, "grep -E '^/dev/.*' "MINDI_CACHE"/biggielist.txt > %s 2> /dev/null", g_filelist_imagedevs);
1123 paranoid_system(command);
1124 mr_free(command);
1125 exit(0);
1126 break;
1127
1128 default:
1129 open_evalcall_form("Pre-processing filelist");
1130 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1131 usleep(100000);
1132 update_evalcall_form(0);
1133 }
1134 }
1135 close_evalcall_form();
1136
1137 log_msg(3, "loading filelist");
1138 filelist = load_filelist(MINDI_CACHE"/filelist.full.gz");
1139 log_msg(3, "deleting original filelist");
1140 unlink(MINDI_CACHE"/filelist.full.gz");
1141 if (g_text_mode) {
1142 printf("Restore which directory? --> ");
1143 mr_getline(tmp1, stdin);
1144 toggle_path_selection(filelist, tmp1, TRUE);
1145 if (strlen(tmp1) == 0) {
1146 res = 1;
1147 } else {
1148 res = 0;
1149 }
1150 mr_free(tmp1);
1151 } else {
1152 res = edit_filelist(filelist);
1153 }
1154 if (res) {
1155 log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1156 free_filelist(filelist);
1157 return (NULL);
1158 }
1159 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1160 close_evalcall_form();
1161
1162 // NB: It's not necessary to add biggielist.txt to the filelist.full
1163 // file. The filelist.full file already contains the filename of EVERY
1164 // file backed up - regular and biggie files.
1165
1166 // However, we do want to make sure the imagedevs selected by the user
1167 // are flagged for restoring.
1168 if (length_of_file(g_imagedevs_restthese) > 2) {
1169 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1170 TRUE);
1171 }
1172
1173 paranoid_free(tmp);
1174 return (filelist);
1175}
1176
1177/**************************************************************************
1178 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1179 **************************************************************************/
1180
1181
1182
1183
1184/**
1185 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1186 * The backup filename is the filename of the original with ".pristine" added.
1187 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1188 * @param filename The filename (absolute path) within @p path_root.
1189 * @return 0 for success, nonzero for failure.
1190 */
1191int backup_crucial_file(char *path_root, char *filename)
1192{
1193 char *tmp = NULL;
1194 char *command = NULL;
1195 int res;
1196
1197 assert(path_root != NULL);
1198 assert_string_is_neither_NULL_nor_zerolength(filename);
1199
1200 mr_asprintf(tmp, "%s/%s", path_root, filename);
1201 mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1202 mr_free(tmp);
1203
1204 res = run_program_and_log_output(command, 5);
1205 mr_free(command);
1206 return (res);
1207}
1208
1209void offer_to_make_initrd() {
1210
1211if (bkpinfo->restore_mode != nuke) {
1212 if (ask_me_yes_or_no
1213 ("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 ?")) {
1214 log_msg(1,"Launching shell for manual initrd recreation");
1215 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.");
1216 mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1217 if (!g_text_mode) {
1218 newtSuspend();
1219 }
1220 (void)system("chroot " MNT_RESTORING);
1221 if (!g_text_mode) {
1222 newtResume();
1223 }
1224 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1225 } else {
1226 return;
1227 }
1228} else {
1229 log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1230 log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1231}
1232}
1233
1234
1235/**
1236 * Install the user's boot loader in the MBR.
1237 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1238 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1239 * @return 0 for success, nonzero for failure.
1240 */
1241int run_boot_loader(bool offer_to_hack_scripts)
1242{
1243 int res;
1244 int retval = 0;
1245
1246 /** malloc *******/
1247 char *device = NULL;
1248 char *name = NULL;
1249 char *cmd = NULL;
1250
1251 /* In order to have a working bootloader, we need to have all devices
1252 * ready in the chroot. If they are not there (udev) then copy them from
1253 * the current /dev location
1254 */
1255 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1256 run_program_and_log_output(cmd, 3);
1257 paranoid_free(cmd);
1258
1259 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1260 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1261 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1262 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1263 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1264 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1265 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1266 device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.device");
1267 name = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.name");
1268 log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1269 sync();
1270
1271 offer_to_make_initrd();
1272 if (!strcmp(name, "LILO")) {
1273 res = run_lilo(offer_to_hack_scripts);
1274 } else if (!strcmp(name, "ELILO")) {
1275 res = run_elilo(offer_to_hack_scripts);
1276 } else if (!strcmp(name, "GRUB")) {
1277 res = run_grub(offer_to_hack_scripts, device);
1278 } else if (!strcmp(name, "RAW")) {
1279 res = run_raw_mbr(offer_to_hack_scripts, device);
1280 }
1281#ifdef __FreeBSD__
1282 else if (!strcmp(name, "BOOT0")) {
1283 mr_asprintf(tmp, "boot0cfg -B %s", device);
1284 res = run_program_and_log_output(tmp, FALSE);
1285 paranoid_free(tmp);
1286 } else {
1287 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1288 if (!system(tmp)) {
1289 mr_free(tmp);
1290 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1291 res = run_program_and_log_output(tmp, 3);
1292 } else {
1293 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1294 }
1295 mr_free(tmp);
1296 }
1297#else
1298 else {
1299 log_to_screen
1300 ("Unable to determine type of boot loader. Defaulting to LILO.");
1301 res = run_lilo(offer_to_hack_scripts);
1302 }
1303#endif
1304 mr_free(device);
1305 mr_free(name);
1306
1307 retval += res;
1308 if (res) {
1309 log_to_screen("Your boot loader returned an error");
1310 } else {
1311 log_to_screen("Your boot loader ran OK");
1312 }
1313 return (retval);
1314}
1315
1316/**************************************************************************
1317 *END_ RUN_BOOT_LOADER *
1318 **************************************************************************/
1319
1320
1321
1322/**
1323 * Attempt to find the user's editor.
1324 * @return The editor found ("vi" if none could be found).
1325 * @note The returned string points to static storage that will be overwritten with each call.
1326 */
1327char *find_my_editor(void) {
1328
1329 char *tmp = NULL;
1330 static char output[MAX_STR_LEN];
1331
1332 tmp = find_home_of_exe("pico");
1333 if (tmp) {
1334 strcpy(output, "pico");
1335 } else {
1336 mr_free(tmp);
1337 tmp = find_home_of_exe("nano");
1338 if (tmp) {
1339 strcpy(output, "nano");
1340 } else {
1341 mr_free(tmp);
1342 tmp = find_home_of_exe("joe");
1343 if (tmp) {
1344 strcpy(output, "joe");
1345 } else {
1346 strcpy(output, "vi");
1347 }
1348 }
1349 }
1350 mr_free(tmp);
1351
1352 tmp = find_home_of_exe(output);
1353 if (!tmp) {
1354 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1355 }
1356 mr_free(tmp);
1357 return (output);
1358}
1359
1360
1361/**
1362 * Install GRUB on @p bd.
1363 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1364 * @param bd The boot device where GRUB is installed.
1365 * @return 0 for success, nonzero for failure.
1366 */
1367int run_grub(bool offer_to_run_stabgrub, char *bd)
1368{
1369 /** malloc **/
1370 char *command = NULL;
1371 char *boot_device = NULL;
1372 char *tmp = NULL;
1373 char *editor = NULL;
1374 char *p = NULL;
1375
1376 int res = 0;
1377 bool done;
1378
1379 assert_string_is_neither_NULL_nor_zerolength(bd);
1380 mr_asprintf(boot_device, "%s", bd);
1381
1382 if (offer_to_run_stabgrub
1383 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1384 /* interactive mode */
1385 mvaddstr_and_log_it(g_currentY,
1386 0,
1387 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
1388 for (done = FALSE; !done;) {
1389 p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1390 if (p == NULL) {
1391 done = TRUE;
1392 mr_free(p);
1393 /* we want some warnings later on */
1394 res = 1;
1395 continue;
1396 }
1397 mr_asprintf(command, "stabgrub-me %s", p);
1398 mr_free(p);
1399
1400 res = run_program_and_log_output(command, 1);
1401 mr_free(command);
1402
1403 if (res) {
1404 popup_and_OK
1405 ("GRUB installation failed. Please install manually using 'grub-install' or similar command. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1406 newtSuspend();
1407 system("chroot " MNT_RESTORING);
1408 newtResume();
1409 popup_and_OK("Thank you.");
1410 } else {
1411 done = TRUE;
1412 }
1413 popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst/grub.cfg");
1414 if (!g_text_mode) {
1415 newtSuspend();
1416 }
1417 mr_asprintf(editor, "%s", find_my_editor());
1418
1419 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1420 paranoid_system(tmp);
1421 mr_free(tmp);
1422
1423 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1424 paranoid_system(tmp);
1425 mr_free(tmp);
1426
1427 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1428 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1429 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1430 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1431 }
1432 paranoid_system(tmp);
1433 mr_free(tmp);
1434
1435 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1436 paranoid_system(tmp);
1437 mr_free(tmp);
1438 mr_free(editor);
1439
1440 if (!g_text_mode) {
1441 newtResume();
1442 }
1443 }
1444 } else {
1445 /* nuke mode */
1446 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1447 log_msg(1, "Yay! grub-MR found...");
1448 mr_asprintf(command, "grub-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1449 log_msg(1, "command = %s", command);
1450 } else {
1451 mr_asprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device);
1452 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1453 }
1454 mvaddstr_and_log_it(g_currentY,
1455 0,
1456 "Running GRUB... ");
1457 log_it("%s",command);
1458 res = run_program_and_log_output(command, 1);
1459 mr_free(command);
1460
1461 if (res) {
1462 popup_and_OK
1463 ("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.");
1464 newtSuspend();
1465 system("chroot " MNT_RESTORING);
1466 newtResume();
1467 popup_and_OK("Thank you.");
1468 }
1469 }
1470 mr_free(boot_device);
1471
1472 if (res) {
1473 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1474 log_to_screen
1475 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1476 log_msg(1, "Type:-");
1477 log_msg(1, " mount-me");
1478 log_msg(1, " chroot " MNT_RESTORING);
1479 log_msg(1, " mount /boot");
1480 log_msg(1, " grub-install '(hd0)'");
1481 log_msg(1, " exit");
1482 log_msg(1, " unmount-me");
1483 log_msg(1,
1484 "If you're really stuck, please e-mail the mailing list.");
1485 } else {
1486 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1487 }
1488
1489 return (res);
1490}
1491
1492/**************************************************************************
1493 *END_RUN_GRUB *
1494 **************************************************************************/
1495
1496
1497/**
1498 * Install ELILO on the user's boot drive (determined by elilo.conf).
1499 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1500 * @return 0 for success, nonzero for failure.
1501 */
1502int run_elilo(bool offer_to_run_stabelilo)
1503{
1504 /** malloc **/
1505 char *command = NULL;
1506 char *tmp = NULL;
1507 char *editor = NULL;
1508
1509 int res;
1510 int done;
1511
1512 if (offer_to_run_stabelilo
1513 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1514
1515 /* interactive mode */
1516 {
1517 mvaddstr_and_log_it(g_currentY,
1518 0,
1519 "Modifying fstab and elilo.conf... ");
1520 mr_asprintf(command, "stabelilo-me");
1521 res = run_program_and_log_output(command, 3);
1522 mr_free(command);
1523
1524 if (res) {
1525 popup_and_OK
1526 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1527 for (done = FALSE; !done;) {
1528 if (!g_text_mode) {
1529 newtSuspend();
1530 }
1531 mr_asprintf(editor, "%s", find_my_editor());
1532
1533 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1534 paranoid_system(tmp);
1535 mr_free(tmp);
1536
1537 mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1538 paranoid_system(tmp);
1539 mr_free(tmp);
1540
1541 mr_free(editor);
1542
1543 if (!g_text_mode) {
1544 newtResume();
1545 }
1546// newtCls();
1547 if (ask_me_yes_or_no("Edit them again?")) {
1548 continue;
1549 }
1550 done = TRUE;
1551 }
1552 } else {
1553 log_to_screen("elilo.conf and fstab were modified OK");
1554 }
1555 } else
1556 /* nuke mode */
1557 {
1558 res = TRUE;
1559 }
1560 return (res);
1561}
1562
1563/**************************************************************************
1564 *END_RUN_ELILO *
1565 **************************************************************************/
1566
1567
1568/**
1569 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1570 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1571 * @return 0 for success, nonzero for failure.
1572 */
1573int run_lilo(bool offer_to_run_stablilo)
1574{
1575 /** malloc **/
1576 char *command = NULL;
1577 char *tmp = NULL;
1578 char *editor = NULL;
1579
1580 int res;
1581 int done;
1582 bool run_lilo_M = FALSE;
1583
1584 if (!run_program_and_log_output
1585 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1586 run_lilo_M = TRUE;
1587 }
1588
1589 if (offer_to_run_stablilo
1590 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1591
1592 /* interactive mode */
1593 {
1594 mvaddstr_and_log_it(g_currentY,
1595 0,
1596 "Modifying fstab and lilo.conf, and running LILO... ");
1597 mr_asprintf(command, "stablilo-me");
1598 res = run_program_and_log_output(command, 3);
1599 mr_free(command);
1600
1601 if (res) {
1602 popup_and_OK
1603 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1604 for (done = FALSE; !done;) {
1605 if (!g_text_mode) {
1606 newtSuspend();
1607 }
1608 mr_asprintf(editor, "%s", find_my_editor());
1609
1610 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1611 paranoid_system(tmp);
1612 mr_free(tmp);
1613
1614 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1615 paranoid_system(tmp);
1616 mr_free(tmp);
1617
1618 mr_free(editor);
1619
1620 if (!g_text_mode) {
1621 newtResume();
1622 }
1623// newtCls();
1624 if (ask_me_yes_or_no("Edit them again?")) {
1625 continue;
1626 }
1627 res =
1628 run_program_and_log_output("chroot " MNT_RESTORING
1629 " lilo -L", 3);
1630 if (res) {
1631 res =
1632 run_program_and_log_output("chroot " MNT_RESTORING
1633 " lilo", 3);
1634 }
1635 if (res) {
1636 done =
1637 ask_me_yes_or_no
1638 ("LILO failed. Re-edit system files?");
1639 } else {
1640 done = TRUE;
1641 }
1642 }
1643 } else {
1644 log_to_screen("lilo.conf and fstab were modified OK");
1645 }
1646 } else
1647 /* nuke mode */
1648 {
1649 mvaddstr_and_log_it(g_currentY,
1650 0,
1651 "Running LILO... ");
1652 res =
1653 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1654 3);
1655 if (res) {
1656 res =
1657 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1658 3);
1659 }
1660 if (res) {
1661 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1662 log_to_screen
1663 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1664 } else {
1665 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1666 }
1667 }
1668 if (run_lilo_M) {
1669 run_program_and_log_output("chroot " MNT_RESTORING
1670 " lilo -M /dev/hda", 3);
1671 run_program_and_log_output("chroot " MNT_RESTORING
1672 " lilo -M /dev/sda", 3);
1673 }
1674 return (res);
1675}
1676
1677/**************************************************************************
1678 *END_RUN_LILO *
1679 **************************************************************************/
1680
1681
1682/**
1683 * Install a raw MBR onto @p bd.
1684 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1685 * @param bd The device to copy the stored MBR to.
1686 * @return 0 for success, nonzero for failure.
1687 */
1688int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1689{
1690 /** malloc **/
1691 char *command = NULL;
1692 char *boot_device = NULL;
1693 char *tmp = NULL;
1694 char *editor;
1695 char *p = NULL;
1696 int res;
1697 int done;
1698
1699 assert_string_is_neither_NULL_nor_zerolength(bd);
1700
1701 mr_asprintf(boot_device, "%s", bd);
1702
1703 if (offer_to_hack_scripts
1704 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1705 /* interactive mode */
1706 mvaddstr_and_log_it(g_currentY, 0,
1707 "Modifying fstab and restoring MBR... ");
1708 for (done = FALSE; !done;) {
1709 if (!run_program_and_log_output("which vi", FALSE)) {
1710 popup_and_OK("You will now edit fstab");
1711 if (!g_text_mode) {
1712 newtSuspend();
1713 }
1714 mr_asprintf(editor, "%s", find_my_editor());
1715 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1716 mr_free(editor);
1717
1718 paranoid_system(tmp);
1719 mr_free(tmp);
1720 if (!g_text_mode) {
1721 newtResume();
1722 }
1723 }
1724 p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1725 if (p == NULL) {
1726 done = TRUE;
1727 mr_free(p);
1728 /* we want some warnings later on */
1729 res = 1;
1730 continue;
1731 }
1732 mr_asprintf(command, "stabraw-me %s", p);
1733 mr_free(p);
1734
1735 res = run_program_and_log_output(command, 3);
1736 mr_free(command);
1737
1738 if (res) {
1739 done = ask_me_yes_or_no("Modifications failed. Re-try?");
1740 } else {
1741 done = TRUE;
1742 }
1743 }
1744 } else {
1745 /* nuke mode */
1746 mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1747 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1748
1749 mvaddstr_and_log_it(g_currentY, 0,
1750 "Restoring MBR... ");
1751 res = run_program_and_log_output(command, 3);
1752 mr_free(command);
1753 }
1754 mr_free(boot_device);
1755
1756 if (res) {
1757 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1758 log_to_screen
1759 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1760 } else {
1761 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1762 }
1763 return (res);
1764}
1765
1766/**************************************************************************
1767 *END_RUN_RAW_MBR *
1768 **************************************************************************/
1769
1770
1771
1772/**
1773 * malloc() and set sensible defaults for the mondorestore filename variables.
1774 * @param bkpinfo The backup information structure. Fields used:
1775 * - @c bkpinfo->tmpdir
1776 * - @c bkpinfo->disaster_recovery
1777 */
1778void setup_MR_global_filenames()
1779{
1780 assert(bkpinfo != NULL);
1781
1782 malloc_string(g_filelist_imagedevs);
1783 malloc_string(g_imagedevs_restthese);
1784 malloc_string(g_mondo_home);
1785
1786 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1787 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", bkpinfo->tmpdir);
1788 if (! bkpinfo->disaster_recovery) {
1789 /* TODO: We need to get mondorestore.cfg and mountlist.txt from initrd.img */
1790 get_cfg_file_from_initrd();
1791 }
1792}
1793
1794/**************************************************************************
1795 *END_SET_GLOBAL_FILENAME *
1796 **************************************************************************/
1797
1798
1799/**
1800 * Copy @p input_file (containing the result of a compare) to @p output_file,
1801 * deleting spurious "changes" along the way.
1802 * @param output_file The output file to write with spurious changes removed.
1803 * @param input_file The input file, a list of changed files created by a compare.
1804 */
1805void streamline_changes_file(char *output_file, char *input_file)
1806{
1807 FILE *fin;
1808 FILE *fout;
1809 char *incoming = NULL;
1810
1811 assert_string_is_neither_NULL_nor_zerolength(output_file);
1812 assert_string_is_neither_NULL_nor_zerolength(input_file);
1813
1814 if (!(fin = fopen(input_file, "r"))) {
1815 log_OS_error(input_file);
1816 return;
1817 }
1818 if (!(fout = fopen(output_file, "w"))) {
1819 fatal_error("cannot open output_file");
1820 }
1821 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
1822 if (strncmp(incoming, "etc/adjtime", 11)
1823 && strncmp(incoming, "etc/mtab", 8)
1824 && strncmp(incoming, "tmp/", 4)
1825 && strncmp(incoming, "boot/map", 8)
1826 && !strstr(incoming, "incheckentry")
1827 && strncmp(incoming, "etc/mail/statistics", 19)
1828 && strncmp(incoming, "var/", 4))
1829 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1830 mr_free(incoming);
1831 }
1832 mr_free(incoming);
1833 paranoid_fclose(fout);
1834 paranoid_fclose(fin);
1835}
1836
1837/**************************************************************************
1838 *END_STREAMLINE_CHANGES_FILE *
1839 **************************************************************************/
1840
1841
1842/**
1843 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1844 */
1845void twenty_seconds_til_yikes()
1846{
1847 int i;
1848 /* MALLOC * */
1849 char *tmp = NULL;
1850
1851 if (does_file_exist("/tmp/NOPAUSE")) {
1852 return;
1853 }
1854 open_progress_form("CAUTION",
1855 "Be advised: I am about to ERASE your hard disk(s)!",
1856 "You may press Ctrl+Alt+Del to abort safely.",
1857 "", 20);
1858 for (i = 0; i < 20; i++) {
1859 g_current_progress = i;
1860 mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1861 update_progress_form(tmp);
1862 mr_free(tmp);
1863 sleep(1);
1864 }
1865 close_progress_form();
1866}
1867
1868/**************************************************************************
1869 *END_TWENTY_SECONDS_TIL_YIKES *
1870 **************************************************************************/
1871
1872
1873/**
1874 * Unmount all devices in @p p_external_copy_of_mountlist.
1875 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1876 * @return 0 for success, nonzero for failure.
1877 */
1878int unmount_all_devices(struct mountlist_itself
1879 *p_external_copy_of_mountlist)
1880{
1881 struct mountlist_itself *mountlist;
1882 int retval = 0, lino, res = 0, i;
1883 char *command = NULL;
1884 char *tmp = NULL;
1885
1886 assert(p_external_copy_of_mountlist != NULL);
1887
1888 mountlist = malloc(sizeof(struct mountlist_itself));
1889 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1890 sizeof(struct mountlist_itself));
1891 sort_mountlist_by_mountpoint(mountlist, 0);
1892
1893 run_program_and_log_output("df -m -P", 3);
1894 mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices ");
1895 open_progress_form("Unmounting devices",
1896 "Unmounting all devices that were mounted,",
1897 "in preparation for the post-restoration reboot.",
1898 "", mountlist->entries);
1899 chdir("/");
1900 for (i = 0;
1901 i < 10
1902 &&
1903 run_program_and_log_output
1904 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1905 i++) {
1906 sleep(1);
1907 log_msg(2, "Waiting for buffer() to finish");
1908 }
1909
1910 sync();
1911
1912 mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1913 if (run_program_and_log_output(tmp, FALSE)) {
1914 log_msg(1,
1915 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1916 }
1917 paranoid_free(tmp);
1918 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1919 run_program_and_log_output("mkdir -p " MNT_RESTORING
1920 "/mnt/.boot.d", 5);
1921 }
1922
1923 /* Unmounting the local /proc and /sys first */
1924 run_program_and_log_output("umount " MNT_RESTORING "/proc",3);
1925 run_program_and_log_output("umount " MNT_RESTORING "/sys",3);
1926
1927 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1928 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1929 continue;
1930 }
1931 mr_asprintf(tmp, "Unmounting device %s ", mountlist->el[lino].device);
1932 update_progress_form(tmp);
1933
1934 if (is_this_device_mounted(mountlist->el[lino].device)) {
1935 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1936 mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
1937 } else {
1938 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1939 mr_asprintf(command, "umount %s/", MNT_RESTORING);
1940 log_msg(3,
1941 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1942 } else {
1943 mr_asprintf(command, "umount " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
1944
1945 /* To support latest Ubuntu where /var is a separate FS
1946 * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1947 * we need to create some dirs under the real / before unmounting it */
1948 if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1949 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1950 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
1951 }
1952 }
1953 }
1954 log_msg(10, "The 'umount' command is '%s'", command);
1955 res = run_program_and_log_output(command, 3);
1956 mr_free(command);
1957 } else {
1958 mr_strcat(tmp, "...not mounted anyway :-) OK");
1959 res = 0;
1960 }
1961 g_current_progress++;
1962 if (res) {
1963 mr_strcat(tmp, "...Failed");
1964 retval++;
1965 log_to_screen(tmp);
1966 } else {
1967 log_msg(2, tmp);
1968 }
1969 paranoid_free(tmp);
1970 }
1971 close_progress_form();
1972 if (retval) {
1973 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1974 } else {
1975 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1976 }
1977 if (retval) {
1978 log_to_screen("Unable to unmount some of your partitions.");
1979 } else {
1980 log_to_screen("All partitions were unmounted OK.");
1981 }
1982 free(mountlist);
1983 return (retval);
1984}
1985
1986/**************************************************************************
1987 *END_UNMOUNT_ALL_DEVICES *
1988 **************************************************************************/
1989
1990
1991
1992/**************************************************************************
1993 *END_GET_CFG_FILE_FROM_ARCHIVE *
1994 **************************************************************************/
1995
1996/* @} - end restoreUtilityGroup */
1997
1998void wait_until_software_raids_are_prepped(char *mdstat_file,
1999 int wait_for_percentage)
2000{
2001 struct raidlist_itself *raidlist;
2002 int unfinished_mdstat_devices = 9999, i;
2003 char *screen_message = NULL;
2004
2005 raidlist = malloc(sizeof(struct raidlist_itself));
2006
2007 assert(wait_for_percentage <= 100);
2008 log_it("wait_until_software_raids_are_prepped");
2009 while (unfinished_mdstat_devices > 0) {
2010 // FIXME: Prefix '/dev/' should really be dynamic!
2011 if (parse_mdstat(raidlist, "/dev/")) {
2012 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2013 log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2014 return;
2015 }
2016 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2017 if (raidlist->el[i].progress < wait_for_percentage) {
2018 unfinished_mdstat_devices++;
2019 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2020 {
2021 continue;
2022 }
2023 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2024 mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
2025 open_evalcall_form(screen_message);
2026 mr_free(screen_message);
2027
2028 while (raidlist->el[i].progress < wait_for_percentage) {
2029 log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2030 update_evalcall_form(raidlist->el[i].progress);
2031 sleep(2);
2032 // FIXME: Prefix '/dev/' should really be dynamic!
2033 if (parse_mdstat(raidlist, "/dev/")) {
2034 break;
2035 }
2036 }
2037 close_evalcall_form();
2038 }
2039 }
2040 }
2041 paranoid_free(raidlist);
2042}
2043
2044
Note: See TracBrowser for help on using the repository browser.