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

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