Changeset 3879 in MondoRescue for branches/3.3/mondo/src/common
- Timestamp:
- Mar 9, 2024, 3:10:04 AM (4 months ago)
- Location:
- branches/3.3/mondo/src/common
- Files:
-
- 1 deleted
- 10 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 -
branches/3.3/mondo/src/common/libmondo-cli.c
r3875 r3879 15 15 #include "mr_str.h" 16 16 #include "mondostructures.h" 17 #include "libmondo-cli-EXT.h" 17 #include "libmondo-string-EXT.h" 18 #include "libmondo-files-EXT.h" 19 #include "libmondo-stream-EXT.h" 20 #include "libmondo-devices-EXT.h" 21 #include "libmondo-fork-EXT.h" 22 #include "libmondo-fifo-EXT.h" 18 23 #include "newt-specific-EXT.h" 19 #include "libmondo.h"20 24 21 25 extern int g_loglevel; … … 61 65 62 66 long g_max_biggie_size = BIGGIEMAXSIZE; 63 64 /**65 * @addtogroup cliGroup66 * @{67 */68 /**69 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.70 * @param argc The argument count, including the program name; @p argc passed to main().71 * @param argv The argument vector; @p argv passed to main().72 * @param bkpinfo The backup information structure to populate.73 * @return The number of problems with the command line (0 for success).74 */75 int76 handle_incoming_parameters(int argc, char *argv[])77 {78 /*@ int *** */79 int res = 0;80 int retval = 0;81 int i = 0;82 83 /*@ buffers *************** */84 char flag_val[128][MAX_STR_LEN];85 bool flag_set[128];86 87 for (i = 0; i < 128; i++) {88 flag_val[i][0] = '\0';89 flag_set[i] = FALSE;90 }91 bkpinfo->media_size = 650; /* default */92 res = retrieve_switches_from_command_line(argc, argv, flag_val, flag_set);93 retval += res;94 if (!retval) {95 res = process_switches(flag_val, flag_set);96 retval += res;97 }98 99 log_msg(3, "Switches:-");100 for (i = 0; i < 128; i++) {101 if (flag_set[i]) {102 log_msg(3, "-%c %s", i, flag_val[i]);103 }104 }105 bkpinfo->boot_type = mr_boot_type();106 107 return (retval);108 }109 67 110 68 … … 131 89 } 132 90 91 133 92 /** 134 * Process mondoarchive's command-line switches. 135 * @param bkpinfo The backup information structure to populate. 136 * @param flag_val An array of the argument passed to each switch (the letter is the index). 137 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter. 138 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set, 139 * FALSE if it's not. 140 * @return The number of problems with the switches, or 0 for success. 141 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here? 93 * Print a not-so-helpful help message and exit. 142 94 */ 143 int 144 process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128]) 95 void help_screen() 145 96 { 146 147 /*@ ints *** */ 148 int i = 0; 149 int retval = 0; 150 151 /*@ buffers ** */ 152 char *tmp = NULL; 153 char *tmp1 = NULL; 154 char *tmp2 = NULL; 155 char *psz = NULL; 156 char *p = NULL; 157 char *q = NULL; 158 char *q2 = NULL; 159 160 long itbs = 0L; 161 162 struct stat buf; 163 164 malloc_string(tmp); 165 166 assert(bkpinfo != NULL); 167 assert(flag_val != NULL); 168 assert(flag_set != NULL); 169 170 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE; 171 172 /* compulsory */ 173 i = flag_set['c'] + flag_set['i'] + flag_set['n'] + 174 flag_set['t'] + flag_set['u'] + flag_set['r'] + 175 flag_set['w'] + flag_set['C'] + flag_set['U']; 176 if ((i == 0) && (! bkpinfo->restore_data)) { 177 retval++; 178 log_to_screen("You must specify the media type\n"); 179 } 180 if (i > 1) { 181 retval++; 182 log_to_screen("Please specify only one media type\n"); 183 } 184 185 if (flag_set['K']) { 186 g_loglevel = atoi(flag_val['K']); 187 log_msg(1,"Loglevel forced to %d",g_loglevel); 188 if (g_loglevel < 3) { 189 g_loglevel = 3; 190 } 191 } 192 193 if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) { 194 retval++; 195 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n"); 196 } 197 if (! bkpinfo->restore_data) { 198 bkpinfo->backup_data = flag_set['O']; 199 } 200 bkpinfo->verify_data = flag_set['V']; 201 202 if (flag_set['I'] && !bkpinfo->backup_data) { 203 log_to_screen("-I switch is ignored if just verifying"); 204 } 205 if (flag_set['E'] && !bkpinfo->backup_data) { 206 log_to_screen("-E switch is ignored if just verifying"); 207 } 208 209 if ((tmp = find_home_of_exe("afio")) == NULL) { 210 mr_free(tmp); 211 if ((tmp = find_home_of_exe("star")) != NULL) { 212 mr_free(tmp); 213 flag_set['R'] = TRUE; 214 log_msg(1, "Using star instead of afio"); 215 } else { 216 mr_free(tmp); 217 fatal_error("Neither afio nor star is installed. Please install at least one."); 218 } 219 } 220 221 if (flag_set['R']) { 222 bkpinfo->use_star = TRUE; 223 if (flag_set['L']) { 224 fatal_error("You may not use star and lzop at the same time."); 225 } 226 if ((tmp = find_home_of_exe("star")) == NULL) { 227 mr_free(tmp); 228 fatal_error("Please install 'star' if you are going to use -R. Thanks."); 229 } 230 mr_free(tmp); 231 } 232 233 if ((flag_set['W']) && (! bkpinfo->restore_data)) { 234 bkpinfo->nonbootable_backup = TRUE; 235 log_to_screen("Warning - you have opted for non-bootable backup"); 236 if (flag_set['f'] || flag_set['l']) { 237 log_to_screen 238 ("You don't need to specify bootloader or bootdevice"); 239 } 240 } 241 242 if (flag_set['I']) { 243 if (flag_val['I'][0] == '-') { 244 retval++; 245 log_to_screen("Please supply a sensible value with '-I'\n"); 246 } 247 if (!strcmp(flag_val['I'],"/")) { 248 log_msg(2, "'/' is pleonastic."); 249 } 250 if (bkpinfo->include_paths && bkpinfo->include_paths[0]) { 251 mr_strcat(bkpinfo->include_paths, "|"); 252 } 253 254 mr_asprintf(tmp1, "%s", flag_val['I']); 255 p = tmp1; 256 q = tmp1; 257 258 /* Cut the flag_val['I'] in parts containing all paths to test them */ 259 while (p != NULL) { 260 q = strchr(p, '|'); 261 if (q != NULL) { 262 *q = '\0'; 263 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 264 log_msg(1, "ERROR ! %s doesn't exist", p); 265 fatal_error("ERROR ! You specified a directory to include which doesn't exist"); 266 } 267 p = q+1 ; 268 } else { 269 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 270 log_msg(1, "ERROR ! %s doesn't exist", p); 271 fatal_error("ERROR ! You specified a directory to include which doesn't exist"); 272 } 273 p = NULL; 274 } 275 } 276 mr_free(tmp1); 277 mr_make_devlist_from_pathlist(flag_val['I'], 'I'); 278 log_msg(4, "Finished with the -I option"); 279 } 280 281 if (g_kernel_version >= 2.6 && !flag_set['d'] && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) { 282 fatal_error("If you are using the 2.6.x kernel, please specify the CD-R(W) device."); 283 } 284 285 286 if (flag_set['J']) { 287 if (flag_set['I']) { 288 retval++; 289 log_to_screen("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)"); 290 } 291 bkpinfo->make_filelist = FALSE; 292 mr_asprintf(bkpinfo->include_paths, "%s", flag_val['J']); 293 } 294 295 if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) { 296 if (system("which cdrecord > /dev/null 2> /dev/null") && system("which dvdrecord > /dev/null 2> /dev/null")) { 297 fatal_error("Please install dvdrecord/cdrecord and try again."); 298 } 299 if (flag_set['C']) { 300 bkpinfo->cdrw_speed = atoi(flag_val['C']); 301 if (bkpinfo->cdrw_speed < 1) { 302 fatal_error("You specified a silly speed for a CD-R[W] drive"); 303 } 304 if (!flag_set['L']) { 305 log_to_screen("You must use -L with -C. Therefore I am setting it for you."); 306 flag_set['L'] = 1; 307 flag_val['L'][0] = '\0'; 308 } 309 } else { 310 log_msg(3, "flag_val['c'] = %s", flag_val['c']); 311 log_msg(3, "flag_val['w'] = %s", flag_val['w']); 312 if (flag_set['c']) { 313 bkpinfo->cdrw_speed = atoi(flag_val['c']); 314 } else if (flag_set['w']) { 315 bkpinfo->cdrw_speed = atoi(flag_val['w']); 316 } else if (flag_set['r']) { 317 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */ 318 } 319 320 if (bkpinfo->cdrw_speed < 1) { 321 fatal_error("You specified a silly speed for a CD-R[W] drive"); 322 } 323 } 324 } 325 326 if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) { 327 log_it("Hmm! No tape drive specified. Let's see what we can do."); 328 if ((bkpinfo->media_device = find_tape_device()) == NULL) { 329 fatal_error("Tape device not specified and I couldn't find it either. Please use option -d"); 330 } 331 flag_set['d'] = TRUE; 332 log_to_screen("You didn't specify a tape streamer device. I'm assuming %s", bkpinfo->media_device); 333 } 334 335 if (flag_set['U']) // USB 336 { 337 if (! flag_set['d']) { 338 fatal_error("You need to specify a device file with -d for bootable USB device usage"); 339 } 340 if ((!flag_set['s']) && (! bkpinfo->restore_data)) { 341 fatal_error("You did not specify a size (-s) for your USB device. Aborting"); 342 } 343 } 344 345 if (flag_set['r']) // DVD 346 { 347 if (flag_set['m']) { 348 fatal_error("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m."); 349 } 350 if (!flag_set['d']) { 351 if ((bkpinfo->media_device = find_optical_device()) != NULL) { 352 flag_set['d'] = TRUE; 353 log_to_screen("I guess DVD drive is at %s", bkpinfo->media_device); 354 } 355 } 356 if (strchr(bkpinfo->media_device, ',')) { 357 fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag."); 358 } 359 if (! bkpinfo->restore_data) { 360 if (!flag_set['s']) { 361 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB 362 strcat(flag_val['s'], "m"); 363 log_to_screen("You did not specify a size (-s) for DVD. I'm guessing %s.", flag_val['s']); 364 flag_set['s'] = 1; 365 } 366 } 367 } 368 369 if (flag_set['t'] || flag_set['u']) { /* tape size */ 370 if (strchr(flag_val['d'], ',')) { 371 fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag."); 372 } 373 if ((flag_set['O']) && (! bkpinfo->restore_data)) { 374 if (flag_set['s']) { 375 if (flag_set['t']) { 376 fatal_error("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway."); 377 } 378 if (process_the_s_switch(flag_val['s'])) { 379 fatal_error("Bad -s switch"); 380 } 381 } else if (flag_set['u'] || flag_set['t']) { 382 bkpinfo->media_size = 0; 383 } else { 384 retval++; 385 log_to_screen("Tape size not specified.\n"); 386 } 387 } 388 } else if (! bkpinfo->restore_data) { /* CD|USB size */ 389 if (flag_set['s']) { 390 if (process_the_s_switch(flag_val['s'])) { 391 fatal_error("Bad -s switch"); 392 } 393 } 394 if (flag_set['w']) { 395 bkpinfo->wipe_media_first = TRUE; 396 } /* CD-RW */ 397 } 398 399 if (flag_set['n']) { 400 mr_asprintf(bkpinfo->netfs_mount, "%s", flag_val['n']); 401 if (!flag_set['d']) { 402 mr_asprintf(bkpinfo->netfs_remote_dir, "/"); 403 mr_asprintf(bkpinfo->isodir, "%s", "."); 404 } 405 /* test for protocol */ 406 p = strstr(bkpinfo->netfs_mount, "://"); 407 if (p == NULL) { 408 /* protocol not found assuming NFS for compatibility */ 409 mr_asprintf(q,"nfs"); 410 411 p = strchr(bkpinfo->netfs_mount, ':'); 412 if (p == NULL) { 413 fatal_error("No protocol specified for remote share mount, nor any old NFS syntax found.\nPlease do man mondoarchive as syntax changed"); 414 } 415 /* p points on to the string server:/path */ 416 p = bkpinfo->netfs_mount; 417 418 } else { 419 /* Isolate the protocol */ 420 *p = '\0'; 421 mr_asprintf(q,"%s",bkpinfo->netfs_mount); 422 423 /* Skip proto now */ 424 p++; 425 p++; 426 p++; 427 } 428 /* whatever done before proto is pointed to by q */ 429 bkpinfo->netfs_proto = q; 430 431 /* p points on to the string server:/path */ 432 /* Store the 2 values */ 433 q2 = bkpinfo->netfs_mount; 434 mr_asprintf(bkpinfo->netfs_mount, "%s", p); 435 mr_free(q2); 436 437 /* test if we specified a user */ 438 p = strchr(bkpinfo->netfs_mount, '@'); 439 if (p != NULL) { 440 /* User found. Store the 2 values */ 441 mr_asprintf(bkpinfo->netfs_user, "%s", bkpinfo->netfs_mount); 442 p = strchr(bkpinfo->netfs_user, '@'); 443 *p = '\0'; 444 p = strchr(bkpinfo->netfs_mount, '@'); 445 p++; 446 /* new netfs mount */ 447 q2 = bkpinfo->netfs_mount; 448 mr_asprintf(bkpinfo->netfs_mount, "%s", p); 449 mr_free(q2); 450 } 451 if (bkpinfo->netfs_user != NULL) { 452 mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount); 453 } else { 454 mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount); 455 } 456 mr_free(bkpinfo->isodir); 457 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1); 458 mr_free(tmp1); 459 460 log_msg(3, "proto = %s", bkpinfo->netfs_proto); 461 log_msg(3, "mount = %s", bkpinfo->netfs_mount); 462 if (bkpinfo->netfs_user) { 463 log_msg(3, "user = %s", bkpinfo->netfs_user); 464 } 465 log_msg(3, "isodir= %s", bkpinfo->isodir); 466 467 if (strlen(bkpinfo->isodir) < 3) { 468 log_to_screen("Network share %s is not mounted. Trying to mount it for you.\n",bkpinfo->netfs_mount); 469 if (bkpinfo->netfs_user) { 470 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 471 mr_asprintf(tmp1, "sshfs %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount); 472 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) { 473 mr_asprintf(tmp1, "mount -t cifs %s -o user=%s", bkpinfo->netfs_mount, bkpinfo->netfs_user); 474 } else if (strstr(bkpinfo->netfs_proto, "nfs")) { 475 mr_asprintf(tmp1, "mount -t %s %s@%s", bkpinfo->netfs_proto, bkpinfo->netfs_user, bkpinfo->netfs_mount); 476 } else { 477 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto); 478 fatal_error("Bad Protocol\n"); 479 } 480 } else { 481 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 482 mr_asprintf(tmp1, "sshfs %s", bkpinfo->netfs_mount); 483 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) { 484 mr_asprintf(tmp1, "mount -t cifs %s", bkpinfo->netfs_mount); 485 } else if (strstr(bkpinfo->netfs_proto, "nfs")) { 486 mr_asprintf(tmp1, "mount -t %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount); 487 } else { 488 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto); 489 fatal_error("Bad Protocol\n"); 490 } 491 } 492 i = system(tmp1); 493 mr_free(tmp1); 494 495 if (i) { 496 log_to_screen("Unable to mount Network share %s. Please mount manually.\n", bkpinfo->netfs_mount); 497 retval++; 498 } else { 499 if (bkpinfo->netfs_user) { 500 mr_asprintf(tmp1, "mount | grep -E \"^[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount); 501 } else { 502 mr_asprintf(tmp1, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount); 503 } 504 mr_free(bkpinfo->isodir); 505 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1); 506 if (strlen(bkpinfo->isodir) < 3) { 507 retval++; 508 log_to_screen("Network share %s is strangely not mounted. Please mount manually...\n", bkpinfo->netfs_mount); 509 } 510 } 511 } 512 } 513 514 if (flag_set['c']) { 515 bkpinfo->backup_media_type = cdr; 516 } 517 if (flag_set['C']) { 518 bkpinfo->backup_media_type = cdstream; 519 } 520 if (flag_set['i']) { 521 bkpinfo->backup_media_type = iso; 522 } 523 if (flag_set['n']) { 524 bkpinfo->backup_media_type = netfs; 525 /* Never try to eject a Network device */ 526 bkpinfo->please_dont_eject = TRUE; 527 } 528 if (flag_set['r']) { 529 bkpinfo->backup_media_type = dvd; 530 } 531 if (flag_set['t']) { 532 bkpinfo->backup_media_type = tape; 533 } 534 if (flag_set['u']) { 535 bkpinfo->backup_media_type = udev; 536 } 537 if (flag_set['U']) { 538 bkpinfo->backup_media_type = usb; 539 /* Never try to eject a USB device */ 540 bkpinfo->please_dont_eject = TRUE; 541 } 542 if (flag_set['z']) { 543 if ((tmp = find_home_of_exe("getfattr")) != NULL) { 544 mr_asprintf(g_getfattr,"getfattr"); 545 } 546 mr_free(tmp); 547 if ((tmp = find_home_of_exe("getfacl")) != NULL) { 548 mr_asprintf(g_getfattr,"getfaacl"); 549 } 550 mr_free(tmp); 551 } 552 553 /* optional, popular */ 554 if (flag_set['g']) { 555 g_text_mode = FALSE; 556 } 557 558 if (flag_set['E']) { 559 if ((flag_val['E'][0] == '-')) { 560 retval++; 561 log_to_screen("Please supply a sensible value with '-E'\n"); 562 } 563 mr_asprintf(tmp1, "%s", flag_val['E']); 564 565 p = tmp1; 566 q = tmp1; 567 568 /* Cut the flag_val['E'] in parts containing all paths to test them */ 569 while (p != NULL) { 570 q = strchr(p, '|'); 571 if (q != NULL) { 572 *q = '\0'; 573 /* Fix bug 14 where ending / cause a problem later 574 * so handled here for the moment */ 575 q--; 576 if (*q == '/') { 577 *q = '\0'; 578 } 579 q++; 580 /* End of bug fix */ 581 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 582 log_msg(1, "WARNING ! %s doesn't exist", p); 583 } 584 p = q+1 ; 585 } else { 586 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 587 log_msg(1, "WARNING ! %s doesn't exist", p); 588 } 589 p = NULL; 590 } 591 } 592 mr_free(tmp1); 593 594 mr_make_devlist_from_pathlist(flag_val['E'], 'E'); 595 log_msg(4, "Finished with the -E option"); 596 } 597 598 if (flag_set['e']) { 599 bkpinfo->please_dont_eject = TRUE; 600 } 601 602 if (flag_set['M']) { 603 g_max_biggie_size = atol(flag_val['M']); 604 log_msg(1, "Max size for biggie file is now %ld KB", g_max_biggie_size); 605 } 606 607 if ((flag_set['N']) && (! bkpinfo->restore_data)) // exclude Network mounts & devices 608 { 609 psz = list_of_NETFS_mounts_only(); 610 log_msg(5, "-N means we'll exclude %s", psz); 611 if (bkpinfo->exclude_paths) { 612 mr_strcat(bkpinfo->exclude_paths, "|%s", psz); 613 mr_free(psz); 614 } else { 615 bkpinfo->exclude_paths = psz; 616 } 617 618 if (bkpinfo->exclude_paths != NULL) { 619 log_msg(3, "-N means we're now excluding %s", bkpinfo->exclude_paths); 620 } 621 } 622 623 if (flag_set['b']) { 624 mr_asprintf(psz, "%s", flag_val['b']); 625 log_msg(1, "psz = '%s'", psz); 626 if (psz[strlen(psz) - 1] == 'k') { 627 psz[strlen(psz) - 1] = '\0'; 628 itbs = atol(psz) * 1024L; 629 } else { 630 itbs = atol(psz); 631 } 632 mr_free(psz); 633 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs); 634 log_msg(1, "Internal tape block size is now %ld bytes", itbs); 635 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) { 636 fatal_error("Are you nuts? Silly, your internal tape block size is. Abort, I shall."); 637 } 638 bkpinfo->internal_tape_block_size = itbs; 639 } 640 641 if ((flag_set['D']) && (! bkpinfo->restore_data)) { 642 bkpinfo->differential = 1; 643 // bkpinfo->differential = atoi (flag_val['D']); 644 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) { 645 fatal_error("The D option should be between 1 and 9 inclusive"); 646 } 647 } 648 649 if (flag_set['x']) { 650 mr_asprintf(bkpinfo->image_devs, "%s", flag_val['x']); 651 if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) { 652 fatal_error("Please install ntfsprogs package/tarball."); 653 } 654 } 655 656 if (flag_set['m']) { 657 bkpinfo->manual_cd_tray = TRUE; 658 } 659 660 if ((flag_set['k']) && (! bkpinfo->restore_data)) { 661 mr_asprintf(bkpinfo->kernel_path, "%s", flag_val['k']); 662 if (!does_file_exist(bkpinfo->kernel_path)) { 663 retval++; 664 log_to_screen("You specified kernel '%s', which does not exist\n", bkpinfo->kernel_path); 665 } 666 } 667 668 if (flag_set['p']) { 669 mr_asprintf(bkpinfo->prefix, "%s", flag_val['p']); 670 log_msg(1,"Prefix forced to %s",bkpinfo->prefix); 671 } 672 673 if (flag_set['d']) { /* backup directory (if ISO/NETFS) */ 674 if (flag_set['i']) { 675 // what is flag_val['d'] is NULL/undefined 676 mr_asprintf(bkpinfo->isodir, "%s", flag_val['d']); 677 mr_asprintf(tmp1, "ls -l %s", bkpinfo->isodir); 678 if (run_program_and_log_output(tmp1, 2)) { 679 mr_free(tmp1); 680 fatal_error("output folder does not exist - please create it"); 681 } 682 mr_free(tmp1); 683 } else if (flag_set['n']) { 684 mr_free(bkpinfo->netfs_remote_dir); 685 // what is flag_val['d'] is NULL/undefined 686 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", flag_val['d']); 687 } else { /* backup device (if tape/CD-R/CD-RW) */ 688 /* bkpinfo-> media_device already setup upper */ 689 } 690 } 691 692 if ((flag_set['n']) && (! bkpinfo->restore_data)) { 693 mr_asprintf(tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->netfs_remote_dir); 694 if ((bkpinfo->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) { 695 mr_asprintf(tmp2, "su - %s -c \"echo hi > %s\"", bkpinfo->netfs_user, tmp1); 696 } else { 697 mr_asprintf(tmp2, "echo hi > %s", tmp1); 698 } 699 i = run_program_and_log_output(tmp2, 2); 700 mr_free(tmp2); 701 702 if (i) { 703 retval++; 704 log_to_screen("Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n", bkpinfo->netfs_remote_dir, bkpinfo->netfs_mount); 705 } 706 unlink(tmp1); 707 mr_free(tmp1); 708 } 709 710 if (!flag_set['d'] && (flag_set['c'] || flag_set['w'] || flag_set['C'])) { 711 tmp1 = mr_popup_and_get_string("Device", "Please specify the device", bkpinfo->media_device); 712 if (tmp1 == NULL) { 713 retval++; 714 log_to_screen("User opted to cancel."); 715 } else { 716 mr_free(bkpinfo->media_device); 717 bkpinfo->media_device = tmp1; 718 } 719 } else { 720 } 721 722 if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) { 723 retval++; 724 log_to_screen("Please specify the backup device/directory.\n"); 725 fatal_error("You didn't use -d to specify the backup device/directory."); 726 } 727 728 for (i = '0'; i <= '9'; i++) { 729 if (flag_set[i]) { 730 bkpinfo->compression_level = i - '0'; 731 } /* not '\0' but '0' */ 732 } 733 734 if (flag_set['S']) { 735 setup_scratchdir(flag_val['S']); 736 mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->scratchdir); 737 if (run_program_and_log_output(tmp1, 1)) { 738 retval++; 739 mr_free(tmp1); 740 log_to_screen("Please specify a scratchdir which I can write to. :)"); 741 fatal_error("I cannot write to the scratchdir you specified."); 742 } 743 mr_free(tmp1); 744 745 mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->scratchdir, bkpinfo->scratchdir); 746 if (run_program_and_log_output(tmp1, 1)) { 747 retval++; 748 mr_free(tmp1); 749 log_to_screen("Please don't specify a SAMBA or VFAT or NFS scratchdir."); 750 fatal_error("I cannot write to the scratchdir you specified."); 751 } 752 mr_free(tmp1); 753 } 754 755 if (flag_set['T']) { 756 setup_tmpdir(flag_val['T']); 757 mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->tmpdir); 758 i = run_program_and_log_output(tmp1, 1); 759 mr_free(tmp1); 760 761 if (i) { 762 retval++; 763 log_to_screen("Please specify a tempdir which I can write to. :)"); 764 fatal_error("I cannot write to the tempdir you specified."); 765 } 766 mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir); 767 i = run_program_and_log_output(tmp1, 1); 768 mr_free(tmp1); 769 770 if (i) { 771 retval++; 772 log_to_screen("Please don't specify a SAMBA or VFAT or NFS tmpdir."); 773 fatal_error("I cannot write to the tempdir you specified."); 774 } 775 } 776 777 if ((flag_set['A']) && (! bkpinfo->restore_data)) { 778 mr_asprintf(bkpinfo->call_after_iso, "%s", flag_val['A']); 779 } 780 781 if ((flag_set['B']) && (! bkpinfo->restore_data)) { 782 mr_asprintf(bkpinfo->call_before_iso, "%s", flag_val['B']); 783 } 784 785 if ((flag_set['H']) && (! bkpinfo->restore_data)) { 786 g_cd_recovery = TRUE; 787 } 788 789 if ((flag_set['l']) && (! bkpinfo->restore_data)) { 790 #ifdef __FreeBSD__ 791 # define BOOT_LOADER_CHARS "GLBMR" 792 #else 793 # ifdef __IA64__ 794 # define BOOT_LOADER_CHARS "GER" 795 # else 796 # define BOOT_LOADER_CHARS "GLR" 797 # endif 798 #endif 799 if (!strchr(BOOT_LOADER_CHARS, (bkpinfo->boot_loader = flag_val['l'][0]))) { 800 log_msg(1, "%c? What is %c? I need G, L, E or R.", bkpinfo->boot_loader, bkpinfo->boot_loader); 801 fatal_error("Please specify GRUB, LILO, ELILO or RAW with the -l switch"); 802 } 803 #undef BOOT_LOADER_CHARS 804 } 805 806 if (flag_set['f']) { 807 mr_free(bkpinfo->boot_device); 808 mr_asprintf(bkpinfo->boot_device, "%s", resolve_softlinks_to_get_to_actual_device_file(flag_val['f'])); 809 } 810 811 if ((flag_set['P']) && (! bkpinfo->restore_data)) { 812 mr_asprintf(bkpinfo->postnuke_tarball, "%s", flag_val['P']); 813 } 814 815 if (flag_set['Q']) { 816 i = which_boot_loader(tmp); 817 log_msg(3, "boot loader is %c, residing at %s", i, tmp); 818 printf("boot loader is %c, residing at %s\n", i, tmp); 819 finish(0); 820 } 821 822 if ((flag_set['L']) && (! bkpinfo->restore_data)) { 823 bkpinfo->use_lzo = TRUE; 824 if (run_program_and_log_output("which lzop", 2)) { 825 retval++; 826 log_to_screen("Please install LZOP. You can't use '-L' until you do.\n"); 827 } 828 } 829 830 if (flag_set['F']) { 831 log_msg(3, "-F means we will fail immediately at the first interaction request"); 832 g_fail_immediately = TRUE; 833 } 834 835 if ((flag_set['G']) && (! bkpinfo->restore_data)) { 836 bkpinfo->use_gzip = TRUE; 837 if (run_program_and_log_output("which gzip", 2)) { 838 retval++; 839 log_to_screen("Please install gzip. You can't use '-G' until you do.\n"); 840 } 841 } 842 843 if ((flag_set['Y']) && (! bkpinfo->restore_data)) { 844 bkpinfo->use_lzma = TRUE; 845 if (run_program_and_log_output("which lzma", 2)) { 846 retval++; 847 log_to_screen("Please install lzma. You can't use '-Y' until you do.\n"); 848 } 849 } 850 851 bkpinfo->use_obdr = FALSE; 852 if (flag_set['o']) { 853 if ((!flag_set['t']) && (! bkpinfo->restore_data)) { 854 log_to_screen("OBDR support is only available for tapes. Use the -t option"); 855 fatal_error("Aborting"); 856 } 857 bkpinfo->use_obdr = TRUE; 858 } 859 860 #ifndef __FreeBSD__ 861 if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) { 862 bkpinfo->make_cd_use_lilo = TRUE; 863 log_to_screen("Your kernel appears not to support vfat filesystems. I am therefore"); 864 log_to_screen("using LILO instead of SYSLINUX as the media boot loader."); 865 } 866 if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) { 867 bkpinfo->make_cd_use_lilo = TRUE; 868 #ifdef __IA32__ 869 log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as"); 870 log_to_screen("your boot loader. I shall therefore use LILO instead."); 871 #endif 872 #ifdef __IA64__ 873 log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI"); 874 log_to_screen("environment correctly. Please install it."); 875 fatal_error("Aborting"); 876 #endif 877 } 878 #ifdef __IA64__ 879 /* We force ELILO usage on IA64 */ 880 bkpinfo->make_cd_use_lilo = TRUE; 881 #endif 882 #endif 883 884 if (! bkpinfo->restore_data) { 885 i = flag_set['O'] + flag_set['V']; 886 if (i == 0) { 887 retval++; 888 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n"); 889 } 890 } 891 892 if ((! bkpinfo->restore_data) && (flag_set['Z'])) { 893 fatal_error("The -Z switch is only valid in restore mode"); 894 } 895 896 if (flag_set['Z']) { 897 if (! strcmp(flag_val['Z'], "nuke")) { 898 bkpinfo->restore_mode = nuke; 899 } else if (! strcmp(flag_val['Z'], "interactive")) { 900 bkpinfo->restore_mode = interactive; 901 } else if (! strcmp(flag_val['Z'], "compare")) { 902 bkpinfo->restore_mode = compare; 903 } else if (! strcmp(flag_val['Z'], "mbr")) { 904 bkpinfo->restore_mode = mbr; 905 } else if (! strcmp(flag_val['Z'], "iso")) { 906 bkpinfo->restore_mode = isoonly; 907 } else if (! strcmp(flag_val['Z'], "isonuke")) { 908 bkpinfo->restore_mode = isonuke; 909 } else { 910 bkpinfo->restore_mode = interactive; 911 } 912 } 913 914 /* and finally... */ 915 916 paranoid_free(tmp); 917 return (retval); 97 log_msg(1, "Type 'man mondoarchive' for more information"); 98 exit(1); 918 99 } 919 920 100 921 101 … … 983 163 984 164 985 986 987 165 /** 988 * Print a not-so-helpful help message and exit. 166 * Process mondoarchive's command-line switches. 167 * @param bkpinfo The backup information structure to populate. 168 * @param flag_val An array of the argument passed to each switch (the letter is the index). 169 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter. 170 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set, 171 * FALSE if it's not. 172 * @return The number of problems with the switches, or 0 for success. 173 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here? 989 174 */ 990 void help_screen() 175 int 176 process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128]) 991 177 { 992 log_msg(1, "Type 'man mondoarchive' for more information"); 993 exit(1); 178 179 /*@ ints *** */ 180 int i = 0; 181 int retval = 0; 182 183 /*@ buffers ** */ 184 char *tmp = NULL; 185 char *tmp1 = NULL; 186 char *tmp2 = NULL; 187 char *psz = NULL; 188 char *p = NULL; 189 char *q = NULL; 190 char *q2 = NULL; 191 192 long itbs = 0L; 193 194 struct stat buf; 195 196 malloc_string(tmp); 197 198 assert(bkpinfo != NULL); 199 assert(flag_val != NULL); 200 assert(flag_set != NULL); 201 202 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE; 203 204 /* compulsory */ 205 i = flag_set['c'] + flag_set['i'] + flag_set['n'] + 206 flag_set['t'] + flag_set['u'] + flag_set['r'] + 207 flag_set['w'] + flag_set['C'] + flag_set['U']; 208 if ((i == 0) && (! bkpinfo->restore_data)) { 209 retval++; 210 log_to_screen("You must specify the media type\n"); 211 } 212 if (i > 1) { 213 retval++; 214 log_to_screen("Please specify only one media type\n"); 215 } 216 217 if (flag_set['K']) { 218 g_loglevel = atoi(flag_val['K']); 219 log_msg(1,"Loglevel forced to %d",g_loglevel); 220 if (g_loglevel < 3) { 221 g_loglevel = 3; 222 } 223 } 224 225 if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) { 226 retval++; 227 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n"); 228 } 229 if (! bkpinfo->restore_data) { 230 bkpinfo->backup_data = flag_set['O']; 231 } 232 bkpinfo->verify_data = flag_set['V']; 233 234 if (flag_set['I'] && !bkpinfo->backup_data) { 235 log_to_screen("-I switch is ignored if just verifying"); 236 } 237 if (flag_set['E'] && !bkpinfo->backup_data) { 238 log_to_screen("-E switch is ignored if just verifying"); 239 } 240 241 if ((tmp = find_home_of_exe("afio")) == NULL) { 242 mr_free(tmp); 243 if ((tmp = find_home_of_exe("star")) != NULL) { 244 mr_free(tmp); 245 flag_set['R'] = TRUE; 246 log_msg(1, "Using star instead of afio"); 247 } else { 248 mr_free(tmp); 249 fatal_error("Neither afio nor star is installed. Please install at least one."); 250 } 251 } 252 253 if (flag_set['R']) { 254 bkpinfo->use_star = TRUE; 255 if (flag_set['L']) { 256 fatal_error("You may not use star and lzop at the same time."); 257 } 258 if ((tmp = find_home_of_exe("star")) == NULL) { 259 mr_free(tmp); 260 fatal_error("Please install 'star' if you are going to use -R. Thanks."); 261 } 262 mr_free(tmp); 263 } 264 265 if ((flag_set['W']) && (! bkpinfo->restore_data)) { 266 bkpinfo->nonbootable_backup = TRUE; 267 log_to_screen("Warning - you have opted for non-bootable backup"); 268 if (flag_set['f'] || flag_set['l']) { 269 log_to_screen 270 ("You don't need to specify bootloader or bootdevice"); 271 } 272 } 273 274 if (flag_set['I']) { 275 if (flag_val['I'][0] == '-') { 276 retval++; 277 log_to_screen("Please supply a sensible value with '-I'\n"); 278 } 279 if (!strcmp(flag_val['I'],"/")) { 280 log_msg(2, "'/' is pleonastic."); 281 } 282 if (bkpinfo->include_paths && bkpinfo->include_paths[0]) { 283 mr_strcat(bkpinfo->include_paths, "|"); 284 } 285 286 mr_asprintf(tmp1, "%s", flag_val['I']); 287 p = tmp1; 288 q = tmp1; 289 290 /* Cut the flag_val['I'] in parts containing all paths to test them */ 291 while (p != NULL) { 292 q = strchr(p, '|'); 293 if (q != NULL) { 294 *q = '\0'; 295 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 296 log_msg(1, "ERROR ! %s doesn't exist", p); 297 fatal_error("ERROR ! You specified a directory to include which doesn't exist"); 298 } 299 p = q+1 ; 300 } else { 301 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 302 log_msg(1, "ERROR ! %s doesn't exist", p); 303 fatal_error("ERROR ! You specified a directory to include which doesn't exist"); 304 } 305 p = NULL; 306 } 307 } 308 mr_free(tmp1); 309 mr_make_devlist_from_pathlist(flag_val['I'], 'I'); 310 log_msg(4, "Finished with the -I option"); 311 } 312 313 if (g_kernel_version >= 2.6 && !flag_set['d'] && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) { 314 fatal_error("If you are using the 2.6.x kernel, please specify the CD-R(W) device."); 315 } 316 317 318 if (flag_set['J']) { 319 if (flag_set['I']) { 320 retval++; 321 log_to_screen("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)"); 322 } 323 bkpinfo->make_filelist = FALSE; 324 mr_asprintf(bkpinfo->include_paths, "%s", flag_val['J']); 325 } 326 327 if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) { 328 if (system("which cdrecord > /dev/null 2> /dev/null") && system("which dvdrecord > /dev/null 2> /dev/null")) { 329 fatal_error("Please install dvdrecord/cdrecord and try again."); 330 } 331 if (flag_set['C']) { 332 bkpinfo->cdrw_speed = atoi(flag_val['C']); 333 if (bkpinfo->cdrw_speed < 1) { 334 fatal_error("You specified a silly speed for a CD-R[W] drive"); 335 } 336 if (!flag_set['L']) { 337 log_to_screen("You must use -L with -C. Therefore I am setting it for you."); 338 flag_set['L'] = 1; 339 flag_val['L'][0] = '\0'; 340 } 341 } else { 342 log_msg(3, "flag_val['c'] = %s", flag_val['c']); 343 log_msg(3, "flag_val['w'] = %s", flag_val['w']); 344 if (flag_set['c']) { 345 bkpinfo->cdrw_speed = atoi(flag_val['c']); 346 } else if (flag_set['w']) { 347 bkpinfo->cdrw_speed = atoi(flag_val['w']); 348 } else if (flag_set['r']) { 349 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */ 350 } 351 352 if (bkpinfo->cdrw_speed < 1) { 353 fatal_error("You specified a silly speed for a CD-R[W] drive"); 354 } 355 } 356 } 357 358 if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) { 359 log_it("Hmm! No tape drive specified. Let's see what we can do."); 360 if ((bkpinfo->media_device = find_tape_device()) == NULL) { 361 fatal_error("Tape device not specified and I couldn't find it either. Please use option -d"); 362 } 363 flag_set['d'] = TRUE; 364 log_to_screen("You didn't specify a tape streamer device. I'm assuming %s", bkpinfo->media_device); 365 } 366 367 if (flag_set['U']) // USB 368 { 369 if (! flag_set['d']) { 370 fatal_error("You need to specify a device file with -d for bootable USB device usage"); 371 } 372 if ((!flag_set['s']) && (! bkpinfo->restore_data)) { 373 fatal_error("You did not specify a size (-s) for your USB device. Aborting"); 374 } 375 } 376 377 if (flag_set['r']) // DVD 378 { 379 if (flag_set['m']) { 380 fatal_error("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m."); 381 } 382 if (!flag_set['d']) { 383 if ((bkpinfo->media_device = find_optical_device()) != NULL) { 384 flag_set['d'] = TRUE; 385 log_to_screen("I guess DVD drive is at %s", bkpinfo->media_device); 386 } 387 } 388 if (strchr(bkpinfo->media_device, ',')) { 389 fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag."); 390 } 391 if (! bkpinfo->restore_data) { 392 if (!flag_set['s']) { 393 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB 394 strcat(flag_val['s'], "m"); 395 log_to_screen("You did not specify a size (-s) for DVD. I'm guessing %s.", flag_val['s']); 396 flag_set['s'] = 1; 397 } 398 } 399 } 400 401 if (flag_set['t'] || flag_set['u']) { /* tape size */ 402 if (strchr(flag_val['d'], ',')) { 403 fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag."); 404 } 405 if ((flag_set['O']) && (! bkpinfo->restore_data)) { 406 if (flag_set['s']) { 407 if (flag_set['t']) { 408 fatal_error("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway."); 409 } 410 if (process_the_s_switch(flag_val['s'])) { 411 fatal_error("Bad -s switch"); 412 } 413 } else if (flag_set['u'] || flag_set['t']) { 414 bkpinfo->media_size = 0; 415 } else { 416 retval++; 417 log_to_screen("Tape size not specified.\n"); 418 } 419 } 420 } else if (! bkpinfo->restore_data) { /* CD|USB size */ 421 if (flag_set['s']) { 422 if (process_the_s_switch(flag_val['s'])) { 423 fatal_error("Bad -s switch"); 424 } 425 } 426 if (flag_set['w']) { 427 bkpinfo->wipe_media_first = TRUE; 428 } /* CD-RW */ 429 } 430 431 if (flag_set['n']) { 432 mr_asprintf(bkpinfo->netfs_mount, "%s", flag_val['n']); 433 if (!flag_set['d']) { 434 mr_asprintf(bkpinfo->netfs_remote_dir, "/"); 435 mr_asprintf(bkpinfo->isodir, "%s", "."); 436 } 437 /* test for protocol */ 438 p = strstr(bkpinfo->netfs_mount, "://"); 439 if (p == NULL) { 440 /* protocol not found assuming NFS for compatibility */ 441 mr_asprintf(q,"nfs"); 442 443 p = strchr(bkpinfo->netfs_mount, ':'); 444 if (p == NULL) { 445 fatal_error("No protocol specified for remote share mount, nor any old NFS syntax found.\nPlease do man mondoarchive as syntax changed"); 446 } 447 /* p points on to the string server:/path */ 448 p = bkpinfo->netfs_mount; 449 450 } else { 451 /* Isolate the protocol */ 452 *p = '\0'; 453 mr_asprintf(q,"%s",bkpinfo->netfs_mount); 454 455 /* Skip proto now */ 456 p++; 457 p++; 458 p++; 459 } 460 /* whatever done before proto is pointed to by q */ 461 bkpinfo->netfs_proto = q; 462 463 /* p points on to the string server:/path */ 464 /* Store the 2 values */ 465 q2 = bkpinfo->netfs_mount; 466 mr_asprintf(bkpinfo->netfs_mount, "%s", p); 467 mr_free(q2); 468 469 /* test if we specified a user */ 470 p = strchr(bkpinfo->netfs_mount, '@'); 471 if (p != NULL) { 472 /* User found. Store the 2 values */ 473 mr_asprintf(bkpinfo->netfs_user, "%s", bkpinfo->netfs_mount); 474 p = strchr(bkpinfo->netfs_user, '@'); 475 *p = '\0'; 476 p = strchr(bkpinfo->netfs_mount, '@'); 477 p++; 478 /* new netfs mount */ 479 q2 = bkpinfo->netfs_mount; 480 mr_asprintf(bkpinfo->netfs_mount, "%s", p); 481 mr_free(q2); 482 } 483 if (bkpinfo->netfs_user != NULL) { 484 mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount); 485 } else { 486 mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount); 487 } 488 mr_free(bkpinfo->isodir); 489 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1); 490 mr_free(tmp1); 491 492 log_msg(3, "proto = %s", bkpinfo->netfs_proto); 493 log_msg(3, "mount = %s", bkpinfo->netfs_mount); 494 if (bkpinfo->netfs_user) { 495 log_msg(3, "user = %s", bkpinfo->netfs_user); 496 } 497 log_msg(3, "isodir= %s", bkpinfo->isodir); 498 499 if (strlen(bkpinfo->isodir) < 3) { 500 log_to_screen("Network share %s is not mounted. Trying to mount it for you.\n",bkpinfo->netfs_mount); 501 if (bkpinfo->netfs_user) { 502 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 503 mr_asprintf(tmp1, "sshfs %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount); 504 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) { 505 mr_asprintf(tmp1, "mount -t cifs %s -o user=%s", bkpinfo->netfs_mount, bkpinfo->netfs_user); 506 } else if (strstr(bkpinfo->netfs_proto, "nfs")) { 507 mr_asprintf(tmp1, "mount -t %s %s@%s", bkpinfo->netfs_proto, bkpinfo->netfs_user, bkpinfo->netfs_mount); 508 } else { 509 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto); 510 fatal_error("Bad Protocol\n"); 511 } 512 } else { 513 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 514 mr_asprintf(tmp1, "sshfs %s", bkpinfo->netfs_mount); 515 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) { 516 mr_asprintf(tmp1, "mount -t cifs %s", bkpinfo->netfs_mount); 517 } else if (strstr(bkpinfo->netfs_proto, "nfs")) { 518 mr_asprintf(tmp1, "mount -t %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount); 519 } else { 520 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto); 521 fatal_error("Bad Protocol\n"); 522 } 523 } 524 i = system(tmp1); 525 mr_free(tmp1); 526 527 if (i) { 528 log_to_screen("Unable to mount Network share %s. Please mount manually.\n", bkpinfo->netfs_mount); 529 retval++; 530 } else { 531 if (bkpinfo->netfs_user) { 532 mr_asprintf(tmp1, "mount | grep -E \"^[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount); 533 } else { 534 mr_asprintf(tmp1, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount); 535 } 536 mr_free(bkpinfo->isodir); 537 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1); 538 if (strlen(bkpinfo->isodir) < 3) { 539 retval++; 540 log_to_screen("Network share %s is strangely not mounted. Please mount manually...\n", bkpinfo->netfs_mount); 541 } 542 } 543 } 544 } 545 546 if (flag_set['c']) { 547 bkpinfo->backup_media_type = cdr; 548 } 549 if (flag_set['C']) { 550 bkpinfo->backup_media_type = cdstream; 551 } 552 if (flag_set['i']) { 553 bkpinfo->backup_media_type = iso; 554 } 555 if (flag_set['n']) { 556 bkpinfo->backup_media_type = netfs; 557 /* Never try to eject a Network device */ 558 bkpinfo->please_dont_eject = TRUE; 559 } 560 if (flag_set['r']) { 561 bkpinfo->backup_media_type = dvd; 562 } 563 if (flag_set['t']) { 564 bkpinfo->backup_media_type = tape; 565 } 566 if (flag_set['u']) { 567 bkpinfo->backup_media_type = udev; 568 } 569 if (flag_set['U']) { 570 bkpinfo->backup_media_type = usb; 571 /* Never try to eject a USB device */ 572 bkpinfo->please_dont_eject = TRUE; 573 } 574 if (flag_set['z']) { 575 if ((tmp = find_home_of_exe("getfattr")) != NULL) { 576 mr_asprintf(g_getfattr,"getfattr"); 577 } 578 mr_free(tmp); 579 if ((tmp = find_home_of_exe("getfacl")) != NULL) { 580 mr_asprintf(g_getfattr,"getfaacl"); 581 } 582 mr_free(tmp); 583 } 584 585 /* optional, popular */ 586 if (flag_set['g']) { 587 g_text_mode = FALSE; 588 } 589 590 if (flag_set['E']) { 591 if ((flag_val['E'][0] == '-')) { 592 retval++; 593 log_to_screen("Please supply a sensible value with '-E'\n"); 594 } 595 mr_asprintf(tmp1, "%s", flag_val['E']); 596 597 p = tmp1; 598 q = tmp1; 599 600 /* Cut the flag_val['E'] in parts containing all paths to test them */ 601 while (p != NULL) { 602 q = strchr(p, '|'); 603 if (q != NULL) { 604 *q = '\0'; 605 /* Fix bug 14 where ending / cause a problem later 606 * so handled here for the moment */ 607 q--; 608 if (*q == '/') { 609 *q = '\0'; 610 } 611 q++; 612 /* End of bug fix */ 613 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 614 log_msg(1, "WARNING ! %s doesn't exist", p); 615 } 616 p = q+1 ; 617 } else { 618 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) { 619 log_msg(1, "WARNING ! %s doesn't exist", p); 620 } 621 p = NULL; 622 } 623 } 624 mr_free(tmp1); 625 626 mr_make_devlist_from_pathlist(flag_val['E'], 'E'); 627 log_msg(4, "Finished with the -E option"); 628 } 629 630 if (flag_set['e']) { 631 bkpinfo->please_dont_eject = TRUE; 632 } 633 634 if (flag_set['M']) { 635 g_max_biggie_size = atol(flag_val['M']); 636 log_msg(1, "Max size for biggie file is now %ld KB", g_max_biggie_size); 637 } 638 639 if ((flag_set['N']) && (! bkpinfo->restore_data)) // exclude Network mounts & devices 640 { 641 psz = list_of_NETFS_mounts_only(); 642 log_msg(5, "-N means we'll exclude %s", psz); 643 if (bkpinfo->exclude_paths) { 644 mr_strcat(bkpinfo->exclude_paths, "|%s", psz); 645 mr_free(psz); 646 } else { 647 bkpinfo->exclude_paths = psz; 648 } 649 650 if (bkpinfo->exclude_paths != NULL) { 651 log_msg(3, "-N means we're now excluding %s", bkpinfo->exclude_paths); 652 } 653 } 654 655 if (flag_set['b']) { 656 mr_asprintf(psz, "%s", flag_val['b']); 657 log_msg(1, "psz = '%s'", psz); 658 if (psz[strlen(psz) - 1] == 'k') { 659 psz[strlen(psz) - 1] = '\0'; 660 itbs = atol(psz) * 1024L; 661 } else { 662 itbs = atol(psz); 663 } 664 mr_free(psz); 665 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs); 666 log_msg(1, "Internal tape block size is now %ld bytes", itbs); 667 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) { 668 fatal_error("Are you nuts? Silly, your internal tape block size is. Abort, I shall."); 669 } 670 bkpinfo->internal_tape_block_size = itbs; 671 } 672 673 if ((flag_set['D']) && (! bkpinfo->restore_data)) { 674 bkpinfo->differential = 1; 675 // bkpinfo->differential = atoi (flag_val['D']); 676 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) { 677 fatal_error("The D option should be between 1 and 9 inclusive"); 678 } 679 } 680 681 if (flag_set['x']) { 682 mr_asprintf(bkpinfo->image_devs, "%s", flag_val['x']); 683 if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) { 684 fatal_error("Please install ntfsprogs package/tarball."); 685 } 686 } 687 688 if (flag_set['m']) { 689 bkpinfo->manual_cd_tray = TRUE; 690 } 691 692 if ((flag_set['k']) && (! bkpinfo->restore_data)) { 693 mr_asprintf(bkpinfo->kernel_path, "%s", flag_val['k']); 694 if (!does_file_exist(bkpinfo->kernel_path)) { 695 retval++; 696 log_to_screen("You specified kernel '%s', which does not exist\n", bkpinfo->kernel_path); 697 } 698 } 699 700 if (flag_set['p']) { 701 mr_asprintf(bkpinfo->prefix, "%s", flag_val['p']); 702 log_msg(1,"Prefix forced to %s",bkpinfo->prefix); 703 } 704 705 if (flag_set['d']) { /* backup directory (if ISO/NETFS) */ 706 if (flag_set['i']) { 707 // what is flag_val['d'] is NULL/undefined 708 mr_asprintf(bkpinfo->isodir, "%s", flag_val['d']); 709 mr_asprintf(tmp1, "ls -l %s", bkpinfo->isodir); 710 if (run_program_and_log_output(tmp1, 2)) { 711 mr_free(tmp1); 712 fatal_error("output folder does not exist - please create it"); 713 } 714 mr_free(tmp1); 715 } else if (flag_set['n']) { 716 mr_free(bkpinfo->netfs_remote_dir); 717 // what is flag_val['d'] is NULL/undefined 718 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", flag_val['d']); 719 } else { /* backup device (if tape/CD-R/CD-RW) */ 720 /* bkpinfo-> media_device already setup upper */ 721 } 722 } 723 724 if ((flag_set['n']) && (! bkpinfo->restore_data)) { 725 mr_asprintf(tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->netfs_remote_dir); 726 if ((bkpinfo->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) { 727 mr_asprintf(tmp2, "su - %s -c \"echo hi > %s\"", bkpinfo->netfs_user, tmp1); 728 } else { 729 mr_asprintf(tmp2, "echo hi > %s", tmp1); 730 } 731 i = run_program_and_log_output(tmp2, 2); 732 mr_free(tmp2); 733 734 if (i) { 735 retval++; 736 log_to_screen("Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n", bkpinfo->netfs_remote_dir, bkpinfo->netfs_mount); 737 } 738 unlink(tmp1); 739 mr_free(tmp1); 740 } 741 742 if (!flag_set['d'] && (flag_set['c'] || flag_set['w'] || flag_set['C'])) { 743 tmp1 = mr_popup_and_get_string("Device", "Please specify the device", bkpinfo->media_device); 744 if (tmp1 == NULL) { 745 retval++; 746 log_to_screen("User opted to cancel."); 747 } else { 748 mr_free(bkpinfo->media_device); 749 bkpinfo->media_device = tmp1; 750 } 751 } else { 752 } 753 754 if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) { 755 retval++; 756 log_to_screen("Please specify the backup device/directory.\n"); 757 fatal_error("You didn't use -d to specify the backup device/directory."); 758 } 759 760 for (i = '0'; i <= '9'; i++) { 761 if (flag_set[i]) { 762 bkpinfo->compression_level = i - '0'; 763 } /* not '\0' but '0' */ 764 } 765 766 if (flag_set['S']) { 767 setup_scratchdir(flag_val['S']); 768 mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->scratchdir); 769 if (run_program_and_log_output(tmp1, 1)) { 770 retval++; 771 mr_free(tmp1); 772 log_to_screen("Please specify a scratchdir which I can write to. :)"); 773 fatal_error("I cannot write to the scratchdir you specified."); 774 } 775 mr_free(tmp1); 776 777 mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->scratchdir, bkpinfo->scratchdir); 778 if (run_program_and_log_output(tmp1, 1)) { 779 retval++; 780 mr_free(tmp1); 781 log_to_screen("Please don't specify a SAMBA or VFAT or NFS scratchdir."); 782 fatal_error("I cannot write to the scratchdir you specified."); 783 } 784 mr_free(tmp1); 785 } 786 787 if (flag_set['T']) { 788 setup_tmpdir(flag_val['T']); 789 mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->tmpdir); 790 i = run_program_and_log_output(tmp1, 1); 791 mr_free(tmp1); 792 793 if (i) { 794 retval++; 795 log_to_screen("Please specify a tempdir which I can write to. :)"); 796 fatal_error("I cannot write to the tempdir you specified."); 797 } 798 mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir); 799 i = run_program_and_log_output(tmp1, 1); 800 mr_free(tmp1); 801 802 if (i) { 803 retval++; 804 log_to_screen("Please don't specify a SAMBA or VFAT or NFS tmpdir."); 805 fatal_error("I cannot write to the tempdir you specified."); 806 } 807 } 808 809 if ((flag_set['A']) && (! bkpinfo->restore_data)) { 810 mr_asprintf(bkpinfo->call_after_iso, "%s", flag_val['A']); 811 } 812 813 if ((flag_set['B']) && (! bkpinfo->restore_data)) { 814 mr_asprintf(bkpinfo->call_before_iso, "%s", flag_val['B']); 815 } 816 817 if ((flag_set['H']) && (! bkpinfo->restore_data)) { 818 g_cd_recovery = TRUE; 819 } 820 821 if ((flag_set['l']) && (! bkpinfo->restore_data)) { 822 #ifdef __FreeBSD__ 823 # define BOOT_LOADER_CHARS "GLBMR" 824 #else 825 # ifdef __IA64__ 826 # define BOOT_LOADER_CHARS "GER" 827 # else 828 # define BOOT_LOADER_CHARS "GLR" 829 # endif 830 #endif 831 if (!strchr(BOOT_LOADER_CHARS, (bkpinfo->boot_loader = flag_val['l'][0]))) { 832 log_msg(1, "%c? What is %c? I need G, L, E or R.", bkpinfo->boot_loader, bkpinfo->boot_loader); 833 fatal_error("Please specify GRUB, LILO, ELILO or RAW with the -l switch"); 834 } 835 #undef BOOT_LOADER_CHARS 836 } 837 838 if (flag_set['f']) { 839 mr_free(bkpinfo->boot_device); 840 mr_asprintf(bkpinfo->boot_device, "%s", resolve_softlinks_to_get_to_actual_device_file(flag_val['f'])); 841 } 842 843 if ((flag_set['P']) && (! bkpinfo->restore_data)) { 844 mr_asprintf(bkpinfo->postnuke_tarball, "%s", flag_val['P']); 845 } 846 847 if (flag_set['Q']) { 848 i = which_boot_loader(tmp); 849 log_msg(3, "boot loader is %c, residing at %s", i, tmp); 850 printf("boot loader is %c, residing at %s\n", i, tmp); 851 finish(0); 852 } 853 854 if ((flag_set['L']) && (! bkpinfo->restore_data)) { 855 bkpinfo->use_lzo = TRUE; 856 if (run_program_and_log_output("which lzop", 2)) { 857 retval++; 858 log_to_screen("Please install LZOP. You can't use '-L' until you do.\n"); 859 } 860 } 861 862 if (flag_set['F']) { 863 log_msg(3, "-F means we will fail immediately at the first interaction request"); 864 g_fail_immediately = TRUE; 865 } 866 867 if ((flag_set['G']) && (! bkpinfo->restore_data)) { 868 bkpinfo->use_gzip = TRUE; 869 if (run_program_and_log_output("which gzip", 2)) { 870 retval++; 871 log_to_screen("Please install gzip. You can't use '-G' until you do.\n"); 872 } 873 } 874 875 if ((flag_set['Y']) && (! bkpinfo->restore_data)) { 876 bkpinfo->use_lzma = TRUE; 877 if (run_program_and_log_output("which lzma", 2)) { 878 retval++; 879 log_to_screen("Please install lzma. You can't use '-Y' until you do.\n"); 880 } 881 } 882 883 bkpinfo->use_obdr = FALSE; 884 if (flag_set['o']) { 885 if ((!flag_set['t']) && (! bkpinfo->restore_data)) { 886 log_to_screen("OBDR support is only available for tapes. Use the -t option"); 887 fatal_error("Aborting"); 888 } 889 bkpinfo->use_obdr = TRUE; 890 } 891 892 #ifndef __FreeBSD__ 893 if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) { 894 bkpinfo->make_cd_use_lilo = TRUE; 895 log_to_screen("Your kernel appears not to support vfat filesystems. I am therefore"); 896 log_to_screen("using LILO instead of SYSLINUX as the media boot loader."); 897 } 898 if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) { 899 bkpinfo->make_cd_use_lilo = TRUE; 900 #ifdef __IA32__ 901 log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as"); 902 log_to_screen("your boot loader. I shall therefore use LILO instead."); 903 #endif 904 #ifdef __IA64__ 905 log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI"); 906 log_to_screen("environment correctly. Please install it."); 907 fatal_error("Aborting"); 908 #endif 909 } 910 #ifdef __IA64__ 911 /* We force ELILO usage on IA64 */ 912 bkpinfo->make_cd_use_lilo = TRUE; 913 #endif 914 #endif 915 916 if (! bkpinfo->restore_data) { 917 i = flag_set['O'] + flag_set['V']; 918 if (i == 0) { 919 retval++; 920 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n"); 921 } 922 } 923 924 if ((! bkpinfo->restore_data) && (flag_set['Z'])) { 925 fatal_error("The -Z switch is only valid in restore mode"); 926 } 927 928 if (flag_set['Z']) { 929 if (! strcmp(flag_val['Z'], "nuke")) { 930 bkpinfo->restore_mode = nuke; 931 } else if (! strcmp(flag_val['Z'], "interactive")) { 932 bkpinfo->restore_mode = interactive; 933 } else if (! strcmp(flag_val['Z'], "compare")) { 934 bkpinfo->restore_mode = compare; 935 } else if (! strcmp(flag_val['Z'], "mbr")) { 936 bkpinfo->restore_mode = mbr; 937 } else if (! strcmp(flag_val['Z'], "iso")) { 938 bkpinfo->restore_mode = isoonly; 939 } else if (! strcmp(flag_val['Z'], "isonuke")) { 940 bkpinfo->restore_mode = isonuke; 941 } else { 942 bkpinfo->restore_mode = interactive; 943 } 944 } 945 946 /* and finally... */ 947 948 paranoid_free(tmp); 949 return (retval); 950 } 951 952 953 954 /** 955 * @addtogroup cliGroup 956 * @{ 957 */ 958 /** 959 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv. 960 * @param argc The argument count, including the program name; @p argc passed to main(). 961 * @param argv The argument vector; @p argv passed to main(). 962 * @param bkpinfo The backup information structure to populate. 963 * @return The number of problems with the command line (0 for success). 964 */ 965 int 966 handle_incoming_parameters(int argc, char *argv[]) 967 { 968 /*@ int *** */ 969 int res = 0; 970 int retval = 0; 971 int i = 0; 972 973 /*@ buffers *************** */ 974 char flag_val[128][MAX_STR_LEN]; 975 bool flag_set[128]; 976 977 for (i = 0; i < 128; i++) { 978 flag_val[i][0] = '\0'; 979 flag_set[i] = FALSE; 980 } 981 bkpinfo->media_size = 650; /* default */ 982 res = retrieve_switches_from_command_line(argc, argv, flag_val, flag_set); 983 retval += res; 984 if (!retval) { 985 res = process_switches(flag_val, flag_set); 986 retval += res; 987 } 988 989 log_msg(3, "Switches:-"); 990 for (i = 0; i < 128; i++) { 991 if (flag_set[i]) { 992 log_msg(3, "-%c %s", i, flag_val[i]); 993 } 994 } 995 bkpinfo->boot_type = mr_boot_type(); 996 997 return (retval); 994 998 } 995 999 … … 1058 1062 1059 1063 1060 /**1061 * Turn signal-trapping on or off.1062 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).1063 */1064 void set_signals(int on)1065 {1066 int signals[] = { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };1067 int i;1068 1069 signal(SIGPIPE, sigpipe_occurred);1070 for (i = 0; signals[i]; i++) {1071 if (on) {1072 signal(signals[i], terminate_daemon);1073 } else {1074 signal(signals[i], termination_in_progress);1075 }1076 }1077 }1078 1079 1080 1081 1064 1082 1065 /** … … 1091 1074 } 1092 1075 1076 1077 1078 /** 1079 * Turn signal-trapping on or off. 1080 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much). 1081 */ 1082 void set_signals(int on) 1083 { 1084 int signals[] = { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 }; 1085 int i; 1086 1087 signal(SIGPIPE, sigpipe_occurred); 1088 for (i = 0; signals[i]; i++) { 1089 if (on) { 1090 signal(signals[i], terminate_daemon); 1091 } else { 1092 signal(signals[i], termination_in_progress); 1093 } 1094 } 1095 } 1096 1093 1097 /* @} - end of cliGroup */ -
branches/3.3/mondo/src/common/libmondo-devices.c
r3878 r3879 80 80 81 81 /** 82 * Retract all CD trays and wait for autorun to complete.83 * @ingroup deviceGroup84 */85 void retract_CD_tray_and_defeat_autorun(void)86 {87 // log_it("rctada: Retracting optical tray", __LINE__);88 if (!bkpinfo->please_dont_eject) {89 if (bkpinfo->media_device != NULL) {90 inject_device(bkpinfo->media_device);91 }92 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {93 log_it("autorun detected; sleeping for 2 seconds");94 sleep(2);95 }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 by104 * caller105 * @bug A bit of a misnomer; it's actually finding out the root device.106 * The mountpoint (where it's mounted) will obviously be '/'.107 */108 char *where_is_root_mounted(void) {109 110 /*@ buffers **************** */111 char *tmp = NULL;112 113 #ifdef __FreeBSD__114 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");115 #else116 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 #endif126 127 return (tmp);128 }129 130 131 132 /**133 * Determine whether we're booted off a ramdisk.134 * @return @c TRUE (we are) or @c FALSE (we aren't).135 * @ingroup utilityGroup136 */137 bool am_I_in_disaster_recovery_mode(void)138 {139 char *tmp = NULL;140 bool is_this_a_ramdisk = FALSE;141 142 tmp = where_is_root_mounted();143 log_msg(0, "root is mounted at %s", tmp);144 log_msg(0, "That doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().", tmp);145 146 #ifdef __FreeBSD__147 if (strstr(tmp, "/dev/md")) {148 is_this_a_ramdisk = TRUE;149 }150 #else151 if (!strncmp(tmp, "/dev/ram", 8)152 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")153 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")154 || !strcmp(tmp, "/dev/root")) {155 is_this_a_ramdisk = TRUE;156 } else {157 is_this_a_ramdisk = FALSE;158 }159 #endif160 mr_free(tmp);161 162 if (is_this_a_ramdisk) {163 if (!does_file_exist("/THIS-IS-A-RAMDISK")) {164 log_to_screen("Using /dev/root is stupid of you but I'll forgive you.");165 is_this_a_ramdisk = FALSE;166 }167 }168 if (does_file_exist("/THIS-IS-A-RAMDISK")) {169 is_this_a_ramdisk = TRUE;170 }171 172 log_msg(1, "Is this a ramdisk? result = %s", (is_this_a_ramdisk) ? "TRUE" : "FALSE");173 return (is_this_a_ramdisk);174 }175 176 177 178 179 180 /**181 * Turn @c bkpinfo->backup_media_type into a human-readable string.182 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).183 * @note The returned string points to static storage that will be overwritten with each call.184 * @ingroup stringGroup185 */186 static char *bkptype_to_string(t_bkptype bt)187 {188 static char output[MAX_STR_LEN / 4];189 switch (bt) {190 case none:191 strcpy(output, "none");192 break;193 case iso:194 strcpy(output, "iso");195 break;196 case cdr:197 strcpy(output, "cdr");198 break;199 case cdstream:200 strcpy(output, "cdstream");201 break;202 case netfs:203 strcpy(output, "netfs");204 break;205 case tape:206 strcpy(output, "tape");207 break;208 case udev:209 strcpy(output, "udev");210 break;211 case usb:212 strcpy(output, "usb");213 break;214 default:215 strcpy(output, "default");216 }217 return (output);218 }219 220 221 222 /**223 * @addtogroup deviceGroup224 * @{225 */226 /**227 * Eject the tray of the specified CD device.228 * @param dev The device to eject.229 * @return the return value of the @c eject command. (0=success, nonzero=failure)230 */231 int eject_device(char *dev)232 {233 char *command = NULL;234 int res1 = 0, res2 = 0;235 236 if (dev == NULL) {237 return (1);238 }239 240 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)241 && g_backup_media_type != udev) {242 mr_asprintf(command, "mt -f %s offline", dev);243 res1 = run_program_and_log_output(command, 1);244 mr_free(command);245 } else {246 res1 = 0;247 }248 249 #ifdef __FreeBSD__250 if (strstr(dev, "acd")) {251 mr_asprintf(command, "cdcontrol -f %s eject", dev);252 } else {253 mr_asprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`", dev);254 }255 #else256 mr_asprintf(command, "eject %s", dev);257 #endif258 259 log_msg(3, "Ejecting %s", dev);260 res2 = run_program_and_log_output(command, 1);261 mr_free(command);262 if (res1 && res2) {263 return (1);264 } else {265 return (0);266 }267 }268 269 /**270 * Load (inject) the tray of the specified CD device.271 * @param dev The device to load/inject.272 * @return 0 for success, nonzero for failure.273 */274 int inject_device(char *dev)275 {276 char *command = NULL;277 int i;278 279 if (dev == NULL) {280 return (1);281 }282 283 #ifdef __FreeBSD__284 if (strstr(dev, "acd")) {285 mr_asprintf(command, "cdcontrol -f %s close", dev);286 } else {287 mr_asprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`", dev);288 }289 #else290 mr_asprintf(command, "eject -t %s", dev);291 #endif292 i = run_program_and_log_output(command, FALSE);293 mr_free(command);294 return (i);295 }296 297 298 /**299 * Determine whether the specified @p device (really, you can use any file)300 * exists.301 * @return TRUE if it exists, FALSE if it doesn't.302 */303 bool does_device_exist(char *device)304 {305 306 /*@ buffers *********************************************************** */307 char *tmp = NULL;308 bool ret;309 310 assert_string_is_neither_NULL_nor_zerolength(device);311 312 mr_asprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);313 314 if (system(tmp)) {315 ret = FALSE;316 } else {317 ret = TRUE;318 }319 mr_free(tmp);320 return (ret);321 }322 323 324 /**325 * Determine whether a non-Microsoft partition exists on any connected hard drive.326 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent machine).327 */328 bool does_nonMS_partition_exist(void)329 {330 #if __FreeBSD__331 return332 !system("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");333 #else334 return335 !system("mr-parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|EFI|FAT|NTFS)'");336 #endif337 }338 339 /**340 * Determine whether the specified @p partno exists on the specified @p drive.341 * @param drive The drive to search for the partition in.342 * @param partno The partition number to look for.343 * @return 0 if it exists, nonzero otherwise.344 */345 int does_partition_exist(const char *drive, int partno)346 {347 /*@ buffers **************************************************** */348 char *program = NULL;349 char *incoming = NULL;350 char *searchstr = NULL;351 352 /*@ ints ******************************************************* */353 int res = 0;354 355 /*@ pointers *************************************************** */356 FILE *fin;357 358 /*@ end vars *************************************************** */359 assert_string_is_neither_NULL_nor_zerolength(drive);360 assert(partno >= 0 && partno < 999);361 362 #ifdef __FreeBSD__363 // We assume here that this is running from mondorestore. (It is.)364 tmp = build_partition_name(drive, partno);365 mr_asprintf(program, "ls %s %s >/dev/null 2>&1", drive, tmp);366 mr_free(tmp);367 res = system(program);368 mr_free(program);369 return(res);370 #endif371 372 mr_asprintf(program, "mr-parted2fdisk -l %s 2> /dev/null", drive);373 fin = popen(program, "r");374 if (!fin) {375 log_it("program=%s", program);376 log_OS_error("Cannot popen-in program");377 mr_free(program);378 return (0);379 }380 mr_free(program);381 382 searchstr = build_partition_name(drive, partno);383 mr_strcat(searchstr, " ");384 for (res = 0, mr_getline(incoming, fin); !res && !feof(fin) ; mr_getline(incoming, fin)) {385 if (strstr(incoming, searchstr)) {386 res = 1;387 }388 mr_free(incoming);389 }390 mr_free(searchstr);391 mr_free(incoming);392 393 if (pclose(fin)) {394 log_OS_error("Cannot pclose fin");395 }396 return (res);397 }398 399 400 401 402 403 /**404 * Determine whether given NULL-terminated @p str exists in the begining of @p dev.405 * @param dev The device to look in.406 * @param str The string to look for.407 * @return TRUE if it exists, FALSE if it doesn't.408 */409 bool does_string_exist_in_boot_block(char *dev, char *str)410 {411 /*@ buffers **************************************************** */412 char *command = NULL;413 414 /*@ end vars *************************************************** */415 int i;416 417 assert_string_is_neither_NULL_nor_zerolength(dev);418 assert_string_is_neither_NULL_nor_zerolength(str);419 420 /* For UEFI detection, this should be extended to count=1000 ! */421 if (bkpinfo->boot_type == UEFI) {422 mr_asprintf(command, "dd if=%s bs=446 count=1000 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str);423 } else {424 mr_asprintf(command, "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str);425 }426 i = system(command);427 mr_free(command);428 if (i) {429 return (FALSE);430 } else {431 return (TRUE);432 }433 }434 435 /**436 * Determine whether specified @p str exists in the first @p n sectors of437 * @p dev.438 * @param dev The device to look in.439 * @param str The string to look for.440 * @param n The number of 512-byte sectors to search.441 */442 bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)443 {444 /*@ buffers **************************************************** */445 char *command = NULL;446 /*@ end vars *************************************************** */447 int i;448 449 mr_asprintf(command, "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, n, str);450 i = system(command);451 mr_free(command);452 if (i) {453 return (FALSE);454 } else {455 return (TRUE);456 }457 }458 459 460 /*461 * This function tries to find an optical media device462 * and return it's device file to the caller that needs to free it463 */464 char *find_optical_device(void) {465 char *dev = NULL;466 char *tmp1 = NULL;467 char *command = NULL;468 469 log_to_screen("I am looking for your optical burner. Please wait.");470 471 if (bkpinfo->media_device != NULL) {472 log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);473 return (bkpinfo->media_device);474 }475 476 mr_asprintf(tmp1, "cdrecord -inq 2> /dev/null | grep -E '^Detected ' | cut -d':' -f2");477 dev = call_program_and_get_last_line_of_output(tmp1);478 mr_free(tmp1);479 480 if ((dev != NULL) && does_file_exist(dev)) {481 log_msg(2, "find_optical_device found %s automatically", dev);482 } else {483 mr_free(dev);484 tmp1 = find_home_of_exe("lsscsi");485 if (tmp1 != NULL) {486 mr_asprintf(command, "%s | grep ' cd' | awk '{print $NF}' | head -1", tmp1);487 dev = call_program_and_get_last_line_of_output(command);488 mr_free(command);489 }490 mr_free(tmp1);491 492 if ((dev == NULL) || !does_file_exist(dev)) {493 /* trying something else then */494 mr_asprintf(dev, "%s", VANILLA_SCSI_CDROM);495 if (!does_file_exist(dev)) {496 mr_asprintf(dev, "%s", ALT_CDROM);497 if (!does_file_exist(dev)) {498 mr_asprintf(dev, "%s", "/dev/cdrom");499 if (!does_file_exist(dev)) {500 mr_asprintf(dev, "%s", "/dev/dvd");501 if (!does_file_exist(dev)) {502 log_it("Unable to find a tape device on this system");503 }504 }505 }506 }507 }508 if (dev != NULL) {509 log_it("find_optical_device found %s manually", dev);510 }511 }512 513 if ((dev != NULL) && does_file_exist(dev)) {514 log_it("find_optical_device returns %s", dev);515 } else {516 mr_free(dev);517 log_it("find_optical_device found no optical burner on your system returning NULL");518 }519 return(dev);520 }521 /**522 * Mount the CD-ROM or USB device at /mnt/cdrom.523 * @param bkpinfo The backup information structure. Fields used:524 * - @c bkpinfo->backup_media_type525 * - @c bkpinfo->disaster_recovery526 * - @c bkpinfo->isodir527 * - @c bkpinfo->media_device528 * @return TRUE for success, FALSE for failure.529 */530 bool mount_media(const char *mountpoint) {531 532 char *mount_cmd = NULL;533 char *mountdir = NULL;534 char *tmp = NULL;535 int i = 0, res = 0;536 #ifdef __FreeBSD__537 char mdd[32];538 char *mddev = mdd;539 char *dev;540 #endif541 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 // NETFS569 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 // ISO572 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 #else579 if (bkpinfo->netfs_remote_dir != NULL) {580 // NETFS581 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 // ISO584 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 #endif587 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 #else601 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, mountpoint);602 #endif603 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 { // optical607 if (bkpinfo->disaster_recovery608 && 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 = dev625 }626 627 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE);628 #else629 mr_asprintf(mount_cmd, "mount %s -o loop,ro -t iso9660 %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE);630 #endif631 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 has667 * 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_media671 */672 bool find_and_mount_actual_cd(char *mountpoint) {673 674 /*@ buffers ***************************************************** */675 676 /*@ int's ****************************************************** */677 bool res;678 679 /*@ end vars **************************************************** */680 681 assert(bkpinfo != NULL);682 assert_string_is_neither_NULL_nor_zerolength(mountpoint);683 684 if (bkpinfo->media_device == NULL) {685 bkpinfo->media_device = find_optical_device();686 }687 688 if (bkpinfo->backup_media_type != iso) {689 retract_CD_tray_and_defeat_autorun();690 }691 692 if ((bkpinfo->media_device == NULL) || (res = mount_media(mountpoint))) {693 mr_free(bkpinfo->media_device);694 if ((bkpinfo->media_device = mr_popup_and_get_string("CD-ROM device", "Please enter your CD-ROM's /dev device", "/dev/cdrom")) == NULL) {695 res = TRUE;696 } else {697 res = mount_media(mountpoint);698 }699 }700 if (res) {701 log_msg(1, "mount failed");702 } else {703 log_msg(1, "mount succeeded with %s", bkpinfo->media_device);704 }705 return (res);706 }707 /*708 * This function tries to find a USB media device709 * and return it's device file to the caller that needs to free it710 */711 char *find_usb_device(void)712 {713 char *dev = NULL;714 char *tmp1 = NULL;715 char *command = NULL;716 717 log_to_screen("I am looking for your USB key. Please wait.");718 719 if (bkpinfo->media_device != NULL) {720 log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);721 return (bkpinfo->media_device);722 }723 724 tmp1 = find_home_of_exe("lsscsi");725 if (tmp1 != NULL) {726 mr_asprintf(command, "%s | grep ' disk' | grep USB | awk '{print $NF}' | head -1", tmp1);727 dev = call_program_and_get_last_line_of_output(command);728 mr_free(command);729 }730 mr_free(tmp1);731 732 if ((dev == NULL) || !does_file_exist(dev)) {733 tmp1 = find_home_of_exe("lsblk");734 if (tmp1 != NULL) {735 mr_asprintf(command, "%s --noheadings --raw --output rm,tran,type,path --sort path | awk '/^1 usb disk/ {d=$4} END {print d}'", tmp1);736 dev = call_program_and_get_last_line_of_output(command);737 mr_free(command);738 }739 mr_free(tmp1);740 log_it("Unable to find a tape device on this system");741 }742 if (dev != NULL) {743 log_it("find_usb_device found %s manually", dev);744 }745 746 if ((dev != NULL) && does_file_exist(dev)) {747 log_it("find_usb_device returns %s", dev);748 } else {749 mr_free(dev);750 log_it("find_usb_device found no USB key on your system returning NULL");751 }752 return(dev);753 }754 755 756 757 /* Generic fund to find a media758 * Return a dynamically allocted string that caller needs to free759 * @media_type is the type of media to look for760 */761 762 char *find_device(t_bkptype media_type) {763 764 if (media_type == usb) {765 return(find_usb_device());766 } else if (media_type == tape) {767 return(find_tape_device());768 } else if ((media_type == dvd) || (media_type == cdr)) {769 return(find_optical_device());770 } else {771 return(NULL);772 }773 }774 775 776 777 778 #include <sys/ioctl.h>779 780 /**781 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls782 * and @c dmesg.783 * @param drive The device to find the size of.784 * @return size in megabytes.785 */786 long get_phys_size_of_drive(char *drive)787 {788 int fd;789 #if linux790 unsigned long long s = 0;791 int fileid, cylinders = 0;792 int cylindersize = 0;793 int gotgeo = 0;794 795 796 struct hd_geometry hdgeo;797 #elif __FreeBSD__798 off_t s;799 #endif800 801 long outvalA = -1;802 long outvalB = -1;803 long outvalC = -1;804 805 if ((fd = open(drive, O_RDONLY)) != -1) {806 if (ioctl(fd,807 #if linux808 #ifdef BLKGETSIZE64809 BLKGETSIZE64,810 #else811 BLKGETSIZE,812 #endif813 #elif __FreeBSD__814 DIOCGMEDIASIZE,815 #endif816 &s) != -1) {817 close(fd);818 // s>>11 works for older disks but not for newer ones819 outvalB =820 #if linux821 #ifdef BLKGETSIZE64822 s >> 20823 #else824 s >> 11825 #endif826 #else827 s >> 20828 #endif829 ;830 }831 }832 833 if (outvalB <= 0) {834 log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));835 #if linux836 fileid = open(drive, O_RDONLY);837 if (fileid != -1) {838 if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {839 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {840 cylindersize = hdgeo.heads * hdgeo.sectors / 2;841 outvalA = cylindersize * cylinders / 1024;842 log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",843 hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);844 gotgeo = 1;845 } else {846 log_msg(1, "Harddisk geometry wrong");847 }848 } else {849 log_msg(1,850 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",851 strerror(errno));852 }853 close(fileid);854 } else {855 log_msg(1, "Failed to open %s for reading: %s", drive,856 strerror(errno));857 }858 if (!gotgeo) {859 log_msg(1, "Failed to get harddisk geometry, using old mode");860 }861 #endif862 }863 // OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)864 // NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)865 866 outvalC = (outvalA > outvalB) ? outvalA : outvalB;867 868 // log_msg (5, "drive = %s, error = %s", drive, strerror (errno));869 // fatal_error ("GPSOD: Unable to get size of drive");870 log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,871 outvalC);872 873 return (outvalC);874 }875 876 /**877 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems878 * under Linux and @c lsvfs under FreeBSD.879 * @param format The format to test.880 * @return TRUE if the format is supported, FALSE if not.881 */882 bool is_this_a_valid_disk_format(char *format)883 {884 char *good_formats = NULL;885 char *command = NULL;886 char *format_sz = NULL;887 char *p = NULL;888 889 FILE *pin;890 int retval;891 892 assert_string_is_neither_NULL_nor_zerolength(format);893 894 mr_asprintf(format_sz, "%s ", format);895 896 #ifdef __FreeBSD__897 mr_asprintf(command, "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");898 #else899 mr_asprintf(command, "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");900 #endif901 902 pin = popen(command, "r");903 mr_free(command);904 905 if (!pin) {906 log_OS_error("Unable to read good formats");907 retval = 0;908 } else {909 mr_getline(p, pin);910 good_formats = mr_strip_spaces(p);911 mr_free(p);912 (void)pclose(pin);913 mr_strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)914 if (strstr(good_formats, format_sz)) {915 retval = 1;916 } else {917 retval = 0;918 }919 }920 mr_free(good_formats);921 mr_free(format_sz);922 923 return (retval);924 }925 926 927 /** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */928 929 /**930 * Determine whether @p device_raw is currently mounted.931 * @param device_raw The device to check.932 * @return TRUE if it's mounted, FALSE if not.933 */934 bool is_this_device_mounted(char *device_raw)935 {936 937 char *tmp = NULL;938 bool retval = FALSE;939 940 mr_asprintf(tmp, "mr-device-mounted %s > /dev/null", device_raw);941 if (system(tmp) == 0) {942 retval = TRUE;943 }944 mr_free(tmp);945 return(retval);946 }947 948 /* previous C version replaced by a call to a perl script, fixing issues with symlinks between devices - RHEL7 e.g.949 FILE *fin;950 951 char *incoming = NULL;952 char *device_with_tab = NULL;953 char *device_with_space = NULL;954 char *tmp = NULL;955 bool retval = FALSE;956 957 #ifdef __FreeBSD__958 #define SWAPLIST_COMMAND "swapinfo"959 #else960 #define SWAPLIST_COMMAND "cat /proc/swaps"961 #endif962 963 964 if (device_raw == NULL) {965 return(FALSE);966 }967 968 if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {969 log_msg(1, "%s needs to have a '/' prefixed - I'll do it", device_raw);970 mr_asprintf(tmp, "/%s", device_raw);971 } else {972 mr_asprintf(tmp, "%s", device_raw);973 }974 log_msg(1, "Is %s mounted?", tmp);975 if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {976 log_msg(1, "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");977 mr_free(tmp);978 return(FALSE);979 }980 mr_asprintf(device_with_tab, "%s\t", tmp);981 mr_asprintf(device_with_space, "%s ", tmp);982 mr_free(tmp);983 984 if (!(fin = popen("mount", "r"))) {985 log_OS_error("Cannot popen 'mount'");986 return(FALSE);987 }988 989 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {990 if (strstr(incoming, device_with_space) || strstr(incoming, device_with_tab)) {991 paranoid_pclose(fin);992 mr_free(incoming);993 return(TRUE);994 }995 mr_free(incoming);996 }997 mr_free(incoming);998 mr_free(device_with_tab);999 paranoid_pclose(fin);1000 1001 mr_asprintf(tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null", SWAPLIST_COMMAND, device_with_space);1002 mr_free(device_with_space);1003 log_msg(4, "tmp (command) = '%s'", tmp);1004 if (!system(tmp)) {1005 retval = TRUE;1006 }1007 mr_free(tmp);1008 return(retval);1009 }1010 */1011 1012 #ifdef __FreeBSD__1013 // CODE IS FREEBSD-SPECIFIC1014 /**1015 * Create a loopback device for specified @p fname.1016 * @param fname The file to associate with a device.1017 * @return /dev entry for the device, or NULL if it couldn't be allocated.1018 */1019 char *make_vn(char *fname)1020 {1021 char *device = (char *) malloc(MAX_STR_LEN);1022 char *mddevice = NULL;1023 char *command = NULL;1024 char *tmp = NULL;1025 int vndev = 2;1026 1027 tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate");1028 if (atoi(tmp) < 500000) {1029 do {1030 mr_asprintf(mddevice, "vn%ic", vndev++);1031 mr_free(command);1032 mr_asprintf(command, "vnconfig %s %s", mddevice, fname);1033 if (vndev > 10) {1034 mr_free(tmp);1035 mr_free(mddevice);1036 mr_free(command);1037 return NULL;1038 }1039 }1040 while (system(command));1041 } else {1042 mr_asprintf(command, "mdconfig -a -t vnode -f %s", fname);1043 mddevice = call_program_and_get_last_line_of_output(command);1044 if (!strstr(mddevice, "md")) {1045 mr_free(tmp);1046 mr_free(command);1047 mr_free(mddevice);1048 return NULL;1049 }1050 }1051 mr_free(tmp);1052 mr_free(command);1053 sprintf(device, "/dev/%s", mddevice);1054 mr_free(mddevice);1055 return device;1056 }1057 1058 1059 1060 // CODE IS FREEBSD-SPECIFIC1061 /**1062 * Deallocate specified @p dname.1063 * This should be called when you are done with the device created by make_vn(),1064 * so the system does not run out of @c vn devices.1065 * @param dname The device to deallocate.1066 * @return 0 for success, nonzero for failure.1067 */1068 int kick_vn(char *dname)1069 {1070 char *command = NULL;1071 char *tmp = NULL;1072 int res = 0;1073 1074 if (strncmp(dname, "/dev/", 5) == 0) {1075 dname += 5;1076 }1077 1078 tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate");1079 if (atoi(tmp) < 500000) {1080 mr_asprintf(command, "vnconfig -d %s", dname);1081 } else {1082 mr_asprintf(command, "mdconfig -d -u %s", dname);1083 }1084 mr_free(tmp);1085 res = system(command);1086 mr_free(command);1087 return(res);1088 }1089 #endif1090 1091 1092 /**1093 * Mount the CD-ROM at @p mountpoint.1094 * @param device The device (or file if g_ISO_restore_mode) to mount.1095 * @param mountpoint The place to mount it.1096 * @return 0 for success, nonzero for failure.1097 */1098 int mount_USB_here(char *device, char *mountpoint)1099 {1100 /*@ buffer ****************************************************** */1101 char *command = NULL;1102 int retval;1103 1104 assert_string_is_neither_NULL_nor_zerolength(device);1105 assert_string_is_neither_NULL_nor_zerolength(mountpoint);1106 1107 make_hole_for_dir(mountpoint);1108 if (isdigit(device[0])) {1109 return(1);1110 }1111 log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device, mountpoint);1112 1113 #ifdef __FreeBSD__1114 mr_asprintf(command, "mount_vfat %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);1115 1116 #else1117 mr_asprintf(command, "mount %s -t vfat %s 2>> %s", device, mountpoint, MONDO_LOGFILE);1118 #endif1119 1120 log_msg(4, command);1121 retval = system(command);1122 log_msg(1, "system(%s) returned %d", command, retval);1123 mr_free(command);1124 1125 return (retval);1126 }1127 1128 /**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 mounted1133 * (and remain mounted after this function returns).1134 */1135 int what_number_cd_is_this(void) {1136 1137 int cd_number = -1;1138 char *mountdev = NULL;1139 char *tmp = NULL;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");1146 mr_free(tmp);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 }1167 1168 1169 1170 1171 /**1172 * Ask the user for CD number @p cd_number_i_want.1173 * Sets g_current_media_number once the correct CD is inserted.1174 * @param bkpinfo The backup information structure. Fields used:1175 * - @c bkpinfo->backup_media_type1176 * - @c bkpinfo->prefix1177 * - @c bkpinfo->isodir1178 * - @c bkpinfo->media_device1179 * - @c bkpinfo->please_dont_eject_when_restoring1180 * @param cd_number_i_want The CD number to ask for.1181 */1182 void1183 insist_on_this_cd_number(int cd_number_i_want)1184 {1185 1186 /*@ int ************************************************************* */1187 int res = 0;1188 1189 1190 /*@ buffers ********************************************************* */1191 char *tmp = NULL;1192 char *mds = NULL;1193 char *request = NULL;1194 1195 assert(bkpinfo != NULL);1196 assert(cd_number_i_want > 0);1197 1198 // log_msg(3, "Insisting on CD number %d", cd_number_i_want);1199 1200 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {1201 log_msg(3,1202 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");1203 return;1204 }1205 if (!does_file_exist(MNT_CDROM)) {1206 mr_asprintf(tmp, "mkdir -p " MNT_CDROM);1207 run_program_and_log_output(tmp, 5);1208 mr_free(tmp);1209 }1210 1211 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso || bkpinfo->backup_media_type == netfs) {1212 g_ISO_restore_mode = TRUE;1213 }1214 if ((res = what_number_cd_is_this()) != cd_number_i_want) {1215 log_msg(3, "Currently, we hold %d but we want %d", res, cd_number_i_want);1216 1217 /* Now we need to umount the current media to have the next mounted after */1218 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);1219 log_msg(3, "Mounting next media %d",cd_number_i_want);1220 g_current_media_number = cd_number_i_want;1221 mount_media(MNT_CDROM);1222 1223 mds = media_descriptor_string(bkpinfo->backup_media_type);1224 log_msg(3, "Insisting on %s #%d", mds, cd_number_i_want);1225 mr_asprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);1226 mr_free(mds);1227 1228 while (what_number_cd_is_this() != cd_number_i_want) {1229 sync();1230 if (is_this_device_mounted(MNT_CDROM)) {1231 res =1232 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);1233 } else {1234 res = 0;1235 }1236 if (res) {1237 log_to_screen("WARNING - failed to unmount CD-ROM drive");1238 }1239 if (!bkpinfo->please_dont_eject) {1240 res = eject_device(bkpinfo->media_device);1241 } else {1242 res = 0;1243 }1244 if (res) {1245 log_to_screen("WARNING - failed to eject CD-ROM disk");1246 }1247 popup_and_OK(request);1248 if (!bkpinfo->please_dont_eject) {1249 inject_device(bkpinfo->media_device);1250 }1251 sync();1252 }1253 mr_free(request);1254 1255 log_msg(1, "Thankyou. Proceeding...");1256 g_current_media_number = cd_number_i_want;1257 }1258 }1259 1260 /* @} - end of deviceGroup */1261 1262 1263 1264 /**1265 * Creates a singly linked list of all of the non-NETFS mounted file systems.1266 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold1267 * the list of mounted file systems.1268 * @return None.1269 */1270 static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)1271 {1272 assert (DSFptr);1273 if (DSF_Head == NULL) {1274 DSF_Head = DSFptr;1275 } else {1276 DSF_Tail->next = DSFptr;1277 }1278 DSFptr->next = NULL;1279 DSF_Tail = DSFptr;1280 }1281 1282 /**1283 * Find the structure, in the singly linked list of all of the non-NETFS1284 * mounted file systems, that contains the specified device.1285 * @param device The device to find1286 * @return NULL if it didn't find the device, a pointer to the1287 * structure if it did.1288 */1289 static MOUNTED_FS_STRUCT *find_device_in_list (char *device)1290 {1291 MOUNTED_FS_STRUCT *DSFptr = NULL;1292 1293 DSFptr = DSF_Head;1294 while (DSFptr != NULL) {1295 if (!strcmp(DSFptr->device, device)) {1296 break;1297 }1298 DSFptr = DSFptr->next;1299 }1300 return (DSFptr);1301 }1302 1303 /**1304 * Find the structure, in the singly linked list of all of the non-NETFS1305 * mounted file systems, that contains the specified mount point.1306 * @param mount_point The mount point to find1307 * @return NULL is it didn't find the mount point, a pointer to the1308 * structure if it did.1309 */1310 static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)1311 {1312 MOUNTED_FS_STRUCT *DSFptr = NULL;1313 1314 DSFptr = DSF_Head;1315 while (DSFptr != NULL) {1316 if (!strcmp(DSFptr->mount_point, mount_point)) {1317 break;1318 }1319 DSFptr = DSFptr->next;1320 }1321 return (DSFptr);1322 }1323 1324 /**1325 82 * Frees the memory for all of the structures on the linked list of 1326 83 * all of the non-NETFS mounted file systems. … … 1339 96 DSF_Tail = NULL; 1340 97 } 98 99 100 /** 101 * Creates a singly linked list of all of the non-NETFS mounted file systems. 102 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold 103 * the list of mounted file systems. 104 * @return None. 105 */ 106 static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr) 107 { 108 assert (DSFptr); 109 if (DSF_Head == NULL) { 110 DSF_Head = DSFptr; 111 } else { 112 DSF_Tail->next = DSFptr; 113 } 114 DSFptr->next = NULL; 115 DSF_Tail = DSFptr; 116 } 117 1341 118 1342 119 … … 1415 192 } 1416 193 194 /** 195 * Find the structure, in the singly linked list of all of the non-NETFS 196 * mounted file systems, that contains the specified mount point. 197 * @param mount_point The mount point to find 198 * @return NULL is it didn't find the mount point, a pointer to the 199 * structure if it did. 200 */ 201 static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point) 202 { 203 MOUNTED_FS_STRUCT *DSFptr = NULL; 204 205 DSFptr = DSF_Head; 206 while (DSFptr != NULL) { 207 if (!strcmp(DSFptr->mount_point, mount_point)) { 208 break; 209 } 210 DSFptr = DSFptr->next; 211 } 212 return (DSFptr); 213 } 214 215 216 /** 217 * Find the structure, in the singly linked list of all of the non-NETFS 218 * mounted file systems, that contains the specified device. 219 * @param device The device to find 220 * @return NULL if it didn't find the device, a pointer to the 221 * structure if it did. 222 */ 223 static MOUNTED_FS_STRUCT *find_device_in_list(char *device) { 224 MOUNTED_FS_STRUCT *DSFptr = NULL; 225 226 DSFptr = DSF_Head; 227 while (DSFptr != NULL) { 228 if (!strcmp(DSFptr->device, device)) { 229 break; 230 } 231 DSFptr = DSFptr->next; 232 } 233 return (DSFptr); 234 } 1417 235 1418 236 … … 1749 567 1750 568 569 /** 570 * Load (inject) the tray of the specified CD device. 571 * @param dev The device to load/inject. 572 * @return 0 for success, nonzero for failure. 573 */ 574 int inject_device(char *dev) 575 { 576 char *command = NULL; 577 int i; 578 579 if (dev == NULL) { 580 return (1); 581 } 582 583 #ifdef __FreeBSD__ 584 if (strstr(dev, "acd")) { 585 mr_asprintf(command, "cdcontrol -f %s close", dev); 586 } else { 587 mr_asprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`", dev); 588 } 589 #else 590 mr_asprintf(command, "eject -t %s", dev); 591 #endif 592 i = run_program_and_log_output(command, FALSE); 593 mr_free(command); 594 return (i); 595 } 596 597 598 /** 599 * Retract all CD trays and wait for autorun to complete. 600 * @ingroup deviceGroup 601 */ 602 void retract_CD_tray_and_defeat_autorun(void) 603 { 604 // log_it("rctada: Retracting optical tray", __LINE__); 605 if (!bkpinfo->please_dont_eject) { 606 if (bkpinfo->media_device != NULL) { 607 inject_device(bkpinfo->media_device); 608 } 609 } 610 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) { 611 log_it("autorun detected; sleeping for 2 seconds"); 612 sleep(2); 613 } 614 } 615 616 617 618 /** 619 * Find out what device is mounted as root (/). 620 * @return Root device. 621 * @note The returned string points to storage that needs to be freed by 622 * caller 623 * @bug A bit of a misnomer; it's actually finding out the root device. 624 * The mountpoint (where it's mounted) will obviously be '/'. 625 */ 626 char *where_is_root_mounted(void) { 627 628 /*@ buffers **************** */ 629 char *tmp = NULL; 630 631 #ifdef __FreeBSD__ 632 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1"); 633 #else 634 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"); 635 if (strstr(tmp, "/dev/cciss/")) { 636 mr_free(tmp); 637 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"); 638 } 639 if (strstr(tmp, "/dev/md")) { 640 mr_free(tmp); 641 tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1"); 642 } 643 #endif 644 645 return (tmp); 646 } 647 648 649 650 /** 651 * Determine whether we're booted off a ramdisk. 652 * @return @c TRUE (we are) or @c FALSE (we aren't). 653 * @ingroup utilityGroup 654 */ 655 bool am_I_in_disaster_recovery_mode(void) 656 { 657 char *tmp = NULL; 658 bool is_this_a_ramdisk = FALSE; 659 660 tmp = where_is_root_mounted(); 661 log_msg(0, "root is mounted at %s", tmp); 662 log_msg(0, "That doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().", tmp); 663 664 #ifdef __FreeBSD__ 665 if (strstr(tmp, "/dev/md")) { 666 is_this_a_ramdisk = TRUE; 667 } 668 #else 669 if (!strncmp(tmp, "/dev/ram", 8) 670 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/") 671 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs") 672 || !strcmp(tmp, "/dev/root")) { 673 is_this_a_ramdisk = TRUE; 674 } else { 675 is_this_a_ramdisk = FALSE; 676 } 677 #endif 678 mr_free(tmp); 679 680 if (is_this_a_ramdisk) { 681 if (!does_file_exist("/THIS-IS-A-RAMDISK")) { 682 log_to_screen("Using /dev/root is stupid of you but I'll forgive you."); 683 is_this_a_ramdisk = FALSE; 684 } 685 } 686 if (does_file_exist("/THIS-IS-A-RAMDISK")) { 687 is_this_a_ramdisk = TRUE; 688 } 689 690 log_msg(1, "Is this a ramdisk? result = %s", (is_this_a_ramdisk) ? "TRUE" : "FALSE"); 691 return (is_this_a_ramdisk); 692 } 693 694 695 696 697 698 /** 699 * Turn @c bkpinfo->backup_media_type into a human-readable string. 700 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>). 701 * @note The returned string points to static storage that will be overwritten with each call. 702 * @ingroup stringGroup 703 */ 704 static char *bkptype_to_string(t_bkptype bt) 705 { 706 char *output = NULL; 707 switch (bt) { 708 case none: 709 mr_asprintf(output, "%s", "none"); 710 break; 711 case iso: 712 mr_asprintf(output, "%s", "iso"); 713 break; 714 case cdr: 715 mr_asprintf(output, "%s", "cdr"); 716 break; 717 case cdstream: 718 mr_asprintf(output, "%s", "cdstream"); 719 break; 720 case netfs: 721 mr_asprintf(output, "%s", "netfs"); 722 break; 723 case tape: 724 mr_asprintf(output, "%s", "tape"); 725 break; 726 case udev: 727 mr_asprintf(output, "%s", "udev"); 728 break; 729 case usb: 730 mr_asprintf(output, "%s", "usb"); 731 break; 732 default: 733 mr_asprintf(output, "%s", "default"); 734 } 735 return (output); 736 } 737 738 739 740 /** 741 * @addtogroup deviceGroup 742 * @{ 743 */ 744 /** 745 * Eject the tray of the specified CD device. 746 * @param dev The device to eject. 747 * @return the return value of the @c eject command. (0=success, nonzero=failure) 748 */ 749 int eject_device(char *dev) 750 { 751 char *command = NULL; 752 int res1 = 0, res2 = 0; 753 754 if (dev == NULL) { 755 return (1); 756 } 757 758 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type) 759 && g_backup_media_type != udev) { 760 mr_asprintf(command, "mt -f %s offline", dev); 761 res1 = run_program_and_log_output(command, 1); 762 mr_free(command); 763 } else { 764 res1 = 0; 765 } 766 767 #ifdef __FreeBSD__ 768 if (strstr(dev, "acd")) { 769 mr_asprintf(command, "cdcontrol -f %s eject", dev); 770 } else { 771 mr_asprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`", dev); 772 } 773 #else 774 mr_asprintf(command, "eject %s", dev); 775 #endif 776 777 log_msg(3, "Ejecting %s", dev); 778 res2 = run_program_and_log_output(command, 1); 779 mr_free(command); 780 if (res1 && res2) { 781 return (1); 782 } else { 783 return (0); 784 } 785 } 786 787 /** 788 * Determine whether a non-Microsoft partition exists on any connected hard drive. 789 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent machine). 790 */ 791 bool does_nonMS_partition_exist(void) 792 { 793 #if __FreeBSD__ 794 return 795 !system("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false"); 796 #else 797 return 798 !system("mr-parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|EFI|FAT|NTFS)'"); 799 #endif 800 } 801 802 /** 803 * Determine whether the specified @p partno exists on the specified @p drive. 804 * @param drive The drive to search for the partition in. 805 * @param partno The partition number to look for. 806 * @return 0 if it exists, nonzero otherwise. 807 */ 808 int does_partition_exist(const char *drive, int partno) 809 { 810 /*@ buffers **************************************************** */ 811 char *program = NULL; 812 char *incoming = NULL; 813 char *searchstr = NULL; 814 815 /*@ ints ******************************************************* */ 816 int res = 0; 817 818 /*@ pointers *************************************************** */ 819 FILE *fin; 820 821 /*@ end vars *************************************************** */ 822 assert_string_is_neither_NULL_nor_zerolength(drive); 823 assert(partno >= 0 && partno < 999); 824 825 #ifdef __FreeBSD__ 826 // We assume here that this is running from mondorestore. (It is.) 827 tmp = build_partition_name(drive, partno); 828 mr_asprintf(program, "ls %s %s >/dev/null 2>&1", drive, tmp); 829 mr_free(tmp); 830 res = system(program); 831 mr_free(program); 832 return(res); 833 #endif 834 835 mr_asprintf(program, "mr-parted2fdisk -l %s 2> /dev/null", drive); 836 fin = popen(program, "r"); 837 if (!fin) { 838 log_it("program=%s", program); 839 log_OS_error("Cannot popen-in program"); 840 mr_free(program); 841 return (0); 842 } 843 mr_free(program); 844 845 searchstr = build_partition_name(drive, partno); 846 mr_strcat(searchstr, " "); 847 for (res = 0, mr_getline(incoming, fin); !res && !feof(fin) ; mr_getline(incoming, fin)) { 848 if (strstr(incoming, searchstr)) { 849 res = 1; 850 } 851 mr_free(incoming); 852 } 853 mr_free(searchstr); 854 mr_free(incoming); 855 856 if (pclose(fin)) { 857 log_OS_error("Cannot pclose fin"); 858 } 859 return (res); 860 } 861 862 863 864 865 866 /** 867 * Determine whether given NULL-terminated @p str exists in the begining of @p dev. 868 * @param dev The device to look in. 869 * @param str The string to look for. 870 * @return TRUE if it exists, FALSE if it doesn't. 871 */ 872 bool does_string_exist_in_boot_block(char *dev, char *str) 873 { 874 /*@ buffers **************************************************** */ 875 char *command = NULL; 876 877 /*@ end vars *************************************************** */ 878 int i; 879 880 assert_string_is_neither_NULL_nor_zerolength(dev); 881 assert_string_is_neither_NULL_nor_zerolength(str); 882 883 /* For UEFI detection, this should be extended to count=1000 ! */ 884 if (bkpinfo->boot_type == UEFI) { 885 mr_asprintf(command, "dd if=%s bs=446 count=1000 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str); 886 } else { 887 mr_asprintf(command, "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str); 888 } 889 i = system(command); 890 mr_free(command); 891 if (i) { 892 return (FALSE); 893 } else { 894 return (TRUE); 895 } 896 } 897 898 /** 899 * Determine whether specified @p str exists in the first @p n sectors of 900 * @p dev. 901 * @param dev The device to look in. 902 * @param str The string to look for. 903 * @param n The number of 512-byte sectors to search. 904 */ 905 bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n) 906 { 907 /*@ buffers **************************************************** */ 908 char *command = NULL; 909 /*@ end vars *************************************************** */ 910 int i; 911 912 mr_asprintf(command, "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, n, str); 913 i = system(command); 914 mr_free(command); 915 if (i) { 916 return (FALSE); 917 } else { 918 return (TRUE); 919 } 920 } 921 922 923 /* 924 * This function tries to find an optical media device 925 * and return it's device file to the caller that needs to free it 926 */ 927 char *find_optical_device(void) { 928 char *dev = NULL; 929 char *tmp1 = NULL; 930 char *command = NULL; 931 932 log_to_screen("I am looking for your optical burner. Please wait."); 933 934 if (bkpinfo->media_device != NULL) { 935 log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device); 936 return (bkpinfo->media_device); 937 } 938 939 mr_asprintf(tmp1, "cdrecord -inq 2> /dev/null | grep -E '^Detected ' | cut -d':' -f2"); 940 dev = call_program_and_get_last_line_of_output(tmp1); 941 mr_free(tmp1); 942 943 if ((dev != NULL) && does_file_exist(dev)) { 944 log_msg(2, "find_optical_device found %s automatically", dev); 945 } else { 946 mr_free(dev); 947 tmp1 = find_home_of_exe("lsscsi"); 948 if (tmp1 != NULL) { 949 mr_asprintf(command, "%s | grep ' cd' | awk '{print $NF}' | head -1", tmp1); 950 dev = call_program_and_get_last_line_of_output(command); 951 mr_free(command); 952 } 953 mr_free(tmp1); 954 955 if ((dev == NULL) || !does_file_exist(dev)) { 956 /* trying something else then */ 957 mr_asprintf(dev, "%s", VANILLA_SCSI_CDROM); 958 if (!does_file_exist(dev)) { 959 mr_asprintf(dev, "%s", ALT_CDROM); 960 if (!does_file_exist(dev)) { 961 mr_asprintf(dev, "%s", "/dev/cdrom"); 962 if (!does_file_exist(dev)) { 963 mr_asprintf(dev, "%s", "/dev/dvd"); 964 if (!does_file_exist(dev)) { 965 log_it("Unable to find a tape device on this system"); 966 } 967 } 968 } 969 } 970 } 971 if (dev != NULL) { 972 log_it("find_optical_device found %s manually", dev); 973 } 974 } 975 976 if ((dev != NULL) && does_file_exist(dev)) { 977 log_it("find_optical_device returns %s", dev); 978 } else { 979 mr_free(dev); 980 log_it("find_optical_device found no optical burner on your system returning NULL"); 981 } 982 return(dev); 983 } 984 /** 985 * Mount the CD-ROM or USB device at /mnt/cdrom. 986 * @param bkpinfo The backup information structure. Fields used: 987 * - @c bkpinfo->backup_media_type 988 * - @c bkpinfo->disaster_recovery 989 * - @c bkpinfo->isodir 990 * - @c bkpinfo->media_device 991 * @return TRUE for success, FALSE for failure. 992 */ 993 bool mount_media(const char *mountpoint) { 994 995 char *mount_cmd = NULL; 996 char *mountdir = NULL; 997 char *tmp = NULL; 998 int i = 0, res = 0; 999 #ifdef __FreeBSD__ 1000 char mdd[32]; 1001 char *mddev = mdd; 1002 char *dev; 1003 #endif 1004 1005 if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) { 1006 log_msg(8, "Tape/udev. Therefore, no need to mount a media."); 1007 return(TRUE); 1008 } 1009 1010 assert_string_is_neither_NULL_nor_zerolength(mountpoint); 1011 1012 mr_asprintf(tmp, "mount | grep -F %s", mountpoint); 1013 if (!run_program_and_log_output(tmp, FALSE)) { 1014 log_msg(2, "mount_media() - media already mounted. Fair enough."); 1015 mr_free(tmp); 1016 return (TRUE); 1017 } 1018 mr_free(tmp); 1019 1020 make_hole_for_dir(mountpoint); 1021 1022 if (bkpinfo->backup_media_type == netfs) { 1023 log_msg(2, "Mounting for Network thingy"); 1024 log_msg(2, "isodir = %s", bkpinfo->isodir); 1025 if (((bkpinfo->isodir == NULL) || !strcmp(bkpinfo->isodir, "/")) && am_I_in_disaster_recovery_mode()) { 1026 mr_asprintf(bkpinfo->isodir, "%s", "/tmp/isodir"); 1027 log_msg(1, "isodir is being set to %s", bkpinfo->isodir); 1028 } 1029 #ifdef __FreeBSD__ 1030 if (bkpinfo->netfs_remote_dir != NULL) { 1031 // NETFS 1032 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number); 1033 } else { 1034 // ISO 1035 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number); 1036 } 1037 mddev = make_vn(mount_cmd); 1038 mr_free(mount_cmd); 1039 1040 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint); 1041 #else 1042 if (bkpinfo->netfs_remote_dir != NULL) { 1043 // NETFS 1044 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); 1045 } else { 1046 // ISO 1047 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, mountpoint); 1048 } 1049 #endif 1050 1051 } else if (bkpinfo->backup_media_type == iso) { 1052 if (bkpinfo->subdir) { 1053 mr_asprintf(mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir); 1054 } else { 1055 mr_asprintf(mountdir, "%s", bkpinfo->isodir); 1056 } 1057 #ifdef __FreeBSD__ 1058 mr_asprintf(mount_cmd, "%s/%s-%d.iso", mountdir, bkpinfo->prefix, g_current_media_number); 1059 mddev = make_vn(mount_cmd); 1060 mr_free(mount_cmd); 1061 1062 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint); 1063 #else 1064 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, mountpoint); 1065 #endif 1066 mr_free(mountdir); 1067 } else if (bkpinfo->backup_media_type == usb) { 1068 mr_asprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, mountpoint); 1069 } else { // optical 1070 if (bkpinfo->disaster_recovery 1071 && does_file_exist("/tmp/CDROM-LIVES-HERE")) { 1072 mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE")); 1073 } else { 1074 if (bkpinfo->media_device == NULL) { 1075 bkpinfo->media_device = find_optical_device(); 1076 } 1077 } 1078 1079 #ifdef __FreeBSD__ 1080 if (g_ISO_restore_mode) { 1081 mr_asprintf(dev, "%s", make_vn(bkpinfo->media_device)); 1082 if (!dev) { 1083 mr_asprintf(command, "Unable to mount ISO (make_vn(%s) failed)", bkpinfo->media_device); 1084 fatal_error(command); 1085 } 1086 mr_free(bkpinfo->media_device); 1087 bkpinfo->media_device = dev 1088 } 1089 1090 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE); 1091 #else 1092 mr_asprintf(mount_cmd, "mount %s -o loop,ro -t iso9660 %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE); 1093 #endif 1094 log_msg(2, "(mount_media) --- command = %s", mount_cmd); 1095 // usefull ?? 1096 if (strncmp(bkpinfo->media_device, "/dev/", 5) == 0) { 1097 retract_CD_tray_and_defeat_autorun(); 1098 } 1099 } 1100 1101 for (i = 0; i < 2; i++) { 1102 res = run_program_and_log_output(mount_cmd, FALSE); 1103 if (!res) { 1104 break; 1105 } else { 1106 log_msg(2, "Failed to mount device."); 1107 sleep(5); 1108 sync(); 1109 } 1110 } 1111 mr_free(mount_cmd); 1112 1113 if (res) { 1114 log_msg(2, "Failed, despite %d attempts", i); 1115 return(FALSE); 1116 } else { 1117 log_msg(2, "Mounted media drive OK"); 1118 return(TRUE); 1119 } 1120 } 1121 /************************************************************************** 1122 *END_MOUNT_MEDIA * 1123 **************************************************************************/ 1124 1125 1126 1127 1128 /** 1129 * Try to mount CD/DVD at @p mountpoint. If the CD/DVD is not found or has 1130 * not been specified, call find_optical_device() to find it. 1131 * @param mountpoint Where to mount the CD-ROM. 1132 * @return TRUE for success, FALSE for failure. 1133 * @see mount_media 1134 */ 1135 bool find_and_mount_actual_cd(char *mountpoint) { 1136 1137 /*@ buffers ***************************************************** */ 1138 1139 /*@ int's ****************************************************** */ 1140 bool res; 1141 1142 /*@ end vars **************************************************** */ 1143 1144 assert(bkpinfo != NULL); 1145 assert_string_is_neither_NULL_nor_zerolength(mountpoint); 1146 1147 if (bkpinfo->media_device == NULL) { 1148 bkpinfo->media_device = find_optical_device(); 1149 } 1150 1151 if (bkpinfo->backup_media_type != iso) { 1152 retract_CD_tray_and_defeat_autorun(); 1153 } 1154 1155 if ((bkpinfo->media_device == NULL) || (res = mount_media(mountpoint))) { 1156 mr_free(bkpinfo->media_device); 1157 if ((bkpinfo->media_device = mr_popup_and_get_string("CD-ROM device", "Please enter your CD-ROM's /dev device", "/dev/cdrom")) == NULL) { 1158 res = TRUE; 1159 } else { 1160 res = mount_media(mountpoint); 1161 } 1162 } 1163 if (res) { 1164 log_msg(1, "mount failed"); 1165 } else { 1166 log_msg(1, "mount succeeded with %s", bkpinfo->media_device); 1167 } 1168 return (res); 1169 } 1170 /* 1171 * This function tries to find a USB media device 1172 * and return it's device file to the caller that needs to free it 1173 */ 1174 char *find_usb_device(void) 1175 { 1176 char *dev = NULL; 1177 char *tmp1 = NULL; 1178 char *command = NULL; 1179 1180 log_to_screen("I am looking for your USB key. Please wait."); 1181 1182 if (bkpinfo->media_device != NULL) { 1183 log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device); 1184 return (bkpinfo->media_device); 1185 } 1186 1187 tmp1 = find_home_of_exe("lsscsi"); 1188 if (tmp1 != NULL) { 1189 mr_asprintf(command, "%s | grep ' disk' | grep USB | awk '{print $NF}' | head -1", tmp1); 1190 dev = call_program_and_get_last_line_of_output(command); 1191 mr_free(command); 1192 } 1193 mr_free(tmp1); 1194 1195 if ((dev == NULL) || !does_file_exist(dev)) { 1196 tmp1 = find_home_of_exe("lsblk"); 1197 if (tmp1 != NULL) { 1198 mr_asprintf(command, "%s --noheadings --raw --output rm,tran,type,path --sort path | awk '/^1 usb disk/ {d=$4} END {print d}'", tmp1); 1199 dev = call_program_and_get_last_line_of_output(command); 1200 mr_free(command); 1201 } 1202 mr_free(tmp1); 1203 log_it("Unable to find a tape device on this system"); 1204 } 1205 if (dev != NULL) { 1206 log_it("find_usb_device found %s manually", dev); 1207 } 1208 1209 if ((dev != NULL) && does_file_exist(dev)) { 1210 log_it("find_usb_device returns %s", dev); 1211 } else { 1212 mr_free(dev); 1213 log_it("find_usb_device found no USB key on your system returning NULL"); 1214 } 1215 return(dev); 1216 } 1217 1218 1219 1220 /* Generic fund to find a media 1221 * Return a dynamically allocted string that caller needs to free 1222 * @media_type is the type of media to look for 1223 */ 1224 1225 char *find_device(t_bkptype media_type) { 1226 1227 if (media_type == usb) { 1228 return(find_usb_device()); 1229 } else if (media_type == tape) { 1230 return(find_tape_device()); 1231 } else if ((media_type == dvd) || (media_type == cdr)) { 1232 return(find_optical_device()); 1233 } else { 1234 return(NULL); 1235 } 1236 } 1237 1238 1239 1240 1241 #include <sys/ioctl.h> 1242 1243 /** 1244 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls 1245 * and @c dmesg. 1246 * @param drive The device to find the size of. 1247 * @return size in megabytes. 1248 */ 1249 long get_phys_size_of_drive(char *drive) 1250 { 1251 int fd; 1252 #if linux 1253 unsigned long long s = 0; 1254 int fileid, cylinders = 0; 1255 int cylindersize = 0; 1256 int gotgeo = 0; 1257 1258 1259 struct hd_geometry hdgeo; 1260 #elif __FreeBSD__ 1261 off_t s; 1262 #endif 1263 1264 long outvalA = -1; 1265 long outvalB = -1; 1266 long outvalC = -1; 1267 1268 if ((fd = open(drive, O_RDONLY)) != -1) { 1269 if (ioctl(fd, 1270 #if linux 1271 #ifdef BLKGETSIZE64 1272 BLKGETSIZE64, 1273 #else 1274 BLKGETSIZE, 1275 #endif 1276 #elif __FreeBSD__ 1277 DIOCGMEDIASIZE, 1278 #endif 1279 &s) != -1) { 1280 close(fd); 1281 // s>>11 works for older disks but not for newer ones 1282 outvalB = 1283 #if linux 1284 #ifdef BLKGETSIZE64 1285 s >> 20 1286 #else 1287 s >> 11 1288 #endif 1289 #else 1290 s >> 20 1291 #endif 1292 ; 1293 } 1294 } 1295 1296 if (outvalB <= 0) { 1297 log_msg(1, "Error getting size of %s: %s", drive, strerror(errno)); 1298 #if linux 1299 fileid = open(drive, O_RDONLY); 1300 if (fileid != -1) { 1301 if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) { 1302 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) { 1303 cylindersize = hdgeo.heads * hdgeo.sectors / 2; 1304 outvalA = cylindersize * cylinders / 1024; 1305 log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d", 1306 hdgeo.cylinders, hdgeo.heads, hdgeo.sectors); 1307 gotgeo = 1; 1308 } else { 1309 log_msg(1, "Harddisk geometry wrong"); 1310 } 1311 } else { 1312 log_msg(1, 1313 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode", 1314 strerror(errno)); 1315 } 1316 close(fileid); 1317 } else { 1318 log_msg(1, "Failed to open %s for reading: %s", drive, 1319 strerror(errno)); 1320 } 1321 if (!gotgeo) { 1322 log_msg(1, "Failed to get harddisk geometry, using old mode"); 1323 } 1324 #endif 1325 } 1326 // OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :) 1327 // NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :) 1328 1329 outvalC = (outvalA > outvalB) ? outvalA : outvalB; 1330 1331 // log_msg (5, "drive = %s, error = %s", drive, strerror (errno)); 1332 // fatal_error ("GPSOD: Unable to get size of drive"); 1333 log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB, 1334 outvalC); 1335 1336 return (outvalC); 1337 } 1338 1339 /** 1340 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems 1341 * under Linux and @c lsvfs under FreeBSD. 1342 * @param format The format to test. 1343 * @return TRUE if the format is supported, FALSE if not. 1344 */ 1345 bool is_this_a_valid_disk_format(char *format) 1346 { 1347 char *good_formats = NULL; 1348 char *command = NULL; 1349 char *format_sz = NULL; 1350 char *p = NULL; 1351 1352 FILE *pin; 1353 int retval; 1354 1355 assert_string_is_neither_NULL_nor_zerolength(format); 1356 1357 mr_asprintf(format_sz, "%s ", format); 1358 1359 #ifdef __FreeBSD__ 1360 mr_asprintf(command, "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '"); 1361 #else 1362 mr_asprintf(command, "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '"); 1363 #endif 1364 1365 pin = popen(command, "r"); 1366 mr_free(command); 1367 1368 if (!pin) { 1369 log_OS_error("Unable to read good formats"); 1370 retval = 0; 1371 } else { 1372 mr_getline(p, pin); 1373 good_formats = mr_strip_spaces(p); 1374 mr_free(p); 1375 (void)pclose(pin); 1376 mr_strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 "); // " ntfs 7 " -- um, cheating much? :) 1377 if (strstr(good_formats, format_sz)) { 1378 retval = 1; 1379 } else { 1380 retval = 0; 1381 } 1382 } 1383 mr_free(good_formats); 1384 mr_free(format_sz); 1385 1386 return (retval); 1387 } 1388 1389 1390 /** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */ 1391 1392 /** 1393 * Determine whether @p device_raw is currently mounted. 1394 * @param device_raw The device to check. 1395 * @return TRUE if it's mounted, FALSE if not. 1396 */ 1397 bool is_this_device_mounted(char *device_raw) 1398 { 1399 1400 char *tmp = NULL; 1401 bool retval = FALSE; 1402 1403 mr_asprintf(tmp, "mr-device-mounted %s > /dev/null", device_raw); 1404 if (system(tmp) == 0) { 1405 retval = TRUE; 1406 } 1407 mr_free(tmp); 1408 return(retval); 1409 } 1410 1411 #ifdef __FreeBSD__ 1412 // CODE IS FREEBSD-SPECIFIC 1413 /** 1414 * Create a loopback device for specified @p fname. 1415 * @param fname The file to associate with a device. 1416 * @return /dev entry for the device, or NULL if it couldn't be allocated. 1417 */ 1418 char *make_vn(char *fname) 1419 { 1420 char *device = (char *) malloc(MAX_STR_LEN); 1421 char *mddevice = NULL; 1422 char *command = NULL; 1423 char *tmp = NULL; 1424 int vndev = 2; 1425 1426 tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate"); 1427 if (atoi(tmp) < 500000) { 1428 do { 1429 mr_asprintf(mddevice, "vn%ic", vndev++); 1430 mr_free(command); 1431 mr_asprintf(command, "vnconfig %s %s", mddevice, fname); 1432 if (vndev > 10) { 1433 mr_free(tmp); 1434 mr_free(mddevice); 1435 mr_free(command); 1436 return NULL; 1437 } 1438 } 1439 while (system(command)); 1440 } else { 1441 mr_asprintf(command, "mdconfig -a -t vnode -f %s", fname); 1442 mddevice = call_program_and_get_last_line_of_output(command); 1443 if (!strstr(mddevice, "md")) { 1444 mr_free(tmp); 1445 mr_free(command); 1446 mr_free(mddevice); 1447 return NULL; 1448 } 1449 } 1450 mr_free(tmp); 1451 mr_free(command); 1452 sprintf(device, "/dev/%s", mddevice); 1453 mr_free(mddevice); 1454 return device; 1455 } 1456 1457 1458 1459 // CODE IS FREEBSD-SPECIFIC 1460 /** 1461 * Deallocate specified @p dname. 1462 * This should be called when you are done with the device created by make_vn(), 1463 * so the system does not run out of @c vn devices. 1464 * @param dname The device to deallocate. 1465 * @return 0 for success, nonzero for failure. 1466 */ 1467 int kick_vn(char *dname) 1468 { 1469 char *command = NULL; 1470 char *tmp = NULL; 1471 int res = 0; 1472 1473 if (strncmp(dname, "/dev/", 5) == 0) { 1474 dname += 5; 1475 } 1476 1477 tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate"); 1478 if (atoi(tmp) < 500000) { 1479 mr_asprintf(command, "vnconfig -d %s", dname); 1480 } else { 1481 mr_asprintf(command, "mdconfig -d -u %s", dname); 1482 } 1483 mr_free(tmp); 1484 res = system(command); 1485 mr_free(command); 1486 return(res); 1487 } 1488 #endif 1489 1490 1491 /** 1492 * Mount the CD-ROM at @p mountpoint. 1493 * @param device The device (or file if g_ISO_restore_mode) to mount. 1494 * @param mountpoint The place to mount it. 1495 * @return 0 for success, nonzero for failure. 1496 */ 1497 int mount_USB_here(char *device, char *mountpoint) 1498 { 1499 /*@ buffer ****************************************************** */ 1500 char *command = NULL; 1501 int retval; 1502 1503 assert_string_is_neither_NULL_nor_zerolength(device); 1504 assert_string_is_neither_NULL_nor_zerolength(mountpoint); 1505 1506 make_hole_for_dir(mountpoint); 1507 if (isdigit(device[0])) { 1508 return(1); 1509 } 1510 log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device, mountpoint); 1511 1512 #ifdef __FreeBSD__ 1513 mr_asprintf(command, "mount_vfat %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE); 1514 1515 #else 1516 mr_asprintf(command, "mount %s -t vfat %s 2>> %s", device, mountpoint, MONDO_LOGFILE); 1517 #endif 1518 1519 log_msg(4, command); 1520 retval = system(command); 1521 log_msg(1, "system(%s) returned %d", command, retval); 1522 mr_free(command); 1523 1524 return (retval); 1525 } 1526 1527 /** 1528 * Find out what number CD is in the drive. 1529 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used. 1530 * @return The current CD number, or -1 if it could not be found. 1531 * @note If the CD is not mounted, it will be mounted 1532 * (and remain mounted after this function returns). 1533 */ 1534 int what_number_cd_is_this(void) { 1535 1536 int cd_number = -1; 1537 char *mountdev = NULL; 1538 char *tmp = NULL; 1539 1540 assert(bkpinfo != NULL); 1541 // log_it("Asking what_number_cd_is_this"); 1542 if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) { 1543 tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'"); 1544 mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER"); 1545 mr_free(tmp); 1546 cd_number = atoi(last_line_of_file(mountdev)); 1547 mr_free(mountdev); 1548 return (cd_number); 1549 } 1550 1551 if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) { 1552 log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n"); 1553 /* trying again ! */ 1554 bkpinfo->media_device = find_optical_device(); 1555 } 1556 if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) { 1557 fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n"); 1558 } 1559 if (!is_this_device_mounted(MNT_CDROM)) { 1560 mount_media(MNT_CDROM); 1561 } 1562 1563 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER")); 1564 return(cd_number); 1565 } 1566 1567 1568 1569 1570 /** 1571 * Ask the user for CD number @p cd_number_i_want. 1572 * Sets g_current_media_number once the correct CD is inserted. 1573 * @param bkpinfo The backup information structure. Fields used: 1574 * - @c bkpinfo->backup_media_type 1575 * - @c bkpinfo->prefix 1576 * - @c bkpinfo->isodir 1577 * - @c bkpinfo->media_device 1578 * - @c bkpinfo->please_dont_eject_when_restoring 1579 * @param cd_number_i_want The CD number to ask for. 1580 */ 1581 void 1582 insist_on_this_cd_number(int cd_number_i_want) 1583 { 1584 1585 /*@ int ************************************************************* */ 1586 int res = 0; 1587 1588 1589 /*@ buffers ********************************************************* */ 1590 char *tmp = NULL; 1591 char *mds = NULL; 1592 char *request = NULL; 1593 1594 assert(bkpinfo != NULL); 1595 assert(cd_number_i_want > 0); 1596 1597 // log_msg(3, "Insisting on CD number %d", cd_number_i_want); 1598 1599 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 1600 log_msg(3, 1601 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO"); 1602 return; 1603 } 1604 if (!does_file_exist(MNT_CDROM)) { 1605 mr_asprintf(tmp, "mkdir -p " MNT_CDROM); 1606 run_program_and_log_output(tmp, 5); 1607 mr_free(tmp); 1608 } 1609 1610 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso || bkpinfo->backup_media_type == netfs) { 1611 g_ISO_restore_mode = TRUE; 1612 } 1613 if ((res = what_number_cd_is_this()) != cd_number_i_want) { 1614 log_msg(3, "Currently, we hold %d but we want %d", res, cd_number_i_want); 1615 1616 /* Now we need to umount the current media to have the next mounted after */ 1617 run_program_and_log_output("umount -d " MNT_CDROM, FALSE); 1618 log_msg(3, "Mounting next media %d",cd_number_i_want); 1619 g_current_media_number = cd_number_i_want; 1620 mount_media(MNT_CDROM); 1621 1622 mds = media_descriptor_string(bkpinfo->backup_media_type); 1623 log_msg(3, "Insisting on %s #%d", mds, cd_number_i_want); 1624 mr_asprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want); 1625 mr_free(mds); 1626 1627 while (what_number_cd_is_this() != cd_number_i_want) { 1628 sync(); 1629 if (is_this_device_mounted(MNT_CDROM)) { 1630 res = 1631 run_program_and_log_output("umount -d " MNT_CDROM, FALSE); 1632 } else { 1633 res = 0; 1634 } 1635 if (res) { 1636 log_to_screen("WARNING - failed to unmount CD-ROM drive"); 1637 } 1638 if (!bkpinfo->please_dont_eject) { 1639 res = eject_device(bkpinfo->media_device); 1640 } else { 1641 res = 0; 1642 } 1643 if (res) { 1644 log_to_screen("WARNING - failed to eject CD-ROM disk"); 1645 } 1646 popup_and_OK(request); 1647 if (!bkpinfo->please_dont_eject) { 1648 inject_device(bkpinfo->media_device); 1649 } 1650 sync(); 1651 } 1652 mr_free(request); 1653 1654 log_msg(1, "Thankyou. Proceeding..."); 1655 g_current_media_number = cd_number_i_want; 1656 } 1657 } 1658 1659 1751 1660 /* Update the bkpinfo structure for exclude & include paths 1752 1661 * in order to handle correctly paths corresponding to devices */ … … 2108 2017 // Tape, CD, NETFS, ...? 2109 2018 srandom(getpid()); 2110 bkpinfo->backup_media_type = 2111 (g_restoring_live_from_cd) ? cdr : 2112 which_backup_media_type(bkpinfo->restore_data); 2019 bkpinfo->backup_media_type = (g_restoring_live_from_cd) ? cdr : which_backup_media_type(bkpinfo->restore_data); 2113 2020 if (bkpinfo->backup_media_type == none) { 2114 2021 log_to_screen("User has chosen not to backup the machine"); 2115 2022 finish(1); 2116 2023 } 2117 log_msg(3, "media type = %s", bkptype_to_string(bkpinfo->backup_media_type)); 2024 tmp = bkptype_to_string(bkpinfo->backup_media_type); 2025 log_msg(3, "media type = %s", tmp); 2026 mr_free(tmp); 2118 2027 2119 2028 /* Why asking to remove the media with tape ? … … 2755 2664 log_it("media device = %s", bkpinfo->media_device); 2756 2665 log_it("media size = %ld", bkpinfo->media_size); 2757 log_it("media type = %s", bkptype_to_string(bkpinfo->backup_media_type)); 2666 tmp = bkptype_to_string(bkpinfo->backup_media_type); 2667 log_it("media type = %s", tmp); 2668 mr_free(tmp); 2758 2669 if (bkpinfo->prefix != NULL) { 2759 2670 log_it("prefix = %s", bkpinfo->prefix); -
branches/3.3/mondo/src/common/libmondo-fifo.c
r3865 r3879 23 23 #include "mr_mem.h" 24 24 #include "mondostructures.h" 25 #include "libmondo.h" 25 #include "libmondo-devices-EXT.h" 26 #include "libmondo-fork-EXT.h" 27 #include "newt-specific-EXT.h" 28 26 29 27 30 /** -
branches/3.3/mondo/src/common/libmondo-filelist.c
r3878 r3879 60 60 extern char *g_getfacl; 61 61 extern char *g_getfattr; 62 63 64 int sort_file(char *orig_fname) 65 { 66 char *tmp_fname = NULL; 67 char *command = NULL; 68 int retval = 0; 69 70 log_msg(5, "Sorting file %s", orig_fname); 71 72 if (!does_file_exist(orig_fname)) { 73 log_msg(2, "file %s empty", orig_fname); 74 return (0); 75 } // no sense in trying to sort an empty file 76 77 mr_asprintf(tmp_fname, "%s/sortfile", bkpinfo->tmpdir); 78 mr_asprintf(command, "sort %s > %s 2>> %s", orig_fname, tmp_fname, MONDO_LOGFILE); 79 retval = system(command); 80 mr_free(command); 81 82 if (retval) { 83 log_msg(2, "Failed to sort %s - oh dear", orig_fname); 84 } else { 85 log_msg(5, "Sorted %s --> %s OK. Copying it back to %s now", orig_fname, tmp_fname, orig_fname); 86 mr_asprintf(command, "mv -f %s %s", tmp_fname, orig_fname); 87 retval += run_program_and_log_output(command, 5); 88 mr_free(command); 89 90 if (retval) { 91 log_msg(2, "Failed to copy %s back to %s - oh dear", tmp_fname, orig_fname); 92 } else { 93 log_msg(5, "%s was sorted OK.", orig_fname); 94 } 95 } 96 mr_free(tmp_fname); 97 log_msg(5, "Finished sorting file %s", orig_fname); 98 return (retval); 99 } 100 62 101 63 102 … … 310 349 return (retval); 311 350 } 312 313 314 315 int sort_file(char *orig_fname)316 {317 char *tmp_fname = NULL;318 char *command = NULL;319 int retval = 0;320 321 log_msg(5, "Sorting file %s", orig_fname);322 323 if (!does_file_exist(orig_fname)) {324 log_msg(2, "file %s empty", orig_fname);325 return (0);326 } // no sense in trying to sort an empty file327 328 mr_asprintf(tmp_fname, "%s/sortfile", bkpinfo->tmpdir);329 mr_asprintf(command, "sort %s > %s 2>> %s", orig_fname, tmp_fname, MONDO_LOGFILE);330 retval = system(command);331 mr_free(command);332 333 if (retval) {334 log_msg(2, "Failed to sort %s - oh dear", orig_fname);335 } else {336 log_msg(5, "Sorted %s --> %s OK. Copying it back to %s now", orig_fname, tmp_fname, orig_fname);337 mr_asprintf(command, "mv -f %s %s", tmp_fname, orig_fname);338 retval += run_program_and_log_output(command, 5);339 mr_free(command);340 341 if (retval) {342 log_msg(2, "Failed to copy %s back to %s - oh dear", tmp_fname, orig_fname);343 } else {344 log_msg(5, "%s was sorted OK.", orig_fname);345 }346 }347 mr_free(tmp_fname);348 log_msg(5, "Finished sorting file %s", orig_fname);349 return (retval);350 }351 352 351 353 352 -
branches/3.3/mondo/src/common/libmondo-raid-EXT.h
r3855 r3879 22 22 extern void process_raidtab_line(FILE *, struct raid_device_record *, 23 23 char *, char *); 24 extern int save_raidlist_to_raidtab(struct raidlist_itself *raidlist,25 char *fname);26 24 extern void save_raidrec_to_file(struct raid_device_record *raidrec, 27 25 FILE * fout); -
branches/3.3/mondo/src/common/libmondo-raid.c
r3878 r3879 245 245 } 246 246 #endif 247 248 249 /** 250 * Save a disklist to a stream in raidtab format. 251 * @param listname One of "raid-disk", "spare-disk", "parity-disk", or "failed-disk". 252 * @param disklist The disklist to save to @p fout. 253 * @param fout The stream to write to. 254 */ 255 void save_disklist_to_file(const char *listname, struct list_of_disks *disklist, FILE * fout) 256 { 257 int i; 258 259 assert_string_is_neither_NULL_nor_zerolength(listname); 260 assert(disklist != NULL); 261 assert(fout != NULL); 262 263 for (i = 0; i < disklist->entries; i++) { 264 fprintf(fout, " device %s\n", disklist->el[i].device); 265 fprintf(fout, " %-21s %d\n", listname, disklist->el[i].index); 266 } 267 } 268 /** 269 * Retrieve the next line from a raidtab stream. 270 * @param fin The file to read the input from. 271 * @param label Where to put the line's label. 272 * @param value Where to put the line's value. 273 * @return 0 if the line was read and stored successfully, 1 if we're at end of file. 274 */ 275 static int get_next_raidtab_line(FILE * fin, char **label, char **value) 276 { 277 char *incoming = NULL; 278 char *p = NULL; 279 char *res = NULL; 280 281 assert(fin != NULL); 282 283 if (feof(fin)) { 284 return (1); 285 } 286 287 for (mr_getline(res, fin); !feof(fin); mr_getline(res, fin)) { 288 log_msg(10,"Found in raidtab line: %s",res); 289 incoming = mr_strip_spaces(res); 290 mr_free(res); 291 p = strchr(incoming, ' '); 292 if (strlen(incoming) < 3 || incoming[0] == '#' || !p) { 293 mr_free(incoming); 294 continue; 295 } 296 *(p++) = '\0'; 297 while (*p == ' ') { 298 p++; 299 } 300 *label = incoming; 301 *value = p; 302 log_msg(10,"Found in raidtab pair: %s|%s",*label,*value); 303 return (0); 304 } 305 return (1); 306 } 307 308 309 /** 310 * Save the additional RAID variables to a stream. 311 * @param vars The RAID variable list to save. 312 * @param fout The FILE pointer to save them to. 313 */ 314 void 315 save_additional_vars_to_file(struct additional_raid_variables *vars, 316 FILE * fout) 317 { 318 int i; 319 320 assert(vars != NULL); 321 assert(fout != NULL); 322 323 for (i = 0; i < vars->entries; i++) { 324 fprintf(fout, " %-21s %s\n", vars->el[i].label, 325 vars->el[i].value); 326 } 327 } 328 329 247 330 248 331 … … 341 424 } 342 425 343 344 /**345 * Save the additional RAID variables to a stream.346 * @param vars The RAID variable list to save.347 * @param fout The FILE pointer to save them to.348 */349 void350 save_additional_vars_to_file(struct additional_raid_variables *vars,351 FILE * fout)352 {353 int i;354 355 assert(vars != NULL);356 assert(fout != NULL);357 358 for (i = 0; i < vars->entries; i++) {359 fprintf(fout, " %-21s %s\n", vars->el[i].label,360 vars->el[i].value);361 }362 }363 364 365 426 /** 366 427 * Save a raidlist structure to disk in raidtab format. … … 412 473 paranoid_fclose(fout); 413 474 return (0); 414 }415 416 417 /**418 * Save a disklist to a stream in raidtab format.419 * @param listname One of "raid-disk", "spare-disk", "parity-disk", or "failed-disk".420 * @param disklist The disklist to save to @p fout.421 * @param fout The stream to write to.422 */423 void save_disklist_to_file(const char *listname, struct list_of_disks *disklist, FILE * fout)424 {425 int i;426 427 assert_string_is_neither_NULL_nor_zerolength(listname);428 assert(disklist != NULL);429 assert(fout != NULL);430 431 for (i = 0; i < disklist->entries; i++) {432 fprintf(fout, " device %s\n", disklist->el[i].device);433 fprintf(fout, " %-21s %d\n", listname, disklist->el[i].index);434 }435 }436 /**437 * Retrieve the next line from a raidtab stream.438 * @param fin The file to read the input from.439 * @param label Where to put the line's label.440 * @param value Where to put the line's value.441 * @return 0 if the line was read and stored successfully, 1 if we're at end of file.442 */443 static int get_next_raidtab_line(FILE * fin, char **label, char **value)444 {445 char *incoming = NULL;446 char *p = NULL;447 char *res = NULL;448 449 assert(fin != NULL);450 451 if (feof(fin)) {452 return (1);453 }454 455 for (mr_getline(res, fin); !feof(fin); mr_getline(res, fin)) {456 log_msg(10,"Found in raidtab line: %s",res);457 incoming = mr_strip_spaces(res);458 mr_free(res);459 p = strchr(incoming, ' ');460 if (strlen(incoming) < 3 || incoming[0] == '#' || !p) {461 mr_free(incoming);462 continue;463 }464 *(p++) = '\0';465 while (*p == ' ') {466 p++;467 }468 *label = incoming;469 *value = p;470 log_msg(10,"Found in raidtab pair: %s|%s",*label,*value);471 return (0);472 }473 return (1);474 475 } 475 476 -
branches/3.3/mondo/src/common/libmondo-stream.c
r3878 r3879 80 80 81 81 82 83 84 /** 85 * Log (to screen) an erroneous marker, along with what it should have been. 86 * @param should_be What we were expecting. 87 * @param it_is What we got. 88 */ 89 void wrong_marker(int should_be, int it_is) 90 { 91 char *tmp1 = NULL; 92 char *tmp2 = NULL; 93 tmp1 = marker_to_string(should_be); 94 tmp2 = marker_to_string(it_is); 95 log_to_screen("Wrong marker! (Should be %s, is actually %s)", tmp1, tmp2); 96 mr_free(tmp1); 97 mr_free(tmp2); 98 } 99 100 101 102 103 /** 104 * Read a header block from the currently opened stream (CD or tape). 105 * This block indicates the length of the following file (if it's file-related) 106 * the filename (if it's file-related), and the block type. 107 * @param plen Where to put the length of the file. Valid only for file-related header blocks. 108 * @param filename Where to put the name of the file. Valid only for file-related header blocks. 109 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...) 110 * @return 0 for success, nonzero for failure. 111 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker(). 112 */ 113 int 114 read_header_block_from_stream(long long *plen, char *filename, 115 int *pcontrol_char) 116 { 117 118 /*@ buffers ***************************************************** */ 119 char *tempblock; 120 char *tmp = NULL; 121 122 /*@ int ********************************************************* */ 123 int i, retval; 124 125 /*@ end vars *************************************************** */ 126 127 tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE); 128 129 for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) { 130 tempblock[i] = 0; 131 } 132 while (!(*pcontrol_char = tempblock[7000])) { 133 g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024; 134 } 135 memcpy((char *) plen, tempblock + 7001, sizeof(long long)); 136 if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) { 137 log_it("Bad header block at %ld K", (long) g_tape_posK); 138 } 139 strcpy(filename, tempblock + 1000); 140 if (*pcontrol_char == BLK_ABORTED_BACKUP) { 141 log_to_screen("I can't verify an aborted backup."); 142 retval = 1; 143 } else { 144 retval = 0; 145 } 146 for (i = 1000; i < 1020; i++) { 147 if (tempblock[i] < 32 || tempblock[i] > 126) { 148 tempblock[i] = ' '; 149 } 150 } 151 tempblock[i] = '\0'; 152 tmp = marker_to_string(*pcontrol_char); 153 log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10); 154 mr_free(tmp); 155 paranoid_free(tempblock); 156 return (retval); 157 } 82 158 83 159 … … 206 282 } 207 283 208 209 210 211 /**212 * Log (to screen) an erroneous marker, along with what it should have been.213 * @param should_be What we were expecting.214 * @param it_is What we got.215 */216 void wrong_marker(int should_be, int it_is)217 {218 char *tmp1 = NULL;219 char *tmp2 = NULL;220 tmp1 = marker_to_string(should_be);221 tmp2 = marker_to_string(it_is);222 log_to_screen("Wrong marker! (Should be %s, is actually %s)", tmp1, tmp2);223 mr_free(tmp1);224 mr_free(tmp2);225 }226 227 228 229 /**230 * Read a header block from the currently opened stream (CD or tape).231 * This block indicates the length of the following file (if it's file-related)232 * the filename (if it's file-related), and the block type.233 * @param plen Where to put the length of the file. Valid only for file-related header blocks.234 * @param filename Where to put the name of the file. Valid only for file-related header blocks.235 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...)236 * @return 0 for success, nonzero for failure.237 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker().238 */239 int240 read_header_block_from_stream(long long *plen, char *filename,241 int *pcontrol_char)242 {243 244 /*@ buffers ***************************************************** */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 284 285 285 … … 561 561 return (dev); 562 562 } 563 564 565 /** 566 * Seek through the stream until we find a header block where the NAME field matches 567 * @p the_file_I_was_reading. This is useful if you've just started reading from 568 * a new tape and want to find the file you were reading when the tape ended. 569 * @param the_file_I_was_reading File name to look for. 570 * @return 0 for success, nonzero for failure. 571 */ 572 int skip_incoming_files_until_we_find_this_one(char 573 *the_file_I_was_reading) 574 { 575 char *pA; 576 char *pB; 577 int res; 578 int ctrl_chr; 579 char *temp_fname; 580 char *datablock; 581 long long temp_size, size; 582 long bytes_to_write; 583 584 datablock = malloc(TAPE_BLOCK_SIZE); 585 malloc_string(temp_fname); 586 pB = strrchr(the_file_I_was_reading, '/'); 587 if (pB) { 588 pB++; 589 } else { 590 pB = the_file_I_was_reading; 591 } 592 log_msg(1, "skip_incoming_..(%s)", pB); 593 log_msg(2, "Looking for initial START_AN_AFIO_OR_SLICE"); 594 ctrl_chr = -1; 595 while (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) { 596 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr); 597 if (res) { 598 // FIXME 599 } 600 if (ctrl_chr == BLK_START_AN_AFIO_OR_SLICE) { 601 break; 602 } 603 log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr); 604 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr); 605 log_msg(3, "Still trying to re-sync w/ tape"); 606 } 607 while (ctrl_chr != BLK_START_FILE) { 608 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr); 609 if (res) { 610 //FIXME 611 } 612 if (ctrl_chr == BLK_START_FILE) { 613 break; 614 } 615 log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr); 616 wrong_marker(BLK_START_FILE, ctrl_chr); 617 log_msg(3, "Still trying to re-sync w/ tape"); 618 } 619 pA = strrchr(temp_fname, '/'); 620 if (pA) { 621 pA++; 622 } else { 623 pA = temp_fname; 624 } 625 pB = strrchr(the_file_I_was_reading, '/'); 626 if (pB) { 627 pB++; 628 } else { 629 pB = the_file_I_was_reading; 630 } 631 while (strcmp(pA, pB)) { 632 log_msg(6, "Skipping %s (it's not %s)", temp_fname, the_file_I_was_reading); 633 for (size = temp_size; size > 0; size -= bytes_to_write) { 634 bytes_to_write = 635 (size < TAPE_BLOCK_SIZE) ? (long) size : TAPE_BLOCK_SIZE; 636 if (fread(datablock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream)) { 637 // FIXME - needs error-checking and -catching 638 } 639 } 640 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr); 641 if (ctrl_chr != BLK_STOP_FILE) { 642 wrong_marker(BLK_STOP_FILE, ctrl_chr); 643 } 644 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr); 645 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) { 646 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr); 647 } 648 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr); 649 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) { 650 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr); 651 } 652 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr); 653 if (ctrl_chr != BLK_START_FILE) { 654 wrong_marker(BLK_START_FILE, ctrl_chr); 655 } 656 pA = strrchr(temp_fname, '/'); 657 if (pA) { 658 pA++; 659 } else { 660 pA = temp_fname; 661 } 662 pB = strrchr(the_file_I_was_reading, '/'); 663 if (pB) { 664 pB++; 665 } else { 666 pB = the_file_I_was_reading; 667 } 668 } 669 log_msg(2, "Reading %s (it matches %s)", temp_fname, the_file_I_was_reading); 670 paranoid_free(temp_fname); 671 paranoid_free(datablock); 672 return (0); 673 } 674 675 676 /** 677 * Start to read from the next tape. Assumes the user has already inserted it. 678 * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used. 679 * @return 0 for success, nonzero for failure. 680 */ 681 int start_to_read_from_next_tape() 682 { 683 /*@ int ********************************************************* */ 684 int res = 0; 685 char *sz_msg; 686 int ctrlchr; 687 long long temp_size; 688 malloc_string(sz_msg); 689 /*@ end vars *************************************************** */ 690 691 if (bkpinfo->media_device == NULL) { 692 log_it("Unable to open in from NULL device"); 693 return (1); 694 } 695 696 paranoid_pclose(g_tape_stream); 697 sync(); 698 sync(); 699 sync(); 700 log_it("Next tape requested."); 701 insist_on_this_tape_number(g_current_media_number + 1); // will increment it, too 702 log_it("Opening IN the next tape"); 703 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'r', bkpinfo->internal_tape_block_size))) { 704 log_OS_error(g_tape_fifo); 705 log_to_screen("Cannot openin stream device"); 706 return (1); 707 } 708 g_tape_posK = 0; 709 g_sigpipe = FALSE; 710 res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */ 711 if (ctrlchr != BLK_START_OF_TAPE) { 712 wrong_marker(BLK_START_OF_TAPE, ctrlchr); 713 } 714 res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */ 715 if (ctrlchr != BLK_START_OF_BACKUP) { 716 wrong_marker(BLK_START_OF_BACKUP, ctrlchr); 717 } else { 718 log_msg(3, "Next tape opened OK. Whoopee!"); 719 } 720 paranoid_free(sz_msg); 721 return (res); 722 } 723 563 724 564 725 … … 1404 1565 1405 1566 /** 1406 * Seek through the stream until we find a header block where the NAME field matches1407 * @p the_file_I_was_reading. This is useful if you've just started reading from1408 * a new tape and want to find the file you were reading when the tape ended.1409 * @param the_file_I_was_reading File name to look for.1410 * @return 0 for success, nonzero for failure.1411 */1412 int skip_incoming_files_until_we_find_this_one(char1413 *the_file_I_was_reading)1414 {1415 char *pA;1416 char *pB;1417 int res;1418 int ctrl_chr;1419 char *temp_fname;1420 char *datablock;1421 long long temp_size, size;1422 long bytes_to_write;1423 1424 datablock = malloc(TAPE_BLOCK_SIZE);1425 malloc_string(temp_fname);1426 pB = strrchr(the_file_I_was_reading, '/');1427 if (pB) {1428 pB++;1429 } else {1430 pB = the_file_I_was_reading;1431 }1432 log_msg(1, "skip_incoming_..(%s)", pB);1433 log_msg(2, "Looking for initial START_AN_AFIO_OR_SLICE");1434 ctrl_chr = -1;1435 while (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {1436 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);1437 if (res) {1438 // FIXME1439 }1440 if (ctrl_chr == BLK_START_AN_AFIO_OR_SLICE) {1441 break;1442 }1443 log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr);1444 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);1445 log_msg(3, "Still trying to re-sync w/ tape");1446 }1447 while (ctrl_chr != BLK_START_FILE) {1448 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);1449 if (res) {1450 //FIXME1451 }1452 if (ctrl_chr == BLK_START_FILE) {1453 break;1454 }1455 log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr);1456 wrong_marker(BLK_START_FILE, ctrl_chr);1457 log_msg(3, "Still trying to re-sync w/ tape");1458 }1459 pA = strrchr(temp_fname, '/');1460 if (pA) {1461 pA++;1462 } else {1463 pA = temp_fname;1464 }1465 pB = strrchr(the_file_I_was_reading, '/');1466 if (pB) {1467 pB++;1468 } else {1469 pB = the_file_I_was_reading;1470 }1471 while (strcmp(pA, pB)) {1472 log_msg(6, "Skipping %s (it's not %s)", temp_fname, the_file_I_was_reading);1473 for (size = temp_size; size > 0; size -= bytes_to_write) {1474 bytes_to_write =1475 (size < TAPE_BLOCK_SIZE) ? (long) size : TAPE_BLOCK_SIZE;1476 if (fread(datablock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream)) {1477 // FIXME - needs error-checking and -catching1478 }1479 }1480 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);1481 if (ctrl_chr != BLK_STOP_FILE) {1482 wrong_marker(BLK_STOP_FILE, ctrl_chr);1483 }1484 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);1485 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {1486 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);1487 }1488 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);1489 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {1490 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);1491 }1492 res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);1493 if (ctrl_chr != BLK_START_FILE) {1494 wrong_marker(BLK_START_FILE, ctrl_chr);1495 }1496 pA = strrchr(temp_fname, '/');1497 if (pA) {1498 pA++;1499 } else {1500 pA = temp_fname;1501 }1502 pB = strrchr(the_file_I_was_reading, '/');1503 if (pB) {1504 pB++;1505 } else {1506 pB = the_file_I_was_reading;1507 }1508 }1509 log_msg(2, "Reading %s (it matches %s)", temp_fname, the_file_I_was_reading);1510 paranoid_free(temp_fname);1511 paranoid_free(datablock);1512 return (0);1513 }1514 1515 1516 /**1517 * Start to read from the next tape. Assumes the user has already inserted it.1518 * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used.1519 * @return 0 for success, nonzero for failure.1520 */1521 int start_to_read_from_next_tape()1522 {1523 /*@ int ********************************************************* */1524 int res = 0;1525 char *sz_msg;1526 int ctrlchr;1527 long long temp_size;1528 malloc_string(sz_msg);1529 /*@ end vars *************************************************** */1530 1531 if (bkpinfo->media_device == NULL) {1532 log_it("Unable to open in from NULL device");1533 return (1);1534 }1535 1536 paranoid_pclose(g_tape_stream);1537 sync();1538 sync();1539 sync();1540 log_it("Next tape requested.");1541 insist_on_this_tape_number(g_current_media_number + 1); // will increment it, too1542 log_it("Opening IN the next tape");1543 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'r', bkpinfo->internal_tape_block_size))) {1544 log_OS_error(g_tape_fifo);1545 log_to_screen("Cannot openin stream device");1546 return (1);1547 }1548 g_tape_posK = 0;1549 g_sigpipe = FALSE;1550 res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */1551 if (ctrlchr != BLK_START_OF_TAPE) {1552 wrong_marker(BLK_START_OF_TAPE, ctrlchr);1553 }1554 res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */1555 if (ctrlchr != BLK_START_OF_BACKUP) {1556 wrong_marker(BLK_START_OF_BACKUP, ctrlchr);1557 } else {1558 log_msg(3, "Next tape opened OK. Whoopee!");1559 }1560 paranoid_free(sz_msg);1561 return (res);1562 }1563 1564 1565 1566 /**1567 1567 * Copy a file from the currently opened stream (CD or tape) to the stream indicated 1568 1568 * by @p fout. -
branches/3.3/mondo/src/common/libmondo-tools-EXT.h
r2470 r3879 4 4 extern long get_time(); 5 5 extern char *mr_date(void); 6 extern void (*log_debug_msg) (int debug_level, const char *szFile,7 const char *szFunction, int nLine,8 const char *fmt, ...);9 extern void standard_log_debug_msg(int debug_level, const char *szFile,10 const char *szFunction, int nLine,11 const char *fmt, ...);12 6 extern int read_cfg_var(char *config_file, char *label, char *value); 13 7 extern int write_cfg_var(char *config_file, char *label, char *value); … … 45 39 extern char *get_uname_m(); 46 40 47 extern bool does_nonMS_partition_exist(void);48 49 50 41 extern void stop_magicdev_if_necessary(void); 51 42 extern void restart_magicdev_if_necessary(void); -
branches/3.3/mondo/src/common/libmondo-tools.c
r3877 r3879 74 74 75 75 extern t_bkptype g_backup_media_type; 76 77 extern bool am_I_in_disaster_recovery_mode(void);78 76 79 77 /*-----------------------------------------------------------*/
Note:
See TracChangeset
for help on using the changeset viewer.