source: branches/stable/mondo/src/mondorestore/mondo-rstr-tools.c @ 1196

Last change on this file since 1196 was 1196, checked in by bruno, 12 years ago

ChangeLog? for mindi UTF-8
mr_strcat much more powerful as taking a vararg (+ tests).
improved text output to log file for mondo
merge from trunk memory management for mondorestore (begining)

  • Property svn:keywords set to Id
File size: 76.0 KB
Line 
1/***************************************************************************
2 * $Id: mondo-rstr-tools.c 1196 2007-02-21 01:40:49Z bruno $
3*/
4
5
6#include <pthread.h>
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "mr_msg.h"
10#include "mr_str.h"
11
12#include "mondostructures.h"
13#include "libmondo.h"
14#include "mr-externs.h"
15//#include "mondo-restore.h"
16//#include "mondo-rstr-compare-EXT.h"
17#include "mondo-rstr-tools.h"
18
19extern bool g_sigpipe_caught;
20extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
21extern bool g_I_have_just_nuked;
22extern char *g_tmpfs_mountpt;
23extern char *g_isodir_device;
24extern char *g_isodir_format;
25extern long g_current_progress, g_maximum_progress;
26extern char *g_biggielist_txt;  // where 'biggielist.txt' is stored, on ramdisk / tempdir;
27                          // biggielist.txt is the list of big files stored on the
28                          // backup media set in question
29extern char *g_filelist_full;   // filelist.full.gz is the list of all regular files
30                          // (excluding big files) stored on the backup media set
31extern char *g_biggielist_pot;  // list of big files which _could_ be restored, if the
32                          // user chooses them
33extern char *g_filelist_imagedevs;  // list of devices (e.g. /dev/hda1, /dev/sda5) which
34                             // were archived as images, not just /dev entries
35                             // ... e.g. NTFS, BeOS partitions
36extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
37                              // restore only these
38extern char *g_mondo_cfg_file;  // where m*ndo-restore.cfg (the config file) is stored
39extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
40extern char *g_mondo_home;      // homedir of Mondo; usually /usr/local/share/mondo
41
42extern t_bkptype g_backup_media_type;
43
44extern int g_partition_table_locked_up;
45
46/* Should we use or not extended attributes and acl when restoring */
47char *g_getfattr = NULL;
48char *g_getfacl = NULL;
49
50/**
51 * @addtogroup restoreUtilityGroup
52 * @{
53 */
54/**
55 * Free the malloc()s for the filename variables.
56 */
57void free_MR_global_filenames(void)
58{
59    mr_free(g_biggielist_txt);
60    mr_free(g_filelist_full);
61    mr_free(g_filelist_imagedevs);
62//  mr_free (g_imagedevs_pot );
63    mr_free(g_imagedevs_restthese);
64    mr_free(g_mondo_cfg_file);
65    mr_free(g_mountlist_fname);
66    mr_free(g_mondo_home);
67    mr_free(g_tmpfs_mountpt);
68    mr_free(g_isodir_device);
69    mr_free(g_isodir_format);
70
71}
72
73
74
75/**
76 * Ask the user which imagedevs from the list contained in @p infname should
77 * actually be restored.
78 * @param infname The file containing a list of all imagedevs.
79 * @param outfname The location of the output file containing the imagedevs the user wanted to restore.
80 * @ingroup restoreUtilityGroup
81 */
82void ask_about_these_imagedevs(char *infname, char *outfname)
83{
84    FILE *fin;
85    FILE *fout;
86  /************************************************************************
87   * allocate memory regions. test and set  -sab 16 feb 2003              *
88   ************************************************************************/
89    char *incoming_ptr;
90    char *question_ptr;
91
92    char incoming[MAX_STR_LEN] = "\0";
93    char question[MAX_STR_LEN];
94
95    assert_string_is_neither_NULL_nor_zerolength(infname);
96    assert_string_is_neither_NULL_nor_zerolength(outfname);
97
98    incoming_ptr = mr_malloc(sizeof(incoming));
99    question_ptr = mr_malloc(sizeof(question));
100
101    memset(incoming_ptr, '\0', sizeof(incoming));
102    memset(question_ptr, '\0', sizeof(question));
103
104
105
106    if (!(fin = fopen(infname, "r"))) {
107        fatal_error("Cannot openin infname");
108    }
109    if (!(fout = fopen(outfname, "w"))) {
110        fatal_error("Cannot openin outfname");
111    }
112    for (fgets(incoming_ptr, MAX_STR_LEN, fin);
113         !feof(fin); fgets(incoming_ptr, MAX_STR_LEN, fin)) {
114        mr_strip_spaces(incoming_ptr);
115
116        if (incoming[0] == '\0') {
117            continue;
118        }
119
120        sprintf(question_ptr,
121                "Should I restore the image of %s ?", incoming_ptr);
122
123        if (ask_me_yes_or_no(question_ptr)) {
124            fprintf(fout, "%s\n", incoming_ptr);
125        }
126    }
127
128  /*** free memory ***********/
129    mr_free(incoming_ptr);
130    incoming_ptr = NULL;
131    mr_free(question_ptr);
132    question_ptr = NULL;
133
134
135    paranoid_fclose(fout);
136    paranoid_fclose(fin);
137}
138
139/**************************************************************************
140 *ASK_ABOUT_THESE_IMAGEDEVS                                               *
141 **************************************************************************/
142
143
144
145
146
147
148
149
150/**
151 * Extract @c mondo-restore.cfg and @c mountlist.txt from @p ramdisk_fname.
152 * @param bkpinfo The backup information structure. @c tmpdir is the only field used.
153 * @param ramdisk_fname The filename of the @b compressed ramdisk to look in.
154 * @param output_cfg_file Where to put the configuration file extracted.
155 * @param output_mountlist_file Where to put the mountlist file extracted.
156 * @return 0 for success, nonzero for failure.
157 * @ingroup restoreUtilityGroup
158 */
159int
160extract_config_file_from_ramdisk(struct s_bkpinfo *bkpinfo,
161                                 char *ramdisk_fname,
162                                 char *output_cfg_file,
163                                 char *output_mountlist_file)
164{
165    char *mountpt;
166    char *command;
167    char *orig_fname;
168    int retval = 0;
169
170    assert(bkpinfo != NULL);
171    malloc_string(mountpt);
172    malloc_string(command);
173    malloc_string(orig_fname);
174    assert_string_is_neither_NULL_nor_zerolength(ramdisk_fname);
175    assert_string_is_neither_NULL_nor_zerolength(output_cfg_file);
176    assert_string_is_neither_NULL_nor_zerolength(output_mountlist_file);
177    sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
178    sprintf(command, "mkdir -p %s", mountpt);
179    run_program_and_log_output(command, FALSE);
180    sprintf(command, "gzip -dc %s > %s/mindi.rd 2> /dev/null",
181            ramdisk_fname, bkpinfo->tmpdir);
182
183    run_program_and_log_output(command, FALSE);
184    sprintf(command, "umount %s", mountpt);
185
186    run_program_and_log_output(command, FALSE);
187
188    sprintf(command, "mount -o loop %s/mindi.rd -t ext2 %s",
189            bkpinfo->tmpdir, mountpt);
190
191    run_program_and_log_output(command, FALSE);
192
193    sprintf(command, "mkdir -p %s/tmp", bkpinfo->tmpdir);
194
195    run_program_and_log_output(command, FALSE);
196
197    sprintf(command, "cp -f %s/%s %s",  // %s/%s becomes {mountpt}/tmp/m*ndo-restore.cfg
198            mountpt, g_mondo_cfg_file, output_cfg_file);
199    run_program_and_log_output(command, FALSE);
200
201    sprintf(orig_fname, "%s/%s", mountpt, g_mountlist_fname);
202    if (does_file_exist(orig_fname)) {
203        sprintf(command, "cp -f %s %s", orig_fname, output_mountlist_file);
204        run_program_and_log_output(command, FALSE);
205    }
206    sprintf(command, "umount %s", mountpt);
207    run_program_and_log_output(command, FALSE);
208    if (!does_file_exist(output_cfg_file)
209        || (!does_file_exist(output_mountlist_file)
210            && does_file_exist(orig_fname))) {
211        mr_msg(2, "Failed to extract %s and/or %s from ramdisk",
212                output_cfg_file, output_mountlist_file);
213        retval = 1;
214    } else {
215        retval = 0;
216    }
217    mr_free(mountpt);
218    mr_free(command);
219    mr_free(orig_fname);
220    return (retval);
221
222}
223
224
225
226
227/**
228 * Keep trying to get mondo-restore.cfg from the archive, until the user gives up.
229 * @param bkpinfo The backup information structure.
230 */
231void get_cfg_file_from_archive_or_bust(struct s_bkpinfo *bkpinfo)
232{
233    while (get_cfg_file_from_archive(bkpinfo)) {
234        if (!ask_me_yes_or_no
235            ("Failed to find config file/archives. Choose another source?"))
236        {
237            fatal_error("Could not find config file/archives. Aborting.");
238        }
239        interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
240    }
241}
242
243
244/**
245 * Determine whether @p list_fname contains a line containing @p f.
246 * @param f The line to search for.
247 * @param list_fname The file to search in.
248 * @param preamble Ignore this beginning part of @p f ("" to disable).
249 * @return TRUE if it's in the list, FALSE if it's not.
250 */
251bool is_file_in_list(char *f, char *list_fname, char *preamble)
252{
253
254  /** needs malloc **/
255    char *command;
256    char *file;
257    char *tmp;
258    int res;
259
260    malloc_string(command);
261    malloc_string(file);
262    malloc_string(tmp);
263    assert_string_is_neither_NULL_nor_zerolength(f);
264    assert_string_is_neither_NULL_nor_zerolength(list_fname);
265    assert(preamble != NULL);
266
267    if (strncmp(preamble, f, strlen(preamble)) == 0) {
268        strcpy(file, f + strlen(preamble));
269    } else {
270        strcpy(file, f);
271    }
272    if (file[0] == '/' && file[1] == '/') {
273        strcpy(tmp, file);
274        strcpy(file, tmp + 1);
275    }
276    sprintf(tmp,
277            "Checking to see if f=%s, file=%s, is in the list of biggiefiles",
278            f, file);
279    mr_msg(2, tmp);
280    sprintf(command, "grep -E '^%s$' %s", file, list_fname);
281    res = run_program_and_log_output(command, FALSE);
282    mr_free(command);
283    mr_free(file);
284    mr_free(tmp);
285    if (res) {
286        return (FALSE);
287    } else {
288        return (TRUE);
289    }
290}
291
292/**************************************************************************
293 *END_IS_FILE_IN_LIST                                                     *
294 **************************************************************************/
295
296
297
298/**
299 * Set up an ISO backup.
300 * @param bkpinfo The backup information structure. Fields used:
301 * - @c bkpinfo->backup_media_type
302 * - @c bkpinfo->disaster_recovery
303 * - @c bkpinfo->isodir
304 * @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
305 * @return 0 for success, nonzero for failure.
306 */
307int iso_fiddly_bits(struct s_bkpinfo *bkpinfo, bool nuke_me_please)
308{
309    char *mount_isodir_command, *tmp, *command;
310    int retval = 0, i;
311    bool already_mounted = FALSE;
312
313    assert(bkpinfo != NULL);
314    malloc_string(mount_isodir_command);
315    malloc_string(tmp);
316    malloc_string(command);
317    g_ISO_restore_mode = TRUE;
318    read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
319    if (bkpinfo->disaster_recovery) {
320/* Patch Conor Daly 26-june-2004
321 * Don't let this clobber an existing bkpinfo->isodir */
322        if (!bkpinfo->isodir[0]) {
323            strcpy(bkpinfo->isodir, "/tmp/isodir");
324        }
325/* End patch */
326        sprintf(command, "mkdir -p %s", bkpinfo->isodir);
327        run_program_and_log_output(command, 5);
328        mr_msg(2, "Setting isodir to %s", bkpinfo->isodir);
329    }
330
331    if (!get_isodir_info
332        (g_isodir_device, g_isodir_format, bkpinfo->isodir,
333         nuke_me_please)) {
334        return (1);
335    }
336    paranoid_system("umount " MNT_CDROM " 2> /dev/null");   /* just in case */
337
338    if (is_this_device_mounted(g_isodir_device)) {
339        log_to_screen("WARNING - isodir is already mounted");
340        already_mounted = TRUE;
341    } else {
342        sprintf(mount_isodir_command, "mount %s", g_isodir_device);
343        if (strlen(g_isodir_format) > 1) {
344            sprintf(mount_isodir_command + strlen(mount_isodir_command),
345                    " -t %s", g_isodir_format);
346        }
347        strcat(mount_isodir_command, " -o ro ");
348        strcat(mount_isodir_command, bkpinfo->isodir);
349        run_program_and_log_output("df -m", FALSE);
350        sprintf(tmp,
351                "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?",
352                mount_isodir_command);
353        mr_msg(1, tmp);
354        if (run_program_and_log_output(mount_isodir_command, FALSE)) {
355            popup_and_OK
356                ("Cannot mount the device where the ISO files are stored.");
357            return (1);
358        }
359        log_to_screen
360            ("I have mounted the device where the ISO files are stored.");
361    }
362    if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
363        mount_cdrom(bkpinfo);
364    }
365    i = what_number_cd_is_this(bkpinfo);    /* has the side-effect of calling mount_cdrom() */
366    sprintf(tmp, "%s #%d has been mounted via loopback mount",
367            media_descriptor_string(bkpinfo->backup_media_type), i);
368    mr_msg(1, tmp);
369    if (i < 0) {
370        popup_and_OK
371            ("Cannot find ISO images in the directory you specified.");
372        retval = 1;
373    }
374    mr_msg(2, "%ld: bkpinfo->isodir is now %s", __LINE__,
375            bkpinfo->isodir);
376    mr_free(mount_isodir_command);
377    mr_free(tmp);
378    mr_free(command);
379    return (retval);
380}
381
382
383
384
385/**
386 * Kill all Petris processes.
387 */
388void kill_petris(void)
389{
390    char *command;
391    malloc_string(command);
392    sprintf(command,
393            "kill `ps 2> /dev/null | grep petris 2> /dev/null | grep -v grep | cut -d' ' -f2` 2> /dev/null");
394    paranoid_system(command);
395    mr_free(command);
396}
397
398/**************************************************************************
399 *END_KILL_PETRIS                                                         *
400 **************************************************************************/
401
402
403/**
404 * (Disabled) Modify rc.local to fix some things on first boot.
405 * This function currently doesn't do anything except make sure /tmp has the
406 * right permissions.
407 * @param path The path to /etc on the user's filesystem.
408 * @return 0 for success, nonzero for failure.
409 */
410int modify_rclocal_one_time(char *path)
411{
412  /** malloc **/
413    char *rclocal_fname;
414    char *newfile_fname;
415    char *tmp;
416
417    malloc_string(rclocal_fname);
418    malloc_string(newfile_fname);
419    malloc_string(tmp);
420    assert_string_is_neither_NULL_nor_zerolength(path);
421
422    sprintf(rclocal_fname, "%s/rc.local", path);
423
424//  sprintf(tmp, "chmod 1777 %s/tmp", MNT_RESTORING);
425//  run_program_and_log_output( tmp, FALSE );
426    return (0);                 /* remove this line to open the floodgates... */
427
428    if (!does_file_exist(rclocal_fname)) {
429        sprintf(rclocal_fname, "%s/rc.d/rc.local", path);
430    }
431    if (!does_file_exist(rclocal_fname)) {
432        mr_free(rclocal_fname);
433        mr_free(newfile_fname);
434        mr_free(tmp);
435        return (1);
436    }
437    sprintf(newfile_fname, "%s/rc.local.mondorescue", path);
438    sprintf(tmp, "grep mondorescue %s > /dev/null 2> /dev/null",
439            rclocal_fname);
440    if (system(tmp)) {
441        sprintf(tmp, "echo \"[ -e %s ] && %s\n\" >> %s",
442                newfile_fname, newfile_fname, rclocal_fname);
443
444        paranoid_system(tmp);
445    }
446    sprintf(tmp, "echo -en \"#!/bin/sh\
447\\n\
448\\n\
449grep -v mondorescue %s > %s\\n\
450rm -f /var/lock/subsys/*xfs*\\n\
451rm -f /var/run/xfs.*\\n\
452killall xfs\\n\
453service xfs start\\n\
454yes | rm -f %s\\n\
455\" > %s", rclocal_fname, rclocal_fname, newfile_fname, newfile_fname);
456    sprintf(tmp, "chmod +x \"%s\"", newfile_fname);
457    run_program_and_log_output(tmp, FALSE);
458    mr_free(rclocal_fname);
459    mr_free(newfile_fname);
460    mr_free(tmp);
461    return (0);
462}
463
464/**************************************************************************
465 *END_ MODIFY_RCLOCAL_ONE_TIME                                            *
466 **************************************************************************/
467
468
469
470
471
472/**
473 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
474 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
475 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
476 * @return The number of errors encountered (0 for success).
477 */
478int mount_all_devices(struct mountlist_itself
479                      *p_external_copy_of_mountlist, bool writeable)
480{
481    int retval = 0, lino, res;
482    char *tmp, *these_failed, *format;
483    struct mountlist_itself *mountlist;
484
485    malloc_string(tmp);
486    malloc_string(format);
487    malloc_string(these_failed);
488    assert(p_external_copy_of_mountlist != NULL);
489    mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
490    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
491           sizeof(struct mountlist_itself));
492    sort_mountlist_by_mountpoint(mountlist, 0);
493
494  /** menset **/
495    these_failed[0] = '\0';
496
497    mvaddstr_and_log_it(g_currentY, 0, "Mounting devices         ");
498    open_progress_form("Mounting devices",
499                       "I am now mounting all the drives.",
500                       "This should not take long.",
501                       "", mountlist->entries);
502
503    for (lino = 0; lino < mountlist->entries; lino++) {
504        if (!strcmp(mountlist->el[lino].device, "/proc")) {
505            mr_msg(1,
506                    "Again with the /proc - why is this in your mountlist?");
507        } else if (is_this_device_mounted(mountlist->el[lino].device)) {
508            sprintf(tmp, "%s is already mounted",
509                    mountlist->el[lino].device);
510            log_to_screen(tmp);
511        } else if (strcmp(mountlist->el[lino].mountpoint, "none")
512                   && strcmp(mountlist->el[lino].mountpoint, "lvm")
513                   && strcmp(mountlist->el[lino].mountpoint, "raid")
514                   && strcmp(mountlist->el[lino].mountpoint, "image")) {
515            sprintf(tmp, "Mounting %s", mountlist->el[lino].device);
516            update_progress_form(tmp);
517            strcpy(format, mountlist->el[lino].format);
518            if (!strcmp(format, "ext3")) {
519                strcpy(format, "ext2");
520            }
521            res = mount_device(mountlist->el[lino].device,
522                               mountlist->el[lino].mountpoint,
523                               format, writeable);
524            retval += res;
525            if (res) {
526                strcat(these_failed, mountlist->el[lino].device);
527                strcat(these_failed, " ");
528            }
529        }
530        g_current_progress++;
531    }
532    close_progress_form();
533    run_program_and_log_output("df -m", TRUE);
534    if (retval) {
535        if (g_partition_table_locked_up > 0) {
536            log_to_screen
537                ("fdisk's ictol() call to refresh its copy of the partition table causes the kernel to");
538            log_to_screen
539                ("lock up the partition table. You might have to reboot and use Interactive Mode to");
540            log_to_screen
541                ("format and restore *without* partitioning first. Sorry for the inconvenience.");
542        }
543        sprintf(tmp, "Could not mount devices %s- shall I abort?",
544                these_failed);
545        if (!ask_me_yes_or_no(tmp)) {
546            retval = 0;
547            log_to_screen
548                ("Continuing, although some devices failed to be mounted");
549            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
550        } else {
551            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
552            log_to_screen
553                ("Unable to mount some or all of your partitions.");
554        }
555    } else {
556        log_to_screen("All partitions were mounted OK.");
557        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
558    }
559    run_program_and_log_output("df -m", 3);
560    mr_free(mountlist);
561    mr_free(tmp);
562    mr_free(format);
563    mr_free(these_failed);
564    return (retval);
565}
566
567 /**************************************************************************
568  *END_MOUNT_ALL_DEVICES                                                   *
569  **************************************************************************/
570
571
572/**
573 * Mount the CD-ROM device at /mnt/cdrom.
574 * @param bkpinfo The backup information structure. Fields used:
575 * - @c bkpinfo->backup_media_type
576 * - @c bkpinfo->disaster_recovery
577 * - @c bkpinfo->isodir
578 * - @c bkpinfo->media_device
579 * @return 0 for success, nonzero for failure.
580 */
581int mount_cdrom(struct s_bkpinfo *bkpinfo)
582{
583    char *mount_cmd;
584    int i, res;
585#ifdef __FreeBSD__
586    char mdd[32];
587    char *mddev = mdd;
588#endif
589
590    malloc_string(mount_cmd);
591    assert(bkpinfo != NULL);
592
593    if (bkpinfo->backup_media_type == tape
594        || bkpinfo->backup_media_type == udev) {
595        mr_msg(8, "Tape/udev. Therefore, no need to mount CDROM.");
596        mr_free(mount_cmd);
597        return 0;
598    }
599
600    if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) {
601        mr_msg(2, "mount_cdrom() - CD already mounted. Fair enough.");
602        mr_free(mount_cmd);
603        return (0);
604    }
605
606    if (bkpinfo->backup_media_type == nfs) {
607        mr_msg(2, "Mounting for NFS thingy");
608        mr_msg(2, "isodir = %s", bkpinfo->isodir);
609        if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/"))
610            && am_I_in_disaster_recovery_mode()) {
611            strcpy(bkpinfo->isodir, "/tmp/isodir");
612            mr_msg(1, "isodir is being set to %s", bkpinfo->isodir);
613        }
614#ifdef __FreeBSD__
615        sprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
616                bkpinfo->nfs_remote_dir, bkpinfo->prefix, g_current_media_number);
617        mddev = make_vn(mount_cmd);
618        sprintf(mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
619#else
620        sprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s",
621                bkpinfo->isodir, bkpinfo->nfs_remote_dir,
622                bkpinfo->prefix, g_current_media_number, MNT_CDROM);
623#endif
624
625    } else
626     if (bkpinfo->backup_media_type == iso) {
627#ifdef __FreeBSD__
628        sprintf(mount_cmd, "%s/%s-%d.iso", bkpinfo->isodir,
629                bkpinfo->prefix, g_current_media_number);
630        mddev = make_vn(mount_cmd);
631        sprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
632#else
633        sprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s",
634                bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, MNT_CDROM);
635#endif
636    } else if (strstr(bkpinfo->media_device, "/dev/"))
637#ifdef __FreeBSD__
638    {
639        sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
640                MNT_CDROM);
641    }
642#else
643    {
644        sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s",
645                bkpinfo->media_device, MNT_CDROM);
646    }
647#endif
648
649    else {
650        if (bkpinfo->disaster_recovery
651            && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
652            strcpy(bkpinfo->media_device,
653                   last_line_of_file("/tmp/CDROM-LIVES-HERE"));
654        } else {
655            find_cdrom_device(bkpinfo->media_device, TRUE);
656        }
657
658#ifdef __FreeBSD__
659        sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
660                MNT_CDROM);
661#else
662        sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s",
663                bkpinfo->media_device, MNT_CDROM);
664#endif
665
666    }
667    mr_msg(2, "(mount_cdrom) --- command = %s", mount_cmd);
668    for (i = 0; i < 2; i++) {
669        res = run_program_and_log_output(mount_cmd, FALSE);
670        if (!res) {
671            break;
672        } else {
673            mr_msg(2, "Failed to mount CD-ROM drive.");
674            sleep(5);
675            run_program_and_log_output("sync", FALSE);
676        }
677    }
678    if (res) {
679        mr_msg(2, "Failed, despite %d attempts", i);
680    } else {
681        mr_msg(2, "Mounted CD-ROM drive OK");
682    }
683    mr_free(mount_cmd);
684    return (res);
685}
686
687
688
689
690
691/**************************************************************************
692 *END_MOUNT_CDROM                                                         *
693 **************************************************************************/
694
695
696/**
697 * Mount @p device at @p mpt as @p format.
698 * @param device The device (/dev entry) to mount.
699 * @param mpt The directory to mount it on.
700 * @param format The filesystem type of @p device.
701 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
702 * @return 0 for success, nonzero for failure.
703 */
704int mount_device(char *device, char *mpt, char *format, bool writeable)
705{
706    int res = 0;
707
708  /** malloc **/
709    char *tmp, *command, *mountdir, *mountpoint, *additional_parameters;
710
711    assert_string_is_neither_NULL_nor_zerolength(device);
712    assert_string_is_neither_NULL_nor_zerolength(mpt);
713    assert(format != NULL);
714    malloc_string(tmp);
715    malloc_string(command);
716    malloc_string(mountdir);
717    malloc_string(mountpoint);
718    malloc_string(additional_parameters);
719
720    if (!strcmp(mpt, "/1")) {
721        strcpy(mountpoint, "/");
722        mr_msg(3, "Mommm! SME is being a dildo!");
723    } else {
724        strcpy(mountpoint, mpt);
725    }
726
727    if (!strcmp(mountpoint, "lvm")) {
728        return (0);
729    }
730    if (!strcmp(mountpoint, "image")) {
731        return (0);
732    }
733    sprintf(tmp, "Mounting device %s   ", device);
734    mr_msg(1, tmp);
735    if (writeable) {
736        strcpy(additional_parameters, "-o rw");
737    } else {
738        strcpy(additional_parameters, "-o ro");
739    }
740    if (find_home_of_exe("setfattr")) {
741        strcat(additional_parameters, ",user_xattr");
742    }
743    if (find_home_of_exe("setfacl")) {
744        strcat(additional_parameters, ",acl");
745    }
746
747    if (!strcmp(mountpoint, "swap")) {
748        sprintf(command, "swapon %s", device);
749    } else {
750        if (!strcmp(mountpoint, "/")) {
751            strcpy(mountdir, MNT_RESTORING);
752        } else {
753            sprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
754        }
755        sprintf(command, "mkdir -p %s", mountdir);
756        run_program_and_log_output(command, FALSE);
757        sprintf(command, "mount -t %s %s %s %s 2>> %s", format, device,
758                additional_parameters, mountdir, MONDO_LOGFILE);
759        mr_msg(2, "command='%s'", command);
760    }
761    res = run_program_and_log_output(command, TRUE);
762    if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
763        mr_msg(1, "Re-trying without the fancy extra parameters");
764        sprintf(command, "mount -t %s %s %s 2>> %s", format, device,
765                mountdir, MONDO_LOGFILE);
766        res = run_program_and_log_output(command, TRUE);
767    }
768    if (res) {
769        mr_msg(1, "Unable to mount device %s (type %s) at %s", device,
770                format, mountdir);
771        mr_msg(1, "command was '%s'", command);
772        if (!strcmp(mountpoint, "swap")) {
773            log_to_screen(tmp);
774        } else {
775            mr_msg(2, "Retrying w/o the '-t' switch");
776            sprintf(command, "mount %s %s 2>> %s", device, mountdir,
777                    MONDO_LOGFILE);
778            mr_msg(2, "2nd command = '%s'", command);
779            res = run_program_and_log_output(command, TRUE);
780            if (res == 0) {
781                mr_msg(1,
782                        "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
783            } else {
784                log_to_screen(tmp);
785            }
786        }
787    }
788    if (res && !strcmp(mountpoint, "swap")) {
789        mr_msg(2, "That's ok. It's just a swap partition.");
790        mr_msg(2, "Non-fatal error. Returning 0.");
791        res = 0;
792    }
793
794    mr_free(tmp);
795    mr_free(command);
796    mr_free(mountdir);
797    mr_free(mountpoint);
798    mr_free(additional_parameters);
799
800    return (res);
801}
802
803/**************************************************************************
804 *END_MOUNT_DEVICE                                                        *
805 **************************************************************************/
806
807
808
809/**
810 * Fix some miscellaneous things in the filesystem so the system will come
811 * up correctly on the first boot.
812 */
813void protect_against_braindead_sysadmins()
814{
815    run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
816                               FALSE);
817    run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
818                               FALSE);
819    if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
820        run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp",
821                                   FALSE);
822    }
823    run_program_and_log_output("mkdir -p " MNT_RESTORING
824                               "/var/run/console", FALSE);
825    run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null",
826                               FALSE);
827    run_program_and_log_output("cd " MNT_RESTORING
828                               "; 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",
829                               TRUE);
830    run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
831                               TRUE);
832    run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
833                               TRUE);
834}
835
836/**************************************************************************
837 *END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS                                 *
838 **************************************************************************/
839
840
841
842
843/**
844 * Fill out @p bkpinfo based on @p cfg_file.
845 * @param cfg_file The mondo-restore.cfg file to read into @p bkpinfo.
846 * @param bkpinfo The backup information structure to fill out with information
847 * from @p cfg_file.
848 * @return 0 for success, nonzero for failure.
849 */
850int read_cfg_file_into_bkpinfo(char *cfgf, struct s_bkpinfo *bkpinfo)
851{
852  /** add mallocs **/
853    char *value = NULL;
854    char *tmp = NULL;
855    char *envtmp1 = NULL;
856    char *envtmp2 = NULL;
857    char *command = NULL;
858    char *iso_mnt = NULL;
859    char *iso_path = NULL;
860    char *old_isodir = NULL;
861    char cfg_file[100];
862    t_bkptype media_specified_by_user;
863
864    malloc_string(command);
865    malloc_string(iso_mnt);
866    malloc_string(iso_path);
867    malloc_string(old_isodir);
868    malloc_string(value);
869    malloc_string(tmp);
870//  assert_string_is_neither_NULL_nor_zerolength(cfg_file);
871    assert(bkpinfo != NULL);
872
873    if (!cfgf) {
874        strcpy(cfg_file, g_mondo_cfg_file);
875    } else {
876        strcpy(cfg_file, cfgf);
877    }
878
879    media_specified_by_user = bkpinfo->backup_media_type;   // or 'none', if not specified
880
881    if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
882        if (!strcmp(value, "cdstream")) {
883            bkpinfo->backup_media_type = cdstream;
884        } else if (!strcmp(value, "cdr")) {
885            bkpinfo->backup_media_type = cdr;
886        } else if (!strcmp(value, "cdrw")) {
887            bkpinfo->backup_media_type = cdrw;
888        } else if (!strcmp(value, "dvd")) {
889            bkpinfo->backup_media_type = dvd;
890        } else if (!strcmp(value, "iso")) {
891/*
892      if (am_I_in_disaster_recovery_mode()
893      && !run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1)
894      && does_file_exist(MNT_CDROM"/archives/filelist.0"))
895*/
896
897// Patch by Conor Daly - 2004/07/12
898            bkpinfo->backup_media_type = iso;
899            if (am_I_in_disaster_recovery_mode()) {
900                /* Check to see if CD is already mounted before mounting it... */
901                if (!is_this_device_mounted("/dev/cdrom")) {
902                    mr_msg(2,
903                            "NB: CDROM device not mounted, mounting...");
904                    run_program_and_log_output("mount /dev/cdrom "
905                                               MNT_CDROM, 1);
906                }
907                if (does_file_exist(MNT_CDROM "/archives/filelist.0")) {
908                    bkpinfo->backup_media_type = cdr;
909                    run_program_and_log_output("umount " MNT_CDROM, 1);
910                    log_it
911                        ("Re-jigging configuration AGAIN. CD-R, not ISO.");
912                }
913            }
914            if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
915                    strcpy(bkpinfo->prefix,value);
916            } else {
917                    strcpy(bkpinfo->prefix,STD_PREFIX);
918            }
919        } else if (!strcmp(value, "nfs")) {
920            bkpinfo->backup_media_type = nfs;
921            if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
922                    strcpy(bkpinfo->prefix,value);
923            } else {
924                    strcpy(bkpinfo->prefix,STD_PREFIX);
925            }
926            if (strstr(call_program_and_get_last_line_of_output
927               ("cat /proc/cmdline"), "pxe")) {
928                /* We need to override prefix value in PXE mode as it's
929                * already done in start-nfs */
930                envtmp1 = getenv("imgname");
931                if (envtmp1 == NULL) {
932                    fatal_error("no imgname variable in environment");
933                }
934                strcpy(bkpinfo->prefix,envtmp1);
935            }
936
937        } else if (!strcmp(value, "tape")) {
938            bkpinfo->backup_media_type = tape;
939        } else if (!strcmp(value, "udev")) {
940            bkpinfo->backup_media_type = udev;
941        } else {
942            fatal_error("UNKNOWN bkp-media-type");
943        }
944    } else {
945        fatal_error("backup-media-type not specified!");
946    }
947    if (bkpinfo->disaster_recovery) {
948        if (bkpinfo->backup_media_type == cdstream) {
949            sprintf(bkpinfo->media_device, "/dev/cdrom");
950//          bkpinfo->media_size[0] = -1;
951            bkpinfo->media_size[0] = 1999 * 1024;
952            bkpinfo->media_size[1] = 650;   /* good guess */
953        } else if (bkpinfo->backup_media_type == tape
954                   || bkpinfo->backup_media_type == udev) {
955            if (read_cfg_var(cfg_file, "media-dev", value)) {
956                fatal_error("Cannot get tape device name from cfg file");
957            }
958            strcpy(bkpinfo->media_device, value);
959            read_cfg_var(cfg_file, "media-size", value);
960            bkpinfo->media_size[1] = atol(value);
961            sprintf(tmp, "Backup medium is TAPE --- dev=%s",
962                    bkpinfo->media_device);
963            mr_msg(2, tmp);
964        } else {
965            strcpy(bkpinfo->media_device, "/dev/cdrom");    /* we don't really need this var */
966            bkpinfo->media_size[0] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
967            bkpinfo->media_size[1] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
968            mr_msg(2, "Backup medium is CD-R[W]");
969        }
970    } else {
971        mr_msg(2,
972                "Not in Disaster Recovery Mode. No need to derive device name from config file.");
973    }
974
975    read_cfg_var(cfg_file, "use-star", value);
976    if (strstr(value, "yes")) {
977        bkpinfo->use_star = TRUE;
978        mr_msg(1, "Goody! ... bkpinfo->use_star is now true.");
979    }
980
981    read_cfg_var(cfg_file, "acl", value);
982    if (strstr(value, "yes")) {
983        mr_asprintf(&g_getfacl,"setfacl");
984        mr_msg(1, "We will restore ACLs");
985        if (! find_home_of_exe("setfacl")) {
986            mr_msg(1, "Unable to restore ACLs as no setfacl found");
987        }
988    }
989    read_cfg_var(cfg_file, "xattr", value);
990    if (strstr(value, "yes")) {
991        mr_asprintf(&g_getfattr,"setfattr");
992        mr_msg(1, "We will restore XATTRs");
993        if (! find_home_of_exe("setfattr")) {
994            mr_msg(1, "Unable to restore XATTRs as no setfattr found");
995        }
996    }
997
998    if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
999        bkpinfo->internal_tape_block_size = atol(value);
1000        mr_msg(1, "Internal tape block size has been custom-set to %ld",
1001                bkpinfo->internal_tape_block_size);
1002    } else {
1003        bkpinfo->internal_tape_block_size =
1004            DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
1005        mr_msg(1, "Internal tape block size = default (%ld)",
1006                DEFAULT_INTERNAL_TAPE_BLOCK_SIZE);
1007    }
1008
1009    read_cfg_var(cfg_file, "use-lzo", value);
1010    if (strstr(value, "yes")) {
1011        bkpinfo->use_lzo = TRUE;
1012        bkpinfo->use_gzip = FALSE;
1013        strcpy(bkpinfo->zip_exe, "lzop");
1014        strcpy(bkpinfo->zip_suffix, "lzo");
1015    } else {
1016        read_cfg_var(cfg_file, "use-gzip", value);
1017        if (strstr(value, "yes")) {
1018            bkpinfo->use_lzo = FALSE;
1019            bkpinfo->use_gzip = TRUE;
1020            strcpy(bkpinfo->zip_exe, "gzip");
1021            strcpy(bkpinfo->zip_suffix, "gz");
1022        } else {
1023            read_cfg_var(cfg_file, "use-comp", value);
1024            if (strstr(value, "yes")) {
1025                bkpinfo->use_lzo = FALSE;
1026                bkpinfo->use_gzip = FALSE;
1027                strcpy(bkpinfo->zip_exe, "bzip2");
1028                strcpy(bkpinfo->zip_suffix, "bz2");
1029            } else {
1030                bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
1031            }
1032        }
1033    }
1034
1035    value[0] = '\0';
1036    read_cfg_var(cfg_file, "differential", value);
1037    if (!strcmp(value, "yes") || !strcmp(value, "1")) {
1038        bkpinfo->differential = TRUE;
1039    }
1040    mr_msg(2, "differential var = '%s'", value);
1041    if (bkpinfo->differential) {
1042        mr_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
1043    } else {
1044        mr_msg(2, "This is a regular (full) backup");
1045    }
1046
1047    read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
1048    if (tmp[0]
1049        ||
1050        strstr(call_program_and_get_last_line_of_output
1051               ("cat /proc/cmdline"), "donteject")) {
1052        bkpinfo->please_dont_eject = TRUE;
1053        mr_msg(2, "Ok, I shan't eject when restoring! Groovy.");
1054    }
1055
1056    if (bkpinfo->backup_media_type == nfs) {
1057        if (!cfgf) {
1058            mr_msg(2, "nfs_mount remains %s", bkpinfo->nfs_mount);
1059            mr_msg(2, "nfs_remote_dir remains %s",
1060                    bkpinfo->nfs_remote_dir);
1061            mr_msg(2,
1062                    "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
1063        } else {
1064            read_cfg_var(g_mondo_cfg_file, "nfs-server-mount",
1065                         bkpinfo->nfs_mount);
1066            read_cfg_var(g_mondo_cfg_file, "nfs-server-path",
1067                         bkpinfo->nfs_remote_dir);
1068            mr_msg(2, "nfs_mount is %s", bkpinfo->nfs_mount);
1069            mr_msg(2, "nfs_remote_dir is %s", bkpinfo->nfs_remote_dir);
1070        }
1071        if (strstr(call_program_and_get_last_line_of_output
1072           ("cat /proc/cmdline"), "pxe")) {
1073            /* We need to override values in PXE mode as it's
1074            * already done in start-nfs */
1075            envtmp1 = getenv("nfsmount");
1076            if (envtmp1 == NULL) {
1077                fatal_error("no nfsmount variable in environment");
1078            }
1079            envtmp2 = getenv("dirimg");
1080            if (envtmp2 == NULL) {
1081                fatal_error("no dirimg variable in environment");
1082            }
1083            strcpy(bkpinfo->nfs_mount,envtmp1);
1084            strcpy(bkpinfo->nfs_remote_dir,envtmp2);
1085        }
1086    } else if (bkpinfo->backup_media_type == iso) {
1087        /* Patch by Conor Daly 23-june-2004
1088         * to correctly mount iso-dev and set a sensible
1089         * isodir in disaster recovery mode
1090         */
1091        strcpy(old_isodir, bkpinfo->isodir);
1092        read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
1093        read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
1094        sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1095        if (!bkpinfo->isodir[0]) {
1096            strcpy(bkpinfo->isodir, old_isodir);
1097        }
1098        if (!bkpinfo->disaster_recovery) {
1099            if (strcmp(old_isodir, bkpinfo->isodir)) {
1100                log_it
1101                    ("user nominated isodir differs from archive, keeping user's choice: %s %s\n",
1102                     old_isodir, bkpinfo->isodir);
1103                strcpy(bkpinfo->isodir, old_isodir);
1104            }
1105        }
1106        read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
1107        mr_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir,
1108                g_isodir_device);
1109        if (bkpinfo->disaster_recovery) {
1110            if (is_this_device_mounted(g_isodir_device)) {
1111                mr_msg(2, "NB: isodir is already mounted");
1112                /* Find out where it's mounted */
1113                sprintf(command,
1114                        "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3",
1115                        g_isodir_device);
1116                log_it("command = %s", command);
1117                log_it("res of it = %s",
1118                       call_program_and_get_last_line_of_output(command));
1119                sprintf(iso_mnt, "%s",
1120                        call_program_and_get_last_line_of_output(command));
1121            } else {
1122                sprintf(iso_mnt, "/tmp/isodir");
1123                sprintf(tmp, "mkdir -p %s", iso_mnt);
1124                run_program_and_log_output(tmp, 5);
1125                sprintf(tmp, "mount %s %s", g_isodir_device, iso_mnt);
1126                if (run_program_and_log_output(tmp, 3)) {
1127                    mr_msg(1,
1128                            "Unable to mount isodir. Perhaps this is really a CD backup?");
1129                    bkpinfo->backup_media_type = cdr;
1130                    strcpy(bkpinfo->media_device, "/dev/cdrom");    /* superfluous */
1131                    bkpinfo->isodir[0] = iso_mnt[0] = iso_path[0] = '\0';
1132                    if (mount_cdrom(bkpinfo)) {
1133                        fatal_error
1134                            ("Unable to mount isodir. Failed to mount CD-ROM as well.");
1135                    } else {
1136                        mr_msg(1,
1137                                "You backed up to disk, then burned some CDs.");
1138                    }
1139                }
1140            }
1141            /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1142            if (bkpinfo->backup_media_type == iso) {
1143                sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1144            }
1145        }
1146    }
1147
1148    if (media_specified_by_user != none) {
1149        if (g_restoring_live_from_cd) {
1150            if (bkpinfo->backup_media_type != media_specified_by_user) {
1151                mr_msg(2,
1152                        "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1153                interactively_obtain_media_parameters_from_user(bkpinfo,
1154                                                                FALSE);
1155                media_specified_by_user = bkpinfo->backup_media_type;
1156                get_cfg_file_from_archive(bkpinfo);
1157/*
1158              if (media_specified_by_user != cdr && media_specified_by_user == cdrw)
1159                { g_restoring_live_from_cd = FALSE; }
1160*/
1161            }
1162        }
1163        bkpinfo->backup_media_type = media_specified_by_user;
1164    }
1165    g_backup_media_type = bkpinfo->backup_media_type;
1166    mr_free(value);
1167    mr_free(tmp);
1168    mr_free(command);
1169    mr_free(iso_mnt);
1170    mr_free(iso_path);
1171    mr_free(old_isodir);
1172    return (0);
1173
1174}
1175
1176/**************************************************************************
1177 *END_READ_CFG_FILE_INTO_BKPINFO                                          *
1178 **************************************************************************/
1179
1180
1181
1182
1183/**
1184 * Allow the user to edit the filelist and biggielist.
1185 * The filelist is unlinked after it is read.
1186 * @param bkpinfo The backup information structure. Fields used:
1187 * - @c bkpinfo->backup_media_type
1188 * - @c bkpinfo->isodir
1189 * - @c bkpinfo->media_device
1190 * - @c bkpinfo->tmpdir
1191 * @return The filelist structure containing the information read from disk.
1192 */
1193struct
1194s_node *process_filelist_and_biggielist(struct s_bkpinfo *bkpinfo)
1195{
1196    struct s_node *filelist;
1197
1198  /** add mallocs**/
1199    char *command;
1200    char *tmp;
1201    int res = 0;
1202    pid_t pid;
1203
1204    assert(bkpinfo != NULL);
1205    malloc_string(command);
1206    malloc_string(tmp);
1207
1208    if (does_file_exist(g_filelist_full)
1209        && does_file_exist(g_biggielist_txt)) {
1210        mr_msg(1, "%s exists", g_filelist_full);
1211        mr_msg(1, "%s exists", g_biggielist_txt);
1212        mr_msg(2,
1213                "Filelist and biggielist already recovered from media. Yay!");
1214    } else {
1215        getcwd(tmp, MAX_STR_LEN);
1216        chdir(bkpinfo->tmpdir);
1217        mr_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1218        log_to_screen("Extracting filelist and biggielist from media...");
1219        unlink("/tmp/filelist.full");
1220        unlink("/" FILELIST_FULL_STUB);
1221        unlink("/tmp/i-want-my-lvm");
1222        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1223            sprintf(command,
1224                    "tar -zxf %s %s %s %s %s %s",
1225                    bkpinfo->media_device,
1226                    MOUNTLIST_FNAME_STUB,
1227                    BIGGIELIST_TXT_STUB,
1228                    FILELIST_FULL_STUB,
1229                    "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1230            mr_msg(1, "tarcommand = %s", command);
1231            run_program_and_log_output(command, 1);
1232        } else {
1233            mr_msg(2,
1234                    "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1235                    bkpinfo->isodir);
1236            insist_on_this_cd_number(bkpinfo, 1);
1237            mr_msg(2, "Back from iotcn");
1238            run_program_and_log_output("mount", 1);
1239            sprintf(command,
1240                    "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1241                    MNT_CDROM,
1242                    MOUNTLIST_FNAME_STUB,
1243                    BIGGIELIST_TXT_STUB,
1244                    FILELIST_FULL_STUB,
1245                    "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1246
1247            mr_msg(1, "tarcommand = %s", command);
1248            run_program_and_log_output(command, 1);
1249//    popup_and_OK("Press ENTER to continue");
1250            if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1251                fatal_error
1252                    ("all.tar.gz did not include tmp/biggielist.txt");
1253            }
1254            if (!does_file_exist(FILELIST_FULL_STUB)) {
1255                fatal_error
1256                    ("all.tar.gz did not include tmp/filelist.full.gz");
1257            }
1258        }
1259        sprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1260                g_mondo_cfg_file);
1261        run_program_and_log_output(command, FALSE);
1262
1263        sprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1264                BIGGIELIST_TXT_STUB, g_biggielist_txt);
1265        mr_msg(1, "command = %s", command);
1266        paranoid_system(command);
1267        sprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1268                FILELIST_FULL_STUB, g_filelist_full);
1269        mr_msg(1, "command = %s", command);
1270        paranoid_system(command);
1271    }
1272
1273    if (am_I_in_disaster_recovery_mode()
1274        &&
1275        ask_me_yes_or_no("Do you want to retrieve the mountlist as well?"))
1276    {
1277//      sprintf(command, "cp -f tmp/mountlist.txt /tmp");
1278        sprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1279                bkpinfo->tmpdir);
1280        paranoid_system(command);
1281    }
1282
1283    chdir(tmp);
1284
1285    if (!does_file_exist(g_biggielist_txt)) {
1286        mr_msg(1, "Warning - %s not found", g_biggielist_txt);
1287    }
1288    if (!does_file_exist(g_filelist_full)) {
1289        mr_msg(1, "Warning - %s does not exist", g_filelist_full);
1290    }
1291//  popup_and_OK("Wonderful.");
1292
1293    mr_msg(2, "Forking");
1294    pid = fork();
1295    switch (pid) {
1296    case -1:
1297        fatal_error("Forking error");
1298        break;
1299
1300    case 0:
1301        log_to_screen("Pre-processing filelist");
1302        if (!does_file_exist(g_biggielist_txt)) {
1303            sprintf(command, "> %s", g_biggielist_txt);
1304            paranoid_system(command);
1305        }
1306        sprintf(command, "grep -E '^/dev/.*' %s > %s",
1307                g_biggielist_txt, g_filelist_imagedevs);
1308        paranoid_system(command);
1309        exit(0);
1310        break;
1311
1312    default:
1313        open_evalcall_form("Pre-processing filelist");
1314        while (!waitpid(pid, (int *) 0, WNOHANG)) {
1315            usleep(100000);
1316            update_evalcall_form(0);
1317        }
1318    }
1319    close_evalcall_form();
1320
1321    mr_msg(3, "loading filelist");
1322    filelist = load_filelist(g_filelist_full);
1323    mr_msg(3, "deleting original filelist");
1324    unlink(g_filelist_full);
1325    if (g_text_mode) {
1326        printf("Restore which directory? --> ");
1327        fgets(tmp, sizeof(tmp), stdin);
1328        toggle_path_selection(filelist, tmp, TRUE);
1329        if (strlen(tmp) == 0) {
1330            res = 1;
1331        } else {
1332            res = 0;
1333        }
1334    } else {
1335        res = edit_filelist(filelist);
1336    }
1337    if (res) {
1338        mr_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1339        free_filelist(filelist);
1340        return (NULL);
1341    }
1342    ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1343    close_evalcall_form();
1344
1345    // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1346    // file. The filelist.full file already contains the filename of EVERY
1347    // file backed up - regular and biggie files.
1348
1349    // However, we do want to make sure the imagedevs selected by the user
1350    // are flagged for restoring.
1351    if (length_of_file(g_imagedevs_restthese) > 2) {
1352        add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1353                                      TRUE);
1354    }
1355
1356    mr_free(command);
1357    mr_free(tmp);
1358    return (filelist);
1359}
1360
1361/**************************************************************************
1362 *END_ PROCESS_FILELIST_AND_BIGGIELIST                                    *
1363 **************************************************************************/
1364
1365
1366
1367
1368/**
1369 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1370 * The backup filename is the filename of the original with ".pristine" added.
1371 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1372 * @param filename The filename (absolute path) within @p path_root.
1373 * @return 0 for success, nonzero for failure.
1374 */
1375int backup_crucial_file(char *path_root, char *filename)
1376{
1377    char *tmp;
1378    char *command;
1379    int res;
1380
1381    malloc_string(tmp);
1382    malloc_string(command);
1383    assert(path_root != NULL);
1384    assert_string_is_neither_NULL_nor_zerolength(filename);
1385
1386    sprintf(tmp, "%s/%s", path_root, filename);
1387    sprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1388
1389    res = run_program_and_log_output(command, 5);
1390    mr_free(tmp);
1391    mr_free(command);
1392    return (res);
1393}
1394
1395
1396/**
1397 * Install the user's boot loader in the MBR.
1398 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1399 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1400 * @return 0 for success, nonzero for failure.
1401 */
1402int run_boot_loader(bool offer_to_hack_scripts)
1403{
1404    int res;
1405    int retval = 0;
1406
1407  /** malloc *******/
1408    char *device;
1409    char *tmp;
1410    char *name;
1411
1412    malloc_string(device);
1413    malloc_string(tmp);
1414    malloc_string(name);
1415    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1416    backup_crucial_file(MNT_RESTORING, "/etc/grub.conf");
1417    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1418    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1419    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1420    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1421    sprintf(tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1422    mr_msg(2, tmp);
1423    system("sync");
1424    if (!strcmp(name, "LILO")) {
1425        res = run_lilo(offer_to_hack_scripts);
1426    } else if (!strcmp(name, "ELILO")) {
1427        res = run_elilo(offer_to_hack_scripts);
1428    } else if (!strcmp(name, "GRUB")) {
1429//      if ( does_file_exist(DO_MBR_PLEASE) || (offer_to_hack_scripts && ask_me_yes_or_no("Because of bugs in GRUB, you're much better off running mondorestore --mbr after this program terminates. Are you sure you want to install GRUB right now?")))
1430//        {
1431        res = run_grub(offer_to_hack_scripts, device);
1432//    unlink(DO_MBR_PLEASE);
1433//  }
1434//      else
1435//        {
1436//    mr_msg(1, "Not running run_grub(). Was a bad idea anyway.");
1437//    res = 1;
1438//  }
1439    } else if (!strcmp(name, "RAW")) {
1440        res = run_raw_mbr(offer_to_hack_scripts, device);
1441    }
1442#ifdef __FreeBSD__
1443    else if (!strcmp(name, "BOOT0")) {
1444        sprintf(tmp, "boot0cfg -B %s", device);
1445        res = run_program_and_log_output(tmp, FALSE);
1446    } else {
1447        sprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1448        if (!system(tmp)) {
1449            sprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1450            res = run_program_and_log_output(tmp, 3);
1451        } else {
1452            mr_msg(1,
1453                    "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1454        }
1455    }
1456#else
1457    else {
1458        log_to_screen
1459            ("Unable to determine type of boot loader. Defaulting to LILO.");
1460        res = run_lilo(offer_to_hack_scripts);
1461    }
1462#endif
1463    retval += res;
1464    if (res) {
1465        log_to_screen("Your boot loader returned an error");
1466    } else {
1467        log_to_screen("Your boot loader ran OK");
1468    }
1469    mr_free(device);
1470    mr_free(tmp);
1471    mr_free(name);
1472    return (retval);
1473}
1474
1475/**************************************************************************
1476 *END_ RUN_BOOT_LOADER                                                    *
1477 **************************************************************************/
1478
1479
1480
1481/**
1482 * Attempt to find the user's editor.
1483 * @return The editor found ("vi" if none could be found).
1484 * @note The returned string points to static storage that will be overwritten with each call.
1485 */
1486char *find_my_editor(void)
1487{
1488    static char output[MAX_STR_LEN];
1489    if (find_home_of_exe("pico")) {
1490        strcpy(output, "pico");
1491    } else if (find_home_of_exe("nano")) {
1492        strcpy(output, "nano");
1493    } else if (find_home_of_exe("e3em")) {
1494        strcpy(output, "e3em");
1495    } else if (find_home_of_exe("e3vi")) {
1496        strcpy(output, "e3vi");
1497    } else {
1498        strcpy(output, "vi");
1499    }
1500    if (!find_home_of_exe(output)) {
1501        mr_msg(2, " (find_my_editor) --- warning - %s not found", output);
1502    }
1503    return (output);
1504}
1505
1506
1507/**
1508 * Install GRUB on @p bd.
1509 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1510 * @param bd The boot device where GRUB is installed.
1511 * @return 0 for success, nonzero for failure.
1512 */
1513int run_grub(bool offer_to_run_stabgrub, char *bd)
1514{
1515  /** malloc **/
1516    char *command;
1517    char *boot_device;
1518    char *rootdev;
1519    char *rootdrive;
1520    char *conffile;
1521    char *tmp;
1522    char *editor;
1523
1524    int res;
1525    int done;
1526
1527    malloc_string(command);
1528    malloc_string(boot_device);
1529    malloc_string(tmp);
1530    malloc_string(editor);
1531    malloc_string(rootdev);
1532    malloc_string(rootdrive);
1533    malloc_string(conffile);
1534    assert_string_is_neither_NULL_nor_zerolength(bd);
1535    strcpy(editor, "vi");       // find_my_editor() );
1536    strcpy(boot_device, bd);
1537
1538    if (!run_program_and_log_output("which grub-MR", FALSE)) {
1539        mr_msg(1, "Yay! grub-MR found...");
1540        sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device);
1541        mr_msg(1, "command = %s", command);
1542    } else {
1543        sprintf(command, "chroot " MNT_RESTORING " grub-install %s",
1544                boot_device);
1545        mr_msg(1, "WARNING - grub-MR not found; using grub-install");
1546    }
1547    if (offer_to_run_stabgrub
1548        && ask_me_yes_or_no("Did you change the mountlist?"))
1549        /* interactive mode */
1550    {
1551        mvaddstr_and_log_it(g_currentY,
1552                            0,
1553                            "Modifying fstab and grub.conf, and running GRUB...                             ");
1554        for (done = FALSE; !done;) {
1555            popup_and_get_string("Boot device",
1556                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1557                                 boot_device, MAX_STR_LEN / 4);
1558            sprintf(command, "stabgrub-me %s", boot_device);
1559            res = run_program_and_log_output(command, 1);
1560            if (res) {
1561                popup_and_OK
1562                    ("GRUB installation failed. Please install manually using 'grub-install' or similar command. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1563                newtSuspend();
1564                system("chroot " MNT_RESTORING);
1565                newtResume();
1566                popup_and_OK("Thank you.");
1567            } else {
1568                done = TRUE;
1569            }
1570            popup_and_OK("You will now edit fstab and grub.conf");
1571            if (!g_text_mode) {
1572                newtSuspend();
1573            }
1574            sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1575            paranoid_system(tmp);
1576            sprintf(tmp, "%s " MNT_RESTORING "/etc/grub.conf", editor);
1577            paranoid_system(tmp);
1578            if (!g_text_mode) {
1579                newtResume();
1580            }
1581        }
1582    } else
1583        /* nuke mode */
1584    {
1585        mvaddstr_and_log_it(g_currentY,
1586                            0,
1587                            "Running GRUB...                                                 ");
1588        iamhere(command);
1589        res = run_program_and_log_output(command, 1);
1590        if (res) {
1591            popup_and_OK
1592                ("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.");
1593            newtSuspend();
1594            system("chroot " MNT_RESTORING);
1595            newtResume();
1596            popup_and_OK("Thank you.");
1597        }
1598    }
1599    if (res) {
1600        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1601        log_to_screen
1602            ("GRUB ran w/error(s). See /tmp/mondo-restore.log for more info.");
1603        mr_msg(1, "Type:-");
1604        mr_msg(1, "    mount-me");
1605        mr_msg(1, "    chroot " MNT_RESTORING);
1606        mr_msg(1, "    mount /boot");
1607        mr_msg(1, "    grub-install '(hd0)'");
1608        mr_msg(1, "    exit");
1609        mr_msg(1, "    unmount-me");
1610        mr_msg(1,
1611                "If you're really stuck, please e-mail the mailing list.");
1612    } else {
1613        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1614    }
1615    mr_free(rootdev);
1616    mr_free(rootdrive);
1617    mr_free(conffile);
1618    mr_free(command);
1619    mr_free(boot_device);
1620    mr_free(tmp);
1621    mr_free(editor);
1622
1623    return (res);
1624}
1625
1626/**************************************************************************
1627 *END_RUN_GRUB                                                            *
1628 **************************************************************************/
1629
1630
1631/**
1632 * Install ELILO on the user's boot drive (determined by elilo.conf).
1633 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1634 * @return 0 for success, nonzero for failure.
1635 */
1636int run_elilo(bool offer_to_run_stabelilo)
1637{
1638  /** malloc **/
1639    char *command;
1640    char *tmp;
1641    char *editor;
1642
1643    int res;
1644    int done;
1645
1646    malloc_string(command);
1647    malloc_string(tmp);
1648    malloc_string(editor);
1649    strcpy(editor, find_my_editor());
1650    if (offer_to_run_stabelilo
1651        && ask_me_yes_or_no("Did you change the mountlist?"))
1652
1653        /* interactive mode */
1654    {
1655        mvaddstr_and_log_it(g_currentY,
1656                            0,
1657                            "Modifying fstab and elilo.conf...                             ");
1658        sprintf(command, "stabelilo-me");
1659        res = run_program_and_log_output(command, 3);
1660        if (res) {
1661            popup_and_OK
1662                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1663            for (done = FALSE; !done;) {
1664                if (!g_text_mode) {
1665                    newtSuspend();
1666                }
1667                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1668                paranoid_system(tmp);
1669                sprintf(tmp, "%s " MNT_RESTORING "/etc/elilo.conf",
1670                        editor);
1671                paranoid_system(tmp);
1672                if (!g_text_mode) {
1673                    newtResume();
1674                }
1675//              newtCls();
1676                if (ask_me_yes_or_no("Edit them again?")) {
1677                    continue;
1678                }
1679                done = TRUE;
1680            }
1681        } else {
1682            log_to_screen("elilo.conf and fstab were modified OK");
1683        }
1684    } else
1685        /* nuke mode */
1686    {
1687        res = TRUE;
1688    }
1689    mr_free(command);
1690    mr_free(tmp);
1691    mr_free(editor);
1692    return (res);
1693}
1694
1695/**************************************************************************
1696 *END_RUN_ELILO                                                            *
1697 **************************************************************************/
1698
1699
1700/**
1701 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1702 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1703 * @return 0 for success, nonzero for failure.
1704 */
1705int run_lilo(bool offer_to_run_stablilo)
1706{
1707  /** malloc **/
1708    char *command;
1709    char *tmp;
1710    char *editor;
1711
1712    int res;
1713    int done;
1714    bool run_lilo_M = FALSE;
1715    malloc_string(command);
1716    malloc_string(tmp);
1717    malloc_string(editor);
1718
1719    if (!run_program_and_log_output
1720        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1721        run_lilo_M = TRUE;
1722    }
1723
1724    strcpy(editor, find_my_editor());
1725    if (offer_to_run_stablilo
1726        && ask_me_yes_or_no("Did you change the mountlist?"))
1727
1728        /* interactive mode */
1729    {
1730        mvaddstr_and_log_it(g_currentY,
1731                            0,
1732                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1733        sprintf(command, "stablilo-me");
1734        res = run_program_and_log_output(command, 3);
1735        if (res) {
1736            popup_and_OK
1737                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1738            for (done = FALSE; !done;) {
1739                if (!g_text_mode) {
1740                    newtSuspend();
1741                }
1742                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1743                paranoid_system(tmp);
1744                sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1745                paranoid_system(tmp);
1746                if (!g_text_mode) {
1747                    newtResume();
1748                }
1749//              newtCls();
1750                if (ask_me_yes_or_no("Edit them again?")) {
1751                    continue;
1752                }
1753                res =
1754                    run_program_and_log_output("chroot " MNT_RESTORING
1755                                               " lilo -L", 3);
1756                if (res) {
1757                    res =
1758                        run_program_and_log_output("chroot " MNT_RESTORING
1759                                                   " lilo", 3);
1760                }
1761                if (res) {
1762                    done =
1763                        ask_me_yes_or_no
1764                        ("LILO failed. Re-edit system files?");
1765                } else {
1766                    done = TRUE;
1767                }
1768            }
1769        } else {
1770            log_to_screen("lilo.conf and fstab were modified OK");
1771        }
1772    } else
1773        /* nuke mode */
1774    {
1775        mvaddstr_and_log_it(g_currentY,
1776                            0,
1777                            "Running LILO...                                                 ");
1778        res =
1779            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1780                                       3);
1781        if (res) {
1782            res =
1783                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1784                                           3);
1785        }
1786        if (res) {
1787            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1788            log_to_screen
1789                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1790        } else {
1791            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1792        }
1793    }
1794    if (run_lilo_M) {
1795        run_program_and_log_output("chroot " MNT_RESTORING
1796                                   " lilo -M /dev/hda", 3);
1797        run_program_and_log_output("chroot " MNT_RESTORING
1798                                   " lilo -M /dev/sda", 3);
1799    }
1800    mr_free(command);
1801    mr_free(tmp);
1802    mr_free(editor);
1803    return (res);
1804}
1805
1806/**************************************************************************
1807 *END_RUN_LILO                                                            *
1808 **************************************************************************/
1809
1810
1811/**
1812 * Install a raw MBR onto @p bd.
1813 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1814 * @param bd The device to copy the stored MBR to.
1815 * @return 0 for success, nonzero for failure.
1816 */
1817int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1818{
1819  /** malloc **/
1820    char *command;
1821    char *boot_device;
1822    char *tmp;
1823    char *editor;
1824    int res;
1825    int done;
1826
1827    malloc_string(command);
1828    malloc_string(boot_device);
1829    malloc_string(tmp);
1830    malloc_string(editor);
1831    assert_string_is_neither_NULL_nor_zerolength(bd);
1832
1833    strcpy(editor, find_my_editor());
1834    strcpy(boot_device, bd);
1835    sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1836    mr_msg(2, "run_raw_mbr() --- command='%s'", command);
1837
1838    if (offer_to_hack_scripts
1839        && ask_me_yes_or_no("Did you change the mountlist?"))
1840        /* interactive mode */
1841    {
1842        mvaddstr_and_log_it(g_currentY, 0,
1843                            "Modifying fstab and restoring MBR...                           ");
1844        for (done = FALSE; !done;) {
1845            if (!run_program_and_log_output("which vi", FALSE)) {
1846                popup_and_OK("You will now edit fstab");
1847                if (!g_text_mode) {
1848                    newtSuspend();
1849                }
1850                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1851                paranoid_system(tmp);
1852                if (!g_text_mode) {
1853                    newtResume();
1854                }
1855//              newtCls();
1856            }
1857            popup_and_get_string("Boot device",
1858                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1859                                 boot_device, MAX_STR_LEN / 4);
1860            sprintf(command, "stabraw-me %s", boot_device);
1861            res = run_program_and_log_output(command, 3);
1862            if (res) {
1863                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1864            } else {
1865                done = TRUE;
1866            }
1867        }
1868    } else
1869        /* nuke mode */
1870    {
1871        mvaddstr_and_log_it(g_currentY, 0,
1872                            "Restoring MBR...                                               ");
1873        res = run_program_and_log_output(command, 3);
1874    }
1875    if (res) {
1876        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1877        log_to_screen
1878            ("MBR+fstab processed w/error(s). See /tmp/mondo-restore.log for more info.");
1879    } else {
1880        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1881    }
1882    mr_free(command);
1883    mr_free(boot_device);
1884    mr_free(tmp);
1885    mr_free(editor);
1886    return (res);
1887}
1888
1889/**************************************************************************
1890 *END_RUN_RAW_MBR                                                         *
1891 **************************************************************************/
1892
1893
1894
1895
1896
1897/**
1898 * Turn signal trapping on or off.
1899 * @param on If TRUE, then do full cleanup when we receive a signal; if FALSE, then
1900 * print a message and exit immediately.
1901 */
1902void set_signals(int on)
1903{
1904    int signals[] =
1905        { SIGKILL, SIGPIPE, SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT,
1906SIGSTOP, 0 };
1907    int i;
1908    for (i = 0; signals[i]; i++) {
1909        if (on) {
1910            signal(signals[i], terminate_daemon);
1911        } else {
1912            signal(signals[i], termination_in_progress);
1913        }
1914    }
1915}
1916
1917/**************************************************************************
1918 *END_SET_SIGNALS                                                         *
1919 **************************************************************************/
1920
1921
1922/**
1923 * malloc() and set sensible defaults for the mondorestore filename variables.
1924 * @param bkpinfo The backup information structure. Fields used:
1925 * - @c bkpinfo->tmpdir
1926 * - @c bkpinfo->disaster_recovery
1927 */
1928void setup_MR_global_filenames(struct s_bkpinfo *bkpinfo)
1929{
1930    char *temppath;
1931
1932    assert(bkpinfo != NULL);
1933
1934    malloc_string(g_biggielist_txt);
1935    malloc_string(g_filelist_full);
1936    malloc_string(g_filelist_imagedevs);
1937    malloc_string(g_imagedevs_restthese);
1938    malloc_string(g_mondo_cfg_file);
1939    malloc_string(g_mountlist_fname);
1940    malloc_string(g_mondo_home);
1941    malloc_string(g_tmpfs_mountpt);
1942    malloc_string(g_isodir_device);
1943    malloc_string(g_isodir_format);
1944
1945    temppath = bkpinfo->tmpdir;
1946
1947    sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1948    sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1949    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1950//  sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1951    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1952            temppath);
1953    if (bkpinfo->disaster_recovery) {
1954        sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1955        sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1956    } else {
1957        sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1958        sprintf(g_mountlist_fname, "%s/%s", temppath,
1959                MOUNTLIST_FNAME_STUB);
1960    }
1961}
1962
1963/**************************************************************************
1964 *END_SET_GLOBAL_FILENAME                                                 *
1965 **************************************************************************/
1966
1967
1968/**
1969 * Copy @p input_file (containing the result of a compare) to @p output_file,
1970 * deleting spurious "changes" along the way.
1971 * @param output_file The output file to write with spurious changes removed.
1972 * @param input_file The input file, a list of changed files created by a compare.
1973 */
1974void streamline_changes_file(char *output_file, char *input_file)
1975{
1976    FILE *fin;
1977    FILE *fout;
1978  /** malloc **/
1979    char *incoming;
1980
1981    assert_string_is_neither_NULL_nor_zerolength(output_file);
1982    assert_string_is_neither_NULL_nor_zerolength(input_file);
1983    malloc_string(incoming);
1984
1985    if (!(fin = fopen(input_file, "r"))) {
1986        log_OS_error(input_file);
1987        return;
1988    }
1989    if (!(fout = fopen(output_file, "w"))) {
1990        fatal_error("cannot open output_file");
1991    }
1992    for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1993         fgets(incoming, MAX_STR_LEN - 1, fin)) {
1994        if (strncmp(incoming, "etc/adjtime", 11)
1995            && strncmp(incoming, "etc/mtab", 8)
1996            && strncmp(incoming, "tmp/", 4)
1997            && strncmp(incoming, "boot/map", 8)
1998            && !strstr(incoming, "incheckentry")
1999            && strncmp(incoming, "etc/mail/statistics", 19)
2000            && strncmp(incoming, "var/", 4))
2001            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
2002    }
2003    paranoid_fclose(fout);
2004    paranoid_fclose(fin);
2005    mr_free(incoming);
2006}
2007
2008/**************************************************************************
2009 *END_STREAMLINE_CHANGES_FILE                                             *
2010 **************************************************************************/
2011
2012
2013/**
2014 * Exit due to a signal (normal cleanup).
2015 * @param sig The signal we're exiting due to.
2016 */
2017void terminate_daemon(int sig)
2018{
2019    log_to_screen
2020        ("Mondorestore is terminating in response to a signal from the OS");
2021    free_MR_global_filenames();
2022    finish(254);
2023}
2024
2025/**************************************************************************
2026 *END_TERMINATE_DAEMON                                                    *
2027 **************************************************************************/
2028
2029
2030/**
2031 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
2032 */
2033void twenty_seconds_til_yikes()
2034{
2035    int i;
2036    /* MALLOC * */
2037    char *tmp;
2038
2039    malloc_string(tmp);
2040    if (does_file_exist("/tmp/NOPAUSE")) {
2041        return;
2042    }
2043    open_progress_form("CAUTION",
2044                       "Be advised: I am about to ERASE your hard disk(s)!",
2045                       "You may press Ctrl+Alt+Del to abort safely.",
2046                       "", 20);
2047    for (i = 0; i < 20; i++) {
2048        g_current_progress = i;
2049        sprintf(tmp, "You have %d seconds left to abort.", 20 - i);
2050        update_progress_form(tmp);
2051        sleep(1);
2052    }
2053    close_progress_form();
2054    mr_free(tmp);
2055}
2056
2057/**************************************************************************
2058 *END_TWENTY_SECONDS_TIL_YIKES                                            *
2059 **************************************************************************/
2060
2061
2062
2063
2064
2065/**
2066 * Exit due to a signal (no cleanup).
2067 * @param sig The signal we're exiting due to.
2068 */
2069void termination_in_progress(int sig)
2070{
2071    mr_msg(1, "Termination in progress");
2072    usleep(1000);
2073    pthread_exit(0);
2074}
2075
2076/**************************************************************************
2077 *END_TERMINATION_IN_PROGRESS                                             *
2078 **************************************************************************/
2079
2080
2081
2082/**
2083 * Unmount all devices in @p p_external_copy_of_mountlist.
2084 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
2085 * @return 0 for success, nonzero for failure.
2086 */
2087int unmount_all_devices(struct mountlist_itself
2088                        *p_external_copy_of_mountlist)
2089{
2090    struct mountlist_itself *mountlist;
2091    int retval = 0, lino, res = 0, i;
2092    char *command;
2093    char *tmp;
2094
2095    malloc_string(command);
2096    malloc_string(tmp);
2097    assert(p_external_copy_of_mountlist != NULL);
2098
2099    mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
2100    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
2101           sizeof(struct mountlist_itself));
2102    sort_mountlist_by_mountpoint(mountlist, 0);
2103
2104    run_program_and_log_output("df -m", 3);
2105    mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices      ");
2106    open_progress_form("Unmounting devices",
2107                       "Unmounting all devices that were mounted,",
2108                       "in preparation for the post-restoration reboot.",
2109                       "", mountlist->entries);
2110    chdir("/");
2111    for (i = 0;
2112         i < 10
2113         &&
2114         run_program_and_log_output
2115         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
2116         i++) {
2117        sleep(1);
2118        mr_msg(2, "Waiting for buffer() to finish");
2119    }
2120
2121    paranoid_system("sync");
2122
2123    if (run_program_and_log_output
2124        ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/tmp/", FALSE)) {
2125        mr_msg(1,
2126                "Error. Failed to copy log to PC's /tmp dir. (Mounted read-only?)");
2127    }
2128    if (run_program_and_log_output
2129        ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/root/", FALSE)) {
2130        mr_msg(1,
2131                "Error. Failed to copy log to PC's /root dir. (Mounted read-only?)");
2132    }
2133    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
2134        run_program_and_log_output("mkdir -p " MNT_RESTORING
2135                                   "/mnt/.boot.d", 5);
2136    }
2137    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
2138        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
2139            continue;
2140        }
2141        sprintf(tmp, "Unmounting device %s  ", mountlist->el[lino].device);
2142
2143        update_progress_form(tmp);
2144        if (is_this_device_mounted(mountlist->el[lino].device)) {
2145            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
2146                sprintf(command, "swapoff %s", mountlist->el[lino].device);
2147            } else {
2148                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2149                    sprintf(command, "umount %s/", MNT_RESTORING);
2150                    mr_msg(3,
2151                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2152                } else {
2153                    sprintf(command, "umount " MNT_RESTORING "%s",
2154                            mountlist->el[lino].mountpoint);
2155                }
2156            }
2157            mr_msg(10, "The 'umount' command is '%s'", command);
2158            res = run_program_and_log_output(command, 3);
2159        } else {
2160            strcat(tmp, "...not mounted anyway :-) OK");
2161            res = 0;
2162        }
2163        g_current_progress++;
2164        if (res) {
2165            strcat(tmp, "...Failed");
2166            retval++;
2167            log_to_screen(tmp);
2168        } else {
2169            mr_msg(2, tmp);
2170        }
2171    }
2172    close_progress_form();
2173    if (retval) {
2174        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2175    } else {
2176        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2177    }
2178    if (retval) {
2179        log_to_screen("Unable to unmount some of your partitions.");
2180    } else {
2181        log_to_screen("All partitions were unmounted OK.");
2182    }
2183    mr_free(mountlist);
2184    mr_free(command);
2185    mr_free(tmp);
2186    return (retval);
2187}
2188
2189/**************************************************************************
2190 *END_UNMOUNT_ALL_DEVICES                                                 *
2191 **************************************************************************/
2192
2193
2194
2195/**
2196 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2197 * to the ./tmp/ directory.
2198 * @param dev The tape device to read from.
2199 * @return 0 for success, nonzero for failure.
2200 */
2201int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2202{
2203    char *command;
2204    int res = 0;
2205    // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2206    long tape_block_size = 32768;
2207
2208    malloc_string(command);
2209
2210    // tar -zxvf-
2211    sprintf(command,
2212            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2213            dev,
2214            tape_block_size,
2215            1024L * 1024 * 32 / tape_block_size,
2216            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2217            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");
2218    mr_msg(2, "command = '%s'", command);
2219    res = run_program_and_log_output(command, -1);
2220    if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2221        res = 0;
2222    }
2223    mr_free(command);
2224    return (res);
2225}
2226
2227
2228
2229/**
2230 * Get the configuration file from the floppy, tape, or CD.
2231 * @param bkpinfo The backup information structure. Fields used:
2232 * - @c bkpinfo->backup_media_type
2233 * - @c bkpinfo->media_device
2234 * - @c bkpinfo->tmpdir
2235 * @return 0 for success, nonzero for failure.
2236 */
2237int get_cfg_file_from_archive(struct s_bkpinfo *bkpinfo)
2238{
2239    int retval = 0;
2240
2241   /** malloc *****/
2242    char *device;
2243    char *command;
2244    char *cfg_file;
2245    char *mounted_cfgf_path;
2246    char *tmp;
2247    char *mountpt;
2248    char *ramdisk_fname;
2249    char *mountlist_file;
2250    int res;
2251
2252    bool try_plan_B;
2253
2254    assert(bkpinfo != NULL);
2255    malloc_string(cfg_file);
2256    malloc_string(mounted_cfgf_path);
2257    malloc_string(mountpt);
2258    malloc_string(ramdisk_fname);
2259    malloc_string(mountlist_file);
2260    malloc_string(device);
2261    malloc_string(command);
2262    malloc_string(tmp);
2263    mr_msg(2, "gcffa --- starting");
2264    log_to_screen("I'm thinking...");
2265    sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2266    device[0] = '\0';
2267    chdir(bkpinfo->tmpdir);
2268    strcpy(cfg_file, MONDO_CFG_FILE_STUB);
2269    unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
2270    unlink(FILELIST_FULL_STUB);
2271    unlink(BIGGIELIST_TXT_STUB);
2272    unlink("tmp/i-want-my-lvm");
2273    sprintf(command, "mkdir -p %s", mountpt);
2274    run_program_and_log_output(command, FALSE);
2275
2276//   unlink( "tmp/mondo-restore.cfg" ); // superfluous, surely?
2277
2278    sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2279    sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir,
2280            MOUNTLIST_FNAME_STUB);
2281    //   make_hole_for_file( cfg_file );
2282    //   make_hole_for_file( mountlist_file);
2283    mr_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2284
2285    /* Floppy? */
2286    sprintf(tmp, "mkdir -p %s", mountpt);
2287    run_program_and_log_output(tmp, FALSE);
2288    sprintf(tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2289    run_program_and_log_output(tmp, FALSE);
2290
2291    sprintf(command, "mount /dev/fd0u1722 %s", mountpt);
2292    sprintf(tmp,
2293            "(sleep 15; kill `ps | grep \"%s\" | cut -d' ' -f1` 2> /dev/null) &",
2294            command);
2295    mr_msg(1, "tmp = '%s'", tmp);
2296    system(tmp);
2297    res = run_program_and_log_output(command, FALSE);
2298    if (res) {
2299        sprintf(command, "mount /dev/fd0H1440 %s", mountpt);
2300        res = run_program_and_log_output(command, FALSE);
2301    }
2302    if (res) {
2303        try_plan_B = TRUE;
2304    } else {
2305        try_plan_B = TRUE;
2306        mr_msg(2,
2307                "Mounted floppy OK but I don't trust it because the archives might contain more up-to-date config file than the floppy does.");
2308// NB: If busybox does not support 'mount -o loop' then Plan A WILL NOT WORK.
2309        mr_msg(2, "Processing floppy (plan A?)");
2310        sprintf(ramdisk_fname, "%s/mindi.rdz", mountpt);
2311        if (!does_file_exist(ramdisk_fname)) {
2312            sprintf(ramdisk_fname, "%s/initrd.img", mountpt);
2313        }
2314        if (!does_file_exist(ramdisk_fname)) {
2315            mr_msg(2,
2316                    "Cannot find ramdisk file on mountpoint. Are you sure that's a boot disk in the drive?");
2317        }
2318        if (extract_config_file_from_ramdisk
2319            (bkpinfo, ramdisk_fname, cfg_file, mountlist_file)) {
2320            mr_msg(2,
2321                    "Warning - failed to extract config file from ramdisk. I think this boot disk is mangled.");
2322        }
2323        sprintf(command, "umount %s", mountpt);
2324        run_program_and_log_output(command, 5);
2325        unlink(ramdisk_fname);
2326    }
2327    if (!does_file_exist(cfg_file)) {
2328        mr_msg(2, "gcffa --- we don't have cfg file yet.");
2329        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2330            try_plan_B = TRUE;
2331        } else {
2332            mr_msg(2, "gcffa --- calling mount_cdrom now :)");
2333            if (!mount_cdrom(bkpinfo)) {
2334                mr_msg(2,
2335                        "gcffa --- managed to mount CD; so, no need for Plan B");
2336                try_plan_B = FALSE;
2337            } else {
2338                try_plan_B = TRUE;
2339            }
2340            if (what_number_cd_is_this(bkpinfo) > 1) {
2341                insist_on_this_cd_number(bkpinfo,
2342                                         (g_current_media_number = 1));
2343            }
2344        }
2345        if (try_plan_B) {
2346            mr_msg(2, "gcffa --- OK, switching to Plan B");
2347            chdir(bkpinfo->tmpdir);
2348            run_program_and_log_output("mkdir -p tmp", FALSE);
2349
2350            if (strlen(bkpinfo->media_device) == 0) {
2351                strcpy(bkpinfo->media_device, "/dev/st0");
2352                mr_msg(2, "media_device is blank; assuming %s");
2353            }
2354            strcpy(tmp, bkpinfo->media_device);
2355            if (extract_cfg_file_and_mountlist_from_tape_dev
2356                (bkpinfo->media_device)) {
2357                strcpy(bkpinfo->media_device, "/dev/st0");
2358                if (extract_cfg_file_and_mountlist_from_tape_dev
2359                    (bkpinfo->media_device)) {
2360                    strcpy(bkpinfo->media_device, "/dev/osst0");
2361                    if (extract_cfg_file_and_mountlist_from_tape_dev
2362                        (bkpinfo->media_device)) {
2363                        strcpy(bkpinfo->media_device, "/dev/ht0");
2364                        if (extract_cfg_file_and_mountlist_from_tape_dev
2365                            (bkpinfo->media_device)) {
2366                            mr_msg(3,
2367                                    "I tried lots of devices but none worked.");
2368                            strcpy(bkpinfo->media_device, tmp);
2369                        }
2370                    }
2371                }
2372            }
2373
2374            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2375                log_to_screen("Cannot find config info on tape/CD/floppy");
2376                return (1);
2377            }
2378        } else {
2379            mr_msg(2,
2380                    "gcffa --- looking at mounted CD for mindi-boot.2880.img");
2381            sprintf(command,
2382                    "mount " MNT_CDROM
2383                    "/images/mindi-boot.2880.img -o loop %s", mountpt);
2384            sprintf(mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2385            if (!does_file_exist(mounted_cfgf_path)) {
2386                mr_msg(2,
2387                        "gcffa --- Plan C, a.k.a. untarring some file from all.tar.gz");
2388                sprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");  // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
2389                run_program_and_log_output(command, TRUE);
2390                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2391                    fatal_error
2392                        ("Please reinsert the disk/CD and try again.");
2393                }
2394            }
2395        }
2396    }
2397    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2398        mr_msg(1, "gcffa --- great! We've got the config file");
2399        sprintf(tmp, "%s/%s",
2400                call_program_and_get_last_line_of_output("pwd"),
2401                MONDO_CFG_FILE_STUB);
2402        sprintf(command, "cp -f %s %s", tmp, cfg_file);
2403        iamhere(command);
2404        if (strcmp(tmp, cfg_file)
2405            && run_program_and_log_output(command, 1)) {
2406            mr_msg(1,
2407                    "... but an error occurred when I tried to move it to %s",
2408                    cfg_file);
2409        } else {
2410            mr_msg(1, "... and I moved it successfully to %s", cfg_file);
2411        }
2412        sprintf(command, "cp -f %s/%s %s",
2413                call_program_and_get_last_line_of_output("pwd"),
2414                MOUNTLIST_FNAME_STUB, mountlist_file);
2415        iamhere(command);
2416        if (strcmp(tmp, cfg_file)
2417            && run_program_and_log_output(command, 1)) {
2418            mr_msg(1, "Failed to get mountlist");
2419        } else {
2420            mr_msg(1, "Got mountlist too");
2421            sprintf(command, "cp -f %s %s", mountlist_file,
2422                    g_mountlist_fname);
2423            if (run_program_and_log_output(command, 1)) {
2424                mr_msg(1, "Failed to copy mountlist to /tmp");
2425            } else {
2426                mr_msg(1, "Copied mountlist to /tmp as well OK");
2427                sprintf(command, "cp -f tmp/i-want-my-lvm /tmp/");
2428                run_program_and_log_output(command, 1);
2429            }
2430        }
2431    }
2432    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2433    if (!does_file_exist(cfg_file)) {
2434        iamhere(cfg_file);
2435        mr_msg(1, "%s not found", cfg_file);
2436        log_to_screen
2437            ("Oh dear. Unable to recover configuration file from boot disk");
2438        return (1);
2439    }
2440
2441    log_to_screen("Recovered mondo-restore.cfg");
2442    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2443        log_to_screen("...but not mountlist.txt - a pity, really...");
2444    }
2445/* start SAH */
2446    else {
2447        sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2448                bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2449        run_program_and_log_output(command, FALSE);
2450    }
2451/*--commented out by SAH
2452  sprintf( command, "cp -f %s %s/%s", cfg_file, bkpinfo->tmpdir, MONDO_CFG_FILE_STUB );
2453  run_program_and_log_output( command, FALSE );
2454  sprintf( command, "cp -f %s %s/%s", mountlist_file, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB );
2455  run_program_and_log_output( command, FALSE );
2456*/
2457/* end SAH */
2458
2459    sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2460    run_program_and_log_output(command, FALSE);
2461    sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2462    run_program_and_log_output(command, FALSE);
2463    sprintf(command, "cp -f etc/raidtab /etc/");
2464    run_program_and_log_output(command, FALSE);
2465    sprintf(command, "cp -f tmp/i-want-my-lvm /tmp/");
2466    run_program_and_log_output(command, FALSE);
2467    g_backup_media_type = bkpinfo->backup_media_type;
2468    mr_free(device);
2469    mr_free(command);
2470    mr_free(tmp);
2471    mr_free(cfg_file);
2472    mr_free(mounted_cfgf_path);
2473    mr_free(mountpt);
2474    mr_free(ramdisk_fname);
2475    mr_free(mountlist_file);
2476    return (retval);
2477}
2478
2479/**************************************************************************
2480 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2481 **************************************************************************/
2482
2483/* @} - end restoreUtilityGroup */
2484
2485
2486/***************************************************************************
2487 * F@                                                                      *
2488 * () -- Hugo Rabson                                  *
2489 *                                                                         *
2490 * Purpose:                                                                *
2491 *                                                                         *
2492 * Called by:                                                              *
2493 * Params:    -                      -                                     *
2494 * Returns:   0=success; nonzero=failure                                   *
2495 ***************************************************************************/
2496
2497
2498
2499void wait_until_software_raids_are_prepped(char *mdstat_file,
2500                                           int wait_for_percentage)
2501{
2502    struct raidlist_itself *raidlist;
2503    int unfinished_mdstat_devices = 9999, i;
2504    char *screen_message;
2505
2506    malloc_string(screen_message);
2507    raidlist = (struct raidlist_itself *)mr_malloc(sizeof(struct raidlist_itself));
2508
2509    assert(wait_for_percentage <= 100);
2510    iamhere("wait_until_software_raids_are_prepped");
2511    while (unfinished_mdstat_devices > 0) {
2512            // FIXME: Prefix '/dev/' should really be dynamic!
2513        if (parse_mdstat(raidlist, "/dev/")) {
2514            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2515            mr_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2516            return;
2517        }
2518        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2519            if (raidlist->el[i].progress < wait_for_percentage) {
2520                unfinished_mdstat_devices++;
2521                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2522                {
2523                    continue;
2524                }
2525                mr_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2526                sprintf(screen_message, "Sync'ing %s",
2527                        raidlist->el[i].raid_device);
2528                open_evalcall_form(screen_message);
2529                while (raidlist->el[i].progress < wait_for_percentage) {
2530                    mr_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2531                    update_evalcall_form(raidlist->el[i].progress);
2532                    sleep(2);
2533                    // FIXME: Prefix '/dev/' should really be dynamic!
2534                    if (parse_mdstat(raidlist, "/dev/")) {
2535                        break;
2536                    }
2537                }
2538                close_evalcall_form();
2539            }
2540        }
2541    }
2542    mr_free(screen_message);
2543    mr_free(raidlist);
2544}
Note: See TracBrowser for help on using the repository browser.