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

Last change on this file since 3161 was 3161, checked in by Bruno Cornec, 7 years ago
  • Apply fixes to 3.1 tree so that at least mondo compiles again (but that branch probably doesn't work at all again).
  • Property svn:keywords set to Id
File size: 64.7 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 3161 2013-06-25 20:53:14Z bruno $
3***************************************************************************/
4
5#include <pthread.h>
6#include <linux/fd.h>
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "mr_str.h"
10#include "../common/mondostructures.h"
11#include "../common/libmondo.h"
12#include "mr-externs.h"
13#include "mondo-rstr-tools.h"
14
15extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
16extern bool g_I_have_just_nuked;
17/*
18extern char *g_tmpfs_mountpt;
19*/
20extern char *g_isodir_device;
21extern long g_current_progress, g_maximum_progress;
22extern char *g_biggielist_pot;  // list of big files which _could_ be restored, if the
23                  // user chooses them
24extern char *g_filelist_imagedevs;  // list of devices (e.g. /dev/hda1, /dev/sda5) which
25                     // were archived as images, not just /dev entries
26                     // ... e.g. NTFS, BeOS partitions
27extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
28                      // restore only these
29extern char *g_mondo_home;      // homedir of Mondo; usually /usr/local/share/mondo
30
31extern t_bkptype g_backup_media_type;
32
33extern int g_partition_table_locked_up;
34extern char *MONDO_LOGFILE;
35
36/* Reference to global bkpinfo */
37extern struct s_bkpinfo *bkpinfo;
38
39/* Should we use or not extended attributes and acl when restoring */
40char *g_getfattr = NULL;
41char *g_getfacl = NULL;
42
43extern void kill_anything_like_this(char *str);
44extern int skip_obdr(void);
45extern int mount_media();
46extern int set_tape_block_size_with_mt(long internal_tape_block_size);
47
48/**
49* @addtogroup restoreUtilityGroup
50* @{
51*/
52/**
53* Free the malloc()s for the filename variables.
54*/
55void free_MR_global_filenames(void)
56{
57paranoid_free(g_filelist_imagedevs);
58paranoid_free(g_imagedevs_restthese);
59paranoid_free(g_mondo_home);
60/*
61paranoid_free(g_tmpfs_mountpt);
62*/
63mr_free(g_isodir_device);
64
65}
66
67
68
69/**
70* Ask the user which imagedevs from the list contained in @p infname should
71* actually be restored.
72* @param infname The file containing a list of all imagedevs.
73* @param outfname The location of the output file containing the imagedevs the user wanted to restore.
74* @ingroup restoreUtilityGroup
75*/
76void ask_about_these_imagedevs(char *infname, char *outfname) {
77
78FILE *fin;
79FILE *fout;
80char *incoming = NULL;
81char *question = NULL;
82
83assert_string_is_neither_NULL_nor_zerolength(infname);
84assert_string_is_neither_NULL_nor_zerolength(outfname);
85
86if (!(fin = fopen(infname, "r"))) {
87    fatal_error("Cannot openin infname");
88}
89if (!(fout = fopen(outfname, "w"))) {
90    fatal_error("Cannot openin outfname");
91}
92for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
93    mr_strip_spaces(incoming);
94
95    if (incoming[0] == '\0') {
96        mr_free(incoming);
97        continue;
98    }
99
100    mr_asprintf(question, "Should I restore the image of %s ?", incoming);
101   
102    if (ask_me_yes_or_no(question)) {
103        fprintf(fout, "%s\n", incoming);
104    }
105    mr_free(incoming);
106}
107mr_free(incoming);
108mr_free(question);
109paranoid_fclose(fout);
110paranoid_fclose(fin);
111}
112
113/**************************************************************************
114*ASK_ABOUT_THESE_IMAGEDEVS                                               *
115**************************************************************************/
116
117/**
118* Determine whether @p list_fname contains a line containing @p f.
119* @param f The line to search for.
120* @param list_fname The file to search in.
121* @param preamble Ignore this beginning part of @p f ("" to disable).
122* @return TRUE if it's in the list, FALSE if it's not.
123*/
124bool is_file_in_list(char *f, char *list_fname, char *preamble)
125{
126
127char *command = NULL;
128char *file = NULL;
129char *tmp = NULL;
130int res;
131
132assert_string_is_neither_NULL_nor_zerolength(f);
133assert_string_is_neither_NULL_nor_zerolength(list_fname);
134assert(preamble != NULL);
135
136if (strncmp(preamble, f, strlen(preamble)) == 0) {
137    mr_asprintf(file, "%s", f + strlen(preamble));
138} else {
139    mr_asprintf(file, "%s", f);
140}
141if (file[0] == '/' && file[1] == '/') {
142    mr_asprintf(tmp, "%s", file);
143    mr_free(file);
144
145    mr_asprintf(file, "%s", tmp + 1);
146    mr_free(tmp);
147}
148log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
149mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
150mr_free(file);
151
152res = run_program_and_log_output(command, FALSE);
153mr_free(command);
154if (res) {
155    return (FALSE);
156} else {
157    return (TRUE);
158}
159}
160
161/**************************************************************************
162*END_IS_FILE_IN_LIST                                                     *
163**************************************************************************/
164
165
166
167/**
168* Set up an ISO backup.
169* @param bkpinfo The backup information structure. Fields used:
170* - @c bkpinfo->backup_media_type
171* - @c bkpinfo->disaster_recovery
172* - @c bkpinfo->isodir
173* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
174* @return 0 for success, nonzero for failure.
175*/
176int iso_fiddly_bits(bool nuke_me_please)
177{
178    char *mount_isodir_command = NULL;
179    char *command = NULL;
180    char *mds = NULL;
181    int retval = 0, i;
182    char *isodir_format = NULL;
183
184g_ISO_restore_mode = TRUE;
185mr_free(g_isodir_device);
186g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
187if (bkpinfo->disaster_recovery) {
188    /* Patch Conor Daly 26-june-2004
189    * Don't let this clobber an existing bkpinfo->isodir */
190    if (!bkpinfo->isodir[0]) {
191        mr_free(bkpinfo->isodir);
192        mr_asprintf(bkpinfo->isodir, "/tmp/isodir");
193    }
194    /* End patch */
195    mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
196    run_program_and_log_output(command, 5);
197    mr_free(command);
198    log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
199}
200
201/* g_isodir_device is passed and modified in this function - memory is managed correctly in it */
202if (!get_isodir_info(g_isodir_device, isodir_format, bkpinfo->isodir, bkpinfo->subdir, nuke_me_please)) {
203    mr_free(isodir_format);
204    return (1);
205}
206paranoid_system("umount -d " MNT_CDROM " 2> /dev/null");    /* just in case */
207
208if (is_this_device_mounted(g_isodir_device)) {
209    log_to_screen("WARNING - isodir is already mounted");
210} else {
211    mr_asprintf(mount_isodir_command, "mount %s", g_isodir_device);
212    if (isodir_format) {
213        mr_strcat(mount_isodir_command, " -t %s", isodir_format);
214    }
215
216    mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
217    run_program_and_log_output("df -m -P", FALSE);
218    log_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?", mount_isodir_command);
219    if (run_program_and_log_output(mount_isodir_command, FALSE)) {
220        popup_and_OK
221            ("Cannot mount the device where the ISO files are stored.");
222        return (1);
223    }
224    paranoid_free(mount_isodir_command);
225    log_to_screen
226    ("I have mounted the device where the ISO files are stored.");
227}
228mr_free(isodir_format);
229
230if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
231    mount_media();
232}
233i = what_number_cd_is_this();   /* has the side-effect of calling mount_media() */
234mds = media_descriptor_string(bkpinfo->backup_media_type);
235mr_free(mds);
236
237log_msg(1, "%s #%d has been mounted via loopback mount", mds, i);
238if (i < 0) {
239    popup_and_OK("Cannot find ISO images in the directory you specified.");
240    retval = 1;
241}
242log_msg(2, "bkpinfo->isodir is now %s", bkpinfo->isodir);
243return (retval);
244}
245
246
247
248
249/**
250* Kill all Petris processes.
251*/
252void kill_petris(void) {
253    kill_anything_like_this("petris");
254}
255
256/**************************************************************************
257*END_KILL_PETRIS                                                         *
258**************************************************************************/
259
260
261/**
262 * Mount @p device at @p mpt as @p format.
263 * @param device The device (/dev entry) to mount.
264 * @param mpt The directory to mount it on.
265 * @param format The filesystem type of @p device.
266 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
267 * @return 0 for success, nonzero for failure.
268 */
269int mount_device(char *device, char *mpt, char *format, bool writeable)
270{
271int res = 0;
272
273/** malloc **/
274char *tmp = NULL;
275char *command = NULL;
276char *mountdir = NULL;
277char *mountpoint = NULL;
278char *additional_parameters = NULL;
279
280assert_string_is_neither_NULL_nor_zerolength(device);
281assert_string_is_neither_NULL_nor_zerolength(mpt);
282assert(format != NULL);
283
284    if (!strcmp(mpt, "/1")) {
285        mr_asprintf(mountpoint, "/");
286        log_msg(3, "Mommm! SME is being a dildo!");
287    } else {
288        mr_asprintf(mountpoint, "%s", mpt);
289    }
290
291    if (!strcmp(mountpoint, "lvm")) {
292        return (0);
293    }
294    if (!strcmp(mountpoint, "image")) {
295        return (0);
296    }
297    mr_asprintf(tmp, "Mounting device %s   ", device);
298    log_msg(1, tmp);
299    /* Deal with additional params only if not /proc or /sys */
300    mr_asprintf(additional_parameters, "");
301    if (strcmp(format, "proc") && strcmp(format, "sys")) {
302        if (writeable) {
303            mr_strcat(additional_parameters, "-o rw");
304        } else {
305            mr_strcat(additional_parameters, "-o ro");
306        }
307        tmp = find_home_of_exe("setfattr");
308        if (tmp) {
309            mr_strcat(additional_parameters, ",user_xattr");
310        }
311        mr_free(tmp);
312
313        tmp = find_home_of_exe("setfacl");
314        if (tmp) {
315            mr_strcat(additional_parameters, ",acl");
316        }
317        mr_free(tmp);
318    }
319
320    if (!strcmp(mountpoint, "swap")) {
321        mr_asprintf(command, "swapon %s", device);
322        mr_asprintf(mountdir, "swap");
323    } else {
324        if (!strcmp(mountpoint, "/")) {
325            mr_asprintf(mountdir, "%s", MNT_RESTORING);
326        } else {
327            mr_asprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
328        }
329        mr_asprintf(command, "mkdir -p %s", mountdir);
330        run_program_and_log_output(command, FALSE);
331        mr_free(command);
332
333        mr_asprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE);
334        log_msg(2, "command='%s'", command);
335    }
336    mr_free(additional_parameters);
337
338    res = run_program_and_log_output(command, TRUE);
339    if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
340        log_msg(1, "Re-trying without the fancy extra parameters");
341        mr_free(command);
342        mr_asprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE);
343        res = run_program_and_log_output(command, TRUE);
344    }
345    if (res) {
346        log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir);
347        log_msg(1, "command was '%s'", command);
348        if (!strcmp(mountpoint, "swap")) {
349            log_to_screen(tmp);
350        } else {
351            log_msg(2, "Retrying w/o the '-t' switch");
352            mr_free(command);
353            mr_asprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE);
354            log_msg(2, "2nd command = '%s'", command);
355            res = run_program_and_log_output(command, TRUE);
356            if (res == 0) {
357                log_msg(1,
358                    "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
359            } else {
360                log_to_screen(tmp);
361            }
362        }
363    }
364
365    if (res && !strcmp(mountpoint, "swap")) {
366        log_msg(2, "That's ok. It's just a swap partition.");
367        log_msg(2, "Non-fatal error. Returning 0.");
368        res = 0;
369    }
370
371mr_free(tmp);
372mr_free(command);
373mr_free(mountdir);
374mr_free(mountpoint);
375
376    return (res);
377}
378/**************************************************************************
379 *END_MOUNT_DEVICE                                                        *
380**************************************************************************/
381
382
383/**
384 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
385 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
386 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
387 * @return The number of errors encountered (0 for success).
388 */
389int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable)
390{
391int retval = 0, lino, res;
392char *tmp = NULL;
393char *these_failed = NULL;
394struct mountlist_itself *mountlist = NULL;
395
396assert(p_external_copy_of_mountlist != NULL);
397mountlist = malloc(sizeof(struct mountlist_itself));
398memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
399   sizeof(struct mountlist_itself));
400    sort_mountlist_by_mountpoint(mountlist, 0);
401
402
403    mvaddstr_and_log_it(g_currentY, 0, "Mounting devices         ");
404    open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries);
405
406    mr_asprintf(these_failed, "");
407    for (lino = 0; lino < mountlist->entries; lino++) {
408        if (!strcmp(mountlist->el[lino].device, "/proc")) {
409            log_msg(1, "Again with the /proc - why is this in your mountlist?");
410        } else if (is_this_device_mounted(mountlist->el[lino].device)) {
411            log_to_screen("%s is already mounted", mountlist->el[lino].device);
412        } else if (strcmp(mountlist->el[lino].mountpoint, "none")
413           && strcmp(mountlist->el[lino].mountpoint, "lvm")
414           && strcmp(mountlist->el[lino].mountpoint, "raid")
415           && strcmp(mountlist->el[lino].mountpoint, "image")) {
416            mr_asprintf(tmp, "Mounting %s", mountlist->el[lino].device);
417            update_progress_form(tmp);
418            mr_free(tmp);
419            res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, mountlist->el[lino].format, writeable);
420
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);
662
663media_specified_by_user = bkpinfo->backup_media_type;   // or 'none', if not specified
664
665if ((value = read_cfg_var(cfg_file, "backup-media-type")) != NULL) {
666    if (!strcmp(value, "cdstream")) {
667        bkpinfo->backup_media_type = cdstream;
668    } else if (!strcmp(value, "cdr")) {
669        bkpinfo->backup_media_type = cdr;
670    } else if (!strcmp(value, "cdrw")) {
671        bkpinfo->backup_media_type = cdrw;
672    } else if (!strcmp(value, "dvd")) {
673        bkpinfo->backup_media_type = dvd;
674    } else if (!strcmp(value, "usb")) {
675        bkpinfo->backup_media_type = usb;
676        bkpinfo->please_dont_eject = TRUE;
677    } else if (!strcmp(value, "iso")) {
678        // Patch by Conor Daly - 2004/07/12
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
690                    ("Re-jigging configuration AGAIN. CD-R, not ISO.");
691            }
692        }
693        mr_free(bkpinfo->prefix);
694        mr_free(value);
695        if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
696            mr_asprintf(bkpinfo->prefix, "%s", value);
697        } else {
698            mr_asprintf(bkpinfo->prefix, "%s", STD_PREFIX);
699        }
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[0] = 1999 * 1024;
757        bkpinfo->media_size[1] = 650;   /* good guess */
758    } else if (bkpinfo->backup_media_type == usb) {
759        envtmp1 = getenv("MRUSBDEV");
760        if (envtmp1 == NULL) {
761            if ((value = read_cfg_var(cfg_file, "usb-dev")) == NULL) {
762                fatal_error("Cannot get USB device name from cfg file");
763            }
764        } else {
765            mr_asprintf(value,"%s", envtmp1);
766        }
767        mr_free(bkpinfo->media_device);
768        mr_asprintf(bkpinfo->media_device, "%s1", value);
769        mr_free(value);
770        log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
771    } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
772        if ((value = read_cfg_var(cfg_file, "media-dev")) == NULL) {
773            fatal_error("Cannot get tape device name from cfg file");
774        }
775        mr_free(bkpinfo->media_device);
776        bkpinfo->media_device = value;
777
778        value = read_cfg_var(cfg_file, "media-size");
779        if (value != NULL) {
780            bkpinfo->media_size[1] = atol(value);
781            mr_free(value);
782        } else {
783            bkpinfo->media_size[1] = 0L;
784        }
785        log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
786    } else {
787        mr_free(bkpinfo->media_device);
788        mr_asprintf(bkpinfo->media_device, "/dev/cdrom");   /* we don't really need this var */
789        bkpinfo->media_size[0] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
790        bkpinfo->media_size[1] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
791        log_msg(2, "Backup medium is CD-R[W]");
792    }
793} else {
794    log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
795}
796
797value = read_cfg_var(cfg_file, "use-star");
798if (value && strstr(value, "yes")) {
799    bkpinfo->use_star = TRUE;
800    log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
801}
802mr_free(value);
803
804value = read_cfg_var(cfg_file, "obdr");
805if (value && strstr(value, "TRUE")) {
806    bkpinfo->use_obdr = TRUE;
807    log_msg(1, "OBDR mode activated");
808}
809mr_free(value);
810
811value = read_cfg_var(cfg_file, "acl");
812if (value && strstr(value, "TRUE")) {
813    mr_asprintf(g_getfacl,"setfacl");
814    log_msg(1, "We will restore ACLs");
815    tmp = find_home_of_exe("setfacl");
816    if (!tmp) {
817        log_msg(1, "Unable to restore ACLs as no setfacl found");
818    }
819    mr_free(tmp);
820}
821mr_free(value);
822
823value = read_cfg_var(cfg_file, "xattr");
824if (value && strstr(value, "TRUE")) {
825    mr_asprintf(g_getfattr,"setfattr");
826    log_msg(1, "We will restore XATTRs");
827    tmp = find_home_of_exe("setfattr");
828    if (!tmp) {
829        log_msg(1, "Unable to restore XATTRs as no setfattr found");
830    }
831    mr_free(tmp);
832}
833mr_free(value);
834
835value = read_cfg_var(cfg_file, "internal-tape-block-size");
836if (value != NULL) {
837    bkpinfo->internal_tape_block_size = atol(value);
838} else {
839    bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
840}
841log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
842mr_free(value);
843
844value = read_cfg_var(cfg_file, "use-lzma");
845if (value && strstr(value, "yes")) {
846    bkpinfo->use_lzma = TRUE;
847    bkpinfo->use_lzo = FALSE;
848    bkpinfo->use_gzip = FALSE;
849    mr_free(bkpinfo->zip_exe);
850    mr_asprintf(bkpinfo->zip_exe, "lzma");
851    mr_free(bkpinfo->zip_suffix);
852    mr_asprintf(bkpinfo->zip_suffix, "lzma");
853}
854mr_free(value);
855
856value = read_cfg_var(cfg_file, "use-lzo");
857if (value && strstr(value, "yes")) {
858    bkpinfo->use_lzma = FALSE;
859    bkpinfo->use_lzo = TRUE;
860    bkpinfo->use_gzip = FALSE;
861    mr_free(bkpinfo->zip_exe);
862    mr_asprintf(bkpinfo->zip_exe, "lzop");
863    mr_free(bkpinfo->zip_suffix);
864    mr_asprintf(bkpinfo->zip_suffix, "lzo");
865}
866mr_free(value);
867
868value = read_cfg_var(cfg_file, "use-gzip");
869if (value && strstr(value, "yes")) {
870    bkpinfo->use_lzma = FALSE;
871    bkpinfo->use_lzo = FALSE;
872    bkpinfo->use_gzip = TRUE;
873    mr_free(bkpinfo->zip_exe);
874    mr_asprintf(bkpinfo->zip_exe, "gzip");
875    mr_free(bkpinfo->zip_suffix);
876    mr_asprintf(bkpinfo->zip_suffix, "gz");
877}
878mr_free(value);
879
880value = read_cfg_var(cfg_file, "use-comp");
881if (value && strstr(value, "yes")) {
882    bkpinfo->use_lzma = FALSE;
883    bkpinfo->use_lzo = FALSE;
884    bkpinfo->use_gzip = FALSE;
885    mr_free(bkpinfo->zip_exe);
886    mr_asprintf(bkpinfo->zip_exe, "bzip2");
887    mr_free(bkpinfo->zip_suffix);
888    mr_asprintf(bkpinfo->zip_suffix, "bz2");
889}
890mr_free(value);
891
892if (bkpinfo->zip_exe == NULL) {
893    mr_asprintf(bkpinfo->zip_exe, "none");
894}
895if (bkpinfo->zip_suffix == NULL) {
896    mr_asprintf(bkpinfo->zip_suffix, "");
897}
898
899value = read_cfg_var(cfg_file, "differential");
900if (value && (!strcmp(value, "yes") || !strcmp(value, "1"))) {
901    bkpinfo->differential = TRUE;
902}
903log_msg(2, "differential var = '%s'", value);
904mr_free(value);
905if (bkpinfo->differential) {
906    log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
907} else {
908    log_msg(2, "This is a regular (full) backup");
909}
910
911tmp = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "please-dont-eject");
912tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
913if (tmp || strstr(tmp1, "donteject")) {
914    bkpinfo->please_dont_eject = TRUE;
915    log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
916}
917mr_free(tmp);
918mr_free(tmp1);
919
920if (bkpinfo->backup_media_type == netfs) {
921    if (!cfgf) {
922        if (bkpinfo->netfs_mount) {
923            log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
924        }
925        if (bkpinfo->netfs_remote_dir) {
926            log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
927        }
928        log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
929    } else {
930        mr_free(bkpinfo->netfs_mount);
931        bkpinfo->netfs_mount = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-mount");
932
933        mr_free(bkpinfo->netfs_remote_dir);
934        bkpinfo->netfs_remote_dir = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-path");
935
936        if (bkpinfo->netfs_mount != NULL) {
937            log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
938        }
939        if (bkpinfo->netfs_remote_dir != NULL) {
940            log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
941        }
942        if (bkpinfo->netfs_proto != NULL) {
943            log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
944        }
945        if (bkpinfo->netfs_user != NULL) {
946            log_msg(2, "netfs_user is %s", bkpinfo->netfs_user);
947        }
948    }
949    tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
950    if (strstr(tmp1, "pxe")) {
951        mr_free(tmp1);
952        /* We need to override values in PXE mode as it's
953        * already done in start-netfs */
954        envtmp1 = getenv("netfsmount");
955        if (envtmp1 == NULL) {
956            fatal_error("no netfsmount variable in environment");
957        }
958        envtmp2 = getenv("dirimg");
959        if (envtmp2 == NULL) {
960            fatal_error("no dirimg variable in environment");
961        }
962        mr_free(bkpinfo->netfs_mount);
963        mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
964
965        mr_free(bkpinfo->netfs_remote_dir);
966        mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
967    } else {
968        mr_free(tmp1);
969    }
970
971} else if (bkpinfo->backup_media_type == iso) {
972    /* Patch by Conor Daly 23-june-2004
973    * to correctly mount iso-dev and set a sensible
974    * isodir in disaster recovery mode
975    */
976    mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
977    iso_mnt = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-mnt");
978    iso_path = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "isodir");
979    mr_free(bkpinfo->isodir);
980    mr_asprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
981    mr_free(iso_mnt);
982
983    if (!bkpinfo->isodir[0]) {
984        mr_free(bkpinfo->isodir);
985        bkpinfo->isodir = old_isodir;
986    } else {
987        mr_free(old_isodir);
988    }
989    if (!bkpinfo->disaster_recovery) {
990        if (strcmp(old_isodir, bkpinfo->isodir)) {
991            log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
992            mr_free(bkpinfo->isodir);
993            bkpinfo->isodir = old_isodir;
994        } else {
995            mr_free(old_isodir);
996        }
997    }
998    mr_free(g_isodir_device);
999    g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
1000    log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
1001
1002    if (bkpinfo->disaster_recovery) {
1003        if (is_this_device_mounted(g_isodir_device)) {
1004            log_msg(2, "NB: isodir is already mounted");
1005            /* Find out where it's mounted */
1006            mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
1007            log_it("command = %s", command);
1008            iso_mnt = call_program_and_get_last_line_of_output(command,TRUE);
1009            log_it("res of it = %s", iso_mnt);
1010            mr_free(command);
1011        } else {
1012            mr_asprintf(iso_mnt, "/tmp/isodir");
1013            mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
1014            run_program_and_log_output(tmp1, 5);
1015            mr_free(tmp1);
1016
1017            mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
1018            if (run_program_and_log_output(tmp1, 3)) {
1019                log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
1020                bkpinfo->backup_media_type = cdr;
1021                mr_free(bkpinfo->media_device);
1022                mr_asprintf(bkpinfo->media_device, "/dev/cdrom");   /* superfluous */
1023                if (mount_media()) {
1024                    mr_free(tmp1);
1025                    fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
1026                } else {
1027                    log_msg(1, "You backed up to disk, then burned some CDs.");
1028                }
1029            }
1030            mr_free(tmp1);
1031        }
1032        /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1033        if (bkpinfo->backup_media_type == iso) {
1034            mr_free(bkpinfo->isodir);
1035            mr_asprintf(tmp1, "%s%s", iso_mnt, iso_path);
1036            bkpinfo->isodir = tmp1;
1037        }
1038        mr_free(iso_mnt);
1039    }
1040    mr_free(iso_path);
1041}
1042
1043if (media_specified_by_user != none) {
1044    if (! bkpinfo->disaster_recovery) {
1045        if (bkpinfo->backup_media_type != media_specified_by_user) {
1046            log_msg(2,
1047                    "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1048            interactively_obtain_media_parameters_from_user(FALSE);
1049            media_specified_by_user = bkpinfo->backup_media_type;
1050            get_cfg_file_from_initrd();
1051        }
1052    }
1053    bkpinfo->backup_media_type = media_specified_by_user;
1054}
1055g_backup_media_type = bkpinfo->backup_media_type;
1056paranoid_free(value);
1057return (0);
1058
1059}
1060
1061/**************************************************************************
1062*END_READ_CFG_FILE_INTO_BKPINFO                                          *
1063**************************************************************************/
1064
1065
1066
1067
1068/**
1069 * Allow the user to edit the filelist and biggielist.
1070 * The filelist is unlinked after it is read.
1071 * @param bkpinfo The backup information structure. Fields used:
1072 * - @c bkpinfo->backup_media_type
1073 * - @c bkpinfo->isodir
1074 * - @c bkpinfo->media_device
1075 * - @c bkpinfo->tmpdir
1076 * @return The filelist structure containing the information read from disk.
1077 */
1078struct
1079s_node *process_filelist_and_biggielist()
1080{
1081struct s_node *filelist;
1082
1083char *command = NULL;
1084char *tmp;
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
1405    assert_string_is_neither_NULL_nor_zerolength(bd);
1406    mr_asprintf(boot_device, "%s", bd);
1407
1408    if (offer_to_run_stabgrub
1409        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1410        /* interactive mode */
1411        mvaddstr_and_log_it(g_currentY,
1412                            0,
1413                            "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB...                             ");
1414        /*  Did we changed the mountlist ? If yes, then force editing conf files */
1415        if ((fin = fopen(MONDO_MNTLISTCHG, "r")) != NULL) {
1416            mntlistchg = TRUE;
1417        }
1418        for (done = FALSE; !done;) {
1419            p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1420            if (p == NULL) {
1421                done = TRUE;
1422                mr_free(p);
1423                /* we want some warnings later on */
1424                res = 1;
1425                continue;
1426            }
1427            /*  Only try to adapt grub here first if the mountlist wasn't changed before */
1428            if (! mntlistchg) {
1429                mr_asprintf(command, "stabgrub-me %s", p);
1430                mr_free(p);
1431
1432                res = run_program_and_log_output(command, 1);
1433                mr_free(command);
1434            }
1435
1436            if ((res) || (mntlistchg)) {
1437                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");
1438            } else {
1439                popup_and_OK("The mountlist was changed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
1440            }
1441            if (!g_text_mode) {
1442                newtSuspend();
1443            }
1444            mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1445            paranoid_system(tmp);
1446            mr_free(tmp);
1447
1448            mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1449            paranoid_system(tmp);
1450            mr_free(tmp);
1451
1452            if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1453                mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1454            } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1455                mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1456            } else if (does_file_exist(MNT_RESTORING"/boot/grub2/grub.cfg")) {
1457                mr_asprintf(tmp, "chroot %s %s /boot/grub2/grub.cfg", MNT_RESTORING, editor);
1458            }
1459            paranoid_system(tmp);
1460            mr_free(tmp);
1461
1462            if (does_file_exist(MNT_RESTORING"/boot/grub/device.map")) {
1463                mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1464            } else if (does_file_exist(MNT_RESTORING"/boot/grub2/device.map")) {
1465                mr_asprintf(tmp, "chroot %s %s /boot/grub2/device.map", MNT_RESTORING, editor);
1466            }
1467            paranoid_system(tmp);
1468            mr_free(tmp);
1469
1470            if (!g_text_mode) {
1471                newtResume();
1472            }
1473            mr_asprintf(command, "stabgrub-me %s", boot_device);
1474            res = run_program_and_log_output(command, 1);
1475            mr_free(command);
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            mr_asprintf(editor, "%s", find_my_editor());
1491
1492            mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1493            paranoid_system(tmp);
1494            mr_free(tmp);
1495
1496            mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1497            paranoid_system(tmp);
1498            mr_free(tmp);
1499
1500            if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1501                mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1502            } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1503                mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1504            }
1505            paranoid_system(tmp);
1506            mr_free(tmp);
1507
1508            mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1509            paranoid_system(tmp);
1510            mr_free(tmp);
1511            mr_free(editor);
1512
1513            if (!g_text_mode) {
1514                newtResume();
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,
1528                            0,
1529                            "Running GRUB...                                                 ");
1530        log_it("%s",command);
1531        res = run_program_and_log_output(command, 1);
1532        mr_free(command);
1533
1534        if (res) {
1535            popup_and_OK
1536                ("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.");
1537            newtSuspend();
1538            paranoid_system("chroot " MNT_RESTORING);
1539            newtResume();
1540            popup_and_OK("Thank you.");
1541        }
1542    }
1543    mr_free(boot_device);
1544
1545    if (res) {
1546        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1547        log_to_screen
1548            ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1549        log_msg(1, "Type:-");
1550        log_msg(1, "    mount-me");
1551        log_msg(1, "    chroot " MNT_RESTORING);
1552        log_msg(1, "    mount /boot");
1553        log_msg(1, "    grub-install '(hd0)'");
1554        log_msg(1, "    exit");
1555        log_msg(1, "    unmount-me");
1556        log_msg(1,
1557                "If you're really stuck, please e-mail the mailing list.");
1558    } else {
1559        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1560    }
1561
1562    return (res);
1563}
1564
1565/**************************************************************************
1566 *END_RUN_GRUB                                                            *
1567 **************************************************************************/
1568
1569
1570/**
1571 * Install ELILO on the user's boot drive (determined by elilo.conf).
1572 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1573 * @return 0 for success, nonzero for failure.
1574 */
1575int run_elilo(bool offer_to_run_stabelilo)
1576{
1577  /** malloc **/
1578    char *command = NULL;
1579    char *tmp = NULL;
1580    char *editor = NULL;
1581
1582    int res;
1583    int done;
1584
1585    if (offer_to_run_stabelilo
1586        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1587
1588        /* interactive mode */
1589    {
1590        mvaddstr_and_log_it(g_currentY,
1591                            0,
1592                            "Modifying fstab and elilo.conf...                             ");
1593        mr_asprintf(command, "stabelilo-me");
1594        res = run_program_and_log_output(command, 3);
1595        mr_free(command);
1596
1597        if (res) {
1598            popup_and_OK
1599                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1600            for (done = FALSE; !done;) {
1601                if (!g_text_mode) {
1602                    newtSuspend();
1603                }
1604                mr_asprintf(editor, "%s", find_my_editor());
1605
1606                mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1607                paranoid_system(tmp);
1608                mr_free(tmp);
1609
1610                mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1611                paranoid_system(tmp);
1612                mr_free(tmp);
1613
1614                mr_free(editor);
1615
1616                if (!g_text_mode) {
1617                    newtResume();
1618                }
1619//              newtCls();
1620                if (ask_me_yes_or_no("Edit them again?")) {
1621                    continue;
1622                }
1623                done = TRUE;
1624            }
1625        } else {
1626            log_to_screen("elilo.conf and fstab were modified OK");
1627        }
1628    } else
1629        /* nuke mode */
1630    {
1631        res = TRUE;
1632    }
1633    return (res);
1634}
1635
1636/**************************************************************************
1637 *END_RUN_ELILO                                                            *
1638 **************************************************************************/
1639
1640
1641/**
1642 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1643 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1644 * @return 0 for success, nonzero for failure.
1645 */
1646int run_lilo(bool offer_to_run_stablilo)
1647{
1648  /** malloc **/
1649    char *command = NULL;
1650    char *tmp = NULL;
1651    char *editor = NULL;
1652
1653    int res;
1654    int done;
1655    bool run_lilo_M = FALSE;
1656
1657    if (!run_program_and_log_output
1658        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1659        run_lilo_M = TRUE;
1660    }
1661
1662    if (offer_to_run_stablilo
1663        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1664
1665        /* interactive mode */
1666    {
1667        mvaddstr_and_log_it(g_currentY,
1668                            0,
1669                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1670        mr_asprintf(command, "stablilo-me");
1671        res = run_program_and_log_output(command, 3);
1672        mr_free(command);
1673
1674        if (res) {
1675            popup_and_OK
1676                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1677            for (done = FALSE; !done;) {
1678                if (!g_text_mode) {
1679                    newtSuspend();
1680                }
1681                mr_asprintf(editor, "%s", find_my_editor());
1682
1683                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1684                paranoid_system(tmp);
1685                mr_free(tmp);
1686
1687                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1688                paranoid_system(tmp);
1689                mr_free(tmp);
1690
1691                mr_free(editor);
1692
1693                if (!g_text_mode) {
1694                    newtResume();
1695                }
1696//              newtCls();
1697                if (ask_me_yes_or_no("Edit them again?")) {
1698                    continue;
1699                }
1700                res =
1701                    run_program_and_log_output("chroot " MNT_RESTORING
1702                                               " lilo -L", 3);
1703                if (res) {
1704                    res =
1705                        run_program_and_log_output("chroot " MNT_RESTORING
1706                                                   " lilo", 3);
1707                }
1708                if (res) {
1709                    done =
1710                        ask_me_yes_or_no
1711                        ("LILO failed. Re-edit system files?");
1712                } else {
1713                    done = TRUE;
1714                }
1715            }
1716        } else {
1717            log_to_screen("lilo.conf and fstab were modified OK");
1718        }
1719    } else
1720        /* nuke mode */
1721    {
1722        mvaddstr_and_log_it(g_currentY,
1723                            0,
1724                            "Running LILO...                                                 ");
1725        res =
1726            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1727                                       3);
1728        if (res) {
1729            res =
1730                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1731                                           3);
1732        }
1733        if (res) {
1734            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1735            log_to_screen
1736                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1737        } else {
1738            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1739        }
1740    }
1741    if (run_lilo_M) {
1742        run_program_and_log_output("chroot " MNT_RESTORING
1743                                   " lilo -M /dev/hda", 3);
1744        run_program_and_log_output("chroot " MNT_RESTORING
1745                                   " lilo -M /dev/sda", 3);
1746    }
1747    return (res);
1748}
1749
1750/**************************************************************************
1751 *END_RUN_LILO                                                            *
1752 **************************************************************************/
1753
1754
1755/**
1756 * Install a raw MBR onto @p bd.
1757 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1758 * @param bd The device to copy the stored MBR to.
1759 * @return 0 for success, nonzero for failure.
1760 */
1761int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1762{
1763  /** malloc **/
1764    char *command = NULL;
1765    char *boot_device = NULL;
1766    char *tmp = NULL;
1767    char *editor;
1768    char *p = NULL;
1769    int res;
1770    int done;
1771
1772    assert_string_is_neither_NULL_nor_zerolength(bd);
1773
1774    mr_asprintf(boot_device, "%s", bd);
1775
1776    if (offer_to_hack_scripts
1777        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1778        /* interactive mode */
1779        mvaddstr_and_log_it(g_currentY, 0,
1780                            "Modifying fstab and restoring MBR...                           ");
1781        for (done = FALSE; !done;) {
1782            if (!run_program_and_log_output("which vi", FALSE)) {
1783                popup_and_OK("You will now edit fstab");
1784                if (!g_text_mode) {
1785                    newtSuspend();
1786                }
1787                mr_asprintf(editor, "%s", find_my_editor());
1788                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1789                mr_free(editor);
1790
1791                paranoid_system(tmp);
1792                mr_free(tmp);
1793                if (!g_text_mode) {
1794                    newtResume();
1795                }
1796            }
1797            p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1798            if (p == NULL) {
1799                done = TRUE;
1800                mr_free(p);
1801                /* we want some warnings later on */
1802                res = 1;
1803                continue;
1804            }
1805            mr_asprintf(command, "stabraw-me %s", p);
1806            mr_free(p);
1807
1808            res = run_program_and_log_output(command, 3);
1809            mr_free(command);
1810
1811            if (res) {
1812                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1813            } else {
1814                done = TRUE;
1815            }
1816        }
1817    } else {
1818        /* nuke mode */
1819        mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1820        log_msg(2, "run_raw_mbr() --- command='%s'", command);
1821
1822        mvaddstr_and_log_it(g_currentY, 0,
1823                            "Restoring MBR...                                               ");
1824        res = run_program_and_log_output(command, 3);
1825        mr_free(command);
1826    }
1827    mr_free(boot_device);
1828
1829    if (res) {
1830        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1831        log_to_screen
1832            ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1833    } else {
1834        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1835    }
1836    return (res);
1837}
1838
1839/**************************************************************************
1840 *END_RUN_RAW_MBR                                                         *
1841 **************************************************************************/
1842
1843
1844
1845/**
1846 * malloc() and set sensible defaults for the mondorestore filename variables.
1847 * @param bkpinfo The backup information structure. Fields used:
1848 * - @c bkpinfo->tmpdir
1849 * - @c bkpinfo->disaster_recovery
1850 */
1851void setup_MR_global_filenames()
1852{
1853    assert(bkpinfo != NULL);
1854
1855    malloc_string(g_filelist_imagedevs);
1856    malloc_string(g_imagedevs_restthese);
1857    malloc_string(g_mondo_home);
1858
1859    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1860    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", bkpinfo->tmpdir);
1861    if (! bkpinfo->disaster_recovery) {
1862        /* TODO: We need to get mondorestore.cfg and mountlist.txt from initrd.img */
1863        get_cfg_file_from_initrd();
1864    }
1865}
1866
1867/**************************************************************************
1868 *END_SET_GLOBAL_FILENAME                                                 *
1869 **************************************************************************/
1870
1871
1872/**
1873 * Copy @p input_file (containing the result of a compare) to @p output_file,
1874 * deleting spurious "changes" along the way.
1875 * @param output_file The output file to write with spurious changes removed.
1876 * @param input_file The input file, a list of changed files created by a compare.
1877 */
1878void streamline_changes_file(char *output_file, char *input_file)
1879{
1880    FILE *fin;
1881    FILE *fout;
1882    char *incoming = NULL;
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.