Changeset 3878 in MondoRescue for branches/3.3/mondo/src
- Timestamp:
- Mar 8, 2024, 12:15:10 PM (4 months ago)
- Location:
- branches/3.3/mondo/src/common
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mondo/src/common/libmondo-archive.c
r3877 r3878 317 317 318 318 319 320 321 322 /**323 * Finalize the backup.324 * For streaming backups, this writes the closing block325 * to the stream. For CD-based backups, this creates326 * the final ISO image.327 * @param bkpinfo The backup information structure, used only328 * for the @c backup_media_type.329 * @ingroup MLarchiveGroup330 */331 int do_that_final_phase()332 {333 334 /*@ int ************************************** */335 int res = 0;336 int retval = 0;337 338 /*@ buffers ********************************** */339 340 assert(bkpinfo != NULL);341 mvaddstr_and_log_it(g_currentY, 0,342 "Writing any remaining data to media ");343 344 log_msg(1, "Closing tape/CD/USB ... ");345 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {346 /* write tape/cdstream */347 closeout_tape();348 } else {349 /* write final ISO/USB */350 res = write_final_iso_if_necessary();351 retval += res;352 if (res) {353 log_msg(1, "write_final_iso_if_necessary returned an error");354 }355 }356 log_msg(2, "Fork is exiting ... ");357 358 mvaddstr_and_log_it(g_currentY++, 74, "Done.");359 360 /* final stuff */361 if (retval) {362 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");363 } else {364 mvaddstr_and_log_it(g_currentY++, 74, "Done.");365 }366 367 return (retval);368 }369 370 /**371 * Wrapper around @c make_slices_and_images().372 * @param bkpinfo The backup information structure. Fields used:373 * - @c backup_media_type374 * - @c scratchdir375 * - @c tmpdir376 * @return The number of errors encountered (0 for success)377 * @ingroup MLarchiveGroup378 */379 int make_those_slices_phase()380 {381 382 /*@ int ***************************************************** */383 int res = 0;384 int retval = 0;385 386 /*@ buffers ************************************************** */387 char *biggielist = NULL;388 char *command = NULL;389 char *blah = NULL;390 char *xattr_fname = NULL;391 char *acl_fname = NULL;392 393 assert(bkpinfo != NULL);394 /* slice big files */395 mvaddstr_and_log_it(g_currentY, 0, "Archiving large files to media ");396 mr_asprintf(biggielist, "%s/archives/biggielist.txt", bkpinfo->scratchdir);397 if (g_getfattr) {398 mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);399 }400 if (g_getfacl) {401 mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);402 }403 404 mr_asprintf(command, "cp %s/biggielist.txt %s", bkpinfo->tmpdir, biggielist);405 paranoid_system(command);406 mr_free(command);407 408 mr_asprintf(blah, "biggielist = %s", biggielist);409 log_msg(2, blah);410 mr_free(blah);411 412 if (!does_file_exist(biggielist)) {413 log_msg(1, "BTW, the biggielist does not exist");414 }415 416 if (g_getfattr) {417 get_fattr_list(biggielist, xattr_fname);418 mr_asprintf(command, "cp %s %s/archives/", xattr_fname, bkpinfo->scratchdir);419 paranoid_system(command);420 mr_free(command);421 }422 if (g_getfacl) {423 get_acl_list(biggielist, acl_fname);424 mr_asprintf(command, "cp %s %s/archives/", acl_fname, bkpinfo->scratchdir);425 paranoid_system(command);426 mr_free(command);427 }428 429 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {430 res += write_EXAT_files_to_tape(xattr_fname, acl_fname);431 mr_asprintf(blah, "%ld", count_lines_in_file(biggielist));432 write_header_block_to_stream((off_t)0, blah, BLK_START_BIGGIEFILES);433 mr_free(blah);434 }435 res = make_slices_and_images(biggielist);436 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {437 write_header_block_to_stream((off_t)0, "end-of-biggiefiles", BLK_STOP_BIGGIEFILES);438 }439 retval += res;440 if (res) {441 log_msg(1, "make_slices_and_images returned an error");442 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");443 } else {444 mvaddstr_and_log_it(g_currentY++, 74, "Done.");445 }446 mr_free(biggielist);447 mr_free(xattr_fname);448 mr_free(acl_fname);449 return (retval);450 }451 452 453 454 /**455 * Wrapper around @c make_afioballs_and_images().456 * @param bkpinfo the backup information structure. Only the457 * @c backup_media_type field is used within this function.458 * @return return code of make_afioballs_and_images459 * @see make_afioballs_and_images460 * @ingroup MLarchiveGroup461 */462 int make_those_afios_phase()463 {464 /*@ int ******************************************* */465 int res = 0;466 int retval = 0;467 468 assert(bkpinfo != NULL);469 470 mvaddstr_and_log_it(g_currentY, 0, "Archiving regular files to media ");471 472 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {473 write_header_block_to_stream((off_t)0, "start-of-afioballs", BLK_START_AFIOBALLS);474 #if __FreeBSD__ == 5475 log_msg(1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0");476 res = make_afioballs_and_images_OLD();477 #else478 res = make_afioballs_and_images_OLD();479 #endif480 write_header_block_to_stream((off_t)0, "stop-afioballs", BLK_STOP_AFIOBALLS);481 } else {482 res = make_afioballs_and_images();483 }484 485 retval += res;486 if (res) {487 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");488 log_msg(1, "make_afioballs_and_images returned an error");489 } else {490 mvaddstr_and_log_it(g_currentY++, 74, "Done.");491 }492 return (retval);493 }494 495 496 497 /**498 * Wrapper function for all the backup commands.499 * Calls these other functions: @c prepare_filelist(),500 * @c call_filelist_chopper(), @c copy_mondo_and_mindi_stuff_to_scratchdir(),501 * @c call_mindi_to_supply_boot_disks(), @c do_that_initial_phase(),502 * @c make_those_afios_phase(), @c make_those_slices_phase(), and503 * @c do_that_final_phase(). If anything fails before @c do_that_initial_phase(),504 * @c fatal_error is called with a suitable message.505 * @param bkpinfo The backup information structure. Uses most fields.506 * @return The number of non-fatal errors encountered (0 for success).507 * @ingroup archiveGroup508 */509 int backup_data()510 {511 int retval = 0, res = 0;512 char *tmp = NULL;513 514 assert(bkpinfo != NULL);515 set_g_cdrom_and_g_dvd_to_bkpinfo_value();516 517 if (bkpinfo->backup_media_type == dvd) {518 #ifdef DVDRWFORMAT519 if ((tmp = find_home_of_exe("dvd+rw-format")) == NULL) {520 mr_free(tmp);521 fatal_error("Cannot find dvd+rw-format. Please install it or fix your PATH.");522 }523 mr_free(tmp);524 #endif525 if ((tmp = find_home_of_exe("growisofs")) == NULL) {526 mr_free(tmp);527 fatal_error("Cannot find growisofs. Please install it or fix your PATH.");528 }529 mr_free(tmp);530 }531 532 if ((res = prepare_filelist())) { /* generate scratchdir/filelist.full */533 fatal_error("Failed to generate filelist catalog");534 }535 if (call_filelist_chopper()) {536 fatal_error("Failed to run filelist chopper");537 }538 539 mr_asprintf(tmp, "gzip -9 %s/archives/filelist.full", bkpinfo->scratchdir);540 if (run_program_and_log_output(tmp, 2)) {541 mr_free(tmp);542 fatal_error("Failed to gzip filelist.full");543 }544 mr_free(tmp);545 546 mr_asprintf(tmp, "cp -f %s/archives/*list*.gz %s", bkpinfo->scratchdir, bkpinfo->tmpdir);547 if (run_program_and_log_output(tmp, 2)) {548 mr_free(tmp);549 fatal_error("Failed to copy to tmpdir");550 }551 mr_free(tmp);552 553 copy_mondo_and_mindi_stuff_to_scratchdir(); // payload, too, if it exists554 if ((res = call_mindi_to_supply_boot_disks())) {555 fatal_error("Failed to generate boot+data disks");556 }557 retval += do_that_initial_phase(); // prepare558 mr_asprintf(tmp, "rm -f %s/images/*.iso", bkpinfo->scratchdir);559 run_program_and_log_output(tmp, 1);560 mr_free(tmp);561 562 retval += make_those_afios_phase(); // backup regular files563 retval += make_those_slices_phase(); // backup BIG files564 retval += do_that_final_phase(); // clean up565 log_msg(1, "Creation of archives... complete.");566 if (bkpinfo->verify_data) {567 sleep(2);568 }569 return (retval);570 }571 572 573 574 575 /**576 * Call Mindi to generate boot and data disks.577 * @note This binds correctly to the new Perl version of mindi.578 * @param bkpinfo The backup information structure. Fields used:579 * - @c backup_media_type580 * - @c boot_loader581 * - @c boot_device582 * - @c compression_level583 * - @c differential584 * - @c image_devs585 * - @c kernel_path586 * - @c make_cd_use_lilo587 * - @c media_device588 * - @c media_size589 * - @c nonbootable_backup590 * - @c scratchdir591 * - @c tmpdir592 * - @c use_lzo593 *594 * @return The number of errors encountered (0 for success)595 * @bug The code to automagically determine the boot drive596 * is messy and system-dependent. In particular, it breaks597 * for Linux RAID and LVM users.598 * @ingroup MLarchiveGroup599 */600 int call_mindi_to_supply_boot_disks()601 {602 /*@ buffer ************************************************************ */603 char *tmp = NULL;604 char *tmp1 = NULL;605 char *tmp2 = NULL;606 char *command = NULL;607 char *use_lzo_sz = NULL;608 char *use_gzip_sz = NULL;609 char *use_lzma_sz = NULL;610 char *use_comp_sz = NULL;611 char *use_star_sz = NULL;612 char *bootldr_str = NULL;613 char *bootldr_ver = NULL;614 char *boot_type = NULL;615 char *tape_device = NULL;616 char *last_filelist_number = NULL;617 char *broken_bios_sz = NULL;618 char *cd_recovery_sz = NULL;619 char *tape_size_sz = NULL;620 char *use_lilo_sz = NULL; /* TODO: shared between LILO/ELILO */621 char *value = NULL;622 char *bootdev = NULL;623 char *ntapedev = NULL;624 625 626 627 /*@ char ************************************************************** */628 char ch = '\0';629 630 /*@ long ********************************************************** */631 long lines_in_filelist = 0L;632 633 /*@ int ************************************************************* */634 int res = 0;635 long estimated_total_noof_slices = 0L;636 637 assert(bkpinfo != NULL);638 639 mvaddstr_and_log_it(g_currentY, 0, "Calling MINDI to create boot+data disks");640 open_evalcall_form("Calling MINDI to create boot+data disks");641 mr_asprintf(tmp, "%s/filelist.full", bkpinfo->tmpdir);642 if (!does_file_exist(tmp)) {643 mr_free(tmp);644 mr_asprintf(tmp, "%s/tmpfs/filelist.full", bkpinfo->tmpdir);645 if (!does_file_exist(tmp)) {646 mr_free(tmp);647 fatal_error ("Cannot find filelist.full, so I cannot count its lines");648 }649 }650 lines_in_filelist = count_lines_in_file(tmp);651 mr_free(tmp);652 653 mr_asprintf(tmp, "%s/LAST-FILELIST-NUMBER", bkpinfo->tmpdir);654 mr_asprintf(last_filelist_number, "%s", last_line_of_file(tmp));655 mr_free(tmp);656 657 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {658 mr_asprintf(tape_size_sz, "%ld", bkpinfo->media_size);659 ntapedev = get_non_rewind_dev(bkpinfo->media_device);660 if ((bkpinfo->use_obdr) && (ntapedev != NULL)) {661 mr_asprintf(bkpinfo->media_device, "%s", ntapedev);662 } else {663 if (ntapedev == NULL) {664 log_it("Not able to create OBDR - Restore will have to be done manually");665 }666 }667 mr_free(ntapedev);668 mr_asprintf(tape_device, "%s", bkpinfo->media_device);669 } else {670 mr_asprintf(tape_size_sz, "%ld", 0L);;671 mr_asprintf(tape_device, "");672 }673 if (bkpinfo->use_lzo) {674 mr_asprintf(use_lzo_sz, "yes");675 } else {676 mr_asprintf(use_lzo_sz, "no");677 }678 if (bkpinfo->use_gzip) {679 mr_asprintf(use_gzip_sz, "yes");680 } else {681 mr_asprintf(use_gzip_sz, "no");682 }683 if (bkpinfo->use_lzma) {684 mr_asprintf(use_lzma_sz, "yes");685 } else {686 mr_asprintf(use_lzma_sz, "no");687 }688 if (bkpinfo->use_star) {689 mr_asprintf(use_star_sz, "yes");690 } else {691 mr_asprintf(use_star_sz, "no");692 }693 694 if (bkpinfo->compression_level > 0) {695 mr_asprintf(use_comp_sz, "yes");696 } else {697 mr_asprintf(use_comp_sz, "no");698 }699 700 mr_asprintf(broken_bios_sz, "yes"); /* assume so */701 if (g_cd_recovery) {702 mr_asprintf(cd_recovery_sz, "yes");703 } else {704 mr_asprintf(cd_recovery_sz, "no");705 }706 if (bkpinfo->make_cd_use_lilo) {707 mr_asprintf(use_lilo_sz, "yes");708 } else {709 mr_asprintf(use_lilo_sz, "no");710 }711 if (bkpinfo->boot_type == UEFI) {712 mr_asprintf(boot_type, "UEFI");713 } else if (bkpinfo->boot_type == EFI) {714 mr_asprintf(boot_type, "EFI");715 } else if (bkpinfo->boot_type == BIOS) {716 mr_asprintf(boot_type, "BIOS");717 } else {718 mr_asprintf(boot_type, "UNKNOWN");719 }720 721 update_evalcall_form(2);722 if (!bkpinfo->nonbootable_backup && (bkpinfo->boot_loader == '\0' || bkpinfo->boot_device == NULL)) {723 724 #ifdef __FreeBSD__725 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'");726 if (!bootdev[0]) {727 mr_free(bootdev);728 bootdev = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'");729 }730 #else731 /* Linux */732 #ifdef __IA64__733 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot/efi ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'");734 #else735 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'");736 #endif737 if (strstr(bootdev, "/dev/cciss/")) {738 mr_free(bootdev);739 #ifdef __IA64__740 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot/efi ' | head -1 | cut -d' ' -f1 | cut -dp -f1");741 #else742 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | cut -dp -f1");743 #endif744 }745 if (!bootdev[0]) {746 mr_free(bootdev);747 bootdev = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'");748 if (strstr(bootdev, "/dev/cciss/")) {749 mr_free(bootdev);750 bootdev = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | cut -dp -f1");751 }752 }753 /* Linux */754 #endif755 if (bootdev[0])756 ch = which_boot_loader(bootdev);757 else758 ch = 'U';759 if (bkpinfo->boot_loader != '\0') {760 log_msg(2, "User specified boot loader. It is '%c'.", bkpinfo->boot_loader);761 } else {762 bkpinfo->boot_loader = ch;763 }764 if (bkpinfo->boot_device != NULL) {765 log_msg(2, "User specified boot device. It is '%s'.", bkpinfo->boot_device);766 } else {767 mr_asprintf(bkpinfo->boot_device, "%s", bootdev);768 }769 }770 mr_free(bootdev);771 772 if (773 #ifdef __FreeBSD__774 bkpinfo->boot_loader != 'B' && bkpinfo->boot_loader != 'D' &&775 #endif776 #ifdef __IA64__777 bkpinfo->boot_loader != 'E' &&778 #endif779 bkpinfo->boot_loader != 'L' && bkpinfo->boot_loader != 'G' && bkpinfo->boot_loader != 'R' && !bkpinfo->nonbootable_backup) {780 fatal_error("Please specify your boot loader and device, e.g. -l GRUB -f /dev/hda. Type 'man mondoarchive' to read the manual.");781 }782 if (bkpinfo->boot_loader == 'L') {783 mr_asprintf(bootldr_str, "LILO");784 if (!does_file_exist("/etc/lilo.conf")) {785 mr_free(bootldr_str);786 fatal_error("The de facto standard location for your boot loader's config file is /etc/lilo.conf but I cannot find it there. What is wrong with your Linux distribution?");787 }788 } else if (bkpinfo->boot_loader == 'G') {789 mr_asprintf(bootldr_str, "GRUB");790 if (!does_file_exist("/boot/grub/menu.lst") && does_file_exist("/boot/grub/grub.conf")) {791 run_program_and_log_output("ln -sf /boot/grub/grub.conf /boot/grub/menu.lst", 5);792 }793 if ((!does_file_exist("/boot/grub/menu.lst")) && (!does_file_exist("/boot/grub/grub.cfg")) && (!does_file_exist("/boot/grub2/grub.cfg"))) {794 /* if UEFI then search under /boot/efi */795 tmp = call_program_and_get_last_line_of_output("find /boot/efi -name grub.c*");796 if (strstr(tmp, "grub.c") == NULL) {797 mr_free(bootldr_str);798 fatal_error("The de facto standard location for your boot loader's config file is /boot/grub/menu.lst, /boot/grub/grub.cfg, or /boot/grub2/grub.cfg /boot/efi/.../grub.cfg but I cannot find it there. What is wrong with your Linux distribution?");799 }800 mr_free(tmp);801 }802 bootldr_ver = call_program_and_get_last_line_of_output("grub --version 2> /dev/null");803 if (strcmp(bootldr_ver,"") == 0) {804 mr_free(bootldr_ver);805 bootldr_ver = call_program_and_get_last_line_of_output("grub2-install --version");806 }807 } else if (bkpinfo->boot_loader == 'E') {808 mr_asprintf(bootldr_str, "ELILO");809 /* TODO: fix it for Debian, Mageia, ... */810 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/redhat/elilo.conf")) {811 run_program_and_log_output("ln -sf /boot/efi/efi/redhat/elilo.conf /etc/elilo.conf", 5);812 }813 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/SuSE/elilo.conf")) {814 run_program_and_log_output("ln -sf /boot/efi/efi/SuSE/elilo.conf /etc/elilo.conf", 5);815 }816 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/debian/elilo.conf")) {817 run_program_and_log_output ("ln -sf /boot/efi/efi/debian/elilo.conf /etc/elilo.conf", 5);818 }819 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/debian/elilo.conf")) {820 run_program_and_log_output ("ln -sf /boot/efi/debian/elilo.conf /etc/elilo.conf", 5);821 }822 if (!does_file_exist("/etc/elilo.conf")) {823 mr_free(bootldr_str);824 fatal_error("The de facto mondo standard location for your boot loader's config file is /etc/elilo.conf but I cannot find it there. What is wrong with your Linux distribution? Try finding it under /boot/efi and do 'ln -s /boot/efi/..../elilo.conf /etc/elilo.conf'");825 }826 } else if (bkpinfo->boot_loader == 'R') {827 mr_asprintf(bootldr_str, "RAW");828 }829 #ifdef __FreeBSD__830 else if (bkpinfo->boot_loader == 'D') {831 mr_asprintf(bootldr_str, "DD");832 }833 834 else if (bkpinfo->boot_loader == 'B') {835 mr_asprintf(bootldr_str, "BOOT0");836 }837 #endif838 else {839 mr_asprintf(bootldr_str, "unknown");840 }841 log_to_screen("Your boot loader is %s and it boots from %s", bootldr_str, bkpinfo->boot_device);842 843 if (bootldr_ver != NULL) {844 log_to_screen("Boot loader version string: %s", bootldr_ver);845 }846 847 mr_asprintf(tmp, "%s/BOOTLOADER.DEVICE", bkpinfo->tmpdir);848 if (write_one_liner_data_file(tmp, bkpinfo->boot_device)) {849 log_msg(1, "%ld: Unable to write one-liner boot device", __LINE__);850 }851 mr_free(tmp);852 853 switch (bkpinfo->backup_media_type) {854 case cdr:855 mr_asprintf(value, "cdr");856 break;857 case cdstream:858 mr_asprintf(value, "cdstream");859 break;860 case tape:861 mr_asprintf(value, "tape");862 break;863 case udev:864 mr_asprintf(value, "udev");865 break;866 case iso:867 mr_asprintf(value, "iso");868 break;869 case netfs:870 mr_asprintf(value, "netfs");871 break;872 case dvd:873 mr_asprintf(value, "dvd");874 break;875 case usb:876 mr_asprintf(value, "usb");877 break;878 default:879 fatal_error("Unknown backup_media_type");880 }881 882 if ((bkpinfo->backup_media_type == usb) && (bkpinfo->media_device)) {883 mr_asprintf(tmp2, "--usb %s", bkpinfo->media_device);884 } else {885 mr_asprintf(tmp2," ");886 }887 888 mr_asprintf(tmp, "%s/BACKUP-MEDIA-TYPE", bkpinfo->tmpdir);889 if (write_one_liner_data_file(tmp, value)) {890 res++;891 log_msg(1, "%ld: Unable to write one-liner backup-media-type", __LINE__);892 }893 mr_free(tmp);894 895 mr_asprintf(tmp, "%s/BOOTLOADER.NAME", bkpinfo->tmpdir);896 if (write_one_liner_data_file(tmp, bootldr_str)) {897 res++;898 log_msg(1, "%ld: Unable to write one-liner bootloader.name", __LINE__);899 }900 mr_free(bootldr_str);901 mr_free(tmp);902 903 mr_asprintf(tmp, "%s/BOOTLOADER.VER", bkpinfo->tmpdir);904 if (write_one_liner_data_file(tmp, bootldr_ver)) {905 res++;906 log_msg(1, "%ld: Unable to write one-liner bootloader.ver", __LINE__);907 }908 mr_free(bootldr_ver);909 mr_free(tmp);910 911 mr_asprintf(tmp, "%s/DIFFERENTIAL", bkpinfo->tmpdir);912 if (bkpinfo->differential) {913 res += write_one_liner_data_file(tmp, "1");914 } else {915 res += write_one_liner_data_file(tmp, "0");916 }917 mr_free(tmp);918 919 if (g_getfattr) {920 mr_asprintf(tmp1, "%s/XATTR", bkpinfo->tmpdir);921 if (write_one_liner_data_file(tmp1, "TRUE")) {922 log_msg(1, "%ld: Unable to write one-liner XATTR", __LINE__);923 }924 mr_free(tmp1);925 }926 if (g_getfacl) {927 mr_asprintf(tmp1, "%s/ACL", bkpinfo->tmpdir);928 if (write_one_liner_data_file(tmp1, "TRUE")) {929 log_msg(1, "%ld: Unable to write one-liner ACL", __LINE__);930 }931 mr_free(tmp1);932 }933 if (bkpinfo->use_obdr) {934 mr_asprintf(tmp1, "%s/OBDR", bkpinfo->tmpdir);935 if (write_one_liner_data_file(tmp1, "TRUE")) {936 log_msg(1, "%ld: Unable to write one-liner OBDR", __LINE__);937 }938 mr_free(tmp1);939 }940 941 estimated_total_noof_slices = size_of_all_biggiefiles_K() / bkpinfo->optimal_set_size + 1L;942 943 /* TODO: add netfs stuff here? */944 mr_asprintf(command, "mkdir -p %s/images", bkpinfo->scratchdir);945 if (system(command)) {946 res++;947 log_OS_error("Unable to make images directory");948 }949 mr_free(command);950 log_msg(1, "lines_in_filelist = %ld", lines_in_filelist);951 update_evalcall_form(3);952 953 unlink(MINDI_RUNFILE);954 mr_asprintf(command, "mindi %s --custom %s %s/images '%s' '%s' '%s' '%ld' '%s' '%s' '%s' '%s' '%s' '%ld' '%s' '%s' '%s' '%s' '%ld' '%d' '%s' '%s' '%s' '%s' 2>&1 >> %s",955 // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24956 tmp2, // parameter #1957 bkpinfo->tmpdir, // parameter #2958 bkpinfo->scratchdir, // parameter #3959 bkpinfo->kernel_path, // parameter #4960 tape_device, // parameter #5961 tape_size_sz, // parameter #6962 lines_in_filelist, // parameter #7 (INT)963 use_lzo_sz, // parameter #8964 cd_recovery_sz, // parameter #9965 (bkpinfo->image_devs == NULL) ? "\"\"" : bkpinfo->image_devs,966 // parameter #10967 broken_bios_sz, // parameter #11968 last_filelist_number, // parameter #12 (STRING)969 estimated_total_noof_slices,970 // parameter #13 (INT)971 (bkpinfo->exclude_devs == NULL) ? "\"\"" : bkpinfo->exclude_devs,972 // parameter #14973 use_comp_sz, // parameter #15974 use_lilo_sz, // parameter #16975 use_star_sz, // parameter #17976 bkpinfo->internal_tape_block_size,977 // parameter #18 (LONG)978 bkpinfo->differential, // parameter #19 (INT)979 use_gzip_sz, // parameter #20 (STRING)980 use_lzma_sz, // parameter #21 (STRING)981 "no", // parameter #22 (STRING) bootable image ?982 boot_type, // parameter #23 (STRING)983 MINDI_RUNFILE // redirect to log file (#24)984 );985 986 mr_free(tmp2);987 mr_free(tape_device);988 mr_free(tape_size_sz);989 mr_free(use_lzo_sz);990 mr_free(boot_type);991 mr_free(cd_recovery_sz);992 mr_free(broken_bios_sz);993 mr_free(last_filelist_number);994 mr_free(use_comp_sz);995 mr_free(use_lilo_sz);996 mr_free(use_star_sz);997 mr_free(use_gzip_sz);998 mr_free(use_lzma_sz);999 mr_free(value);1000 1001 /* This parameter is always the last one and optional */1002 if (bkpinfo->nonbootable_backup) {1003 mr_strcat(command, " NONBOOTABLE");1004 }1005 log_msg(2, command);1006 1007 // TODO old call :1008 //res = run_program_and_log_output(command, FALSE);1009 log_msg(1, "Call to mindi");1010 log_msg(1, "-------------");1011 res = run_external_binary_with_percentage_indicator_NEW("Calling MINDI for boot disk",command);1012 /* May crash now that we changed the call1013 update_evalcall_form(99);1014 */1015 paranoid_free(command);1016 log_msg(1, "-------------");1017 log_msg(1, "End of call to mindi");1018 1019 if (bkpinfo->nonbootable_backup) {1020 res = 0;1021 } // hack1022 if (!res) {1023 log_to_screen("Boot+data disks were created OK");1024 1025 if (bkpinfo->nonbootable_backup) {1026 mr_asprintf(command, "cp -f %s/all.tar.gz %s/images", bkpinfo->tmpdir, bkpinfo->scratchdir);1027 if (system(command)) {1028 mr_free(command);1029 fatal_error("Unable to create temporary all tarball");1030 }1031 mr_free(command);1032 }1033 /* For USB we already have everything on the key */1034 if (bkpinfo->backup_media_type == usb) {1035 mr_asprintf(command, "rm -rf %s/images", bkpinfo->scratchdir);1036 run_program_and_log_output(command, FALSE);1037 mr_free(command);1038 } else {1039 mr_asprintf(tmp, "cp -f %s/images/all.tar.gz %s", bkpinfo->scratchdir, bkpinfo->tmpdir);1040 if (system(tmp)) {1041 fatal_error("Cannot find all.tar.gz in tmpdir");1042 }1043 mr_free(tmp);1044 }1045 if (res) {1046 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");1047 } else {1048 mvaddstr_and_log_it(g_currentY++, 74, "Done.");1049 }1050 } else {1051 log_to_screen("Mindi failed to create your boot+data disks.");1052 mr_asprintf(command, "grep 'Fatal error' %s", MINDI_LOGFILE);1053 tmp = call_program_and_get_last_line_of_output(command);1054 mr_free(command);1055 1056 if (strlen(tmp) > 1) {1057 popup_and_OK(tmp);1058 }1059 mr_free(tmp);1060 }1061 close_evalcall_form();1062 return (res);1063 }1064 1065 1066 /**1067 * Set the <tt>N</tt>th bit of @c array to @c true_or_false.1068 * @param array The bit array (as a @c char pointer).1069 * @param N The bit number to set or reset.1070 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.1071 * @see get_bit_N_of_array1072 */1073 void set_bit_N_of_array(char *array, int N, bool true_or_false)1074 {1075 int bit_number;1076 int mask, orig_val, to_add;1077 int element_number;1078 1079 assert(array != NULL);1080 1081 element_number = N / 8;1082 bit_number = N % 8;1083 to_add = (1 << bit_number);1084 mask = 255 - to_add;1085 orig_val = array[element_number] & mask;1086 // log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);1087 if (true_or_false) {1088 array[element_number] = orig_val | to_add;1089 }1090 }1091 1092 1093 1094 /**1095 * Maximum number of filesets allowed in this function.1096 */1097 #define MAX_NOOF_SETS_HERE 327671098 1099 /**1100 * Offset of the bkpinfo pointer (in bytes) from the1101 * buffer passed to create_afio_files_in_background.1102 */1103 #define BKPINFO_LOC_OFFSET (16+MAX_NOOF_SETS_HERE/8+16)1104 1105 /**1106 * Main function for each @c afio thread.1107 * @param inbuf A transfer block containing:1108 * - @c p_last_set_archived: [offset 0] pointer to an @c int1109 * containing the last set archived.1110 * - @c p_archival_threads_running: [offset 4] pointer to an @c int1111 * containing the number of archival threads currently running.1112 * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing1113 * the next set that should be archived.1114 * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a1115 * bit array, where each bit corresponds to a filelist (1=needs1116 * to be archived, 0=archived).1117 * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information1118 * structure. Fields used:1119 * - @c tmpdir1120 * - @c zip_suffix1121 *1122 * Any of the above may be modified by the caller at any time.1123 *1124 * @bug Assumes @c int pointers are 4 bytes.1125 * @see archive_this_fileset1126 * @see make_afioballs_and_images1127 * @return NULL, always.1128 * @ingroup LLarchiveGroup1129 */1130 void *create_afio_files_in_background(void *inbuf)1131 {1132 long int archiving_set_no = 0L;1133 char *archiving_filelist_fname = NULL;1134 char *archiving_afioball_fname = NULL;1135 char *curr_xattr_list_fname = NULL;1136 char *curr_acl_list_fname = NULL;1137 1138 char *tmp = NULL;1139 int res = 0, retval = 0;1140 int *p_archival_threads_running;1141 int *p_last_set_archived;1142 int *p_next_set_to_archive;1143 char *p_list_of_fileset_flags;1144 int this_thread_no = g_current_thread_no++;1145 1146 p_last_set_archived = (int *) inbuf;1147 p_archival_threads_running = (int *) (inbuf + 4);1148 p_next_set_to_archive = (int *) (inbuf + 8);1149 p_list_of_fileset_flags = (char *) (inbuf + 12);1150 1151 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);1152 1153 while (does_file_exist(archiving_filelist_fname)) {1154 if (g_exiting) {1155 mr_free(archiving_filelist_fname);1156 fatal_error("Execution run aborted (pthread)");1157 }1158 if (archiving_set_no >= MAX_NOOF_SETS_HERE) {1159 mr_free(archiving_filelist_fname);1160 fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please.");1161 }1162 if (!semaphore_p()) {1163 log_msg(3, "P sem failed (pid=%d)", (int) getpid());1164 mr_free(archiving_filelist_fname);1165 fatal_error("Cannot get semaphore P");1166 }1167 if (archiving_set_no < *p_next_set_to_archive) {1168 archiving_set_no = *p_next_set_to_archive;1169 }1170 *p_next_set_to_archive = *p_next_set_to_archive + 1;1171 if (!semaphore_v()) {1172 mr_free(archiving_filelist_fname);1173 fatal_error("Cannot get semaphore V");1174 }1175 1176 /* backup this set of files */1177 mr_asprintf(archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no, bkpinfo->zip_suffix);1178 mr_free(archiving_filelist_fname);1179 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);1180 if (!does_file_exist(archiving_filelist_fname)) {1181 log_msg(3, "%s[%d:%d] - well, I would archive %d, except that it doesn't exist. I'll stop now.", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);1182 mr_free(archiving_afioball_fname);1183 break;1184 }1185 1186 mr_asprintf(tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no - ARCH_BUFFER_NUM, bkpinfo->zip_suffix);1187 if (does_file_exist(tmp)) {1188 log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no);1189 while (does_file_exist(tmp)) {1190 sleep(1);1191 }1192 log_msg(4, "[%d] - continuing", getpid());1193 }1194 mr_free(tmp);1195 1196 log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);1197 1198 if (g_getfattr) {1199 mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);1200 get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname);1201 mr_free(curr_xattr_list_fname);1202 }1203 if (g_getfacl) {1204 mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);1205 get_acl_list(archiving_filelist_fname, curr_acl_list_fname);1206 mr_free(curr_acl_list_fname);1207 }1208 1209 log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);1210 res = archive_this_fileset(archiving_filelist_fname, archiving_afioball_fname, archiving_set_no);1211 mr_free(archiving_afioball_fname);1212 1213 retval += res;1214 1215 if (res) {1216 log_to_screen("Errors occurred while archiving set %ld. Please review logs.", archiving_set_no);1217 }1218 1219 if (!semaphore_p()) {1220 mr_free(archiving_filelist_fname);1221 fatal_error("Cannot get semaphore P");1222 }1223 1224 set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5);1225 1226 if (*p_last_set_archived < archiving_set_no) {1227 *p_last_set_archived = archiving_set_no;1228 } // finished archiving this one1229 1230 if (!semaphore_v()) {1231 mr_free(archiving_filelist_fname);1232 fatal_error("Cannot get semaphore V");1233 }1234 log_msg(4, "%s[%d:%d] - archived %d OK", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);1235 archiving_set_no++;1236 1237 mr_free(archiving_filelist_fname);1238 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);1239 }1240 mr_free(archiving_filelist_fname);1241 1242 if (!semaphore_p()) {1243 fatal_error("Cannot get semaphore P");1244 }1245 (*p_archival_threads_running)--;1246 if (!semaphore_v()) {1247 fatal_error("Cannot get semaphore V");1248 }1249 log_msg(3, "%s[%d:%d] - exiting", FORTY_SPACES, getpid(), this_thread_no);1250 pthread_exit(NULL);1251 }1252 1253 1254 /**1255 * Write the final ISO image.1256 * @param bkpinfo The backup information structure. Used only1257 * in the call to @c write_iso_and_go_on().1258 * @return The number of errors encountered (0 for success)1259 * @see write_iso_and_go_on1260 * @see make_iso_fs1261 * @bug The final ISO is written even if there are no files on it. In practice,1262 * however, this occurs rarely.1263 */1264 int write_final_iso_if_necessary()1265 {1266 /*@ int ***************************************************** */1267 int res;1268 1269 /*@ buffers ************************************************** */1270 char *tmp = NULL;1271 1272 assert(bkpinfo != NULL);1273 // I should really check if there are any slices or tarballs to be copied to CD-R(W)'s; the odds are approx. 1 in a million that there are no files here, so I'll just go ahead & make one more CD anyway1274 1275 tmp = mr_center_string("Writing the final ISO", 80);1276 log_msg(2, tmp);1277 if (!g_text_mode) {1278 newtPushHelpLine(tmp);1279 }1280 mr_free(tmp);1281 res = write_iso_and_go_on(TRUE);1282 if (!g_text_mode) {1283 newtPopHelpLine();1284 }1285 log_msg(2, "Returning from writing final ISO (res=%d)", res);1286 return (res);1287 }1288 1289 1290 1291 1292 319 /** 1293 320 * Remove the archives in @c d. … … 1328 355 1329 356 1330 /** 1331 * Initialize the backup. 1332 * Does the following: 1333 * - Sets up the serial number. 1334 * - For streaming backups, opens the tape stream and writes the data disks 1335 * and backup headers. 1336 * - For CD-based backups, wipes the ISOs in the target directory. 357 358 /** 359 * Write an ISO image to <tt>[bkpinfo->isodir]/bkpinfo->prefix-[g_current_media_number].iso</tt>. 360 * @param bkpinfo The backup information structure. Fields used: 361 * - @c backup_media_type 362 * - @c prefix 363 * - @c isodir 364 * - @c manual_cd_tray 365 * - @c media_size 366 * - @c netfs_remote_dir 367 * - @c scratchdir 368 * - @c verify_data 369 * 370 * @param last_cd If TRUE, this is the last CD to write; if FALSE, it's not. 371 * @return The number of errors encountered (0 for success) 372 * @see make_iso_fs 373 */ 374 int write_iso_and_go_on(bool last_cd) 375 { 376 /*@ pointers **************************************************** */ 377 FILE *fout; 378 379 /*@ buffers ***************************************************** */ 380 char *tmp = NULL; 381 char *tmp1 = NULL; 382 char *cdno_fname = NULL; 383 char *lastcd_fname = NULL; 384 char *isofile = NULL; 385 char *mds = NULL; 386 387 /*@ bool ******************************************************** */ 388 bool that_one_was_ok; 389 bool orig_vfy_flag_val; 390 391 /*@ int *********************************************************** */ 392 int res = 0; 393 394 assert(bkpinfo != NULL); 395 orig_vfy_flag_val = bkpinfo->verify_data; 396 if (bkpinfo->media_size <= 0) { 397 fatal_error("write_iso_and_go_on() - unknown media size"); 398 } 399 400 mds = media_descriptor_string(bkpinfo->backup_media_type); 401 log_msg(1, "OK, time to make %s #%d", mds, g_current_media_number); 402 mr_free(mds); 403 404 /* label the ISO with its number */ 405 406 mr_asprintf(cdno_fname, "%s/archives/THIS-CD-NUMBER", bkpinfo->scratchdir); 407 fout = fopen(cdno_fname, "w"); 408 mr_free(cdno_fname); 409 410 fprintf(fout, "%d", g_current_media_number); 411 paranoid_fclose(fout); 412 413 mr_asprintf(tmp1, "cp -f %s/autorun %s/", g_mondo_home, bkpinfo->scratchdir); 414 if (run_program_and_log_output(tmp1, FALSE)) { 415 log_msg(2, "Warning - unable to copy autorun to scratchdir"); 416 } 417 mr_free(tmp1); 418 419 /* last CD or not? Label accordingly */ 420 mr_asprintf(lastcd_fname, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir); 421 if (last_cd) { 422 unlink(lastcd_fname); 423 log_msg(2, 424 "OK, you're telling me this is the last CD. Fair enough."); 425 } else { 426 fout = fopen(lastcd_fname, "w"); 427 fprintf(fout, 428 "You're listening to 90.3 WPLN, Nashville Public Radio.\n"); 429 paranoid_fclose(fout); 430 } 431 mr_free(lastcd_fname); 432 433 if (space_occupied_by_cd(bkpinfo->scratchdir) / 1024 > bkpinfo->media_size) { 434 log_to_screen("Warning! CD is too big. It occupies %ld KB, which is more than the %ld MB allowed.",(long) space_occupied_by_cd(bkpinfo->scratchdir),(long) bkpinfo->media_size); 435 } 436 437 if (bkpinfo->netfs_remote_dir != NULL) { 438 // NETFS 439 mr_asprintf(isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number); 440 } else { 441 // ISO 442 mr_asprintf(isofile, "%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number); 443 } 444 for (that_one_was_ok = FALSE; !that_one_was_ok;) { 445 if (bkpinfo->backup_media_type != usb) { 446 res = make_iso_fs(isofile); 447 } else { 448 res = make_usb_fs(); 449 } 450 if (g_current_media_number == 1 && !res 451 && (bkpinfo->backup_media_type == cdr)) { 452 if ((tmp = find_optical_device()) == NULL) { // make sure find_optical_device() finds, records CD-R's loc 453 log_msg(3, "*Sigh* Mike, I hate your computer."); 454 // if it can't be found then force pausing 455 bkpinfo->manual_cd_tray = TRUE; 456 } else { 457 log_msg(3, "Great. Found Mike's CD-ROM drive."); 458 } 459 mr_free(tmp); 460 } 461 if (bkpinfo->verify_data && !res) { 462 mds = media_descriptor_string(g_backup_media_type); 463 log_to_screen("Please reboot from the 1st %s in Compare Mode, as a precaution.", mds); 464 mr_free(mds); 465 if (chdir("/")) { 466 // FIXME 467 } 468 log_it("Before calling verification of image()"); 469 if (bkpinfo->backup_media_type == usb) { 470 res += verify_usb_image(); 471 } else { 472 res += verify_cd_image(); 473 } 474 log_it("After calling verification of image()"); 475 } 476 if (!res) { 477 that_one_was_ok = TRUE; 478 } else { 479 mds = media_descriptor_string(bkpinfo->backup_media_type); 480 mr_asprintf(tmp1, "Failed to create %s #%d. Retry?", mds, g_current_media_number); 481 mr_free(mds); 482 res = ask_me_yes_or_no(tmp1); 483 mr_free(tmp1); 484 485 if (!res) { 486 if (ask_me_yes_or_no("Abort the backup?")) { 487 fatal_error("FAILED TO BACKUP"); 488 } else { 489 break; 490 } 491 } else { 492 log_msg(2, "Retrying, at user's request..."); 493 res = 0; 494 } 495 } 496 } 497 mr_free(isofile); 498 499 g_current_media_number++; 500 wipe_archives(bkpinfo->scratchdir); 501 mr_asprintf(tmp1, "rm -Rf %s/images/*gz %s/images/*data*img", bkpinfo->scratchdir, bkpinfo->scratchdir); 502 if (system(tmp1)) { 503 log_msg(2, "Error occurred when I tried to delete the redundant IMGs and GZs"); 504 } 505 mr_free(tmp1); 506 507 if (last_cd) { 508 log_msg(2, "This was your last media."); 509 } else { 510 log_msg(2, "Continuing to backup your data..."); 511 } 512 513 bkpinfo->verify_data = orig_vfy_flag_val; 514 return (0); 515 } 516 517 518 519 520 521 /** 522 * Write the final ISO image. 523 * @param bkpinfo The backup information structure. Used only 524 * in the call to @c write_iso_and_go_on(). 525 * @return The number of errors encountered (0 for success) 526 * @see write_iso_and_go_on 527 * @see make_iso_fs 528 * @bug The final ISO is written even if there are no files on it. In practice, 529 * however, this occurs rarely. 530 */ 531 int write_final_iso_if_necessary() 532 { 533 /*@ int ***************************************************** */ 534 int res; 535 536 /*@ buffers ************************************************** */ 537 char *tmp = NULL; 538 539 assert(bkpinfo != NULL); 540 // I should really check if there are any slices or tarballs to be copied to CD-R(W)'s; the odds are approx. 1 in a million that there are no files here, so I'll just go ahead & make one more CD anyway 541 542 tmp = mr_center_string("Writing the final ISO", 80); 543 log_msg(2, tmp); 544 if (!g_text_mode) { 545 newtPushHelpLine(tmp); 546 } 547 mr_free(tmp); 548 res = write_iso_and_go_on(TRUE); 549 if (!g_text_mode) { 550 newtPopHelpLine(); 551 } 552 log_msg(2, "Returning from writing final ISO (res=%d)", res); 553 return (res); 554 } 555 556 557 558 559 /** 560 * Finalize the backup. 561 * For streaming backups, this writes the closing block 562 * to the stream. For CD-based backups, this creates 563 * the final ISO image. 564 * @param bkpinfo The backup information structure, used only 565 * for the @c backup_media_type. 566 * @ingroup MLarchiveGroup 567 */ 568 int do_that_final_phase() 569 { 570 571 /*@ int ************************************** */ 572 int res = 0; 573 int retval = 0; 574 575 /*@ buffers ********************************** */ 576 577 assert(bkpinfo != NULL); 578 mvaddstr_and_log_it(g_currentY, 0, 579 "Writing any remaining data to media "); 580 581 log_msg(1, "Closing tape/CD/USB ... "); 582 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 583 /* write tape/cdstream */ 584 closeout_tape(); 585 } else { 586 /* write final ISO/USB */ 587 res = write_final_iso_if_necessary(); 588 retval += res; 589 if (res) { 590 log_msg(1, "write_final_iso_if_necessary returned an error"); 591 } 592 } 593 log_msg(2, "Fork is exiting ... "); 594 595 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 596 597 /* final stuff */ 598 if (retval) { 599 mvaddstr_and_log_it(g_currentY++, 74, "Errors."); 600 } else { 601 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 602 } 603 604 return (retval); 605 } 606 607 608 609 /** 610 * Back up big files by chopping them up. 611 * This function backs up all "big" files (where "big" depends 612 * on your backup media) in "chunks" (whose size again depends 613 * on your media). 1337 614 * 1338 615 * @param bkpinfo The backup information structure. Fields used: 1339 616 * - @c backup_media_type 1340 * - @c cdrw_speed 1341 * - @c prefix 1342 * - @c isodir 1343 * - @c media_device 617 * - @c optimal_set_size 618 * @param biggielist_fname The path to a file containing a list of 619 * all "big" files. 620 * @return The number of errors encountered (0 for success) 621 * @see slice_up_file_etc 622 */ 623 int make_slices_and_images(char *biggielist_fname) { 624 625 /*@ pointers ******************************************* */ 626 FILE *fin = NULL; 627 char *p; 628 char *q; 629 630 /*@ buffers ******************************************** */ 631 char *tmp = NULL; 632 char *bigfile_fname = NULL; 633 char *sz_devfile = NULL; 634 char *ntfsprog_fifo = NULL; 635 /*@ long *********************************************** */ 636 long biggie_file_number = 0L; 637 long noof_biggie_files = 0L; 638 long estimated_total_noof_slices = 0L; 639 long size_of_all_biggiefiles = 0L; 640 641 /*@ int ************************************************ */ 642 int retval = 0; 643 int res = 0; 644 pid_t pid; 645 FILE *ftmp = NULL; 646 bool delete_when_done; 647 bool use_ntfsprog; 648 off_t biggie_fsize; 649 650 assert(bkpinfo != NULL); 651 assert_string_is_neither_NULL_nor_zerolength(biggielist_fname); 652 653 size_of_all_biggiefiles = size_of_all_biggiefiles_K(); 654 estimated_total_noof_slices = size_of_all_biggiefiles / bkpinfo->optimal_set_size + 1L; 655 656 log_msg(1, "size of all biggiefiles = %ld", size_of_all_biggiefiles); 657 log_msg(1, "estimated_total_noof_slices = %ld KB / %ld KB = %ld", size_of_all_biggiefiles, bkpinfo->optimal_set_size, estimated_total_noof_slices); 658 659 if (length_of_file(biggielist_fname) < 6) { 660 log_msg(1, "No biggiefiles; fair enough..."); 661 return (0); 662 } 663 mr_asprintf(tmp, "I am now backing up all large files."); 664 log_to_screen(tmp); 665 noof_biggie_files = count_lines_in_file(biggielist_fname); 666 log_msg(1, "noof_biggie_files = %ld", noof_biggie_files); 667 open_progress_form("Backing up big files", tmp, "Please wait. This may take some time.", "", estimated_total_noof_slices); 668 mr_free(tmp); 669 670 if (!(fin = fopen(biggielist_fname, "r"))) { 671 log_OS_error("Unable to openin biggielist"); 672 return (1); 673 } 674 675 malloc_string(bigfile_fname); 676 for (q = fgets(bigfile_fname, MAX_STR_LEN, fin); !feof(fin) && (q != NULL); 677 q = fgets(bigfile_fname, MAX_STR_LEN, fin), biggie_file_number++) { 678 use_ntfsprog = FALSE; 679 if (bigfile_fname[strlen(bigfile_fname) - 1] < 32) { 680 bigfile_fname[strlen(bigfile_fname) - 1] = '\0'; 681 } 682 biggie_fsize = length_of_file(bigfile_fname); 683 delete_when_done = FALSE; 684 685 if (!does_file_exist(bigfile_fname)) { 686 ftmp = fopen(bigfile_fname, "w"); 687 if (ftmp == NULL) { 688 log_msg(3, "Unable to write to %s", bigfile_fname); 689 // So skip it as it doesn't exist 690 continue; 691 } else { 692 paranoid_fclose(ftmp); 693 } 694 delete_when_done = TRUE; 695 } else { 696 // Call ntfsclone (formerly partimagehack) if it's a /dev entry 697 // (i.e. a partition to be imaged) 698 log_msg(2, "bigfile_fname = %s", bigfile_fname); 699 use_ntfsprog = FALSE; 700 if (!strncmp(bigfile_fname, "/dev/", 5) && is_dev_an_NTFS_dev(bigfile_fname)) { 701 use_ntfsprog = TRUE; 702 log_msg(2, "Calling ntfsclone in background because %s is an NTFS partition", bigfile_fname); 703 mr_asprintf(sz_devfile, "%s/%d.%d.000", bkpinfo->tmpdir, (int) (random() % 32768), (int) (random() % 32768)); 704 mkfifo(sz_devfile, 0x770); 705 ntfsprog_fifo = sz_devfile; 706 switch (pid = fork()) { 707 case -1: 708 mr_free(sz_devfile); 709 fatal_error("Fork failure"); 710 case 0: 711 log_msg(2, "CHILD - fip - calling feed_into_ntfsprog(%s, %s)", bigfile_fname, sz_devfile); 712 res = feed_into_ntfsprog(bigfile_fname, sz_devfile); 713 /* TODO: Does the child need to unalocate memory as well ? 714 mr_free(bigfile_fname); 715 mr_free(sz_devfile); 716 */ 717 exit(res); 718 break; 719 default: 720 log_msg(2, "feed_into_ntfsprog() called in background --- pid=%ld", (long int) (pid)); 721 } 722 } 723 // Otherwise, use good old 'dd' and 'bzip2' 724 else { 725 ntfsprog_fifo = NULL; 726 } 727 728 // Whether partition or biggiefile, just do your thang :-) 729 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 730 write_header_block_to_stream(biggie_fsize, bigfile_fname, use_ntfsprog ? BLK_START_A_PIHBIGGIE : BLK_START_A_NORMBIGGIE); 731 } 732 res = slice_up_file_etc(bigfile_fname, ntfsprog_fifo, biggie_file_number, noof_biggie_files, use_ntfsprog); 733 734 /* Free it here as ntfsprog_fifo is not used anymore */ 735 mr_free(sz_devfile); 736 737 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 738 write_header_block_to_stream((off_t)0, calc_checksum_of_file(bigfile_fname), BLK_STOP_A_BIGGIE); 739 } 740 retval += res; 741 p = strrchr(bigfile_fname, '/'); 742 if (p) { 743 p++; 744 } else { 745 p = bigfile_fname; 746 } 747 mr_asprintf(tmp, "Archiving %s ... ", bigfile_fname); 748 if (res) { 749 mr_strcat(tmp, "Failed!"); 750 } else { 751 mr_strcat(tmp, "OK"); 752 } 753 if (delete_when_done) { 754 unlink(bigfile_fname); 755 delete_when_done = FALSE; 756 } 757 } 758 if (!g_text_mode) { 759 newtDrawRootText(0, g_noof_rows - 2, tmp); 760 newtRefresh(); 761 } 762 mr_free(tmp); 763 } 764 mr_free(bigfile_fname); 765 766 log_msg(1, "Finished backing up bigfiles"); 767 log_msg(1, "estimated slices = %ld; actual slices = %ld", estimated_total_noof_slices, g_current_progress); 768 close_progress_form(); 769 paranoid_fclose(fin); 770 return (retval); 771 } 772 773 774 775 776 /** 777 * Wrapper around @c make_slices_and_images(). 778 * @param bkpinfo The backup information structure. Fields used: 779 * - @c backup_media_type 1344 780 * - @c scratchdir 1345 781 * - @c tmpdir 1346 * - @c serial_string 1347 * @return The number of errors encountered (0 for success). 782 * @return The number of errors encountered (0 for success) 1348 783 * @ingroup MLarchiveGroup 1349 784 */ 1350 int do_that_initial_phase() { 1351 /*@ int *************************************** */ 785 int make_those_slices_phase() 786 { 787 788 /*@ int ***************************************************** */ 789 int res = 0; 1352 790 int retval = 0; 1353 791 1354 /*@ buffers *********************************** */ 792 /*@ buffers ************************************************** */ 793 char *biggielist = NULL; 1355 794 char *command = NULL; 1356 char * tmp= NULL;1357 char * tmpfile = NULL;1358 char * data_disks_file = NULL;795 char *blah = NULL; 796 char *xattr_fname = NULL; 797 char *acl_fname = NULL; 1359 798 1360 799 assert(bkpinfo != NULL); 1361 mr_asprintf(data_disks_file, "%s/all.tar.gz", bkpinfo->tmpdir); 1362 1363 tmp = call_program_and_get_last_line_of_output("dd if=/dev/urandom bs=16 count=1 2> /dev/null | hexdump | tr -s ' ' '0' | head -n1"); 1364 bkpinfo->serial_string = mr_strip_spaces(tmp); 1365 mr_free(tmp); 1366 mr_strcat(bkpinfo->serial_string, "...word."); 1367 log_msg(2, "bkpinfo->serial_string = '%s'", bkpinfo->serial_string); 1368 1369 mr_asprintf(tmpfile, "%s/archives/SERIAL-STRING", bkpinfo->scratchdir); 1370 if (write_one_liner_data_file(tmpfile, bkpinfo->serial_string)) { 1371 log_msg(1, "%ld: Failed to write serial string", __LINE__); 1372 } 1373 mr_free(tmpfile); 1374 1375 mvaddstr_and_log_it(g_currentY, 0, "Preparing to archive your data"); 1376 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1377 if (bkpinfo->backup_media_type == cdstream) { 1378 openout_cdstream(bkpinfo->media_device, bkpinfo->cdrw_speed); 1379 } else { 1380 openout_tape(); /* sets g_tape_stream */ 1381 } 1382 if (!g_tape_stream) { 1383 fatal_error("Cannot open backup (streaming) device"); 1384 } 1385 log_msg(1, "Backup (stream) opened OK"); 1386 write_data_disks_to_stream(data_disks_file); 1387 } else { 1388 if (bkpinfo->backup_media_type == usb) { 1389 log_msg(1, "Backing up to USB's"); 1390 } else { 1391 log_msg(1, "Backing up to CD's"); 1392 } 1393 } 1394 mr_free(data_disks_file); 1395 1396 if (bkpinfo->netfs_remote_dir != NULL) { 1397 mr_asprintf(command, "rm -f %s/%s/%s-[1-9]*.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix); 1398 } else { 1399 mr_asprintf(command, "rm -f %s/%s-[1-9]*.iso", bkpinfo->isodir, bkpinfo->prefix); 1400 } 800 /* slice big files */ 801 mvaddstr_and_log_it(g_currentY, 0, "Archiving large files to media "); 802 mr_asprintf(biggielist, "%s/archives/biggielist.txt", bkpinfo->scratchdir); 803 if (g_getfattr) { 804 mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir); 805 } 806 if (g_getfacl) { 807 mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir); 808 } 809 810 mr_asprintf(command, "cp %s/biggielist.txt %s", bkpinfo->tmpdir, biggielist); 1401 811 paranoid_system(command); 1402 812 mr_free(command); 1403 813 1404 wipe_archives(bkpinfo->scratchdir); 1405 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 814 mr_asprintf(blah, "biggielist = %s", biggielist); 815 log_msg(2, blah); 816 mr_free(blah); 817 818 if (!does_file_exist(biggielist)) { 819 log_msg(1, "BTW, the biggielist does not exist"); 820 } 821 822 if (g_getfattr) { 823 get_fattr_list(biggielist, xattr_fname); 824 mr_asprintf(command, "cp %s %s/archives/", xattr_fname, bkpinfo->scratchdir); 825 paranoid_system(command); 826 mr_free(command); 827 } 828 if (g_getfacl) { 829 get_acl_list(biggielist, acl_fname); 830 mr_asprintf(command, "cp %s %s/archives/", acl_fname, bkpinfo->scratchdir); 831 paranoid_system(command); 832 mr_free(command); 833 } 834 1406 835 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1407 write_header_block_to_stream((off_t)0, "start-of-tape", BLK_START_OF_TAPE); 1408 write_header_block_to_stream((off_t)0, "start-of-backup", BLK_START_OF_BACKUP); 1409 } 836 res += write_EXAT_files_to_tape(xattr_fname, acl_fname); 837 mr_asprintf(blah, "%ld", count_lines_in_file(biggielist)); 838 write_header_block_to_stream((off_t)0, blah, BLK_START_BIGGIEFILES); 839 mr_free(blah); 840 } 841 res = make_slices_and_images(biggielist); 842 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 843 write_header_block_to_stream((off_t)0, "end-of-biggiefiles", BLK_STOP_BIGGIEFILES); 844 } 845 retval += res; 846 if (res) { 847 log_msg(1, "make_slices_and_images returned an error"); 848 mvaddstr_and_log_it(g_currentY++, 74, "Errors."); 849 } else { 850 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 851 } 852 mr_free(biggielist); 853 mr_free(xattr_fname); 854 mr_free(acl_fname); 1410 855 return (retval); 1411 856 } 1412 857 1413 1414 /**1415 * Get the <tt>N</tt>th bit of @c array.1416 * @param array The bit-array (as a @c char pointer).1417 * @param N The number of the bit you want.1418 * @return TRUE (bit is set) or FALSE (bit is not set).1419 * @see set_bit_N_of_array1420 * @ingroup utilityGroup1421 */1422 bool get_bit_N_of_array(char *array, int N)1423 {1424 int element_number;1425 int bit_number;1426 int mask;1427 1428 element_number = N / 8;1429 bit_number = N % 8;1430 mask = 1 << bit_number;1431 if (array[element_number] & mask) {1432 return (TRUE);1433 } else {1434 return (FALSE);1435 }1436 }1437 1438 1439 /**1440 * @addtogroup LLarchiveGroup1441 * @{1442 */1443 /**1444 * Function pointer to an appropriate @c move_files_to_stream routine.1445 * You can set this to your own function (for example, one to1446 * transfer files over the network) or leave it as is.1447 */1448 int (*move_files_to_stream) (char *, ...) =1449 _move_files_to_stream;1450 1451 1452 /**1453 * Function pointer to an appropriate @c move_files_to_cd routine.1454 * You can set this to your own function (for example, one to1455 * transfer files over the network) or leave it as is.1456 */1457 int (*move_files_to_cd) (char *, ...) =1458 _move_files_to_cd;1459 1460 1461 1462 /**1463 * @addtogroup LLarchiveGroup1464 * @{1465 */1466 858 /** 1467 859 * Start up threads to archive your files. … … 1649 1041 1650 1042 1043 1044 /** 1045 * Single-threaded version of @c make_afioballs_and_images(). 1046 * @see make_afioballs_and_images 1047 */ 1048 int make_afioballs_and_images_OLD() 1049 { 1050 1051 /*@ int ************************************************** */ 1052 int retval = 0; 1053 long int curr_set_no = 0L; 1054 int res = 0; 1055 1056 /*@ buffers ********************************************** */ 1057 char *curr_filelist_fname = NULL; 1058 char *curr_afioball_fname = NULL; 1059 char *curr_xattr_list_fname = NULL; 1060 char *curr_acl_list_fname = NULL; 1061 char *tmp = NULL; 1062 char *media_usage_comment = NULL; 1063 1064 log_to_screen("Archiving regular files"); 1065 1066 open_progress_form("Backing up filesystem", 1067 "I am backing up your live filesystem now.", 1068 "Please wait. This may take a couple of hours.", 1069 "Working...", 1070 get_last_filelist_number() + 1); 1071 1072 for (;;) { 1073 /* backup this set of files */ 1074 mr_asprintf(curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no); 1075 if (! does_file_exist(curr_filelist_fname)) { 1076 mr_free(curr_filelist_fname); 1077 break; 1078 } 1079 1080 mr_asprintf(curr_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no, bkpinfo->zip_suffix); 1081 1082 log_msg(1, "EXAT'g set %ld", curr_set_no); 1083 if (g_getfattr) { 1084 mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no); 1085 get_fattr_list(curr_filelist_fname, curr_xattr_list_fname); 1086 } 1087 if (g_getfacl) { 1088 mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no); 1089 get_acl_list(curr_filelist_fname, curr_acl_list_fname); 1090 } 1091 1092 log_msg(1, "Archiving set %ld", curr_set_no); 1093 res = archive_this_fileset(curr_filelist_fname, curr_afioball_fname, curr_set_no); 1094 retval += res; 1095 if (res) { 1096 log_to_screen("Errors occurred while archiving set %ld. Perhaps your live filesystem changed?", curr_set_no); 1097 } 1098 1099 /* copy to CD (scratchdir) ... and an actual CD-R if necessary */ 1100 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1101 register_in_tape_catalog(fileset, curr_set_no, -1, curr_afioball_fname); 1102 maintain_collection_of_recent_archives(bkpinfo->tmpdir, curr_afioball_fname); 1103 log_it("Writing EXAT files"); 1104 res += 1105 write_EXAT_files_to_tape(curr_xattr_list_fname, 1106 curr_acl_list_fname); 1107 // archives themselves 1108 res = move_files_to_stream(curr_afioball_fname, NULL); 1109 } else { 1110 if (g_getfacl) { 1111 if (g_getfattr) { 1112 res = move_files_to_cd(curr_filelist_fname, 1113 curr_xattr_list_fname, 1114 curr_acl_list_fname, 1115 curr_afioball_fname, NULL); 1116 } else { 1117 res = move_files_to_cd(curr_filelist_fname, 1118 curr_acl_list_fname, 1119 curr_afioball_fname, NULL); 1120 } 1121 } else { 1122 if (g_getfattr) { 1123 res = move_files_to_cd(curr_filelist_fname, 1124 curr_xattr_list_fname, 1125 curr_afioball_fname, NULL); 1126 } else { 1127 res = move_files_to_cd(curr_filelist_fname, 1128 curr_afioball_fname, NULL); 1129 } 1130 } 1131 } 1132 if (g_getfattr) { 1133 mr_free(curr_xattr_list_fname); 1134 } 1135 if (g_getfacl) { 1136 mr_free(curr_acl_list_fname); 1137 } 1138 retval += res; 1139 g_current_progress++; 1140 1141 media_usage_comment = percent_media_full_comment(); 1142 update_progress_form(media_usage_comment); 1143 mr_free(media_usage_comment); 1144 1145 if (res) { 1146 log_to_screen("Failed to add archive %ld's files to CD dir\n", curr_set_no); 1147 fatal_error("Is your hard disk is full? If not, please send the author the logfile."); 1148 } 1149 mr_free(curr_filelist_fname); 1150 mr_free(curr_afioball_fname); 1151 curr_set_no++; 1152 } 1153 close_progress_form(); 1154 mr_asprintf(tmp, "Your regular files have been archived "); 1155 if (retval) { 1156 mr_strcat(tmp, "(with errors)."); 1157 } else { 1158 mr_strcat(tmp, "successfully."); 1159 } 1160 log_to_screen(tmp); 1161 mr_free(tmp); 1162 return (retval); 1163 } 1164 1165 1166 1167 /** 1168 * Wrapper around @c make_afioballs_and_images(). 1169 * @param bkpinfo the backup information structure. Only the 1170 * @c backup_media_type field is used within this function. 1171 * @return return code of make_afioballs_and_images 1172 * @see make_afioballs_and_images 1173 * @ingroup MLarchiveGroup 1174 */ 1175 int make_those_afios_phase() 1176 { 1177 /*@ int ******************************************* */ 1178 int res = 0; 1179 int retval = 0; 1180 1181 assert(bkpinfo != NULL); 1182 1183 mvaddstr_and_log_it(g_currentY, 0, "Archiving regular files to media "); 1184 1185 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1186 write_header_block_to_stream((off_t)0, "start-of-afioballs", BLK_START_AFIOBALLS); 1187 #if __FreeBSD__ == 5 1188 log_msg(1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0"); 1189 res = make_afioballs_and_images_OLD(); 1190 #else 1191 res = make_afioballs_and_images_OLD(); 1192 #endif 1193 write_header_block_to_stream((off_t)0, "stop-afioballs", BLK_STOP_AFIOBALLS); 1194 } else { 1195 res = make_afioballs_and_images(); 1196 } 1197 1198 retval += res; 1199 if (res) { 1200 mvaddstr_and_log_it(g_currentY++, 74, "Errors."); 1201 log_msg(1, "make_afioballs_and_images returned an error"); 1202 } else { 1203 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1204 } 1205 return (retval); 1206 } 1207 1208 1209 /** 1210 * Initialize the backup. 1211 * Does the following: 1212 * - Sets up the serial number. 1213 * - For streaming backups, opens the tape stream and writes the data disks 1214 * and backup headers. 1215 * - For CD-based backups, wipes the ISOs in the target directory. 1216 * 1217 * @param bkpinfo The backup information structure. Fields used: 1218 * - @c backup_media_type 1219 * - @c cdrw_speed 1220 * - @c prefix 1221 * - @c isodir 1222 * - @c media_device 1223 * - @c scratchdir 1224 * - @c tmpdir 1225 * - @c serial_string 1226 * @return The number of errors encountered (0 for success). 1227 * @ingroup MLarchiveGroup 1228 */ 1229 int do_that_initial_phase() { 1230 /*@ int *************************************** */ 1231 int retval = 0; 1232 1233 /*@ buffers *********************************** */ 1234 char *command = NULL; 1235 char *tmp = NULL; 1236 char *tmpfile = NULL; 1237 char *data_disks_file = NULL; 1238 1239 assert(bkpinfo != NULL); 1240 mr_asprintf(data_disks_file, "%s/all.tar.gz", bkpinfo->tmpdir); 1241 1242 tmp = call_program_and_get_last_line_of_output("dd if=/dev/urandom bs=16 count=1 2> /dev/null | hexdump | tr -s ' ' '0' | head -n1"); 1243 bkpinfo->serial_string = mr_strip_spaces(tmp); 1244 mr_free(tmp); 1245 mr_strcat(bkpinfo->serial_string, "...word."); 1246 log_msg(2, "bkpinfo->serial_string = '%s'", bkpinfo->serial_string); 1247 1248 mr_asprintf(tmpfile, "%s/archives/SERIAL-STRING", bkpinfo->scratchdir); 1249 if (write_one_liner_data_file(tmpfile, bkpinfo->serial_string)) { 1250 log_msg(1, "%ld: Failed to write serial string", __LINE__); 1251 } 1252 mr_free(tmpfile); 1253 1254 mvaddstr_and_log_it(g_currentY, 0, "Preparing to archive your data"); 1255 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1256 if (bkpinfo->backup_media_type == cdstream) { 1257 openout_cdstream(bkpinfo->media_device, bkpinfo->cdrw_speed); 1258 } else { 1259 openout_tape(); /* sets g_tape_stream */ 1260 } 1261 if (!g_tape_stream) { 1262 fatal_error("Cannot open backup (streaming) device"); 1263 } 1264 log_msg(1, "Backup (stream) opened OK"); 1265 write_data_disks_to_stream(data_disks_file); 1266 } else { 1267 if (bkpinfo->backup_media_type == usb) { 1268 log_msg(1, "Backing up to USB's"); 1269 } else { 1270 log_msg(1, "Backing up to CD's"); 1271 } 1272 } 1273 mr_free(data_disks_file); 1274 1275 if (bkpinfo->netfs_remote_dir != NULL) { 1276 mr_asprintf(command, "rm -f %s/%s/%s-[1-9]*.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix); 1277 } else { 1278 mr_asprintf(command, "rm -f %s/%s-[1-9]*.iso", bkpinfo->isodir, bkpinfo->prefix); 1279 } 1280 paranoid_system(command); 1281 mr_free(command); 1282 1283 wipe_archives(bkpinfo->scratchdir); 1284 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1285 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1286 write_header_block_to_stream((off_t)0, "start-of-tape", BLK_START_OF_TAPE); 1287 write_header_block_to_stream((off_t)0, "start-of-backup", BLK_START_OF_BACKUP); 1288 } 1289 return (retval); 1290 } 1291 1292 1293 1294 /** 1295 * Call Mindi to generate boot and data disks. 1296 * @note This binds correctly to the new Perl version of mindi. 1297 * @param bkpinfo The backup information structure. Fields used: 1298 * - @c backup_media_type 1299 * - @c boot_loader 1300 * - @c boot_device 1301 * - @c compression_level 1302 * - @c differential 1303 * - @c image_devs 1304 * - @c kernel_path 1305 * - @c make_cd_use_lilo 1306 * - @c media_device 1307 * - @c media_size 1308 * - @c nonbootable_backup 1309 * - @c scratchdir 1310 * - @c tmpdir 1311 * - @c use_lzo 1312 * 1313 * @return The number of errors encountered (0 for success) 1314 * @bug The code to automagically determine the boot drive 1315 * is messy and system-dependent. In particular, it breaks 1316 * for Linux RAID and LVM users. 1317 * @ingroup MLarchiveGroup 1318 */ 1319 int call_mindi_to_supply_boot_disks() 1320 { 1321 /*@ buffer ************************************************************ */ 1322 char *tmp = NULL; 1323 char *tmp1 = NULL; 1324 char *tmp2 = NULL; 1325 char *command = NULL; 1326 char *use_lzo_sz = NULL; 1327 char *use_gzip_sz = NULL; 1328 char *use_lzma_sz = NULL; 1329 char *use_comp_sz = NULL; 1330 char *use_star_sz = NULL; 1331 char *bootldr_str = NULL; 1332 char *bootldr_ver = NULL; 1333 char *boot_type = NULL; 1334 char *tape_device = NULL; 1335 char *last_filelist_number = NULL; 1336 char *broken_bios_sz = NULL; 1337 char *cd_recovery_sz = NULL; 1338 char *tape_size_sz = NULL; 1339 char *use_lilo_sz = NULL; /* TODO: shared between LILO/ELILO */ 1340 char *value = NULL; 1341 char *bootdev = NULL; 1342 char *ntapedev = NULL; 1343 1344 1345 1346 /*@ char ************************************************************** */ 1347 char ch = '\0'; 1348 1349 /*@ long ********************************************************** */ 1350 long lines_in_filelist = 0L; 1351 1352 /*@ int ************************************************************* */ 1353 int res = 0; 1354 long estimated_total_noof_slices = 0L; 1355 1356 assert(bkpinfo != NULL); 1357 1358 mvaddstr_and_log_it(g_currentY, 0, "Calling MINDI to create boot+data disks"); 1359 open_evalcall_form("Calling MINDI to create boot+data disks"); 1360 mr_asprintf(tmp, "%s/filelist.full", bkpinfo->tmpdir); 1361 if (!does_file_exist(tmp)) { 1362 mr_free(tmp); 1363 mr_asprintf(tmp, "%s/tmpfs/filelist.full", bkpinfo->tmpdir); 1364 if (!does_file_exist(tmp)) { 1365 mr_free(tmp); 1366 fatal_error ("Cannot find filelist.full, so I cannot count its lines"); 1367 } 1368 } 1369 lines_in_filelist = count_lines_in_file(tmp); 1370 mr_free(tmp); 1371 1372 mr_asprintf(tmp, "%s/LAST-FILELIST-NUMBER", bkpinfo->tmpdir); 1373 mr_asprintf(last_filelist_number, "%s", last_line_of_file(tmp)); 1374 mr_free(tmp); 1375 1376 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1377 mr_asprintf(tape_size_sz, "%ld", bkpinfo->media_size); 1378 ntapedev = get_non_rewind_dev(bkpinfo->media_device); 1379 if ((bkpinfo->use_obdr) && (ntapedev != NULL)) { 1380 mr_asprintf(bkpinfo->media_device, "%s", ntapedev); 1381 } else { 1382 if (ntapedev == NULL) { 1383 log_it("Not able to create OBDR - Restore will have to be done manually"); 1384 } 1385 } 1386 mr_free(ntapedev); 1387 mr_asprintf(tape_device, "%s", bkpinfo->media_device); 1388 } else { 1389 mr_asprintf(tape_size_sz, "%ld", 0L);; 1390 mr_asprintf(tape_device, ""); 1391 } 1392 if (bkpinfo->use_lzo) { 1393 mr_asprintf(use_lzo_sz, "yes"); 1394 } else { 1395 mr_asprintf(use_lzo_sz, "no"); 1396 } 1397 if (bkpinfo->use_gzip) { 1398 mr_asprintf(use_gzip_sz, "yes"); 1399 } else { 1400 mr_asprintf(use_gzip_sz, "no"); 1401 } 1402 if (bkpinfo->use_lzma) { 1403 mr_asprintf(use_lzma_sz, "yes"); 1404 } else { 1405 mr_asprintf(use_lzma_sz, "no"); 1406 } 1407 if (bkpinfo->use_star) { 1408 mr_asprintf(use_star_sz, "yes"); 1409 } else { 1410 mr_asprintf(use_star_sz, "no"); 1411 } 1412 1413 if (bkpinfo->compression_level > 0) { 1414 mr_asprintf(use_comp_sz, "yes"); 1415 } else { 1416 mr_asprintf(use_comp_sz, "no"); 1417 } 1418 1419 mr_asprintf(broken_bios_sz, "yes"); /* assume so */ 1420 if (g_cd_recovery) { 1421 mr_asprintf(cd_recovery_sz, "yes"); 1422 } else { 1423 mr_asprintf(cd_recovery_sz, "no"); 1424 } 1425 if (bkpinfo->make_cd_use_lilo) { 1426 mr_asprintf(use_lilo_sz, "yes"); 1427 } else { 1428 mr_asprintf(use_lilo_sz, "no"); 1429 } 1430 if (bkpinfo->boot_type == UEFI) { 1431 mr_asprintf(boot_type, "UEFI"); 1432 } else if (bkpinfo->boot_type == EFI) { 1433 mr_asprintf(boot_type, "EFI"); 1434 } else if (bkpinfo->boot_type == BIOS) { 1435 mr_asprintf(boot_type, "BIOS"); 1436 } else { 1437 mr_asprintf(boot_type, "UNKNOWN"); 1438 } 1439 1440 update_evalcall_form(2); 1441 if (!bkpinfo->nonbootable_backup && (bkpinfo->boot_loader == '\0' || bkpinfo->boot_device == NULL)) { 1442 1443 #ifdef __FreeBSD__ 1444 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"); 1445 if (!bootdev[0]) { 1446 mr_free(bootdev); 1447 bootdev = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"); 1448 } 1449 #else 1450 /* Linux */ 1451 #ifdef __IA64__ 1452 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot/efi ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"); 1453 #else 1454 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"); 1455 #endif 1456 if (strstr(bootdev, "/dev/cciss/")) { 1457 mr_free(bootdev); 1458 #ifdef __IA64__ 1459 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot/efi ' | head -1 | cut -d' ' -f1 | cut -dp -f1"); 1460 #else 1461 bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | cut -dp -f1"); 1462 #endif 1463 } 1464 if (!bootdev[0]) { 1465 mr_free(bootdev); 1466 bootdev = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"); 1467 if (strstr(bootdev, "/dev/cciss/")) { 1468 mr_free(bootdev); 1469 bootdev = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | cut -dp -f1"); 1470 } 1471 } 1472 /* Linux */ 1473 #endif 1474 if (bootdev[0]) 1475 ch = which_boot_loader(bootdev); 1476 else 1477 ch = 'U'; 1478 if (bkpinfo->boot_loader != '\0') { 1479 log_msg(2, "User specified boot loader. It is '%c'.", bkpinfo->boot_loader); 1480 } else { 1481 bkpinfo->boot_loader = ch; 1482 } 1483 if (bkpinfo->boot_device != NULL) { 1484 log_msg(2, "User specified boot device. It is '%s'.", bkpinfo->boot_device); 1485 } else { 1486 mr_asprintf(bkpinfo->boot_device, "%s", bootdev); 1487 } 1488 } 1489 mr_free(bootdev); 1490 1491 if ( 1492 #ifdef __FreeBSD__ 1493 bkpinfo->boot_loader != 'B' && bkpinfo->boot_loader != 'D' && 1494 #endif 1495 #ifdef __IA64__ 1496 bkpinfo->boot_loader != 'E' && 1497 #endif 1498 bkpinfo->boot_loader != 'L' && bkpinfo->boot_loader != 'G' && bkpinfo->boot_loader != 'R' && !bkpinfo->nonbootable_backup) { 1499 fatal_error("Please specify your boot loader and device, e.g. -l GRUB -f /dev/hda. Type 'man mondoarchive' to read the manual."); 1500 } 1501 if (bkpinfo->boot_loader == 'L') { 1502 mr_asprintf(bootldr_str, "LILO"); 1503 if (!does_file_exist("/etc/lilo.conf")) { 1504 mr_free(bootldr_str); 1505 fatal_error("The de facto standard location for your boot loader's config file is /etc/lilo.conf but I cannot find it there. What is wrong with your Linux distribution?"); 1506 } 1507 } else if (bkpinfo->boot_loader == 'G') { 1508 mr_asprintf(bootldr_str, "GRUB"); 1509 if (!does_file_exist("/boot/grub/menu.lst") && does_file_exist("/boot/grub/grub.conf")) { 1510 run_program_and_log_output("ln -sf /boot/grub/grub.conf /boot/grub/menu.lst", 5); 1511 } 1512 if ((!does_file_exist("/boot/grub/menu.lst")) && (!does_file_exist("/boot/grub/grub.cfg")) && (!does_file_exist("/boot/grub2/grub.cfg"))) { 1513 /* if UEFI then search under /boot/efi */ 1514 tmp = call_program_and_get_last_line_of_output("find /boot/efi -name grub.c*"); 1515 if (strstr(tmp, "grub.c") == NULL) { 1516 mr_free(bootldr_str); 1517 fatal_error("The de facto standard location for your boot loader's config file is /boot/grub/menu.lst, /boot/grub/grub.cfg, or /boot/grub2/grub.cfg /boot/efi/.../grub.cfg but I cannot find it there. What is wrong with your Linux distribution?"); 1518 } 1519 mr_free(tmp); 1520 } 1521 bootldr_ver = call_program_and_get_last_line_of_output("grub --version 2> /dev/null"); 1522 if (strcmp(bootldr_ver,"") == 0) { 1523 mr_free(bootldr_ver); 1524 bootldr_ver = call_program_and_get_last_line_of_output("grub2-install --version"); 1525 } 1526 } else if (bkpinfo->boot_loader == 'E') { 1527 mr_asprintf(bootldr_str, "ELILO"); 1528 /* TODO: fix it for Debian, Mageia, ... */ 1529 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/redhat/elilo.conf")) { 1530 run_program_and_log_output("ln -sf /boot/efi/efi/redhat/elilo.conf /etc/elilo.conf", 5); 1531 } 1532 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/SuSE/elilo.conf")) { 1533 run_program_and_log_output("ln -sf /boot/efi/efi/SuSE/elilo.conf /etc/elilo.conf", 5); 1534 } 1535 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/efi/debian/elilo.conf")) { 1536 run_program_and_log_output ("ln -sf /boot/efi/efi/debian/elilo.conf /etc/elilo.conf", 5); 1537 } 1538 if (!does_file_exist("/etc/elilo.conf") && does_file_exist("/boot/efi/debian/elilo.conf")) { 1539 run_program_and_log_output ("ln -sf /boot/efi/debian/elilo.conf /etc/elilo.conf", 5); 1540 } 1541 if (!does_file_exist("/etc/elilo.conf")) { 1542 mr_free(bootldr_str); 1543 fatal_error("The de facto mondo standard location for your boot loader's config file is /etc/elilo.conf but I cannot find it there. What is wrong with your Linux distribution? Try finding it under /boot/efi and do 'ln -s /boot/efi/..../elilo.conf /etc/elilo.conf'"); 1544 } 1545 } else if (bkpinfo->boot_loader == 'R') { 1546 mr_asprintf(bootldr_str, "RAW"); 1547 } 1548 #ifdef __FreeBSD__ 1549 else if (bkpinfo->boot_loader == 'D') { 1550 mr_asprintf(bootldr_str, "DD"); 1551 } 1552 1553 else if (bkpinfo->boot_loader == 'B') { 1554 mr_asprintf(bootldr_str, "BOOT0"); 1555 } 1556 #endif 1557 else { 1558 mr_asprintf(bootldr_str, "unknown"); 1559 } 1560 log_to_screen("Your boot loader is %s and it boots from %s", bootldr_str, bkpinfo->boot_device); 1561 1562 if (bootldr_ver != NULL) { 1563 log_to_screen("Boot loader version string: %s", bootldr_ver); 1564 } 1565 1566 mr_asprintf(tmp, "%s/BOOTLOADER.DEVICE", bkpinfo->tmpdir); 1567 if (write_one_liner_data_file(tmp, bkpinfo->boot_device)) { 1568 log_msg(1, "%ld: Unable to write one-liner boot device", __LINE__); 1569 } 1570 mr_free(tmp); 1571 1572 switch (bkpinfo->backup_media_type) { 1573 case cdr: 1574 mr_asprintf(value, "cdr"); 1575 break; 1576 case cdstream: 1577 mr_asprintf(value, "cdstream"); 1578 break; 1579 case tape: 1580 mr_asprintf(value, "tape"); 1581 break; 1582 case udev: 1583 mr_asprintf(value, "udev"); 1584 break; 1585 case iso: 1586 mr_asprintf(value, "iso"); 1587 break; 1588 case netfs: 1589 mr_asprintf(value, "netfs"); 1590 break; 1591 case dvd: 1592 mr_asprintf(value, "dvd"); 1593 break; 1594 case usb: 1595 mr_asprintf(value, "usb"); 1596 break; 1597 default: 1598 fatal_error("Unknown backup_media_type"); 1599 } 1600 1601 if ((bkpinfo->backup_media_type == usb) && (bkpinfo->media_device)) { 1602 mr_asprintf(tmp2, "--usb %s", bkpinfo->media_device); 1603 } else { 1604 mr_asprintf(tmp2," "); 1605 } 1606 1607 mr_asprintf(tmp, "%s/BACKUP-MEDIA-TYPE", bkpinfo->tmpdir); 1608 if (write_one_liner_data_file(tmp, value)) { 1609 res++; 1610 log_msg(1, "%ld: Unable to write one-liner backup-media-type", __LINE__); 1611 } 1612 mr_free(tmp); 1613 1614 mr_asprintf(tmp, "%s/BOOTLOADER.NAME", bkpinfo->tmpdir); 1615 if (write_one_liner_data_file(tmp, bootldr_str)) { 1616 res++; 1617 log_msg(1, "%ld: Unable to write one-liner bootloader.name", __LINE__); 1618 } 1619 mr_free(bootldr_str); 1620 mr_free(tmp); 1621 1622 mr_asprintf(tmp, "%s/BOOTLOADER.VER", bkpinfo->tmpdir); 1623 if (write_one_liner_data_file(tmp, bootldr_ver)) { 1624 res++; 1625 log_msg(1, "%ld: Unable to write one-liner bootloader.ver", __LINE__); 1626 } 1627 mr_free(bootldr_ver); 1628 mr_free(tmp); 1629 1630 mr_asprintf(tmp, "%s/DIFFERENTIAL", bkpinfo->tmpdir); 1631 if (bkpinfo->differential) { 1632 res += write_one_liner_data_file(tmp, "1"); 1633 } else { 1634 res += write_one_liner_data_file(tmp, "0"); 1635 } 1636 mr_free(tmp); 1637 1638 if (g_getfattr) { 1639 mr_asprintf(tmp1, "%s/XATTR", bkpinfo->tmpdir); 1640 if (write_one_liner_data_file(tmp1, "TRUE")) { 1641 log_msg(1, "%ld: Unable to write one-liner XATTR", __LINE__); 1642 } 1643 mr_free(tmp1); 1644 } 1645 if (g_getfacl) { 1646 mr_asprintf(tmp1, "%s/ACL", bkpinfo->tmpdir); 1647 if (write_one_liner_data_file(tmp1, "TRUE")) { 1648 log_msg(1, "%ld: Unable to write one-liner ACL", __LINE__); 1649 } 1650 mr_free(tmp1); 1651 } 1652 if (bkpinfo->use_obdr) { 1653 mr_asprintf(tmp1, "%s/OBDR", bkpinfo->tmpdir); 1654 if (write_one_liner_data_file(tmp1, "TRUE")) { 1655 log_msg(1, "%ld: Unable to write one-liner OBDR", __LINE__); 1656 } 1657 mr_free(tmp1); 1658 } 1659 1660 estimated_total_noof_slices = size_of_all_biggiefiles_K() / bkpinfo->optimal_set_size + 1L; 1661 1662 /* TODO: add netfs stuff here? */ 1663 mr_asprintf(command, "mkdir -p %s/images", bkpinfo->scratchdir); 1664 if (system(command)) { 1665 res++; 1666 log_OS_error("Unable to make images directory"); 1667 } 1668 mr_free(command); 1669 log_msg(1, "lines_in_filelist = %ld", lines_in_filelist); 1670 update_evalcall_form(3); 1671 1672 unlink(MINDI_RUNFILE); 1673 mr_asprintf(command, "mindi %s --custom %s %s/images '%s' '%s' '%s' '%ld' '%s' '%s' '%s' '%s' '%s' '%ld' '%s' '%s' '%s' '%s' '%ld' '%d' '%s' '%s' '%s' '%s' 2>&1 >> %s", 1674 // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 1675 tmp2, // parameter #1 1676 bkpinfo->tmpdir, // parameter #2 1677 bkpinfo->scratchdir, // parameter #3 1678 bkpinfo->kernel_path, // parameter #4 1679 tape_device, // parameter #5 1680 tape_size_sz, // parameter #6 1681 lines_in_filelist, // parameter #7 (INT) 1682 use_lzo_sz, // parameter #8 1683 cd_recovery_sz, // parameter #9 1684 (bkpinfo->image_devs == NULL) ? "\"\"" : bkpinfo->image_devs, 1685 // parameter #10 1686 broken_bios_sz, // parameter #11 1687 last_filelist_number, // parameter #12 (STRING) 1688 estimated_total_noof_slices, 1689 // parameter #13 (INT) 1690 (bkpinfo->exclude_devs == NULL) ? "\"\"" : bkpinfo->exclude_devs, 1691 // parameter #14 1692 use_comp_sz, // parameter #15 1693 use_lilo_sz, // parameter #16 1694 use_star_sz, // parameter #17 1695 bkpinfo->internal_tape_block_size, 1696 // parameter #18 (LONG) 1697 bkpinfo->differential, // parameter #19 (INT) 1698 use_gzip_sz, // parameter #20 (STRING) 1699 use_lzma_sz, // parameter #21 (STRING) 1700 "no", // parameter #22 (STRING) bootable image ? 1701 boot_type, // parameter #23 (STRING) 1702 MINDI_RUNFILE // redirect to log file (#24) 1703 ); 1704 1705 mr_free(tmp2); 1706 mr_free(tape_device); 1707 mr_free(tape_size_sz); 1708 mr_free(use_lzo_sz); 1709 mr_free(boot_type); 1710 mr_free(cd_recovery_sz); 1711 mr_free(broken_bios_sz); 1712 mr_free(last_filelist_number); 1713 mr_free(use_comp_sz); 1714 mr_free(use_lilo_sz); 1715 mr_free(use_star_sz); 1716 mr_free(use_gzip_sz); 1717 mr_free(use_lzma_sz); 1718 mr_free(value); 1719 1720 /* This parameter is always the last one and optional */ 1721 if (bkpinfo->nonbootable_backup) { 1722 mr_strcat(command, " NONBOOTABLE"); 1723 } 1724 log_msg(2, command); 1725 1726 // TODO old call : 1727 //res = run_program_and_log_output(command, FALSE); 1728 log_msg(1, "Call to mindi"); 1729 log_msg(1, "-------------"); 1730 res = run_external_binary_with_percentage_indicator_NEW("Calling MINDI for boot disk",command); 1731 /* May crash now that we changed the call 1732 update_evalcall_form(99); 1733 */ 1734 paranoid_free(command); 1735 log_msg(1, "-------------"); 1736 log_msg(1, "End of call to mindi"); 1737 1738 if (bkpinfo->nonbootable_backup) { 1739 res = 0; 1740 } // hack 1741 if (!res) { 1742 log_to_screen("Boot+data disks were created OK"); 1743 1744 if (bkpinfo->nonbootable_backup) { 1745 mr_asprintf(command, "cp -f %s/all.tar.gz %s/images", bkpinfo->tmpdir, bkpinfo->scratchdir); 1746 if (system(command)) { 1747 mr_free(command); 1748 fatal_error("Unable to create temporary all tarball"); 1749 } 1750 mr_free(command); 1751 } 1752 /* For USB we already have everything on the key */ 1753 if (bkpinfo->backup_media_type == usb) { 1754 mr_asprintf(command, "rm -rf %s/images", bkpinfo->scratchdir); 1755 run_program_and_log_output(command, FALSE); 1756 mr_free(command); 1757 } else { 1758 mr_asprintf(tmp, "cp -f %s/images/all.tar.gz %s", bkpinfo->scratchdir, bkpinfo->tmpdir); 1759 if (system(tmp)) { 1760 fatal_error("Cannot find all.tar.gz in tmpdir"); 1761 } 1762 mr_free(tmp); 1763 } 1764 if (res) { 1765 mvaddstr_and_log_it(g_currentY++, 74, "Errors."); 1766 } else { 1767 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1768 } 1769 } else { 1770 log_to_screen("Mindi failed to create your boot+data disks."); 1771 mr_asprintf(command, "grep 'Fatal error' %s", MINDI_LOGFILE); 1772 tmp = call_program_and_get_last_line_of_output(command); 1773 mr_free(command); 1774 1775 if (strlen(tmp) > 1) { 1776 popup_and_OK(tmp); 1777 } 1778 mr_free(tmp); 1779 } 1780 close_evalcall_form(); 1781 return (res); 1782 } 1783 1784 1785 1786 /** 1787 * Wrapper function for all the backup commands. 1788 * Calls these other functions: @c prepare_filelist(), 1789 * @c call_filelist_chopper(), @c copy_mondo_and_mindi_stuff_to_scratchdir(), 1790 * @c call_mindi_to_supply_boot_disks(), @c do_that_initial_phase(), 1791 * @c make_those_afios_phase(), @c make_those_slices_phase(), and 1792 * @c do_that_final_phase(). If anything fails before @c do_that_initial_phase(), 1793 * @c fatal_error is called with a suitable message. 1794 * @param bkpinfo The backup information structure. Uses most fields. 1795 * @return The number of non-fatal errors encountered (0 for success). 1796 * @ingroup archiveGroup 1797 */ 1798 int backup_data() 1799 { 1800 int retval = 0, res = 0; 1801 char *tmp = NULL; 1802 1803 assert(bkpinfo != NULL); 1804 1805 if (bkpinfo->backup_media_type == dvd) { 1806 #ifdef DVDRWFORMAT 1807 if ((tmp = find_home_of_exe("dvd+rw-format")) == NULL) { 1808 mr_free(tmp); 1809 fatal_error("Cannot find dvd+rw-format. Please install it or fix your PATH."); 1810 } 1811 mr_free(tmp); 1812 #endif 1813 if ((tmp = find_home_of_exe("growisofs")) == NULL) { 1814 mr_free(tmp); 1815 fatal_error("Cannot find growisofs. Please install it or fix your PATH."); 1816 } 1817 mr_free(tmp); 1818 } 1819 1820 if ((res = prepare_filelist())) { /* generate scratchdir/filelist.full */ 1821 fatal_error("Failed to generate filelist catalog"); 1822 } 1823 if (call_filelist_chopper()) { 1824 fatal_error("Failed to run filelist chopper"); 1825 } 1826 1827 mr_asprintf(tmp, "gzip -9 %s/archives/filelist.full", bkpinfo->scratchdir); 1828 if (run_program_and_log_output(tmp, 2)) { 1829 mr_free(tmp); 1830 fatal_error("Failed to gzip filelist.full"); 1831 } 1832 mr_free(tmp); 1833 1834 mr_asprintf(tmp, "cp -f %s/archives/*list*.gz %s", bkpinfo->scratchdir, bkpinfo->tmpdir); 1835 if (run_program_and_log_output(tmp, 2)) { 1836 mr_free(tmp); 1837 fatal_error("Failed to copy to tmpdir"); 1838 } 1839 mr_free(tmp); 1840 1841 copy_mondo_and_mindi_stuff_to_scratchdir(); // payload, too, if it exists 1842 if ((res = call_mindi_to_supply_boot_disks())) { 1843 fatal_error("Failed to generate boot+data disks"); 1844 } 1845 retval += do_that_initial_phase(); // prepare 1846 mr_asprintf(tmp, "rm -f %s/images/*.iso", bkpinfo->scratchdir); 1847 run_program_and_log_output(tmp, 1); 1848 mr_free(tmp); 1849 1850 retval += make_those_afios_phase(); // backup regular files 1851 retval += make_those_slices_phase(); // backup BIG files 1852 retval += do_that_final_phase(); // clean up 1853 log_msg(1, "Creation of archives... complete."); 1854 if (bkpinfo->verify_data) { 1855 sleep(2); 1856 } 1857 return (retval); 1858 } 1859 1860 1861 1862 /** 1863 * Set the <tt>N</tt>th bit of @c array to @c true_or_false. 1864 * @param array The bit array (as a @c char pointer). 1865 * @param N The bit number to set or reset. 1866 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N. 1867 * @see get_bit_N_of_array 1868 */ 1869 void set_bit_N_of_array(char *array, int N, bool true_or_false) 1870 { 1871 int bit_number; 1872 int mask, orig_val, to_add; 1873 int element_number; 1874 1875 assert(array != NULL); 1876 1877 element_number = N / 8; 1878 bit_number = N % 8; 1879 to_add = (1 << bit_number); 1880 mask = 255 - to_add; 1881 orig_val = array[element_number] & mask; 1882 // log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val); 1883 if (true_or_false) { 1884 array[element_number] = orig_val | to_add; 1885 } 1886 } 1887 1888 1889 1890 /** 1891 * Maximum number of filesets allowed in this function. 1892 */ 1893 #define MAX_NOOF_SETS_HERE 32767 1894 1895 /** 1896 * Offset of the bkpinfo pointer (in bytes) from the 1897 * buffer passed to create_afio_files_in_background. 1898 */ 1899 #define BKPINFO_LOC_OFFSET (16+MAX_NOOF_SETS_HERE/8+16) 1900 1901 /** 1902 * Main function for each @c afio thread. 1903 * @param inbuf A transfer block containing: 1904 * - @c p_last_set_archived: [offset 0] pointer to an @c int 1905 * containing the last set archived. 1906 * - @c p_archival_threads_running: [offset 4] pointer to an @c int 1907 * containing the number of archival threads currently running. 1908 * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing 1909 * the next set that should be archived. 1910 * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a 1911 * bit array, where each bit corresponds to a filelist (1=needs 1912 * to be archived, 0=archived). 1913 * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information 1914 * structure. Fields used: 1915 * - @c tmpdir 1916 * - @c zip_suffix 1917 * 1918 * Any of the above may be modified by the caller at any time. 1919 * 1920 * @bug Assumes @c int pointers are 4 bytes. 1921 * @see archive_this_fileset 1922 * @see make_afioballs_and_images 1923 * @return NULL, always. 1924 * @ingroup LLarchiveGroup 1925 */ 1926 void *create_afio_files_in_background(void *inbuf) 1927 { 1928 long int archiving_set_no = 0L; 1929 char *archiving_filelist_fname = NULL; 1930 char *archiving_afioball_fname = NULL; 1931 char *curr_xattr_list_fname = NULL; 1932 char *curr_acl_list_fname = NULL; 1933 1934 char *tmp = NULL; 1935 int res = 0, retval = 0; 1936 int *p_archival_threads_running; 1937 int *p_last_set_archived; 1938 int *p_next_set_to_archive; 1939 char *p_list_of_fileset_flags; 1940 int this_thread_no = g_current_thread_no++; 1941 1942 p_last_set_archived = (int *) inbuf; 1943 p_archival_threads_running = (int *) (inbuf + 4); 1944 p_next_set_to_archive = (int *) (inbuf + 8); 1945 p_list_of_fileset_flags = (char *) (inbuf + 12); 1946 1947 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L); 1948 1949 while (does_file_exist(archiving_filelist_fname)) { 1950 if (g_exiting) { 1951 mr_free(archiving_filelist_fname); 1952 fatal_error("Execution run aborted (pthread)"); 1953 } 1954 if (archiving_set_no >= MAX_NOOF_SETS_HERE) { 1955 mr_free(archiving_filelist_fname); 1956 fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please."); 1957 } 1958 if (!semaphore_p()) { 1959 log_msg(3, "P sem failed (pid=%d)", (int) getpid()); 1960 mr_free(archiving_filelist_fname); 1961 fatal_error("Cannot get semaphore P"); 1962 } 1963 if (archiving_set_no < *p_next_set_to_archive) { 1964 archiving_set_no = *p_next_set_to_archive; 1965 } 1966 *p_next_set_to_archive = *p_next_set_to_archive + 1; 1967 if (!semaphore_v()) { 1968 mr_free(archiving_filelist_fname); 1969 fatal_error("Cannot get semaphore V"); 1970 } 1971 1972 /* backup this set of files */ 1973 mr_asprintf(archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no, bkpinfo->zip_suffix); 1974 mr_free(archiving_filelist_fname); 1975 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 1976 if (!does_file_exist(archiving_filelist_fname)) { 1977 log_msg(3, "%s[%d:%d] - well, I would archive %d, except that it doesn't exist. I'll stop now.", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 1978 mr_free(archiving_afioball_fname); 1979 break; 1980 } 1981 1982 mr_asprintf(tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no - ARCH_BUFFER_NUM, bkpinfo->zip_suffix); 1983 if (does_file_exist(tmp)) { 1984 log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no); 1985 while (does_file_exist(tmp)) { 1986 sleep(1); 1987 } 1988 log_msg(4, "[%d] - continuing", getpid()); 1989 } 1990 mr_free(tmp); 1991 1992 log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 1993 1994 if (g_getfattr) { 1995 mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 1996 get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname); 1997 mr_free(curr_xattr_list_fname); 1998 } 1999 if (g_getfacl) { 2000 mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 2001 get_acl_list(archiving_filelist_fname, curr_acl_list_fname); 2002 mr_free(curr_acl_list_fname); 2003 } 2004 2005 log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 2006 res = archive_this_fileset(archiving_filelist_fname, archiving_afioball_fname, archiving_set_no); 2007 mr_free(archiving_afioball_fname); 2008 2009 retval += res; 2010 2011 if (res) { 2012 log_to_screen("Errors occurred while archiving set %ld. Please review logs.", archiving_set_no); 2013 } 2014 2015 if (!semaphore_p()) { 2016 mr_free(archiving_filelist_fname); 2017 fatal_error("Cannot get semaphore P"); 2018 } 2019 2020 set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5); 2021 2022 if (*p_last_set_archived < archiving_set_no) { 2023 *p_last_set_archived = archiving_set_no; 2024 } // finished archiving this one 2025 2026 if (!semaphore_v()) { 2027 mr_free(archiving_filelist_fname); 2028 fatal_error("Cannot get semaphore V"); 2029 } 2030 log_msg(4, "%s[%d:%d] - archived %d OK", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 2031 archiving_set_no++; 2032 2033 mr_free(archiving_filelist_fname); 2034 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 2035 } 2036 mr_free(archiving_filelist_fname); 2037 2038 if (!semaphore_p()) { 2039 fatal_error("Cannot get semaphore P"); 2040 } 2041 (*p_archival_threads_running)--; 2042 if (!semaphore_v()) { 2043 fatal_error("Cannot get semaphore V"); 2044 } 2045 log_msg(3, "%s[%d:%d] - exiting", FORTY_SPACES, getpid(), this_thread_no); 2046 pthread_exit(NULL); 2047 } 2048 2049 2050 /** 2051 * Get the <tt>N</tt>th bit of @c array. 2052 * @param array The bit-array (as a @c char pointer). 2053 * @param N The number of the bit you want. 2054 * @return TRUE (bit is set) or FALSE (bit is not set). 2055 * @see set_bit_N_of_array 2056 * @ingroup utilityGroup 2057 */ 2058 bool get_bit_N_of_array(char *array, int N) 2059 { 2060 int element_number; 2061 int bit_number; 2062 int mask; 2063 2064 element_number = N / 8; 2065 bit_number = N % 8; 2066 mask = 1 << bit_number; 2067 if (array[element_number] & mask) { 2068 return (TRUE); 2069 } else { 2070 return (FALSE); 2071 } 2072 } 2073 2074 2075 /** 2076 * Move some files to the ISO scratch directory. 2077 * This function moves files specified as parameters, into the directory 2078 * @c bkpinfo->scratchdir, where the files that will be stored on the next 2079 * CD are waiting. 2080 * 2081 * @param bkpinfo The backup information structure. Fields used: 2082 * - @c media_size 2083 * - @c scratchdir 2084 * @param files_to_add The files to add to the scratchdir. 2085 * @warning The list of @c files_to_add must be terminated with @c NULL. 2086 * @note If and when the space occupied by the scratchdir would exceed 2087 * the capacity of the current CD, 2088 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the 2089 * scratchdir is emptied. 2090 * 2091 * @return The number of errors encountered (0 for success) 2092 */ 2093 int _move_files_to_cd(char *files_to_add, ...) 2094 { 2095 2096 /*@ int ************************************************************ */ 2097 int retval = 0; 2098 int res = 0; 2099 2100 /*@ buffers ******************************************************** */ 2101 char *tmp = NULL; 2102 char *curr_file = NULL; 2103 char *cf; 2104 2105 /*@ long ************************************************************ */ 2106 va_list ap; 2107 long long would_occupy; 2108 2109 assert(bkpinfo != NULL); 2110 would_occupy = space_occupied_by_cd(bkpinfo->scratchdir); 2111 va_start(ap, files_to_add); // initialize the variable arguments 2112 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) { 2113 if (!cf) { 2114 continue; 2115 } 2116 mr_asprintf(curr_file, "%s", cf); 2117 if (!does_file_exist(curr_file)) { 2118 log_msg(1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file); 2119 } else { 2120 log_msg(8, "Trying to add file %s to CD", curr_file); 2121 would_occupy += length_of_file(curr_file) / 1024; 2122 } 2123 mr_free(curr_file); 2124 } 2125 va_end(ap); 2126 2127 if (bkpinfo->media_size <= 0) { 2128 fatal_error("move_files_to_cd() - unknown media size"); 2129 } 2130 if (would_occupy / 1024 > bkpinfo->media_size) { 2131 res = write_iso_and_go_on(FALSE); /* FALSE because this is not the last CD we'll write */ 2132 retval += res; 2133 if (res) { 2134 log_msg(1, "WARNING - write_iso_and_go_on returned an error"); 2135 } 2136 } 2137 2138 va_start(ap, files_to_add); // initialize the variable arguments 2139 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) { 2140 if (!cf) { 2141 continue; 2142 } 2143 mr_asprintf(curr_file, "%s", cf); 2144 2145 mr_asprintf(tmp, "mv -f %s %s/archives/", curr_file, bkpinfo->scratchdir); 2146 mr_free(curr_file); 2147 res = run_program_and_log_output(tmp, 5); 2148 retval += res; 2149 if (res) { 2150 log_msg(1, "(move_files_to_cd) '%s' failed", tmp); 2151 } else { 2152 log_msg(8, "Moved %s to CD OK", tmp); 2153 } 2154 mr_free(tmp); 2155 } 2156 va_end(ap); 2157 2158 if (retval) { 2159 log_msg(1, 2160 "Warning - errors occurred while I was adding files to CD dir"); 2161 } 2162 return (retval); 2163 } 2164 2165 /* @} - end of LLarchiveGroup */ 2166 2167 /** 2168 * Copy some files to tape. 2169 * This function copies the files specified as parameters into the tape stream. 2170 * 2171 * @param bkpinfo The backup information structure. Used only in the call to 2172 * @c write_file_to_stream_from_file(). 2173 * 2174 * @param files_to_add The files to copy to the tape stream. 2175 * @warning The list of @c files_to_add must be terminated with @c NULL. 2176 * @note Files may be split across multiple tapes if necessary. 2177 * 2178 * @return The number of errors encountered (0 for success) 2179 */ 2180 int 2181 _move_files_to_stream(char *files_to_add, ...) 2182 { 2183 2184 /*@ int ************************************************************ */ 2185 int retval = 0; 2186 int res = 0; 2187 /*@ buffers ******************************************************** */ 2188 2189 /*@ char *********************************************************** */ 2190 char start_chr; 2191 char stop_chr; 2192 char *curr_file = NULL; 2193 char *cf; 2194 /*@ long long ****************************************************** */ 2195 off_t length_of_incoming_file = (off_t)0; 2196 va_list ap; 2197 2198 assert(bkpinfo != NULL); 2199 va_start(ap, files_to_add); 2200 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) { 2201 if (!cf) { 2202 continue; 2203 } 2204 mr_asprintf(curr_file, "%s", cf); 2205 if (!does_file_exist(curr_file)) { 2206 log_msg(1, 2207 "Warning - you're trying to add a non-existent file - '%s' to the tape", 2208 curr_file); 2209 } 2210 /* create header chars */ 2211 start_chr = BLK_START_AN_AFIO_OR_SLICE; 2212 stop_chr = BLK_STOP_AN_AFIO_OR_SLICE; 2213 /* ask for new tape if necessary */ 2214 length_of_incoming_file = length_of_file(curr_file); 2215 write_header_block_to_stream(length_of_incoming_file, curr_file, start_chr); 2216 res = write_file_to_stream_from_file(curr_file); 2217 retval += res; 2218 unlink(curr_file); 2219 mr_free(curr_file); 2220 /* write closing header */ 2221 write_header_block_to_stream((off_t)0, "finished-writing-file", stop_chr); 2222 } 2223 va_end(ap); 2224 2225 if (retval) { 2226 log_msg(1, 2227 "Warning - errors occurred while I was adding file to tape"); 2228 } 2229 return (retval); 2230 } 2231 2232 2233 /** 2234 * @addtogroup LLarchiveGroup 2235 * @{ 2236 */ 2237 /** 2238 * Function pointer to an appropriate @c move_files_to_stream routine. 2239 * You can set this to your own function (for example, one to 2240 * transfer files over the network) or leave it as is. 2241 */ 2242 int (*move_files_to_stream) (char *, ...) = 2243 _move_files_to_stream; 2244 2245 2246 /** 2247 * Function pointer to an appropriate @c move_files_to_cd routine. 2248 * You can set this to your own function (for example, one to 2249 * transfer files over the network) or leave it as is. 2250 */ 2251 int (*move_files_to_cd) (char *, ...) = 2252 _move_files_to_cd; 2253 2254 2255 2256 /** 2257 * @addtogroup LLarchiveGroup 2258 * @{ 2259 */ 2260 1651 2261 void pause_for_N_seconds(int how_long, char *msg) 1652 2262 { … … 1772 2382 } 1773 2383 return(retval); 2384 } 2385 2386 /** 2387 * Make sure the user has a valid CD-R(W) in the CD drive. 2388 * @param cd_dev Set to the CD-R(W) device checked. 2389 * @param keep_looping If TRUE, keep pestering user until they insist 2390 * or insert a correct CD; if FALSE, only check once. 2391 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't). 2392 */ 2393 int interrogate_disk_currently_in_cddrive(char *cd_dev, 2394 bool keep_looping) 2395 { 2396 int res = 0; 2397 char *bkp = NULL; 2398 char *cdrecord = NULL; 2399 2400 mr_asprintf(bkp, "%s", cd_dev); 2401 if ((cd_dev = find_optical_device()) != NULL) { 2402 if (!system("which cdrecord > /dev/null 2> /dev/null")) { 2403 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev); 2404 } else if (!system("which dvdrecord > /dev/null 2> /dev/null")) { 2405 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev); 2406 } else { 2407 log_msg(2, "Oh well. I guess I'll just pray then."); 2408 } 2409 if (cdrecord != NULL) { 2410 if (!keep_looping) { 2411 retract_CD_tray_and_defeat_autorun(); 2412 res = run_program_and_log_output(cdrecord, 5); 2413 } else { 2414 while ((res = run_program_and_log_output(cdrecord, 5))) { 2415 retract_CD_tray_and_defeat_autorun(); 2416 if (ask_me_yes_or_no 2417 ("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?")) 2418 { 2419 log_msg(1, "Well, he insisted..."); 2420 break; 2421 } 2422 } 2423 } 2424 } 2425 } 2426 mr_free(bkp); 2427 2428 mr_free(cdrecord); 2429 return (res); 1774 2430 } 1775 2431 … … 2482 3138 2483 3139 2484 /**2485 * Back up big files by chopping them up.2486 * This function backs up all "big" files (where "big" depends2487 * on your backup media) in "chunks" (whose size again depends2488 * on your media).2489 *2490 * @param bkpinfo The backup information structure. Fields used:2491 * - @c backup_media_type2492 * - @c optimal_set_size2493 * @param biggielist_fname The path to a file containing a list of2494 * all "big" files.2495 * @return The number of errors encountered (0 for success)2496 * @see slice_up_file_etc2497 */2498 int make_slices_and_images(char *biggielist_fname) {2499 2500 /*@ pointers ******************************************* */2501 FILE *fin = NULL;2502 char *p;2503 char *q;2504 2505 /*@ buffers ******************************************** */2506 char *tmp = NULL;2507 char *bigfile_fname = NULL;2508 char *sz_devfile = NULL;2509 char *ntfsprog_fifo = NULL;2510 /*@ long *********************************************** */2511 long biggie_file_number = 0L;2512 long noof_biggie_files = 0L;2513 long estimated_total_noof_slices = 0L;2514 long size_of_all_biggiefiles = 0L;2515 2516 /*@ int ************************************************ */2517 int retval = 0;2518 int res = 0;2519 pid_t pid;2520 FILE *ftmp = NULL;2521 bool delete_when_done;2522 bool use_ntfsprog;2523 off_t biggie_fsize;2524 2525 assert(bkpinfo != NULL);2526 assert_string_is_neither_NULL_nor_zerolength(biggielist_fname);2527 2528 size_of_all_biggiefiles = size_of_all_biggiefiles_K();2529 estimated_total_noof_slices = size_of_all_biggiefiles / bkpinfo->optimal_set_size + 1L;2530 2531 log_msg(1, "size of all biggiefiles = %ld", size_of_all_biggiefiles);2532 log_msg(1, "estimated_total_noof_slices = %ld KB / %ld KB = %ld", size_of_all_biggiefiles, bkpinfo->optimal_set_size, estimated_total_noof_slices);2533 2534 if (length_of_file(biggielist_fname) < 6) {2535 log_msg(1, "No biggiefiles; fair enough...");2536 return (0);2537 }2538 mr_asprintf(tmp, "I am now backing up all large files.");2539 log_to_screen(tmp);2540 noof_biggie_files = count_lines_in_file(biggielist_fname);2541 log_msg(1, "noof_biggie_files = %ld", noof_biggie_files);2542 open_progress_form("Backing up big files", tmp, "Please wait. This may take some time.", "", estimated_total_noof_slices);2543 mr_free(tmp);2544 2545 if (!(fin = fopen(biggielist_fname, "r"))) {2546 log_OS_error("Unable to openin biggielist");2547 return (1);2548 }2549 2550 malloc_string(bigfile_fname);2551 for (q = fgets(bigfile_fname, MAX_STR_LEN, fin); !feof(fin) && (q != NULL);2552 q = fgets(bigfile_fname, MAX_STR_LEN, fin), biggie_file_number++) {2553 use_ntfsprog = FALSE;2554 if (bigfile_fname[strlen(bigfile_fname) - 1] < 32) {2555 bigfile_fname[strlen(bigfile_fname) - 1] = '\0';2556 }2557 biggie_fsize = length_of_file(bigfile_fname);2558 delete_when_done = FALSE;2559 2560 if (!does_file_exist(bigfile_fname)) {2561 ftmp = fopen(bigfile_fname, "w");2562 if (ftmp == NULL) {2563 log_msg(3, "Unable to write to %s", bigfile_fname);2564 // So skip it as it doesn't exist2565 continue;2566 } else {2567 paranoid_fclose(ftmp);2568 }2569 delete_when_done = TRUE;2570 } else {2571 // Call ntfsclone (formerly partimagehack) if it's a /dev entry2572 // (i.e. a partition to be imaged)2573 log_msg(2, "bigfile_fname = %s", bigfile_fname);2574 use_ntfsprog = FALSE;2575 if (!strncmp(bigfile_fname, "/dev/", 5) && is_dev_an_NTFS_dev(bigfile_fname)) {2576 use_ntfsprog = TRUE;2577 log_msg(2, "Calling ntfsclone in background because %s is an NTFS partition", bigfile_fname);2578 mr_asprintf(sz_devfile, "%s/%d.%d.000", bkpinfo->tmpdir, (int) (random() % 32768), (int) (random() % 32768));2579 mkfifo(sz_devfile, 0x770);2580 ntfsprog_fifo = sz_devfile;2581 switch (pid = fork()) {2582 case -1:2583 mr_free(sz_devfile);2584 fatal_error("Fork failure");2585 case 0:2586 log_msg(2, "CHILD - fip - calling feed_into_ntfsprog(%s, %s)", bigfile_fname, sz_devfile);2587 res = feed_into_ntfsprog(bigfile_fname, sz_devfile);2588 /* TODO: Does the child need to unalocate memory as well ?2589 mr_free(bigfile_fname);2590 mr_free(sz_devfile);2591 */2592 exit(res);2593 break;2594 default:2595 log_msg(2, "feed_into_ntfsprog() called in background --- pid=%ld", (long int) (pid));2596 }2597 }2598 // Otherwise, use good old 'dd' and 'bzip2'2599 else {2600 ntfsprog_fifo = NULL;2601 }2602 2603 // Whether partition or biggiefile, just do your thang :-)2604 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {2605 write_header_block_to_stream(biggie_fsize, bigfile_fname, use_ntfsprog ? BLK_START_A_PIHBIGGIE : BLK_START_A_NORMBIGGIE);2606 }2607 res = slice_up_file_etc(bigfile_fname, ntfsprog_fifo, biggie_file_number, noof_biggie_files, use_ntfsprog);2608 2609 /* Free it here as ntfsprog_fifo is not used anymore */2610 mr_free(sz_devfile);2611 2612 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {2613 write_header_block_to_stream((off_t)0, calc_checksum_of_file(bigfile_fname), BLK_STOP_A_BIGGIE);2614 }2615 retval += res;2616 p = strrchr(bigfile_fname, '/');2617 if (p) {2618 p++;2619 } else {2620 p = bigfile_fname;2621 }2622 mr_asprintf(tmp, "Archiving %s ... ", bigfile_fname);2623 if (res) {2624 mr_strcat(tmp, "Failed!");2625 } else {2626 mr_strcat(tmp, "OK");2627 }2628 if (delete_when_done) {2629 unlink(bigfile_fname);2630 delete_when_done = FALSE;2631 }2632 }2633 if (!g_text_mode) {2634 newtDrawRootText(0, g_noof_rows - 2, tmp);2635 newtRefresh();2636 }2637 mr_free(tmp);2638 }2639 mr_free(bigfile_fname);2640 2641 log_msg(1, "Finished backing up bigfiles");2642 log_msg(1, "estimated slices = %ld; actual slices = %ld", estimated_total_noof_slices, g_current_progress);2643 close_progress_form();2644 paranoid_fclose(fin);2645 return (retval);2646 }2647 2648 2649 2650 2651 /**2652 * Single-threaded version of @c make_afioballs_and_images().2653 * @see make_afioballs_and_images2654 */2655 int make_afioballs_and_images_OLD()2656 {2657 2658 /*@ int ************************************************** */2659 int retval = 0;2660 long int curr_set_no = 0L;2661 int res = 0;2662 2663 /*@ buffers ********************************************** */2664 char *curr_filelist_fname = NULL;2665 char *curr_afioball_fname = NULL;2666 char *curr_xattr_list_fname = NULL;2667 char *curr_acl_list_fname = NULL;2668 char *tmp = NULL;2669 char *media_usage_comment = NULL;2670 2671 log_to_screen("Archiving regular files");2672 2673 open_progress_form("Backing up filesystem",2674 "I am backing up your live filesystem now.",2675 "Please wait. This may take a couple of hours.",2676 "Working...",2677 get_last_filelist_number() + 1);2678 2679 for (;;) {2680 /* backup this set of files */2681 mr_asprintf(curr_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);2682 if (! does_file_exist(curr_filelist_fname)) {2683 mr_free(curr_filelist_fname);2684 break;2685 }2686 2687 mr_asprintf(curr_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no, bkpinfo->zip_suffix);2688 2689 log_msg(1, "EXAT'g set %ld", curr_set_no);2690 if (g_getfattr) {2691 mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);2692 get_fattr_list(curr_filelist_fname, curr_xattr_list_fname);2693 }2694 if (g_getfacl) {2695 mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, curr_set_no);2696 get_acl_list(curr_filelist_fname, curr_acl_list_fname);2697 }2698 2699 log_msg(1, "Archiving set %ld", curr_set_no);2700 res = archive_this_fileset(curr_filelist_fname, curr_afioball_fname, curr_set_no);2701 retval += res;2702 if (res) {2703 log_to_screen("Errors occurred while archiving set %ld. Perhaps your live filesystem changed?", curr_set_no);2704 }2705 2706 /* copy to CD (scratchdir) ... and an actual CD-R if necessary */2707 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {2708 register_in_tape_catalog(fileset, curr_set_no, -1, curr_afioball_fname);2709 maintain_collection_of_recent_archives(bkpinfo->tmpdir, curr_afioball_fname);2710 log_it("Writing EXAT files");2711 res +=2712 write_EXAT_files_to_tape(curr_xattr_list_fname,2713 curr_acl_list_fname);2714 // archives themselves2715 res = move_files_to_stream(curr_afioball_fname, NULL);2716 } else {2717 if (g_getfacl) {2718 if (g_getfattr) {2719 res = move_files_to_cd(curr_filelist_fname,2720 curr_xattr_list_fname,2721 curr_acl_list_fname,2722 curr_afioball_fname, NULL);2723 } else {2724 res = move_files_to_cd(curr_filelist_fname,2725 curr_acl_list_fname,2726 curr_afioball_fname, NULL);2727 }2728 } else {2729 if (g_getfattr) {2730 res = move_files_to_cd(curr_filelist_fname,2731 curr_xattr_list_fname,2732 curr_afioball_fname, NULL);2733 } else {2734 res = move_files_to_cd(curr_filelist_fname,2735 curr_afioball_fname, NULL);2736 }2737 }2738 }2739 if (g_getfattr) {2740 mr_free(curr_xattr_list_fname);2741 }2742 if (g_getfacl) {2743 mr_free(curr_acl_list_fname);2744 }2745 retval += res;2746 g_current_progress++;2747 2748 media_usage_comment = percent_media_full_comment();2749 update_progress_form(media_usage_comment);2750 mr_free(media_usage_comment);2751 2752 if (res) {2753 log_to_screen("Failed to add archive %ld's files to CD dir\n", curr_set_no);2754 fatal_error("Is your hard disk is full? If not, please send the author the logfile.");2755 }2756 mr_free(curr_filelist_fname);2757 mr_free(curr_afioball_fname);2758 curr_set_no++;2759 }2760 close_progress_form();2761 mr_asprintf(tmp, "Your regular files have been archived ");2762 if (retval) {2763 mr_strcat(tmp, "(with errors).");2764 } else {2765 mr_strcat(tmp, "successfully.");2766 }2767 log_to_screen(tmp);2768 mr_free(tmp);2769 return (retval);2770 }2771 2772 3140 /* @} - end of LLarchiveGroup */ 2773 2774 /**2775 * Write an ISO image to <tt>[bkpinfo->isodir]/bkpinfo->prefix-[g_current_media_number].iso</tt>.2776 * @param bkpinfo The backup information structure. Fields used:2777 * - @c backup_media_type2778 * - @c prefix2779 * - @c isodir2780 * - @c manual_cd_tray2781 * - @c media_size2782 * - @c netfs_remote_dir2783 * - @c scratchdir2784 * - @c verify_data2785 *2786 * @param last_cd If TRUE, this is the last CD to write; if FALSE, it's not.2787 * @return The number of errors encountered (0 for success)2788 * @see make_iso_fs2789 */2790 int write_iso_and_go_on(bool last_cd)2791 {2792 /*@ pointers **************************************************** */2793 FILE *fout;2794 2795 /*@ buffers ***************************************************** */2796 char *tmp = NULL;2797 char *tmp1 = NULL;2798 char *cdno_fname = NULL;2799 char *lastcd_fname = NULL;2800 char *isofile = NULL;2801 char *mds = NULL;2802 2803 /*@ bool ******************************************************** */2804 bool that_one_was_ok;2805 bool orig_vfy_flag_val;2806 2807 /*@ int *********************************************************** */2808 int res = 0;2809 2810 assert(bkpinfo != NULL);2811 orig_vfy_flag_val = bkpinfo->verify_data;2812 if (bkpinfo->media_size <= 0) {2813 fatal_error("write_iso_and_go_on() - unknown media size");2814 }2815 2816 mds = media_descriptor_string(bkpinfo->backup_media_type);2817 log_msg(1, "OK, time to make %s #%d", mds, g_current_media_number);2818 mr_free(mds);2819 2820 /* label the ISO with its number */2821 2822 mr_asprintf(cdno_fname, "%s/archives/THIS-CD-NUMBER", bkpinfo->scratchdir);2823 fout = fopen(cdno_fname, "w");2824 mr_free(cdno_fname);2825 2826 fprintf(fout, "%d", g_current_media_number);2827 paranoid_fclose(fout);2828 2829 mr_asprintf(tmp1, "cp -f %s/autorun %s/", g_mondo_home, bkpinfo->scratchdir);2830 if (run_program_and_log_output(tmp1, FALSE)) {2831 log_msg(2, "Warning - unable to copy autorun to scratchdir");2832 }2833 mr_free(tmp1);2834 2835 /* last CD or not? Label accordingly */2836 mr_asprintf(lastcd_fname, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);2837 if (last_cd) {2838 unlink(lastcd_fname);2839 log_msg(2,2840 "OK, you're telling me this is the last CD. Fair enough.");2841 } else {2842 fout = fopen(lastcd_fname, "w");2843 fprintf(fout,2844 "You're listening to 90.3 WPLN, Nashville Public Radio.\n");2845 paranoid_fclose(fout);2846 }2847 mr_free(lastcd_fname);2848 2849 if (space_occupied_by_cd(bkpinfo->scratchdir) / 1024 > bkpinfo->media_size) {2850 log_to_screen("Warning! CD is too big. It occupies %ld KB, which is more than the %ld MB allowed.",(long) space_occupied_by_cd(bkpinfo->scratchdir),(long) bkpinfo->media_size);2851 }2852 2853 if (bkpinfo->netfs_remote_dir != NULL) {2854 // NETFS2855 mr_asprintf(isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);2856 } else {2857 // ISO2858 mr_asprintf(isofile, "%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number);2859 }2860 for (that_one_was_ok = FALSE; !that_one_was_ok;) {2861 if (bkpinfo->backup_media_type != usb) {2862 res = make_iso_fs(isofile);2863 } else {2864 res = make_usb_fs();2865 }2866 if (g_current_media_number == 1 && !res2867 && (bkpinfo->backup_media_type == cdr)) {2868 if ((tmp = find_optical_device()) == NULL) { // make sure find_optical_device() finds, records CD-R's loc2869 log_msg(3, "*Sigh* Mike, I hate your computer.");2870 // if it can't be found then force pausing2871 bkpinfo->manual_cd_tray = TRUE;2872 } else {2873 log_msg(3, "Great. Found Mike's CD-ROM drive.");2874 }2875 mr_free(tmp);2876 }2877 if (bkpinfo->verify_data && !res) {2878 mds = media_descriptor_string(g_backup_media_type);2879 log_to_screen("Please reboot from the 1st %s in Compare Mode, as a precaution.", mds);2880 mr_free(mds);2881 if (chdir("/")) {2882 // FIXME2883 }2884 log_it("Before calling verification of image()");2885 if (bkpinfo->backup_media_type == usb) {2886 res += verify_usb_image();2887 } else {2888 res += verify_cd_image();2889 }2890 log_it("After calling verification of image()");2891 }2892 if (!res) {2893 that_one_was_ok = TRUE;2894 } else {2895 mds = media_descriptor_string(bkpinfo->backup_media_type);2896 mr_asprintf(tmp1, "Failed to create %s #%d. Retry?", mds, g_current_media_number);2897 mr_free(mds);2898 res = ask_me_yes_or_no(tmp1);2899 mr_free(tmp1);2900 2901 if (!res) {2902 if (ask_me_yes_or_no("Abort the backup?")) {2903 fatal_error("FAILED TO BACKUP");2904 } else {2905 break;2906 }2907 } else {2908 log_msg(2, "Retrying, at user's request...");2909 res = 0;2910 }2911 }2912 }2913 mr_free(isofile);2914 2915 g_current_media_number++;2916 wipe_archives(bkpinfo->scratchdir);2917 mr_asprintf(tmp1, "rm -Rf %s/images/*gz %s/images/*data*img", bkpinfo->scratchdir, bkpinfo->scratchdir);2918 if (system(tmp1)) {2919 log_msg(2, "Error occurred when I tried to delete the redundant IMGs and GZs");2920 }2921 mr_free(tmp1);2922 2923 if (last_cd) {2924 log_msg(2, "This was your last media.");2925 } else {2926 log_msg(2, "Continuing to backup your data...");2927 }2928 2929 bkpinfo->verify_data = orig_vfy_flag_val;2930 return (0);2931 }2932 2933 /* @} - end of LLarchiveGroup */2934 2935 /**2936 * Move some files to the ISO scratch directory.2937 * This function moves files specified as parameters, into the directory2938 * @c bkpinfo->scratchdir, where the files that will be stored on the next2939 * CD are waiting.2940 *2941 * @param bkpinfo The backup information structure. Fields used:2942 * - @c media_size2943 * - @c scratchdir2944 * @param files_to_add The files to add to the scratchdir.2945 * @warning The list of @c files_to_add must be terminated with @c NULL.2946 * @note If and when the space occupied by the scratchdir would exceed2947 * the capacity of the current CD,2948 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the2949 * scratchdir is emptied.2950 *2951 * @return The number of errors encountered (0 for success)2952 */2953 int _move_files_to_cd(char *files_to_add, ...)2954 {2955 2956 /*@ int ************************************************************ */2957 int retval = 0;2958 int res = 0;2959 2960 /*@ buffers ******************************************************** */2961 char *tmp = NULL;2962 char *curr_file = NULL;2963 char *cf;2964 2965 /*@ long ************************************************************ */2966 va_list ap;2967 long long would_occupy;2968 2969 assert(bkpinfo != NULL);2970 would_occupy = space_occupied_by_cd(bkpinfo->scratchdir);2971 va_start(ap, files_to_add); // initialize the variable arguments2972 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {2973 if (!cf) {2974 continue;2975 }2976 mr_asprintf(curr_file, "%s", cf);2977 if (!does_file_exist(curr_file)) {2978 log_msg(1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file);2979 } else {2980 log_msg(8, "Trying to add file %s to CD", curr_file);2981 would_occupy += length_of_file(curr_file) / 1024;2982 }2983 mr_free(curr_file);2984 }2985 va_end(ap);2986 2987 if (bkpinfo->media_size <= 0) {2988 fatal_error("move_files_to_cd() - unknown media size");2989 }2990 if (would_occupy / 1024 > bkpinfo->media_size) {2991 res = write_iso_and_go_on(FALSE); /* FALSE because this is not the last CD we'll write */2992 retval += res;2993 if (res) {2994 log_msg(1, "WARNING - write_iso_and_go_on returned an error");2995 }2996 }2997 2998 va_start(ap, files_to_add); // initialize the variable arguments2999 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {3000 if (!cf) {3001 continue;3002 }3003 mr_asprintf(curr_file, "%s", cf);3004 3005 mr_asprintf(tmp, "mv -f %s %s/archives/", curr_file, bkpinfo->scratchdir);3006 mr_free(curr_file);3007 res = run_program_and_log_output(tmp, 5);3008 retval += res;3009 if (res) {3010 log_msg(1, "(move_files_to_cd) '%s' failed", tmp);3011 } else {3012 log_msg(8, "Moved %s to CD OK", tmp);3013 }3014 mr_free(tmp);3015 }3016 va_end(ap);3017 3018 if (retval) {3019 log_msg(1,3020 "Warning - errors occurred while I was adding files to CD dir");3021 }3022 return (retval);3023 }3024 3025 /* @} - end of LLarchiveGroup */3026 3027 /**3028 * Copy some files to tape.3029 * This function copies the files specified as parameters into the tape stream.3030 *3031 * @param bkpinfo The backup information structure. Used only in the call to3032 * @c write_file_to_stream_from_file().3033 *3034 * @param files_to_add The files to copy to the tape stream.3035 * @warning The list of @c files_to_add must be terminated with @c NULL.3036 * @note Files may be split across multiple tapes if necessary.3037 *3038 * @return The number of errors encountered (0 for success)3039 */3040 int3041 _move_files_to_stream(char *files_to_add, ...)3042 {3043 3044 /*@ int ************************************************************ */3045 int retval = 0;3046 int res = 0;3047 /*@ buffers ******************************************************** */3048 3049 /*@ char *********************************************************** */3050 char start_chr;3051 char stop_chr;3052 char *curr_file = NULL;3053 char *cf;3054 /*@ long long ****************************************************** */3055 off_t length_of_incoming_file = (off_t)0;3056 va_list ap;3057 3058 assert(bkpinfo != NULL);3059 va_start(ap, files_to_add);3060 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {3061 if (!cf) {3062 continue;3063 }3064 mr_asprintf(curr_file, "%s", cf);3065 if (!does_file_exist(curr_file)) {3066 log_msg(1,3067 "Warning - you're trying to add a non-existent file - '%s' to the tape",3068 curr_file);3069 }3070 /* create header chars */3071 start_chr = BLK_START_AN_AFIO_OR_SLICE;3072 stop_chr = BLK_STOP_AN_AFIO_OR_SLICE;3073 /* ask for new tape if necessary */3074 length_of_incoming_file = length_of_file(curr_file);3075 write_header_block_to_stream(length_of_incoming_file, curr_file, start_chr);3076 res = write_file_to_stream_from_file(curr_file);3077 retval += res;3078 unlink(curr_file);3079 mr_free(curr_file);3080 /* write closing header */3081 write_header_block_to_stream((off_t)0, "finished-writing-file", stop_chr);3082 }3083 va_end(ap);3084 3085 if (retval) {3086 log_msg(1,3087 "Warning - errors occurred while I was adding file to tape");3088 }3089 return (retval);3090 }3091 3092 /* @} - end of LLarchiveGroup */3093 3094 3095 3096 /**3097 * @addtogroup utilityGroup3098 * @{3099 */3100 /**3101 * Make sure the user has a valid CD-R(W) in the CD drive.3102 * @param cd_dev Set to the CD-R(W) device checked.3103 * @param keep_looping If TRUE, keep pestering user until they insist3104 * or insert a correct CD; if FALSE, only check once.3105 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't).3106 */3107 int interrogate_disk_currently_in_cddrive(char *cd_dev,3108 bool keep_looping)3109 {3110 int res = 0;3111 char *bkp = NULL;3112 char *cdrecord = NULL;3113 3114 mr_asprintf(bkp, "%s", cd_dev);3115 if ((cd_dev = find_optical_device()) != NULL) {3116 if (!system("which cdrecord > /dev/null 2> /dev/null")) {3117 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);3118 } else if (!system("which dvdrecord > /dev/null 2> /dev/null")) {3119 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);3120 } else {3121 log_msg(2, "Oh well. I guess I'll just pray then.");3122 }3123 if (cdrecord != NULL) {3124 if (!keep_looping) {3125 retract_CD_tray_and_defeat_autorun();3126 res = run_program_and_log_output(cdrecord, 5);3127 } else {3128 while ((res = run_program_and_log_output(cdrecord, 5))) {3129 retract_CD_tray_and_defeat_autorun();3130 if (ask_me_yes_or_no3131 ("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?"))3132 {3133 log_msg(1, "Well, he insisted...");3134 break;3135 }3136 }3137 }3138 }3139 }3140 mr_free(bkp);3141 3142 mr_free(cdrecord);3143 return (res);3144 }3145 3146 /* @} - end of utilityGroup */3147 3148 3149 /**3150 * @addtogroup LLarchiveGroup3151 * @{3152 */3153 3154 3141 3155 3142 /** -
branches/3.3/mondo/src/common/libmondo-devices-EXT.h
r3877 r3878 54 54 extern char *resolve_softlinks_to_get_to_actual_device_file(char *incoming); 55 55 56 extern void set_g_cdrom_and_g_dvd_to_bkpinfo_value();57 58 56 extern bool is_dev_an_NTFS_dev(char *bigfile_fname); 59 57 -
branches/3.3/mondo/src/common/libmondo-devices.c
r3877 r3878 55 55 extern char *call_program_and_get_last_line_of_output(const char *); 56 56 57 static char g_cd_drive_is_here[MAX_STR_LEN / 4] = "";58 static char g_cdrom_drive_is_here[MAX_STR_LEN / 4] = "";59 static char g_dvd_drive_is_here[MAX_STR_LEN / 4] = "";60 61 62 57 /** 63 58 * ????? @bug ????? … … 84 79 85 80 86 void set_g_cdrom_and_g_dvd_to_bkpinfo_value()87 {88 strcpy(g_cdrom_drive_is_here, bkpinfo->media_device); // just in case89 strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case90 }91 92 93 94 81 /** 95 82 * Retract all CD trays and wait for autorun to complete. … … 98 85 void retract_CD_tray_and_defeat_autorun(void) 99 86 { 100 // log_it("rctada: Retracting all CD trays", __LINE__);87 // log_it("rctada: Retracting optical tray", __LINE__); 101 88 if (!bkpinfo->please_dont_eject) { 102 if (strlen(g_cdrom_drive_is_here) > 0) { 103 inject_device(g_cdrom_drive_is_here); 104 } 105 if (strlen(g_dvd_drive_is_here) > 0) { 106 inject_device(g_dvd_drive_is_here); 107 } 108 } 109 // log_it("rctada: killing autorun"); 110 // run_program_and_log_output("killall autorun", TRUE); 89 if (bkpinfo->media_device != NULL) { 90 inject_device(bkpinfo->media_device); 91 } 111 92 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) { 112 93 log_it("autorun detected; sleeping for 2 seconds"); 113 94 sleep(2); 114 95 } 115 log_it("rctada: Unmounting all CD drives", __LINE__); 116 run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5); 96 } 97 98 99 100 /** 101 * Find out what device is mounted as root (/). 102 * @return Root device. 103 * @note The returned string points to storage that needs to be freed by 104 * caller 105 * @bug A bit of a misnomer; it's actually finding out the root device. 106 * The mountpoint (where it's mounted) will obviously be '/'. 107 */ 108 char *where_is_root_mounted(void) { 109 110 /*@ buffers **************** */ 111 char *tmp = NULL; 112 113 #ifdef __FreeBSD__ 114 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1"); 115 #else 116 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"); 117 if (strstr(tmp, "/dev/cciss/")) { 118 mr_free(tmp); 119 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"); 120 } 121 if (strstr(tmp, "/dev/md")) { 122 mr_free(tmp); 123 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1"); 124 } 125 #endif 126 127 return (tmp); 117 128 } 118 129 … … 447 458 448 459 449 /**450 * Try to mount CD/DVD at @p mountpoint. If the CD/DVD is not found or has451 * not been specified, call find_optical_device() to find it.452 * @param mountpoint Where to mount the CD-ROM.453 * @return TRUE for success, FALSE for failure.454 * @see mount_media455 */456 bool find_and_mount_actual_cd(char *mountpoint) {457 458 /*@ buffers ***************************************************** */459 460 /*@ int's ****************************************************** */461 bool res;462 463 /*@ end vars **************************************************** */464 465 assert(bkpinfo != NULL);466 assert_string_is_neither_NULL_nor_zerolength(mountpoint);467 468 if (bkpinfo->media_device == NULL) {469 bkpinfo->media_device = find_optical_device();470 }471 472 if (bkpinfo->backup_media_type != iso) {473 retract_CD_tray_and_defeat_autorun();474 }475 476 if ((bkpinfo->media_device == NULL) || (res = mount_media(mountpoint))) {477 mr_free(bkpinfo->media_device);478 if ((bkpinfo->media_device = mr_popup_and_get_string("CD-ROM device", "Please enter your CD-ROM's /dev device", "/dev/cdrom")) == NULL) {479 res = TRUE;480 } else {481 res = mount_media(mountpoint);482 }483 }484 if (res) {485 log_msg(1, "mount failed");486 } else {487 log_msg(1, "mount succeeded with %s", bkpinfo->media_device);488 }489 return (res);490 }491 /*492 * This function tries to find a USB media device493 * and return it's device file to the caller that needs to free it494 */495 char *find_usb_device(void)496 {497 char *dev = NULL;498 char *tmp1 = NULL;499 char *command = NULL;500 501 log_to_screen("I am looking for your USB key. Please wait.");502 503 if (bkpinfo->media_device != NULL) {504 log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);505 return (bkpinfo->media_device);506 }507 508 tmp1 = find_home_of_exe("lsscsi");509 if (tmp1 != NULL) {510 mr_asprintf(command, "%s | grep ' disk' | grep USB | awk '{print $NF}' | head -1", tmp1);511 dev = call_program_and_get_last_line_of_output(command);512 mr_free(command);513 }514 mr_free(tmp1);515 516 if ((dev == NULL) || !does_file_exist(dev)) {517 tmp1 = find_home_of_exe("lsblk");518 if (tmp1 != NULL) {519 mr_asprintf(command, "%s --noheadings --raw --output rm,tran,type,path --sort path | awk '/^1 usb disk/ {d=$4} END {print d}'", tmp1);520 dev = call_program_and_get_last_line_of_output(command);521 mr_free(command);522 }523 mr_free(tmp1);524 log_it("Unable to find a tape device on this system");525 }526 if (dev != NULL) {527 log_it("find_usb_device found %s manually", dev);528 }529 530 if ((dev != NULL) && does_file_exist(dev)) {531 log_it("find_usb_device returns %s", dev);532 } else {533 mr_free(dev);534 log_it("find_usb_device found no USB key on your system returning NULL");535 }536 return(dev);537 }538 539 540 460 /* 541 461 * This function tries to find an optical media device 542 462 * and return it's device file to the caller that needs to free it 543 463 */ 544 char *find_optical_device(void) 545 { 464 char *find_optical_device(void) { 546 465 char *dev = NULL; 547 466 char *tmp1 = NULL; … … 582 501 if (!does_file_exist(dev)) { 583 502 log_it("Unable to find a tape device on this system"); 503 } 504 } 584 505 } 585 506 } … … 598 519 return(dev); 599 520 } 521 /** 522 * Mount the CD-ROM or USB device at /mnt/cdrom. 523 * @param bkpinfo The backup information structure. Fields used: 524 * - @c bkpinfo->backup_media_type 525 * - @c bkpinfo->disaster_recovery 526 * - @c bkpinfo->isodir 527 * - @c bkpinfo->media_device 528 * @return TRUE for success, FALSE for failure. 529 */ 530 bool mount_media(const char *mountpoint) { 531 532 char *mount_cmd = NULL; 533 char *mountdir = NULL; 534 char *tmp = NULL; 535 int i = 0, res = 0; 536 #ifdef __FreeBSD__ 537 char mdd[32]; 538 char *mddev = mdd; 539 char *dev; 540 #endif 541 542 if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) { 543 log_msg(8, "Tape/udev. Therefore, no need to mount a media."); 544 return(TRUE); 545 } 546 547 assert_string_is_neither_NULL_nor_zerolength(mountpoint); 548 549 mr_asprintf(tmp, "mount | grep -F %s", mountpoint); 550 if (!run_program_and_log_output(tmp, FALSE)) { 551 log_msg(2, "mount_media() - media already mounted. Fair enough."); 552 mr_free(tmp); 553 return (TRUE); 554 } 555 mr_free(tmp); 556 557 make_hole_for_dir(mountpoint); 558 559 if (bkpinfo->backup_media_type == netfs) { 560 log_msg(2, "Mounting for Network thingy"); 561 log_msg(2, "isodir = %s", bkpinfo->isodir); 562 if (((bkpinfo->isodir == NULL) || !strcmp(bkpinfo->isodir, "/")) && am_I_in_disaster_recovery_mode()) { 563 mr_asprintf(bkpinfo->isodir, "%s", "/tmp/isodir"); 564 log_msg(1, "isodir is being set to %s", bkpinfo->isodir); 565 } 566 #ifdef __FreeBSD__ 567 if (bkpinfo->netfs_remote_dir != NULL) { 568 // NETFS 569 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number); 570 } else { 571 // ISO 572 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number); 573 } 574 mddev = make_vn(mount_cmd); 575 mr_free(mount_cmd); 576 577 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint); 578 #else 579 if (bkpinfo->netfs_remote_dir != NULL) { 580 // NETFS 581 mr_asprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number, mountpoint); 582 } else { 583 // ISO 584 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, mountpoint); 585 } 586 #endif 587 588 } else if (bkpinfo->backup_media_type == iso) { 589 if (bkpinfo->subdir) { 590 mr_asprintf(mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir); 591 } else { 592 mr_asprintf(mountdir, "%s", bkpinfo->isodir); 593 } 594 #ifdef __FreeBSD__ 595 mr_asprintf(mount_cmd, "%s/%s-%d.iso", mountdir, bkpinfo->prefix, g_current_media_number); 596 mddev = make_vn(mount_cmd); 597 mr_free(mount_cmd); 598 599 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint); 600 #else 601 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, mountpoint); 602 #endif 603 mr_free(mountdir); 604 } else if (bkpinfo->backup_media_type == usb) { 605 mr_asprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, mountpoint); 606 } else { // optical 607 if (bkpinfo->disaster_recovery 608 && does_file_exist("/tmp/CDROM-LIVES-HERE")) { 609 mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE")); 610 } else { 611 if (bkpinfo->media_device == NULL) { 612 bkpinfo->media_device = find_optical_device(); 613 } 614 } 615 616 #ifdef __FreeBSD__ 617 if (g_ISO_restore_mode) { 618 mr_asprintf(dev, "%s", make_vn(bkpinfo->media_device)); 619 if (!dev) { 620 mr_asprintf(command, "Unable to mount ISO (make_vn(%s) failed)", bkpinfo->media_device); 621 fatal_error(command); 622 } 623 mr_free(bkpinfo->media_device); 624 bkpinfo->media_device = dev 625 } 626 627 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE); 628 #else 629 mr_asprintf(mount_cmd, "mount %s -o loop,ro -t iso9660 %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE); 630 #endif 631 log_msg(2, "(mount_media) --- command = %s", mount_cmd); 632 // usefull ?? 633 if (strncmp(bkpinfo->media_device, "/dev/", 5) == 0) { 634 retract_CD_tray_and_defeat_autorun(); 635 } 636 } 637 638 for (i = 0; i < 2; i++) { 639 res = run_program_and_log_output(mount_cmd, FALSE); 640 if (!res) { 641 break; 642 } else { 643 log_msg(2, "Failed to mount device."); 644 sleep(5); 645 sync(); 646 } 647 } 648 mr_free(mount_cmd); 649 650 if (res) { 651 log_msg(2, "Failed, despite %d attempts", i); 652 return(FALSE); 653 } else { 654 log_msg(2, "Mounted media drive OK"); 655 return(TRUE); 656 } 657 } 658 /************************************************************************** 659 *END_MOUNT_MEDIA * 660 **************************************************************************/ 661 662 663 664 665 /** 666 * Try to mount CD/DVD at @p mountpoint. If the CD/DVD is not found or has 667 * not been specified, call find_optical_device() to find it. 668 * @param mountpoint Where to mount the CD-ROM. 669 * @return TRUE for success, FALSE for failure. 670 * @see mount_media 671 */ 672 bool find_and_mount_actual_cd(char *mountpoint) { 673 674 /*@ buffers ***************************************************** */ 675 676 /*@ int's ****************************************************** */ 677 bool res; 678 679 /*@ end vars **************************************************** */ 680 681 assert(bkpinfo != NULL); 682 assert_string_is_neither_NULL_nor_zerolength(mountpoint); 683 684 if (bkpinfo->media_device == NULL) { 685 bkpinfo->media_device = find_optical_device(); 686 } 687 688 if (bkpinfo->backup_media_type != iso) { 689 retract_CD_tray_and_defeat_autorun(); 690 } 691 692 if ((bkpinfo->media_device == NULL) || (res = mount_media(mountpoint))) { 693 mr_free(bkpinfo->media_device); 694 if ((bkpinfo->media_device = mr_popup_and_get_string("CD-ROM device", "Please enter your CD-ROM's /dev device", "/dev/cdrom")) == NULL) { 695 res = TRUE; 696 } else { 697 res = mount_media(mountpoint); 698 } 699 } 700 if (res) { 701 log_msg(1, "mount failed"); 702 } else { 703 log_msg(1, "mount succeeded with %s", bkpinfo->media_device); 704 } 705 return (res); 706 } 707 /* 708 * This function tries to find a USB media device 709 * and return it's device file to the caller that needs to free it 710 */ 711 char *find_usb_device(void) 712 { 713 char *dev = NULL; 714 char *tmp1 = NULL; 715 char *command = NULL; 716 717 log_to_screen("I am looking for your USB key. Please wait."); 718 719 if (bkpinfo->media_device != NULL) { 720 log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device); 721 return (bkpinfo->media_device); 722 } 723 724 tmp1 = find_home_of_exe("lsscsi"); 725 if (tmp1 != NULL) { 726 mr_asprintf(command, "%s | grep ' disk' | grep USB | awk '{print $NF}' | head -1", tmp1); 727 dev = call_program_and_get_last_line_of_output(command); 728 mr_free(command); 729 } 730 mr_free(tmp1); 731 732 if ((dev == NULL) || !does_file_exist(dev)) { 733 tmp1 = find_home_of_exe("lsblk"); 734 if (tmp1 != NULL) { 735 mr_asprintf(command, "%s --noheadings --raw --output rm,tran,type,path --sort path | awk '/^1 usb disk/ {d=$4} END {print d}'", tmp1); 736 dev = call_program_and_get_last_line_of_output(command); 737 mr_free(command); 738 } 739 mr_free(tmp1); 740 log_it("Unable to find a tape device on this system"); 741 } 742 if (dev != NULL) { 743 log_it("find_usb_device found %s manually", dev); 744 } 745 746 if ((dev != NULL) && does_file_exist(dev)) { 747 log_it("find_usb_device returns %s", dev); 748 } else { 749 mr_free(dev); 750 log_it("find_usb_device found no USB key on your system returning NULL"); 751 } 752 return(dev); 753 } 754 755 600 756 601 757 /* Generic fund to find a media … … 971 1127 972 1128 /** 973 * Mount the CD-ROM or USB device at /mnt/cdrom. 974 * @param bkpinfo The backup information structure. Fields used: 975 * - @c bkpinfo->backup_media_type 976 * - @c bkpinfo->disaster_recovery 977 * - @c bkpinfo->isodir 978 * - @c bkpinfo->media_device 979 * @return TRUE for success, FALSE for failure. 980 */ 981 bool mount_media(const char *mountpoint) { 982 983 char *mount_cmd = NULL; 984 char *mountdir = NULL; 1129 * Find out what number CD is in the drive. 1130 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used. 1131 * @return The current CD number, or -1 if it could not be found. 1132 * @note If the CD is not mounted, it will be mounted 1133 * (and remain mounted after this function returns). 1134 */ 1135 int what_number_cd_is_this(void) { 1136 1137 int cd_number = -1; 1138 char *mountdev = NULL; 985 1139 char *tmp = NULL; 986 int i = 0, res = 0; 987 #ifdef __FreeBSD__ 988 char mdd[32]; 989 char *mddev = mdd; 990 char *dev; 991 #endif 992 993 if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) { 994 log_msg(8, "Tape/udev. Therefore, no need to mount a media."); 995 return(TRUE); 996 } 997 998 assert_string_is_neither_NULL_nor_zerolength(mountpoint); 999 1000 mr_asprintf(tmp, "mount | grep -F %s", mountpoint); 1001 if (!run_program_and_log_output(tmp, FALSE)) { 1002 log_msg(2, "mount_media() - media already mounted. Fair enough."); 1140 1141 assert(bkpinfo != NULL); 1142 // log_it("Asking what_number_cd_is_this"); 1143 if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) { 1144 tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'"); 1145 mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER"); 1003 1146 mr_free(tmp); 1004 return (TRUE); 1005 } 1006 mr_free(tmp); 1007 1008 make_hole_for_dir(mountpoint); 1009 1010 if (bkpinfo->backup_media_type == netfs) { 1011 log_msg(2, "Mounting for Network thingy"); 1012 log_msg(2, "isodir = %s", bkpinfo->isodir); 1013 if (((bkpinfo->isodir == NULL) || !strcmp(bkpinfo->isodir, "/")) && am_I_in_disaster_recovery_mode()) { 1014 mr_asprintf(bkpinfo->isodir, "%s", "/tmp/isodir"); 1015 log_msg(1, "isodir is being set to %s", bkpinfo->isodir); 1016 } 1017 #ifdef __FreeBSD__ 1018 if (bkpinfo->netfs_remote_dir != NULL) { 1019 // NETFS 1020 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number); 1021 } else { 1022 // ISO 1023 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number); 1024 } 1025 mddev = make_vn(mount_cmd); 1026 mr_free(mount_cmd); 1027 1028 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint); 1029 #else 1030 if (bkpinfo->netfs_remote_dir != NULL) { 1031 // NETFS 1032 mr_asprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number, mountpoint); 1033 } else { 1034 // ISO 1035 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, mountpoint); 1036 } 1037 #endif 1038 1039 } else if (bkpinfo->backup_media_type == iso) { 1040 if (bkpinfo->subdir) { 1041 mr_asprintf(mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir); 1042 } else { 1043 mr_asprintf(mountdir, "%s", bkpinfo->isodir); 1044 } 1045 #ifdef __FreeBSD__ 1046 mr_asprintf(mount_cmd, "%s/%s-%d.iso", mountdir, bkpinfo->prefix, g_current_media_number); 1047 mddev = make_vn(mount_cmd); 1048 mr_free(mount_cmd); 1049 1050 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint); 1051 #else 1052 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, mountpoint); 1053 #endif 1054 mr_free(mountdir); 1055 } else if (bkpinfo->backup_media_type == usb) { 1056 mr_asprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, mountpoint); 1057 } else { // optical 1058 if (bkpinfo->disaster_recovery 1059 && does_file_exist("/tmp/CDROM-LIVES-HERE")) { 1060 mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE")); 1061 } else { 1062 if (bkpinfo->media_device == NULL) { 1063 bkpinfo->media_device = find_optical_device(); 1064 } 1065 } 1066 1067 #ifdef __FreeBSD__ 1068 if (g_ISO_restore_mode) { 1069 mr_asprintf(dev, "%s", make_vn(bkpinfo->media_device)); 1070 if (!dev) { 1071 mr_asprintf(command, "Unable to mount ISO (make_vn(%s) failed)", bkpinfo->media_device); 1072 fatal_error(command); 1073 } 1074 mr_free(bkpinfo->media_device); 1075 bkpinfo->media_device = dev 1076 } 1077 1078 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE); 1079 #else 1080 mr_asprintf(mount_cmd, "mount %s -o loop,ro -t iso9660 %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE); 1081 #endif 1082 log_msg(2, "(mount_media) --- command = %s", mount_cmd); 1083 // usefull ?? 1084 if (strncmp(device, "/dev/", 5) == 0) { 1085 retract_CD_tray_and_defeat_autorun(); 1086 } 1087 } 1088 1089 for (i = 0; i < 2; i++) { 1090 res = run_program_and_log_output(mount_cmd, FALSE); 1091 if (!res) { 1092 break; 1093 } else { 1094 log_msg(2, "Failed to mount device."); 1095 sleep(5); 1096 sync(); 1097 } 1098 } 1099 mr_free(mount_cmd); 1100 1101 if (res) { 1102 log_msg(2, "Failed, despite %d attempts", i); 1103 return(FALSE); 1104 } else { 1105 log_msg(2, "Mounted media drive OK"); 1106 return(TRUE); 1107 } 1108 } 1109 /************************************************************************** 1110 *END_MOUNT_MEDIA * 1111 **************************************************************************/ 1147 cd_number = atoi(last_line_of_file(mountdev)); 1148 mr_free(mountdev); 1149 return (cd_number); 1150 } 1151 1152 if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) { 1153 log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n"); 1154 /* trying again ! */ 1155 bkpinfo->media_device = find_optical_device(); 1156 } 1157 if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) { 1158 fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n"); 1159 } 1160 if (!is_this_device_mounted(MNT_CDROM)) { 1161 mount_media(MNT_CDROM); 1162 } 1163 1164 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER")); 1165 return(cd_number); 1166 } 1112 1167 1113 1168 … … 2000 2055 2001 2056 /** 2057 * Get a |-separated list of NETFS mounts. 2058 * @return The list created. 2059 * @note The return value points to allocated string that needs to be freed by 2060 * caller 2061 * @bug Even though we only want the mounts, the devices are still checked. 2062 */ 2063 char *list_of_NETFS_mounts_only(void) 2064 { 2065 char *exclude_these_directories = NULL; 2066 2067 exclude_these_directories = call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,vmhgfs,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol,fuse.boostfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' '|' | awk '{print $0;}'"); 2068 log_msg(9,"list_of_NETFS_mounts_only returns %s",exclude_these_directories); 2069 return(exclude_these_directories); 2070 } 2071 2072 /* @} - end of utilityGroup */ 2073 2074 2075 /** 2002 2076 * Ask user for details of backup/restore information. 2003 2077 * Called when @c mondoarchive doesn't get any parameters. … … 2717 2791 2718 2792 2719 /**2720 * Get a |-separated list of NETFS mounts.2721 * @return The list created.2722 * @note The return value points to allocated string that needs to be freed by2723 * caller2724 * @bug Even though we only want the mounts, the devices are still checked.2725 */2726 char *list_of_NETFS_mounts_only(void)2727 {2728 char *exclude_these_directories = NULL;2729 2730 exclude_these_directories = call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,vmhgfs,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol,fuse.boostfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' '|' | awk '{print $0;}'");2731 log_msg(9,"list_of_NETFS_mounts_only returns %s",exclude_these_directories);2732 return(exclude_these_directories);2733 }2734 2735 /* @} - end of utilityGroup */2736 2737 2738 2793 2739 2794 … … 2804 2859 return(ret); 2805 2860 } 2806 2807 2808 2809 2810 2811 /**2812 * Find out what number CD is in the drive.2813 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.2814 * @return The current CD number, or -1 if it could not be found.2815 * @note If the CD is not mounted, it will be mounted2816 * (and remain mounted after this function returns).2817 */2818 int what_number_cd_is_this(void) {2819 2820 int cd_number = -1;2821 char *mountdev = NULL;2822 char *tmp = NULL;2823 2824 assert(bkpinfo != NULL);2825 // log_it("Asking what_number_cd_is_this");2826 if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) {2827 tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'");2828 mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER");2829 mr_free(tmp);2830 cd_number = atoi(last_line_of_file(mountdev));2831 mr_free(mountdev);2832 return (cd_number);2833 }2834 2835 if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {2836 log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n");2837 /* trying again ! */2838 bkpinfo->media_device = find_optical_device();2839 }2840 if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {2841 fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n");2842 }2843 if (!is_this_device_mounted(bkpinfo->media_device, MNT_CDROM)) {2844 mount_media(MNT_CDROM);2845 }2846 2847 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));2848 return(cd_number);2849 }2850 2851 2852 /**2853 * Find out what device is mounted as root (/).2854 * @return Root device.2855 * @note The returned string points to storage that needs to be freed by2856 * caller2857 * @bug A bit of a misnomer; it's actually finding out the root device.2858 * The mountpoint (where it's mounted) will obviously be '/'.2859 */2860 char *where_is_root_mounted(void) {2861 2862 /*@ buffers **************** */2863 char *tmp = NULL;2864 2865 #ifdef __FreeBSD__2866 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");2867 #else2868 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//");2869 if (strstr(tmp, "/dev/cciss/")) {2870 mr_free(tmp);2871 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1");2872 }2873 if (strstr(tmp, "/dev/md")) {2874 mr_free(tmp);2875 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");2876 }2877 #endif2878 2879 return (tmp);2880 }2881 2882 2861 2883 2862 -
branches/3.3/mondo/src/common/libmondo-filelist.c
r3871 r3878 60 60 extern char *g_getfacl; 61 61 extern char *g_getfattr; 62 63 64 65 /** 66 * Chop the filelist into sets. 67 * Each fileset is a list of files whose total (uncompressed) size is usually 68 * about X KB. Files bigger than 8X KB are placed in a "biggielist"; they will 69 * be sliced and compressed separately from the regular files. 70 * 71 * @param filelist The big filelist (filelist.full) to chop up. 72 * @param outdir The directory to place the files (filelist.N where N is 73 * an integer, biggielist.txt, and LAST-FILELIST-NUMBER) created 74 * @param maxsetsizeK Optimal size of a fileset (X above). 75 * @return number of errors encountered (0 for success). 76 */ 77 int chop_filelist(char *filelist, char *outdir, long maxsetsizeK) 78 { 79 /*@ long ****************************************/ 80 long lino = 0; 81 // A big file has more than 64 MB of real content 82 long curr_set_size; 83 long noof_lines; 84 long siz; 85 86 /*@ int **************************************** */ 87 int i; 88 long curr_set_no; 89 90 /*@ buffers ************************************* */ 91 char *outfname = NULL; 92 char *biggie_fname = NULL; 93 char *incoming = NULL; 94 char *tmp = NULL; 95 96 /*@ pointers *********************************** */ 97 FILE *fin; 98 FILE *fout; 99 FILE *fbig; 100 101 /*@ structures ********************************* */ 102 struct stat buf; 103 int err = 0; 104 105 assert_string_is_neither_NULL_nor_zerolength(filelist); 106 assert_string_is_neither_NULL_nor_zerolength(outdir); 107 assert(maxsetsizeK > 0); 108 109 log_it("filelist=%s;", filelist); 110 open_evalcall_form("Dividing filelist into sets"); 111 noof_lines = count_lines_in_file(filelist); 112 if (!(fin = fopen(filelist, "r"))) { 113 log_OS_error("Cannot openin filelist"); 114 return (0); 115 } 116 curr_set_no = 0; 117 curr_set_size = 0; 118 mr_asprintf(outfname, "%s/filelist.%ld", outdir, curr_set_no); 119 mr_asprintf(biggie_fname, "%s/biggielist.txt", outdir); 120 log_it("outfname=%s; biggie_fname=%s", outfname, biggie_fname); 121 if (!(fbig = fopen(biggie_fname, "w"))) { 122 log_OS_error("Cannot openout biggie_fname"); 123 err++; 124 mr_free(outfname); 125 mr_free(biggie_fname); 126 return (curr_set_no + 1); 127 } 128 if (!(fout = fopen(outfname, "w"))) { 129 log_OS_error("Cannot openout outfname"); 130 err++; 131 mr_free(outfname); 132 mr_free(biggie_fname); 133 return (curr_set_no + 1); 134 } 135 136 mr_getline(incoming, fin); 137 while (!feof(fin)) { 138 lino++; 139 i = strlen(incoming) - 1; 140 if (i < 0) { 141 i = 0; 142 } 143 if (incoming[i] < 32) { 144 incoming[i] = '\0'; 145 } 146 if (!strncmp(incoming, "/dev/", 5)) { 147 siz = 1; 148 } else if (lstat(incoming, &buf) != 0) { 149 siz = 0; 150 } else { 151 // blocks are 512 bytes long - cf man 2 stat - Pass to the previous unit (MB => kB e.g.) 152 // use blocks instead of size to allow sparse file correct handling as much as possible 153 siz = (long) ((buf.st_blocks*512) >> 10); 154 } 155 if (siz > g_max_biggie_size) { 156 log_msg(10, "Adding %s to big files (size = %ld)", incoming, siz); 157 fprintf(fbig, "%s\n", incoming); 158 } else { 159 curr_set_size += siz; 160 log_msg(10, "Adding %s to filelist %d (size = %ld)", incoming, curr_set_no, siz); 161 fprintf(fout, "%s\n", incoming); 162 if (curr_set_size > maxsetsizeK) { 163 paranoid_fclose(fout); 164 sort_file(outfname); 165 mr_free(outfname); 166 curr_set_no++; 167 curr_set_size = 0; 168 169 mr_asprintf(outfname, "%s/filelist.%ld", outdir, curr_set_no); 170 if (!(fout = fopen(outfname, "w"))) { 171 log_OS_error("Unable to openout outfname"); 172 err++; 173 mr_free(outfname); 174 mr_free(biggie_fname); 175 mr_free(incoming); 176 return (curr_set_no + 1); 177 } 178 update_evalcall_form((int) (lino * 100 / noof_lines)); 179 } 180 } 181 mr_free(incoming); 182 mr_getline(incoming, fin); 183 } 184 mr_free(incoming); 185 186 paranoid_fclose(fin); 187 paranoid_fclose(fout); 188 paranoid_fclose(fbig); 189 190 if (length_of_file(outfname) <= 2) { 191 unlink(outfname); 192 g_noof_sets--; 193 } 194 g_noof_sets = curr_set_no; 195 sort_file(outfname); 196 mr_free(outfname); 197 198 sort_file(biggie_fname); 199 mr_free(biggie_fname); 200 201 mr_asprintf(outfname, "%s/LAST-FILELIST-NUMBER", outdir); 202 mr_asprintf(tmp, "%ld", curr_set_no); 203 if (write_one_liner_data_file(outfname, tmp)) { 204 log_OS_error 205 ("Unable to echo write one-liner to LAST-FILELIST-NUMBER"); 206 err = 1; 207 } 208 mr_free(tmp); 209 mr_free(outfname); 210 211 if (curr_set_no == 0) { 212 log_msg(1, "Only one fileset. Fine."); 213 } else { 214 log_msg(1, "Filelist divided into %ld sets", curr_set_no + 1); 215 } 216 close_evalcall_form(); 217 /* This is to work around an obscure bug in Newt; open a form, close it, 218 carry on... I don't know why it works but it works. If you don't do this 219 then update_progress_form() won't show the "time taken / time remaining" 220 line. The bug only crops up AFTER the call to chop_filelist(). Weird. */ 221 if (!g_text_mode) { 222 open_progress_form("", "", "", "", 100); 223 newtPopHelpLine(); 224 newtFormDestroy(g_progressForm); 225 newtPopWindow(); 226 } 227 return (err ? 0 : curr_set_no + 1); 228 } 229 62 230 63 231 … … 184 352 185 353 186 /**187 * Chop the filelist into sets.188 * Each fileset is a list of files whose total (uncompressed) size is usually189 * about X KB. Files bigger than 8X KB are placed in a "biggielist"; they will190 * be sliced and compressed separately from the regular files.191 *192 * @param filelist The big filelist (filelist.full) to chop up.193 * @param outdir The directory to place the files (filelist.N where N is194 * an integer, biggielist.txt, and LAST-FILELIST-NUMBER) created195 * @param maxsetsizeK Optimal size of a fileset (X above).196 * @return number of errors encountered (0 for success).197 */198 int chop_filelist(char *filelist, char *outdir, long maxsetsizeK)199 {200 /*@ long ****************************************/201 long lino = 0;202 // A big file has more than 64 MB of real content203 long curr_set_size;204 long noof_lines;205 long siz;206 207 /*@ int **************************************** */208 int i;209 long curr_set_no;210 211 /*@ buffers ************************************* */212 char *outfname = NULL;213 char *biggie_fname = NULL;214 char *incoming = NULL;215 char *tmp = NULL;216 217 /*@ pointers *********************************** */218 FILE *fin;219 FILE *fout;220 FILE *fbig;221 222 /*@ structures ********************************* */223 struct stat buf;224 int err = 0;225 226 assert_string_is_neither_NULL_nor_zerolength(filelist);227 assert_string_is_neither_NULL_nor_zerolength(outdir);228 assert(maxsetsizeK > 0);229 230 log_it("filelist=%s;", filelist);231 open_evalcall_form("Dividing filelist into sets");232 noof_lines = count_lines_in_file(filelist);233 if (!(fin = fopen(filelist, "r"))) {234 log_OS_error("Cannot openin filelist");235 return (0);236 }237 curr_set_no = 0;238 curr_set_size = 0;239 mr_asprintf(outfname, "%s/filelist.%ld", outdir, curr_set_no);240 mr_asprintf(biggie_fname, "%s/biggielist.txt", outdir);241 log_it("outfname=%s; biggie_fname=%s", outfname, biggie_fname);242 if (!(fbig = fopen(biggie_fname, "w"))) {243 log_OS_error("Cannot openout biggie_fname");244 err++;245 mr_free(outfname);246 mr_free(biggie_fname);247 return (curr_set_no + 1);248 }249 if (!(fout = fopen(outfname, "w"))) {250 log_OS_error("Cannot openout outfname");251 err++;252 mr_free(outfname);253 mr_free(biggie_fname);254 return (curr_set_no + 1);255 }256 257 mr_getline(incoming, fin);258 while (!feof(fin)) {259 lino++;260 i = strlen(incoming) - 1;261 if (i < 0) {262 i = 0;263 }264 if (incoming[i] < 32) {265 incoming[i] = '\0';266 }267 if (!strncmp(incoming, "/dev/", 5)) {268 siz = 1;269 } else if (lstat(incoming, &buf) != 0) {270 siz = 0;271 } else {272 // blocks are 512 bytes long - cf man 2 stat - Pass to the previous unit (MB => kB e.g.)273 // use blocks instead of size to allow sparse file correct handling as much as possible274 siz = (long) ((buf.st_blocks*512) >> 10);275 }276 if (siz > g_max_biggie_size) {277 log_msg(10, "Adding %s to big files (size = %ld)", incoming, siz);278 fprintf(fbig, "%s\n", incoming);279 } else {280 curr_set_size += siz;281 log_msg(10, "Adding %s to filelist %d (size = %ld)", incoming, curr_set_no, siz);282 fprintf(fout, "%s\n", incoming);283 if (curr_set_size > maxsetsizeK) {284 paranoid_fclose(fout);285 sort_file(outfname);286 mr_free(outfname);287 curr_set_no++;288 curr_set_size = 0;289 290 mr_asprintf(outfname, "%s/filelist.%ld", outdir, curr_set_no);291 if (!(fout = fopen(outfname, "w"))) {292 log_OS_error("Unable to openout outfname");293 err++;294 mr_free(outfname);295 mr_free(biggie_fname);296 mr_free(incoming);297 return (curr_set_no + 1);298 }299 update_evalcall_form((int) (lino * 100 / noof_lines));300 }301 }302 mr_free(incoming);303 mr_getline(incoming, fin);304 }305 mr_free(incoming);306 307 paranoid_fclose(fin);308 paranoid_fclose(fout);309 paranoid_fclose(fbig);310 311 if (length_of_file(outfname) <= 2) {312 unlink(outfname);313 g_noof_sets--;314 }315 g_noof_sets = curr_set_no;316 sort_file(outfname);317 mr_free(outfname);318 319 sort_file(biggie_fname);320 mr_free(biggie_fname);321 322 mr_asprintf(outfname, "%s/LAST-FILELIST-NUMBER", outdir);323 mr_asprintf(tmp, "%ld", curr_set_no);324 if (write_one_liner_data_file(outfname, tmp)) {325 log_OS_error326 ("Unable to echo write one-liner to LAST-FILELIST-NUMBER");327 err = 1;328 }329 mr_free(tmp);330 mr_free(outfname);331 332 if (curr_set_no == 0) {333 log_msg(1, "Only one fileset. Fine.");334 } else {335 log_msg(1, "Filelist divided into %ld sets", curr_set_no + 1);336 }337 close_evalcall_form();338 /* This is to work around an obscure bug in Newt; open a form, close it,339 carry on... I don't know why it works but it works. If you don't do this340 then update_progress_form() won't show the "time taken / time remaining"341 line. The bug only crops up AFTER the call to chop_filelist(). Weird. */342 if (!g_text_mode) {343 open_progress_form("", "", "", "", 100);344 newtPopHelpLine();345 newtFormDestroy(g_progressForm);346 newtPopWindow();347 }348 return (err ? 0 : curr_set_no + 1);349 }350 351 352 353 354 354 355 355 /** … … 967 967 } 968 968 return; 969 }970 971 972 973 974 /**975 * Reset the filelist to the state it was when it was loaded. This does not976 * touch the file on disk.977 * @param filelist The filelist tree structure.978 */979 void reload_filelist(struct s_node *filelist)980 {981 assert(filelist != NULL);982 toggle_node_selection(filelist, FALSE);983 toggle_path_expandability(filelist, "/", FALSE);984 toggle_all_root_dirs_on(filelist);985 }986 987 988 989 /**990 * Save a filelist tree structure to disk.991 * @param filelist The filelist tree structure to save.992 * @param outfname Where to save it.993 */994 void save_filelist(struct s_node *filelist, char *outfname)995 {996 /*@ int ********************************************************* */997 static int percentage;998 static int depth = 0;999 1000 /*@ buffers ***************************************************** */1001 static char str[MAX_STR_LEN];1002 1003 /*@ structures ************************************************** */1004 struct s_node *node;1005 1006 /*@ pointers **************************************************** */1007 static FILE *fout = NULL;1008 1009 /*@ long ******************************************************** */1010 static long lines_in_filelist = 0;1011 static long lino = 0;1012 1013 /*@ end vars *************************************************** */1014 1015 assert(filelist != NULL);1016 assert(outfname != NULL); // will be zerolength if save_filelist() is called by itself1017 if (depth == 0) {1018 log_to_screen("Saving filelist");1019 if (!(fout = fopen(outfname, "w"))) {1020 fatal_error("Cannot openout/save filelist");1021 }1022 lines_in_filelist = g_original_noof_lines_in_filelist; /* set by load_filelist() */1023 open_evalcall_form("Saving selection to disk");1024 }1025 for (node = filelist; node != NULL; node = node->right) {1026 str[depth] = node->ch;1027 log_msg(5, "depth=%d ch=%c", depth, node->ch);1028 if (!node->ch) {1029 // if (node->selected)1030 // {1031 fprintf(fout, "%s\n", str);1032 // }1033 if (!(++lino % 1111)) {1034 percentage = (int) (lino * 100 / lines_in_filelist);1035 update_evalcall_form(percentage);1036 }1037 }1038 if (node->down) {1039 depth++;1040 save_filelist(node->down, "");1041 depth--;1042 }1043 }1044 if (depth == 0) {1045 paranoid_fclose(fout);1046 close_evalcall_form();1047 log_it("Finished saving filelist");1048 }1049 969 } 1050 970 … … 1251 1171 } 1252 1172 1173 1174 1175 1176 /** 1177 * Reset the filelist to the state it was when it was loaded. This does not 1178 * touch the file on disk. 1179 * @param filelist The filelist tree structure. 1180 */ 1181 void reload_filelist(struct s_node *filelist) 1182 { 1183 assert(filelist != NULL); 1184 toggle_node_selection(filelist, FALSE); 1185 toggle_path_expandability(filelist, "/", FALSE); 1186 toggle_all_root_dirs_on(filelist); 1187 } 1188 1189 1190 1191 /** 1192 * Save a filelist tree structure to disk. 1193 * @param filelist The filelist tree structure to save. 1194 * @param outfname Where to save it. 1195 */ 1196 void save_filelist(struct s_node *filelist, char *outfname) 1197 { 1198 /*@ int ********************************************************* */ 1199 static int percentage; 1200 static int depth = 0; 1201 1202 /*@ buffers ***************************************************** */ 1203 static char str[MAX_STR_LEN]; 1204 1205 /*@ structures ************************************************** */ 1206 struct s_node *node; 1207 1208 /*@ pointers **************************************************** */ 1209 static FILE *fout = NULL; 1210 1211 /*@ long ******************************************************** */ 1212 static long lines_in_filelist = 0; 1213 static long lino = 0; 1214 1215 /*@ end vars *************************************************** */ 1216 1217 assert(filelist != NULL); 1218 assert(outfname != NULL); // will be zerolength if save_filelist() is called by itself 1219 if (depth == 0) { 1220 log_to_screen("Saving filelist"); 1221 if (!(fout = fopen(outfname, "w"))) { 1222 fatal_error("Cannot openout/save filelist"); 1223 } 1224 lines_in_filelist = g_original_noof_lines_in_filelist; /* set by load_filelist() */ 1225 open_evalcall_form("Saving selection to disk"); 1226 } 1227 for (node = filelist; node != NULL; node = node->right) { 1228 str[depth] = node->ch; 1229 log_msg(5, "depth=%d ch=%c", depth, node->ch); 1230 if (!node->ch) { 1231 // if (node->selected) 1232 // { 1233 fprintf(fout, "%s\n", str); 1234 // } 1235 if (!(++lino % 1111)) { 1236 percentage = (int) (lino * 100 / lines_in_filelist); 1237 update_evalcall_form(percentage); 1238 } 1239 } 1240 if (node->down) { 1241 depth++; 1242 save_filelist(node->down, ""); 1243 depth--; 1244 } 1245 } 1246 if (depth == 0) { 1247 paranoid_fclose(fout); 1248 close_evalcall_form(); 1249 log_it("Finished saving filelist"); 1250 } 1251 } 1253 1252 1254 1253 -
branches/3.3/mondo/src/common/libmondo-files.c
r3874 r3878 13 13 #include "mr_file.h" 14 14 #include "mondostructures.h" 15 #include "crcttt.h" 15 16 16 17 #include "libmondo-tools-EXT.h" -
branches/3.3/mondo/src/common/libmondo-fork.c
r3871 r3878 87 87 #define MONDO_POPMSG "Your machine will not retract the CD tray automatically. Please call mondoarchive with the -m (manual CD tray) flag." 88 88 89 void *run_prog_in_bkgd_then_exit(void *info) 90 { 91 char *sz_command; 92 static int res = 4444; 93 94 res = 999; 95 sz_command = (char *) info; 96 log_msg(4, "sz_command = '%s'", sz_command); 97 res = system(sz_command); 98 if (res > 256 && res != 4444) { 99 res = res / 256; 100 } 101 log_msg(4, "child res = %d", res); 102 sz_command[0] = '\0'; 103 pthread_exit((void *) (&res)); 104 } 105 106 107 89 108 90 109 int run_external_binary_with_percentage_indicator_NEW(char *tt, char *cmd) { … … 689 708 690 709 691 void *run_prog_in_bkgd_then_exit(void *info)692 {693 char *sz_command;694 static int res = 4444;695 696 res = 999;697 sz_command = (char *) info;698 log_msg(4, "sz_command = '%s'", sz_command);699 res = system(sz_command);700 if (res > 256 && res != 4444) {701 res = res / 256;702 }703 log_msg(4, "child res = %d", res);704 sz_command[0] = '\0';705 pthread_exit((void *) (&res));706 }707 708 709 710 710 /** 711 711 * Feed @p input_fifo through ntfsclone (restore) to @p output_device. -
branches/3.3/mondo/src/common/libmondo-raid.c
r3871 r3878 246 246 #endif 247 247 248 249 /**250 * Save the additional RAID variables to a stream.251 * @param vars The RAID variable list to save.252 * @param fout The FILE pointer to save them to.253 */254 void255 save_additional_vars_to_file(struct additional_raid_variables *vars,256 FILE * fout)257 {258 int i;259 260 assert(vars != NULL);261 assert(fout != NULL);262 263 for (i = 0; i < vars->entries; i++) {264 fprintf(fout, " %-21s %s\n", vars->el[i].label,265 vars->el[i].value);266 }267 }268 269 270 /**271 * Save a raidlist structure to disk in raidtab format.272 * @param raidlist The raidlist to save.273 * @param fname The file to save it to.274 * @return 0, always.275 * @bug Return value is redundant.276 */277 int save_raidlist_to_raidtab(struct raidlist_itself *raidlist, char *fname)278 {279 FILE *fout;280 int current_raid_device;281 #ifdef __FreeBSD__282 int i;283 #else284 // Linux285 #endif286 287 assert(raidlist != NULL);288 assert_string_is_neither_NULL_nor_zerolength(fname);289 290 if (raidlist->entries <= 0) {291 unlink(fname);292 log_it("Deleting raidtab (no RAID devs anyway)");293 return (0);294 }295 if (!(fout = fopen(fname, "w"))) {296 log_OS_error("Failed to save raidlist");297 return (1);298 }299 fprintf(fout, "# Generated by Mondo Rescue\n");300 301 #ifdef __FreeBSD__302 for (i = 0; i < raidlist->disks.entries; ++i) {303 fprintf(fout, "drive %s device %s\n", raidlist->disks.el[i].name,304 raidlist->disks.el[i].device);305 }306 for (i = 0; i < (raidlist->spares.entries); ++i) {307 fprintf(fout, "drive %s device %s hotspare\n",308 raidlist->spares.el[i].name,309 raidlist->spares.el[i].device);310 }311 #endif312 313 for (current_raid_device = 0; current_raid_device < raidlist->entries;314 current_raid_device++) {315 save_raidrec_to_file(&raidlist->el[current_raid_device], fout);316 }317 paranoid_fclose(fout);318 return (0);319 }320 321 322 /**323 * Save a disklist to a stream in raidtab format.324 * @param listname One of "raid-disk", "spare-disk", "parity-disk", or "failed-disk".325 * @param disklist The disklist to save to @p fout.326 * @param fout The stream to write to.327 */328 void save_disklist_to_file(const char *listname, struct list_of_disks *disklist, FILE * fout)329 {330 int i;331 332 assert_string_is_neither_NULL_nor_zerolength(listname);333 assert(disklist != NULL);334 assert(fout != NULL);335 336 for (i = 0; i < disklist->entries; i++) {337 fprintf(fout, " device %s\n", disklist->el[i].device);338 fprintf(fout, " %-21s %d\n", listname, disklist->el[i].index);339 }340 }341 248 342 249 /** … … 434 341 } 435 342 343 344 /** 345 * Save the additional RAID variables to a stream. 346 * @param vars The RAID variable list to save. 347 * @param fout The FILE pointer to save them to. 348 */ 349 void 350 save_additional_vars_to_file(struct additional_raid_variables *vars, 351 FILE * fout) 352 { 353 int i; 354 355 assert(vars != NULL); 356 assert(fout != NULL); 357 358 for (i = 0; i < vars->entries; i++) { 359 fprintf(fout, " %-21s %s\n", vars->el[i].label, 360 vars->el[i].value); 361 } 362 } 363 364 365 /** 366 * Save a raidlist structure to disk in raidtab format. 367 * @param raidlist The raidlist to save. 368 * @param fname The file to save it to. 369 * @return 0, always. 370 * @bug Return value is redundant. 371 */ 372 int save_raidlist_to_raidtab(struct raidlist_itself *raidlist, char *fname) 373 { 374 FILE *fout; 375 int current_raid_device; 376 #ifdef __FreeBSD__ 377 int i; 378 #else 379 // Linux 380 #endif 381 382 assert(raidlist != NULL); 383 assert_string_is_neither_NULL_nor_zerolength(fname); 384 385 if (raidlist->entries <= 0) { 386 unlink(fname); 387 log_it("Deleting raidtab (no RAID devs anyway)"); 388 return (0); 389 } 390 if (!(fout = fopen(fname, "w"))) { 391 log_OS_error("Failed to save raidlist"); 392 return (1); 393 } 394 fprintf(fout, "# Generated by Mondo Rescue\n"); 395 396 #ifdef __FreeBSD__ 397 for (i = 0; i < raidlist->disks.entries; ++i) { 398 fprintf(fout, "drive %s device %s\n", raidlist->disks.el[i].name, 399 raidlist->disks.el[i].device); 400 } 401 for (i = 0; i < (raidlist->spares.entries); ++i) { 402 fprintf(fout, "drive %s device %s hotspare\n", 403 raidlist->spares.el[i].name, 404 raidlist->spares.el[i].device); 405 } 406 #endif 407 408 for (current_raid_device = 0; current_raid_device < raidlist->entries; 409 current_raid_device++) { 410 save_raidrec_to_file(&raidlist->el[current_raid_device], fout); 411 } 412 paranoid_fclose(fout); 413 return (0); 414 } 415 416 417 /** 418 * Save a disklist to a stream in raidtab format. 419 * @param listname One of "raid-disk", "spare-disk", "parity-disk", or "failed-disk". 420 * @param disklist The disklist to save to @p fout. 421 * @param fout The stream to write to. 422 */ 423 void save_disklist_to_file(const char *listname, struct list_of_disks *disklist, FILE * fout) 424 { 425 int i; 426 427 assert_string_is_neither_NULL_nor_zerolength(listname); 428 assert(disklist != NULL); 429 assert(fout != NULL); 430 431 for (i = 0; i < disklist->entries; i++) { 432 fprintf(fout, " device %s\n", disklist->el[i].device); 433 fprintf(fout, " %-21s %d\n", listname, disklist->el[i].index); 434 } 435 } 436 436 /** 437 437 * Retrieve the next line from a raidtab stream. … … 473 473 return (1); 474 474 } 475 476 477 #ifndef __FreeBSD__ 478 /** 479 * Process a single line from the raidtab and store the results into @p raidrec. 480 * @param fin The stream to read the line from. 481 * @param raidrec The RAID device record to update. 482 * @param label Where to put the label processed. 483 * @param value Where to put the value processed. 484 */ 485 void 486 process_raidtab_line(FILE * fin, struct raid_device_record *raidrec, char *label, char *value) 487 { 488 489 /*@ add mallocs * */ 490 char *labelB = NULL; 491 char *valueB = NULL; 492 493 struct list_of_disks *disklist; 494 int index; 495 int v; 496 497 assert(fin != NULL); 498 assert(raidrec != NULL); 499 assert_string_is_neither_NULL_nor_zerolength(label); 500 assert(value != NULL); 501 502 if (!strcmp(label, "raid-level")) { 503 if (!strcmp(value, "multipath")) { 504 raidrec->raid_level = -2; 505 } else if (!strcmp(value, "linear")) { 506 raidrec->raid_level = -1; 507 } else { 508 raidrec->raid_level = atoi(value); 509 } 510 log_msg(4,"Found raid level %d",raidrec->raid_level); 511 } else if (!strcmp(label, "nr-raid-disks")) { /* ignore it */ 512 } else if (!strcmp(label, "nr-spare-disks")) { /* ignore it */ 513 } else if (!strcmp(label, "nr-parity-disks")) { /* ignore it */ 514 } else if (!strcmp(label, "nr-failed-disks")) { /* ignore it */ 515 } else if (!strcmp(label, "persistent-superblock")) { 516 raidrec->persistent_superblock = atoi(value); 517 } else if (!strcmp(label, "chunk-size")) { 518 raidrec->chunk_size = atoi(value); 519 } else if (!strcmp(label, "parity-algorithm")) { 520 if (!strcmp(value, "left-asymmetric")) { 521 raidrec->parity = 0; 522 } else if (!strcmp(value, "right-asymmetric")) { 523 raidrec->parity = 1; 524 } else if (!strcmp(value, "left-symmetric")) { 525 raidrec->parity = 2; 526 } else if (!strcmp(value, "right-symmetric")) { 527 raidrec->parity = 3; 528 } else { 529 log_msg(1, "Unknown RAID parity algorithm '%s'", value); 530 } 531 log_msg(4,"Found raid parity %d",raidrec->parity); 532 } else if (!strcmp(label, "device")) { 533 get_next_raidtab_line(fin, &labelB, &valueB); 534 if (!strcmp(labelB, "raid-disk")) { 535 disklist = &raidrec->data_disks; 536 } else if (!strcmp(labelB, "spare-disk")) { 537 disklist = &raidrec->spare_disks; 538 } else if (!strcmp(labelB, "parity-disk")) { 539 disklist = &raidrec->parity_disks; 540 } else if (!strcmp(labelB, "failed-disk")) { 541 disklist = &raidrec->failed_disks; 542 } else { 543 disklist = NULL; 544 } 545 if (!disklist) { 546 log_it("Ignoring '%s %s' pair of disk %s", labelB, valueB, label); 547 } else { 548 index = atoi(valueB); 549 add_disk_to_raid_device(disklist, value, index); 550 } 551 mr_free(labelB); 552 } else { 553 v = raidrec->additional_vars.entries; 554 strcpy(raidrec->additional_vars.el[v].label, label); 555 strcpy(raidrec->additional_vars.el[v].value, value); 556 log_msg(4,"Found additional raid pair #%d: %s / %s",v,raidrec->additional_vars.el[v].label,raidrec->additional_vars.el[v].value); 557 v++; 558 raidrec->additional_vars.entries = v; 559 } 560 } 561 #endif 562 475 563 476 564 … … 659 747 #endif 660 748 661 662 663 664 665 666 667 668 #ifndef __FreeBSD__669 /**670 * Process a single line from the raidtab and store the results into @p raidrec.671 * @param fin The stream to read the line from.672 * @param raidrec The RAID device record to update.673 * @param label Where to put the label processed.674 * @param value Where to put the value processed.675 */676 void677 process_raidtab_line(FILE * fin, struct raid_device_record *raidrec, char *label, char *value)678 {679 680 /*@ add mallocs * */681 char *labelB = NULL;682 char *valueB = NULL;683 684 struct list_of_disks *disklist;685 int index;686 int v;687 688 assert(fin != NULL);689 assert(raidrec != NULL);690 assert_string_is_neither_NULL_nor_zerolength(label);691 assert(value != NULL);692 693 if (!strcmp(label, "raid-level")) {694 if (!strcmp(value, "multipath")) {695 raidrec->raid_level = -2;696 } else if (!strcmp(value, "linear")) {697 raidrec->raid_level = -1;698 } else {699 raidrec->raid_level = atoi(value);700 }701 log_msg(4,"Found raid level %d",raidrec->raid_level);702 } else if (!strcmp(label, "nr-raid-disks")) { /* ignore it */703 } else if (!strcmp(label, "nr-spare-disks")) { /* ignore it */704 } else if (!strcmp(label, "nr-parity-disks")) { /* ignore it */705 } else if (!strcmp(label, "nr-failed-disks")) { /* ignore it */706 } else if (!strcmp(label, "persistent-superblock")) {707 raidrec->persistent_superblock = atoi(value);708 } else if (!strcmp(label, "chunk-size")) {709 raidrec->chunk_size = atoi(value);710 } else if (!strcmp(label, "parity-algorithm")) {711 if (!strcmp(value, "left-asymmetric")) {712 raidrec->parity = 0;713 } else if (!strcmp(value, "right-asymmetric")) {714 raidrec->parity = 1;715 } else if (!strcmp(value, "left-symmetric")) {716 raidrec->parity = 2;717 } else if (!strcmp(value, "right-symmetric")) {718 raidrec->parity = 3;719 } else {720 log_msg(1, "Unknown RAID parity algorithm '%s'", value);721 }722 log_msg(4,"Found raid parity %d",raidrec->parity);723 } else if (!strcmp(label, "device")) {724 get_next_raidtab_line(fin, &labelB, &valueB);725 if (!strcmp(labelB, "raid-disk")) {726 disklist = &raidrec->data_disks;727 } else if (!strcmp(labelB, "spare-disk")) {728 disklist = &raidrec->spare_disks;729 } else if (!strcmp(labelB, "parity-disk")) {730 disklist = &raidrec->parity_disks;731 } else if (!strcmp(labelB, "failed-disk")) {732 disklist = &raidrec->failed_disks;733 } else {734 disklist = NULL;735 }736 if (!disklist) {737 log_it("Ignoring '%s %s' pair of disk %s", labelB, valueB, label);738 } else {739 index = atoi(valueB);740 add_disk_to_raid_device(disklist, value, index);741 }742 mr_free(labelB);743 } else {744 v = raidrec->additional_vars.entries;745 strcpy(raidrec->additional_vars.el[v].label, label);746 strcpy(raidrec->additional_vars.el[v].value, value);747 log_msg(4,"Found additional raid pair #%d: %s / %s",v,raidrec->additional_vars.el[v].label,raidrec->additional_vars.el[v].value);748 v++;749 raidrec->additional_vars.entries = v;750 }751 }752 #endif753 749 754 750 -
branches/3.3/mondo/src/common/libmondo-stream.c
r3877 r3878 23 23 #include "libmondo-tools-EXT.h" 24 24 #include "libmondo-fifo-EXT.h" 25 #include "libmondo-devices-EXT.h" 25 26 26 27 #define EXTRA_TAPE_CHECKSUMS … … 40 41 41 42 /** 43 * FIFO used to read/write to the tape device. 44 * @bug This seems obsolete now that we call an external @c buffer program. Please look onto this. 45 */ 46 char g_tape_fifo[MAX_STR_LEN]; 47 48 49 /** 42 50 * @addtogroup globalGroup 43 51 * @{ … … 76 84 77 85 /** 78 * @addtogroup streamGroup 79 * @{ 80 */ 86 * Close the global output file descriptor which Mondo has used to read 87 * from buffer or dd, which read from the tape. 88 * @param bkpinfo The backup information structure. Unused. 89 * @return 0 for success, nonzero for failure. 90 * @note This should be called by restore processes only. 91 * @note This function also works for cdstreams for now, but don't count on this behavior. 92 * @bug @p bkpinfo parameter is unused. 93 */ 94 int closein_tape() 95 { 96 /*@ int's ******************************************************* */ 97 int retval = 0; 98 int res = 0; 99 int ctrl_chr = '\0'; 100 101 /*@ buffers ***************************************************** */ 102 char fname[MAX_STR_LEN]; 103 104 /*@ long long's ************************************************* */ 105 long long size; 106 char *blk; 107 int i; 108 int j; 109 110 blk = (char *) malloc(256 * 1024); 111 112 log_it("closein_tape() -- entering"); 113 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 114 retval += res; 115 if (ctrl_chr != BLK_END_OF_BACKUP) { 116 wrong_marker(BLK_END_OF_BACKUP, ctrl_chr); 117 } 118 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 119 retval += res; 120 if (ctrl_chr != BLK_END_OF_TAPE) { 121 wrong_marker(BLK_END_OF_TAPE, ctrl_chr); 122 } 123 for (i = 0; i < 8 && !feof(g_tape_stream); i++) { 124 j = fread(blk, 1, 256 * 1024, g_tape_stream); 125 if (j) { 126 // FIXME 127 } 128 } 129 sleep(1); 130 sync(); 131 sleep(1); 132 paranoid_pclose(g_tape_stream); 133 log_it("closein_tape() -- leaving"); 134 if (!bkpinfo->please_dont_eject) { 135 eject_device(bkpinfo->media_device); 136 } 137 paranoid_free(blk); 138 paranoid_free(g_tapecatalog); 139 return (retval); 140 } 141 142 143 81 144 /** 82 145 * Close the global output file descriptor which Mondo has used to read … … 144 207 145 208 146 /** 147 * Close the global output file descriptor which Mondo has used to read 148 * from buffer or dd, which read from the tape. 149 * @param bkpinfo The backup information structure. Unused. 150 * @return 0 for success, nonzero for failure. 151 * @note This should be called by restore processes only. 152 * @note This function also works for cdstreams for now, but don't count on this behavior. 153 * @bug @p bkpinfo parameter is unused. 154 */ 155 int closein_tape() 156 { 157 /*@ int's ******************************************************* */ 158 int retval = 0; 159 int res = 0; 160 int ctrl_chr = '\0'; 209 210 211 /** 212 * Log (to screen) an erroneous marker, along with what it should have been. 213 * @param should_be What we were expecting. 214 * @param it_is What we got. 215 */ 216 void wrong_marker(int should_be, int it_is) 217 { 218 char *tmp1 = NULL; 219 char *tmp2 = NULL; 220 tmp1 = marker_to_string(should_be); 221 tmp2 = marker_to_string(it_is); 222 log_to_screen("Wrong marker! (Should be %s, is actually %s)", tmp1, tmp2); 223 mr_free(tmp1); 224 mr_free(tmp2); 225 } 226 227 228 229 /** 230 * Read a header block from the currently opened stream (CD or tape). 231 * This block indicates the length of the following file (if it's file-related) 232 * the filename (if it's file-related), and the block type. 233 * @param plen Where to put the length of the file. Valid only for file-related header blocks. 234 * @param filename Where to put the name of the file. Valid only for file-related header blocks. 235 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...) 236 * @return 0 for success, nonzero for failure. 237 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker(). 238 */ 239 int 240 read_header_block_from_stream(long long *plen, char *filename, 241 int *pcontrol_char) 242 { 161 243 162 244 /*@ buffers ***************************************************** */ 163 char fname[MAX_STR_LEN]; 164 165 /*@ long long's ************************************************* */ 166 long long size; 167 char *blk; 245 char *tempblock; 246 char *tmp = NULL; 247 248 /*@ int ********************************************************* */ 249 int i, retval; 250 251 /*@ end vars *************************************************** */ 252 253 tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE); 254 255 for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) { 256 tempblock[i] = 0; 257 } 258 while (!(*pcontrol_char = tempblock[7000])) { 259 g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024; 260 } 261 memcpy((char *) plen, tempblock + 7001, sizeof(long long)); 262 if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) { 263 log_it("Bad header block at %ld K", (long) g_tape_posK); 264 } 265 strcpy(filename, tempblock + 1000); 266 if (*pcontrol_char == BLK_ABORTED_BACKUP) { 267 log_to_screen("I can't verify an aborted backup."); 268 retval = 1; 269 } else { 270 retval = 0; 271 } 272 for (i = 1000; i < 1020; i++) { 273 if (tempblock[i] < 32 || tempblock[i] > 126) { 274 tempblock[i] = ' '; 275 } 276 } 277 tempblock[i] = '\0'; 278 tmp = marker_to_string(*pcontrol_char); 279 log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10); 280 mr_free(tmp); 281 paranoid_free(tempblock); 282 return (retval); 283 } 284 285 286 287 /** 288 * Tell the user to insert tape @p tapeno and wait for it to settle (5 seconds). 289 * @param tapeno The tape number to insist on. 290 * @bug There is currently no way to actually verify that the user has actually 291 * inserted the right tape. 292 */ 293 void insist_on_this_tape_number(int tapeno) 294 { 168 295 int i; 169 int j; 170 171 blk = (char *) malloc(256 * 1024); 172 173 log_it("closein_tape() -- entering"); 174 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 175 retval += res; 176 if (ctrl_chr != BLK_END_OF_BACKUP) { 177 wrong_marker(BLK_END_OF_BACKUP, ctrl_chr); 178 } 179 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 180 retval += res; 181 if (ctrl_chr != BLK_END_OF_TAPE) { 182 wrong_marker(BLK_END_OF_TAPE, ctrl_chr); 183 } 184 for (i = 0; i < 8 && !feof(g_tape_stream); i++) { 185 j = fread(blk, 1, 256 * 1024, g_tape_stream); 186 if (j) { 187 // FIXME 188 } 189 } 190 sleep(1); 191 sync(); 192 sleep(1); 193 paranoid_pclose(g_tape_stream); 194 log_it("closein_tape() -- leaving"); 195 if (!bkpinfo->please_dont_eject) { 196 eject_device(bkpinfo->media_device); 197 } 198 paranoid_free(blk); 199 paranoid_free(g_tapecatalog); 200 return (retval); 201 } 296 char *tmp = NULL; 297 298 log_it("Insisting on tape #%d", tapeno); 299 if (g_current_media_number != tapeno) { 300 mr_asprintf(tmp, "When the tape drive goes quiet, please insert volume %d in this series.", tapeno); 301 popup_and_OK(tmp); 302 mr_free(tmp); 303 open_evalcall_form("Waiting while the tape drive settles"); 304 } else { 305 open_evalcall_form("Waiting while the tape drive rewinds"); 306 } 307 308 for (i = 0; i <= 100; i += 2) { 309 usleep(100000); 310 update_evalcall_form(i); 311 } 312 close_evalcall_form(); 313 log_it("I assume user has inserted it. They _say_ they have..."); 314 g_current_media_number = tapeno; 315 316 // log_it("g_current_media_number = %d", g_current_media_number); 317 log_it("OK, I've finished insisting. On with the revelry."); 318 } 319 320 202 321 203 322 … … 441 560 } 442 561 return (dev); 443 }444 445 446 /**447 * Copy a file from the opened stream (CD or tape) to @p outfile.448 * @param outfile The file to write to.449 * @param size The size of the file in the input stream.450 * @return 0 for success, nonzero for failure.451 */452 int453 read_file_from_stream_to_file(char *outfile, long long size)454 {455 456 /*@ int ******************************************************** */457 int res;458 459 /*@ end vars *************************************************** */460 461 res = read_file_from_stream_FULL(outfile, NULL, size);462 463 return (res);464 }465 466 467 468 469 int read_EXAT_files_from_tape(long long *ptmp_size, char *tmp_fname,470 int *pctrl_chr, char *xattr_fname,471 char *acl_fname)472 {473 int res = 0;474 char fname_buf[PATH_MAX];475 char *fname = (char *)fname_buf; /* Should NOT be NULL */476 char *tmp = NULL;477 478 // xattr479 if (g_getfattr) {480 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);481 if (*pctrl_chr != BLK_START_EXAT_FILE) {482 wrong_marker(BLK_START_EXAT_FILE, *pctrl_chr);483 }484 if (strstr(fname, "xattr") == NULL) {485 mr_asprintf(tmp,"Wrong order expected xattr, got %s, sunshine.", fname);486 fatal_error(tmp);487 }488 read_file_from_stream_to_file(xattr_fname, *ptmp_size);489 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);490 if (*pctrl_chr != BLK_STOP_EXAT_FILE) {491 wrong_marker(BLK_STOP_EXAT_FILE, *pctrl_chr);492 }493 log_msg(1, "Got xattr");494 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);495 if (*pctrl_chr != BLK_STOP_EXTENDED_ATTRIBUTES) {496 wrong_marker(BLK_STOP_EXTENDED_ATTRIBUTES, *pctrl_chr);497 }498 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);499 if (*pctrl_chr == BLK_START_AN_AFIO_OR_SLICE) {500 log_msg(1, "No acl attributes found, skipping to afio files");501 return(0);502 } else {503 if (*pctrl_chr != BLK_START_EXTENDED_ATTRIBUTES) {504 wrong_marker(BLK_START_EXTENDED_ATTRIBUTES, *pctrl_chr);505 }506 }507 }508 // acl509 if (g_getfacl) {510 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);511 if (*pctrl_chr != BLK_START_EXAT_FILE) {512 wrong_marker(BLK_START_EXAT_FILE, *pctrl_chr);513 }514 if (strstr(fname, "acl") == NULL) {515 mr_asprintf(tmp,"Wrong order expected acl, got %s, sunshine.", fname);516 fatal_error(tmp);517 }518 read_file_from_stream_to_file(acl_fname, *ptmp_size);519 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);520 if (*pctrl_chr != BLK_STOP_EXAT_FILE) {521 wrong_marker(BLK_STOP_EXAT_FILE, *pctrl_chr);522 }523 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr);524 if (*pctrl_chr != BLK_STOP_EXTENDED_ATTRIBUTES) {525 wrong_marker(BLK_STOP_EXTENDED_ATTRIBUTES, *pctrl_chr);526 }527 log_msg(1, "Got acl");528 }529 // tarball itself530 res = read_header_block_from_stream(ptmp_size, tmp_fname, pctrl_chr);531 log_msg(1, "End of extended attributes, now looking for afioball");532 return (res);533 }534 535 536 /**537 * Copy @p infile to the opened stream (CD or tape).538 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.539 * @param infile The file to write to the stream.540 * @return 0 for success, nonzero for failure.541 */542 int write_file_to_stream_from_file(char *infile)543 {544 /*@ buffers **************************************************** */545 char datablock[TAPE_BLOCK_SIZE];546 char *checksum = NULL;547 char *infile_basename;548 549 /*@ int ******************************************************** */550 int retval = 0;551 int noof_blocks;552 553 /* unsigned int ch; */554 unsigned int crc16;555 unsigned int crctt;556 557 /*@ pointers *************************************************** */558 FILE *fin;559 char *p;560 561 /*@ long ******************************************************* */562 long bytes_to_read = 0;563 long i;564 565 off_t filesize;566 567 #ifdef EXTRA_TAPE_CHECKSUMS568 int ch;569 #endif570 571 /*@ initialize ************************************************ */572 crc16 = 0;573 crctt = 0;574 575 576 577 /*@ end vars *************************************************** */578 579 infile_basename = strrchr(infile, '/');580 if (infile_basename) {581 infile_basename++;582 } else {583 infile_basename = infile;584 }585 filesize = length_of_file(infile);586 if (should_we_write_to_next_tape(bkpinfo->media_size, filesize)) {587 start_to_write_to_next_tape();588 write_backcatalog_to_tape();589 }590 p = strrchr(infile, '/');591 if (!p) {592 p = infile;593 } else {594 p++;595 }596 log_it("Writing file '%s' to tape (%ld KB)", p, (long) filesize >> 10);597 write_header_block_to_stream(filesize, infile_basename, BLK_START_FILE);598 //go_here_to_restart_saving_of_file:599 if (!(fin = fopen(infile, "r"))) {600 log_OS_error(infile);601 return (1);602 }603 for (noof_blocks = 0; filesize > 0;604 noof_blocks++, filesize -= bytes_to_read) {605 if (filesize < TAPE_BLOCK_SIZE) {606 bytes_to_read = (long) filesize;607 for (i = 0; i < TAPE_BLOCK_SIZE; i++) {608 datablock[i] = '\0';609 }610 } else {611 bytes_to_read = TAPE_BLOCK_SIZE;612 }613 if (fread(datablock, 1, (size_t) bytes_to_read, fin)) {614 // FIXME615 }616 g_tape_posK +=617 fwrite(datablock, 1, /*bytes_to_read */618 (size_t) TAPE_BLOCK_SIZE,619 g_tape_stream) / 1024;620 if (g_sigpipe) {621 log_it("Sigpipe occurred recently. I'll start a new tape.");622 fclose(fin);623 g_sigpipe = FALSE;624 start_to_write_to_next_tape();625 write_backcatalog_to_tape(); // kinda-sorta recursive :)626 return (0);627 }628 #ifdef EXTRA_TAPE_CHECKSUMS629 for (i = 0; i < bytes_to_read; i++) {630 ch = datablock[i];631 crc16 = updcrcr(crc16, (unsigned) ch);632 crctt = updcrc(crctt, (unsigned) ch);633 }634 #endif635 }636 paranoid_fclose(fin);637 mr_asprintf(checksum, "%04x%04x", crc16, crctt);638 /* TODO: what does it do ??? */639 write_header_block_to_stream((off_t)g_current_media_number, checksum, BLK_STOP_FILE);640 mr_free(checksum);641 642 // log_it("File '%s' written to tape.", infile);643 return (retval);644 }645 646 647 648 649 650 651 652 653 int write_EXAT_files_to_tape(char *xattr_fname,654 char *acl_fname)655 {656 int res = 0;657 if (g_getfattr) {658 // xattr659 write_header_block_to_stream(length_of_file(xattr_fname), xattr_fname, BLK_START_EXTENDED_ATTRIBUTES);660 write_header_block_to_stream(length_of_file(xattr_fname), xattr_fname, BLK_START_EXAT_FILE);661 write_file_to_stream_from_file(xattr_fname);662 write_header_block_to_stream((off_t)-1, xattr_fname, BLK_STOP_EXAT_FILE);663 write_header_block_to_stream(length_of_file(xattr_fname), xattr_fname, BLK_STOP_EXTENDED_ATTRIBUTES);664 }665 if (g_getfacl) {666 // acl667 write_header_block_to_stream(length_of_file(acl_fname), acl_fname, BLK_START_EXTENDED_ATTRIBUTES);668 write_header_block_to_stream(length_of_file(acl_fname), acl_fname, BLK_START_EXAT_FILE);669 write_file_to_stream_from_file(acl_fname);670 write_header_block_to_stream((off_t)-1, acl_fname, BLK_STOP_EXAT_FILE);671 write_header_block_to_stream(length_of_file(acl_fname), acl_fname, BLK_STOP_EXTENDED_ATTRIBUTES);672 }673 return (res);674 }675 676 677 678 679 /**680 * Tell the user to insert tape @p tapeno and wait for it to settle (5 seconds).681 * @param tapeno The tape number to insist on.682 * @bug There is currently no way to actually verify that the user has actually683 * inserted the right tape.684 */685 void insist_on_this_tape_number(int tapeno)686 {687 int i;688 char *tmp = NULL;689 690 log_it("Insisting on tape #%d", tapeno);691 if (g_current_media_number != tapeno) {692 mr_asprintf(tmp, "When the tape drive goes quiet, please insert volume %d in this series.", tapeno);693 popup_and_OK(tmp);694 mr_free(tmp);695 open_evalcall_form("Waiting while the tape drive settles");696 } else {697 open_evalcall_form("Waiting while the tape drive rewinds");698 }699 700 for (i = 0; i <= 100; i += 2) {701 usleep(100000);702 update_evalcall_form(i);703 }704 close_evalcall_form();705 log_it("I assume user has inserted it. They _say_ they have...");706 g_current_media_number = tapeno;707 708 // log_it("g_current_media_number = %d", g_current_media_number);709 log_it("OK, I've finished insisting. On with the revelry.");710 }711 712 713 714 715 /**716 * Debugging aid - log the offset we're at on the tape (reading or writing).717 */718 void log_tape_pos(void)719 {720 /*@ buffers ***************************************************** */721 722 723 /*@ end vars *************************************************** */724 725 log_it("Tape position -- %ld KB (%ld MB)", (long) g_tape_posK,726 (long) g_tape_posK >> 10);727 }728 729 730 731 732 /**733 * Add a file to a collection of recently archived filesets/slices.734 * The type is determined by the filename: if it contains ".afio." it is735 * assumed to be a fileset, otherwise if it contains "slice" it's a slice,736 * otherwise we generate a fatal_error().737 * @param td The current @c bkpinfo->tempdir (file will be placed in <tt>td</tt>/tmpfs/backcatalog/).738 * @param latest_fname The file to place in the collection.739 * @return 0, always.740 * @bug Return value is redundant.741 * @bug The detection won't work for uncompressed afioballs (they end in ".afio", no dot afterwards). // Not true. They end in '.' -Hugo742 */743 int maintain_collection_of_recent_archives(char *td, char *latest_fname)744 {745 long long final_alleged_writeK, final_projected_certain_writeK,746 cposK, bufsize_K;747 int last, curr, i;748 char *command = NULL;749 char *tmpdir = NULL;750 char *old_fname = NULL;751 char *p;752 char suffix[16];753 754 bufsize_K = (long long) (1024LL * (1 + g_tape_buffer_size_MB));755 if ((p = strrchr(latest_fname, '.'))) {756 strcpy(suffix, ++p);757 } else {758 suffix[0] = '\0';759 }760 mr_asprintf(tmpdir, "%s/tmpfs/backcatalog", td);761 mkdir(tmpdir, 0x700);762 mr_asprintf(command, "cp -f %s %s", latest_fname, tmpdir);763 if (run_program_and_log_output(command, 6)) {764 log_it("Warning - failed to copy %s to backcatalog at %s",765 latest_fname, tmpdir);766 }767 mr_free(command);768 769 last = g_tapecatalog->entries - 1;770 if (last <= 0) {771 log_it("Too early to start deleting from collection.");772 mr_free(tmpdir);773 return (0);774 }775 final_alleged_writeK = g_tapecatalog->el[last].tape_posK;776 final_projected_certain_writeK = final_alleged_writeK - bufsize_K;777 for (curr = last; curr >= 0; curr--) {778 cposK = g_tapecatalog->el[curr].tape_posK;779 if (cposK < final_projected_certain_writeK) {780 break;781 }782 }783 if (curr < 0) {784 log_it("Not far enough into tape to start deleting old archives from collection.");785 mr_free(tmpdir);786 return (0);787 }788 789 for (i = curr - 1; i >= 0 && curr - i < 10; i--) {790 mr_asprintf(old_fname, "%s/%s", tmpdir, g_tapecatalog->el[i].fname);791 unlink(old_fname);792 mr_free(old_fname);793 }794 mr_free(tmpdir);795 return (0);796 }797 798 799 800 /**801 * Open the tape device for input.802 * @param bkpinfo The backup information structure. Fields used:803 * - @c bkpinfo->media_device804 * - @c bkpinfo->tmpdir805 * @return 0 for success, nonzero for failure.806 * @note This will also work with a cdstream for now, but don't count on this behavior.807 */808 int openin_tape()809 {810 /*@ buffer ***************************************************** */811 char fname[MAX_STR_LEN];812 char *datablock;813 char *tmp = NULL;814 char *old_pwd = NULL;815 char *outfname = NULL;816 /*@ int ******************************************************* */817 int i;818 int j;819 int res = 0;820 long length, templong;821 size_t k;822 int retval = 0;823 int ctrl_chr;824 825 /*@ long long ************************************************* */826 long long size;827 828 /*@ pointers ************************************************** */829 FILE *fout;830 831 /*@ end vars *************************************************** */832 833 g_tapecatalog = mr_malloc(sizeof(struct s_tapecatalog));834 g_tapecatalog->entries = 0;835 g_tape_posK = 0;836 if (g_tape_stream) {837 log_it("FYI - I won't 'openin' the tape. It's already open.");838 return (0);839 }840 841 // mondoarchive should have configured everything to give the right non-rew device842 if ((bkpinfo->use_obdr) && (bkpinfo->media_device != NULL)) {843 res = skip_obdr();844 if (res != 0) {845 log_it("Not able to skip OBDR - Restore will have to be done manually");846 }847 } else {848 if (bkpinfo->media_device == NULL) {849 log_it("Not able to skip OBDR - Restore will have to be done manually");850 return (1);851 }852 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);853 }854 855 insist_on_this_tape_number(1);856 mr_asprintf(outfname, "%s/tmp/all.tar.gz", bkpinfo->tmpdir);857 make_hole_for_file(outfname);858 859 log_it("Opening IN tape");860 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'r', bkpinfo->internal_tape_block_size))) {861 log_OS_error(g_tape_fifo);862 log_to_screen("Cannot openin stream device");863 mr_free(outfname);864 return (1);865 }866 log_to_screen("Reading stream");867 log_it("stream device = '%s'", bkpinfo->media_device);868 /* skip data disks */869 open_evalcall_form("Skipping data disks on stream");870 log_to_screen("Skipping data disks on stream");871 if (!(fout = fopen(outfname, "w"))) {872 log_OS_error(outfname);873 log_to_screen("Cannot openout datadisk all.tar.gz file");874 mr_free(outfname);875 return (-1);876 }877 if (!(datablock = (char *) malloc(256 * 1024))) {878 log_to_screen("Unable to malloc 256*1024");879 mr_free(outfname);880 finish(1);881 }882 for (i = 0; i < 32; i++) {883 for (j = 0; j < 4; j++) {884 for (length = 0, k = 0; length < 256 * 1024; length += k) {885 k = fread(datablock + length, 1, 256 * 1024 - length,886 g_tape_stream);887 }888 if (fwrite(datablock, 1, (size_t) length, fout)) {889 // FIXME890 }891 g_tape_posK += length / 1024;892 }893 if (i > 8) // otherwise, 'buffer' distorts calculations894 {895 templong = ((i - 8) * 4 + j) * 100 / (128 - 8 * 4);896 update_evalcall_form((int) (templong));897 }898 }899 paranoid_fclose(fout);900 paranoid_free(datablock);901 902 /* find initial blocks */903 res = read_header_block_from_stream(&size, fname, &ctrl_chr);904 retval += res;905 if (ctrl_chr != BLK_START_OF_TAPE) {906 wrong_marker(BLK_START_OF_TAPE, ctrl_chr);907 }908 res = read_header_block_from_stream(&size, fname, &ctrl_chr);909 retval += res;910 if (ctrl_chr != BLK_START_OF_BACKUP) {911 wrong_marker(BLK_START_OF_BACKUP, ctrl_chr);912 }913 close_evalcall_form();914 log_it("Saved all.tar.gz to '%s'", outfname);915 old_pwd = mr_getcwd();916 if (chdir(bkpinfo->tmpdir)) {917 // FIXME918 }919 mr_asprintf(tmp, "tar -zxf %s ./tmp/mondorestore.cfg 2> /dev/null", outfname);920 paranoid_system(tmp);921 mr_free(tmp);922 923 paranoid_system("cp -f tmp/mondorestore.cfg . 2> /dev/null");924 if (chdir(old_pwd)) {925 // FIXME926 }927 mr_free(old_pwd);928 unlink(outfname);929 mr_free(outfname);930 return (retval);931 }932 933 934 935 /**936 * Open the CD stream for input.937 * @param bkpinfo The backup information structure. Passed to openin_tape().938 * @return 0 for success, nonzero for failure.939 * @note Equivalent to openin_tape() for now, but don't count on this behavior.940 */941 int openin_cdstream()942 {943 return (openin_tape());944 }945 946 /**947 * FIFO used to read/write to the tape device.948 * @bug This seems obsolete now that we call an external @c buffer program. Please look onto this.949 */950 char g_tape_fifo[MAX_STR_LEN];951 952 953 954 int set_tape_block_size_with_mt(long internal_tape_block_size)955 {956 char *tmp = NULL;957 int res;958 959 if (bkpinfo->media_device == NULL) {960 return(1);961 }962 963 if (strncmp(bkpinfo->media_device, "/dev/", 5)) {964 log_msg(1, "Not using 'mt setblk'. This isn't an actual /dev entry.");965 return (0);966 }967 mr_asprintf(tmp, "mt -f %s setblk %ld", bkpinfo->media_device, internal_tape_block_size);968 res = run_program_and_log_output(tmp, 3);969 mr_free(tmp);970 return (res);971 }972 973 /**974 * Return the non-rewinding device when passed the normal one975 * @param tapedev The tape device to open for writing.976 * @note the caller needs to free the string returned977 */978 char *get_non_rewind_dev(char *tapedev)979 {980 981 char *ntapedev = NULL;982 char *p = NULL;983 char *q = NULL;984 char *r = NULL;985 986 ntapedev = (char *)mr_malloc(strlen(tapedev)+2*sizeof(char));987 p = strrchr(tapedev,'/');988 if (p == NULL) {989 log_it("Didn't find a '/' in %s",tapedev);990 return(NULL);991 }992 993 /* Copy tapedev content up to the last / */994 q = tapedev;995 r = ntapedev;996 while (q != p) {997 *r = *q;998 r++;999 q++;1000 }1001 /* Copy the '/' */1002 *r = *q;1003 r++;1004 q++;1005 /* Adds a 'n' - non-rewinding */1006 *r = 'n';1007 r++;1008 /* Copy the rest of tapedev */1009 while (*q != '\0') {1010 *r = *q;1011 r++;1012 q++;1013 }1014 *r = '\0';1015 if (mt_says_tape_exists(ntapedev)) {1016 log_it("Non-rewinding tape device is %s",ntapedev);1017 } else {1018 log_it("Unable to find non-rewinding tape device.");1019 ntapedev = NULL;1020 }1021 return(ntapedev);1022 }1023 1024 1025 1026 /**1027 * Handle OBDR if we were asked to do so1028 * @param tapedev The tape device to open for reading.1029 */1030 int skip_obdr(void)1031 {1032 char *command = NULL;1033 int res = 0;1034 1035 if (bkpinfo->media_device == NULL) {1036 return(1);1037 }1038 1039 log_it("Skipping OBDR headers");1040 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);1041 res = run_program_and_log_output(command, 1);1042 paranoid_free(command);1043 1044 mr_asprintf(command, "mt -f %s fsf 2",bkpinfo->media_device);1045 res = run_program_and_log_output(command, 1);1046 paranoid_free(command);1047 1048 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);1049 return(res);1050 }1051 1052 /**1053 * Handle OBDR if we were asked to do so1054 * @param tapedev The tape device to open for writing.1055 * @return 0 for success, nonzero for failure.1056 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY1057 * EXISTING DATA on the tape!1058 */1059 int create_obdr(void)1060 {1061 1062 char *command = NULL;1063 int res = 0;1064 1065 if (bkpinfo->media_device == NULL) {1066 return(1);1067 }1068 1069 log_it("Creating OBDR headers");1070 /* OBDR: First block 10 kB of zero bs = 512 */1071 mr_asprintf(command, "mt -f %s compression off",bkpinfo->media_device);1072 res = run_program_and_log_output(command, 1);1073 paranoid_free(command);1074 1075 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);1076 res += run_program_and_log_output(command, 1);1077 paranoid_free(command);1078 1079 set_tape_block_size_with_mt(512);1080 1081 mr_asprintf(command, "dd if=/dev/zero of=%s bs=512 count=20",bkpinfo->media_device);1082 res += run_program_and_log_output(command, 1);1083 paranoid_free(command);1084 1085 /* OBDR: then ISO boot image bs = 2048 */1086 set_tape_block_size_with_mt(2048);1087 1088 mr_asprintf(command, "dd if=%s of=%s bs=2048",MINDI_CACHE"/mindi.iso",bkpinfo->media_device);1089 res += run_program_and_log_output(command, 1);1090 paranoid_free(command);1091 1092 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);1093 1094 /* restore compression mode on */1095 mr_asprintf(command, "mt -f %s compression on",bkpinfo->media_device);1096 res = run_program_and_log_output(command, 1);1097 paranoid_free(command);1098 1099 return(res);1100 }1101 1102 1103 /**1104 * Start writing to a CD stream.1105 * @param cddev The CD device to openout via cdrecord.1106 * @param speed The speed to write at.1107 * @return 0 for success, nonzero for failure.1108 * @note This should be called only from backup processes.1109 */1110 int openout_cdstream(char *cddev, int speed)1111 {1112 /*@ buffers ***************************************************** */1113 char *command = NULL;1114 1115 /*@ end vars *************************************************** */1116 1117 if (cddev == NULL) {1118 log_to_screen("Failed to openout NULL cddev");1119 return (1);1120 }1121 /* add 'dummy' if testing */1122 mr_asprintf(command, "cdrecord -eject dev=%s speed=%d fs=24m -waiti - >> %s 2>> %s", cddev, speed, MONDO_LOGFILE, MONDO_LOGFILE);1123 /* initialise the catalog */1124 g_current_media_number = 1;1125 if (!(g_tapecatalog = malloc(sizeof(struct s_tapecatalog)))) {1126 fatal_error("Cannot alloc mem for tape catalog");1127 }1128 g_tapecatalog->entries = 0;1129 /* log stuff */1130 log_it("Opening OUT cdstream with the command");1131 log_it(command);1132 /* log_it("Let's see what happens, shall we?"); */1133 g_tape_stream = popen(command, "w");1134 mr_free(command);1135 1136 if (g_tape_stream) {1137 return (0);1138 } else {1139 log_to_screen("Failed to openout to cdstream (fifo)");1140 return (1);1141 }1142 }1143 1144 1145 /**1146 * Start writing to a tape device for the backup.1147 * Handle OBDR if we were asked to do so1148 * @param tapedev The tape device to open for writing.1149 * @return 0 for success, nonzero for failure.1150 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY1151 * EXISTING DATA on the tape!1152 */1153 int openout_tape() {1154 1155 g_current_media_number = 1;1156 if (g_tape_stream) {1157 log_it("FYI - I won't 'openout' the tape. It's already open.");1158 return (0);1159 }1160 if (bkpinfo->media_device == NULL) {1161 log_it("Unable to openout NULL device");1162 return(1);1163 }1164 g_tapecatalog = mr_malloc(sizeof(struct s_tapecatalog));1165 g_tapecatalog->entries = 0;1166 g_tape_posK = 0;1167 1168 if (bkpinfo->use_obdr) {1169 create_obdr();1170 } else {1171 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);1172 }1173 log_it("Opening OUT tape");1174 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'w', bkpinfo->internal_tape_block_size))) {1175 log_OS_error(g_tape_fifo);1176 log_to_screen("Cannot openin stream device");1177 return (1);1178 }1179 return (0);1180 562 } 1181 563 … … 1327 709 1328 710 1329 1330 /** 1331 * Copy a file from the currently opened stream (CD or tape) to the stream indicated 1332 * by @p fout. 1333 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used. 1334 * @param fout The stream to write the file to. 1335 * @param size The size of the file in bytes. 711 /** 712 * Copy a file from the opened stream (CD or tape) to @p outfile. 713 * @param outfile The file to write to. 714 * @param size The size of the file in the input stream. 1336 715 * @return 0 for success, nonzero for failure. 1337 716 */ 1338 717 int 1339 read_file_from_stream_to_ stream(FILE * fout, long long size)718 read_file_from_stream_to_file(char *outfile, long long size) 1340 719 { 1341 720 … … 1345 724 /*@ end vars *************************************************** */ 1346 725 1347 res = read_file_from_stream_FULL(NULL, fout, size); 1348 /* fflush(g_tape_stream); 1349 fflush(fout);*/ 726 res = read_file_from_stream_FULL(outfile, NULL, size); 727 1350 728 return (res); 729 } 730 731 732 733 734 int read_EXAT_files_from_tape(long long *ptmp_size, char *tmp_fname, 735 int *pctrl_chr, char *xattr_fname, 736 char *acl_fname) 737 { 738 int res = 0; 739 char fname_buf[PATH_MAX]; 740 char *fname = (char *)fname_buf; /* Should NOT be NULL */ 741 char *tmp = NULL; 742 743 // xattr 744 if (g_getfattr) { 745 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 746 if (*pctrl_chr != BLK_START_EXAT_FILE) { 747 wrong_marker(BLK_START_EXAT_FILE, *pctrl_chr); 748 } 749 if (strstr(fname, "xattr") == NULL) { 750 mr_asprintf(tmp,"Wrong order expected xattr, got %s, sunshine.", fname); 751 fatal_error(tmp); 752 } 753 read_file_from_stream_to_file(xattr_fname, *ptmp_size); 754 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 755 if (*pctrl_chr != BLK_STOP_EXAT_FILE) { 756 wrong_marker(BLK_STOP_EXAT_FILE, *pctrl_chr); 757 } 758 log_msg(1, "Got xattr"); 759 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 760 if (*pctrl_chr != BLK_STOP_EXTENDED_ATTRIBUTES) { 761 wrong_marker(BLK_STOP_EXTENDED_ATTRIBUTES, *pctrl_chr); 762 } 763 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 764 if (*pctrl_chr == BLK_START_AN_AFIO_OR_SLICE) { 765 log_msg(1, "No acl attributes found, skipping to afio files"); 766 return(0); 767 } else { 768 if (*pctrl_chr != BLK_START_EXTENDED_ATTRIBUTES) { 769 wrong_marker(BLK_START_EXTENDED_ATTRIBUTES, *pctrl_chr); 770 } 771 } 772 } 773 // acl 774 if (g_getfacl) { 775 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 776 if (*pctrl_chr != BLK_START_EXAT_FILE) { 777 wrong_marker(BLK_START_EXAT_FILE, *pctrl_chr); 778 } 779 if (strstr(fname, "acl") == NULL) { 780 mr_asprintf(tmp,"Wrong order expected acl, got %s, sunshine.", fname); 781 fatal_error(tmp); 782 } 783 read_file_from_stream_to_file(acl_fname, *ptmp_size); 784 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 785 if (*pctrl_chr != BLK_STOP_EXAT_FILE) { 786 wrong_marker(BLK_STOP_EXAT_FILE, *pctrl_chr); 787 } 788 res = read_header_block_from_stream(ptmp_size, fname, pctrl_chr); 789 if (*pctrl_chr != BLK_STOP_EXTENDED_ATTRIBUTES) { 790 wrong_marker(BLK_STOP_EXTENDED_ATTRIBUTES, *pctrl_chr); 791 } 792 log_msg(1, "Got acl"); 793 } 794 // tarball itself 795 res = read_header_block_from_stream(ptmp_size, tmp_fname, pctrl_chr); 796 log_msg(1, "End of extended attributes, now looking for afioball"); 797 return (res); 798 } 799 800 801 /** 802 * Copy @p infile to the opened stream (CD or tape). 803 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used. 804 * @param infile The file to write to the stream. 805 * @return 0 for success, nonzero for failure. 806 */ 807 int write_file_to_stream_from_file(char *infile) 808 { 809 /*@ buffers **************************************************** */ 810 char datablock[TAPE_BLOCK_SIZE]; 811 char *checksum = NULL; 812 char *infile_basename; 813 814 /*@ int ******************************************************** */ 815 int retval = 0; 816 int noof_blocks; 817 818 /* unsigned int ch; */ 819 unsigned int crc16; 820 unsigned int crctt; 821 822 /*@ pointers *************************************************** */ 823 FILE *fin; 824 char *p; 825 826 /*@ long ******************************************************* */ 827 long bytes_to_read = 0; 828 long i; 829 830 off_t filesize; 831 832 #ifdef EXTRA_TAPE_CHECKSUMS 833 int ch; 834 #endif 835 836 /*@ initialize ************************************************ */ 837 crc16 = 0; 838 crctt = 0; 839 840 841 842 /*@ end vars *************************************************** */ 843 844 infile_basename = strrchr(infile, '/'); 845 if (infile_basename) { 846 infile_basename++; 847 } else { 848 infile_basename = infile; 849 } 850 filesize = length_of_file(infile); 851 if (should_we_write_to_next_tape(bkpinfo->media_size, filesize)) { 852 start_to_write_to_next_tape(); 853 write_backcatalog_to_tape(); 854 } 855 p = strrchr(infile, '/'); 856 if (!p) { 857 p = infile; 858 } else { 859 p++; 860 } 861 log_it("Writing file '%s' to tape (%ld KB)", p, (long) filesize >> 10); 862 write_header_block_to_stream(filesize, infile_basename, BLK_START_FILE); 863 //go_here_to_restart_saving_of_file: 864 if (!(fin = fopen(infile, "r"))) { 865 log_OS_error(infile); 866 return (1); 867 } 868 for (noof_blocks = 0; filesize > 0; 869 noof_blocks++, filesize -= bytes_to_read) { 870 if (filesize < TAPE_BLOCK_SIZE) { 871 bytes_to_read = (long) filesize; 872 for (i = 0; i < TAPE_BLOCK_SIZE; i++) { 873 datablock[i] = '\0'; 874 } 875 } else { 876 bytes_to_read = TAPE_BLOCK_SIZE; 877 } 878 if (fread(datablock, 1, (size_t) bytes_to_read, fin)) { 879 // FIXME 880 } 881 g_tape_posK += 882 fwrite(datablock, 1, /*bytes_to_read */ 883 (size_t) TAPE_BLOCK_SIZE, 884 g_tape_stream) / 1024; 885 if (g_sigpipe) { 886 log_it("Sigpipe occurred recently. I'll start a new tape."); 887 fclose(fin); 888 g_sigpipe = FALSE; 889 start_to_write_to_next_tape(); 890 write_backcatalog_to_tape(); // kinda-sorta recursive :) 891 return (0); 892 } 893 #ifdef EXTRA_TAPE_CHECKSUMS 894 for (i = 0; i < bytes_to_read; i++) { 895 ch = datablock[i]; 896 crc16 = updcrcr(crc16, (unsigned) ch); 897 crctt = updcrc(crctt, (unsigned) ch); 898 } 899 #endif 900 } 901 paranoid_fclose(fin); 902 mr_asprintf(checksum, "%04x%04x", crc16, crctt); 903 /* TODO: what does it do ??? */ 904 write_header_block_to_stream((off_t)g_current_media_number, checksum, BLK_STOP_FILE); 905 mr_free(checksum); 906 907 // log_it("File '%s' written to tape.", infile); 908 return (retval); 909 } 910 911 912 913 914 915 916 917 918 int write_EXAT_files_to_tape(char *xattr_fname, 919 char *acl_fname) 920 { 921 int res = 0; 922 if (g_getfattr) { 923 // xattr 924 write_header_block_to_stream(length_of_file(xattr_fname), xattr_fname, BLK_START_EXTENDED_ATTRIBUTES); 925 write_header_block_to_stream(length_of_file(xattr_fname), xattr_fname, BLK_START_EXAT_FILE); 926 write_file_to_stream_from_file(xattr_fname); 927 write_header_block_to_stream((off_t)-1, xattr_fname, BLK_STOP_EXAT_FILE); 928 write_header_block_to_stream(length_of_file(xattr_fname), xattr_fname, BLK_STOP_EXTENDED_ATTRIBUTES); 929 } 930 if (g_getfacl) { 931 // acl 932 write_header_block_to_stream(length_of_file(acl_fname), acl_fname, BLK_START_EXTENDED_ATTRIBUTES); 933 write_header_block_to_stream(length_of_file(acl_fname), acl_fname, BLK_START_EXAT_FILE); 934 write_file_to_stream_from_file(acl_fname); 935 write_header_block_to_stream((off_t)-1, acl_fname, BLK_STOP_EXAT_FILE); 936 write_header_block_to_stream(length_of_file(acl_fname), acl_fname, BLK_STOP_EXTENDED_ATTRIBUTES); 937 } 938 return (res); 939 } 940 941 942 943 944 /** 945 * Debugging aid - log the offset we're at on the tape (reading or writing). 946 */ 947 void log_tape_pos(void) 948 { 949 /*@ buffers ***************************************************** */ 950 951 952 /*@ end vars *************************************************** */ 953 954 log_it("Tape position -- %ld KB (%ld MB)", (long) g_tape_posK, 955 (long) g_tape_posK >> 10); 956 } 957 958 959 960 961 /** 962 * Add a file to a collection of recently archived filesets/slices. 963 * The type is determined by the filename: if it contains ".afio." it is 964 * assumed to be a fileset, otherwise if it contains "slice" it's a slice, 965 * otherwise we generate a fatal_error(). 966 * @param td The current @c bkpinfo->tempdir (file will be placed in <tt>td</tt>/tmpfs/backcatalog/). 967 * @param latest_fname The file to place in the collection. 968 * @return 0, always. 969 * @bug Return value is redundant. 970 * @bug The detection won't work for uncompressed afioballs (they end in ".afio", no dot afterwards). // Not true. They end in '.' -Hugo 971 */ 972 int maintain_collection_of_recent_archives(char *td, char *latest_fname) 973 { 974 long long final_alleged_writeK, final_projected_certain_writeK, 975 cposK, bufsize_K; 976 int last, curr, i; 977 char *command = NULL; 978 char *tmpdir = NULL; 979 char *old_fname = NULL; 980 char *p; 981 char suffix[16]; 982 983 bufsize_K = (long long) (1024LL * (1 + g_tape_buffer_size_MB)); 984 if ((p = strrchr(latest_fname, '.'))) { 985 strcpy(suffix, ++p); 986 } else { 987 suffix[0] = '\0'; 988 } 989 mr_asprintf(tmpdir, "%s/tmpfs/backcatalog", td); 990 mkdir(tmpdir, 0x700); 991 mr_asprintf(command, "cp -f %s %s", latest_fname, tmpdir); 992 if (run_program_and_log_output(command, 6)) { 993 log_it("Warning - failed to copy %s to backcatalog at %s", 994 latest_fname, tmpdir); 995 } 996 mr_free(command); 997 998 last = g_tapecatalog->entries - 1; 999 if (last <= 0) { 1000 log_it("Too early to start deleting from collection."); 1001 mr_free(tmpdir); 1002 return (0); 1003 } 1004 final_alleged_writeK = g_tapecatalog->el[last].tape_posK; 1005 final_projected_certain_writeK = final_alleged_writeK - bufsize_K; 1006 for (curr = last; curr >= 0; curr--) { 1007 cposK = g_tapecatalog->el[curr].tape_posK; 1008 if (cposK < final_projected_certain_writeK) { 1009 break; 1010 } 1011 } 1012 if (curr < 0) { 1013 log_it("Not far enough into tape to start deleting old archives from collection."); 1014 mr_free(tmpdir); 1015 return (0); 1016 } 1017 1018 for (i = curr - 1; i >= 0 && curr - i < 10; i--) { 1019 mr_asprintf(old_fname, "%s/%s", tmpdir, g_tapecatalog->el[i].fname); 1020 unlink(old_fname); 1021 mr_free(old_fname); 1022 } 1023 mr_free(tmpdir); 1024 return (0); 1025 } 1026 1027 1028 int set_tape_block_size_with_mt(long internal_tape_block_size) 1029 { 1030 char *tmp = NULL; 1031 int res; 1032 1033 if (bkpinfo->media_device == NULL) { 1034 return(1); 1035 } 1036 1037 if (strncmp(bkpinfo->media_device, "/dev/", 5)) { 1038 log_msg(1, "Not using 'mt setblk'. This isn't an actual /dev entry."); 1039 return (0); 1040 } 1041 mr_asprintf(tmp, "mt -f %s setblk %ld", bkpinfo->media_device, internal_tape_block_size); 1042 res = run_program_and_log_output(tmp, 3); 1043 mr_free(tmp); 1044 return (res); 1045 } 1046 1047 1048 /** 1049 * Handle OBDR if we were asked to do so 1050 * @param tapedev The tape device to open for reading. 1051 */ 1052 int skip_obdr(void) 1053 { 1054 char *command = NULL; 1055 int res = 0; 1056 1057 if (bkpinfo->media_device == NULL) { 1058 return(1); 1059 } 1060 1061 log_it("Skipping OBDR headers"); 1062 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device); 1063 res = run_program_and_log_output(command, 1); 1064 paranoid_free(command); 1065 1066 mr_asprintf(command, "mt -f %s fsf 2",bkpinfo->media_device); 1067 res = run_program_and_log_output(command, 1); 1068 paranoid_free(command); 1069 1070 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 1071 return(res); 1072 } 1073 1074 1075 1076 /** 1077 * Open the tape device for input. 1078 * @param bkpinfo The backup information structure. Fields used: 1079 * - @c bkpinfo->media_device 1080 * - @c bkpinfo->tmpdir 1081 * @return 0 for success, nonzero for failure. 1082 * @note This will also work with a cdstream for now, but don't count on this behavior. 1083 */ 1084 int openin_tape() 1085 { 1086 /*@ buffer ***************************************************** */ 1087 char fname[MAX_STR_LEN]; 1088 char *datablock; 1089 char *tmp = NULL; 1090 char *old_pwd = NULL; 1091 char *outfname = NULL; 1092 /*@ int ******************************************************* */ 1093 int i; 1094 int j; 1095 int res = 0; 1096 long length, templong; 1097 size_t k; 1098 int retval = 0; 1099 int ctrl_chr; 1100 1101 /*@ long long ************************************************* */ 1102 long long size; 1103 1104 /*@ pointers ************************************************** */ 1105 FILE *fout; 1106 1107 /*@ end vars *************************************************** */ 1108 1109 g_tapecatalog = mr_malloc(sizeof(struct s_tapecatalog)); 1110 g_tapecatalog->entries = 0; 1111 g_tape_posK = 0; 1112 if (g_tape_stream) { 1113 log_it("FYI - I won't 'openin' the tape. It's already open."); 1114 return (0); 1115 } 1116 1117 // mondoarchive should have configured everything to give the right non-rewinding device 1118 if (bkpinfo->media_device == NULL) { 1119 log_it("Not able to open tape - no tape device found"); 1120 return (1); 1121 } 1122 if (bkpinfo->use_obdr) { 1123 res = skip_obdr(); 1124 if (res != 0) { 1125 log_it("Not able to skip OBDR - Restore will have to be done manually"); 1126 return (1); 1127 } 1128 } else { 1129 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 1130 } 1131 1132 insist_on_this_tape_number(1); 1133 mr_asprintf(outfname, "%s/tmp/all.tar.gz", bkpinfo->tmpdir); 1134 make_hole_for_file(outfname); 1135 1136 log_it("Opening IN tape"); 1137 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'r', bkpinfo->internal_tape_block_size))) { 1138 log_OS_error(g_tape_fifo); 1139 log_to_screen("Cannot openin stream device"); 1140 mr_free(outfname); 1141 return (1); 1142 } 1143 log_to_screen("Reading stream"); 1144 log_it("stream device = '%s'", bkpinfo->media_device); 1145 /* skip data disks */ 1146 open_evalcall_form("Skipping data disks on stream"); 1147 log_to_screen("Skipping data disks on stream"); 1148 if (!(fout = fopen(outfname, "w"))) { 1149 log_OS_error(outfname); 1150 log_to_screen("Cannot openout datadisk all.tar.gz file"); 1151 mr_free(outfname); 1152 return (-1); 1153 } 1154 if (!(datablock = (char *) malloc(256 * 1024))) { 1155 log_to_screen("Unable to malloc 256*1024"); 1156 mr_free(outfname); 1157 finish(1); 1158 } 1159 for (i = 0; i < 32; i++) { 1160 for (j = 0; j < 4; j++) { 1161 for (length = 0, k = 0; length < 256 * 1024; length += k) { 1162 k = fread(datablock + length, 1, 256 * 1024 - length, 1163 g_tape_stream); 1164 } 1165 if (fwrite(datablock, 1, (size_t) length, fout)) { 1166 // FIXME 1167 } 1168 g_tape_posK += length / 1024; 1169 } 1170 if (i > 8) // otherwise, 'buffer' distorts calculations 1171 { 1172 templong = ((i - 8) * 4 + j) * 100 / (128 - 8 * 4); 1173 update_evalcall_form((int) (templong)); 1174 } 1175 } 1176 paranoid_fclose(fout); 1177 paranoid_free(datablock); 1178 1179 /* find initial blocks */ 1180 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 1181 retval += res; 1182 if (ctrl_chr != BLK_START_OF_TAPE) { 1183 wrong_marker(BLK_START_OF_TAPE, ctrl_chr); 1184 } 1185 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 1186 retval += res; 1187 if (ctrl_chr != BLK_START_OF_BACKUP) { 1188 wrong_marker(BLK_START_OF_BACKUP, ctrl_chr); 1189 } 1190 close_evalcall_form(); 1191 log_it("Saved all.tar.gz to '%s'", outfname); 1192 old_pwd = mr_getcwd(); 1193 if (chdir(bkpinfo->tmpdir)) { 1194 // FIXME 1195 } 1196 mr_asprintf(tmp, "tar -zxf %s ./tmp/mondorestore.cfg 2> /dev/null", outfname); 1197 paranoid_system(tmp); 1198 mr_free(tmp); 1199 1200 paranoid_system("cp -f tmp/mondorestore.cfg . 2> /dev/null"); 1201 if (chdir(old_pwd)) { 1202 // FIXME 1203 } 1204 mr_free(old_pwd); 1205 unlink(outfname); 1206 mr_free(outfname); 1207 return (retval); 1208 } 1209 1210 1211 1212 /** 1213 * Open the CD stream for input. 1214 * @param bkpinfo The backup information structure. Passed to openin_tape(). 1215 * @return 0 for success, nonzero for failure. 1216 * @note Equivalent to openin_tape() for now, but don't count on this behavior. 1217 */ 1218 int openin_cdstream() 1219 { 1220 return (openin_tape()); 1221 } 1222 1223 /** 1224 * Return the non-rewinding device when passed the normal one 1225 * @param tapedev The tape device to open for writing. 1226 * @note the caller needs to free the string returned 1227 */ 1228 char *get_non_rewind_dev(char *tapedev) 1229 { 1230 1231 char *ntapedev = NULL; 1232 char *p = NULL; 1233 char *q = NULL; 1234 char *r = NULL; 1235 1236 ntapedev = (char *)mr_malloc(strlen(tapedev)+2*sizeof(char)); 1237 p = strrchr(tapedev,'/'); 1238 if (p == NULL) { 1239 log_it("Didn't find a '/' in %s",tapedev); 1240 return(NULL); 1241 } 1242 1243 /* Copy tapedev content up to the last / */ 1244 q = tapedev; 1245 r = ntapedev; 1246 while (q != p) { 1247 *r = *q; 1248 r++; 1249 q++; 1250 } 1251 /* Copy the '/' */ 1252 *r = *q; 1253 r++; 1254 q++; 1255 /* Adds a 'n' - non-rewinding */ 1256 *r = 'n'; 1257 r++; 1258 /* Copy the rest of tapedev */ 1259 while (*q != '\0') { 1260 *r = *q; 1261 r++; 1262 q++; 1263 } 1264 *r = '\0'; 1265 if (mt_says_tape_exists(ntapedev)) { 1266 log_it("Non-rewinding tape device is %s",ntapedev); 1267 } else { 1268 log_it("Unable to find non-rewinding tape device."); 1269 ntapedev = NULL; 1270 } 1271 return(ntapedev); 1272 } 1273 1274 /** 1275 * Handle OBDR if we were asked to do so 1276 * @param tapedev The tape device to open for writing. 1277 * @return 0 for success, nonzero for failure. 1278 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY 1279 * EXISTING DATA on the tape! 1280 */ 1281 int create_obdr(void) 1282 { 1283 1284 char *command = NULL; 1285 int res = 0; 1286 1287 if (bkpinfo->media_device == NULL) { 1288 return(1); 1289 } 1290 1291 log_it("Creating OBDR headers"); 1292 /* OBDR: First block 10 kB of zero bs = 512 */ 1293 mr_asprintf(command, "mt -f %s compression off",bkpinfo->media_device); 1294 res = run_program_and_log_output(command, 1); 1295 paranoid_free(command); 1296 1297 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device); 1298 res += run_program_and_log_output(command, 1); 1299 paranoid_free(command); 1300 1301 set_tape_block_size_with_mt(512); 1302 1303 mr_asprintf(command, "dd if=/dev/zero of=%s bs=512 count=20",bkpinfo->media_device); 1304 res += run_program_and_log_output(command, 1); 1305 paranoid_free(command); 1306 1307 /* OBDR: then ISO boot image bs = 2048 */ 1308 set_tape_block_size_with_mt(2048); 1309 1310 mr_asprintf(command, "dd if=%s of=%s bs=2048",MINDI_CACHE"/mindi.iso",bkpinfo->media_device); 1311 res += run_program_and_log_output(command, 1); 1312 paranoid_free(command); 1313 1314 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 1315 1316 /* restore compression mode on */ 1317 mr_asprintf(command, "mt -f %s compression on",bkpinfo->media_device); 1318 res = run_program_and_log_output(command, 1); 1319 paranoid_free(command); 1320 1321 return(res); 1322 } 1323 1324 1325 /** 1326 * Start writing to a CD stream. 1327 * @param cddev The CD device to openout via cdrecord. 1328 * @param speed The speed to write at. 1329 * @return 0 for success, nonzero for failure. 1330 * @note This should be called only from backup processes. 1331 */ 1332 int openout_cdstream(char *cddev, int speed) 1333 { 1334 /*@ buffers ***************************************************** */ 1335 char *command = NULL; 1336 1337 /*@ end vars *************************************************** */ 1338 1339 if (cddev == NULL) { 1340 log_to_screen("Failed to openout NULL cddev"); 1341 return (1); 1342 } 1343 /* add 'dummy' if testing */ 1344 mr_asprintf(command, "cdrecord -eject dev=%s speed=%d fs=24m -waiti - >> %s 2>> %s", cddev, speed, MONDO_LOGFILE, MONDO_LOGFILE); 1345 /* initialise the catalog */ 1346 g_current_media_number = 1; 1347 if (!(g_tapecatalog = malloc(sizeof(struct s_tapecatalog)))) { 1348 fatal_error("Cannot alloc mem for tape catalog"); 1349 } 1350 g_tapecatalog->entries = 0; 1351 /* log stuff */ 1352 log_it("Opening OUT cdstream with the command"); 1353 log_it(command); 1354 /* log_it("Let's see what happens, shall we?"); */ 1355 g_tape_stream = popen(command, "w"); 1356 mr_free(command); 1357 1358 if (g_tape_stream) { 1359 return (0); 1360 } else { 1361 log_to_screen("Failed to openout to cdstream (fifo)"); 1362 return (1); 1363 } 1364 } 1365 1366 1367 /** 1368 * Start writing to a tape device for the backup. 1369 * Handle OBDR if we were asked to do so 1370 * @param tapedev The tape device to open for writing. 1371 * @return 0 for success, nonzero for failure. 1372 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY 1373 * EXISTING DATA on the tape! 1374 */ 1375 int openout_tape() { 1376 1377 g_current_media_number = 1; 1378 if (g_tape_stream) { 1379 log_it("FYI - I won't 'openout' the tape. It's already open."); 1380 return (0); 1381 } 1382 if (bkpinfo->media_device == NULL) { 1383 log_it("Unable to openout NULL device"); 1384 return(1); 1385 } 1386 g_tapecatalog = mr_malloc(sizeof(struct s_tapecatalog)); 1387 g_tapecatalog->entries = 0; 1388 g_tape_posK = 0; 1389 1390 if (bkpinfo->use_obdr) { 1391 create_obdr(); 1392 } else { 1393 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 1394 } 1395 log_it("Opening OUT tape"); 1396 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'w', bkpinfo->internal_tape_block_size))) { 1397 log_OS_error(g_tape_fifo); 1398 log_to_screen("Cannot openin stream device"); 1399 return (1); 1400 } 1401 return (0); 1351 1402 } 1352 1403 … … 1514 1565 1515 1566 /** 1516 * Read a header block from the currently opened stream (CD or tape). 1517 * This block indicates the length of the following file (if it's file-related) 1518 * the filename (if it's file-related), and the block type. 1519 * @param plen Where to put the length of the file. Valid only for file-related header blocks. 1520 * @param filename Where to put the name of the file. Valid only for file-related header blocks. 1521 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...) 1522 * @return 0 for success, nonzero for failure. 1523 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker(). 1567 * Copy a file from the currently opened stream (CD or tape) to the stream indicated 1568 * by @p fout. 1569 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used. 1570 * @param fout The stream to write the file to. 1571 * @param size The size of the file in bytes. 1572 * @return 0 for success, nonzero for failure. 1524 1573 */ 1525 1574 int 1526 read_header_block_from_stream(long long *plen, char *filename, 1527 int *pcontrol_char) 1528 { 1529 1530 /*@ buffers ***************************************************** */ 1531 char *tempblock; 1532 char *tmp = NULL; 1533 1534 /*@ int ********************************************************* */ 1535 int i, retval; 1575 read_file_from_stream_to_stream(FILE * fout, long long size) 1576 { 1577 1578 /*@ int ******************************************************** */ 1579 int res; 1536 1580 1537 1581 /*@ end vars *************************************************** */ 1538 1582 1539 tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE); 1540 1541 for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) { 1542 tempblock[i] = 0; 1543 } 1544 while (!(*pcontrol_char = tempblock[7000])) { 1545 g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024; 1546 } 1547 memcpy((char *) plen, tempblock + 7001, sizeof(long long)); 1548 if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) { 1549 log_it("Bad header block at %ld K", (long) g_tape_posK); 1550 } 1551 strcpy(filename, tempblock + 1000); 1552 if (*pcontrol_char == BLK_ABORTED_BACKUP) { 1553 log_to_screen("I can't verify an aborted backup."); 1554 retval = 1; 1555 } else { 1556 retval = 0; 1557 } 1558 for (i = 1000; i < 1020; i++) { 1559 if (tempblock[i] < 32 || tempblock[i] > 126) { 1560 tempblock[i] = ' '; 1561 } 1562 } 1563 tempblock[i] = '\0'; 1564 tmp = marker_to_string(*pcontrol_char); 1565 log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10); 1566 mr_free(tmp); 1567 paranoid_free(tempblock); 1568 return (retval); 1569 } 1570 1583 res = read_file_from_stream_FULL(NULL, fout, size); 1584 /* fflush(g_tape_stream); 1585 fflush(fout);*/ 1586 return (res); 1587 } 1571 1588 1572 1589 … … 1718 1735 1719 1736 1720 1721 1722 1723 1724 /**1725 * Log (to screen) an erroneous marker, along with what it should have been.1726 * @param should_be What we were expecting.1727 * @param it_is What we got.1728 */1729 void wrong_marker(int should_be, int it_is)1730 {1731 char *tmp1 = NULL;1732 char *tmp2 = NULL;1733 tmp1 = marker_to_string(should_be);1734 tmp2 = marker_to_string(it_is);1735 log_to_screen("Wrong marker! (Should be %s, is actually %s)", tmp1, tmp2);1736 mr_free(tmp1);1737 mr_free(tmp2);1738 }1739 1740 1737 /* @} - end of streamGroup */ -
branches/3.3/mondo/src/common/libmondo-string.c
r3874 r3878 965 965 966 966 967 /** 968 * Get a string form of @p type_of_bkp. 969 * @param type_of_bkp The backup type to stringify. 970 * @return The stringification of @p type_of_bkp. 971 * @note The returned string points to static storage that will be overwritten with each call. 972 */ 973 char *media_descriptor_string(t_bkptype type_of_bkp) { 974 975 char *type_of_backup = NULL; 976 977 switch (type_of_bkp) { 978 case dvd: 979 mr_asprintf(type_of_backup, "DVD"); 980 break; 981 case cdr: 982 mr_asprintf(type_of_backup, "CDR"); 983 break; 984 case tape: 985 mr_asprintf(type_of_backup, "tape"); 986 break; 987 case cdstream: 988 mr_asprintf(type_of_backup, "CDR"); 989 break; 990 case udev: 991 mr_asprintf(type_of_backup, "udev"); 992 break; 993 case iso: 994 mr_asprintf(type_of_backup, "ISO"); 995 break; 996 case netfs: 997 mr_asprintf(type_of_backup, "%s", bkpinfo->netfs_proto); 998 break; 999 case usb: 1000 mr_asprintf(type_of_backup, "USB"); 1001 break; 1002 default: 1003 mr_asprintf(type_of_backup, "ISO"); 1004 } 1005 return (type_of_backup); 1006 } 967 1007 968 1008 … … 1023 1063 1024 1064 1025 /**1026 * Get a string form of @p type_of_bkp.1027 * @param type_of_bkp The backup type to stringify.1028 * @return The stringification of @p type_of_bkp.1029 * @note The returned string points to static storage that will be overwritten with each call.1030 */1031 char *media_descriptor_string(t_bkptype type_of_bkp) {1032 1033 char *type_of_backup = NULL;1034 1035 switch (type_of_bkp) {1036 case dvd:1037 mr_asprintf(type_of_backup, "DVD");1038 break;1039 case cdr:1040 mr_asprintf(type_of_backup, "CDR");1041 break;1042 case tape:1043 mr_asprintf(type_of_backup, "tape");1044 break;1045 case cdstream:1046 mr_asprintf(type_of_backup, "CDR");1047 break;1048 case udev:1049 mr_asprintf(type_of_backup, "udev");1050 break;1051 case iso:1052 mr_asprintf(type_of_backup, "ISO");1053 break;1054 case netfs:1055 mr_asprintf(type_of_backup, "%s", bkpinfo->netfs_proto);1056 break;1057 case usb:1058 mr_asprintf(type_of_backup, "USB");1059 break;1060 default:1061 mr_asprintf(type_of_backup, "ISO");1062 }1063 return (type_of_backup);1064 } -
branches/3.3/mondo/src/common/libmondo-verify.c
r3877 r3878 122 122 mr_free(command); 123 123 return (afio_diffs); 124 } 125 126 127 128 129 130 /** 131 * Verify one afioball from the CD. 132 * You should be changed to the root directory (/) for this to work. 133 * @param bkpinfo The backup information structure. Fields used: 134 * - @c bkpinfo->use_lzo 135 * - @c bkpinfo->tmpdir 136 * - @c bkpinfo->zip_exe 137 * - @c bkpinfo->zip_suffix 138 * @param tarball_fname The filename of the afioball to verify. 139 * @return 0, always. 140 */ 141 int verify_a_tarball(char *tarball_fname) 142 { 143 /*@ buffers ********************************************************* */ 144 char *command = NULL; 145 char *outlog = NULL; 146 char *tmp = NULL; 147 148 /*@ pointers ******************************************************* */ 149 FILE *pin; 150 151 /*@ long *********************************************************** */ 152 long diffs = 0; 153 154 assert(bkpinfo != NULL); 155 assert_string_is_neither_NULL_nor_zerolength(tarball_fname); 156 157 log_it("Verifying fileset '%s'", tarball_fname); 158 mr_asprintf(outlog, "%s/afio.log", bkpinfo->tmpdir); 159 /* if programmer forgot to say which compression thingy to use then find out */ 160 if (strstr(tarball_fname, ".lzo") && strcmp(bkpinfo->zip_suffix, "lzo")) { 161 log_msg(2, "OK, I'm going to start using lzop."); 162 mr_free(bkpinfo->zip_exe); 163 mr_free(bkpinfo->zip_suffix); 164 mr_asprintf(bkpinfo->zip_exe, "%s", "lzop"); 165 mr_asprintf(bkpinfo->zip_suffix, "%s", "lzo"); 166 bkpinfo->use_lzo = TRUE; 167 bkpinfo->use_gzip = FALSE; 168 bkpinfo->use_lzma = FALSE; 169 } 170 if (strstr(tarball_fname, ".gz") && strcmp(bkpinfo->zip_suffix, "gz")) { 171 log_msg(2, "OK, I'm going to start using gzip."); 172 mr_free(bkpinfo->zip_exe); 173 mr_free(bkpinfo->zip_suffix); 174 mr_asprintf(bkpinfo->zip_exe, "%s", "gzip"); 175 mr_asprintf(bkpinfo->zip_suffix, "%s", "gz"); 176 bkpinfo->use_lzo = FALSE; 177 bkpinfo->use_gzip = TRUE; 178 bkpinfo->use_lzma = FALSE; 179 } 180 if (strstr(tarball_fname, ".bz2") && strcmp(bkpinfo->zip_suffix, "bz2")) { 181 log_msg(2, "OK, I'm going to start using bzip2."); 182 mr_free(bkpinfo->zip_exe); 183 mr_free(bkpinfo->zip_suffix); 184 mr_asprintf(bkpinfo->zip_exe, "%s", "bzip2"); 185 mr_asprintf(bkpinfo->zip_suffix, "%s", "bz2"); 186 bkpinfo->use_lzo = FALSE; 187 bkpinfo->use_gzip = FALSE; 188 bkpinfo->use_lzma = FALSE; 189 } 190 if (strstr(tarball_fname, ".xz") && strcmp(bkpinfo->zip_suffix, "xz")) { 191 log_msg(2, "OK, I'm going to start using lzma."); 192 mr_free(bkpinfo->zip_exe); 193 mr_free(bkpinfo->zip_suffix); 194 mr_asprintf(bkpinfo->zip_exe, "%s", "xz"); 195 mr_asprintf(bkpinfo->zip_suffix, "%s", "xz"); 196 bkpinfo->use_lzo = FALSE; 197 bkpinfo->use_gzip = FALSE; 198 bkpinfo->use_lzma = TRUE; 199 } 200 // As suffix is used even when no compression make it non-NULL 201 if (bkpinfo->zip_suffix == NULL) { 202 mr_asprintf(bkpinfo->zip_suffix, "%s", ""); 203 } 204 unlink(outlog); 205 if (strstr(tarball_fname, ".star")) { 206 bkpinfo->use_star = TRUE; 207 if (strstr(tarball_fname, ".bz2")) 208 mr_asprintf(command, "star -sparse -diff diffopts=mode,size,data file=%s %s >> %s 2>> %s", tarball_fname, (strstr(tarball_fname, ".bz2")) ? "-bz" : " ", outlog, outlog); 209 } else { 210 bkpinfo->use_star = FALSE; 211 /* Here we suppose that there is always a compression program called */ 212 if (bkpinfo->zip_exe) { 213 mr_asprintf(command, "afio -r -P %s -Z %s >> %s 2>> %s", bkpinfo->zip_exe, tarball_fname, outlog, outlog); 214 } else { 215 mr_asprintf(command, "afio -r -Z %s >> %s 2>> %s", tarball_fname, outlog, outlog); 216 } 217 } 218 log_msg(6, "command=%s", command); 219 paranoid_system(command); 220 mr_free(command); 221 222 if (length_of_file(outlog) < 10) { 223 mr_asprintf(command, "cat %s >> %s", outlog, MONDO_LOGFILE); 224 } else { 225 mr_asprintf(command, "cut -d: -f%d %s | sort -u", (bkpinfo->use_star) ? 1 : 2, outlog); 226 pin = popen(command, "r"); 227 if (pin) { 228 for (mr_getline(tmp, pin); !feof(pin); mr_getline(tmp, pin)) { 229 if (bkpinfo->use_star) { 230 if (!strstr(tmp, "diffopts=")) { 231 while (strlen(tmp) > 0 && tmp[strlen(tmp) - 1] < 32) { 232 tmp[strlen(tmp) - 1] = '\0'; 233 } 234 if (strchr(tmp, '/')) { 235 if (!diffs) { 236 log_msg(0, "'%s' - differences found", tarball_fname); 237 } 238 log_msg(0, "star: /%s", strip_afio_output_line(tmp)); 239 diffs++; 240 } 241 } 242 } else { 243 if (!diffs) { 244 log_msg(0, "'%s' - differences found", tarball_fname); 245 } 246 log_msg(0, "afio: /%s", strip_afio_output_line(tmp)); 247 diffs++; 248 } 249 mr_free(tmp); 250 } 251 mr_free(tmp); 252 paranoid_pclose(pin); 253 } else { 254 log_OS_error(command); 255 } 256 } 257 mr_free(command); 258 mr_free(outlog); 259 return (0); 260 } 261 262 263 264 265 266 /** 267 * Verify one afioball from the CD. 268 * Checks for existence (calls fatal_error() if it does not exist) and 269 * then calls verify_an_afioball(). 270 * @param bkpinfo The backup information structure. Passed to verify_an_afioball(). 271 * @param tarball_fname The filename of the afioball to verify. 272 * @return The return value of verify_an_afioball(). 273 * @see verify_an_afioball 274 */ 275 int 276 verify_an_afioball_from_CD(char *tarball_fname) 277 { 278 279 /*@ int ************************************************************* */ 280 int res = 0; 281 282 assert_string_is_neither_NULL_nor_zerolength(tarball_fname); 283 284 log_msg(1, "Verifying %s", tarball_fname); 285 if (!does_file_exist(tarball_fname)) { 286 fatal_error("Cannot verify nonexistent afioball"); 287 } 288 res = verify_a_tarball(tarball_fname); 289 return (res); 290 } 291 292 293 /** 294 * Verify one afioball from the opened tape/CD stream. 295 * Copies the file from tape to tmpdir and then calls verify_an_afioball(). 296 * @param bkpinfo The backup information structure. Passed to verify_an_afioball(). 297 * @param orig_fname The original filename of the afioball to verify. 298 * @param size The size of the afioball to verify. 299 * @return The return value of verify_an_afioball(). 300 * @see verify_an_afioball 301 */ 302 int 303 verify_an_afioball_from_stream(char *orig_fname, long long size) 304 { 305 306 /*@ int ************************************************************** */ 307 int retval = 0; 308 int res = 0; 309 310 /*@ buffers ********************************************************** */ 311 char *tmp = NULL; 312 char *tarball_fname = NULL; 313 314 /*@ pointers ********************************************************* */ 315 char *p; 316 317 assert(bkpinfo != NULL); 318 assert_string_is_neither_NULL_nor_zerolength(orig_fname); 319 320 p = strrchr(orig_fname, '/'); 321 if (!p) { 322 p = orig_fname; 323 } else { 324 p++; 325 } 326 mr_asprintf(tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir); 327 paranoid_system(tmp); 328 mr_free(tmp); 329 330 mr_asprintf(tarball_fname, "%s/tmpfs/temporary-%s", bkpinfo->tmpdir, p); 331 read_file_from_stream_to_file(tarball_fname, size); 332 res = verify_a_tarball(tarball_fname); 333 if (res) { 334 log_msg(0, "Afioball '%s' no longer matches your live filesystem", p); 335 retval++; 336 } 337 unlink(tarball_fname); 338 mr_free(tarball_fname); 339 return (retval); 340 } 341 342 343 /** 344 * Verify one biggiefile form the opened tape/CD stream. 345 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir is the only field used. 346 * @param biggie_fname The filename of the biggiefile to verify. 347 * @param size The size in bytes of said biggiefile. 348 * @return 0 for success (even if the file doesn't match); nonzero for a tape error. 349 */ 350 int 351 verify_a_biggiefile_from_stream(char *biggie_fname, long long size) 352 { 353 354 /*@ int ************************************************************* */ 355 int retval = 0; 356 int res = 0; 357 int current_slice_number = 0; 358 int ctrl_chr = '\0'; 359 360 /*@ char ************************************************************ */ 361 char *test_file = NULL; 362 char *biggie_cksum = NULL; 363 char *orig_cksum = NULL; 364 char *tmp = NULL; 365 char *slice_fnam = NULL; 366 367 /*@ pointers ******************************************************** */ 368 char *p; 369 370 /*@ long long ******************************************************* */ 371 long long slice_siz; 372 373 malloc_string(slice_fnam); 374 assert(bkpinfo != NULL); 375 assert_string_is_neither_NULL_nor_zerolength(biggie_fname); 376 377 p = strrchr(biggie_fname, '/'); 378 if (!p) { 379 p = biggie_fname; 380 } else { 381 p++; 382 } 383 mr_asprintf(test_file, "%s/temporary-%s", bkpinfo->tmpdir, p); 384 for (res = 385 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr); 386 ctrl_chr != BLK_STOP_A_BIGGIE; 387 res = 388 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr)) { 389 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) { 390 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr); 391 } 392 res = read_file_from_stream_to_file(test_file, slice_siz); 393 unlink(test_file); 394 res = 395 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr); 396 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) { 397 log_msg(2, "test_file = %s", test_file); 398 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr); 399 } 400 current_slice_number++; 401 retval += res; 402 } 403 mr_asprintf(biggie_cksum, "%s", slice_fnam); 404 if (biggie_cksum[0] != '\0') { 405 mr_asprintf(orig_cksum, "%s", calc_checksum_of_file(biggie_fname)); 406 if (strcmp(biggie_cksum, orig_cksum)) { 407 log_msg(2, "orig cksum=%s; curr cksum=%s", biggie_cksum, orig_cksum); 408 log_to_screen("%s has changed on live filesystem", biggie_fname); 409 410 mr_asprintf(tmp, "echo \"%s\" >> %s/biggies.changed", biggie_fname, bkpinfo->tmpdir); 411 paranoid_system(tmp); 412 mr_free(tmp); 413 } 414 mr_free(orig_cksum); 415 } 416 mr_free(biggie_cksum); 417 mr_free(test_file); 418 paranoid_free(slice_fnam); 419 return (retval); 420 } 421 422 423 /** 424 * Verify all afioballs from the opened tape/CD stream. 425 * @param bkpinfo The backup information structure. Fields used: 426 * - @c bkpinfo->tmpdir 427 * 428 * @return 0 for success (even if there are differences); nonzero for a tape error. 429 */ 430 int verify_afioballs_from_stream() 431 { 432 /*@ int ********************************************************** */ 433 int retval = 0; 434 int res = 0; 435 long current_afioball_number = 0; 436 int ctrl_chr = 0; 437 int total_afioballs = 0; 438 439 /*@ buffers ***************************************************** */ 440 char *tmp = NULL; 441 char *fname; 442 char *curr_xattr_list_fname; 443 char *curr_acl_list_fname; 444 445 /*@ long long *************************************************** */ 446 long long size = 0; 447 448 assert(bkpinfo != NULL); 449 malloc_string(fname); 450 malloc_string(curr_xattr_list_fname); 451 malloc_string(curr_acl_list_fname); 452 453 if (g_getfattr) { 454 sprintf(curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ, 455 bkpinfo->tmpdir); 456 } 457 if (g_getfacl) { 458 sprintf(curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ, 459 bkpinfo->tmpdir); 460 } 461 log_to_screen("Verifying regular archives on tape"); 462 total_afioballs = get_last_filelist_number() + 1; 463 open_progress_form("Verifying filesystem", 464 "I am verifying archives against your live filesystem now.", 465 "Please wait. This may take a couple of hours.", "", 466 total_afioballs); 467 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 468 if (ctrl_chr != BLK_START_AFIOBALLS) { 469 log_it("YOU SHOULD NOT GET HERE"); 470 log_it("Grabbing the EXAT files"); 471 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) { 472 res = read_EXAT_files_from_tape(&size, fname, &ctrl_chr, 473 curr_xattr_list_fname, 474 curr_acl_list_fname); 475 } 476 } 477 if (ctrl_chr != BLK_START_AFIOBALLS) { 478 wrong_marker(BLK_START_AFIOBALLS, ctrl_chr); 479 } 480 481 for (res = read_header_block_from_stream(&size, fname, &ctrl_chr); 482 ctrl_chr != BLK_STOP_AFIOBALLS; 483 res = read_header_block_from_stream(&size, fname, &ctrl_chr)) { 484 if (g_getfattr) { 485 sprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, 486 bkpinfo->tmpdir, current_afioball_number); 487 } 488 if (g_getfacl) { 489 sprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, 490 bkpinfo->tmpdir, current_afioball_number); 491 } 492 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) { 493 log_it("Reading EXAT files from tape"); 494 res = read_EXAT_files_from_tape(&size, fname, &ctrl_chr, 495 curr_xattr_list_fname, 496 curr_acl_list_fname); 497 } 498 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) { 499 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr); 500 } 501 mr_asprintf(tmp, "Verifying fileset #%ld", current_afioball_number); 502 update_progress_form(tmp); 503 mr_free(tmp); 504 505 res = verify_an_afioball_from_stream(fname, size); 506 if (res) { 507 log_to_screen("Afioball %ld differs from live filesystem", current_afioball_number); 508 } 509 retval += res; 510 current_afioball_number++; 511 g_current_progress++; 512 res = read_header_block_from_stream(&size, fname, &ctrl_chr); 513 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) { 514 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr); 515 } 516 } 517 log_msg(1, "All done with afioballs"); 518 close_progress_form(); 519 paranoid_free(fname); 520 paranoid_free(curr_xattr_list_fname); 521 paranoid_free(curr_acl_list_fname); 522 return (retval); 523 } 524 525 /** 526 * Verify all biggiefiles on the opened CD/tape stream. 527 * @param bkpinfo The backup information structure. Fields used: 528 * - @c bkpinfo->restore_path 529 * - @c bkpinfo->tmpdir 530 * 531 * @return 0 for success (even if there are differences); nonzero for a tape error. 532 */ 533 int verify_biggiefiles_from_stream() 534 { 535 536 /*@ int ************************************************************ */ 537 int retval = 0; 538 int res = 0; 539 int ctrl_chr = 0; 540 541 /*@ long *********************************************************** */ 542 long noof_biggiefiles = 0; 543 long current_biggiefile_number = 0; 544 545 /*@ buffers ******************************************************** */ 546 char *orig_fname; 547 char *logical_fname = NULL; 548 char *comment = NULL; 549 char *curr_xattr_list_fname = NULL; 550 char *curr_acl_list_fname = NULL; 551 /*@ pointers ******************************************************* */ 552 char *p; 553 554 /*@ long long size ************************************************* */ 555 long long size = 0; 556 557 assert(bkpinfo != NULL); 558 malloc_string(orig_fname); 559 malloc_string(curr_xattr_list_fname); 560 malloc_string(curr_acl_list_fname); 561 562 if (g_getfattr) { 563 sprintf(curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ, 564 bkpinfo->tmpdir); 565 } 566 if (g_getfacl) { 567 sprintf(curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ, 568 bkpinfo->tmpdir); 569 } 570 mr_asprintf(comment, "Verifying all bigfiles."); 571 log_to_screen(comment); 572 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr); 573 if (ctrl_chr != BLK_START_BIGGIEFILES) { 574 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) { 575 log_it("Grabbing the EXAT biggiefiles"); 576 res = read_EXAT_files_from_tape(&size, orig_fname, 577 &ctrl_chr, curr_xattr_list_fname, 578 curr_acl_list_fname); 579 } 580 } 581 if (ctrl_chr != BLK_START_BIGGIEFILES) { 582 wrong_marker(BLK_START_BIGGIEFILES, ctrl_chr); 583 } 584 noof_biggiefiles = (long) size; 585 log_msg(1, "noof_biggiefiles = %ld", noof_biggiefiles); 586 open_progress_form("Verifying big files", comment, 587 "Please wait. This may take some time.", "", 588 noof_biggiefiles); 589 mr_free(comment); 590 591 for (res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr); 592 ctrl_chr != BLK_STOP_BIGGIEFILES; 593 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr)) 594 { 595 if (ctrl_chr != BLK_START_A_NORMBIGGIE 596 && ctrl_chr != BLK_START_A_PIHBIGGIE) { 597 wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr); 598 } 599 p = strrchr(orig_fname, '/'); 600 if (!p) { 601 p = orig_fname; 602 } else { 603 p++; 604 } 605 mr_asprintf(comment, "Verifying bigfile #%ld (%ld K)", current_biggiefile_number, (long) size >> 10); 606 update_progress_form(comment); 607 mr_free(comment); 608 609 if (bkpinfo->restore_path != NULL) { 610 mr_asprintf(logical_fname, "%s/%s", bkpinfo->restore_path, orig_fname); 611 res = verify_a_biggiefile_from_stream(logical_fname, size); 612 mr_free(logical_fname); 613 retval += res; 614 } else { 615 log_it("Unable to verify bigfile as restore_path is NULL"); 616 } 617 618 current_biggiefile_number++; 619 g_current_progress++; 620 } 621 close_progress_form(); 622 paranoid_free(orig_fname); 623 paranoid_free(curr_xattr_list_fname); 624 paranoid_free(curr_acl_list_fname); 625 return (retval); 124 626 } 125 627 … … 391 893 392 894 393 394 395 396 /**397 * Verify one afioball from the CD.398 * You should be changed to the root directory (/) for this to work.399 * @param bkpinfo The backup information structure. Fields used:400 * - @c bkpinfo->use_lzo401 * - @c bkpinfo->tmpdir402 * - @c bkpinfo->zip_exe403 * - @c bkpinfo->zip_suffix404 * @param tarball_fname The filename of the afioball to verify.405 * @return 0, always.406 */407 int verify_a_tarball(char *tarball_fname)408 {409 /*@ buffers ********************************************************* */410 char *command = NULL;411 char *outlog = NULL;412 char *tmp = NULL;413 414 /*@ pointers ******************************************************* */415 FILE *pin;416 417 /*@ long *********************************************************** */418 long diffs = 0;419 420 assert(bkpinfo != NULL);421 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);422 423 log_it("Verifying fileset '%s'", tarball_fname);424 mr_asprintf(outlog, "%s/afio.log", bkpinfo->tmpdir);425 /* if programmer forgot to say which compression thingy to use then find out */426 if (strstr(tarball_fname, ".lzo") && strcmp(bkpinfo->zip_suffix, "lzo")) {427 log_msg(2, "OK, I'm going to start using lzop.");428 mr_free(bkpinfo->zip_exe);429 mr_free(bkpinfo->zip_suffix);430 mr_asprintf(bkpinfo->zip_exe, "%s", "lzop");431 mr_asprintf(bkpinfo->zip_suffix, "%s", "lzo");432 bkpinfo->use_lzo = TRUE;433 bkpinfo->use_gzip = FALSE;434 bkpinfo->use_lzma = FALSE;435 }436 if (strstr(tarball_fname, ".gz") && strcmp(bkpinfo->zip_suffix, "gz")) {437 log_msg(2, "OK, I'm going to start using gzip.");438 mr_free(bkpinfo->zip_exe);439 mr_free(bkpinfo->zip_suffix);440 mr_asprintf(bkpinfo->zip_exe, "%s", "gzip");441 mr_asprintf(bkpinfo->zip_suffix, "%s", "gz");442 bkpinfo->use_lzo = FALSE;443 bkpinfo->use_gzip = TRUE;444 bkpinfo->use_lzma = FALSE;445 }446 if (strstr(tarball_fname, ".bz2") && strcmp(bkpinfo->zip_suffix, "bz2")) {447 log_msg(2, "OK, I'm going to start using bzip2.");448 mr_free(bkpinfo->zip_exe);449 mr_free(bkpinfo->zip_suffix);450 mr_asprintf(bkpinfo->zip_exe, "%s", "bzip2");451 mr_asprintf(bkpinfo->zip_suffix, "%s", "bz2");452 bkpinfo->use_lzo = FALSE;453 bkpinfo->use_gzip = FALSE;454 bkpinfo->use_lzma = FALSE;455 }456 if (strstr(tarball_fname, ".xz") && strcmp(bkpinfo->zip_suffix, "xz")) {457 log_msg(2, "OK, I'm going to start using lzma.");458 mr_free(bkpinfo->zip_exe);459 mr_free(bkpinfo->zip_suffix);460 mr_asprintf(bkpinfo->zip_exe, "%s", "xz");461 mr_asprintf(bkpinfo->zip_suffix, "%s", "xz");462 bkpinfo->use_lzo = FALSE;463 bkpinfo->use_gzip = FALSE;464 bkpinfo->use_lzma = TRUE;465 }466 // As suffix is used even when no compression make it non-NULL467 if (bkpinfo->zip_suffix == NULL) {468 mr_asprintf(bkpinfo->zip_suffix, "%s", "");469 }470 unlink(outlog);471 if (strstr(tarball_fname, ".star")) {472 bkpinfo->use_star = TRUE;473 if (strstr(tarball_fname, ".bz2"))474 mr_asprintf(command, "star -sparse -diff diffopts=mode,size,data file=%s %s >> %s 2>> %s", tarball_fname, (strstr(tarball_fname, ".bz2")) ? "-bz" : " ", outlog, outlog);475 } else {476 bkpinfo->use_star = FALSE;477 /* Here we suppose that there is always a compression program called */478 if (bkpinfo->zip_exe) {479 mr_asprintf(command, "afio -r -P %s -Z %s >> %s 2>> %s", bkpinfo->zip_exe, tarball_fname, outlog, outlog);480 } else {481 mr_asprintf(command, "afio -r -Z %s >> %s 2>> %s", tarball_fname, outlog, outlog);482 }483 }484 log_msg(6, "command=%s", command);485 paranoid_system(command);486 mr_free(command);487 488 if (length_of_file(outlog) < 10) {489 mr_asprintf(command, "cat %s >> %s", outlog, MONDO_LOGFILE);490 } else {491 mr_asprintf(command, "cut -d: -f%d %s | sort -u", (bkpinfo->use_star) ? 1 : 2, outlog);492 pin = popen(command, "r");493 if (pin) {494 for (mr_getline(tmp, pin); !feof(pin); mr_getline(tmp, pin)) {495 if (bkpinfo->use_star) {496 if (!strstr(tmp, "diffopts=")) {497 while (strlen(tmp) > 0 && tmp[strlen(tmp) - 1] < 32) {498 tmp[strlen(tmp) - 1] = '\0';499 }500 if (strchr(tmp, '/')) {501 if (!diffs) {502 log_msg(0, "'%s' - differences found", tarball_fname);503 }504 log_msg(0, "star: /%s", strip_afio_output_line(tmp));505 diffs++;506 }507 }508 } else {509 if (!diffs) {510 log_msg(0, "'%s' - differences found", tarball_fname);511 }512 log_msg(0, "afio: /%s", strip_afio_output_line(tmp));513 diffs++;514 }515 mr_free(tmp);516 }517 mr_free(tmp);518 paranoid_pclose(pin);519 } else {520 log_OS_error(command);521 }522 }523 mr_free(command);524 mr_free(outlog);525 return (0);526 }527 528 529 530 531 532 533 /**534 * Verify one afioball from the CD.535 * Checks for existence (calls fatal_error() if it does not exist) and536 * then calls verify_an_afioball().537 * @param bkpinfo The backup information structure. Passed to verify_an_afioball().538 * @param tarball_fname The filename of the afioball to verify.539 * @return The return value of verify_an_afioball().540 * @see verify_an_afioball541 */542 int543 verify_an_afioball_from_CD(char *tarball_fname)544 {545 546 /*@ int ************************************************************* */547 int res = 0;548 549 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);550 551 log_msg(1, "Verifying %s", tarball_fname);552 if (!does_file_exist(tarball_fname)) {553 fatal_error("Cannot verify nonexistent afioball");554 }555 res = verify_a_tarball(tarball_fname);556 return (res);557 }558 559 560 /**561 * Verify one afioball from the opened tape/CD stream.562 * Copies the file from tape to tmpdir and then calls verify_an_afioball().563 * @param bkpinfo The backup information structure. Passed to verify_an_afioball().564 * @param orig_fname The original filename of the afioball to verify.565 * @param size The size of the afioball to verify.566 * @return The return value of verify_an_afioball().567 * @see verify_an_afioball568 */569 int570 verify_an_afioball_from_stream(char *orig_fname, long long size)571 {572 573 /*@ int ************************************************************** */574 int retval = 0;575 int res = 0;576 577 /*@ buffers ********************************************************** */578 char *tmp = NULL;579 char *tarball_fname = NULL;580 581 /*@ pointers ********************************************************* */582 char *p;583 584 assert(bkpinfo != NULL);585 assert_string_is_neither_NULL_nor_zerolength(orig_fname);586 587 p = strrchr(orig_fname, '/');588 if (!p) {589 p = orig_fname;590 } else {591 p++;592 }593 mr_asprintf(tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);594 paranoid_system(tmp);595 mr_free(tmp);596 597 mr_asprintf(tarball_fname, "%s/tmpfs/temporary-%s", bkpinfo->tmpdir, p);598 read_file_from_stream_to_file(tarball_fname, size);599 res = verify_a_tarball(tarball_fname);600 if (res) {601 log_msg(0, "Afioball '%s' no longer matches your live filesystem", p);602 retval++;603 }604 unlink(tarball_fname);605 mr_free(tarball_fname);606 return (retval);607 }608 609 610 /**611 * Verify one biggiefile form the opened tape/CD stream.612 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir is the only field used.613 * @param biggie_fname The filename of the biggiefile to verify.614 * @param size The size in bytes of said biggiefile.615 * @return 0 for success (even if the file doesn't match); nonzero for a tape error.616 */617 int618 verify_a_biggiefile_from_stream(char *biggie_fname, long long size)619 {620 621 /*@ int ************************************************************* */622 int retval = 0;623 int res = 0;624 int current_slice_number = 0;625 int ctrl_chr = '\0';626 627 /*@ char ************************************************************ */628 char *test_file = NULL;629 char *biggie_cksum = NULL;630 char *orig_cksum = NULL;631 char *tmp = NULL;632 char *slice_fnam = NULL;633 634 /*@ pointers ******************************************************** */635 char *p;636 637 /*@ long long ******************************************************* */638 long long slice_siz;639 640 malloc_string(slice_fnam);641 assert(bkpinfo != NULL);642 assert_string_is_neither_NULL_nor_zerolength(biggie_fname);643 644 p = strrchr(biggie_fname, '/');645 if (!p) {646 p = biggie_fname;647 } else {648 p++;649 }650 mr_asprintf(test_file, "%s/temporary-%s", bkpinfo->tmpdir, p);651 for (res =652 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr);653 ctrl_chr != BLK_STOP_A_BIGGIE;654 res =655 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr)) {656 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {657 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);658 }659 res = read_file_from_stream_to_file(test_file, slice_siz);660 unlink(test_file);661 res =662 read_header_block_from_stream(&slice_siz, slice_fnam, &ctrl_chr);663 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {664 log_msg(2, "test_file = %s", test_file);665 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);666 }667 current_slice_number++;668 retval += res;669 }670 mr_asprintf(biggie_cksum, "%s", slice_fnam);671 if (biggie_cksum[0] != '\0') {672 mr_asprintf(orig_cksum, "%s", calc_checksum_of_file(biggie_fname));673 if (strcmp(biggie_cksum, orig_cksum)) {674 log_msg(2, "orig cksum=%s; curr cksum=%s", biggie_cksum, orig_cksum);675 log_to_screen("%s has changed on live filesystem", biggie_fname);676 677 mr_asprintf(tmp, "echo \"%s\" >> %s/biggies.changed", biggie_fname, bkpinfo->tmpdir);678 paranoid_system(tmp);679 mr_free(tmp);680 }681 mr_free(orig_cksum);682 }683 mr_free(biggie_cksum);684 mr_free(test_file);685 paranoid_free(slice_fnam);686 return (retval);687 }688 689 690 /**691 * Verify all afioballs from the opened tape/CD stream.692 * @param bkpinfo The backup information structure. Fields used:693 * - @c bkpinfo->tmpdir694 *695 * @return 0 for success (even if there are differences); nonzero for a tape error.696 */697 int verify_afioballs_from_stream()698 {699 /*@ int ********************************************************** */700 int retval = 0;701 int res = 0;702 long current_afioball_number = 0;703 int ctrl_chr = 0;704 int total_afioballs = 0;705 706 /*@ buffers ***************************************************** */707 char *tmp = NULL;708 char *fname;709 char *curr_xattr_list_fname;710 char *curr_acl_list_fname;711 712 /*@ long long *************************************************** */713 long long size = 0;714 715 assert(bkpinfo != NULL);716 malloc_string(fname);717 malloc_string(curr_xattr_list_fname);718 malloc_string(curr_acl_list_fname);719 720 if (g_getfattr) {721 sprintf(curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ,722 bkpinfo->tmpdir);723 }724 if (g_getfacl) {725 sprintf(curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ,726 bkpinfo->tmpdir);727 }728 log_to_screen("Verifying regular archives on tape");729 total_afioballs = get_last_filelist_number() + 1;730 open_progress_form("Verifying filesystem",731 "I am verifying archives against your live filesystem now.",732 "Please wait. This may take a couple of hours.", "",733 total_afioballs);734 res = read_header_block_from_stream(&size, fname, &ctrl_chr);735 if (ctrl_chr != BLK_START_AFIOBALLS) {736 log_it("YOU SHOULD NOT GET HERE");737 log_it("Grabbing the EXAT files");738 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {739 res = read_EXAT_files_from_tape(&size, fname, &ctrl_chr,740 curr_xattr_list_fname,741 curr_acl_list_fname);742 }743 }744 if (ctrl_chr != BLK_START_AFIOBALLS) {745 wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);746 }747 748 for (res = read_header_block_from_stream(&size, fname, &ctrl_chr);749 ctrl_chr != BLK_STOP_AFIOBALLS;750 res = read_header_block_from_stream(&size, fname, &ctrl_chr)) {751 if (g_getfattr) {752 sprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ,753 bkpinfo->tmpdir, current_afioball_number);754 }755 if (g_getfacl) {756 sprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ,757 bkpinfo->tmpdir, current_afioball_number);758 }759 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {760 log_it("Reading EXAT files from tape");761 res = read_EXAT_files_from_tape(&size, fname, &ctrl_chr,762 curr_xattr_list_fname,763 curr_acl_list_fname);764 }765 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {766 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);767 }768 mr_asprintf(tmp, "Verifying fileset #%ld", current_afioball_number);769 update_progress_form(tmp);770 mr_free(tmp);771 772 res = verify_an_afioball_from_stream(fname, size);773 if (res) {774 log_to_screen("Afioball %ld differs from live filesystem", current_afioball_number);775 }776 retval += res;777 current_afioball_number++;778 g_current_progress++;779 res = read_header_block_from_stream(&size, fname, &ctrl_chr);780 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {781 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);782 }783 }784 log_msg(1, "All done with afioballs");785 close_progress_form();786 paranoid_free(fname);787 paranoid_free(curr_xattr_list_fname);788 paranoid_free(curr_acl_list_fname);789 return (retval);790 }791 792 /**793 * Verify all biggiefiles on the opened CD/tape stream.794 * @param bkpinfo The backup information structure. Fields used:795 * - @c bkpinfo->restore_path796 * - @c bkpinfo->tmpdir797 *798 * @return 0 for success (even if there are differences); nonzero for a tape error.799 */800 int verify_biggiefiles_from_stream()801 {802 803 /*@ int ************************************************************ */804 int retval = 0;805 int res = 0;806 int ctrl_chr = 0;807 808 /*@ long *********************************************************** */809 long noof_biggiefiles = 0;810 long current_biggiefile_number = 0;811 812 /*@ buffers ******************************************************** */813 char *orig_fname;814 char *logical_fname = NULL;815 char *comment = NULL;816 char *curr_xattr_list_fname = NULL;817 char *curr_acl_list_fname = NULL;818 /*@ pointers ******************************************************* */819 char *p;820 821 /*@ long long size ************************************************* */822 long long size = 0;823 824 assert(bkpinfo != NULL);825 malloc_string(orig_fname);826 malloc_string(curr_xattr_list_fname);827 malloc_string(curr_acl_list_fname);828 829 if (g_getfattr) {830 sprintf(curr_xattr_list_fname, XATTR_BIGGLST_FNAME_RAW_SZ,831 bkpinfo->tmpdir);832 }833 if (g_getfacl) {834 sprintf(curr_acl_list_fname, ACL_BIGGLST_FNAME_RAW_SZ,835 bkpinfo->tmpdir);836 }837 mr_asprintf(comment, "Verifying all bigfiles.");838 log_to_screen(comment);839 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr);840 if (ctrl_chr != BLK_START_BIGGIEFILES) {841 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {842 log_it("Grabbing the EXAT biggiefiles");843 res = read_EXAT_files_from_tape(&size, orig_fname,844 &ctrl_chr, curr_xattr_list_fname,845 curr_acl_list_fname);846 }847 }848 if (ctrl_chr != BLK_START_BIGGIEFILES) {849 wrong_marker(BLK_START_BIGGIEFILES, ctrl_chr);850 }851 noof_biggiefiles = (long) size;852 log_msg(1, "noof_biggiefiles = %ld", noof_biggiefiles);853 open_progress_form("Verifying big files", comment,854 "Please wait. This may take some time.", "",855 noof_biggiefiles);856 mr_free(comment);857 858 for (res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr);859 ctrl_chr != BLK_STOP_BIGGIEFILES;860 res = read_header_block_from_stream(&size, orig_fname, &ctrl_chr))861 {862 if (ctrl_chr != BLK_START_A_NORMBIGGIE863 && ctrl_chr != BLK_START_A_PIHBIGGIE) {864 wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);865 }866 p = strrchr(orig_fname, '/');867 if (!p) {868 p = orig_fname;869 } else {870 p++;871 }872 mr_asprintf(comment, "Verifying bigfile #%ld (%ld K)", current_biggiefile_number, (long) size >> 10);873 update_progress_form(comment);874 mr_free(comment);875 876 if (bkpinfo->restore_path != NULL) {877 mr_asprintf(logical_fname, "%s/%s", bkpinfo->restore_path, orig_fname);878 res = verify_a_biggiefile_from_stream(logical_fname, size);879 mr_free(logical_fname);880 retval += res;881 } else {882 log_it("Unable to verify bigfile as restore_path is NULL");883 }884 885 current_biggiefile_number++;886 g_current_progress++;887 }888 close_progress_form();889 paranoid_free(orig_fname);890 paranoid_free(curr_xattr_list_fname);891 paranoid_free(curr_acl_list_fname);892 return (retval);893 }894 895 895 /* @} - end of LLverifyGroup */ 896 896 -
branches/3.3/mondo/src/common/newt-specific-EXT.h
r3873 r3878 16 16 extern void popup_and_OK(const char *prompt); 17 17 extern bool popup_and_get_string(char *title, char *b, char *output, int maxsize); 18 extern char *mr_popup_and_get_string(c har *title, char *b,char *output);18 extern char *mr_popup_and_get_string(const char *title, const char *b, const char *output); 19 19 extern bool popup_with_buttons(char *p, char *button1, char *button2); 20 20 extern void refresh_log_screen();
Note:
See TracChangeset
for help on using the changeset viewer.