/*************************************************************************** $Id: mondo-rstr-tools.c 2230 2009-06-17 20:53:23Z bruno $ ***************************************************************************/ #include #include #include "my-stuff.h" #include "mr_mem.h" #include "../common/mondostructures.h" #include "../common/libmondo.h" #include "mr-externs.h" #include "mondo-rstr-tools.h" /** * The biggielist stub (appended to the directory where all.tar.gz was unpacked). */ #define BIGGIELIST_TXT_STUB "tmp/biggielist.txt" /** * The filelist stub (appended to the directory where all.tar.gz was unpacked). */ #define FILELIST_FULL_STUB "tmp/filelist.full.gz" /** * The mountlist stub (appended to the directory where all.tar.gz was unpacked). */ #define MOUNTLIST_FNAME_STUB "tmp/mountlist.txt" /** * The mondo-restore.cfg stub (appended to the directory where all.tar.gz was unpacked). */ #define MONDO_CFG_FILE_STUB "tmp/mondo-restore.cfg" /** * The i-want-my-lvm stub */ #define IWANTMYLVM_STUB "tmp/i-want-my-lvm" extern bool g_ISO_restore_mode; /* are we in Iso Mode? */ extern bool g_I_have_just_nuked; /* extern char *g_tmpfs_mountpt; */ extern char *g_isodir_device; extern char *g_isodir_format; extern long g_current_progress, g_maximum_progress; extern char *g_biggielist_txt; // where 'biggielist.txt' is stored, on ramdisk / tempdir; // biggielist.txt is the list of big files stored on the // backup media set in question extern char *g_filelist_full; // filelist.full.gz is the list of all regular files // (excluding big files) stored on the backup media set extern char *g_biggielist_pot; // list of big files which _could_ be restored, if the // user chooses them extern char *g_filelist_imagedevs; // list of devices (e.g. /dev/hda1, /dev/sda5) which // were archived as images, not just /dev entries // ... e.g. NTFS, BeOS partitions extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS, // restore only these extern char *g_mondo_cfg_file; // where m*ndo-restore.cfg (the config file) is stored extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored extern char *g_mondo_home; // homedir of Mondo; usually /usr/local/share/mondo extern t_bkptype g_backup_media_type; extern int g_partition_table_locked_up; extern char *MONDO_LOGFILE; /* Reference to global bkpinfo */ extern struct s_bkpinfo *bkpinfo; /* Should we use or not extended attributes and acl when restoring */ char *g_getfattr = NULL; char *g_getfacl = NULL; extern void kill_anything_like_this(char *str); extern int skip_obdr(void); extern int set_tape_block_size_with_mt(long internal_tape_block_size); /** * @addtogroup restoreUtilityGroup * @{ */ /** * Free the malloc()s for the filename variables. */ void free_MR_global_filenames(void) { paranoid_free(g_biggielist_txt); paranoid_free(g_filelist_full); paranoid_free(g_filelist_imagedevs); paranoid_free(g_imagedevs_restthese); paranoid_free(g_mondo_cfg_file); paranoid_free(g_mountlist_fname); paranoid_free(g_mondo_home); /* paranoid_free(g_tmpfs_mountpt); */ paranoid_free(g_isodir_device); paranoid_free(g_isodir_format); } /** * Ask the user which imagedevs from the list contained in @p infname should * actually be restored. * @param infname The file containing a list of all imagedevs. * @param outfname The location of the output file containing the imagedevs the user wanted to restore. * @ingroup restoreUtilityGroup */ void ask_about_these_imagedevs(char *infname, char *outfname) { FILE *fin; FILE *fout; /************************************************************************ * allocate memory regions. test and set -sab 16 feb 2003 * ************************************************************************/ char *incoming_ptr; char *question_ptr; char incoming[MAX_STR_LEN] = "\0"; char question[MAX_STR_LEN]; assert_string_is_neither_NULL_nor_zerolength(infname); assert_string_is_neither_NULL_nor_zerolength(outfname); incoming_ptr = malloc(sizeof(incoming)); if (incoming_ptr == NULL) { fprintf(stderr, "Out of Memory\n"); exit(EXIT_FAILURE); } question_ptr = malloc(sizeof(question)); if (question_ptr == NULL) { fprintf(stderr, "Out of Memory\n"); exit(EXIT_FAILURE); } memset(incoming_ptr, '\0', sizeof(incoming)); memset(question_ptr, '\0', sizeof(question)); if (!(fin = fopen(infname, "r"))) { fatal_error("Cannot openin infname"); } if (!(fout = fopen(outfname, "w"))) { fatal_error("Cannot openin outfname"); } for (fgets(incoming_ptr, MAX_STR_LEN, fin); !feof(fin); fgets(incoming_ptr, MAX_STR_LEN, fin)) { strip_spaces(incoming_ptr); if (incoming[0] == '\0') { continue; } sprintf(question_ptr, "Should I restore the image of %s ?", incoming_ptr); if (ask_me_yes_or_no(question_ptr)) { fprintf(fout, "%s\n", incoming_ptr); } } /*** free memory ***********/ paranoid_free(incoming_ptr); incoming_ptr = NULL; paranoid_free(question_ptr); question_ptr = NULL; paranoid_fclose(fout); paranoid_fclose(fin); } /************************************************************************** *ASK_ABOUT_THESE_IMAGEDEVS * **************************************************************************/ /** * Extract @c mondo-restore.cfg and @c mountlist.txt from @p ramdisk_fname. * @param bkpinfo The backup information structure. @c tmpdir is the only field used. * @param ramdisk_fname The filename of the @b compressed ramdisk to look in. * @param output_cfg_file Where to put the configuration file extracted. * @param output_mountlist_file Where to put the mountlist file extracted. * @return 0 for success, nonzero for failure. * @ingroup restoreUtilityGroup */ /** * Keep trying to get mondo-restore.cfg from the archive, until the user gives up. */ void get_cfg_file_from_archive_or_bust() { while (get_cfg_file_from_archive()) { if (!ask_me_yes_or_no ("Failed to find config file/archives. Choose another source?")) { fatal_error("Could not find config file/archives. Aborting."); } interactively_obtain_media_parameters_from_user(FALSE); } } /** * Determine whether @p list_fname contains a line containing @p f. * @param f The line to search for. * @param list_fname The file to search in. * @param preamble Ignore this beginning part of @p f ("" to disable). * @return TRUE if it's in the list, FALSE if it's not. */ bool is_file_in_list(char *f, char *list_fname, char *preamble) { /** needs malloc **/ char *command; char *file; char *tmp; int res; malloc_string(command); malloc_string(file); malloc_string(tmp); assert_string_is_neither_NULL_nor_zerolength(f); assert_string_is_neither_NULL_nor_zerolength(list_fname); assert(preamble != NULL); if (strncmp(preamble, f, strlen(preamble)) == 0) { strcpy(file, f + strlen(preamble)); } else { strcpy(file, f); } if (file[0] == '/' && file[1] == '/') { strcpy(tmp, file); strcpy(file, tmp + 1); } sprintf(tmp, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file); log_msg(2, tmp); sprintf(command, "grep -E '^%s$' %s", file, list_fname); res = run_program_and_log_output(command, FALSE); paranoid_free(command); paranoid_free(file); paranoid_free(tmp); if (res) { return (FALSE); } else { return (TRUE); } } /************************************************************************** *END_IS_FILE_IN_LIST * **************************************************************************/ /** * Set up an ISO backup. * @param bkpinfo The backup information structure. Fields used: * - @c bkpinfo->backup_media_type * - @c bkpinfo->disaster_recovery * - @c bkpinfo->isodir * @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode. * @return 0 for success, nonzero for failure. */ int iso_fiddly_bits(bool nuke_me_please) { char *mount_isodir_command = NULL; char *tmp, *command; int retval = 0, i; bool already_mounted = FALSE; assert(bkpinfo != NULL); malloc_string(tmp); malloc_string(command); g_ISO_restore_mode = TRUE; read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device); if (bkpinfo->disaster_recovery) { /* Patch Conor Daly 26-june-2004 * Don't let this clobber an existing bkpinfo->isodir */ if (!bkpinfo->isodir[0]) { strcpy(bkpinfo->isodir, "/tmp/isodir"); } /* End patch */ sprintf(command, "mkdir -p %s", bkpinfo->isodir); run_program_and_log_output(command, 5); log_msg(2, "Setting isodir to %s", bkpinfo->isodir); } if (!get_isodir_info(g_isodir_device, g_isodir_format, bkpinfo->isodir, nuke_me_please)) { return (1); } paranoid_system("umount " MNT_CDROM " 2> /dev/null"); /* just in case */ if (is_this_device_mounted(g_isodir_device)) { log_to_screen("WARNING - isodir is already mounted"); already_mounted = TRUE; } else { mr_asprintf(&mount_isodir_command, "mount %s", g_isodir_device); if (strlen(g_isodir_format) > 1) { mr_strcat(mount_isodir_command, " -t %s", g_isodir_format); } mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir); run_program_and_log_output("df -m", FALSE); sprintf(tmp, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?", mount_isodir_command); log_msg(1, tmp); if (run_program_and_log_output(mount_isodir_command, FALSE)) { popup_and_OK ("Cannot mount the device where the ISO files are stored."); return (1); } paranoid_free(mount_isodir_command); log_to_screen ("I have mounted the device where the ISO files are stored."); } if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { mount_media(); } i = what_number_cd_is_this(); /* has the side-effect of calling mount_media() */ sprintf(tmp, "%s #%d has been mounted via loopback mount", media_descriptor_string(bkpinfo->backup_media_type), i); log_msg(1, tmp); if (i < 0) { popup_and_OK ("Cannot find ISO images in the directory you specified."); retval = 1; } log_msg(2, "%ld: bkpinfo->isodir is now %s", __LINE__, bkpinfo->isodir); paranoid_free(tmp); paranoid_free(command); return (retval); } /** * Kill all Petris processes. */ void kill_petris(void) { kill_anything_like_this("petris"); } /************************************************************************** *END_KILL_PETRIS * **************************************************************************/ /** * Mount @p device at @p mpt as @p format. * @param device The device (/dev entry) to mount. * @param mpt The directory to mount it on. * @param format The filesystem type of @p device. * @param writeable If TRUE, mount read-write; if FALSE, mount read-only. * @return 0 for success, nonzero for failure. */ int mount_device(char *device, char *mpt, char *format, bool writeable) { int res = 0; /** malloc **/ char *tmp, *command, *mountdir, *mountpoint; char *additional_parameters = NULL; assert_string_is_neither_NULL_nor_zerolength(device); assert_string_is_neither_NULL_nor_zerolength(mpt); assert(format != NULL); malloc_string(tmp); malloc_string(command); malloc_string(mountdir); malloc_string(mountpoint); if (!strcmp(mpt, "/1")) { strcpy(mountpoint, "/"); log_msg(3, "Mommm! SME is being a dildo!"); } else { strcpy(mountpoint, mpt); } if (!strcmp(mountpoint, "lvm")) { return (0); } if (!strcmp(mountpoint, "image")) { return (0); } sprintf(tmp, "Mounting device %s ", device); log_msg(1, tmp); /* Deal with additional params only if not /proc or /sys */ mr_asprintf(&additional_parameters, ""); if (strcmp(format, "proc") && strcmp(format, "sys")) { if (writeable) { mr_strcat(additional_parameters, "-o rw"); } else { mr_strcat(additional_parameters, "-o ro"); } if (find_home_of_exe("setfattr")) { mr_strcat(additional_parameters, ",user_xattr"); } if (find_home_of_exe("setfacl")) { mr_strcat(additional_parameters, ",acl"); } } if (!strcmp(mountpoint, "swap")) { sprintf(command, "swapon %s", device); } else { if (!strcmp(mountpoint, "/")) { strcpy(mountdir, MNT_RESTORING); } else { sprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint); } sprintf(command, "mkdir -p %s", mountdir); run_program_and_log_output(command, FALSE); sprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE); log_msg(2, "command='%s'", command); } paranoid_free(additional_parameters); res = run_program_and_log_output(command, TRUE); if (res && (strstr(command, "xattr") || strstr(command, "acl"))) { log_msg(1, "Re-trying without the fancy extra parameters"); sprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE); res = run_program_and_log_output(command, TRUE); } if (res) { log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir); log_msg(1, "command was '%s'", command); if (!strcmp(mountpoint, "swap")) { log_to_screen(tmp); } else { log_msg(2, "Retrying w/o the '-t' switch"); sprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE); log_msg(2, "2nd command = '%s'", command); res = run_program_and_log_output(command, TRUE); if (res == 0) { log_msg(1, "That's OK. I called mount w/o a filesystem type and it worked fine in the end."); } else { log_to_screen(tmp); } } } if (res && !strcmp(mountpoint, "swap")) { log_msg(2, "That's ok. It's just a swap partition."); log_msg(2, "Non-fatal error. Returning 0."); res = 0; } paranoid_free(tmp); paranoid_free(command); paranoid_free(mountdir); paranoid_free(mountpoint); return (res); } /************************************************************************** *END_MOUNT_DEVICE * **************************************************************************/ /** * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING. * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted. * @param writeable If TRUE, then mount read-write; if FALSE mount read-only. * @return The number of errors encountered (0 for success). */ int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable) { int retval = 0, lino, res; char *tmp; char *these_failed = NULL; char *format; struct mountlist_itself *mountlist = NULL; malloc_string(tmp); malloc_string(format); assert(p_external_copy_of_mountlist != NULL); mountlist = malloc(sizeof(struct mountlist_itself)); memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist, sizeof(struct mountlist_itself)); sort_mountlist_by_mountpoint(mountlist, 0); mvaddstr_and_log_it(g_currentY, 0, "Mounting devices "); open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries); mr_asprintf(&these_failed, ""); for (lino = 0; lino < mountlist->entries; lino++) { if (!strcmp(mountlist->el[lino].device, "/proc")) { log_msg(1, "Again with the /proc - why is this in your mountlist?"); } else if (is_this_device_mounted(mountlist->el[lino].device)) { sprintf(tmp, "%s is already mounted", mountlist->el[lino].device); log_to_screen(tmp); } else if (strcmp(mountlist->el[lino].mountpoint, "none") && strcmp(mountlist->el[lino].mountpoint, "lvm") && strcmp(mountlist->el[lino].mountpoint, "raid") && strcmp(mountlist->el[lino].mountpoint, "image")) { sprintf(tmp, "Mounting %s", mountlist->el[lino].device); update_progress_form(tmp); strcpy(format, mountlist->el[lino].format); res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, format, writeable); retval += res; if (res) { mr_strcat(these_failed, "%s ",mountlist->el[lino].device); } } g_current_progress++; } close_progress_form(); if (retval) { if (g_partition_table_locked_up > 0) { log_to_screen ("fdisk's ictol() call to refresh its copy of the partition table causes the kernel to"); log_to_screen ("lock up the partition table. You might have to reboot and use Interactive Mode to"); log_to_screen ("format and restore *without* partitioning first. Sorry for the inconvenience."); } sprintf(tmp, "Could not mount device(s) %s- shall I abort?", these_failed); if (!ask_me_yes_or_no(tmp)) { retval = 0; log_to_screen ("Continuing, although some device(s) failed to be mounted"); mvaddstr_and_log_it(g_currentY++, 74, "Done."); } else { mvaddstr_and_log_it(g_currentY++, 74, "Failed."); log_to_screen ("Unable to mount some or all of your partitions."); } } else { log_to_screen("All partitions were mounted OK."); mvaddstr_and_log_it(g_currentY++, 74, "Done."); } paranoid_free(these_failed); /* Also mounting under MNT_RESTORING special FS */ (void)mount_device("/proc","/proc","proc",TRUE); (void)mount_device("/sys","/sys","sysfs",TRUE); run_program_and_log_output("df -m", 3); paranoid_free(mountlist); paranoid_free(tmp); paranoid_free(format); return (retval); } /************************************************************************** *END_MOUNT_ALL_DEVICES * **************************************************************************/ /** * Mount the CD-ROM or USB device at /mnt/cdrom. * @param bkpinfo The backup information structure. Fields used: * - @c bkpinfo->backup_media_type * - @c bkpinfo->disaster_recovery * - @c bkpinfo->isodir * - @c bkpinfo->media_device * @return 0 for success, nonzero for failure. */ int mount_media() { char *mount_cmd; int i, res; #ifdef __FreeBSD__ char mdd[32]; char *mddev = mdd; #endif malloc_string(mount_cmd); assert(bkpinfo != NULL); if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) { log_msg(8, "Tape/udev. Therefore, no need to mount a media."); paranoid_free(mount_cmd); return 0; } if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) { log_msg(2, "mount_media() - media already mounted. Fair enough."); paranoid_free(mount_cmd); return (0); } if (bkpinfo->backup_media_type == nfs) { log_msg(2, "Mounting for NFS thingy"); log_msg(2, "isodir = %s", bkpinfo->isodir); if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/")) && am_I_in_disaster_recovery_mode()) { strcpy(bkpinfo->isodir, "/tmp/isodir"); log_msg(1, "isodir is being set to %s", bkpinfo->isodir); } #ifdef __FreeBSD__ sprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->nfs_remote_dir, bkpinfo->prefix, g_current_media_number); mddev = make_vn(mount_cmd); sprintf(mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev); #else sprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->nfs_remote_dir, bkpinfo->prefix, g_current_media_number, MNT_CDROM); #endif } else if (bkpinfo->backup_media_type == iso) { #ifdef __FreeBSD__ sprintf(mount_cmd, "%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number); mddev = make_vn(mount_cmd); sprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM); #else sprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, MNT_CDROM); #endif } else if (bkpinfo->backup_media_type == usb) { sprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, MNT_CDROM); } else if (strstr(bkpinfo->media_device, "/dev/")) { #ifdef __FreeBSD__ sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device, MNT_CDROM); #else sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s", bkpinfo->media_device, MNT_CDROM); #endif } else { if (bkpinfo->disaster_recovery && does_file_exist("/tmp/CDROM-LIVES-HERE")) { strcpy(bkpinfo->media_device, last_line_of_file("/tmp/CDROM-LIVES-HERE")); } else { find_cdrom_device(bkpinfo->media_device, TRUE); } #ifdef __FreeBSD__ sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device, MNT_CDROM); #else sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s", bkpinfo->media_device, MNT_CDROM); #endif } log_msg(2, "(mount_media) --- command = %s", mount_cmd); for (i = 0; i < 2; i++) { res = run_program_and_log_output(mount_cmd, FALSE); if (!res) { break; } else { log_msg(2, "Failed to mount device."); sleep(5); run_program_and_log_output("sync", FALSE); } } if (res) { log_msg(2, "Failed, despite %d attempts", i); } else { log_msg(2, "Mounted media drive OK"); } paranoid_free(mount_cmd); return (res); } /************************************************************************** *END_MOUNT_CDROM * **************************************************************************/ /** * Fix some miscellaneous things in the filesystem so the system will come * up correctly on the first boot. */ void protect_against_braindead_sysadmins() { run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct", FALSE); run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct", FALSE); if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) { run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp", FALSE); } run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run/console", FALSE); run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null", FALSE); run_program_and_log_output("cd " MNT_RESTORING "; 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", TRUE); run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid", TRUE); run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*", TRUE); } /************************************************************************** *END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS * **************************************************************************/ /** * Fill out @p bkpinfo based on @p cfg_file. * @param cfg_file The mondo-restore.cfg file to read into @p bkpinfo. * @param bkpinfo The backup information structure to fill out with information * from @p cfg_file. * @return 0 for success, nonzero for failure. */ int read_cfg_file_into_bkpinfo(char *cfgf) { /** add mallocs **/ char *value = NULL; char *tmp = NULL; char *envtmp1 = NULL; char *envtmp2 = NULL; char *command = NULL; char *iso_mnt = NULL; char *iso_path = NULL; char *old_isodir = NULL; char cfg_file[100]; t_bkptype media_specified_by_user; malloc_string(command); malloc_string(iso_mnt); malloc_string(iso_path); malloc_string(old_isodir); malloc_string(value); malloc_string(tmp); // assert_string_is_neither_NULL_nor_zerolength(cfg_file); assert(bkpinfo != NULL); if (!cfgf) { strcpy(cfg_file, g_mondo_cfg_file); } else { strcpy(cfg_file, cfgf); } media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) { if (!strcmp(value, "cdstream")) { bkpinfo->backup_media_type = cdstream; } else if (!strcmp(value, "cdr")) { bkpinfo->backup_media_type = cdr; } else if (!strcmp(value, "cdrw")) { bkpinfo->backup_media_type = cdrw; } else if (!strcmp(value, "dvd")) { bkpinfo->backup_media_type = dvd; } else if (!strcmp(value, "usb")) { bkpinfo->backup_media_type = usb; bkpinfo->please_dont_eject = TRUE; } else if (!strcmp(value, "iso")) { // Patch by Conor Daly - 2004/07/12 bkpinfo->backup_media_type = iso; if (am_I_in_disaster_recovery_mode()) { /* Check to see if CD is already mounted before mounting it... */ if (!is_this_device_mounted("/dev/cdrom")) { log_msg(2, "NB: CDROM device not mounted, mounting..."); run_program_and_log_output("mount /dev/cdrom " MNT_CDROM, 1); } if (does_file_exist(MNT_CDROM "/archives/filelist.0")) { bkpinfo->backup_media_type = cdr; run_program_and_log_output("umount " MNT_CDROM, 1); log_it ("Re-jigging configuration AGAIN. CD-R, not ISO."); } } if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) { strcpy(bkpinfo->prefix,value); } else { strcpy(bkpinfo->prefix,STD_PREFIX); } } else if (!strcmp(value, "nfs")) { bkpinfo->backup_media_type = nfs; bkpinfo->please_dont_eject = TRUE; if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) { strcpy(bkpinfo->prefix,value); } else { strcpy(bkpinfo->prefix,STD_PREFIX); } if (strstr(call_program_and_get_last_line_of_output ("cat /proc/cmdline"), "pxe")) { /* We need to override prefix value in PXE mode as it's * already done in start-nfs */ envtmp1 = getenv("imgname"); if (envtmp1 == NULL) { fatal_error("no imgname variable in environment"); } strcpy(bkpinfo->prefix,envtmp1); } } else if (!strcmp(value, "tape")) { bkpinfo->backup_media_type = tape; } else if (!strcmp(value, "udev")) { bkpinfo->backup_media_type = udev; } else { fatal_error("UNKNOWN bkp-media-type"); } } else { fatal_error("backup-media-type not specified!"); } if (bkpinfo->disaster_recovery) { if (bkpinfo->backup_media_type == cdstream) { sprintf(bkpinfo->media_device, "/dev/cdrom"); // bkpinfo->media_size[0] = -1; bkpinfo->media_size[0] = 1999 * 1024; bkpinfo->media_size[1] = 650; /* good guess */ } else if (bkpinfo->backup_media_type == usb) { envtmp1 = getenv("MRUSBDEV"); if (envtmp1 == NULL) { if (read_cfg_var(cfg_file, "usb-dev", value)) { fatal_error("Cannot get USB device name from cfg file"); } } else { strcpy(value,envtmp1); } sprintf(bkpinfo->media_device, "%s1", value); sprintf(tmp, "Backup medium is USB --- dev=%s", bkpinfo->media_device); log_msg(2, tmp); } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) { if (read_cfg_var(cfg_file, "media-dev", value)) { fatal_error("Cannot get tape device name from cfg file"); } strcpy(bkpinfo->media_device, value); read_cfg_var(cfg_file, "media-size", value); bkpinfo->media_size[1] = atol(value); sprintf(tmp, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device); log_msg(2, tmp); } else { strcpy(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */ bkpinfo->media_size[0] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */ bkpinfo->media_size[1] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */ log_msg(2, "Backup medium is CD-R[W]"); } } else { log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file."); } read_cfg_var(cfg_file, "use-star", value); if (strstr(value, "yes")) { bkpinfo->use_star = TRUE; log_msg(1, "Goody! ... bkpinfo->use_star is now true."); } read_cfg_var(cfg_file, "obdr", value); if (strstr(value, "TRUE")) { bkpinfo->use_obdr = TRUE; log_msg(1, "OBDR mode activated"); } read_cfg_var(cfg_file, "acl", value); if (strstr(value, "TRUE")) { mr_asprintf(&g_getfacl,"setfacl"); log_msg(1, "We will restore ACLs"); if (! find_home_of_exe("setfacl")) { log_msg(1, "Unable to restore ACLs as no setfacl found"); } } read_cfg_var(cfg_file, "xattr", value); if (strstr(value, "TRUE")) { mr_asprintf(&g_getfattr,"setfattr"); log_msg(1, "We will restore XATTRs"); if (! find_home_of_exe("setfattr")) { log_msg(1, "Unable to restore XATTRs as no setfattr found"); } } if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) { bkpinfo->internal_tape_block_size = atol(value); log_msg(1, "Internal tape block size has been custom-set to %ld", bkpinfo->internal_tape_block_size); } else { bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE; log_msg(1, "Internal tape block size = default (%ld)", DEFAULT_INTERNAL_TAPE_BLOCK_SIZE); } read_cfg_var(cfg_file, "use-lzo", value); if (strstr(value, "yes")) { bkpinfo->use_lzo = TRUE; bkpinfo->use_gzip = FALSE; strcpy(bkpinfo->zip_exe, "lzop"); strcpy(bkpinfo->zip_suffix, "lzo"); } else { read_cfg_var(cfg_file, "use-gzip", value); if (strstr(value, "yes")) { bkpinfo->use_lzo = FALSE; bkpinfo->use_gzip = TRUE; strcpy(bkpinfo->zip_exe, "gzip"); strcpy(bkpinfo->zip_suffix, "gz"); } else { read_cfg_var(cfg_file, "use-comp", value); if (strstr(value, "yes")) { bkpinfo->use_lzo = FALSE; bkpinfo->use_gzip = FALSE; strcpy(bkpinfo->zip_exe, "bzip2"); strcpy(bkpinfo->zip_suffix, "bz2"); } else { bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0'; } } } value[0] = '\0'; read_cfg_var(cfg_file, "differential", value); if (!strcmp(value, "yes") || !strcmp(value, "1")) { bkpinfo->differential = TRUE; } log_msg(2, "differential var = '%s'", value); if (bkpinfo->differential) { log_msg(2, "THIS IS A DIFFERENTIAL BACKUP"); } else { log_msg(2, "This is a regular (full) backup"); } read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp); if (tmp[0] || strstr(call_program_and_get_last_line_of_output ("cat /proc/cmdline"), "donteject")) { bkpinfo->please_dont_eject = TRUE; log_msg(2, "Ok, I shan't eject when restoring! Groovy."); } if (bkpinfo->backup_media_type == nfs) { if (!cfgf) { log_msg(2, "nfs_mount remains %s", bkpinfo->nfs_mount); log_msg(2, "nfs_remote_dir remains %s", bkpinfo->nfs_remote_dir); log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place"); } else { read_cfg_var(g_mondo_cfg_file, "nfs-server-mount", bkpinfo->nfs_mount); read_cfg_var(g_mondo_cfg_file, "nfs-server-path", bkpinfo->nfs_remote_dir); log_msg(2, "nfs_mount is %s", bkpinfo->nfs_mount); log_msg(2, "nfs_remote_dir is %s", bkpinfo->nfs_remote_dir); } if (strstr(call_program_and_get_last_line_of_output ("cat /proc/cmdline"), "pxe")) { /* We need to override values in PXE mode as it's * already done in start-nfs */ envtmp1 = getenv("nfsmount"); if (envtmp1 == NULL) { fatal_error("no nfsmount variable in environment"); } envtmp2 = getenv("dirimg"); if (envtmp2 == NULL) { fatal_error("no dirimg variable in environment"); } strcpy(bkpinfo->nfs_mount,envtmp1); strcpy(bkpinfo->nfs_remote_dir,envtmp2); } } else if (bkpinfo->backup_media_type == iso) { /* Patch by Conor Daly 23-june-2004 * to correctly mount iso-dev and set a sensible * isodir in disaster recovery mode */ strcpy(old_isodir, bkpinfo->isodir); read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt); read_cfg_var(g_mondo_cfg_file, "isodir", iso_path); sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path); if (!bkpinfo->isodir[0]) { strcpy(bkpinfo->isodir, old_isodir); } if (!bkpinfo->disaster_recovery) { if (strcmp(old_isodir, bkpinfo->isodir)) { log_it ("user nominated isodir differs from archive, keeping user's choice: %s %s\n", old_isodir, bkpinfo->isodir); strcpy(bkpinfo->isodir, old_isodir); } } read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device); log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device); if (bkpinfo->disaster_recovery) { if (is_this_device_mounted(g_isodir_device)) { log_msg(2, "NB: isodir is already mounted"); /* Find out where it's mounted */ sprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device); log_it("command = %s", command); log_it("res of it = %s", call_program_and_get_last_line_of_output(command)); sprintf(iso_mnt, "%s", call_program_and_get_last_line_of_output(command)); } else { sprintf(iso_mnt, "/tmp/isodir"); sprintf(tmp, "mkdir -p %s", iso_mnt); run_program_and_log_output(tmp, 5); sprintf(tmp, "mount %s %s", g_isodir_device, iso_mnt); if (run_program_and_log_output(tmp, 3)) { log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?"); bkpinfo->backup_media_type = cdr; strcpy(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */ bkpinfo->isodir[0] = iso_mnt[0] = iso_path[0] = '\0'; if (mount_media()) { fatal_error ("Unable to mount isodir. Failed to mount CD-ROM as well."); } else { log_msg(1, "You backed up to disk, then burned some CDs."); } } } /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */ if (bkpinfo->backup_media_type == iso) { sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path); } } } if (media_specified_by_user != none) { if (g_restoring_live_from_cd) { if (bkpinfo->backup_media_type != media_specified_by_user) { log_msg(2, "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)"); interactively_obtain_media_parameters_from_user(FALSE); media_specified_by_user = bkpinfo->backup_media_type; get_cfg_file_from_archive(); /* if (media_specified_by_user != cdr && media_specified_by_user == cdrw) { g_restoring_live_from_cd = FALSE; } */ } } bkpinfo->backup_media_type = media_specified_by_user; } g_backup_media_type = bkpinfo->backup_media_type; paranoid_free(value); paranoid_free(tmp); paranoid_free(command); paranoid_free(iso_mnt); paranoid_free(iso_path); paranoid_free(old_isodir); return (0); } /************************************************************************** *END_READ_CFG_FILE_INTO_BKPINFO * **************************************************************************/ /** * Allow the user to edit the filelist and biggielist. * The filelist is unlinked after it is read. * @param bkpinfo The backup information structure. Fields used: * - @c bkpinfo->backup_media_type * - @c bkpinfo->isodir * - @c bkpinfo->media_device * - @c bkpinfo->tmpdir * @return The filelist structure containing the information read from disk. */ struct s_node *process_filelist_and_biggielist() { struct s_node *filelist; /** add mallocs**/ char *command; char *tmp; int res = 0; pid_t pid; bool extract_mountlist_stub = FALSE; assert(bkpinfo != NULL); malloc_string(command); malloc_string(tmp); /* If those files already exist, do not overwrite them later on */ if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) { extract_mountlist_stub = FALSE; } else { extract_mountlist_stub = TRUE; } if (does_file_exist(g_filelist_full) && does_file_exist(g_biggielist_txt)) { log_msg(1, "%s exists", g_filelist_full); log_msg(1, "%s exists", g_biggielist_txt); log_msg(2, "Filelist and biggielist already recovered from media. Yay!"); } else { getcwd(tmp, MAX_STR_LEN); chdir(bkpinfo->tmpdir); log_msg(1, "chdir(%s)", bkpinfo->tmpdir); log_to_screen("Extracting filelist and biggielist from media..."); unlink("/tmp/filelist.full"); unlink(FILELIST_FULL_STUB); if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { sprintf(command, "tar -b %ld -zxf %s ./%s ./%s ./%s ./%s ./%s", bkpinfo->internal_tape_block_size, bkpinfo->media_device, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB); log_msg(1, "tarcommand = %s", command); run_program_and_log_output(command, 1); if (!does_file_exist(FILELIST_FULL_STUB)) { /* Doing that allow us to remain compatible with pre-2.2.5 versions */ log_msg(2, "pre-2.2.4 compatible mode on"); sprintf(command, "tar -b %ld -zxf %s %s %s %s %s %s", bkpinfo->internal_tape_block_size, bkpinfo->media_device, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB); log_msg(1, "tarcommand = %s", command); run_program_and_log_output(command, 1); } } else { log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir); insist_on_this_cd_number(1); log_msg(2, "Back from iotcn"); run_program_and_log_output("mount", 1); sprintf(command, "tar -zxf %s/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MNT_CDROM, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB); log_msg(1, "tarcommand = %s", command); run_program_and_log_output(command, 1); if (!does_file_exist(FILELIST_FULL_STUB)) { /* Doing that allow us to remain compatible with pre-2.2.5 versions */ log_msg(2, "pre-2.2.4 compatible mode on"); sprintf(command, "tar -zxf %s/images/all.tar.gz %s %s %s %s %s", MNT_CDROM, MOUNTLIST_FNAME_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB, MONDO_CFG_FILE_STUB); log_msg(1, "tarcommand = %s", command); run_program_and_log_output(command, 1); } if (!does_file_exist(BIGGIELIST_TXT_STUB)) { fatal_error ("all.tar.gz did not include " BIGGIELIST_TXT_STUB); } if (!does_file_exist(FILELIST_FULL_STUB)) { fatal_error ("all.tar.gz did not include " FILELIST_FULL_STUB); } } sprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB, g_mondo_cfg_file); run_program_and_log_output(command, FALSE); sprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir, BIGGIELIST_TXT_STUB, g_biggielist_txt); log_msg(1, "command = %s", command); paranoid_system(command); sprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir, FILELIST_FULL_STUB, g_filelist_full); log_msg(1, "command = %s", command); paranoid_system(command); } if (am_I_in_disaster_recovery_mode() && /* If it was there, do not overwrite it */ (extract_mountlist_stub) && ask_me_yes_or_no("Do you want to retrieve the mountlist as well?")) { sprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir); paranoid_system(command); } chdir(tmp); if (!does_file_exist(g_biggielist_txt)) { log_msg(1, "Warning - %s not found", g_biggielist_txt); } if (!does_file_exist(g_filelist_full)) { log_msg(1, "Warning - %s does not exist", g_filelist_full); } // popup_and_OK("Wonderful."); log_msg(2, "Forking"); pid = fork(); switch (pid) { case -1: fatal_error("Forking error"); break; case 0: log_to_screen("Pre-processing filelist"); if (!does_file_exist(g_biggielist_txt)) { sprintf(command, "echo -n > %s", g_biggielist_txt); paranoid_system(command); } sprintf(command, "grep -E '^/dev/.*' %s > %s", g_biggielist_txt, g_filelist_imagedevs); paranoid_system(command); exit(0); break; default: open_evalcall_form("Pre-processing filelist"); while (!waitpid(pid, (int *) 0, WNOHANG)) { usleep(100000); update_evalcall_form(0); } } close_evalcall_form(); log_msg(3, "loading filelist"); filelist = load_filelist(g_filelist_full); log_msg(3, "deleting original filelist"); unlink(g_filelist_full); if (g_text_mode) { printf("Restore which directory? --> "); fgets(tmp, sizeof(tmp), stdin); toggle_path_selection(filelist, tmp, TRUE); if (strlen(tmp) == 0) { res = 1; } else { res = 0; } } else { res = edit_filelist(filelist); } if (res) { log_msg(2, "User hit 'cancel'. Freeing filelist and aborting."); free_filelist(filelist); return (NULL); } ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese); close_evalcall_form(); // NB: It's not necessary to add g_biggielist_txt to the filelist.full // file. The filelist.full file already contains the filename of EVERY // file backed up - regular and biggie files. // However, we do want to make sure the imagedevs selected by the user // are flagged for restoring. if (length_of_file(g_imagedevs_restthese) > 2) { add_list_of_files_to_filelist(filelist, g_imagedevs_restthese, TRUE); } paranoid_free(command); paranoid_free(tmp); return (filelist); } /************************************************************************** *END_ PROCESS_FILELIST_AND_BIGGIELIST * **************************************************************************/ /** * Make a backup copy of path_root/filename. * The backup filename is the filename of the original with ".pristine" added. * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING). * @param filename The filename (absolute path) within @p path_root. * @return 0 for success, nonzero for failure. */ int backup_crucial_file(char *path_root, char *filename) { char *tmp; char *command; int res; malloc_string(tmp); malloc_string(command); assert(path_root != NULL); assert_string_is_neither_NULL_nor_zerolength(filename); sprintf(tmp, "%s/%s", path_root, filename); sprintf(command, "cp -f %s %s.pristine", tmp, tmp); res = run_program_and_log_output(command, 5); paranoid_free(tmp); paranoid_free(command); return (res); } void offer_to_make_initrd() { if (bkpinfo->restore_mode != nuke) { if (ask_me_yes_or_no ("You will now be able to re-generate your initrd.\nThis is especially useful if you changed of hardware configuration, cloned, made P2V, used multipath...\nDo you need to do it ?")) { log_msg(1,"Launching shell for manual initrd recreation"); popup_and_OK("You'll now be chrooted under your future / partition.\nGo under /boot and rebuild your initrd with\nmkinitrd -f -v initrd-2.x.y.img 2.x.y e.g.\nThen type exit to finish."); mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd..."); if (!g_text_mode) { newtSuspend(); } (void)system("chroot " MNT_RESTORING); if (!g_text_mode) { newtResume(); } mvaddstr_and_log_it(g_currentY++, 74, "Done."); } else { return; } } else { log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK"); log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK"); } } /** * Install the user's boot loader in the MBR. * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported. * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them. * @return 0 for success, nonzero for failure. */ int run_boot_loader(bool offer_to_hack_scripts) { int res; int retval = 0; /** malloc *******/ char *device; char *tmp = NULL; char *name; char *cmd = NULL; malloc_string(device); malloc_string(name); /* In order to have a working bootloader, we need to have all devices * ready in the chroot. If they are not there (udev) then copy them from * the current /dev location */ mr_asprintf(&cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING); run_program_and_log_output(cmd, 3); paranoid_free(cmd); backup_crucial_file(MNT_RESTORING, "/etc/fstab"); backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst"); backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf"); backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf"); backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map"); backup_crucial_file(MNT_RESTORING, "/etc/mtab"); read_cfg_var(g_mondo_cfg_file, "bootloader.device", device); read_cfg_var(g_mondo_cfg_file, "bootloader.name", name); mr_asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name); log_msg(2, tmp); paranoid_free(tmp); system("sync"); offer_to_make_initrd(); if (!strcmp(name, "LILO")) { res = run_lilo(offer_to_hack_scripts); } else if (!strcmp(name, "ELILO")) { res = run_elilo(offer_to_hack_scripts); } else if (!strcmp(name, "GRUB")) { res = run_grub(offer_to_hack_scripts, device); } else if (!strcmp(name, "RAW")) { res = run_raw_mbr(offer_to_hack_scripts, device); } #ifdef __FreeBSD__ else if (!strcmp(name, "BOOT0")) { mr_asprintf(&tmp, "boot0cfg -B %s", device); res = run_program_and_log_output(tmp, FALSE); paranoid_free(tmp); } else { mr_asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device); if (!system(tmp)) { paranoid_free(tmp); mr_asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device); res = run_program_and_log_output(tmp, 3); } else { log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up."); } paranoid_free(tmp); } #else else { log_to_screen ("Unable to determine type of boot loader. Defaulting to LILO."); res = run_lilo(offer_to_hack_scripts); } #endif retval += res; if (res) { log_to_screen("Your boot loader returned an error"); } else { log_to_screen("Your boot loader ran OK"); } paranoid_free(device); paranoid_free(name); return (retval); } /************************************************************************** *END_ RUN_BOOT_LOADER * **************************************************************************/ /** * Attempt to find the user's editor. * @return The editor found ("vi" if none could be found). * @note The returned string points to static storage that will be overwritten with each call. */ char *find_my_editor(void) { static char output[MAX_STR_LEN]; if (find_home_of_exe("pico")) { strcpy(output, "pico"); } else if (find_home_of_exe("nano")) { strcpy(output, "nano"); } else if (find_home_of_exe("e3em")) { strcpy(output, "e3em"); } else if (find_home_of_exe("e3vi")) { strcpy(output, "e3vi"); } else { strcpy(output, "vi"); } if (!find_home_of_exe(output)) { log_msg(2, " (find_my_editor) --- warning - %s not found", output); } return (output); } /** * Install GRUB on @p bd. * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them. * @param bd The boot device where GRUB is installed. * @return 0 for success, nonzero for failure. */ int run_grub(bool offer_to_run_stabgrub, char *bd) { /** malloc **/ char *command; char *boot_device; char *rootdev; char *rootdrive; char *conffile; char *tmp; char *editor; int res; int done; malloc_string(command); malloc_string(boot_device); malloc_string(tmp); malloc_string(editor); malloc_string(rootdev); malloc_string(rootdrive); malloc_string(conffile); assert_string_is_neither_NULL_nor_zerolength(bd); strcpy(editor, find_my_editor()); strcpy(boot_device, bd); if (!run_program_and_log_output("which grub-MR", FALSE)) { log_msg(1, "Yay! grub-MR found..."); sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device); log_msg(1, "command = %s", command); } else { sprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device); log_msg(1, "WARNING - grub-MR not found; using grub-install"); } if (offer_to_run_stabgrub && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) /* interactive mode */ { mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab, mtab, device.map and menu.lst, and running GRUB... "); for (done = FALSE; !done;) { popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4); sprintf(command, "stabgrub-me %s", boot_device); res = run_program_and_log_output(command, 1); if (res) { popup_and_OK ("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."); newtSuspend(); system("chroot " MNT_RESTORING); newtResume(); popup_and_OK("Thank you."); } else { done = TRUE; } popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst"); if (!g_text_mode) { newtSuspend(); } sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor); paranoid_system(tmp); sprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor); paranoid_system(tmp); sprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor); paranoid_system(tmp); sprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor); paranoid_system(tmp); if (!g_text_mode) { newtResume(); } } } else /* nuke mode */ { mvaddstr_and_log_it(g_currentY, 0, "Running GRUB... "); log_it("%s",command); res = run_program_and_log_output(command, 1); if (res) { popup_and_OK ("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."); newtSuspend(); system("chroot " MNT_RESTORING); newtResume(); popup_and_OK("Thank you."); } } if (res) { mvaddstr_and_log_it(g_currentY++, 74, "Failed."); log_to_screen ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE); log_msg(1, "Type:-"); log_msg(1, " mount-me"); log_msg(1, " chroot " MNT_RESTORING); log_msg(1, " mount /boot"); log_msg(1, " grub-install '(hd0)'"); log_msg(1, " exit"); log_msg(1, " unmount-me"); log_msg(1, "If you're really stuck, please e-mail the mailing list."); } else { mvaddstr_and_log_it(g_currentY++, 74, "Done."); } paranoid_free(rootdev); paranoid_free(rootdrive); paranoid_free(conffile); paranoid_free(command); paranoid_free(boot_device); paranoid_free(tmp); paranoid_free(editor); return (res); } /************************************************************************** *END_RUN_GRUB * **************************************************************************/ /** * Install ELILO on the user's boot drive (determined by elilo.conf). * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them. * @return 0 for success, nonzero for failure. */ int run_elilo(bool offer_to_run_stabelilo) { /** malloc **/ char *command; char *tmp; char *editor; int res; int done; malloc_string(command); malloc_string(tmp); malloc_string(editor); strcpy(editor, find_my_editor()); if (offer_to_run_stabelilo && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) /* interactive mode */ { mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and elilo.conf... "); sprintf(command, "stabelilo-me"); res = run_program_and_log_output(command, 3); if (res) { popup_and_OK ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist."); for (done = FALSE; !done;) { if (!g_text_mode) { newtSuspend(); } sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor); paranoid_system(tmp); sprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor); paranoid_system(tmp); if (!g_text_mode) { newtResume(); } // newtCls(); if (ask_me_yes_or_no("Edit them again?")) { continue; } done = TRUE; } } else { log_to_screen("elilo.conf and fstab were modified OK"); } } else /* nuke mode */ { res = TRUE; } paranoid_free(command); paranoid_free(tmp); paranoid_free(editor); return (res); } /************************************************************************** *END_RUN_ELILO * **************************************************************************/ /** * Install LILO on the user's boot drive (determined by /etc/lilo.conf). * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them. * @return 0 for success, nonzero for failure. */ int run_lilo(bool offer_to_run_stablilo) { /** malloc **/ char *command; char *tmp; char *editor; int res; int done; bool run_lilo_M = FALSE; malloc_string(command); malloc_string(tmp); malloc_string(editor); if (!run_program_and_log_output ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) { run_lilo_M = TRUE; } strcpy(editor, find_my_editor()); if (offer_to_run_stablilo && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) /* interactive mode */ { mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and lilo.conf, and running LILO... "); sprintf(command, "stablilo-me"); res = run_program_and_log_output(command, 3); if (res) { popup_and_OK ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."); for (done = FALSE; !done;) { if (!g_text_mode) { newtSuspend(); } sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor); paranoid_system(tmp); sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor); paranoid_system(tmp); if (!g_text_mode) { newtResume(); } // newtCls(); if (ask_me_yes_or_no("Edit them again?")) { continue; } res = run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 3); if (res) { res = run_program_and_log_output("chroot " MNT_RESTORING " lilo", 3); } if (res) { done = ask_me_yes_or_no ("LILO failed. Re-edit system files?"); } else { done = TRUE; } } } else { log_to_screen("lilo.conf and fstab were modified OK"); } } else /* nuke mode */ { mvaddstr_and_log_it(g_currentY, 0, "Running LILO... "); res = run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 3); if (res) { res = run_program_and_log_output("chroot " MNT_RESTORING " lilo", 3); } if (res) { mvaddstr_and_log_it(g_currentY++, 74, "Failed."); log_to_screen ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."); } else { mvaddstr_and_log_it(g_currentY++, 74, "Done."); } } if (run_lilo_M) { run_program_and_log_output("chroot " MNT_RESTORING " lilo -M /dev/hda", 3); run_program_and_log_output("chroot " MNT_RESTORING " lilo -M /dev/sda", 3); } paranoid_free(command); paranoid_free(tmp); paranoid_free(editor); return (res); } /************************************************************************** *END_RUN_LILO * **************************************************************************/ /** * Install a raw MBR onto @p bd. * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them. * @param bd The device to copy the stored MBR to. * @return 0 for success, nonzero for failure. */ int run_raw_mbr(bool offer_to_hack_scripts, char *bd) { /** malloc **/ char *command; char *boot_device; char *tmp; char *editor; int res; int done; malloc_string(command); malloc_string(boot_device); malloc_string(tmp); malloc_string(editor); assert_string_is_neither_NULL_nor_zerolength(bd); strcpy(editor, find_my_editor()); strcpy(boot_device, bd); sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device); log_msg(2, "run_raw_mbr() --- command='%s'", command); if (offer_to_hack_scripts && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) /* interactive mode */ { mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and restoring MBR... "); for (done = FALSE; !done;) { if (!run_program_and_log_output("which vi", FALSE)) { popup_and_OK("You will now edit fstab"); if (!g_text_mode) { newtSuspend(); } sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor); paranoid_system(tmp); if (!g_text_mode) { newtResume(); } // newtCls(); } popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4); sprintf(command, "stabraw-me %s", boot_device); res = run_program_and_log_output(command, 3); if (res) { done = ask_me_yes_or_no("Modifications failed. Re-try?"); } else { done = TRUE; } } } else /* nuke mode */ { mvaddstr_and_log_it(g_currentY, 0, "Restoring MBR... "); res = run_program_and_log_output(command, 3); } if (res) { mvaddstr_and_log_it(g_currentY++, 74, "Failed."); log_to_screen ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE); } else { mvaddstr_and_log_it(g_currentY++, 74, "Done."); } paranoid_free(command); paranoid_free(boot_device); paranoid_free(tmp); paranoid_free(editor); return (res); } /************************************************************************** *END_RUN_RAW_MBR * **************************************************************************/ /** * malloc() and set sensible defaults for the mondorestore filename variables. * @param bkpinfo The backup information structure. Fields used: * - @c bkpinfo->tmpdir * - @c bkpinfo->disaster_recovery */ void setup_MR_global_filenames() { char *temppath; assert(bkpinfo != NULL); malloc_string(g_biggielist_txt); malloc_string(g_filelist_full); malloc_string(g_filelist_imagedevs); malloc_string(g_imagedevs_restthese); malloc_string(g_mondo_cfg_file); malloc_string(g_mountlist_fname); malloc_string(g_mondo_home); /* malloc_string(g_tmpfs_mountpt); */ malloc_string(g_isodir_device); malloc_string(g_isodir_format); temppath = bkpinfo->tmpdir; sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB); sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB); sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath); // sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath); sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", temppath); if (bkpinfo->disaster_recovery) { sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB); sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB); } else { sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB); sprintf(g_mountlist_fname, "%s/%s", temppath, MOUNTLIST_FNAME_STUB); } } /************************************************************************** *END_SET_GLOBAL_FILENAME * **************************************************************************/ /** * Copy @p input_file (containing the result of a compare) to @p output_file, * deleting spurious "changes" along the way. * @param output_file The output file to write with spurious changes removed. * @param input_file The input file, a list of changed files created by a compare. */ void streamline_changes_file(char *output_file, char *input_file) { FILE *fin; FILE *fout; /** malloc **/ char *incoming; assert_string_is_neither_NULL_nor_zerolength(output_file); assert_string_is_neither_NULL_nor_zerolength(input_file); malloc_string(incoming); if (!(fin = fopen(input_file, "r"))) { log_OS_error(input_file); return; } if (!(fout = fopen(output_file, "w"))) { fatal_error("cannot open output_file"); } for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin); fgets(incoming, MAX_STR_LEN - 1, fin)) { if (strncmp(incoming, "etc/adjtime", 11) && strncmp(incoming, "etc/mtab", 8) && strncmp(incoming, "tmp/", 4) && strncmp(incoming, "boot/map", 8) && !strstr(incoming, "incheckentry") && strncmp(incoming, "etc/mail/statistics", 19) && strncmp(incoming, "var/", 4)) fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */ } paranoid_fclose(fout); paranoid_fclose(fin); paranoid_free(incoming); } /************************************************************************** *END_STREAMLINE_CHANGES_FILE * **************************************************************************/ /** * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives. */ void twenty_seconds_til_yikes() { int i; /* MALLOC * */ char *tmp; malloc_string(tmp); if (does_file_exist("/tmp/NOPAUSE")) { return; } open_progress_form("CAUTION", "Be advised: I am about to ERASE your hard disk(s)!", "You may press Ctrl+Alt+Del to abort safely.", "", 20); for (i = 0; i < 20; i++) { g_current_progress = i; sprintf(tmp, "You have %d seconds left to abort.", 20 - i); update_progress_form(tmp); sleep(1); } close_progress_form(); paranoid_free(tmp); } /************************************************************************** *END_TWENTY_SECONDS_TIL_YIKES * **************************************************************************/ /** * Unmount all devices in @p p_external_copy_of_mountlist. * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount. * @return 0 for success, nonzero for failure. */ int unmount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist) { struct mountlist_itself *mountlist; int retval = 0, lino, res = 0, i; char *command; char *tmp = NULL; malloc_string(command); assert(p_external_copy_of_mountlist != NULL); mountlist = malloc(sizeof(struct mountlist_itself)); memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist, sizeof(struct mountlist_itself)); sort_mountlist_by_mountpoint(mountlist, 0); run_program_and_log_output("df -m", 3); mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices "); open_progress_form("Unmounting devices", "Unmounting all devices that were mounted,", "in preparation for the post-restoration reboot.", "", mountlist->entries); chdir("/"); for (i = 0; i < 10 && run_program_and_log_output ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0; i++) { sleep(1); log_msg(2, "Waiting for buffer() to finish"); } paranoid_system("sync"); mr_asprintf(&tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE); if (run_program_and_log_output(tmp, FALSE)) { log_msg(1, "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)"); } paranoid_free(tmp); if (does_file_exist("/tmp/DUMBASS-GENTOO")) { run_program_and_log_output("mkdir -p " MNT_RESTORING "/mnt/.boot.d", 5); } /* Unmounting the local /proc and /sys first */ run_program_and_log_output("umount " MNT_RESTORING "/proc",3); run_program_and_log_output("umount " MNT_RESTORING "/sys",3); for (lino = mountlist->entries - 1; lino >= 0; lino--) { if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) { continue; } mr_asprintf(&tmp, "Unmounting device %s ", mountlist->el[lino].device); update_progress_form(tmp); if (is_this_device_mounted(mountlist->el[lino].device)) { if (!strcmp(mountlist->el[lino].mountpoint, "swap")) { sprintf(command, "swapoff %s", mountlist->el[lino].device); } else { if (!strcmp(mountlist->el[lino].mountpoint, "/1")) { sprintf(command, "umount %s/", MNT_RESTORING); log_msg(3, "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight..."); } else { sprintf(command, "umount " MNT_RESTORING "%s", mountlist->el[lino].mountpoint); /* To support latest Ubuntu where /var is a separate FS * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html * we need to create some dirs under the real / before unmounting it */ if (!strcmp(mountlist->el[lino].mountpoint, "/")) { run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE); run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE); } } } log_msg(10, "The 'umount' command is '%s'", command); res = run_program_and_log_output(command, 3); } else { mr_strcat(tmp, "...not mounted anyway :-) OK"); res = 0; } g_current_progress++; if (res) { mr_strcat(tmp, "...Failed"); retval++; log_to_screen(tmp); } else { log_msg(2, tmp); } paranoid_free(tmp); } close_progress_form(); if (retval) { mvaddstr_and_log_it(g_currentY++, 74, "Failed."); } else { mvaddstr_and_log_it(g_currentY++, 74, "Done."); } if (retval) { log_to_screen("Unable to unmount some of your partitions."); } else { log_to_screen("All partitions were unmounted OK."); } free(mountlist); paranoid_free(command); return (retval); } /************************************************************************** *END_UNMOUNT_ALL_DEVICES * **************************************************************************/ /** * Extract mondo-restore.cfg and the mountlist from the tape inserted * to the ./tmp/ directory. * @param dev The tape device to read from. * @return 0 for success, nonzero for failure. */ int extract_cfg_file_and_mountlist_from_tape_dev(char *dev) { char *command; int res = 0; malloc_string(command); if (bkpinfo->use_obdr) { skip_obdr(); } else { // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); } sprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); log_msg(2, "command = '%s'", command); res = run_program_and_log_output(command, -1); if (res != 0) { if (does_file_exist(MONDO_CFG_FILE_STUB)) { res = 0; } else { /* Doing that allow us to remain compatible with pre-2.2.5 versions */ log_msg(2, "pre-2.2.4 compatible mode on"); sprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); log_msg(2, "command = '%s'", command); res = run_program_and_log_output(command, -1); if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) { res = 0; } } } paranoid_free(command); return (res); } /** * Get the configuration file from the floppy, tape, or CD. * @param bkpinfo The backup information structure. Fields used: * - @c bkpinfo->backup_media_type * - @c bkpinfo->media_device * - @c bkpinfo->tmpdir * @return 0 for success, nonzero for failure. */ int get_cfg_file_from_archive() { int retval = 0; /** malloc *****/ char *device; char *command; char *cfg_file; char *mounted_cfgf_path; char *tmp; char *mountpt; char *ramdisk_fname; char *mountlist_file; bool extract_mountlist_stub = FALSE; bool extract_i_want_my_lvm = FALSE; bool try_plan_B; assert(bkpinfo != NULL); malloc_string(cfg_file); malloc_string(mounted_cfgf_path); malloc_string(mountpt); malloc_string(ramdisk_fname); malloc_string(mountlist_file); malloc_string(device); malloc_string(command); malloc_string(tmp); log_msg(2, "gcffa --- starting"); log_to_screen("I'm thinking..."); sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir); device[0] = '\0'; chdir(bkpinfo->tmpdir); strcpy(cfg_file, MONDO_CFG_FILE_STUB); unlink(cfg_file); // cfg_file[] is missing the '/' at the start, FYI, by intent unlink(FILELIST_FULL_STUB); unlink(BIGGIELIST_TXT_STUB); sprintf(command, "mkdir -p %s", mountpt); run_program_and_log_output(command, FALSE); sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB); sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB); // make_hole_for_file( cfg_file ); // make_hole_for_file( mountlist_file); log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file); if (!does_file_exist(cfg_file)) { log_msg(2, "gcffa --- we don't have cfg file yet."); if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { try_plan_B = TRUE; } else { log_msg(2, "gcffa --- calling mount_media now :)"); if (!mount_media()) { log_msg(2, "gcffa --- managed to mount CD; so, no need for Plan B"); try_plan_B = FALSE; } else { try_plan_B = TRUE; } if (what_number_cd_is_this() > 1) { insist_on_this_cd_number((g_current_media_number = 1)); } } if (try_plan_B) { log_msg(2, "gcffa --- OK, switching to Plan B"); chdir(bkpinfo->tmpdir); run_program_and_log_output("mkdir -p tmp", FALSE); if (strlen(bkpinfo->media_device) == 0) { strcpy(bkpinfo->media_device, "/dev/st0"); log_msg(2, "media_device is blank; assuming %s"); } strcpy(tmp, bkpinfo->media_device); if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) { strcpy(bkpinfo->media_device, "/dev/st0"); if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) { strcpy(bkpinfo->media_device, "/dev/osst0"); if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) { strcpy(bkpinfo->media_device, "/dev/ht0"); if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) { log_msg(3, "I tried lots of devices but none worked."); strcpy(bkpinfo->media_device, tmp); } } } } if (!does_file_exist("tmp/mondo-restore.cfg")) { log_to_screen("Cannot find config info on media"); return (1); } } else { if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) { extract_mountlist_stub = FALSE; } else { extract_mountlist_stub = TRUE; } if (does_file_exist("/"IWANTMYLVM_STUB)) { extract_i_want_my_lvm = FALSE; } else { extract_i_want_my_lvm = TRUE; } log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz"); 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, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary run_program_and_log_output(command, TRUE); if (!does_file_exist(MONDO_CFG_FILE_STUB)) { /* Doing that allow us to remain compatible with pre-2.2.5 versions */ log_msg(2, "pre-2.2.4 compatible mode on"); 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, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary run_program_and_log_output(command, TRUE); if (!does_file_exist(MONDO_CFG_FILE_STUB)) { fatal_error ("Please reinsert the disk/CD and try again."); } } } } if (does_file_exist(MONDO_CFG_FILE_STUB)) { log_msg(1, "gcffa --- great! We've got the config file"); sprintf(tmp, "%s/%s", call_program_and_get_last_line_of_output("pwd"), MONDO_CFG_FILE_STUB); sprintf(command, "cp -f %s %s", tmp, cfg_file); log_it("%s",command); if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) { log_msg(1, "... but an error occurred when I tried to move it to %s", cfg_file); } else { log_msg(1, "... and I moved it successfully to %s", cfg_file); } sprintf(command, "cp -f %s/%s %s", call_program_and_get_last_line_of_output("pwd"), MOUNTLIST_FNAME_STUB, mountlist_file); log_it("%s",command); if (extract_mountlist_stub) { if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) { log_msg(1, "Failed to get mountlist"); } else { log_msg(1, "Got mountlist too"); sprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname); if (run_program_and_log_output(command, 1)) { log_msg(1, "Failed to copy mountlist to /tmp"); } else { log_msg(1, "Copied mountlist to /tmp as well OK"); sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB); run_program_and_log_output(command, 1); } } } } run_program_and_log_output("umount " MNT_CDROM, FALSE); if (!does_file_exist(cfg_file)) { log_it("%s",cfg_file); log_msg(1, "%s not found", cfg_file); log_to_screen ("Oh dear. Unable to recover configuration file from boot disk"); return (1); } log_to_screen("Recovered mondo-restore.cfg"); if (!does_file_exist(MOUNTLIST_FNAME_STUB)) { log_to_screen("...but not mountlist.txt - a pity, really..."); } else { /* Is this code really useful ??? */ if (extract_mountlist_stub) { sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB); run_program_and_log_output(command, FALSE); } } sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB); run_program_and_log_output(command, FALSE); if (extract_mountlist_stub) { sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB); run_program_and_log_output(command, FALSE); } sprintf(command, "cp -f etc/raidtab /etc/"); run_program_and_log_output(command, FALSE); if (extract_i_want_my_lvm) { sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB); run_program_and_log_output(command, FALSE); } g_backup_media_type = bkpinfo->backup_media_type; paranoid_free(device); paranoid_free(command); paranoid_free(tmp); paranoid_free(cfg_file); paranoid_free(mounted_cfgf_path); paranoid_free(mountpt); paranoid_free(ramdisk_fname); paranoid_free(mountlist_file); return (retval); } /************************************************************************** *END_GET_CFG_FILE_FROM_ARCHIVE * **************************************************************************/ /* @} - end restoreUtilityGroup */ /*************************************************************************** * F@ * * () -- Hugo Rabson * * * * Purpose: * * * * Called by: * * Params: - - * * Returns: 0=success; nonzero=failure * ***************************************************************************/ void wait_until_software_raids_are_prepped(char *mdstat_file, int wait_for_percentage) { struct raidlist_itself *raidlist; int unfinished_mdstat_devices = 9999, i; char *screen_message; malloc_string(screen_message); raidlist = malloc(sizeof(struct raidlist_itself)); assert(wait_for_percentage <= 100); log_it("wait_until_software_raids_are_prepped"); while (unfinished_mdstat_devices > 0) { // FIXME: Prefix '/dev/' should really be dynamic! if (parse_mdstat(raidlist, "/dev/")) { log_to_screen("Sorry, cannot read %s", MDSTAT_FILE); log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE); return; } for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) { if (raidlist->el[i].progress < wait_for_percentage) { unfinished_mdstat_devices++; if (raidlist->el[i].progress == -1) // delayed while another partition inits { continue; } log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i); sprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device); open_evalcall_form(screen_message); while (raidlist->el[i].progress < wait_for_percentage) { log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress); update_evalcall_form(raidlist->el[i].progress); sleep(2); // FIXME: Prefix '/dev/' should really be dynamic! if (parse_mdstat(raidlist, "/dev/")) { break; } } close_evalcall_form(); } } } paranoid_free(screen_message); paranoid_free(raidlist); }