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

Last change on this file since 3148 was 3148, checked in by Bruno Cornec, 11 years ago

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