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

Last change on this file since 3193 was 3193, checked in by Bruno Cornec, 7 years ago
  • Finish with backports from 3.1 for now. Still some work to do, but we will now make that version compile and work again and serve as a base

so the gettext patch can be added

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