Changeset 3878 in MondoRescue for branches/3.3/mondo/src


Ignore:
Timestamp:
Mar 8, 2024, 12:15:10 PM (4 months ago)
Author:
Bruno Cornec
Message:

Fix compiler errors

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  
    317317
    318318
    319 
    320 
    321 
    322 /**
    323  * Finalize the backup.
    324  * For streaming backups, this writes the closing block
    325  * to the stream. For CD-based backups, this creates
    326  * the final ISO image.
    327  * @param bkpinfo The backup information structure, used only
    328  * for the @c backup_media_type.
    329  * @ingroup MLarchiveGroup
    330  */
    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_type
    374  * - @c scratchdir
    375  * - @c tmpdir
    376  * @return The number of errors encountered (0 for success)
    377  * @ingroup MLarchiveGroup
    378  */
    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 the
    457  * @c backup_media_type field is used within this function.
    458  * @return return code of make_afioballs_and_images
    459  * @see make_afioballs_and_images
    460  * @ingroup MLarchiveGroup
    461  */
    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__ == 5
    475         log_msg(1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0");
    476         res = make_afioballs_and_images_OLD();
    477 #else
    478         res = make_afioballs_and_images_OLD();
    479 #endif
    480         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(), and
    503  * @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 archiveGroup
    508  */
    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 DVDRWFORMAT
    519         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 #endif
    525         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 exists
    554     if ((res = call_mindi_to_supply_boot_disks())) {
    555         fatal_error("Failed to generate boot+data disks");
    556     }
    557     retval += do_that_initial_phase();  // prepare
    558     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 files
    563     retval += make_those_slices_phase();    // backup BIG files
    564     retval += do_that_final_phase();    // clean up
    565     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_type
    580  * - @c boot_loader
    581  * - @c boot_device
    582  * - @c compression_level
    583  * - @c differential
    584  * - @c image_devs
    585  * - @c kernel_path
    586  * - @c make_cd_use_lilo
    587  * - @c media_device
    588  * - @c media_size
    589  * - @c nonbootable_backup
    590  * - @c scratchdir
    591  * - @c tmpdir
    592  * - @c use_lzo
    593  *
    594  * @return The number of errors encountered (0 for success)
    595  * @bug The code to automagically determine the boot drive
    596  * is messy and system-dependent. In particular, it breaks
    597  * for Linux RAID and LVM users.
    598  * @ingroup MLarchiveGroup
    599  */
    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 #else
    731         /* 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 #else
    735         bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'");
    736 #endif
    737         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 #else
    742             bootdev = call_program_and_get_last_line_of_output("mount | grep ' /boot ' | head -1 | cut -d' ' -f1 | cut -dp -f1");
    743 #endif
    744         }
    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 #endif
    755         if (bootdev[0])
    756             ch = which_boot_loader(bootdev);
    757         else
    758             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 #endif
    776 #ifdef __IA64__
    777            bkpinfo->boot_loader != 'E' &&
    778 #endif
    779            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 #endif
    838     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         24
    956             tmp2,           // parameter #1
    957             bkpinfo->tmpdir,    // parameter #2
    958             bkpinfo->scratchdir,    // parameter #3
    959             bkpinfo->kernel_path,   // parameter #4
    960             tape_device,        // parameter #5
    961             tape_size_sz,       // parameter #6
    962             lines_in_filelist,  // parameter #7 (INT)
    963             use_lzo_sz,     // parameter #8
    964             cd_recovery_sz,     // parameter #9
    965             (bkpinfo->image_devs == NULL) ? "\"\"" : bkpinfo->image_devs,   
    966                         // parameter #10
    967             broken_bios_sz,     // parameter #11
    968             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 #14
    973             use_comp_sz,        // parameter #15
    974             use_lilo_sz,        // parameter #16
    975             use_star_sz,        // parameter #17
    976             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 call
    1013     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     }                           // hack
    1022     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_array
    1072  */
    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 32767
    1098 
    1099 /**
    1100  * Offset of the bkpinfo pointer (in bytes) from the
    1101  * 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 int
    1109  *   containing the last set archived.
    1110  * - @c p_archival_threads_running: [offset 4] pointer to an @c int
    1111  *   containing the number of archival threads currently running.
    1112  * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing
    1113  *   the next set that should be archived.
    1114  * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a
    1115  *   bit array, where each bit corresponds to a filelist (1=needs
    1116  *   to be archived, 0=archived).
    1117  * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information
    1118  *   structure. Fields used:
    1119  *   - @c tmpdir
    1120  *   - @c zip_suffix
    1121  *
    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_fileset
    1126  * @see make_afioballs_and_images
    1127  * @return NULL, always.
    1128  * @ingroup LLarchiveGroup
    1129  */
    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 one
    1229 
    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 only
    1257  * 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_on
    1260  * @see make_iso_fs
    1261  * @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 anyway
    1274 
    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 
    1292319/**
    1293320 * Remove the archives in @c d.
     
    1328355
    1329356
    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 */
     374int 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 */
     531int 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 */
     568int 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).
    1337614 *
    1338615 * @param bkpinfo The backup information structure. Fields used:
    1339616 * - @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 */
     623int 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
    1344780 * - @c scratchdir
    1345781 * - @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)
    1348783 * @ingroup MLarchiveGroup
    1349784 */
    1350 int do_that_initial_phase() {
    1351     /*@ int *************************************** */
     785int make_those_slices_phase()
     786{
     787
     788    /*@ int ***************************************************** */
     789    int res = 0;
    1352790    int retval = 0;
    1353791
    1354     /*@ buffers *********************************** */
     792    /*@ buffers ************************************************** */
     793    char *biggielist = NULL;
    1355794    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;
    1359798
    1360799    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);
    1401811    paranoid_system(command);
    1402812    mr_free(command);
    1403813
    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
    1406835    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);
    1410855    return (retval);
    1411856}
    1412857
    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_array
    1420  * @ingroup utilityGroup
    1421  */
    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 LLarchiveGroup
    1441  * @{
    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 to
    1446  * 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 to
    1455  * 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 LLarchiveGroup
    1464  * @{
    1465  */
    1466858/**
    1467859 * Start up threads to archive your files.
     
    16491041
    16501042
     1043
     1044/**
     1045 * Single-threaded version of @c make_afioballs_and_images().
     1046 * @see make_afioballs_and_images
     1047 */
     1048int 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 */
     1175int 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 */
     1229int 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 */
     1319int 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 */
     1798int 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 */
     1869void 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 */
     1926void *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 */
     2058bool 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 */
     2093int _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 */
     2180int
     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 */
     2242int (*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 */
     2251int (*move_files_to_cd) (char *, ...) =
     2252    _move_files_to_cd;
     2253
     2254
     2255
     2256/**
     2257 * @addtogroup LLarchiveGroup
     2258 * @{
     2259 */
     2260
    16512261void pause_for_N_seconds(int how_long, char *msg)
    16522262{
     
    17722382    }
    17732383    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 */
     2393int 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);
    17742430}
    17752431
     
    24823138
    24833139
    2484 /**
    2485  * Back up big files by chopping them up.
    2486  * This function backs up all "big" files (where "big" depends
    2487  * on your backup media) in "chunks" (whose size again depends
    2488  * on your media).
    2489  *
    2490  * @param bkpinfo The backup information structure. Fields used:
    2491  * - @c backup_media_type
    2492  * - @c optimal_set_size
    2493  * @param biggielist_fname The path to a file containing a list of
    2494  * all "big" files.
    2495  * @return The number of errors encountered (0 for success)
    2496  * @see slice_up_file_etc
    2497  */
    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 exist
    2565                 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 entry
    2572             // (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_images
    2654  */
    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 themselves
    2715             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 
    27723140/* @} - 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_type
    2778  * - @c prefix
    2779  * - @c isodir
    2780  * - @c manual_cd_tray
    2781  * - @c media_size
    2782  * - @c netfs_remote_dir
    2783  * - @c scratchdir
    2784  * - @c verify_data
    2785  *
    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_fs
    2789  */
    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         // NETFS
    2855         mr_asprintf(isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
    2856     } else {
    2857         // ISO
    2858         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 && !res
    2867             && (bkpinfo->backup_media_type == cdr)) {
    2868             if ((tmp = find_optical_device())   == NULL) {  // make sure find_optical_device() finds, records CD-R's loc
    2869                 log_msg(3, "*Sigh* Mike, I hate your computer.");
    2870                 // if it can't be found then force pausing
    2871                 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                 // FIXME
    2883             }
    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 directory
    2938  * @c bkpinfo->scratchdir, where the files that will be stored on the next
    2939  * CD are waiting.
    2940  *
    2941  * @param bkpinfo The backup information structure. Fields used:
    2942  * - @c media_size
    2943  * - @c scratchdir
    2944  * @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 exceed
    2947  * the capacity of the current CD,
    2948  * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the
    2949  * 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 arguments
    2972     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 arguments
    2999     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 to
    3032  * @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 int
    3041 _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 utilityGroup
    3098  * @{
    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 insist
    3104  * 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_no
    3131                         ("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 LLarchiveGroup
    3151  * @{
    3152  */
    3153 
    31543141
    31553142/**
  • branches/3.3/mondo/src/common/libmondo-devices-EXT.h

    r3877 r3878  
    5454extern char *resolve_softlinks_to_get_to_actual_device_file(char *incoming);
    5555
    56 extern void set_g_cdrom_and_g_dvd_to_bkpinfo_value();
    57 
    5856extern bool is_dev_an_NTFS_dev(char *bigfile_fname);
    5957
  • branches/3.3/mondo/src/common/libmondo-devices.c

    r3877 r3878  
    5555extern char *call_program_and_get_last_line_of_output(const char *);
    5656
    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 
    6257/**
    6358 * ????? @bug ?????
     
    8479
    8580
    86 void set_g_cdrom_and_g_dvd_to_bkpinfo_value()
    87 {
    88     strcpy(g_cdrom_drive_is_here, bkpinfo->media_device);   // just in case
    89     strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
    90 }
    91 
    92 
    93 
    9481/**
    9582 * Retract all CD trays and wait for autorun to complete.
     
    9885void retract_CD_tray_and_defeat_autorun(void)
    9986{
    100 //  log_it("rctada: Retracting all CD trays", __LINE__);
     87//  log_it("rctada: Retracting optical tray", __LINE__);
    10188    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    }
    11192    if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
    11293        log_it("autorun detected; sleeping for 2 seconds");
    11394        sleep(2);
    11495    }
    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 */
     108char *where_is_root_mounted(void) {
     109
     110/*@ buffers **************** */
     111char *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
     127return (tmp);
    117128}
    118129
     
    447458
    448459
    449 /**
    450  * Try to mount CD/DVD at @p mountpoint. If the CD/DVD is not found or has
    451  * 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_media
    455  */
    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 device
    493  * and return it's device file to the caller that needs to free it
    494  */
    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 
    540460/*
    541461 * This function tries to find an optical media device
    542462 * and return it's device file to the caller that needs to free it
    543463 */
    544 char *find_optical_device(void)
    545 {
     464char *find_optical_device(void) {
    546465    char *dev = NULL;
    547466    char *tmp1 = NULL;
     
    582501                        if (!does_file_exist(dev)) {
    583502                            log_it("Unable to find a tape device on this system");
     503                        }
     504                    }
    584505                }
    585506            }
     
    598519    return(dev);
    599520}
     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*/
     530bool 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 */
     672bool 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 */
     711char *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
    600756
    601757/* Generic fund to find a media
     
    9711127
    9721128/**
    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 */
     1135int what_number_cd_is_this(void) {
     1136
     1137    int cd_number = -1;
     1138    char *mountdev = NULL;
    9851139    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");
    10031146        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}
    11121167
    11131168
     
    20002055
    20012056/**
     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 */
     2063char *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/**
    20022076 * Ask user for details of backup/restore information.
    20032077 * Called when @c mondoarchive doesn't get any parameters.
     
    27172791
    27182792
    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 by
    2723  * caller
    2724  * @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 
    27382793
    27392794
     
    28042859    return(ret);
    28052860}
    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 mounted
    2816  * (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 by
    2856  * caller
    2857  * @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 #else
    2868     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 #endif
    2878 
    2879 return (tmp);
    2880 }
    2881 
    28822861
    28832862
  • branches/3.3/mondo/src/common/libmondo-filelist.c

    r3871 r3878  
    6060extern char *g_getfacl;
    6161extern 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 */
     77int 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
    62230
    63231
     
    184352
    185353
    186 /**
    187  * Chop the filelist into sets.
    188  * Each fileset is a list of files whose total (uncompressed) size is usually
    189  * about X KB. Files bigger than 8X KB are placed in a "biggielist"; they will
    190  * 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 is
    194  * an integer, biggielist.txt, and LAST-FILELIST-NUMBER) created
    195  * @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 content
    203     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 possible
    274             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_error
    326             ("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 this
    340        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 
    354354
    355355/**
     
    967967    }
    968968    return;
    969 }
    970 
    971 
    972 
    973 
    974 /**
    975  * Reset the filelist to the state it was when it was loaded. This does not
    976  * 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 itself
    1017     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     }
    1049969}
    1050970
     
    12511171}
    12521172
     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 */
     1181void 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 */
     1196void 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}
    12531252
    12541253
  • branches/3.3/mondo/src/common/libmondo-files.c

    r3874 r3878  
    1313#include "mr_file.h"
    1414#include "mondostructures.h"
     15#include "crcttt.h"
    1516
    1617#include "libmondo-tools-EXT.h"
  • branches/3.3/mondo/src/common/libmondo-fork.c

    r3871 r3878  
    8787#define MONDO_POPMSG  "Your machine will not retract the CD tray automatically. Please call mondoarchive with the -m (manual CD tray) flag."
    8888
     89void *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
    89108
    90109int run_external_binary_with_percentage_indicator_NEW(char *tt, char *cmd) {
     
    689708
    690709
    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 
    710710/**
    711711 * Feed @p input_fifo through ntfsclone (restore) to @p output_device.
  • branches/3.3/mondo/src/common/libmondo-raid.c

    r3871 r3878  
    246246#endif
    247247
    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 void
    255 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 #else
    284 // Linux
    285 #endif
    286 
    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 #endif
    312 
    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 }
    341248
    342249/**
     
    434341}
    435342
     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 */
     349void
     350save_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 */
     372int 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 */
     423void 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}
    436436/**
    437437 * Retrieve the next line from a raidtab stream.
     
    473473    return (1);
    474474}
     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 */
     485void
     486process_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
    475563
    476564
     
    659747#endif
    660748
    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 void
    677 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 #endif
    753749
    754750
  • branches/3.3/mondo/src/common/libmondo-stream.c

    r3877 r3878  
    2323#include "libmondo-tools-EXT.h"
    2424#include "libmondo-fifo-EXT.h"
     25#include "libmondo-devices-EXT.h"
    2526
    2627#define EXTRA_TAPE_CHECKSUMS
     
    4041
    4142/**
     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 */
     46char g_tape_fifo[MAX_STR_LEN];
     47
     48
     49/**
    4250 * @addtogroup globalGroup
    4351 * @{
     
    7684
    7785/**
    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 */
     94int 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
    81144/**
    82145 * Close the global output file descriptor which Mondo has used to read
     
    144207
    145208
    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 */
     216void 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 */
     239int
     240read_header_block_from_stream(long long *plen, char *filename,
     241                              int *pcontrol_char)
     242{
    161243
    162244    /*@ 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 */
     293void insist_on_this_tape_number(int tapeno)
     294{
    168295    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
    202321
    203322
     
    441560    }
    442561    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 int
    453 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     // xattr
    479     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     // acl
    509     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 itself
    530     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_CHECKSUMS
    568     int ch;
    569 #endif
    570 
    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             // FIXME
    615         }
    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_CHECKSUMS
    629         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 #endif
    635     }
    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     // xattr
    659         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     // acl
    667         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 actually
    683  * 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 is
    735  * 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 '.' -Hugo
    742  */
    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_device
    804  * - @c bkpinfo->tmpdir
    805  * @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 device
    842     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                 // FIXME
    890             }
    891             g_tape_posK += length / 1024;
    892         }
    893         if (i > 8)              // otherwise, 'buffer' distorts calculations
    894         {
    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         // FIXME
    918     }
    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         // FIXME
    926     }
    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 one
    975  * @param tapedev The tape device to open for writing.
    976  * @note the caller needs to free the string returned
    977  */
    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 so
    1028  * @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 so
    1054  * @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 ANY
    1057  * 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 so
    1148  * @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 ANY
    1151  * 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);
    1180562}
    1181563
     
    1327709
    1328710
    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.
    1336715 * @return 0 for success, nonzero for failure.
    1337716 */
    1338717int
    1339 read_file_from_stream_to_stream(FILE * fout, long long size)
     718read_file_from_stream_to_file(char *outfile, long long size)
    1340719{
    1341720
     
    1345724    /*@ end vars *************************************************** */
    1346725
    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
    1350728    return (res);
     729}
     730
     731
     732
     733
     734int 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 */
     807int 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
     918int 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 */
     947void 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 */
     972int 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
     1028int 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 */
     1052int 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 */
     1084int 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 */
     1218int 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 */
     1228char *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 */
     1281int 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 */
     1332int 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 */
     1375int openout_tape() {
     1376
     1377g_current_media_number = 1;
     1378if (g_tape_stream) {
     1379    log_it("FYI - I won't 'openout' the tape. It's already open.");
     1380    return (0);
     1381}
     1382if (bkpinfo->media_device == NULL) {
     1383    log_it("Unable to openout NULL device");
     1384    return(1);
     1385}
     1386g_tapecatalog = mr_malloc(sizeof(struct s_tapecatalog));
     1387g_tapecatalog->entries = 0;
     1388g_tape_posK = 0;
     1389
     1390if (bkpinfo->use_obdr) {
     1391    create_obdr();
     1392} else {
     1393    set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
     1394}
     1395log_it("Opening OUT tape");
     1396if (!(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}
     1401return (0);
    13511402}
    13521403
     
    15141565
    15151566/**
    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.
    15241573 */
    15251574int
    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;
     1575read_file_from_stream_to_stream(FILE * fout, long long size)
     1576{
     1577
     1578    /*@ int ******************************************************** */
     1579    int res;
    15361580
    15371581    /*@ end vars *************************************************** */
    15381582
    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}
    15711588
    15721589
     
    17181735
    17191736
    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 
    17401737/* @} - end of streamGroup */
  • branches/3.3/mondo/src/common/libmondo-string.c

    r3874 r3878  
    965965
    966966
     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 */
     973char *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}
    9671007
    9681008
     
    10231063
    10241064
    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  
    122122    mr_free(command);
    123123    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 */
     141int 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 */
     275int
     276verify_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 */
     302int
     303verify_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 */
     350int
     351verify_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 */
     430int 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 */
     533int 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);
    124626}
    125627
     
    391893
    392894
    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_lzo
    401  * - @c bkpinfo->tmpdir
    402  * - @c bkpinfo->zip_exe
    403  * - @c bkpinfo->zip_suffix
    404  * @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-NULL
    467     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) and
    536  * 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_afioball
    541  */
    542 int
    543 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_afioball
    568  */
    569 int
    570 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 int
    618 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->tmpdir
    694  *
    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_path
    796  * - @c bkpinfo->tmpdir
    797  *
    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_NORMBIGGIE
    863             && 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 
    895895/* @} - end of LLverifyGroup */
    896896
  • branches/3.3/mondo/src/common/newt-specific-EXT.h

    r3873 r3878  
    1616extern void popup_and_OK(const char *prompt);
    1717extern bool popup_and_get_string(char *title, char *b, char *output, int maxsize);
    18 extern char *mr_popup_and_get_string(char *title, char *b, char *output);
     18extern char *mr_popup_and_get_string(const char *title, const char *b, const char *output);
    1919extern bool popup_with_buttons(char *p, char *button1, char *button2);
    2020extern void refresh_log_screen();
Note: See TracChangeset for help on using the changeset viewer.