/*************************************************************************** $Id: mondoarchive.c 3208 2013-12-10 07:50:00Z bruno $ * The main file for mondoarchive. */ /************************* #include statements *************************/ #include #include #include #include "my-stuff.h" #include "mr_mem.h" #include "mr_str.h" #include "../common/mondostructures.h" #include "../common/libmondo.h" #include "../common/libmondo-cli-EXT.h" #include "../common/libmondo-tools-EXT.h" #include "mondoarchive.h" // for CVS //static char cvsid[] = "$Id: mondoarchive.c 3208 2013-12-10 07:50:00Z bruno $"; /************************* external variables *************************/ extern void set_signals(int); extern int g_current_media_number; extern int g_currentY; extern bool g_text_mode; extern char *g_boot_mountpt; extern bool g_remount_floppy_at_end; extern char *g_cdrw_drive_is_here; static char *g_cdrom_drive_is_here = NULL; static char *g_dvd_drive_is_here = NULL; extern double g_kernel_version; /***************** global vars, used only by main.c ******************/ long diffs = 0L; extern t_bkptype g_backup_media_type; extern int g_loglevel; extern char *g_magicdev_command; /** * Whether we're restoring from ISOs. Obviously not, since this is the * backup program. * @note You @b MUST declare this variable somewhere in your program if * you use libmondo. Otherwise the link will fail. * @ingroup globalGroup */ bool g_ISO_restore_mode = FALSE; /* Whether we should fail immediately at first error */ bool g_fail_immediately = FALSE; /* Do we use extended attributes and acl ? * * By default no, use --acl & --attr options to force their usage */ char *g_getfacl = NULL; char *g_getfattr = NULL; /* Reference to global bkpinfo */ struct s_bkpinfo *bkpinfo; /* No cleanup for the moment */ void (*mr_cleanup)(void) = NULL; /* To be coded */ void free_MR_global_filenames(void) { } /****************** subroutines used only by main.c ******************/ /** * Print a "don't panic" message to the log and a message about the logfile to the screen. */ void welcome_to_mondoarchive(void) { char *tmp = NULL; log_msg(0, "Mondo Archive v%s --- http://www.mondorescue.org", PACKAGE_VERSION); log_msg(0, "running %s binaries", get_architecture()); tmp = get_uname_m(); log_msg(0, "running on %s architecture", tmp); mr_free(tmp); log_msg(0, "-----------------------------------------------------------"); log_msg(0, "NB: Mondo logs almost everything, so don't panic if you see"); log_msg(0, "some error messages. Please read them carefully before you"); log_msg(0, "decide to break out in a cold sweat. Despite (or perhaps"); log_msg(0, "because of) the wealth of messages. some users are inclined"); log_msg(0, "to stop reading this log. If Mondo stopped for some reason,"); log_msg(0, "chances are it's detailed here. More than likely there's a"); log_msg(0, "message at the very end of this log that will tell you what"); log_msg(0, "is wrong. Please read it! -Devteam"); log_msg(0, "-----------------------------------------------------------"); log_msg(0, "Zero..."); log_msg(1, "One..."); log_msg(2, "Two..."); log_msg(3, "Three..."); log_msg(4, "Four..."); log_msg(5, "Five..."); log_msg(6, "Six..."); log_msg(7, "Seven..."); log_msg(8, "Eight..."); printf("See %s for details of backup run.\n", MONDO_LOGFILE); } /** * Do whatever is necessary to insure a successful backup on the Linux distribution * of the day. */ void distro_specific_kludges_at_start_of_mondoarchive(void) { log_msg(2, "Unmounting old ramdisks if necessary"); stop_magicdev_if_necessary(); // for RH+Gnome users /* run_program_and_log_output ("umount `mount | grep shm | grep mondo | cut -d' ' -f3`", 2); */ unmount_supermounts_if_necessary(); // for Mandrake users whose CD-ROMs are supermounted // stop_autofs_if_necessary(); // for Xandros users mount_boot_if_necessary(); // for Gentoo users with non-mounted /boot partitions clean_up_KDE_desktop_if_necessary(); // delete various misc ~/.* files that get in the way } /** * Undo whatever was done by distro_specific_kludges_at_start_of_mondoarchive(). */ void distro_specific_kludges_at_end_of_mondoarchive(void) { log_msg(2, "Restarting magicdev if necessary"); sync(); restart_magicdev_if_necessary(); // for RH+Gnome users log_msg(2, "Restarting autofs if necessary"); sync(); // restart_autofs_if_necessary(); // for Xandros users log_msg(2, "Restarting supermounts if necessary"); sync(); remount_supermounts_if_necessary(); // for Mandrake users log_msg(2, "Unmounting /boot if necessary"); sync(); unmount_boot_if_necessary(); // for Gentoo users // log_msg( 2, "Cleaning up KDE desktop"); // clean_up_KDE_desktop_if_necessary(); } /** * Backup/verify the user's data. * What did you think it did, anyway? :-) */ int main(int argc, char *argv[]) { char *tmp = NULL; char *tmp1 = NULL; int res = 0; int retval = 0; char *say_at_end = NULL; FILE *fin = NULL; /* Make sure I'm root; abort if not */ if (getuid() != 0) { fprintf(stderr, "Please run as root.\r\n"); finish(127); } /* If -V, -v or --version then echo version no. and quit */ if (argc == 2 && (!strcmp(argv[argc - 1], "-v") || !strcmp(argv[argc - 1], "-V") || !strcmp(argv[argc - 1], "--version"))) { printf("mondoarchive v%s\nSee man page for help\n", PACKAGE_VERSION); finish(0); } /* initialize log file with time stamp */ unlink(MONDO_LOGFILE); log_msg(0, "Time started: %s", mr_date()); /* Initialize variables */ if (!(bkpinfo = (struct s_bkpinfo *)malloc(sizeof(struct s_bkpinfo)))) { fprintf(stderr, "Cannot malloc bkpinfo\n"); finish(-1); } log_msg(9, "reset_bkpinfo"); reset_bkpinfo(); /* Memory allocation is done in those functions */ malloc_libmondo_global_strings(); /* make sure PATH environmental variable allows access to mkfs, fdisk, etc. */ mr_asprintf(tmp1,"%s:/sbin:/usr/sbin:/usr/local/sbin",getenv("PATH")); setenv("PATH", tmp1, 1); mr_free(tmp1); /* Add the ARCH environment variable for ia64 purposes */ mr_asprintf(tmp1,"%s",get_architecture()); setenv("ARCH", tmp1, 1); mr_free(tmp1); /* Add MONDO_SHARE environment variable for mindi */ setenv_mondo_share(); /* Configure the bkpinfo structure, global file paths, etc. */ g_main_pid = getpid(); log_msg(9, "This"); set_signals(TRUE); // catch SIGTERM, etc. run_program_and_log_output("dmesg -n1", TRUE); log_msg(9, "Next"); make_hole_for_dir(MONDO_CACHE); welcome_to_mondoarchive(); distro_specific_kludges_at_start_of_mondoarchive(); g_kernel_version = get_kernel_version(); if (argc == 4 && !strcmp(argv[1], "getfattr")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); if (!strstr(argv[2], "filelist")) { printf("Sorry - filelist goes first\n"); finish(1); } else { finish(get_fattr_list(argv[2], argv[3])); } finish(0); } if (argc == 4 && !strcmp(argv[1], "setfattr")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); finish(set_fattr_list(argv[2], argv[3])); } if (argc == 3 && !strcmp(argv[1], "wildcards")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); tmp1 = mr_stresc(argv[2], "[]*?", '\\', '\''); printf("in=%s; out=%s\n", argv[2], tmp1); mr_free(tmp1); finish(1); } if (argc == 4 && !strcmp(argv[1], "getfacl")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); if (!strstr(argv[2], "filelist")) { printf("Sorry - filelist goes first\n"); finish(1); } else { finish(get_acl_list(argv[2], argv[3])); } finish(0); } if (argc == 4 && !strcmp(argv[1], "setfacl")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); finish(set_acl_list(argv[2], argv[3])); } if (argc >= 2 && !strcmp(argv[1], "mkraidtab")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); #undef MDSTAT_FILE #define MDSTAT_FILE "/tmp/mdstat" if (!(fin = fopen(MDSTAT_FILE, "r"))) { log_msg(1, "Could not open %s.\n", MDSTAT_FILE); finish(1); } create_raidtab_from_mdstat(MDSTAT_FILE,"/tmp/raidtab"); finish(0); } if (argc > 2 && !strcmp(argv[1], "find-cd")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); malloc_string(tmp); if (find_cdrw_device(tmp)) { printf("Failed to find CDR-RW drive\n"); } else { printf("CD-RW is at %s\n", tmp); } tmp[0] = '\0'; if (find_cdrom_device(tmp, atoi(argv[2]))) { printf("Failed to find CD-ROM drive\n"); } else { printf("CD-ROM is at %s\n", tmp); } mr_free(tmp); finish(0); } if (argc > 2 && !strcmp(argv[1], "find-dvd")) { g_loglevel = 10; g_text_mode = TRUE; setup_newt_stuff(); malloc_string(tmp); if (find_dvd_device(tmp, atoi(argv[2]))) { printf("Failed to find DVD drive\n"); } else { printf("DVD is at %s\n", tmp); } mr_free(tmp); finish(0); } if (argc > 2 && !strcmp(argv[1], "disksize")) { printf("%s --> %ld\n", argv[2], get_phys_size_of_drive(argv[2])); finish(0); } if (argc > 2 && !strcmp(argv[1], "test-dev")) { if (is_dev_an_NTFS_dev(argv[2])) { printf("%s is indeed an NTFS dev\n", argv[2]); } else { printf("%s is _not_ an NTFS dev\n", argv[2]); } finish(0); } if (pre_param_configuration()) { fatal_error("Pre-param initialization phase failed. Please review the error messages above, make the specified changes, then try again. Exiting..."); } /* Process command line, if there is one. If not, ask user for info. */ if (argc == 1) { g_text_mode = FALSE; setup_newt_stuff(); res = interactively_obtain_media_parameters_from_user(TRUE); /* yes, archiving */ if (res) { fatal_error("Syntax error. Please review the parameters you have supplied and try again."); } } else { res = handle_incoming_parameters(argc, argv); if (res) { printf("Errors were detected in the command line you supplied.\n"); printf("Please review the log file - %s\n", MONDO_LOGFILE ); log_msg(1, "Mondoarchive will now exit."); finish(1); } setup_newt_stuff(); } /* Finish configuring global structures */ if (post_param_configuration()) { fatal_error("Post-param initialization phase failed. Perhaps bad parameters were supplied to mondoarchive? Please review the documentation, error messages and logs. Exiting..."); } /* If we're meant to backup then backup */ if (bkpinfo->backup_data) { res = backup_data(); retval += res; if (res) { mr_asprintf(say_at_end, "Data archived. Please check the logs, just as a precaution. "); } else { mr_asprintf(say_at_end, "Data archived OK. "); } } /* If we're meant to verify then verify */ if (bkpinfo->verify_data) { res = verify_data(); if (res < 0) { mr_asprintf(tmp, "%d difference%c found.", -res, (-res != 1) ? 's' : ' '); mr_asprintf(say_at_end, "%s", tmp); log_to_screen(tmp); mr_free(tmp); res = 0; } retval += res; } /* Report result of entire operation (success? errors?) */ if (!retval) { mvaddstr_and_log_it(g_currentY++, 0, "Backup and/or verify ran to completion. Everything appears to be fine."); } else { mvaddstr_and_log_it(g_currentY++, 0, "Backup and/or verify ran to completion. However, errors did occur."); } if (does_file_exist(MINDI_CACHE"/mondorescue.iso")) { log_to_screen (MINDI_CACHE"/mondorescue.iso, a boot/utility CD, is available if you want it."); } if (length_of_file(MONDO_CACHE"/changed.files") > 2) { if (g_text_mode) { log_to_screen("Type 'less "MONDO_CACHE"/changed.files' to see which files don't match the archives"); } else { log_msg(1, "Type 'less "MONDO_CACHE"/changed.files' to see which files don't match the archives"); log_msg(2, "Calling popup_changelist_from_file()"); popup_changelist_from_file(MONDO_CACHE"/changed.files"); log_msg(2, "Returned from popup_changelist_from_file()"); } } else { unlink(MONDO_CACHE"/changed.files"); } if (say_at_end != NULL) { log_to_screen(say_at_end); mr_free(say_at_end); } mr_asprintf(tmp, "umount %s/tmpfs", bkpinfo->tmpdir); run_program_and_log_output(tmp, TRUE); mr_free(tmp); if (bkpinfo->backup_media_type == usb) { log_msg(1, "Unmounting USB device."); if (bkpinfo->media_device == NULL) { fatal_error("USB device set to NULL"); } mr_asprintf(tmp, "umount %s1", bkpinfo->media_device); run_program_and_log_output(tmp, TRUE); mr_free(tmp); } run_program_and_log_output("mount", 2); paranoid_system("rm -f "MONDO_CACHE"/last-backup.aborted"); if (!retval) { printf("Mondoarchive ran OK.\n"); } else { printf("Errors occurred during backup. Please check logfile.\n"); } distro_specific_kludges_at_end_of_mondoarchive(); set_signals(FALSE); free_libmondo_global_strings(); if (!g_cdrom_drive_is_here) { log_msg(10, "FYI, g_cdrom_drive_is_here was never used"); } if (!g_dvd_drive_is_here) { log_msg(10, "FYI, g_dvd_drive_is_here was never used"); } /* finalize log file with time stamp */ log_msg(0, "Time finished: %s", mr_date()); if (chdir("/tmp")) { // FIXME } if (!g_text_mode) { popup_and_OK("Mondo Archive has finished its run. Please press ENTER to return to the shell prompt."); log_to_screen("See %s for details of backup run.", MONDO_LOGFILE); } else { printf("See %s for details of backup run.\n", MONDO_LOGFILE); } finish(retval); return EXIT_SUCCESS; }