Changeset 3879 in MondoRescue for branches/3.3/mondo/src/common/libmondo-archive.c
- Timestamp:
- Mar 9, 2024, 3:10:04 AM (4 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mondo/src/common/libmondo-archive.c
r3878 r3879 33 33 #include <stdarg.h> 34 34 #include <unistd.h> 35 35 36 #define DVDRWFORMAT 1 37 38 /** 39 * Maximum number of filesets allowed in this function. 40 */ 41 #define MAX_NOOF_SETS_HERE 32767 42 43 /** 44 * Offset of the bkpinfo pointer (in bytes) from the 45 * buffer passed to create_afio_files_in_background. 46 */ 47 #define BKPINFO_LOC_OFFSET (16+MAX_NOOF_SETS_HERE/8+16) 36 48 37 49 … … 355 367 356 368 369 /** 370 * Create a USB image in @c destfile, from files in @c bkpinfo->scratchdir. 371 * 372 * @param bkpinfo The backup information structure. Fields used: 373 * - @c backup_media_type 374 * - @c nonbootable_backup 375 * - @c scratchdir 376 * 377 * @param destfile Where to put the generated USB image. 378 * @return The number of errors encountered (0 for success) 379 */ 380 int make_usb_fs() 381 { 382 /*@ int ********************************************** */ 383 int retval = 0; 384 int res; 385 386 /*@ buffers ****************************************** */ 387 char *tmp = NULL; 388 char *tmp1 = NULL; 389 char *result_sz = NULL; 390 char *message_to_screen = NULL; 391 char *old_pwd = NULL; 392 char *mds = NULL; 393 394 assert(bkpinfo != NULL); 395 396 log_msg(2, "make_usb_fs --- scratchdir=%s", bkpinfo->scratchdir); 397 old_pwd = mr_getcwd(); 398 mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir); 399 run_program_and_log_output(tmp, FALSE); 400 mr_free(tmp); 401 if (chdir(bkpinfo->scratchdir)) { 402 // FIXME 403 } 404 405 mds = media_descriptor_string(bkpinfo->backup_media_type); 406 mr_asprintf(message_to_screen, "Copying data to make %s #%d",mds, g_current_media_number); 407 mr_free(mds); 408 log_msg(1, message_to_screen); 409 410 if (bkpinfo->media_device) { 411 mr_asprintf(tmp1, "%s1", bkpinfo->media_device); 412 } else { 413 mr_asprintf(tmp1, ""); 414 } 415 if (is_this_device_mounted(tmp1)) { 416 log_msg(1, "USB device mounted. Remounting it at the right place"); 417 mr_asprintf(tmp, "umount %s", tmp1); 418 run_program_and_log_output(tmp, FALSE); 419 mr_free(tmp); 420 } 421 mr_free(tmp1); 422 423 log_msg(1, "Mounting USB device."); 424 mr_asprintf(tmp1, "%s/usb", bkpinfo->tmpdir); 425 mr_asprintf(tmp, "mkdir -p %s", tmp1); 426 run_program_and_log_output(tmp, FALSE); 427 mr_free(tmp); 428 429 430 /* Mindi always create one single parition on the USB dev */ 431 mr_asprintf(tmp, "mount %s1 %s", bkpinfo->media_device, tmp1); 432 run_program_and_log_output(tmp, FALSE); 433 mr_free(tmp); 434 435 if (bkpinfo->nonbootable_backup) { 436 log_msg(1, "Making nonbootable USB backup not implemented yet"); 437 } else { 438 log_msg(1, "Making bootable backup"); 439 440 /* Command to execute */ 441 mr_asprintf(tmp,"cd %s ; rm -fr %s/syslinux ; mv * %s", bkpinfo->scratchdir, tmp1, tmp1); 442 res = eval_call_to_make_USB(tmp, message_to_screen); 443 if (res) { 444 mr_asprintf(result_sz, "%s ...failed",tmp); 445 } else { 446 mr_asprintf(result_sz, "%s ...OK",tmp); 447 } 448 log_to_screen(result_sz); 449 mr_free(result_sz); 450 mr_free(tmp); 451 retval += res; 452 453 /* Recreate the required structure under the scratch dir */ 454 mr_asprintf(tmp,"mkdir %s/archive", bkpinfo->scratchdir); 455 run_program_and_log_output(tmp, FALSE); 456 mr_free(tmp); 457 } 458 paranoid_free(message_to_screen); 459 460 /* Copy the current logfile - of course incomplete to the media */ 461 mr_system("gzip -c9 %s > %s/archives/%s", MONDO_LOGFILE, tmp1, MONDO_LOGFILENAME); 462 paranoid_free(tmp1); 463 464 if (is_this_device_mounted(bkpinfo->media_device)) { 465 mr_asprintf(tmp, "umount %s1", bkpinfo->media_device); 466 run_program_and_log_output(tmp, FALSE); 467 mr_free(tmp); 468 } 469 470 if (chdir(old_pwd)) { 471 // FIXME 472 } 473 mr_free(old_pwd); 474 if (retval) { 475 log_msg(1, "WARNING - make_usb_fs returned an error"); 476 } 477 return(retval); 478 } 479 480 481 /** 482 * Make sure the user has a valid CD-R(W) in the CD drive. 483 * @param cd_dev Set to the CD-R(W) device checked. 484 * @param keep_looping If TRUE, keep pestering user until they insist 485 * or insert a correct CD; if FALSE, only check once. 486 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't). 487 */ 488 int interrogate_disk_currently_in_cddrive(char *cd_dev, 489 bool keep_looping) 490 { 491 int res = 0; 492 char *bkp = NULL; 493 char *cdrecord = NULL; 494 495 mr_asprintf(bkp, "%s", cd_dev); 496 if ((cd_dev = find_optical_device()) != NULL) { 497 if (!system("which cdrecord > /dev/null 2> /dev/null")) { 498 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev); 499 } else if (!system("which dvdrecord > /dev/null 2> /dev/null")) { 500 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev); 501 } else { 502 log_msg(2, "Oh well. I guess I'll just pray then."); 503 } 504 if (cdrecord != NULL) { 505 if (!keep_looping) { 506 retract_CD_tray_and_defeat_autorun(); 507 res = run_program_and_log_output(cdrecord, 5); 508 } else { 509 while ((res = run_program_and_log_output(cdrecord, 5))) { 510 retract_CD_tray_and_defeat_autorun(); 511 if (ask_me_yes_or_no 512 ("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?")) 513 { 514 log_msg(1, "Well, he insisted..."); 515 break; 516 } 517 } 518 } 519 } 520 } 521 mr_free(bkp); 522 523 mr_free(cdrecord); 524 return (res); 525 } 526 527 528 /** 529 * Asks the user to put a CD-R(W) in the drive. 530 * @param ask_for_one_if_more_than_this (unused) 531 * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise. 532 */ 533 void pause_and_ask_for_cdr(int ask_for_one_if_more_than_this, bool * pmountable) { 534 535 /*@ buffers ********************************************* */ 536 char *tmp = NULL; 537 char *cdrom_dev = NULL; 538 char *cd_dev = NULL; 539 char *our_serial_str = NULL; 540 bool ok_go_ahead_burn_it; 541 int cd_number = -1; 542 int attempt_to_mount_returned_this = 999; 543 char *mtpt = NULL; 544 char *szcdno = NULL; 545 char *szserfname = NULL; 546 char *szunmount = NULL; 547 char *mds = NULL; 548 549 malloc_string(cd_dev); 550 551 mds = media_descriptor_string(g_backup_media_type); 552 log_to_screen("I am about to burn %s #%d", mds, g_current_media_number); 553 mr_free(mds); 554 if (g_current_media_number < ask_for_one_if_more_than_this) { 555 return; 556 } 557 log_to_screen("Scanning CD-ROM drive..."); 558 mr_asprintf(mtpt, "%s/cd.mtpt", bkpinfo->tmpdir); 559 make_hole_for_dir(mtpt); 560 561 gotos_make_me_puke: 562 ok_go_ahead_burn_it = TRUE; 563 mr_free(cdrom_dev); 564 if ((cdrom_dev = find_optical_device()) != NULL) { 565 /* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird 566 log_msg(2, "paafcd: Retracting CD-ROM drive if possible" ); 567 retract_CD_tray_and_defeat_autorun(); 568 */ 569 mr_asprintf(tmp, "umount %s", cdrom_dev); 570 run_program_and_log_output(tmp, 1); 571 mr_asprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt); 572 mr_asprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt); 573 mr_asprintf(szunmount, "umount %s", mtpt); 574 cd_number = -1; 575 mr_asprintf(tmp, "mount %s %s", cdrom_dev, mtpt); 576 mr_asprintf(our_serial_str, "%s", ""); 577 attempt_to_mount_returned_this = run_program_and_log_output(tmp, 1); 578 mr_free(tmp); 579 580 if (attempt_to_mount_returned_this) { 581 log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt); 582 log_to_screen("If there's a CD/DVD in the drive, it's blank."); 583 } else if (!does_file_exist(szcdno) || !does_file_exist(szserfname)) { 584 mds = media_descriptor_string(g_backup_media_type); 585 log_to_screen("%s has data on it but it's probably not a Mondo CD.", mds); 586 mr_free(mds); 587 } else { 588 mds = media_descriptor_string(g_backup_media_type); 589 log_to_screen("%s found in drive. It's a Mondo disk.", mds); 590 mr_free(mds); 591 592 cd_number = atoi(last_line_of_file(szcdno)); 593 mr_asprintf(tmp, "cat %s 2> /dev/null", szserfname); 594 mr_free(our_serial_str); 595 our_serial_str = call_program_and_get_last_line_of_output(tmp); 596 mr_free(tmp); 597 // FIXME - should be able to use last_line_of_file(), surely? 598 } 599 mr_free(szcdno); 600 mr_free(szserfname); 601 602 run_program_and_log_output(szunmount, 1); 603 mr_free(szunmount); 604 605 log_msg(2, "paafcd: cd_number = %d", cd_number); 606 log_msg(2, "our serial str = %s; bkpinfo->serial_string = %s", our_serial_str, bkpinfo->serial_string); 607 if (cd_number > 0 && !strcmp(our_serial_str, bkpinfo->serial_string)) { 608 mds = media_descriptor_string(g_backup_media_type); 609 log_msg(2, "This %s is part of this backup set!", mds); 610 ok_go_ahead_burn_it = FALSE; 611 if (cd_number == g_current_media_number - 1) { 612 log_to_screen("I think you've left the previous %s in the drive.", mds); 613 } else { 614 log_to_screen("Please remove this %s. It is part of the backup set you're making now.", mds); 615 } 616 mr_free(mds); 617 618 } else { 619 log_to_screen("...but not part of _our_ backup set."); 620 } 621 mr_free(our_serial_str); 622 } else { 623 mds = media_descriptor_string(g_backup_media_type); 624 log_msg(2, 625 "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", mds); 626 if (interrogate_disk_currently_in_cddrive(cd_dev, FALSE)) { 627 ok_go_ahead_burn_it = FALSE; 628 log_to_screen("There isn't a writable %s in the drive.", mds); 629 } 630 mr_free(mds); 631 } 632 633 if (!ok_go_ahead_burn_it) { 634 if (!bkpinfo->please_dont_eject) { 635 eject_device(cdrom_dev); 636 } 637 mds = media_descriptor_string(g_backup_media_type); 638 mr_asprintf(tmp, "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.", mds, g_current_media_number, mds); 639 mr_free(mds); 640 641 popup_and_OK(tmp); 642 mr_free(tmp); 643 goto gotos_make_me_puke; 644 } else { 645 log_msg(2, "paafcd: OK, going ahead and burning it."); 646 } 647 648 mds = media_descriptor_string(g_backup_media_type); 649 log_msg(2, "paafcd: OK, I assume I have a blank/reusable %s in the drive...", mds); 650 651 log_to_screen("Proceeding w/ %s in drive.", mds); 652 mr_free(mds); 653 654 mr_free(cdrom_dev); 655 paranoid_free(cd_dev); 656 mr_free(mtpt); 657 if (pmountable) { 658 if (attempt_to_mount_returned_this) { 659 *pmountable = FALSE; 660 } else { 661 *pmountable = TRUE; 662 } 663 } 664 665 } 666 667 668 /** 669 * @addtogroup LLarchiveGroup 670 * @{ 671 */ 672 673 void pause_for_N_seconds(int how_long, char *msg) 674 { 675 int i; 676 open_evalcall_form(msg); 677 for (i = 0; i < how_long; i++) { 678 update_evalcall_form((int) ((100.0 / (float) (how_long) * i))); 679 sleep(1); 680 } 681 close_evalcall_form(); 682 } 683 684 685 /** 686 * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir. 687 * 688 * @param bkpinfo The backup information structure. Fields used: 689 * - @c backup_media_type 690 * - @c call_after_iso 691 * - @c call_before_iso 692 * - @c call_burn_iso 693 * - @c call_make_iso 694 * - @c make_cd_use_lilo 695 * - @c manual_cd_tray 696 * - @c nonbootable_backup 697 * - @c scratchdir 698 * 699 * @param destfile Where to put the generated ISO image. 700 * @return The number of errors encountered (0 for success) 701 */ 702 int make_iso_fs(char *destfile) { 703 /*@ int ********************************************** */ 704 int retval = 0; 705 int res; 706 707 /*@ buffers ****************************************** */ 708 char *tmp = NULL; 709 char *old_pwd = NULL; 710 char *result_sz = NULL; 711 char *message_to_screen = NULL; 712 char *sz_blank_disk = NULL; 713 char *isofs_cmd = NULL; 714 char *full_isofs_cmd = NULL; 715 char *mds = NULL; 716 char *uefistr = NULL; 717 bool cd_is_mountable; 718 719 assert(bkpinfo != NULL); 720 assert_string_is_neither_NULL_nor_zerolength(destfile); 721 722 if (bkpinfo->backup_media_type == iso && bkpinfo->manual_cd_tray) { 723 popup_and_OK("Please insert new media and press Enter."); 724 } 725 726 log_msg(2, "make_iso_fs --- scratchdir=%s --- destfile=%s", bkpinfo->scratchdir, destfile); 727 old_pwd = mr_getcwd(); 728 mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir); 729 run_program_and_log_output(tmp, FALSE); 730 mr_free(tmp); 731 732 if (chdir(bkpinfo->scratchdir)) { 733 // FIXME 734 } 735 736 if (bkpinfo->call_before_iso != NULL) { 737 mr_asprintf(message_to_screen, "Running pre-ISO call for CD#%d", g_current_media_number); 738 res = eval_call_to_make_ISO(bkpinfo->call_before_iso, destfile, g_current_media_number, message_to_screen); 739 if (res) { 740 mr_strcat(message_to_screen, "...failed"); 741 } else { 742 mr_strcat(message_to_screen, "...OK"); 743 } 744 log_to_screen(message_to_screen); 745 paranoid_free(message_to_screen); 746 747 retval += res; 748 } 749 750 if (bkpinfo->call_make_iso != NULL) { 751 log_msg(2, "bkpinfo->call_make_iso = %s", bkpinfo->call_make_iso); 752 mds = media_descriptor_string(bkpinfo->backup_media_type); 753 mr_asprintf(message_to_screen, "Making an ISO (%s #%d)", mds, g_current_media_number); 754 mr_free(mds); 755 756 pause_and_ask_for_cdr(2, &cd_is_mountable); /* if g_current_media_number >= 2 then pause & ask */ 757 if (retval) { 758 log_to_screen 759 ("Serious error(s) occurred already. I shan't try to write to media."); 760 } else { 761 res = 762 eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen); 763 if (res) { 764 log_to_screen("%s...failed to write", message_to_screen); 765 } else { 766 log_to_screen("%s...OK", message_to_screen); 767 mr_asprintf(tmp, "tail -n10 %s | grep -F ':-('", MONDO_LOGFILE); 768 if (!run_program_and_log_output(tmp, 1)) { 769 log_to_screen 770 ("Despite nonfatal errors, growisofs confirms the write was successful."); 771 } 772 mr_free(tmp); 773 } 774 retval += res; 775 #ifdef DVDRWFORMAT 776 mr_asprintf(tmp, "tail -n8 %s | grep 'blank=full.*dvd-compat.*DAO'", MONDO_LOGFILE); 777 if (g_backup_media_type == dvd 778 && (res || !run_program_and_log_output(tmp, 1))) { 779 log_to_screen 780 ("Failed to write to disk. I shall blank it and then try again."); 781 sleep(5); 782 /* reset error counter before trying to blank DVD */ 783 retval -= res; 784 sync(); 785 pause_for_N_seconds(5, "Letting DVD drive settle"); 786 787 // dvd+rw-format --- OPTION 2 788 if (!bkpinfo->please_dont_eject) { 789 log_to_screen("Ejecting media to clear drive status."); 790 eject_device(bkpinfo->media_device); 791 inject_device(bkpinfo->media_device); 792 } 793 pause_for_N_seconds(5, "Letting DVD drive settle"); 794 if (bkpinfo->media_device) { 795 mr_asprintf(sz_blank_disk, "dvd+rw-format -force %s", bkpinfo->media_device); 796 } else { 797 mr_asprintf(sz_blank_disk, "dvd+rw-format"); 798 } 799 log_msg(3, "sz_blank_disk = '%s'", sz_blank_disk); 800 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk); 801 if (res) { 802 log_to_screen("Warning - format failed. (Was it a DVD-R?) Sleeping for 5 seconds to take a breath..."); 803 pause_for_N_seconds(5, "Letting DVD drive settle... and trying again."); 804 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk); 805 if (res) { 806 log_to_screen("Format failed a second time."); 807 } 808 } else { 809 log_to_screen 810 ("Format succeeded. Sleeping for 5 seconds to take a breath..."); 811 } 812 mr_free(sz_blank_disk); 813 pause_for_N_seconds(5, "Letting DVD drive settle"); 814 if (!bkpinfo->please_dont_eject) { 815 log_to_screen("Ejecting media to clear drive status."); 816 eject_device(bkpinfo->media_device); 817 inject_device(bkpinfo->media_device); 818 } 819 pause_for_N_seconds(5, "Letting DVD drive settle"); 820 res = eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen); 821 retval += res; 822 if (!bkpinfo->please_dont_eject) { 823 log_to_screen("Ejecting media."); 824 eject_device(bkpinfo->media_device); 825 } 826 if (res) { 827 log_to_screen("Dagnabbit. It still failed."); 828 } else { 829 log_to_screen 830 ("OK, this time I successfully backed up to DVD."); 831 } 832 } 833 mr_free(tmp); 834 #endif 835 if (g_backup_media_type == dvd && !bkpinfo->please_dont_eject) { 836 eject_device(bkpinfo->media_device); 837 } 838 } 839 paranoid_free(message_to_screen); 840 } else { 841 mds = media_descriptor_string(bkpinfo->backup_media_type); 842 mr_asprintf(message_to_screen, "Running mkisofs to make %s #%d", mds, g_current_media_number); 843 log_msg(1, message_to_screen); 844 mr_asprintf(result_sz, "Call to mkisofs to make ISO (%s #%d) ", mds, g_current_media_number); 845 mr_free(mds); 846 if ((tmp = find_home_of_exe("xorriso")) != NULL) { 847 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_XORRISO_OPT); 848 } else if ((tmp = find_home_of_exe("genisoimage")) != NULL) { 849 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_GENISOIMAGE_OPT); 850 } else if ((tmp = find_home_of_exe("mkisofs")) != NULL) { 851 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_MKISOFS_OPT); 852 } else if ((tmp = find_home_of_exe("wodim")) != NULL) { 853 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_WODIM_OPT); 854 } else { 855 fatal_error("Unable to find a command to create ISO among xorriso, genisoimage, mksiofs or wodim, please install one"); 856 } 857 mr_free(tmp); 858 if (bkpinfo->nonbootable_backup) { 859 log_msg(1, "Making nonbootable backup"); 860 mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS); 861 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen); 862 mr_free(full_isofs_cmd); 863 } else { 864 log_msg(1, "Making bootable backup"); 865 866 #ifdef __FreeBSD__ 867 bkpinfo->make_cd_use_lilo = TRUE; 868 #endif 869 870 871 log_msg(1, "make_cd_use_lilo is actually %d", bkpinfo->make_cd_use_lilo); 872 if (bkpinfo->make_cd_use_lilo) { 873 log_msg(1, "make_cd_use_lilo = TRUE"); 874 #ifdef __IA64__ 875 log_msg(1, "IA64 --> elilo"); 876 mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_ELILO); 877 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen); 878 mr_free(full_isofs_cmd); 879 #else 880 log_msg(1, "Non-ia64 --> lilo"); 881 mr_asprintf(full_isofs_cmd, "%s%s-b images/mindi-bootroot.img -c images/boot.cat -o '_ISO_' .",isofs_cmd,MONDO_MKISOFS); 882 // FIXME: fixed boot size probably wrong. lilo to be removed 883 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen); 884 mr_free(full_isofs_cmd); 885 #endif 886 } else { 887 log_msg(1, "make_cd_use_lilo = FALSE"); 888 log_msg(1, "Isolinux"); 889 if (bkpinfo->boot_type == UEFI) { 890 if (strstr(isofs_cmd,"xorriso")) { 891 /* xorriso needs another '-' before efi-boot */ 892 mr_asprintf(uefistr, "%s -%s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI); 893 } else { 894 mr_asprintf(uefistr, "%s %s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI); 895 } 896 } else { 897 mr_asprintf(uefistr, "%s",MONDO_MKISOFS_CMS); 898 } 899 mr_asprintf(full_isofs_cmd, "%s%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_SYSLINUX,uefistr); 900 mr_free(uefistr); 901 902 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen); 903 mr_free(full_isofs_cmd); 904 } 905 } 906 mr_free(isofs_cmd); 907 paranoid_free(message_to_screen); 908 909 if (res) { 910 mr_strcat(result_sz, "...failed"); 911 } else { 912 mr_strcat(result_sz, "...OK"); 913 } 914 log_to_screen(result_sz); 915 paranoid_free(result_sz); 916 retval += res; 917 } 918 919 if (bkpinfo->backup_media_type == cdr) { 920 if (is_this_device_mounted(bkpinfo->media_device)) { 921 log_msg(2, "Warning - %s mounted. I'm unmounting it before I burn to it.", bkpinfo->media_device); 922 mr_asprintf(tmp, "umount %s", bkpinfo->media_device); 923 run_program_and_log_output(tmp, FALSE); 924 mr_free(tmp); 925 } 926 } 927 928 if (bkpinfo->call_burn_iso != NULL) { 929 log_msg(2, "bkpinfo->call_burn_iso = %s", bkpinfo->call_burn_iso); 930 mds = media_descriptor_string(bkpinfo->backup_media_type); 931 mr_asprintf(message_to_screen, "Burning %s #%d", mds, g_current_media_number); 932 mr_free(mds); 933 pause_and_ask_for_cdr(2, &cd_is_mountable); 934 res = eval_call_to_make_ISO(bkpinfo->call_burn_iso, destfile, g_current_media_number, message_to_screen); 935 if (res) { 936 mr_strcat(message_to_screen, "...failed"); 937 } else { 938 mr_strcat(message_to_screen, "...OK"); 939 } 940 log_to_screen(message_to_screen); 941 paranoid_free(message_to_screen); 942 943 retval += res; 944 } 945 946 if (bkpinfo->call_after_iso != NULL) { 947 mds = media_descriptor_string(bkpinfo->backup_media_type); 948 mr_asprintf(message_to_screen, "Running post-ISO call (%s #%d)", mds, g_current_media_number); 949 mr_free(mds); 950 res = eval_call_to_make_ISO(bkpinfo->call_after_iso, destfile, g_current_media_number, message_to_screen); 951 if (res) { 952 mr_strcat(message_to_screen, "...failed"); 953 } else { 954 mr_strcat(message_to_screen, "...OK"); 955 } 956 log_to_screen(message_to_screen); 957 paranoid_free(message_to_screen); 958 959 retval += res; 960 } 961 962 if (chdir(old_pwd)) { 963 // FIXME 964 } 965 mr_free(old_pwd); 966 if (retval) { 967 log_msg(1, "WARNING - make_iso_fs returned an error"); 968 } 969 return (retval); 970 } 971 972 973 bool is_dev_an_NTFS_dev(char *bigfile_fname) 974 { 975 char *tmp = NULL; 976 char *command = NULL; 977 bool ret = TRUE; 978 979 mr_asprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | strings | head -n1", bigfile_fname); 980 log_msg(1, "command = '%s'", command); 981 tmp = call_program_and_get_last_line_of_output(command); 982 mr_free(command); 983 984 log_msg(1, "--> tmp = '%s'", tmp); 985 if (strstr(tmp, "NTFS")) { 986 log_it("TRUE"); 987 ret = TRUE; 988 } else { 989 log_it("FALSE"); 990 ret = FALSE; 991 } 992 mr_free(tmp); 993 return(ret); 994 } 995 996 357 997 358 998 /** … … 601 1241 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 602 1242 } 1243 1244 return (retval); 1245 } 1246 1247 /** 1248 * Copy some files to tape. 1249 * This function copies the files specified as parameters into the tape stream. 1250 * 1251 * @param bkpinfo The backup information structure. Used only in the call to 1252 * @c write_file_to_stream_from_file(). 1253 * 1254 * @param files_to_add The files to copy to the tape stream. 1255 * @warning The list of @c files_to_add must be terminated with @c NULL. 1256 * @note Files may be split across multiple tapes if necessary. 1257 * 1258 * @return The number of errors encountered (0 for success) 1259 */ 1260 int 1261 _move_files_to_stream(char *files_to_add, ...) 1262 { 1263 1264 /*@ int ************************************************************ */ 1265 int retval = 0; 1266 int res = 0; 1267 /*@ buffers ******************************************************** */ 1268 1269 /*@ char *********************************************************** */ 1270 char start_chr; 1271 char stop_chr; 1272 char *curr_file = NULL; 1273 char *cf; 1274 /*@ long long ****************************************************** */ 1275 off_t length_of_incoming_file = (off_t)0; 1276 va_list ap; 1277 1278 assert(bkpinfo != NULL); 1279 va_start(ap, files_to_add); 1280 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) { 1281 if (!cf) { 1282 continue; 1283 } 1284 mr_asprintf(curr_file, "%s", cf); 1285 if (!does_file_exist(curr_file)) { 1286 log_msg(1, 1287 "Warning - you're trying to add a non-existent file - '%s' to the tape", 1288 curr_file); 1289 } 1290 /* create header chars */ 1291 start_chr = BLK_START_AN_AFIO_OR_SLICE; 1292 stop_chr = BLK_STOP_AN_AFIO_OR_SLICE; 1293 /* ask for new tape if necessary */ 1294 length_of_incoming_file = length_of_file(curr_file); 1295 write_header_block_to_stream(length_of_incoming_file, curr_file, start_chr); 1296 res = write_file_to_stream_from_file(curr_file); 1297 retval += res; 1298 unlink(curr_file); 1299 mr_free(curr_file); 1300 /* write closing header */ 1301 write_header_block_to_stream((off_t)0, "finished-writing-file", stop_chr); 1302 } 1303 va_end(ap); 1304 1305 if (retval) { 1306 log_msg(1, 1307 "Warning - errors occurred while I was adding file to tape"); 1308 } 1309 return (retval); 1310 } 1311 1312 /** 1313 * Move some files to the ISO scratch directory. 1314 * This function moves files specified as parameters, into the directory 1315 * @c bkpinfo->scratchdir, where the files that will be stored on the next 1316 * CD are waiting. 1317 * 1318 * @param bkpinfo The backup information structure. Fields used: 1319 * - @c media_size 1320 * - @c scratchdir 1321 * @param files_to_add The files to add to the scratchdir. 1322 * @warning The list of @c files_to_add must be terminated with @c NULL. 1323 * @note If and when the space occupied by the scratchdir would exceed 1324 * the capacity of the current CD, 1325 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the 1326 * scratchdir is emptied. 1327 * 1328 * @return The number of errors encountered (0 for success) 1329 */ 1330 int _move_files_to_cd(char *files_to_add, ...) 1331 { 1332 1333 /*@ int ************************************************************ */ 1334 int retval = 0; 1335 int res = 0; 1336 1337 /*@ buffers ******************************************************** */ 1338 char *tmp = NULL; 1339 char *curr_file = NULL; 1340 char *cf; 1341 1342 /*@ long ************************************************************ */ 1343 va_list ap; 1344 long long would_occupy; 1345 1346 assert(bkpinfo != NULL); 1347 would_occupy = space_occupied_by_cd(bkpinfo->scratchdir); 1348 va_start(ap, files_to_add); // initialize the variable arguments 1349 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) { 1350 if (!cf) { 1351 continue; 1352 } 1353 mr_asprintf(curr_file, "%s", cf); 1354 if (!does_file_exist(curr_file)) { 1355 log_msg(1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file); 1356 } else { 1357 log_msg(8, "Trying to add file %s to CD", curr_file); 1358 would_occupy += length_of_file(curr_file) / 1024; 1359 } 1360 mr_free(curr_file); 1361 } 1362 va_end(ap); 1363 1364 if (bkpinfo->media_size <= 0) { 1365 fatal_error("move_files_to_cd() - unknown media size"); 1366 } 1367 if (would_occupy / 1024 > bkpinfo->media_size) { 1368 res = write_iso_and_go_on(FALSE); /* FALSE because this is not the last CD we'll write */ 1369 retval += res; 1370 if (res) { 1371 log_msg(1, "WARNING - write_iso_and_go_on returned an error"); 1372 } 1373 } 1374 1375 va_start(ap, files_to_add); // initialize the variable arguments 1376 for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) { 1377 if (!cf) { 1378 continue; 1379 } 1380 mr_asprintf(curr_file, "%s", cf); 1381 1382 mr_asprintf(tmp, "mv -f %s %s/archives/", curr_file, bkpinfo->scratchdir); 1383 mr_free(curr_file); 1384 res = run_program_and_log_output(tmp, 5); 1385 retval += res; 1386 if (res) { 1387 log_msg(1, "(move_files_to_cd) '%s' failed", tmp); 1388 } else { 1389 log_msg(8, "Moved %s to CD OK", tmp); 1390 } 1391 mr_free(tmp); 1392 } 1393 va_end(ap); 1394 1395 if (retval) { 1396 log_msg(1, 1397 "Warning - errors occurred while I was adding files to CD dir"); 1398 } 1399 return (retval); 1400 } 1401 1402 1403 1404 /** 1405 * @addtogroup LLarchiveGroup 1406 * @{ 1407 */ 1408 /** 1409 * Function pointer to an appropriate @c move_files_to_stream routine. 1410 * You can set this to your own function (for example, one to 1411 * transfer files over the network) or leave it as is. 1412 */ 1413 int (*move_files_to_stream) (char *, ...) = 1414 _move_files_to_stream; 1415 1416 1417 /** 1418 * Function pointer to an appropriate @c move_files_to_cd routine. 1419 * You can set this to your own function (for example, one to 1420 * transfer files over the network) or leave it as is. 1421 */ 1422 int (*move_files_to_cd) (char *, ...) = 1423 _move_files_to_cd; 1424 1425 1426 /** 1427 * Set the <tt>N</tt>th bit of @c array to @c true_or_false. 1428 * @param array The bit array (as a @c char pointer). 1429 * @param N The bit number to set or reset. 1430 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N. 1431 * @see get_bit_N_of_array 1432 */ 1433 void set_bit_N_of_array(char *array, int N, bool true_or_false) 1434 { 1435 int bit_number; 1436 int mask, orig_val, to_add; 1437 int element_number; 1438 1439 assert(array != NULL); 1440 1441 element_number = N / 8; 1442 bit_number = N % 8; 1443 to_add = (1 << bit_number); 1444 mask = 255 - to_add; 1445 orig_val = array[element_number] & mask; 1446 // log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val); 1447 if (true_or_false) { 1448 array[element_number] = orig_val | to_add; 1449 } 1450 } 1451 1452 1453 /** 1454 * Get the <tt>N</tt>th bit of @c array. 1455 * @param array The bit-array (as a @c char pointer). 1456 * @param N The number of the bit you want. 1457 * @return TRUE (bit is set) or FALSE (bit is not set). 1458 * @see set_bit_N_of_array 1459 * @ingroup utilityGroup 1460 */ 1461 bool get_bit_N_of_array(char *array, int N) 1462 { 1463 int element_number; 1464 int bit_number; 1465 int mask; 1466 1467 element_number = N / 8; 1468 bit_number = N % 8; 1469 mask = 1 << bit_number; 1470 if (array[element_number] & mask) { 1471 return (TRUE); 1472 } else { 1473 return (FALSE); 1474 } 1475 } 1476 1477 1478 1479 /** 1480 * Chop up @c filename. 1481 * @param bkpinfo The backup information structure. Fields used: 1482 * - @c backup_media_type 1483 * - @c compression_level 1484 * - @c optimal_set_size 1485 * - @c tmpdir 1486 * - @c use_lzo 1487 * - @c zip_exe 1488 * - @c zip_suffix 1489 * 1490 * @param biggie_filename The file to chop up. 1491 * @param ntfsprog_fifo The FIFO to ntfsclone if this is an imagedev, NULL otherwise. 1492 * @param biggie_file_number The sequence number of this biggie file (starting from 0). 1493 * @param noof_biggie_files The number of biggie files there are total. 1494 * @return The number of errors encountered (0 for success) 1495 * @see make_slices_and_images 1496 * @ingroup LLarchiveGroup 1497 */ 1498 int slice_up_file_etc(char *biggie_filename, char *ntfsprog_fifo, long biggie_file_number, long noof_biggie_files, bool use_ntfsprog) { 1499 1500 /*@ buffers ************************************************** */ 1501 char *tmp = NULL; 1502 char *checksum_line = NULL; 1503 char *command = NULL; 1504 char *tempblock = NULL; 1505 char *curr_slice_fname_uncompressed = NULL; 1506 char *curr_slice_fname_compressed = NULL; 1507 char *file_to_archive = NULL; 1508 char *file_to_openin = NULL; 1509 /*@ pointers ************************************************** */ 1510 char *pB = NULL; 1511 FILE *fin = NULL; 1512 FILE *fout = NULL; 1513 1514 /*@ bool ****************************************************** */ 1515 bool finished = FALSE; 1516 1517 /*@ long ****************************************************** */ 1518 size_t blksize = (size_t)0; 1519 long slice_num = 0L; 1520 long i = 0L; 1521 bool should_I_compress_slices = TRUE; 1522 char *suffix = NULL; // for compressed slices 1523 1524 /*@ long long ************************************************** */ 1525 off_t totalread = (off_t)0; 1526 off_t totallength = (off_t)0; 1527 1528 /*@ int ******************************************************** */ 1529 int retval = 0; 1530 int res = 0; 1531 1532 /*@ structures ************************************************** */ 1533 struct s_filename_and_lstat_info biggiestruct; 1534 1535 assert(bkpinfo != NULL); 1536 assert_string_is_neither_NULL_nor_zerolength(biggie_filename); 1537 1538 biggiestruct.for_backward_compatibility = '\n'; 1539 biggiestruct.use_ntfsprog = use_ntfsprog; 1540 if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0) { 1541 mr_asprintf(suffix, "%s", ""); 1542 should_I_compress_slices = FALSE; 1543 } else { 1544 mr_asprintf(suffix, "%s", bkpinfo->zip_suffix); 1545 should_I_compress_slices = TRUE; 1546 } 1547 1548 if (bkpinfo->optimal_set_size < 999L) { 1549 fatal_error("bkpinfo->optimal_set_size is insanely small"); 1550 } 1551 1552 if (ntfsprog_fifo) { 1553 file_to_openin = ntfsprog_fifo; 1554 mr_asprintf(checksum_line, "IGNORE"); 1555 log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename); 1556 if ((tmp = find_home_of_exe("ntfsresize")) == NULL) { 1557 fatal_error("ntfsresize not found"); 1558 } 1559 mr_asprintf(command, "%s --force --info %s|grep '^You might resize at '|cut -d' ' -f5", tmp, biggie_filename); 1560 mr_free(tmp); 1561 log_it("command = %s", command); 1562 tmp = call_program_and_get_last_line_of_output(command); 1563 mr_free(command); 1564 log_it("res of it = %s", tmp); 1565 totallength = (off_t)atoll(tmp); 1566 mr_free(tmp); 1567 } else { 1568 file_to_openin = biggie_filename; 1569 if (strchr(biggie_filename,'\'') != NULL) { 1570 mr_asprintf(command, "md5sum \"%s\"", biggie_filename); 1571 } else { 1572 mr_asprintf(command, "md5sum '%s'", biggie_filename); 1573 } 1574 if (!(fin = popen(command, "r"))) { 1575 log_OS_error("Unable to popen-in command"); 1576 mr_free(suffix); 1577 return (1); 1578 } 1579 mr_free(command); 1580 mr_getline(checksum_line, fin); 1581 pclose(fin); 1582 totallength = length_of_file(biggie_filename); 1583 } 1584 lstat(biggie_filename, &biggiestruct.properties); 1585 strcpy(biggiestruct.filename, biggie_filename); 1586 pB = strchr(checksum_line, ' '); 1587 if (!pB) { 1588 pB = strchr(checksum_line, '\t'); 1589 } 1590 if (pB) { 1591 *pB = '\0'; 1592 } 1593 strcpy(biggiestruct.checksum, checksum_line); 1594 mr_free(checksum_line); 1595 1596 mr_asprintf(tmp, "%s", slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, "")); 1597 fout = fopen(tmp, "w"); 1598 if (fout == NULL) { 1599 log_msg(1, "Unable to open and write to %s", tmp); 1600 mr_free(tmp); 1601 mr_free(suffix); 1602 return (1); 1603 } 1604 res = fwrite((void *) &biggiestruct, 1, sizeof(biggiestruct), fout); 1605 paranoid_fclose(fout); 1606 mr_free(tmp); 1607 1608 log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin); 1609 if (!(fin = fopen(file_to_openin, "r"))) { 1610 log_OS_error("Unable to openin biggie_filename"); 1611 log_to_screen("Cannot archive bigfile '%s': not found", biggie_filename); 1612 1613 mr_free(suffix); 1614 return (1); 1615 } 1616 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1617 res = move_files_to_stream(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL); 1618 } else { 1619 res = move_files_to_cd(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL); 1620 } 1621 i = bkpinfo->optimal_set_size / 256L; 1622 if (!(tempblock = (char *) malloc(256 * 1024))) { 1623 fatal_error("malloc error 256*1024"); 1624 } 1625 for (slice_num = 1; !finished; slice_num++) { 1626 mr_asprintf(curr_slice_fname_uncompressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, "")); 1627 mr_asprintf(curr_slice_fname_compressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, suffix)); 1628 1629 tmp = percent_media_full_comment(); 1630 update_progress_form(tmp); 1631 mr_free(tmp); 1632 1633 if (!(fout = fopen(curr_slice_fname_uncompressed, "w"))) { 1634 log_OS_error(curr_slice_fname_uncompressed); 1635 mr_free(suffix); 1636 return (1); 1637 } 1638 if ((i == bkpinfo->optimal_set_size / 256L) && (totalread < (off_t)1.1 * totallength)) { 1639 for (i = 0L; i < (bkpinfo->optimal_set_size / 256L); i++) { 1640 blksize = fread(tempblock, 1, 256 * 1024, fin); 1641 if (blksize > (size_t)0) { 1642 totalread = totalread + (off_t)blksize; 1643 res = fwrite(tempblock, 1, blksize, fout); 1644 } else { 1645 break; 1646 } 1647 } 1648 } else { 1649 i = 0L; 1650 } 1651 paranoid_fclose(fout); 1652 if (i > 0L) // length_of_file (curr_slice_fname_uncompressed) 1653 { 1654 if (!does_file_exist(curr_slice_fname_uncompressed)) { 1655 log_msg(2, "Warning - '%s' doesn't exist. How can I compress slice?", curr_slice_fname_uncompressed); 1656 } 1657 if (should_I_compress_slices && bkpinfo->compression_level > 0) { 1658 mr_asprintf(command, "%s -%d %s", bkpinfo->zip_exe, bkpinfo->compression_level, curr_slice_fname_uncompressed); 1659 log_msg(2, command); 1660 if ((res = system(command))) { 1661 log_OS_error(command); 1662 } 1663 // did_I_compress_slice = TRUE; 1664 } else { 1665 mr_asprintf(command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE); 1666 res = 0; // don't do it :) 1667 // did_I_compress_slice = FALSE; 1668 } 1669 mr_free(command); 1670 1671 retval += res; 1672 if (res) { 1673 log_msg(2, "Failed to compress the slice"); 1674 } 1675 if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed)) { 1676 unlink(curr_slice_fname_uncompressed); 1677 } 1678 if (res) { 1679 mr_asprintf(tmp, "Problem with slice # %ld", slice_num); 1680 } else { 1681 mr_asprintf(tmp, "%s - Bigfile #%ld, slice #%ld compressed OK ", biggie_filename, biggie_file_number + 1, slice_num); 1682 } 1683 if (!g_text_mode) { 1684 newtDrawRootText(0, g_noof_rows - 2, tmp); 1685 newtRefresh(); 1686 } else { 1687 log_msg(2, tmp); 1688 } 1689 mr_free(tmp); 1690 1691 mr_asprintf(file_to_archive, "%s", curr_slice_fname_compressed); 1692 g_current_progress++; 1693 } else { /* if i==0 then ... */ 1694 finished = TRUE; 1695 mr_asprintf(file_to_archive, "%s", curr_slice_fname_uncompressed); 1696 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1697 break; 1698 } 1699 } 1700 mr_free(curr_slice_fname_uncompressed); 1701 mr_free(curr_slice_fname_compressed); 1702 1703 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1704 register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive); 1705 maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive); 1706 res = move_files_to_stream(file_to_archive, NULL); 1707 } else { 1708 res = move_files_to_cd(file_to_archive, NULL); 1709 } 1710 mr_free(file_to_archive); 1711 1712 retval += res; 1713 if (res) { 1714 log_to_screen("Failed to add slice %ld of bigfile %ld to scratchdir", slice_num, biggie_file_number + 1); 1715 fatal_error("Hard disk full. You should have bought a bigger one."); 1716 } 1717 } 1718 mr_free(tempblock); 1719 mr_free(suffix); 1720 paranoid_fclose(fin); 1721 mr_asprintf(tmp, "Sliced bigfile #%ld", biggie_file_number + 1); 1722 if (retval) { 1723 mr_strcat(tmp, "...FAILED"); 1724 } else { 1725 mr_strcat(tmp, "...OK!"); 1726 } 1727 log_msg(1, tmp); 1728 mr_free(tmp); 603 1729 604 1730 return (retval); … … 708 1834 mr_free(sz_devfile); 709 1835 fatal_error("Fork failure"); 1836 break; 710 1837 case 0: 711 1838 log_msg(2, "CHILD - fip - calling feed_into_ntfsprog(%s, %s)", bigfile_fname, sz_devfile); … … 855 1982 return (retval); 856 1983 } 1984 /* @} - end of LLarchiveGroup */ 1985 1986 /** 1987 * Main function for each @c afio thread. 1988 * @param inbuf A transfer block containing: 1989 * - @c p_last_set_archived: [offset 0] pointer to an @c int 1990 * containing the last set archived. 1991 * - @c p_archival_threads_running: [offset 4] pointer to an @c int 1992 * containing the number of archival threads currently running. 1993 * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing 1994 * the next set that should be archived. 1995 * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a 1996 * bit array, where each bit corresponds to a filelist (1=needs 1997 * to be archived, 0=archived). 1998 * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information 1999 * structure. Fields used: 2000 * - @c tmpdir 2001 * - @c zip_suffix 2002 * 2003 * Any of the above may be modified by the caller at any time. 2004 * 2005 * @bug Assumes @c int pointers are 4 bytes. 2006 * @see archive_this_fileset 2007 * @see make_afioballs_and_images 2008 * @return NULL, always. 2009 * @ingroup LLarchiveGroup 2010 */ 2011 void *create_afio_files_in_background(void *inbuf) 2012 { 2013 long int archiving_set_no = 0L; 2014 char *archiving_filelist_fname = NULL; 2015 char *archiving_afioball_fname = NULL; 2016 char *curr_xattr_list_fname = NULL; 2017 char *curr_acl_list_fname = NULL; 2018 2019 char *tmp = NULL; 2020 int res = 0, retval = 0; 2021 int *p_archival_threads_running; 2022 int *p_last_set_archived; 2023 int *p_next_set_to_archive; 2024 char *p_list_of_fileset_flags; 2025 int this_thread_no = g_current_thread_no++; 2026 2027 p_last_set_archived = (int *) inbuf; 2028 p_archival_threads_running = (int *) (inbuf + 4); 2029 p_next_set_to_archive = (int *) (inbuf + 8); 2030 p_list_of_fileset_flags = (char *) (inbuf + 12); 2031 2032 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L); 2033 2034 while (does_file_exist(archiving_filelist_fname)) { 2035 if (g_exiting) { 2036 mr_free(archiving_filelist_fname); 2037 fatal_error("Execution run aborted (pthread)"); 2038 } 2039 if (archiving_set_no >= MAX_NOOF_SETS_HERE) { 2040 mr_free(archiving_filelist_fname); 2041 fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please."); 2042 } 2043 if (!semaphore_p()) { 2044 log_msg(3, "P sem failed (pid=%d)", (int) getpid()); 2045 mr_free(archiving_filelist_fname); 2046 fatal_error("Cannot get semaphore P"); 2047 } 2048 if (archiving_set_no < *p_next_set_to_archive) { 2049 archiving_set_no = *p_next_set_to_archive; 2050 } 2051 *p_next_set_to_archive = *p_next_set_to_archive + 1; 2052 if (!semaphore_v()) { 2053 mr_free(archiving_filelist_fname); 2054 fatal_error("Cannot get semaphore V"); 2055 } 2056 2057 /* backup this set of files */ 2058 mr_asprintf(archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no, bkpinfo->zip_suffix); 2059 mr_free(archiving_filelist_fname); 2060 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 2061 if (!does_file_exist(archiving_filelist_fname)) { 2062 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); 2063 mr_free(archiving_afioball_fname); 2064 break; 2065 } 2066 2067 mr_asprintf(tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no - ARCH_BUFFER_NUM, bkpinfo->zip_suffix); 2068 if (does_file_exist(tmp)) { 2069 log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no); 2070 while (does_file_exist(tmp)) { 2071 sleep(1); 2072 } 2073 log_msg(4, "[%d] - continuing", getpid()); 2074 } 2075 mr_free(tmp); 2076 2077 log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 2078 2079 if (g_getfattr) { 2080 mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 2081 get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname); 2082 mr_free(curr_xattr_list_fname); 2083 } 2084 if (g_getfacl) { 2085 mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 2086 get_acl_list(archiving_filelist_fname, curr_acl_list_fname); 2087 mr_free(curr_acl_list_fname); 2088 } 2089 2090 log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 2091 res = archive_this_fileset(archiving_filelist_fname, archiving_afioball_fname, archiving_set_no); 2092 mr_free(archiving_afioball_fname); 2093 2094 retval += res; 2095 2096 if (res) { 2097 log_to_screen("Errors occurred while archiving set %ld. Please review logs.", archiving_set_no); 2098 } 2099 2100 if (!semaphore_p()) { 2101 mr_free(archiving_filelist_fname); 2102 fatal_error("Cannot get semaphore P"); 2103 } 2104 2105 set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5); 2106 2107 if (*p_last_set_archived < archiving_set_no) { 2108 *p_last_set_archived = archiving_set_no; 2109 } // finished archiving this one 2110 2111 if (!semaphore_v()) { 2112 mr_free(archiving_filelist_fname); 2113 fatal_error("Cannot get semaphore V"); 2114 } 2115 log_msg(4, "%s[%d:%d] - archived %d OK", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no); 2116 archiving_set_no++; 2117 2118 mr_free(archiving_filelist_fname); 2119 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no); 2120 } 2121 mr_free(archiving_filelist_fname); 2122 2123 if (!semaphore_p()) { 2124 fatal_error("Cannot get semaphore P"); 2125 } 2126 (*p_archival_threads_running)--; 2127 if (!semaphore_v()) { 2128 fatal_error("Cannot get semaphore V"); 2129 } 2130 log_msg(3, "%s[%d:%d] - exiting", FORTY_SPACES, getpid(), this_thread_no); 2131 pthread_exit(NULL); 2132 } 2133 857 2134 858 2135 /** … … 1859 3136 1860 3137 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_array1868 */1869 void set_bit_N_of_array(char *array, int N, bool true_or_false)1870 {1871 int bit_number;1872 int mask, orig_val, to_add;1873 int element_number;1874 1875 assert(array != NULL);1876 1877 element_number = N / 8;1878 bit_number = N % 8;1879 to_add = (1 << bit_number);1880 mask = 255 - to_add;1881 orig_val = array[element_number] & mask;1882 // log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);1883 if (true_or_false) {1884 array[element_number] = orig_val | to_add;1885 }1886 }1887 1888 1889 1890 /**1891 * Maximum number of filesets allowed in this function.1892 */1893 #define MAX_NOOF_SETS_HERE 327671894 1895 /**1896 * Offset of the bkpinfo pointer (in bytes) from the1897 * 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 int1905 * containing the last set archived.1906 * - @c p_archival_threads_running: [offset 4] pointer to an @c int1907 * containing the number of archival threads currently running.1908 * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing1909 * the next set that should be archived.1910 * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a1911 * bit array, where each bit corresponds to a filelist (1=needs1912 * to be archived, 0=archived).1913 * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information1914 * structure. Fields used:1915 * - @c tmpdir1916 * - @c zip_suffix1917 *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_fileset1922 * @see make_afioballs_and_images1923 * @return NULL, always.1924 * @ingroup LLarchiveGroup1925 */1926 void *create_afio_files_in_background(void *inbuf)1927 {1928 long int archiving_set_no = 0L;1929 char *archiving_filelist_fname = NULL;1930 char *archiving_afioball_fname = NULL;1931 char *curr_xattr_list_fname = NULL;1932 char *curr_acl_list_fname = NULL;1933 1934 char *tmp = NULL;1935 int res = 0, retval = 0;1936 int *p_archival_threads_running;1937 int *p_last_set_archived;1938 int *p_next_set_to_archive;1939 char *p_list_of_fileset_flags;1940 int this_thread_no = g_current_thread_no++;1941 1942 p_last_set_archived = (int *) inbuf;1943 p_archival_threads_running = (int *) (inbuf + 4);1944 p_next_set_to_archive = (int *) (inbuf + 8);1945 p_list_of_fileset_flags = (char *) (inbuf + 12);1946 1947 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);1948 1949 while (does_file_exist(archiving_filelist_fname)) {1950 if (g_exiting) {1951 mr_free(archiving_filelist_fname);1952 fatal_error("Execution run aborted (pthread)");1953 }1954 if (archiving_set_no >= MAX_NOOF_SETS_HERE) {1955 mr_free(archiving_filelist_fname);1956 fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please.");1957 }1958 if (!semaphore_p()) {1959 log_msg(3, "P sem failed (pid=%d)", (int) getpid());1960 mr_free(archiving_filelist_fname);1961 fatal_error("Cannot get semaphore P");1962 }1963 if (archiving_set_no < *p_next_set_to_archive) {1964 archiving_set_no = *p_next_set_to_archive;1965 }1966 *p_next_set_to_archive = *p_next_set_to_archive + 1;1967 if (!semaphore_v()) {1968 mr_free(archiving_filelist_fname);1969 fatal_error("Cannot get semaphore V");1970 }1971 1972 /* backup this set of files */1973 mr_asprintf(archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no, bkpinfo->zip_suffix);1974 mr_free(archiving_filelist_fname);1975 mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);1976 if (!does_file_exist(archiving_filelist_fname)) {1977 log_msg(3, "%s[%d:%d] - well, I would archive %d, except that it doesn't exist. I'll stop now.", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);1978 mr_free(archiving_afioball_fname);1979 break;1980 }1981 1982 mr_asprintf(tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no - ARCH_BUFFER_NUM, bkpinfo->zip_suffix);1983 if (does_file_exist(tmp)) {1984 log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no);1985 while (does_file_exist(tmp)) {1986 sleep(1);1987 }1988 log_msg(4, "[%d] - continuing", getpid());1989 }1990 mr_free(tmp);1991 1992 log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);1993 1994 if (g_getfattr) {1995 mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);1996 get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname);1997 mr_free(curr_xattr_list_fname);1998 }1999 if (g_getfacl) {2000 mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);2001 get_acl_list(archiving_filelist_fname, curr_acl_list_fname);2002 mr_free(curr_acl_list_fname);2003 }2004 2005 log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);2006 res = archive_this_fileset(archiving_filelist_fname, archiving_afioball_fname, archiving_set_no);2007 mr_free(archiving_afioball_fname);2008 2009 retval += res;2010 2011 if (res) {2012 log_to_screen("Errors occurred while archiving set %ld. Please review logs.", archiving_set_no);2013 }2014 2015 if (!semaphore_p()) {2016 mr_free(archiving_filelist_fname);2017 fatal_error("Cannot get semaphore P");2018 }2019 2020 set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5);2021 2022 if (*p_last_set_archived < archiving_set_no) {2023 *p_last_set_archived = archiving_set_no;2024 } // finished archiving this one2025 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_array2056 * @ingroup utilityGroup2057 */2058 bool get_bit_N_of_array(char *array, int N)2059 {2060 int element_number;2061 int bit_number;2062 int mask;2063 2064 element_number = N / 8;2065 bit_number = N % 8;2066 mask = 1 << bit_number;2067 if (array[element_number] & mask) {2068 return (TRUE);2069 } else {2070 return (FALSE);2071 }2072 }2073 2074 2075 /**2076 * Move some files to the ISO scratch directory.2077 * This function moves files specified as parameters, into the directory2078 * @c bkpinfo->scratchdir, where the files that will be stored on the next2079 * CD are waiting.2080 *2081 * @param bkpinfo The backup information structure. Fields used:2082 * - @c media_size2083 * - @c scratchdir2084 * @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 exceed2087 * the capacity of the current CD,2088 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the2089 * scratchdir is emptied.2090 *2091 * @return The number of errors encountered (0 for success)2092 */2093 int _move_files_to_cd(char *files_to_add, ...)2094 {2095 2096 /*@ int ************************************************************ */2097 int retval = 0;2098 int res = 0;2099 2100 /*@ buffers ******************************************************** */2101 char *tmp = NULL;2102 char *curr_file = NULL;2103 char *cf;2104 2105 /*@ long ************************************************************ */2106 va_list ap;2107 long long would_occupy;2108 2109 assert(bkpinfo != NULL);2110 would_occupy = space_occupied_by_cd(bkpinfo->scratchdir);2111 va_start(ap, files_to_add); // initialize the variable arguments2112 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 arguments2139 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 to2172 * @c write_file_to_stream_from_file().2173 *2174 * @param files_to_add The files to copy to the tape stream.2175 * @warning The list of @c files_to_add must be terminated with @c NULL.2176 * @note Files may be split across multiple tapes if necessary.2177 *2178 * @return The number of errors encountered (0 for success)2179 */2180 int2181 _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 LLarchiveGroup2235 * @{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 to2240 * transfer files over the network) or leave it as is.2241 */2242 int (*move_files_to_stream) (char *, ...) =2243 _move_files_to_stream;2244 2245 2246 /**2247 * Function pointer to an appropriate @c move_files_to_cd routine.2248 * You can set this to your own function (for example, one to2249 * transfer files over the network) or leave it as is.2250 */2251 int (*move_files_to_cd) (char *, ...) =2252 _move_files_to_cd;2253 2254 2255 2256 /**2257 * @addtogroup LLarchiveGroup2258 * @{2259 */2260 2261 void pause_for_N_seconds(int how_long, char *msg)2262 {2263 int i;2264 open_evalcall_form(msg);2265 for (i = 0; i < how_long; i++) {2266 update_evalcall_form((int) ((100.0 / (float) (how_long) * i)));2267 sleep(1);2268 }2269 close_evalcall_form();2270 }2271 2272 2273 2274 2275 /**2276 * Create a USB image in @c destfile, from files in @c bkpinfo->scratchdir.2277 *2278 * @param bkpinfo The backup information structure. Fields used:2279 * - @c backup_media_type2280 * - @c nonbootable_backup2281 * - @c scratchdir2282 *2283 * @param destfile Where to put the generated USB image.2284 * @return The number of errors encountered (0 for success)2285 */2286 int make_usb_fs()2287 {2288 /*@ int ********************************************** */2289 int retval = 0;2290 int res;2291 2292 /*@ buffers ****************************************** */2293 char *tmp = NULL;2294 char *tmp1 = NULL;2295 char *result_sz = NULL;2296 char *message_to_screen = NULL;2297 char *old_pwd = NULL;2298 char *mds = NULL;2299 2300 assert(bkpinfo != NULL);2301 2302 log_msg(2, "make_usb_fs --- scratchdir=%s", bkpinfo->scratchdir);2303 old_pwd = mr_getcwd();2304 mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir);2305 run_program_and_log_output(tmp, FALSE);2306 mr_free(tmp);2307 if (chdir(bkpinfo->scratchdir)) {2308 // FIXME2309 }2310 2311 mds = media_descriptor_string(bkpinfo->backup_media_type);2312 mr_asprintf(message_to_screen, "Copying data to make %s #%d",mds, g_current_media_number);2313 mr_free(mds);2314 log_msg(1, message_to_screen);2315 2316 if (bkpinfo->media_device) {2317 mr_asprintf(tmp1, "%s1", bkpinfo->media_device);2318 } else {2319 mr_asprintf(tmp1, "");2320 }2321 if (is_this_device_mounted(tmp1)) {2322 log_msg(1, "USB device mounted. Remounting it at the right place");2323 mr_asprintf(tmp, "umount %s", tmp1);2324 run_program_and_log_output(tmp, FALSE);2325 mr_free(tmp);2326 }2327 mr_free(tmp1);2328 2329 log_msg(1, "Mounting USB device.");2330 mr_asprintf(tmp1, "%s/usb", bkpinfo->tmpdir);2331 mr_asprintf(tmp, "mkdir -p %s", tmp1);2332 run_program_and_log_output(tmp, FALSE);2333 mr_free(tmp);2334 2335 2336 /* Mindi always create one single parition on the USB dev */2337 mr_asprintf(tmp, "mount %s1 %s", bkpinfo->media_device, tmp1);2338 run_program_and_log_output(tmp, FALSE);2339 mr_free(tmp);2340 2341 if (bkpinfo->nonbootable_backup) {2342 log_msg(1, "Making nonbootable USB backup not implemented yet");2343 } else {2344 log_msg(1, "Making bootable backup");2345 2346 /* Command to execute */2347 mr_asprintf(tmp,"cd %s ; rm -fr %s/syslinux ; mv * %s", bkpinfo->scratchdir, tmp1, tmp1);2348 res = eval_call_to_make_USB(tmp, message_to_screen);2349 if (res) {2350 mr_asprintf(result_sz, "%s ...failed",tmp);2351 } else {2352 mr_asprintf(result_sz, "%s ...OK",tmp);2353 }2354 log_to_screen(result_sz);2355 mr_free(result_sz);2356 mr_free(tmp);2357 retval += res;2358 2359 /* Recreate the required structure under the scratch dir */2360 mr_asprintf(tmp,"mkdir %s/archive", bkpinfo->scratchdir);2361 run_program_and_log_output(tmp, FALSE);2362 mr_free(tmp);2363 }2364 paranoid_free(message_to_screen);2365 2366 /* Copy the current logfile - of course incomplete to the media */2367 mr_system("gzip -c9 %s > %s/archives/%s", MONDO_LOGFILE, tmp1, MONDO_LOGFILENAME);2368 paranoid_free(tmp1);2369 2370 if (is_this_device_mounted(bkpinfo->media_device)) {2371 mr_asprintf(tmp, "umount %s1", bkpinfo->media_device);2372 run_program_and_log_output(tmp, FALSE);2373 mr_free(tmp);2374 }2375 2376 if (chdir(old_pwd)) {2377 // FIXME2378 }2379 mr_free(old_pwd);2380 if (retval) {2381 log_msg(1, "WARNING - make_usb_fs returned an error");2382 }2383 return(retval);2384 }2385 2386 /**2387 * Make sure the user has a valid CD-R(W) in the CD drive.2388 * @param cd_dev Set to the CD-R(W) device checked.2389 * @param keep_looping If TRUE, keep pestering user until they insist2390 * or insert a correct CD; if FALSE, only check once.2391 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't).2392 */2393 int interrogate_disk_currently_in_cddrive(char *cd_dev,2394 bool keep_looping)2395 {2396 int res = 0;2397 char *bkp = NULL;2398 char *cdrecord = NULL;2399 2400 mr_asprintf(bkp, "%s", cd_dev);2401 if ((cd_dev = find_optical_device()) != NULL) {2402 if (!system("which cdrecord > /dev/null 2> /dev/null")) {2403 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);2404 } else if (!system("which dvdrecord > /dev/null 2> /dev/null")) {2405 mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);2406 } else {2407 log_msg(2, "Oh well. I guess I'll just pray then.");2408 }2409 if (cdrecord != NULL) {2410 if (!keep_looping) {2411 retract_CD_tray_and_defeat_autorun();2412 res = run_program_and_log_output(cdrecord, 5);2413 } else {2414 while ((res = run_program_and_log_output(cdrecord, 5))) {2415 retract_CD_tray_and_defeat_autorun();2416 if (ask_me_yes_or_no2417 ("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);2430 }2431 2432 2433 /**2434 * Asks the user to put a CD-R(W) in the drive.2435 * @param ask_for_one_if_more_than_this (unused)2436 * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.2437 */2438 void pause_and_ask_for_cdr(int ask_for_one_if_more_than_this, bool * pmountable) {2439 2440 /*@ buffers ********************************************* */2441 char *tmp = NULL;2442 char *cdrom_dev = NULL;2443 char *cd_dev = NULL;2444 char *our_serial_str = NULL;2445 bool ok_go_ahead_burn_it;2446 int cd_number = -1;2447 int attempt_to_mount_returned_this = 999;2448 char *mtpt = NULL;2449 char *szcdno = NULL;2450 char *szserfname = NULL;2451 char *szunmount = NULL;2452 char *mds = NULL;2453 2454 malloc_string(cd_dev);2455 2456 mds = media_descriptor_string(g_backup_media_type);2457 log_to_screen("I am about to burn %s #%d", mds, g_current_media_number);2458 mr_free(mds);2459 if (g_current_media_number < ask_for_one_if_more_than_this) {2460 return;2461 }2462 log_to_screen("Scanning CD-ROM drive...");2463 mr_asprintf(mtpt, "%s/cd.mtpt", bkpinfo->tmpdir);2464 make_hole_for_dir(mtpt);2465 2466 gotos_make_me_puke:2467 ok_go_ahead_burn_it = TRUE;2468 mr_free(cdrom_dev);2469 if ((cdrom_dev = find_optical_device()) != NULL) {2470 /* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird2471 log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );2472 retract_CD_tray_and_defeat_autorun();2473 */2474 mr_asprintf(tmp, "umount %s", cdrom_dev);2475 run_program_and_log_output(tmp, 1);2476 mr_asprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);2477 mr_asprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);2478 mr_asprintf(szunmount, "umount %s", mtpt);2479 cd_number = -1;2480 mr_asprintf(tmp, "mount %s %s", cdrom_dev, mtpt);2481 mr_asprintf(our_serial_str, "%s", "");2482 attempt_to_mount_returned_this = run_program_and_log_output(tmp, 1);2483 mr_free(tmp);2484 2485 if (attempt_to_mount_returned_this) {2486 log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);2487 log_to_screen("If there's a CD/DVD in the drive, it's blank.");2488 } else if (!does_file_exist(szcdno) || !does_file_exist(szserfname)) {2489 mds = media_descriptor_string(g_backup_media_type);2490 log_to_screen("%s has data on it but it's probably not a Mondo CD.", mds);2491 mr_free(mds);2492 } else {2493 mds = media_descriptor_string(g_backup_media_type);2494 log_to_screen("%s found in drive. It's a Mondo disk.", mds);2495 mr_free(mds);2496 2497 cd_number = atoi(last_line_of_file(szcdno));2498 mr_asprintf(tmp, "cat %s 2> /dev/null", szserfname);2499 mr_free(our_serial_str);2500 our_serial_str = call_program_and_get_last_line_of_output(tmp);2501 mr_free(tmp);2502 // FIXME - should be able to use last_line_of_file(), surely?2503 }2504 mr_free(szcdno);2505 mr_free(szserfname);2506 2507 run_program_and_log_output(szunmount, 1);2508 mr_free(szunmount);2509 2510 log_msg(2, "paafcd: cd_number = %d", cd_number);2511 log_msg(2, "our serial str = %s; bkpinfo->serial_string = %s", our_serial_str, bkpinfo->serial_string);2512 if (cd_number > 0 && !strcmp(our_serial_str, bkpinfo->serial_string)) {2513 mds = media_descriptor_string(g_backup_media_type);2514 log_msg(2, "This %s is part of this backup set!", mds);2515 ok_go_ahead_burn_it = FALSE;2516 if (cd_number == g_current_media_number - 1) {2517 log_to_screen("I think you've left the previous %s in the drive.", mds);2518 } else {2519 log_to_screen("Please remove this %s. It is part of the backup set you're making now.", mds);2520 }2521 mr_free(mds);2522 2523 } else {2524 log_to_screen("...but not part of _our_ backup set.");2525 }2526 mr_free(our_serial_str);2527 } else {2528 mds = media_descriptor_string(g_backup_media_type);2529 log_msg(2,2530 "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", mds);2531 if (interrogate_disk_currently_in_cddrive(cd_dev, FALSE)) {2532 ok_go_ahead_burn_it = FALSE;2533 log_to_screen("There isn't a writable %s in the drive.", mds);2534 }2535 mr_free(mds);2536 }2537 2538 if (!ok_go_ahead_burn_it) {2539 if (!bkpinfo->please_dont_eject) {2540 eject_device(cdrom_dev);2541 }2542 mds = media_descriptor_string(g_backup_media_type);2543 mr_asprintf(tmp, "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.", mds, g_current_media_number, mds);2544 mr_free(mds);2545 2546 popup_and_OK(tmp);2547 mr_free(tmp);2548 goto gotos_make_me_puke;2549 } else {2550 log_msg(2, "paafcd: OK, going ahead and burning it.");2551 }2552 2553 mds = media_descriptor_string(g_backup_media_type);2554 log_msg(2, "paafcd: OK, I assume I have a blank/reusable %s in the drive...", mds);2555 2556 log_to_screen("Proceeding w/ %s in drive.", mds);2557 mr_free(mds);2558 2559 mr_free(cdrom_dev);2560 paranoid_free(cd_dev);2561 mr_free(mtpt);2562 if (pmountable) {2563 if (attempt_to_mount_returned_this) {2564 *pmountable = FALSE;2565 } else {2566 *pmountable = TRUE;2567 }2568 }2569 2570 }2571 2572 2573 /**2574 * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir.2575 *2576 * @param bkpinfo The backup information structure. Fields used:2577 * - @c backup_media_type2578 * - @c call_after_iso2579 * - @c call_before_iso2580 * - @c call_burn_iso2581 * - @c call_make_iso2582 * - @c make_cd_use_lilo2583 * - @c manual_cd_tray2584 * - @c nonbootable_backup2585 * - @c scratchdir2586 *2587 * @param destfile Where to put the generated ISO image.2588 * @return The number of errors encountered (0 for success)2589 */2590 int make_iso_fs(char *destfile) {2591 /*@ int ********************************************** */2592 int retval = 0;2593 int res;2594 2595 /*@ buffers ****************************************** */2596 char *tmp = NULL;2597 char *old_pwd = NULL;2598 char *result_sz = NULL;2599 char *message_to_screen = NULL;2600 char *sz_blank_disk = NULL;2601 char *isofs_cmd = NULL;2602 char *full_isofs_cmd = NULL;2603 char *mds = NULL;2604 char *uefistr = NULL;2605 bool cd_is_mountable;2606 2607 assert(bkpinfo != NULL);2608 assert_string_is_neither_NULL_nor_zerolength(destfile);2609 2610 if (bkpinfo->backup_media_type == iso && bkpinfo->manual_cd_tray) {2611 popup_and_OK("Please insert new media and press Enter.");2612 }2613 2614 log_msg(2, "make_iso_fs --- scratchdir=%s --- destfile=%s", bkpinfo->scratchdir, destfile);2615 old_pwd = mr_getcwd();2616 mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir);2617 run_program_and_log_output(tmp, FALSE);2618 mr_free(tmp);2619 2620 if (chdir(bkpinfo->scratchdir)) {2621 // FIXME2622 }2623 2624 if (bkpinfo->call_before_iso != NULL) {2625 mr_asprintf(message_to_screen, "Running pre-ISO call for CD#%d", g_current_media_number);2626 res = eval_call_to_make_ISO(bkpinfo->call_before_iso, destfile, g_current_media_number, message_to_screen);2627 if (res) {2628 mr_strcat(message_to_screen, "...failed");2629 } else {2630 mr_strcat(message_to_screen, "...OK");2631 }2632 log_to_screen(message_to_screen);2633 paranoid_free(message_to_screen);2634 2635 retval += res;2636 }2637 2638 if (bkpinfo->call_make_iso != NULL) {2639 log_msg(2, "bkpinfo->call_make_iso = %s", bkpinfo->call_make_iso);2640 mds = media_descriptor_string(bkpinfo->backup_media_type);2641 mr_asprintf(message_to_screen, "Making an ISO (%s #%d)", mds, g_current_media_number);2642 mr_free(mds);2643 2644 pause_and_ask_for_cdr(2, &cd_is_mountable); /* if g_current_media_number >= 2 then pause & ask */2645 if (retval) {2646 log_to_screen2647 ("Serious error(s) occurred already. I shan't try to write to media.");2648 } else {2649 res =2650 eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen);2651 if (res) {2652 log_to_screen("%s...failed to write", message_to_screen);2653 } else {2654 log_to_screen("%s...OK", message_to_screen);2655 mr_asprintf(tmp, "tail -n10 %s | grep -F ':-('", MONDO_LOGFILE);2656 if (!run_program_and_log_output(tmp, 1)) {2657 log_to_screen2658 ("Despite nonfatal errors, growisofs confirms the write was successful.");2659 }2660 mr_free(tmp);2661 }2662 retval += res;2663 #ifdef DVDRWFORMAT2664 mr_asprintf(tmp, "tail -n8 %s | grep 'blank=full.*dvd-compat.*DAO'", MONDO_LOGFILE);2665 if (g_backup_media_type == dvd2666 && (res || !run_program_and_log_output(tmp, 1))) {2667 log_to_screen2668 ("Failed to write to disk. I shall blank it and then try again.");2669 sleep(5);2670 /* reset error counter before trying to blank DVD */2671 retval -= res;2672 sync();2673 pause_for_N_seconds(5, "Letting DVD drive settle");2674 2675 // dvd+rw-format --- OPTION 22676 if (!bkpinfo->please_dont_eject) {2677 log_to_screen("Ejecting media to clear drive status.");2678 eject_device(bkpinfo->media_device);2679 inject_device(bkpinfo->media_device);2680 }2681 pause_for_N_seconds(5, "Letting DVD drive settle");2682 if (bkpinfo->media_device) {2683 mr_asprintf(sz_blank_disk, "dvd+rw-format -force %s", bkpinfo->media_device);2684 } else {2685 mr_asprintf(sz_blank_disk, "dvd+rw-format");2686 }2687 log_msg(3, "sz_blank_disk = '%s'", sz_blank_disk);2688 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);2689 if (res) {2690 log_to_screen("Warning - format failed. (Was it a DVD-R?) Sleeping for 5 seconds to take a breath...");2691 pause_for_N_seconds(5, "Letting DVD drive settle... and trying again.");2692 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);2693 if (res) {2694 log_to_screen("Format failed a second time.");2695 }2696 } else {2697 log_to_screen2698 ("Format succeeded. Sleeping for 5 seconds to take a breath...");2699 }2700 mr_free(sz_blank_disk);2701 pause_for_N_seconds(5, "Letting DVD drive settle");2702 if (!bkpinfo->please_dont_eject) {2703 log_to_screen("Ejecting media to clear drive status.");2704 eject_device(bkpinfo->media_device);2705 inject_device(bkpinfo->media_device);2706 }2707 pause_for_N_seconds(5, "Letting DVD drive settle");2708 res = eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen);2709 retval += res;2710 if (!bkpinfo->please_dont_eject) {2711 log_to_screen("Ejecting media.");2712 eject_device(bkpinfo->media_device);2713 }2714 if (res) {2715 log_to_screen("Dagnabbit. It still failed.");2716 } else {2717 log_to_screen2718 ("OK, this time I successfully backed up to DVD.");2719 }2720 }2721 mr_free(tmp);2722 #endif2723 if (g_backup_media_type == dvd && !bkpinfo->please_dont_eject) {2724 eject_device(bkpinfo->media_device);2725 }2726 }2727 paranoid_free(message_to_screen);2728 } else {2729 mds = media_descriptor_string(bkpinfo->backup_media_type);2730 mr_asprintf(message_to_screen, "Running mkisofs to make %s #%d", mds, g_current_media_number);2731 log_msg(1, message_to_screen);2732 mr_asprintf(result_sz, "Call to mkisofs to make ISO (%s #%d) ", mds, g_current_media_number);2733 mr_free(mds);2734 if ((tmp = find_home_of_exe("xorriso")) != NULL) {2735 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_XORRISO_OPT);2736 } else if ((tmp = find_home_of_exe("genisoimage")) != NULL) {2737 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_GENISOIMAGE_OPT);2738 } else if ((tmp = find_home_of_exe("mkisofs")) != NULL) {2739 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_MKISOFS_OPT);2740 } else if ((tmp = find_home_of_exe("wodim")) != NULL) {2741 mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_WODIM_OPT);2742 } else {2743 fatal_error("Unable to find a command to create ISO among xorriso, genisoimage, mksiofs or wodim, please install one");2744 }2745 mr_free(tmp);2746 if (bkpinfo->nonbootable_backup) {2747 log_msg(1, "Making nonbootable backup");2748 mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS);2749 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);2750 mr_free(full_isofs_cmd);2751 } else {2752 log_msg(1, "Making bootable backup");2753 2754 #ifdef __FreeBSD__2755 bkpinfo->make_cd_use_lilo = TRUE;2756 #endif2757 2758 2759 log_msg(1, "make_cd_use_lilo is actually %d", bkpinfo->make_cd_use_lilo);2760 if (bkpinfo->make_cd_use_lilo) {2761 log_msg(1, "make_cd_use_lilo = TRUE");2762 #ifdef __IA64__2763 log_msg(1, "IA64 --> elilo");2764 mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_ELILO);2765 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);2766 mr_free(full_isofs_cmd);2767 #else2768 log_msg(1, "Non-ia64 --> lilo");2769 mr_asprintf(full_isofs_cmd, "%s%s-b images/mindi-bootroot.img -c images/boot.cat -o '_ISO_' .",isofs_cmd,MONDO_MKISOFS);2770 // FIXME: fixed boot size probably wrong. lilo to be removed2771 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);2772 mr_free(full_isofs_cmd);2773 #endif2774 } else {2775 log_msg(1, "make_cd_use_lilo = FALSE");2776 log_msg(1, "Isolinux");2777 if (bkpinfo->boot_type == UEFI) {2778 if (strstr(isofs_cmd,"xorriso")) {2779 /* xorriso needs another '-' before efi-boot */2780 mr_asprintf(uefistr, "%s -%s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);2781 } else {2782 mr_asprintf(uefistr, "%s %s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);2783 }2784 } else {2785 mr_asprintf(uefistr, "%s",MONDO_MKISOFS_CMS);2786 }2787 mr_asprintf(full_isofs_cmd, "%s%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_SYSLINUX,uefistr);2788 mr_free(uefistr);2789 2790 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);2791 mr_free(full_isofs_cmd);2792 }2793 }2794 mr_free(isofs_cmd);2795 paranoid_free(message_to_screen);2796 2797 if (res) {2798 mr_strcat(result_sz, "...failed");2799 } else {2800 mr_strcat(result_sz, "...OK");2801 }2802 log_to_screen(result_sz);2803 paranoid_free(result_sz);2804 retval += res;2805 }2806 2807 if (bkpinfo->backup_media_type == cdr) {2808 if (is_this_device_mounted(bkpinfo->media_device)) {2809 log_msg(2, "Warning - %s mounted. I'm unmounting it before I burn to it.", bkpinfo->media_device);2810 mr_asprintf(tmp, "umount %s", bkpinfo->media_device);2811 run_program_and_log_output(tmp, FALSE);2812 mr_free(tmp);2813 }2814 }2815 2816 if (bkpinfo->call_burn_iso != NULL) {2817 log_msg(2, "bkpinfo->call_burn_iso = %s", bkpinfo->call_burn_iso);2818 mds = media_descriptor_string(bkpinfo->backup_media_type);2819 mr_asprintf(message_to_screen, "Burning %s #%d", mds, g_current_media_number);2820 mr_free(mds);2821 pause_and_ask_for_cdr(2, &cd_is_mountable);2822 res = eval_call_to_make_ISO(bkpinfo->call_burn_iso, destfile, g_current_media_number, message_to_screen);2823 if (res) {2824 mr_strcat(message_to_screen, "...failed");2825 } else {2826 mr_strcat(message_to_screen, "...OK");2827 }2828 log_to_screen(message_to_screen);2829 paranoid_free(message_to_screen);2830 2831 retval += res;2832 }2833 2834 if (bkpinfo->call_after_iso != NULL) {2835 mds = media_descriptor_string(bkpinfo->backup_media_type);2836 mr_asprintf(message_to_screen, "Running post-ISO call (%s #%d)", mds, g_current_media_number);2837 mr_free(mds);2838 res = eval_call_to_make_ISO(bkpinfo->call_after_iso, destfile, g_current_media_number, message_to_screen);2839 if (res) {2840 mr_strcat(message_to_screen, "...failed");2841 } else {2842 mr_strcat(message_to_screen, "...OK");2843 }2844 log_to_screen(message_to_screen);2845 paranoid_free(message_to_screen);2846 2847 retval += res;2848 }2849 2850 if (chdir(old_pwd)) {2851 // FIXME2852 }2853 mr_free(old_pwd);2854 if (retval) {2855 log_msg(1, "WARNING - make_iso_fs returned an error");2856 }2857 return (retval);2858 }2859 2860 2861 bool is_dev_an_NTFS_dev(char *bigfile_fname)2862 {2863 char *tmp = NULL;2864 char *command = NULL;2865 bool ret = TRUE;2866 2867 mr_asprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | strings | head -n1", bigfile_fname);2868 log_msg(1, "command = '%s'", command);2869 tmp = call_program_and_get_last_line_of_output(command);2870 mr_free(command);2871 2872 log_msg(1, "--> tmp = '%s'", tmp);2873 if (strstr(tmp, "NTFS")) {2874 log_it("TRUE");2875 ret = TRUE;2876 } else {2877 log_it("FALSE");2878 ret = FALSE;2879 }2880 mr_free(tmp);2881 return(ret);2882 }2883 2884 2885 /**2886 * Chop up @c filename.2887 * @param bkpinfo The backup information structure. Fields used:2888 * - @c backup_media_type2889 * - @c compression_level2890 * - @c optimal_set_size2891 * - @c tmpdir2892 * - @c use_lzo2893 * - @c zip_exe2894 * - @c zip_suffix2895 *2896 * @param biggie_filename The file to chop up.2897 * @param ntfsprog_fifo The FIFO to ntfsclone if this is an imagedev, NULL otherwise.2898 * @param biggie_file_number The sequence number of this biggie file (starting from 0).2899 * @param noof_biggie_files The number of biggie files there are total.2900 * @return The number of errors encountered (0 for success)2901 * @see make_slices_and_images2902 * @ingroup LLarchiveGroup2903 */2904 int slice_up_file_etc(char *biggie_filename, char *ntfsprog_fifo, long biggie_file_number, long noof_biggie_files, bool use_ntfsprog) {2905 2906 /*@ buffers ************************************************** */2907 char *tmp = NULL;2908 char *checksum_line = NULL;2909 char *command = NULL;2910 char *tempblock = NULL;2911 char *curr_slice_fname_uncompressed = NULL;2912 char *curr_slice_fname_compressed = NULL;2913 char *file_to_archive = NULL;2914 char *file_to_openin = NULL;2915 /*@ pointers ************************************************** */2916 char *pB = NULL;2917 FILE *fin = NULL;2918 FILE *fout = NULL;2919 2920 /*@ bool ****************************************************** */2921 bool finished = FALSE;2922 2923 /*@ long ****************************************************** */2924 size_t blksize = (size_t)0;2925 long slice_num = 0L;2926 long i = 0L;2927 bool should_I_compress_slices = TRUE;2928 char *suffix = NULL; // for compressed slices2929 2930 /*@ long long ************************************************** */2931 off_t totalread = (off_t)0;2932 off_t totallength = (off_t)0;2933 2934 /*@ int ******************************************************** */2935 int retval = 0;2936 int res = 0;2937 2938 /*@ structures ************************************************** */2939 struct s_filename_and_lstat_info biggiestruct;2940 2941 assert(bkpinfo != NULL);2942 assert_string_is_neither_NULL_nor_zerolength(biggie_filename);2943 2944 biggiestruct.for_backward_compatibility = '\n';2945 biggiestruct.use_ntfsprog = use_ntfsprog;2946 if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0) {2947 mr_asprintf(suffix, "%s", "");2948 should_I_compress_slices = FALSE;2949 } else {2950 mr_asprintf(suffix, "%s", bkpinfo->zip_suffix);2951 should_I_compress_slices = TRUE;2952 }2953 2954 if (bkpinfo->optimal_set_size < 999L) {2955 fatal_error("bkpinfo->optimal_set_size is insanely small");2956 }2957 2958 if (ntfsprog_fifo) {2959 file_to_openin = ntfsprog_fifo;2960 mr_asprintf(checksum_line, "IGNORE");2961 log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);2962 if ((tmp = find_home_of_exe("ntfsresize")) == NULL) {2963 fatal_error("ntfsresize not found");2964 }2965 mr_asprintf(command, "%s --force --info %s|grep '^You might resize at '|cut -d' ' -f5", tmp, biggie_filename);2966 mr_free(tmp);2967 log_it("command = %s", command);2968 tmp = call_program_and_get_last_line_of_output(command);2969 mr_free(command);2970 log_it("res of it = %s", tmp);2971 totallength = (off_t)atoll(tmp);2972 mr_free(tmp);2973 } else {2974 file_to_openin = biggie_filename;2975 if (strchr(biggie_filename,'\'') != NULL) {2976 mr_asprintf(command, "md5sum \"%s\"", biggie_filename);2977 } else {2978 mr_asprintf(command, "md5sum '%s'", biggie_filename);2979 }2980 if (!(fin = popen(command, "r"))) {2981 log_OS_error("Unable to popen-in command");2982 mr_free(suffix);2983 return (1);2984 }2985 mr_free(command);2986 mr_getline(checksum_line, fin);2987 pclose(fin);2988 totallength = length_of_file(biggie_filename);2989 }2990 lstat(biggie_filename, &biggiestruct.properties);2991 strcpy(biggiestruct.filename, biggie_filename);2992 pB = strchr(checksum_line, ' ');2993 if (!pB) {2994 pB = strchr(checksum_line, '\t');2995 }2996 if (pB) {2997 *pB = '\0';2998 }2999 strcpy(biggiestruct.checksum, checksum_line);3000 mr_free(checksum_line);3001 3002 mr_asprintf(tmp, "%s", slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""));3003 fout = fopen(tmp, "w");3004 if (fout == NULL) {3005 log_msg(1, "Unable to open and write to %s", tmp);3006 mr_free(tmp);3007 mr_free(suffix);3008 return (1);3009 }3010 res = fwrite((void *) &biggiestruct, 1, sizeof(biggiestruct), fout);3011 paranoid_fclose(fout);3012 mr_free(tmp);3013 3014 log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);3015 if (!(fin = fopen(file_to_openin, "r"))) {3016 log_OS_error("Unable to openin biggie_filename");3017 log_to_screen("Cannot archive bigfile '%s': not found", biggie_filename);3018 3019 mr_free(suffix);3020 return (1);3021 }3022 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {3023 res = move_files_to_stream(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);3024 } else {3025 res = move_files_to_cd(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);3026 }3027 i = bkpinfo->optimal_set_size / 256L;3028 if (!(tempblock = (char *) malloc(256 * 1024))) {3029 fatal_error("malloc error 256*1024");3030 }3031 for (slice_num = 1; !finished; slice_num++) {3032 mr_asprintf(curr_slice_fname_uncompressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, ""));3033 mr_asprintf(curr_slice_fname_compressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));3034 3035 tmp = percent_media_full_comment();3036 update_progress_form(tmp);3037 mr_free(tmp);3038 3039 if (!(fout = fopen(curr_slice_fname_uncompressed, "w"))) {3040 log_OS_error(curr_slice_fname_uncompressed);3041 mr_free(suffix);3042 return (1);3043 }3044 if ((i == bkpinfo->optimal_set_size / 256L) && (totalread < (off_t)1.1 * totallength)) {3045 for (i = 0L; i < (bkpinfo->optimal_set_size / 256L); i++) {3046 blksize = fread(tempblock, 1, 256 * 1024, fin);3047 if (blksize > (size_t)0) {3048 totalread = totalread + (off_t)blksize;3049 res = fwrite(tempblock, 1, blksize, fout);3050 } else {3051 break;3052 }3053 }3054 } else {3055 i = 0L;3056 }3057 paranoid_fclose(fout);3058 if (i > 0L) // length_of_file (curr_slice_fname_uncompressed)3059 {3060 if (!does_file_exist(curr_slice_fname_uncompressed)) {3061 log_msg(2, "Warning - '%s' doesn't exist. How can I compress slice?", curr_slice_fname_uncompressed);3062 }3063 if (should_I_compress_slices && bkpinfo->compression_level > 0) {3064 mr_asprintf(command, "%s -%d %s", bkpinfo->zip_exe, bkpinfo->compression_level, curr_slice_fname_uncompressed);3065 log_msg(2, command);3066 if ((res = system(command))) {3067 log_OS_error(command);3068 }3069 // did_I_compress_slice = TRUE;3070 } else {3071 mr_asprintf(command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);3072 res = 0; // don't do it :)3073 // did_I_compress_slice = FALSE;3074 }3075 mr_free(command);3076 3077 retval += res;3078 if (res) {3079 log_msg(2, "Failed to compress the slice");3080 }3081 if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed)) {3082 unlink(curr_slice_fname_uncompressed);3083 }3084 if (res) {3085 mr_asprintf(tmp, "Problem with slice # %ld", slice_num);3086 } else {3087 mr_asprintf(tmp, "%s - Bigfile #%ld, slice #%ld compressed OK ", biggie_filename, biggie_file_number + 1, slice_num);3088 }3089 if (!g_text_mode) {3090 newtDrawRootText(0, g_noof_rows - 2, tmp);3091 newtRefresh();3092 } else {3093 log_msg(2, tmp);3094 }3095 mr_free(tmp);3096 3097 mr_asprintf(file_to_archive, "%s", curr_slice_fname_compressed);3098 g_current_progress++;3099 } else { /* if i==0 then ... */3100 finished = TRUE;3101 mr_asprintf(file_to_archive, "%s", curr_slice_fname_uncompressed);3102 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {3103 break;3104 }3105 }3106 mr_free(curr_slice_fname_uncompressed);3107 mr_free(curr_slice_fname_compressed);3108 3109 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {3110 register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);3111 maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);3112 res = move_files_to_stream(file_to_archive, NULL);3113 } else {3114 res = move_files_to_cd(file_to_archive, NULL);3115 }3116 mr_free(file_to_archive);3117 3118 retval += res;3119 if (res) {3120 log_to_screen("Failed to add slice %ld of bigfile %ld to scratchdir", slice_num, biggie_file_number + 1);3121 fatal_error("Hard disk full. You should have bought a bigger one.");3122 }3123 }3124 mr_free(tempblock);3125 mr_free(suffix);3126 paranoid_fclose(fin);3127 mr_asprintf(tmp, "Sliced bigfile #%ld", biggie_file_number + 1);3128 if (retval) {3129 mr_strcat(tmp, "...FAILED");3130 } else {3131 mr_strcat(tmp, "...OK!");3132 }3133 log_msg(1, tmp);3134 mr_free(tmp);3135 3136 return (retval);3137 }3138 3139 3140 3138 /* @} - end of LLarchiveGroup */ 3141 3139
Note:
See TracChangeset
for help on using the changeset viewer.