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

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

2nd phase for svn merge -r 2935:3146 ../3.0

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