Changeset 3879 in MondoRescue
- Timestamp:
- Mar 9, 2024, 3:10:04 AM (4 months ago)
- Location:
- branches/3.3/mondo
- Files:
-
- 8 deleted
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mondo/bootstrap
r3412 r3879 30 30 libtoolize -f -c --automake 31 31 aclocal 32 autoheader 32 #autoheader # to be used with AC_CONFIG_HEADER 33 33 rm -f missing 34 34 automake --add-missing --copy -
branches/3.3/mondo/configure.ac
r3848 r3879 13 13 AC_CONFIG_SRCDIR([src/mondoarchive/mondoarchive.c]) 14 14 AC_CONFIG_MACRO_DIR([m4]) 15 AC_CONFIG_HEADERS([config.h])16 15 17 AC_PREREQ([2. 63])16 AC_PREREQ([2.71]) 18 17 AC_CANONICAL_HOST 19 18 AC_CANONICAL_TARGET … … 74 73 GCC_MAJ="`gcc -dumpversion 2>&1 | cut -d. -f1`" 75 74 GCC_MIN="`gcc -dumpversion 2>&1 | cut -d. -f2`" 76 CFLAGS="$CFLAGS -Wall -Wextra -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wconversion -Wno-return-type -Wformat=2 -Werror=implicit-function-declaration -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -D_FORTIFY_SOURCE=2 -fstack-clash-protection -fstack-protector-strong -fcf-protection -fsanitize=undefined -Wl,-z,defs -Wl,-z,now -Wl,-z,relro" # -Wstrict-prototypes -Werror" 75 76 # Just test for dev machine on x86_64 ubsan used for option -fsanitize=undefined 77 if [ -f /usr/lib64/libubsan.so ]; then 78 CFLAGS="$CFLAGS -fsanitize=undefined" 79 HAVE_UBSAN=1 80 else 81 HAVE_UBSAN=0 82 fi 83 84 # Just test for dev machine on x86_64 asan used for option -fsanitize=address 85 if [ -f /usr/lib64/libasan.so ]; then 86 CFLAGS="$CFLAGS -fsanitize=address" 87 HAVE_ASAN=1 88 else 89 HAVE_ASAN=0 90 fi 91 92 CFLAGS="$CFLAGS -Wall -Wextra -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wno-return-type -Wformat=2 -Werror=implicit-function-declaration -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -D_FORTIFY_SOURCE=2 -fstack-clash-protection -fstack-protector-strong -fcf-protection -Wl,-z,defs -Wl,-z,now -Wl,-z,relro -Wno-discarded-qualifiers" # -Wconversion -Wstrict-prototypes -Werror" 77 93 ;; 78 94 *) … … 103 119 104 120 # Checks for header files. 105 AC_HEADER_STDC 121 AC_CHECK_INCLUDES_DEFAULT 122 AC_PROG_EGREP 123 106 124 AC_HEADER_SYS_WAIT 107 125 AC_HEADER_STDBOOL -
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 /*-----------------------------------------------------------*/ -
branches/3.3/mondo/src/include/my-stuff.h
r3876 r3879 5 5 #define HAVE_MALLOC 1 6 6 7 8 // Extra info for ACLs and SELINUX users9 #define STAR_ACL_SZ "-xattr -acl"10 11 7 /** 12 8 * @file … … 25 21 #ifndef _MY_STUFF_H_ 26 22 #define _MY_STUFF_H_ 27 28 #ifdef HAVE_CONFIG_H29 #include <config.h>30 #endif31 23 32 24 #ifndef __FreeBSD__ … … 83 75 */ 84 76 #define MONDO_CACHE "/var/cache/mondo" 77 #define ARCHIVES_PATH MNT_CDROM"/archives" 78 #define BIGGIELIST ARCHIVES_PATH"/biggielist.txt" 85 79 86 80 /** … … 109 103 #define assert(exp) ((exp)?((void)0):_mondo_assert_fail(__FILE__, __FUNCTION__, __LINE__, #exp)) 110 104 #endif 105 106 // Extra info for ACLs and SELINUX users 107 #define STAR_ACL_SZ "-xattr -acl" 111 108 112 109 #define CRC_M16 0xA001 ///< Mask for crc16. … … 351 348 #define MONDO_MNTLISTCHG "/tmp/mountlist.changed" 352 349 350 extern void (*log_debug_msg) (int debug_level, const char *szFile, 351 const char *szFunction, int nLine, 352 const char *fmt, ...); 353 extern void standard_log_debug_msg(int debug_level, const char *szFile, 354 const char *szFunction, int nLine, 355 const char *fmt, ...); 353 356 354 357 /** -
branches/3.3/mondo/src/mondoarchive/mondoarchive.c
r3875 r3879 12 12 #include "mr_str.h" 13 13 #include "mr_msg.h" 14 #include "../common/mondostructures.h" 15 #include "../common/libmondo.h" 16 #include "../common/libmondo-cli-EXT.h" 17 #include "../common/libmondo-tools-EXT.h" 14 #include "mondostructures.h" 15 #include "libmondo-cli-EXT.h" 16 #include "libmondo-tools-EXT.h" 17 #include "libmondo-archive-EXT.h" 18 #include "libmondo-fork-EXT.h" 19 #include "libmondo-files-EXT.h" 20 #include "libmondo-filelist-EXT.h" 21 #include "libmondo-raid-EXT.h" 22 #include "libmondo-devices-EXT.h" 23 #include "newt-specific-EXT.h" 18 24 #include "mondoarchive.h" 19 25 -
branches/3.3/mondo/src/mondorestore/Makefile.am
r3564 r3879 7 7 8 8 ## Headers 9 noinst_HEADERS = mondorestore.h mondo-rstr-compare.h mondo-rstr-newt.h mondo-rstr-tools.h \ 10 mondorestore-EXT.h mr-externs.h \ 11 mondo-rstr-compare-EXT.h mondo-rstr-tools-EXT.h mondoprep.h \ 12 libmondo-mountlist.h libmondo-mountlist-EXT.h \ 13 mondorestore.h 9 noinst_HEADERS = mondorestore.h \ 10 mondo-rstr-compare-EXT.h mondo-rstr-tools-EXT.h \ 11 libmondo-mountlist-EXT.h 14 12 15 13 ## The program -
branches/3.3/mondo/src/mondorestore/mondo-prep.c
r3866 r3879 5 5 6 6 7 #include "my-stuff.h"8 #include "mr_mem.h"9 #include "../common/mondostructures.h"10 #include "mondoprep.h"11 #include "../common/libmondo.h"12 #include "../common/libmondo-tools-EXT.h"13 #include "mondo-rstr-tools-EXT.h"14 #include "libmondo-mountlist-EXT.h"15 7 #include <sys/ioctl.h> 16 8 #include <linux/hdreg.h> 17 9 #include <math.h> 10 #include "my-stuff.h" 11 #include "mr_mem.h" 12 #include "mondostructures.h" 13 #include "mondo-rstr-tools-EXT.h" 14 #include "libmondo-mountlist-EXT.h" 15 #include "libmondo-tools-EXT.h" 16 #include "libmondo-gui-EXT.h" 17 #include "libmondo-devices-EXT.h" 18 #include "libmondo-fork-EXT.h" 19 #include "libmondo-string-EXT.h" 20 #include "libmondo-files-EXT.h" 21 #include "newt-specific-EXT.h" 18 22 19 23 … … 32 36 #endif 33 37 34 #define ARCHIVES_PATH MNT_CDROM"/archives"35 38 #define MONDO_WAS_HERE "MONDOWOZEREMONDOWOZEREMONDOWOZEREhahahaMOJOJOJO" 36 39 … … 39 42 extern char *g_mountlist_fname; 40 43 extern long g_current_progress, g_maximum_progress; 41 42 44 extern bool g_text_mode; 45 extern int g_currentY; 46 43 47 44 48 extern void pause_for_N_seconds(int, char *); … … 628 632 629 633 634 635 /** 636 * Stop @p raid_device using @p raidstop. 637 * @param raid_device The software RAID device to stop. 638 * @return 0 for success, nonzero for failure. 639 */ 640 int stop_raid_device(char *raid_device) { 641 642 /** int *************************************************************/ 643 int res; 644 int retval = 0; 645 646 /** buffers *********************************************************/ 647 char *program = NULL; 648 649 /** end *************************************************************/ 650 651 assert_string_is_neither_NULL_nor_zerolength(raid_device); 652 653 #ifdef __FreeBSD__ 654 if (is_this_device_mounted(raid_device)) { 655 log_it("Can't stop %s when it's mounted!", raid_device); 656 return 1; 657 } 658 mr_asprintf(program, "vinum stop -f %s", raid_device); 659 #else 660 // use raidstop if it exists, otherwise use mdadm 661 if (run_program_and_log_output("which raidstop", FALSE)) { 662 mr_asprintf(program, "mdadm -S %s", raid_device); 663 } else { 664 mr_asprintf(program, "raidstop %s", raid_device); 665 } 666 #endif 667 log_msg(1, "program = %s", program); 668 res = run_program_and_log_output(program, 1); 669 if (g_fprep) { 670 fprintf(g_fprep, "%s\n", program); 671 } 672 mr_free(program); 673 674 if (res) { 675 log_msg(1, "Warning - failed to stop RAID device %s", raid_device); 676 } 677 retval += res; 678 return (retval); 679 } 680 681 682 683 int start_raid_device(char *raid_device) { 684 685 /** int *************************************************************/ 686 int res; 687 int retval = 0; 688 689 /** buffers *********************************************************/ 690 char *program = NULL; 691 692 /** end *************************************************************/ 693 694 assert_string_is_neither_NULL_nor_zerolength(raid_device); 695 696 #ifdef __FreeBSD__ 697 if (is_this_device_mounted(raid_device)) { 698 log_it("Can't start %s when it's mounted!", raid_device); 699 return 1; 700 } 701 mr_asprintf(program, "vinum start -f %s", raid_device); 702 #else 703 mr_asprintf(program, "raidstart %s", raid_device); 704 #endif 705 log_msg(1, "program = %s", program); 706 res = run_program_and_log_output(program, 1); 707 if (g_fprep) { 708 fprintf(g_fprep, "%s\n", program); 709 } 710 mr_free(program); 711 712 if (res) { 713 log_msg(1, "Warning - failed to start RAID device %s", raid_device); 714 } 715 retval += res; 716 sleep(1); 717 return (retval); 718 } 719 720 721 /** 722 * Decide which command we need to use to format a device of type @p format. 723 * @param format The filesystem type we are about to format. 724 * @param program Where to put the binary name for this format. 725 * @return 0 for success, nonzero for failure. 726 */ 727 char *which_format_command_do_i_need(char *format) { 728 729 char *program = NULL; 730 731 assert_string_is_neither_NULL_nor_zerolength(format); 732 733 if (strcmp(format, "swap") == 0) { 734 #ifdef __FreeBSD__ 735 mr_asprintf(program, "true"); 736 #else 737 mr_asprintf(program, "mkswap -f"); 738 #endif 739 } else if (strcmp(format, "vfat") == 0) { 740 #ifdef __FreeBSD__ 741 mr_asprintf(program, "newfs_msdos -F 32"); 742 #else 743 #ifdef __IA64__ 744 /* For EFI partitions on ia64 take fat16 745 * as we want to make small ones */ 746 mr_asprintf(program, "mkfs.vfat -F 16"); 747 #else 748 /* mkfs.vfat will make the best possible choice itself */ 749 /* should avoid problems with mr-label later on when used */ 750 mr_asprintf(program, "mkfs.vfat"); 751 #endif 752 #endif 753 #ifndef __FreeBSD__ 754 } else if (strcmp(format, "reiserfs") == 0) { 755 mr_asprintf(program, "mkreiserfs -ff"); 756 } else if (strcmp(format, "xfs") == 0) { 757 /* Cf: https://bugzilla.redhat.com/show_bug.cgi?id=1309498 */ 758 mr_asprintf(program, "mkfs.xfs -f -q -m crc=0 -n ftype=0"); 759 } else if (strcmp(format, "jfs") == 0) { 760 mr_asprintf(program, "mkfs.jfs"); 761 } else if (strcmp(format, "ext3") == 0) { 762 mr_asprintf(program, "mkfs -t ext3 -F -q"); 763 } else if (strcmp(format, "ext4") == 0) { 764 mr_asprintf(program, "mkfs -t ext4 -F -q"); 765 } else if (strcmp(format, "btrfs") == 0) { 766 mr_asprintf(program, "mkfs.btrfs -f"); 767 } else if (strcmp(format, "minix") == 0) { 768 mr_asprintf(program, "mkfs.minix"); 769 } else if (strcmp(format, "vmfs") == 0) { 770 mr_asprintf(program, "mkfs -t vmfs"); 771 } else if (strcmp(format, "ntfs") == 0) { 772 /* 773 * mkfs.ntfs treats the '-c' switch as 'specify cluster size' 774 * so the default "mkfs -t %s -c" command structure fails 775 */ 776 mr_asprintf(program, "mkfs -t ntfs"); 777 } else if (strcmp(format, "ocfs2") == 0) { 778 /* 779 * For existing OCFS2 volumes, mkfs.ocfs2 ensures the volume is not mounted on any node in the cluster before formatting. For that to work, mkfs.ocfs2 expects the O2CB cluster service to be running. Specify this option to disable this check. 780 * 781 */ 782 mr_asprintf(program, "mkfs -t ocfs2 -F"); 783 #endif 784 } else if (strcmp(format, "ext2") == 0) { 785 mr_asprintf(program, "mke2fs -F -q"); 786 } else { 787 #ifdef __FreeBSD__ 788 mr_asprintf(program, "newfs_%s", format); 789 #else 790 mr_asprintf(program, "mkfs -t %s -c", format); // -c checks for bad blocks 791 #endif 792 log_it("Unknown format (%s) - assuming '%s' will do", format, program); 793 } 794 return(program); 795 } 796 797 798 630 799 /** 631 800 * Format @p device as a @p format filesystem. … … 821 990 return (retval); 822 991 } 992 993 994 /** 995 * Stop all software RAID devices listed in @p mountlist. 996 * @param mountlist The mountlist to stop the RAID devices in. 997 * @return The number of errors encountered (0 for success). 998 * @bug @p mountlist is not used. 999 */ 1000 int stop_all_raid_devices(struct mountlist_itself *mountlist) { 1001 1002 /** int *************************************************************/ 1003 int retval = 0; 1004 1005 /** char ************************************************************/ 1006 char *incoming; 1007 #ifndef __FreeBSD__ 1008 char *dev; 1009 #endif 1010 /** pointers ********************************************************/ 1011 #ifndef __FreeBSD__ 1012 char *p; 1013 #endif 1014 FILE *fin; 1015 char *q; 1016 int i; 1017 1018 /** end ****************************************************************/ 1019 1020 malloc_string(incoming); 1021 assert(mountlist != NULL); 1022 1023 for (i = 0; i < 3; i++) { 1024 #ifdef __FreeBSD__ 1025 fin = popen("vinum list | grep '^[PVS]' | sed 's/S/1/;s/P/2/;s/V/3/' | sort | cut -d' ' -f2", "r"); 1026 if (!fin) { 1027 paranoid_free(incoming); 1028 return (1); 1029 } 1030 for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) { 1031 retval += stop_raid_device(incoming); 1032 } 1033 #else 1034 fin = fopen("/proc/mdstat", "r"); 1035 if (!fin) { 1036 log_OS_error("/proc/mdstat"); 1037 paranoid_free(incoming); 1038 return (1); 1039 } 1040 for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) { 1041 for (p = incoming; *p != '\0' && (*p != 'm' || *(p + 1) != 'd' || !isdigit(*(p + 2))); p++); 1042 if (*p != '\0') { 1043 malloc_string(dev); 1044 sprintf(dev, "/dev/%s", p); 1045 for (p = dev; *p > 32; p++); 1046 *p = '\0'; 1047 retval += stop_raid_device(dev); 1048 paranoid_free(dev); 1049 } 1050 } 1051 #endif 1052 } 1053 paranoid_fclose(fin); 1054 if (retval) { 1055 log_msg(1, "Warning - unable to stop some RAID devices"); 1056 } 1057 paranoid_free(incoming); 1058 paranoid_system("sync"); 1059 paranoid_system("sync"); 1060 paranoid_system("sync"); 1061 sleep(1); 1062 return (retval); 1063 } 1064 1065 823 1066 824 1067 … … 984 1227 paranoid_system("clear"); 985 1228 newtResume(); 1229 return (retval); 1230 } 1231 1232 1233 /** 1234 * Set the type of partition number @p partno on @p drive to @p format. 1235 * @param drive The drive to change the type of a partition on. 1236 * @param partno The partition number on @p drive to change the type of. 1237 * @param format The filesystem type this partition will eventually contain. 1238 * @param partsize The size of this partition, in @e bytes (used for vfat 1239 * type calculations). 1240 * @return 0 for success, nonzero for failure. 1241 */ 1242 int set_partition_type(FILE * pout_to_fdisk, const char *drive, int partno, const char *format, long long partsize) { 1243 1244 /** buffers *********************************************************/ 1245 char *partition = NULL; 1246 char *command = NULL; 1247 char *output = NULL; 1248 char *tmp = NULL; 1249 char *partcode = NULL; 1250 1251 /** pointers *********************************************************/ 1252 FILE *fout; 1253 1254 /** int **************************************************************/ 1255 int res = 0; 1256 1257 /** end **************************************************************/ 1258 1259 assert_string_is_neither_NULL_nor_zerolength(drive); 1260 assert(format != NULL); 1261 1262 partition = build_partition_name(drive, partno); 1263 if (strcmp(format, "swap") == 0) { 1264 mr_asprintf(partcode, "82"); 1265 } else if (strcmp(format, "vfat") == 0) { 1266 if (partsize / 1024 > 8192) { 1267 mr_asprintf(partcode, "c"); 1268 } else { 1269 mr_asprintf(partcode, "b"); 1270 } 1271 } else if (strcmp(format, "ext2") == 0 1272 || strcmp(format, "reiserfs") == 0 1273 || strcmp(format, "ext3") == 0 1274 || strcmp(format, "ext4") == 0 1275 || strcmp(format, "xfs") == 0 1276 || strcmp(format, "jfs") == 0 1277 || strcmp(format, "btrfs") == 0) { 1278 mr_asprintf(partcode, "83"); 1279 } else if (strcmp(format, "minix") == 0) { 1280 mr_asprintf(partcode, "81"); 1281 } else if (strcmp(format, "vmfs3") == 0) { 1282 mr_asprintf(partcode, "fb"); 1283 } else if (strcmp(format, "vmkcore") == 0) { 1284 mr_asprintf(partcode, "fc"); 1285 } else if (strcmp(format, "raid") == 0) { 1286 mr_asprintf(partcode, "fd"); 1287 } else if (strcmp(format, "ntfs") == 0) { 1288 mr_asprintf(partcode, "7"); 1289 } else if ((strcmp(format, "ufs") == 0) 1290 || (strcmp(format, "ffs") == 0)) { /* raid autodetect */ 1291 mr_asprintf(partcode, "a5"); 1292 } else if (strcmp(format, "lvm") == 0) { 1293 mr_asprintf(partcode, "8e"); 1294 } else if (format[0] == '\0') { /* LVM physical partition */ 1295 mr_asprintf(partcode, ""); 1296 } else if (strlen(format) >= 1 && strlen(format) <= 2) { 1297 mr_asprintf(partcode, "%s", format); 1298 } else { 1299 /* probably an image */ 1300 mr_asprintf(tmp, "Unknown format ('%s') - using supplied string anyway", format); 1301 mvaddstr_and_log_it(g_currentY++, 0, tmp); 1302 mr_free(tmp); 1303 1304 #ifdef __FreeBSD__ 1305 mr_asprintf(partcode, "%s", format); // was a5 1306 #else 1307 mr_asprintf(partcode, "%s", format); // was 83 1308 #endif 1309 } 1310 log_msg(1, "Setting %s's type to %s (%s)", partition, format, partcode); 1311 mr_free(partition); 1312 1313 if ((strcmp(partcode,"") != 0) && strcmp(partcode, "83")) { /* no need to set type if 83: 83 is default */ 1314 1315 if (pout_to_fdisk) { 1316 res = 0; 1317 fput_string_one_char_at_a_time(pout_to_fdisk, "t\n"); 1318 if (partno > 1 1319 || strstr(last_line_of_file(FDISK_LOG), " (1-4)")) { 1320 log_msg(5, "Specifying partno (%d) - yay", partno); 1321 mr_asprintf(tmp, "%d\n", partno); 1322 fput_string_one_char_at_a_time(pout_to_fdisk, tmp); 1323 log_msg(5, "A - last line = '%s'", last_line_of_file(FDISK_LOG)); 1324 mr_free(tmp); 1325 } 1326 1327 mr_asprintf(tmp, "%s\n", partcode); 1328 fput_string_one_char_at_a_time(pout_to_fdisk, tmp); 1329 mr_free(tmp); 1330 1331 log_msg(5, "B - last line = '%s'", 1332 last_line_of_file(FDISK_LOG)); 1333 fput_string_one_char_at_a_time(pout_to_fdisk, "\n"); 1334 log_msg(5, "C - last line = '%s'", 1335 last_line_of_file(FDISK_LOG)); 1336 1337 mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG)); 1338 if (!strstr(tmp, " (m ")) { 1339 log_msg(1, "last line = '%s'; part type set failed", tmp); 1340 res++; 1341 fput_string_one_char_at_a_time(pout_to_fdisk, "\n"); 1342 } 1343 mr_free(tmp); 1344 1345 fput_string_one_char_at_a_time(pout_to_fdisk, "p\n"); 1346 } else { 1347 mr_asprintf(output, "t\n%d\n%s\nw\n", partno, partcode); 1348 mr_asprintf(command, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE); 1349 log_msg(5, "output = '%s'", output); 1350 log_msg(5, "partno=%d; partcode=%s", partno, partcode); 1351 log_msg(5, "command = '%s'", command); 1352 fout = popen(command, "w"); 1353 if (!fout) { 1354 log_OS_error(command); 1355 res = 1; 1356 } else { 1357 res = 0; 1358 fprintf(fout, "%s", output); 1359 paranoid_pclose(fout); 1360 } 1361 mr_free(command); 1362 paranoid_free(output); 1363 } 1364 } 1365 mr_free(partcode); 1366 1367 return (res); 1368 } 1369 1370 1371 /** 1372 * Create partition number @p partno on @p drive with @p fdisk. 1373 * @param drive The drive to create the partition on. 1374 // * @param partno The partition number of the new partition (1-4 are primary, >=5 is logical). 1375 * @param prev_partno The partition number of the most recently prepped partition. 1376 * @param format The filesystem type of this partition (used to set the type). 1377 * @param partsize The size of the partition in @e bytes. 1378 * @return 0 for success, nonzero for failure. 1379 */ 1380 int partition_device(FILE * pout_to_fdisk, const char *drive, int partno, int prev_partno, const char *format, long long partsize) { 1381 1382 /** int **************************************************************/ 1383 int retval = 0; 1384 int res = 0; 1385 1386 /** buffers **********************************************************/ 1387 char *program = NULL; 1388 char *partition_name = NULL; 1389 char *tmp = NULL; 1390 char *output = NULL; 1391 1392 /** pointers **********************************************************/ 1393 char *part_table_fmt = NULL; 1394 FILE *fout; 1395 1396 /** end ***************************************************************/ 1397 1398 assert_string_is_neither_NULL_nor_zerolength(drive); 1399 assert(format != NULL); 1400 1401 log_it("partition_device('%s', %d, %d, '%s', %lld) --- starting", drive, partno, prev_partno, format, partsize); 1402 1403 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) { 1404 log_it("Not partitioning %s - it is a virtual drive", drive); 1405 return (0); 1406 } 1407 1408 partition_name = build_partition_name(drive, partno); 1409 if (partsize <= 0) { 1410 mr_asprintf(tmp, "Partitioning device %s (max size)", partition_name); 1411 } else { 1412 mr_asprintf(tmp, "Partitioning device %s (%lld MB)", partition_name, (long long) partsize / 1024); 1413 } 1414 update_progress_form(tmp); 1415 log_it(tmp); 1416 mr_free(tmp); 1417 1418 if (is_this_device_mounted(partition_name)) { 1419 log_to_screen("%s is mounted, and should not be partitioned", partition_name); 1420 mr_free(partition_name); 1421 return (1); 1422 } 1423 1424 1425 mr_asprintf(program, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE); 1426 1427 /* TODO: should not be called each time */ 1428 part_table_fmt = which_partition_format(drive); 1429 mr_asprintf(output, ""); 1430 1431 /* make it a primary/extended/logical */ 1432 if (partno <= 4) { 1433 mr_strcat(output, "n\np\n%d\n", partno); 1434 } else { 1435 /* MBR needs an extended partition if more than 4 partitions */ 1436 if (strcmp(part_table_fmt, "MBR") == 0) { 1437 if (partno == 5) { 1438 if (prev_partno >= 4) { 1439 log_to_screen("You need to leave at least one partition free, for 'extended/logical'"); 1440 mr_free(partition_name); 1441 paranoid_free(output); 1442 return (1); 1443 } else { 1444 mr_strcat(output, "n\ne\n%d\n\n\n", prev_partno + 1); 1445 } 1446 } 1447 mr_strcat(output, "n\nl\n"); 1448 } else { 1449 /* GPT allows more than 4 primary partitions */ 1450 mr_strcat(output, "n\np\n%d\n", partno); 1451 } 1452 } 1453 mr_free(part_table_fmt); 1454 1455 mr_strcat(output, "\n"); /*start block (ENTER for next free blk */ 1456 if (partsize > 0) { 1457 if (!strcmp(format, "7")) { 1458 log_msg(1, "Adding 512K, just in case"); 1459 partsize += 512; 1460 } 1461 mr_strcat(output, "+%lldK", (long long) (partsize)); 1462 } 1463 mr_strcat(output, "\n"); 1464 #if 0 1465 /* 1466 #endif 1467 log_it("PARTSIZE = +%ld",(long)partsize); 1468 log_it("---fdisk command---"); 1469 log_it(output); 1470 log_it("---end of fdisk---"); 1471 #if 0 1472 */ 1473 #endif 1474 1475 1476 if (pout_to_fdisk) { 1477 log_msg(1, "Doing the new all-in-one fdisk thing"); 1478 mr_strcat(output, "\n\np\n\n"); 1479 log_msg(1, "output = '%s'", output); 1480 fput_string_one_char_at_a_time(pout_to_fdisk, output); 1481 mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG)); 1482 if (strstr(tmp, " (m ")) { 1483 log_msg(1, "Successfully created partition %d on %s", partno, drive); 1484 } else { 1485 log_msg(1, "last line = %s", tmp); 1486 log_msg(1, "Failed to create partition %d on %s; sending 'Enter'...", partno, drive); 1487 } 1488 mr_free(tmp); 1489 1490 if (!retval) { 1491 log_msg(1, "Trying to set partition %d type now on %s", partno, drive); 1492 retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize); 1493 if (retval) { 1494 log_msg(1, "Failed. Trying again..."); 1495 retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize); 1496 } 1497 } 1498 if (retval) { 1499 log_msg(1, "...but failed to set type"); 1500 } 1501 } else { 1502 mr_strcat(output, "w\n\n"); 1503 if (g_fprep) { 1504 fprintf(g_fprep, "echo \"%s\" | %s\n", output, program); 1505 } 1506 /* write to disk; close fdisk's stream */ 1507 if (!(fout = popen(program, "w"))) { 1508 log_OS_error("can't popen-out to program"); 1509 } else { 1510 fputs(output, fout); 1511 paranoid_pclose(fout); 1512 } 1513 1514 if (!does_partition_exist(drive, partno) && partsize > 0) { 1515 log_it("Vaccum-packing"); 1516 g_current_progress--; 1517 res = partition_device(pout_to_fdisk, drive, partno, prev_partno, format, -1); 1518 if (res) { 1519 log_it("Failed to vacuum-pack %s", partition_name); 1520 retval++; 1521 } else { 1522 retval = 0; 1523 } 1524 } 1525 if (does_partition_exist(drive, partno)) { 1526 retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize); 1527 if (retval) { 1528 log_it("Partitioned %s but failed to set its type", partition_name); 1529 } else { 1530 if (partsize > 0) { 1531 log_to_screen("Partition %s created+configured OK", partition_name); 1532 } else { 1533 log_it("Returning from a successful vacuum-pack"); 1534 } 1535 } 1536 } else { 1537 mr_asprintf(tmp, "Failed to partition %s", partition_name); 1538 if (partsize > 0) { 1539 log_to_screen(tmp); 1540 } else { 1541 log_it(tmp); 1542 } 1543 mr_free(tmp); 1544 retval++; 1545 } 1546 } 1547 mr_free(program); 1548 mr_free(output); 1549 mr_free(partition_name); 1550 1551 g_current_progress++; 1552 log_it("partition_device() --- leaving"); 986 1553 return (retval); 987 1554 } … … 1532 2099 } 1533 2100 1534 /**1535 * Create partition number @p partno on @p drive with @p fdisk.1536 * @param drive The drive to create the partition on.1537 // * @param partno The partition number of the new partition (1-4 are primary, >=5 is logical).1538 * @param prev_partno The partition number of the most recently prepped partition.1539 * @param format The filesystem type of this partition (used to set the type).1540 * @param partsize The size of the partition in @e bytes.1541 * @return 0 for success, nonzero for failure.1542 */1543 int partition_device(FILE * pout_to_fdisk, const char *drive, int partno, int prev_partno, const char *format, long long partsize) {1544 1545 /** int **************************************************************/1546 int retval = 0;1547 int res = 0;1548 1549 /** buffers **********************************************************/1550 char *program = NULL;1551 char *partition_name = NULL;1552 char *tmp = NULL;1553 char *output = NULL;1554 1555 /** pointers **********************************************************/1556 char *part_table_fmt = NULL;1557 FILE *fout;1558 1559 /** end ***************************************************************/1560 1561 assert_string_is_neither_NULL_nor_zerolength(drive);1562 assert(format != NULL);1563 1564 log_it("partition_device('%s', %d, %d, '%s', %lld) --- starting", drive, partno, prev_partno, format, partsize);1565 1566 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {1567 log_it("Not partitioning %s - it is a virtual drive", drive);1568 return (0);1569 }1570 1571 partition_name = build_partition_name(drive, partno);1572 if (partsize <= 0) {1573 mr_asprintf(tmp, "Partitioning device %s (max size)", partition_name);1574 } else {1575 mr_asprintf(tmp, "Partitioning device %s (%lld MB)", partition_name, (long long) partsize / 1024);1576 }1577 update_progress_form(tmp);1578 log_it(tmp);1579 mr_free(tmp);1580 1581 if (is_this_device_mounted(partition_name)) {1582 log_to_screen("%s is mounted, and should not be partitioned", partition_name);1583 mr_free(partition_name);1584 return (1);1585 }1586 1587 1588 mr_asprintf(program, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);1589 1590 /* TODO: should not be called each time */1591 part_table_fmt = which_partition_format(drive);1592 mr_asprintf(output, "");1593 1594 /* make it a primary/extended/logical */1595 if (partno <= 4) {1596 mr_strcat(output, "n\np\n%d\n", partno);1597 } else {1598 /* MBR needs an extended partition if more than 4 partitions */1599 if (strcmp(part_table_fmt, "MBR") == 0) {1600 if (partno == 5) {1601 if (prev_partno >= 4) {1602 log_to_screen("You need to leave at least one partition free, for 'extended/logical'");1603 mr_free(partition_name);1604 paranoid_free(output);1605 return (1);1606 } else {1607 mr_strcat(output, "n\ne\n%d\n\n\n", prev_partno + 1);1608 }1609 }1610 mr_strcat(output, "n\nl\n");1611 } else {1612 /* GPT allows more than 4 primary partitions */1613 mr_strcat(output, "n\np\n%d\n", partno);1614 }1615 }1616 mr_free(part_table_fmt);1617 1618 mr_strcat(output, "\n"); /*start block (ENTER for next free blk */1619 if (partsize > 0) {1620 if (!strcmp(format, "7")) {1621 log_msg(1, "Adding 512K, just in case");1622 partsize += 512;1623 }1624 mr_strcat(output, "+%lldK", (long long) (partsize));1625 }1626 mr_strcat(output, "\n");1627 #if 01628 /*1629 #endif1630 log_it("PARTSIZE = +%ld",(long)partsize);1631 log_it("---fdisk command---");1632 log_it(output);1633 log_it("---end of fdisk---");1634 #if 01635 */1636 #endif1637 1638 1639 if (pout_to_fdisk) {1640 log_msg(1, "Doing the new all-in-one fdisk thing");1641 mr_strcat(output, "\n\np\n\n");1642 log_msg(1, "output = '%s'", output);1643 fput_string_one_char_at_a_time(pout_to_fdisk, output);1644 mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG));1645 if (strstr(tmp, " (m ")) {1646 log_msg(1, "Successfully created partition %d on %s", partno, drive);1647 } else {1648 log_msg(1, "last line = %s", tmp);1649 log_msg(1, "Failed to create partition %d on %s; sending 'Enter'...", partno, drive);1650 }1651 mr_free(tmp);1652 1653 if (!retval) {1654 log_msg(1, "Trying to set partition %d type now on %s", partno, drive);1655 retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);1656 if (retval) {1657 log_msg(1, "Failed. Trying again...");1658 retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);1659 }1660 }1661 if (retval) {1662 log_msg(1, "...but failed to set type");1663 }1664 } else {1665 mr_strcat(output, "w\n\n");1666 if (g_fprep) {1667 fprintf(g_fprep, "echo \"%s\" | %s\n", output, program);1668 }1669 /* write to disk; close fdisk's stream */1670 if (!(fout = popen(program, "w"))) {1671 log_OS_error("can't popen-out to program");1672 } else {1673 fputs(output, fout);1674 paranoid_pclose(fout);1675 }1676 1677 if (!does_partition_exist(drive, partno) && partsize > 0) {1678 log_it("Vaccum-packing");1679 g_current_progress--;1680 res = partition_device(pout_to_fdisk, drive, partno, prev_partno, format, -1);1681 if (res) {1682 log_it("Failed to vacuum-pack %s", partition_name);1683 retval++;1684 } else {1685 retval = 0;1686 }1687 }1688 if (does_partition_exist(drive, partno)) {1689 retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);1690 if (retval) {1691 log_it("Partitioned %s but failed to set its type", partition_name);1692 } else {1693 if (partsize > 0) {1694 log_to_screen("Partition %s created+configured OK", partition_name);1695 } else {1696 log_it("Returning from a successful vacuum-pack");1697 }1698 }1699 } else {1700 mr_asprintf(tmp, "Failed to partition %s", partition_name);1701 if (partsize > 0) {1702 log_to_screen(tmp);1703 } else {1704 log_it(tmp);1705 }1706 mr_free(tmp);1707 retval++;1708 }1709 }1710 mr_free(program);1711 mr_free(output);1712 mr_free(partition_name);1713 1714 g_current_progress++;1715 log_it("partition_device() --- leaving");1716 return (retval);1717 }1718 1719 1720 2101 1721 2102 /** … … 1789 2170 1790 2171 1791 1792 2172 /** 1793 * Set the type of partition number @p partno on @p drive to @p format. 1794 * @param drive The drive to change the type of a partition on. 1795 * @param partno The partition number on @p drive to change the type of. 1796 * @param format The filesystem type this partition will eventually contain. 1797 * @param partsize The size of this partition, in @e bytes (used for vfat 1798 * type calculations). 1799 * @return 0 for success, nonzero for failure. 2173 * Create a mountlist_reference structure for @p drive_name in @p mountlist. 2174 * @param mountlist The complete mountlist to get the drive references from. 2175 * @param drive_name The drive to put in @p drivemntlist. 2176 * @param drivemntlist The mountlist_reference structure to put the drive's entries in. 2177 * @note @p drivemntlist and @p drivemntlist->el must be allocated by the caller. 2178 * @author Ralph Grewe 1800 2179 */ 1801 int set_partition_type(FILE * pout_to_fdisk, const char *drive, int partno, const char *format, long long partsize) { 1802 1803 /** buffers *********************************************************/ 1804 char *partition = NULL; 1805 char *command = NULL; 1806 char *output = NULL; 1807 char *tmp = NULL; 1808 char *partcode = NULL; 1809 1810 /** pointers *********************************************************/ 1811 FILE *fout; 1812 1813 /** int **************************************************************/ 1814 int res = 0; 1815 1816 /** end **************************************************************/ 1817 1818 assert_string_is_neither_NULL_nor_zerolength(drive); 1819 assert(format != NULL); 1820 1821 partition = build_partition_name(drive, partno); 1822 if (strcmp(format, "swap") == 0) { 1823 mr_asprintf(partcode, "82"); 1824 } else if (strcmp(format, "vfat") == 0) { 1825 if (partsize / 1024 > 8192) { 1826 mr_asprintf(partcode, "c"); 1827 } else { 1828 mr_asprintf(partcode, "b"); 1829 } 1830 } else if (strcmp(format, "ext2") == 0 1831 || strcmp(format, "reiserfs") == 0 1832 || strcmp(format, "ext3") == 0 1833 || strcmp(format, "ext4") == 0 1834 || strcmp(format, "xfs") == 0 1835 || strcmp(format, "jfs") == 0 1836 || strcmp(format, "btrfs") == 0) { 1837 mr_asprintf(partcode, "83"); 1838 } else if (strcmp(format, "minix") == 0) { 1839 mr_asprintf(partcode, "81"); 1840 } else if (strcmp(format, "vmfs3") == 0) { 1841 mr_asprintf(partcode, "fb"); 1842 } else if (strcmp(format, "vmkcore") == 0) { 1843 mr_asprintf(partcode, "fc"); 1844 } else if (strcmp(format, "raid") == 0) { 1845 mr_asprintf(partcode, "fd"); 1846 } else if (strcmp(format, "ntfs") == 0) { 1847 mr_asprintf(partcode, "7"); 1848 } else if ((strcmp(format, "ufs") == 0) 1849 || (strcmp(format, "ffs") == 0)) { /* raid autodetect */ 1850 mr_asprintf(partcode, "a5"); 1851 } else if (strcmp(format, "lvm") == 0) { 1852 mr_asprintf(partcode, "8e"); 1853 } else if (format[0] == '\0') { /* LVM physical partition */ 1854 mr_asprintf(partcode, ""); 1855 } else if (strlen(format) >= 1 && strlen(format) <= 2) { 1856 mr_asprintf(partcode, "%s", format); 1857 } else { 1858 /* probably an image */ 1859 mr_asprintf(tmp, "Unknown format ('%s') - using supplied string anyway", format); 1860 mvaddstr_and_log_it(g_currentY++, 0, tmp); 1861 mr_free(tmp); 1862 1863 #ifdef __FreeBSD__ 1864 mr_asprintf(partcode, "%s", format); // was a5 1865 #else 1866 mr_asprintf(partcode, "%s", format); // was 83 1867 #endif 1868 } 1869 log_msg(1, "Setting %s's type to %s (%s)", partition, format, partcode); 1870 mr_free(partition); 1871 1872 if ((strcmp(partcode,"") != 0) && strcmp(partcode, "83")) { /* no need to set type if 83: 83 is default */ 1873 1874 if (pout_to_fdisk) { 1875 res = 0; 1876 fput_string_one_char_at_a_time(pout_to_fdisk, "t\n"); 1877 if (partno > 1 1878 || strstr(last_line_of_file(FDISK_LOG), " (1-4)")) { 1879 log_msg(5, "Specifying partno (%d) - yay", partno); 1880 mr_asprintf(tmp, "%d\n", partno); 1881 fput_string_one_char_at_a_time(pout_to_fdisk, tmp); 1882 log_msg(5, "A - last line = '%s'", last_line_of_file(FDISK_LOG)); 1883 mr_free(tmp); 1884 } 1885 1886 mr_asprintf(tmp, "%s\n", partcode); 1887 fput_string_one_char_at_a_time(pout_to_fdisk, tmp); 1888 mr_free(tmp); 1889 1890 log_msg(5, "B - last line = '%s'", 1891 last_line_of_file(FDISK_LOG)); 1892 fput_string_one_char_at_a_time(pout_to_fdisk, "\n"); 1893 log_msg(5, "C - last line = '%s'", 1894 last_line_of_file(FDISK_LOG)); 1895 1896 mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG)); 1897 if (!strstr(tmp, " (m ")) { 1898 log_msg(1, "last line = '%s'; part type set failed", tmp); 1899 res++; 1900 fput_string_one_char_at_a_time(pout_to_fdisk, "\n"); 1901 } 1902 mr_free(tmp); 1903 1904 fput_string_one_char_at_a_time(pout_to_fdisk, "p\n"); 1905 } else { 1906 mr_asprintf(output, "t\n%d\n%s\nw\n", partno, partcode); 1907 mr_asprintf(command, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE); 1908 log_msg(5, "output = '%s'", output); 1909 log_msg(5, "partno=%d; partcode=%s", partno, partcode); 1910 log_msg(5, "command = '%s'", command); 1911 fout = popen(command, "w"); 1912 if (!fout) { 1913 log_OS_error(command); 1914 res = 1; 1915 } else { 1916 res = 0; 1917 fprintf(fout, "%s", output); 1918 paranoid_pclose(fout); 1919 } 1920 mr_free(command); 1921 paranoid_free(output); 1922 } 1923 } 1924 mr_free(partcode); 1925 1926 return (res); 1927 } 1928 1929 1930 int start_raid_device(char *raid_device) { 1931 1932 /** int *************************************************************/ 1933 int res; 1934 int retval = 0; 1935 1936 /** buffers *********************************************************/ 1937 char *program = NULL; 1938 1939 /** end *************************************************************/ 1940 1941 assert_string_is_neither_NULL_nor_zerolength(raid_device); 1942 1943 #ifdef __FreeBSD__ 1944 if (is_this_device_mounted(raid_device)) { 1945 log_it("Can't start %s when it's mounted!", raid_device); 1946 return 1; 1947 } 1948 mr_asprintf(program, "vinum start -f %s", raid_device); 1949 #else 1950 mr_asprintf(program, "raidstart %s", raid_device); 1951 #endif 1952 log_msg(1, "program = %s", program); 1953 res = run_program_and_log_output(program, 1); 1954 if (g_fprep) { 1955 fprintf(g_fprep, "%s\n", program); 1956 } 1957 mr_free(program); 1958 1959 if (res) { 1960 log_msg(1, "Warning - failed to start RAID device %s", raid_device); 1961 } 1962 retval += res; 1963 sleep(1); 1964 return (retval); 1965 } 1966 1967 1968 1969 /** 1970 * Stop @p raid_device using @p raidstop. 1971 * @param raid_device The software RAID device to stop. 1972 * @return 0 for success, nonzero for failure. 1973 */ 1974 int stop_raid_device(char *raid_device) { 1975 1976 /** int *************************************************************/ 1977 int res; 1978 int retval = 0; 1979 1980 /** buffers *********************************************************/ 1981 char *program = NULL; 1982 1983 /** end *************************************************************/ 1984 1985 assert_string_is_neither_NULL_nor_zerolength(raid_device); 1986 1987 #ifdef __FreeBSD__ 1988 if (is_this_device_mounted(raid_device)) { 1989 log_it("Can't stop %s when it's mounted!", raid_device); 1990 return 1; 1991 } 1992 mr_asprintf(program, "vinum stop -f %s", raid_device); 1993 #else 1994 // use raidstop if it exists, otherwise use mdadm 1995 if (run_program_and_log_output("which raidstop", FALSE)) { 1996 mr_asprintf(program, "mdadm -S %s", raid_device); 1997 } else { 1998 mr_asprintf(program, "raidstop %s", raid_device); 1999 } 2000 #endif 2001 log_msg(1, "program = %s", program); 2002 res = run_program_and_log_output(program, 1); 2003 if (g_fprep) { 2004 fprintf(g_fprep, "%s\n", program); 2005 } 2006 mr_free(program); 2007 2008 if (res) { 2009 log_msg(1, "Warning - failed to stop RAID device %s", raid_device); 2010 } 2011 retval += res; 2012 return (retval); 2013 } 2014 2015 2016 int start_all_raid_devices(struct mountlist_itself *mountlist) { 2017 2018 int i; 2019 int retval = 0; 2020 int res; 2021 2022 for (i = 0; i < mountlist->entries; i++) { 2023 if (!strncmp(mountlist->el[i].device, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) { 2024 log_msg(1, "Starting %s", mountlist->el[i].device); 2025 res = start_raid_device(mountlist->el[i].device); 2026 retval += res; 2027 } 2028 } 2029 if (retval) { 2030 log_msg(1, "Started all s/w raid devices OK"); 2031 } else { 2032 log_msg(1, "Failed to start some/all s/w raid devices"); 2033 } 2034 return (retval); 2035 } 2036 2037 /** 2038 * Stop all software RAID devices listed in @p mountlist. 2039 * @param mountlist The mountlist to stop the RAID devices in. 2040 * @return The number of errors encountered (0 for success). 2041 * @bug @p mountlist is not used. 2042 */ 2043 int stop_all_raid_devices(struct mountlist_itself *mountlist) { 2044 2045 /** int *************************************************************/ 2046 int retval = 0; 2047 2048 /** char ************************************************************/ 2049 char *incoming; 2050 #ifndef __FreeBSD__ 2051 char *dev; 2052 #endif 2053 /** pointers ********************************************************/ 2054 #ifndef __FreeBSD__ 2055 char *p; 2056 #endif 2057 FILE *fin; 2058 char *q; 2059 int i; 2060 2061 /** end ****************************************************************/ 2062 2063 malloc_string(incoming); 2180 void create_mountlist_for_drive(struct mountlist_itself *mountlist, char *drive_name, struct mountlist_reference *drivemntlist) { 2181 2182 int partno; 2183 char *tmp_drive_name, *c; 2184 2064 2185 assert(mountlist != NULL); 2065 2066 for (i = 0; i < 3; i++) { 2067 #ifdef __FreeBSD__ 2068 fin = popen("vinum list | grep '^[PVS]' | sed 's/S/1/;s/P/2/;s/V/3/' | sort | cut -d' ' -f2", "r"); 2069 if (!fin) { 2070 paranoid_free(incoming); 2071 return (1); 2072 } 2073 for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) { 2074 retval += stop_raid_device(incoming); 2075 } 2076 #else 2077 fin = fopen("/proc/mdstat", "r"); 2078 if (!fin) { 2079 log_OS_error("/proc/mdstat"); 2080 paranoid_free(incoming); 2081 return (1); 2082 } 2083 for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) { 2084 for (p = incoming; *p != '\0' && (*p != 'm' || *(p + 1) != 'd' || !isdigit(*(p + 2))); p++); 2085 if (*p != '\0') { 2086 malloc_string(dev); 2087 sprintf(dev, "/dev/%s", p); 2088 for (p = dev; *p > 32; p++); 2089 *p = '\0'; 2090 retval += stop_raid_device(dev); 2091 paranoid_free(dev); 2092 } 2093 } 2094 #endif 2095 } 2096 paranoid_fclose(fin); 2097 if (retval) { 2098 log_msg(1, "Warning - unable to stop some RAID devices"); 2099 } 2100 paranoid_free(incoming); 2101 paranoid_system("sync"); 2102 paranoid_system("sync"); 2103 paranoid_system("sync"); 2104 sleep(1); 2105 return (retval); 2106 } 2107 2108 2109 2110 /** 2111 * Decide which command we need to use to format a device of type @p format. 2112 * @param format The filesystem type we are about to format. 2113 * @param program Where to put the binary name for this format. 2114 * @return 0 for success, nonzero for failure. 2115 */ 2116 char *which_format_command_do_i_need(char *format) { 2117 2118 char *program = NULL; 2119 2120 assert_string_is_neither_NULL_nor_zerolength(format); 2121 2122 if (strcmp(format, "swap") == 0) { 2123 #ifdef __FreeBSD__ 2124 mr_asprintf(program, "true"); 2125 #else 2126 mr_asprintf(program, "mkswap -f"); 2127 #endif 2128 } else if (strcmp(format, "vfat") == 0) { 2129 #ifdef __FreeBSD__ 2130 mr_asprintf(program, "newfs_msdos -F 32"); 2131 #else 2132 #ifdef __IA64__ 2133 /* For EFI partitions on ia64 take fat16 2134 * as we want to make small ones */ 2135 mr_asprintf(program, "mkfs.vfat -F 16"); 2136 #else 2137 /* mkfs.vfat will make the best possible choice itself */ 2138 /* should avoid problems with mr-label later on when used */ 2139 mr_asprintf(program, "mkfs.vfat"); 2140 #endif 2141 #endif 2142 #ifndef __FreeBSD__ 2143 } else if (strcmp(format, "reiserfs") == 0) { 2144 mr_asprintf(program, "mkreiserfs -ff"); 2145 } else if (strcmp(format, "xfs") == 0) { 2146 /* Cf: https://bugzilla.redhat.com/show_bug.cgi?id=1309498 */ 2147 mr_asprintf(program, "mkfs.xfs -f -q -m crc=0 -n ftype=0"); 2148 } else if (strcmp(format, "jfs") == 0) { 2149 mr_asprintf(program, "mkfs.jfs"); 2150 } else if (strcmp(format, "ext3") == 0) { 2151 mr_asprintf(program, "mkfs -t ext3 -F -q"); 2152 } else if (strcmp(format, "ext4") == 0) { 2153 mr_asprintf(program, "mkfs -t ext4 -F -q"); 2154 } else if (strcmp(format, "btrfs") == 0) { 2155 mr_asprintf(program, "mkfs.btrfs -f"); 2156 } else if (strcmp(format, "minix") == 0) { 2157 mr_asprintf(program, "mkfs.minix"); 2158 } else if (strcmp(format, "vmfs") == 0) { 2159 mr_asprintf(program, "mkfs -t vmfs"); 2160 } else if (strcmp(format, "ntfs") == 0) { 2161 /* 2162 * mkfs.ntfs treats the '-c' switch as 'specify cluster size' 2163 * so the default "mkfs -t %s -c" command structure fails 2164 */ 2165 mr_asprintf(program, "mkfs -t ntfs"); 2166 } else if (strcmp(format, "ocfs2") == 0) { 2167 /* 2168 * For existing OCFS2 volumes, mkfs.ocfs2 ensures the volume is not mounted on any node in the cluster before formatting. For that to work, mkfs.ocfs2 expects the O2CB cluster service to be running. Specify this option to disable this check. 2169 * 2170 */ 2171 mr_asprintf(program, "mkfs -t ocfs2 -F"); 2172 #endif 2173 } else if (strcmp(format, "ext2") == 0) { 2174 mr_asprintf(program, "mke2fs -F -q"); 2175 } else { 2176 #ifdef __FreeBSD__ 2177 mr_asprintf(program, "newfs_%s", format); 2178 #else 2179 mr_asprintf(program, "mkfs -t %s -c", format); // -c checks for bad blocks 2180 #endif 2181 log_it("Unknown format (%s) - assuming '%s' will do", format, program); 2182 } 2183 return(program); 2186 assert(drive_name != NULL); 2187 assert(drivemntlist != NULL); 2188 2189 log_msg(1, "Creating list of partitions for drive %s", drive_name); 2190 2191 tmp_drive_name = strdup(drive_name); 2192 if (!tmp_drive_name) 2193 fatal_error("Out of memory"); 2194 2195 /* devfs devices? */ 2196 c = strrchr(tmp_drive_name, '/'); 2197 if (c && strncmp(c, "/disc", 5) == 0) { 2198 /* yup its devfs, change the "disc" to "part" so the existing code works */ 2199 strcpy(c + 1, "part"); 2200 } 2201 drivemntlist->entries = 0; 2202 for (partno = 0; partno < mountlist->entries; partno++) { 2203 if (strncmp(mountlist->el[partno].device, tmp_drive_name, strlen(tmp_drive_name)) == 0) { 2204 drivemntlist->el[drivemntlist->entries] = &mountlist->el[partno]; 2205 drivemntlist->entries++; 2206 } 2207 } 2208 if (tmp_drive_name) 2209 free(tmp_drive_name); 2184 2210 } 2185 2211 … … 2331 2357 paranoid_free(drivelist); 2332 2358 } 2333 2334 /**2335 * Create a mountlist_reference structure for @p drive_name in @p mountlist.2336 * @param mountlist The complete mountlist to get the drive references from.2337 * @param drive_name The drive to put in @p drivemntlist.2338 * @param drivemntlist The mountlist_reference structure to put the drive's entries in.2339 * @note @p drivemntlist and @p drivemntlist->el must be allocated by the caller.2340 * @author Ralph Grewe2341 */2342 void create_mountlist_for_drive(struct mountlist_itself *mountlist, char *drive_name, struct mountlist_reference *drivemntlist) {2343 2344 int partno;2345 char *tmp_drive_name, *c;2346 2347 assert(mountlist != NULL);2348 assert(drive_name != NULL);2349 assert(drivemntlist != NULL);2350 2351 log_msg(1, "Creating list of partitions for drive %s", drive_name);2352 2353 tmp_drive_name = strdup(drive_name);2354 if (!tmp_drive_name)2355 fatal_error("Out of memory");2356 2357 /* devfs devices? */2358 c = strrchr(tmp_drive_name, '/');2359 if (c && strncmp(c, "/disc", 5) == 0) {2360 /* yup its devfs, change the "disc" to "part" so the existing code works */2361 strcpy(c + 1, "part");2362 }2363 drivemntlist->entries = 0;2364 for (partno = 0; partno < mountlist->entries; partno++) {2365 if (strncmp(mountlist->el[partno].device, tmp_drive_name, strlen(tmp_drive_name)) == 0) {2366 drivemntlist->el[drivemntlist->entries] = &mountlist->el[partno];2367 drivemntlist->entries++;2368 }2369 }2370 if (tmp_drive_name)2371 free(tmp_drive_name);2372 }2373 2374 2359 /* @} - end of prepGroup */ -
branches/3.3/mondo/src/mondorestore/mondo-rstr-compare.c
r3875 r3879 7 7 #include "mr_mem.h" 8 8 #include "mr_file.h" 9 #include "../common/mondostructures.h" 10 #include "../common/libmondo.h" 11 //#include "../../config.h" 12 #include "mr-externs.h" 13 #include "mondo-rstr-compare.h" 14 #include "mondorestore-EXT.h" 9 #include "mr_sys.h" 10 #include "mondostructures.h" 15 11 #include "mondo-rstr-tools-EXT.h" 12 #include "libmondo-string-EXT.h" 13 #include "libmondo-verify-EXT.h" 14 #include "libmondo-files-EXT.h" 15 #include "libmondo-tools-EXT.h" 16 #include "libmondo-fork-EXT.h" 17 #include "libmondo-devices-EXT.h" 18 #include "libmondo-string-EXT.h" 19 #include "libmondo-mountlist-EXT.h" 20 #include "libmondo-raid-EXT.h" 21 #include "newt-specific-EXT.h" 16 22 17 23 extern char *MONDO_LOGFILE; … … 21 27 22 28 extern char *g_mountlist_fname; 29 extern int g_current_media_number; 30 extern bool g_text_mode; 31 extern int g_currentY; 32 extern long g_current_progress; 33 extern char *g_mondo_cfg_file; 34 35 // in mondo-rstr-newt.c 36 extern int edit_mountlist(char *, struct mountlist_itself *, struct raidlist_itself *); 23 37 24 38 //static char cvsid[] = "$Id$"; … … 63 77 64 78 if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) { 65 if (does_file_exist( MNT_CDROM "/archives/NOT-THE-LAST")) {79 if (does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST")) { 66 80 insist_on_this_cd_number((++g_current_media_number)); 67 81 } else { … … 368 382 insist_on_this_cd_number(g_current_media_number); 369 383 update_progress_form(progress_str); 370 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.bz2", current_tarball_number);384 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.bz2", current_tarball_number); 371 385 372 386 if (!does_file_exist(tarball_fname)) { 373 387 mr_free(tarball_fname); 374 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.lzo", current_tarball_number);388 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.lzo", current_tarball_number); 375 389 } 376 390 if (!does_file_exist(tarball_fname)) { 377 391 mr_free(tarball_fname); 378 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.lzma", current_tarball_number);392 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.lzma", current_tarball_number); 379 393 } 380 394 if (!does_file_exist(tarball_fname)) { 381 395 mr_free(tarball_fname); 382 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.gz", current_tarball_number);396 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.gz", current_tarball_number); 383 397 } 384 398 if (!does_file_exist(tarball_fname)) { 385 399 mr_free(tarball_fname); 386 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.", current_tarball_number);400 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.", current_tarball_number); 387 401 } 388 402 if (!does_file_exist(tarball_fname)) { 389 403 mr_free(tarball_fname); 390 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.star.bz2", current_tarball_number);404 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.star.bz2", current_tarball_number); 391 405 } 392 406 if (!does_file_exist(tarball_fname)) { 393 407 mr_free(tarball_fname); 394 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.star.", current_tarball_number);408 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.star.", current_tarball_number); 395 409 } 396 410 if (!does_file_exist(tarball_fname)) { 397 if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST") || 398 system("find " MNT_CDROM 399 "/archives/slice* > /dev/null 2> /dev/null") 411 if (!does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST") || 412 system("find " ARCHIVES_PATH "/slice* > /dev/null 2> /dev/null") 400 413 == 0) { 401 414 log_msg(2, "OK, I think I'm done with tarballs..."); … … 492 505 **************************************************************************/ 493 506 507 /** 508 * Compare all data on a tape-based backup. 509 * @param bkpinfo The backup information structure. Field used: @c bkpinfo->restore_path. 510 * @return 0 for success, nonzero for failure. 511 */ 512 /************************************************************************** 513 * F@COMPARE_TO_TAPE() * 514 * compare_to_tape() - gots me?? * 515 * * 516 * returns: int * 517 **************************************************************************/ 518 int compare_to_tape() 519 { 520 int res; 521 char *dir; 522 char *command = NULL; 523 524 assert(bkpinfo != NULL); 525 malloc_string(dir); 526 527 if (getcwd(dir, MAX_STR_LEN)) { 528 // FIXME 529 } 530 if (chdir(bkpinfo->restore_path)) { 531 // FIXME 532 } 533 mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path); 534 run_program_and_log_output(command, FALSE); 535 mr_free(command); 536 537 mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem"); 538 res = verify_tape_backups(); 539 if (chdir(dir)) { 540 // FIXME 541 } 542 if (res) { 543 mvaddstr_and_log_it(g_currentY++, 74, "Failed."); 544 } else { 545 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 546 } 547 paranoid_free(dir); 548 return (res); 549 } 550 551 /************************************************************************** 552 *END_COMPARE_TO_TAPE * 553 **************************************************************************/ 554 555 556 /** 557 * Compare all data on a cdstream-based backup. 558 * @param bkpinfo The backup information structure. Fields used: 559 * - @c bkpinfo->disaster_recovery 560 * - @c bkpinfo->media_device 561 * - @c bkpinfo->restore_path 562 * @return 0 for success, nonzero for failure. 563 */ 564 int compare_to_cdstream() 565 { 566 int res; 567 568 /** needs malloc **/ 569 char *dir; 570 char *command = NULL; 571 572 assert(bkpinfo != NULL); 573 malloc_string(dir); 574 if (getcwd(dir, MAX_STR_LEN)) { 575 // FIXME 576 } 577 if (chdir(bkpinfo->restore_path)) { 578 // FIXME 579 } 580 581 mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path); 582 run_program_and_log_output(command, FALSE); 583 mr_free(command); 584 mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem"); 585 586 if (bkpinfo->disaster_recovery 587 && does_file_exist("/tmp/CDROM-LIVES-HERE")) { 588 mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE")); 589 } else { 590 bkpinfo->media_device = find_optical_device(); 591 } 592 res = verify_tape_backups(); 593 if (chdir(dir)) { 594 // FIXME 595 } 596 if (length_of_file(MONDO_CACHE"/changed.txt") > 2 597 && length_of_file(MONDO_CACHE"/changed.files") > 2) { 598 log_msg(0, 599 "Type 'less "MONDO_CACHE"/changed.files' to see which files don't match the archives"); 600 log_msg(2, "Calling popup_changelist_from_file()"); 601 popup_changelist_from_file(MONDO_CACHE"/changed.files"); 602 log_msg(2, "Returned from popup_changelist_from_file()"); 603 } 604 605 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 606 paranoid_free(dir); 607 return (res); 608 } 609 610 /************************************************************************** 611 *END_COMPARE_CD_STREAM * 612 **************************************************************************/ 494 613 495 614 … … 620 739 *END_COMPARE_MODE * 621 740 **************************************************************************/ 622 623 /**624 * Compare all data on a cdstream-based backup.625 * @param bkpinfo The backup information structure. Fields used:626 * - @c bkpinfo->disaster_recovery627 * - @c bkpinfo->media_device628 * - @c bkpinfo->restore_path629 * @return 0 for success, nonzero for failure.630 */631 int compare_to_cdstream()632 {633 int res;634 635 /** needs malloc **/636 char *dir;637 char *command = NULL;638 639 assert(bkpinfo != NULL);640 malloc_string(dir);641 if (getcwd(dir, MAX_STR_LEN)) {642 // FIXME643 }644 if (chdir(bkpinfo->restore_path)) {645 // FIXME646 }647 648 mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path);649 run_program_and_log_output(command, FALSE);650 mr_free(command);651 mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem");652 653 if (bkpinfo->disaster_recovery654 && does_file_exist("/tmp/CDROM-LIVES-HERE")) {655 mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE"));656 } else {657 bkpinfo->media_device = find_optical_device();658 }659 res = verify_tape_backups();660 if (chdir(dir)) {661 // FIXME662 }663 if (length_of_file(MONDO_CACHE"/changed.txt") > 2664 && length_of_file(MONDO_CACHE"/changed.files") > 2) {665 log_msg(0,666 "Type 'less "MONDO_CACHE"/changed.files' to see which files don't match the archives");667 log_msg(2, "Calling popup_changelist_from_file()");668 popup_changelist_from_file(MONDO_CACHE"/changed.files");669 log_msg(2, "Returned from popup_changelist_from_file()");670 }671 672 mvaddstr_and_log_it(g_currentY++, 74, "Done.");673 paranoid_free(dir);674 return (res);675 }676 677 /**************************************************************************678 *END_COMPARE_CD_STREAM *679 **************************************************************************/680 681 682 /**683 * Compare all data on a tape-based backup.684 * @param bkpinfo The backup information structure. Field used: @c bkpinfo->restore_path.685 * @return 0 for success, nonzero for failure.686 */687 /**************************************************************************688 * F@COMPARE_TO_TAPE() *689 * compare_to_tape() - gots me?? *690 * *691 * returns: int *692 **************************************************************************/693 int compare_to_tape()694 {695 int res;696 char *dir;697 char *command = NULL;698 699 assert(bkpinfo != NULL);700 malloc_string(dir);701 702 if (getcwd(dir, MAX_STR_LEN)) {703 // FIXME704 }705 if (chdir(bkpinfo->restore_path)) {706 // FIXME707 }708 mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path);709 run_program_and_log_output(command, FALSE);710 mr_free(command);711 712 mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem");713 res = verify_tape_backups();714 if (chdir(dir)) {715 // FIXME716 }717 if (res) {718 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");719 } else {720 mvaddstr_and_log_it(g_currentY++, 74, "Done.");721 }722 paranoid_free(dir);723 return (res);724 }725 726 /**************************************************************************727 *END_COMPARE_TO_TAPE *728 **************************************************************************/729 730 741 /* @} - end compareGroup */ -
branches/3.3/mondo/src/mondorestore/mondo-rstr-mountlist.c
r3871 r3879 12 12 #include "mr_mem.h" 13 13 #include "mondostructures.h" 14 #include "libmondo-mountlist.h"15 16 14 #include "libmondo-raid-EXT.h" 17 15 #include "libmondo-devices-EXT.h" … … 535 533 536 534 /** 535 * Make a list of the drives mentioned in the mountlist. 536 * @param mountlist The mountlist to examine. 537 * @param drivelist Where to put the list of drives found. 538 * @return The number of physical (non-RAID non-LVM) drives found, or \<= 0 for error. 539 */ 540 int 541 make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist, 542 struct list_of_disks *drivelist) 543 { 544 545 /*@ int ************************************************************* */ 546 int lino; 547 int noof_drives; 548 int j; 549 550 /*@ buffers ********************************************************* */ 551 char *drive = NULL; 552 char *truncdrive = NULL; 553 554 long long size; 555 556 assert(mountlist != NULL); 557 assert(drivelist != NULL); 558 log_it("Making list of drives"); 559 for (lino = 0, noof_drives = 0; lino < mountlist->entries; lino++) { 560 561 mr_asprintf(drive, "%s", mountlist->el[lino].device); 562 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) { 563 log_msg(8, "Not putting %s in list of drives: it's a virtual drive", drive); 564 mr_free(drive); 565 continue; 566 } 567 568 size = mountlist->el[lino].size; 569 if (size == 0) { 570 log_msg(8, "Not putting %s in list of drives: it has zero size (maybe an LVM volume)", drive); 571 mr_free(drive); 572 continue; 573 } 574 575 log_msg(8, "Putting %s with size %lli in list of drives", drive, size); 576 577 /* memory allocation */ 578 truncdrive = truncate_to_drive_name(drive); 579 mr_free(drive); 580 581 log_msg(8, "drive truncated to %s", truncdrive); 582 583 for (j = 0; 584 j < noof_drives 585 && strcmp(drivelist->el[j].device, truncdrive) != 0; j++) { 586 continue; 587 } 588 if (j == noof_drives) { 589 strncpy(drivelist->el[noof_drives].device, truncdrive, 63); 590 drivelist->el[noof_drives].device[63] = '\0'; 591 log_msg(8,"Adding drive %s to list", drivelist->el[noof_drives].device); 592 noof_drives++; 593 } 594 paranoid_free(truncdrive); 595 if (noof_drives >= MAXIMUM_DISKS_PER_RAID_DEV) { 596 log_msg(0, "Unable to handle mountlist with more than %d lines", MAXIMUM_DISKS_PER_RAID_DEV); 597 log_to_screen("Unable to handle a so big mountlist"); 598 finish(1); 599 } 600 } 601 drivelist->entries = noof_drives; 602 log_msg(8, "Made list of %d drives",noof_drives); 603 604 return (noof_drives); 605 } 606 607 608 /** 537 609 * Evaluate a whole mountlist for flaws. Calls evaluate_drive_within_mountlist() 538 610 * for each drive, and then spreads the flaws across three lines. … … 642 714 return (i); 643 715 } 644 }645 646 647 /**648 * Make a list of the drives mentioned in the mountlist.649 * @param mountlist The mountlist to examine.650 * @param drivelist Where to put the list of drives found.651 * @return The number of physical (non-RAID non-LVM) drives found, or \<= 0 for error.652 */653 int654 make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist,655 struct list_of_disks *drivelist)656 {657 658 /*@ int ************************************************************* */659 int lino;660 int noof_drives;661 int j;662 663 /*@ buffers ********************************************************* */664 char *drive = NULL;665 char *truncdrive = NULL;666 667 long long size;668 669 assert(mountlist != NULL);670 assert(drivelist != NULL);671 log_it("Making list of drives");672 for (lino = 0, noof_drives = 0; lino < mountlist->entries; lino++) {673 674 mr_asprintf(drive, "%s", mountlist->el[lino].device);675 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {676 log_msg(8, "Not putting %s in list of drives: it's a virtual drive", drive);677 mr_free(drive);678 continue;679 }680 681 size = mountlist->el[lino].size;682 if (size == 0) {683 log_msg(8, "Not putting %s in list of drives: it has zero size (maybe an LVM volume)", drive);684 mr_free(drive);685 continue;686 }687 688 log_msg(8, "Putting %s with size %lli in list of drives", drive, size);689 690 /* memory allocation */691 truncdrive = truncate_to_drive_name(drive);692 mr_free(drive);693 694 log_msg(8, "drive truncated to %s", truncdrive);695 696 for (j = 0;697 j < noof_drives698 && strcmp(drivelist->el[j].device, truncdrive) != 0; j++) {699 continue;700 }701 if (j == noof_drives) {702 strncpy(drivelist->el[noof_drives].device, truncdrive, 63);703 drivelist->el[noof_drives].device[63] = '\0';704 log_msg(8,"Adding drive %s to list", drivelist->el[noof_drives].device);705 noof_drives++;706 }707 paranoid_free(truncdrive);708 if (noof_drives >= MAXIMUM_DISKS_PER_RAID_DEV) {709 log_msg(0, "Unable to handle mountlist with more than %d lines", MAXIMUM_DISKS_PER_RAID_DEV);710 log_to_screen("Unable to handle a so big mountlist");711 finish(1);712 }713 }714 drivelist->entries = noof_drives;715 log_msg(8, "Made list of %d drives",noof_drives);716 717 return (noof_drives);718 716 } 719 717 … … 938 936 939 937 /** 938 * Swap two entries in the mountlist in-place. 939 * @param mountlist The mountlist to swap the entries in. 940 * @param a The index number of the first entry. 941 * @param b The index number of the second entry. 942 */ 943 void 944 swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b) 945 { 946 /*@ mallocs *** */ 947 char *device = NULL; 948 char *mountpoint = NULL; 949 char *format = NULL; 950 951 long long size; 952 953 assert(mountlist != NULL); 954 assert(a >= 0); 955 assert(b >= 0); 956 957 mr_asprintf(device, "%s", mountlist->el[a].device); 958 mr_asprintf(mountpoint, "%s", mountlist->el[a].mountpoint); 959 mr_asprintf(format, "%s", mountlist->el[a].format); 960 961 size = mountlist->el[a].size; 962 963 strcpy(mountlist->el[a].device, mountlist->el[b].device); 964 strcpy(mountlist->el[a].mountpoint, mountlist->el[b].mountpoint); 965 strcpy(mountlist->el[a].format, mountlist->el[b].format); 966 967 mountlist->el[a].size = mountlist->el[b].size; 968 969 strcpy(mountlist->el[b].device, device); 970 strcpy(mountlist->el[b].mountpoint, mountpoint); 971 strcpy(mountlist->el[b].format, format); 972 973 mountlist->el[b].size = size; 974 mr_free(device); 975 mr_free(mountpoint); 976 mr_free(format); 977 } 978 979 980 981 /** 940 982 * Sort the mountlist alphabetically by device. 941 983 * The sorting is done in-place. … … 991 1033 } 992 1034 993 994 /**995 * Swap two entries in the mountlist in-place.996 * @param mountlist The mountlist to swap the entries in.997 * @param a The index number of the first entry.998 * @param b The index number of the second entry.999 */1000 void1001 swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b)1002 {1003 /*@ mallocs *** */1004 char *device = NULL;1005 char *mountpoint = NULL;1006 char *format = NULL;1007 1008 long long size;1009 1010 assert(mountlist != NULL);1011 assert(a >= 0);1012 assert(b >= 0);1013 1014 mr_asprintf(device, "%s", mountlist->el[a].device);1015 mr_asprintf(mountpoint, "%s", mountlist->el[a].mountpoint);1016 mr_asprintf(format, "%s", mountlist->el[a].format);1017 1018 size = mountlist->el[a].size;1019 1020 strcpy(mountlist->el[a].device, mountlist->el[b].device);1021 strcpy(mountlist->el[a].mountpoint, mountlist->el[b].mountpoint);1022 strcpy(mountlist->el[a].format, mountlist->el[b].format);1023 1024 mountlist->el[a].size = mountlist->el[b].size;1025 1026 strcpy(mountlist->el[b].device, device);1027 strcpy(mountlist->el[b].mountpoint, mountpoint);1028 strcpy(mountlist->el[b].format, format);1029 1030 mountlist->el[b].size = size;1031 mr_free(device);1032 mr_free(mountpoint);1033 mr_free(format);1034 }1035 1036 1035 /* @} - end of mountlistGroup */ -
branches/3.3/mondo/src/mondorestore/mondo-rstr-newt.c
r3856 r3879 10 10 #endif 11 11 12 #include "mondo-rstr-newt.h" 12 #include "my-stuff.h" 13 #include "mondostructures.h" 13 14 #include "mr_mem.h" 14 15 #include "mr_str.h" 16 #include "libmondo-raid-EXT.h" 17 #include "libmondo-mountlist-EXT.h" 18 #include "libmondo-string-EXT.h" 19 #include "libmondo-tools-EXT.h" 20 #include "libmondo-files-EXT.h" 21 #include "libmondo-filelist-EXT.h" 22 #include "newt-specific-EXT.h" 15 23 16 24 //static char cvsid[] = "$Id$"; … … 18 26 extern bool popup_with_buttons(char *p, char *button1, char *button2); 19 27 extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN]; 28 29 static char g_strings_of_flist_window[ARBITRARY_MAXIMUM][MAX_STR_LEN]; 30 static bool g_is_path_selected[ARBITRARY_MAXIMUM]; 31 static bool g_is_path_expanded[ARBITRARY_MAXIMUM]; 32 static char tmpnopath[MAX_STR_LEN + 2]; 33 static char tmpprevpath[MAX_STR_LEN + 2]; 34 35 // from mondo-rstr-mountlist.c 36 extern void make_list_of_unallocated_raid_partitions(struct mountlist_itself *, struct mountlist_itself *, struct raidlist_itself *); 37 38 extern bool g_text_mode; 39 20 40 21 41 /** … … 36 56 37 57 /** 38 * @addtogroup restoreGuiGroup 39 * @{ 40 */ 58 * Redraw the list of unallocated RAID partitions. 59 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions. 60 * @param keylist The list of keys for @p listbox. 61 * @param listbox The Newt listbox component to redraw. 62 * @ingroup restoreGuiDisklist 63 */ 64 void redraw_unallocpartnslist(struct mountlist_itself 65 *unallocated_raid_partitions, 66 void *keylist[ARBITRARY_MAXIMUM], 67 newtComponent listbox) 68 { 69 70 /** long *************************************************************/ 71 long i = 0; 72 73 /** buffers **********************************************************/ 74 char tmp[MAX_STR_LEN]; 75 76 assert(unallocated_raid_partitions != NULL); 77 assert(keylist != NULL); 78 assert(listbox != NULL); 79 80 newtListboxClear(listbox); 81 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 82 keylist[i] = (void *) i; 83 } 84 for (i = 0; i < unallocated_raid_partitions->entries; i++) { 85 sprintf(tmp, "%-22s %8lld", 86 unallocated_raid_partitions->el[i].device, 87 unallocated_raid_partitions->el[i].size / 1024L); 88 newtListboxAppendEntry(listbox, tmp, keylist[i]); 89 } 90 } 91 92 93 /** 94 * Find the next free location to place a disk in @p disklist. 95 * @param disklist The disklist to operate on. 96 * @return The next free location (starting from 0). 97 * @ingroup restoreGuiDisklist 98 */ 99 int find_next_free_index_in_disklist(struct list_of_disks *disklist) 100 { 101 102 /** int ***************************************************************/ 103 int index = -1; 104 int pos = 0; 105 106 /** bool **************************************************************/ 107 bool done; 108 109 assert(disklist != NULL); 110 111 for (done = FALSE; !done;) { 112 for (pos = 0; 113 pos < disklist->entries && disklist->el[pos].index <= index; 114 pos++); 115 if (pos >= disklist->entries) { 116 done = TRUE; 117 } else { 118 index = disklist->el[pos].index; 119 } 120 } 121 return (index + 1); 122 } 123 124 125 41 126 /** 42 127 * Add an entry in @p disklist from the list in @p unallocated_raid_partitions. … … 118 203 119 204 120 121 122 /** 123 * Add an entry to @p mountlist. 124 * @param mountlist The mountlist to add an entry to. 125 * @param raidlist The raidlist that accompanies @p mountlist. 126 * @param listbox The listbox component in the mountlist editor. 127 * @param currline The line selected in @p listbox. 205 /** 206 * Locate @p device in @p raidlist. 207 * @param raidlist The raidlist ot search in. 208 * @param device The RAID device to search for. 209 * @return The index of the device, or -1 if it could not be found. 210 * @ingroup restoreGuiMountlist 211 */ 212 int 213 find_raid_device_in_raidlist(struct raidlist_itself *raidlist, 214 char *device) 215 { 216 217 /** int ***************************************************************/ 218 int i = 0; 219 #ifdef __FreeBSD__ 220 char *vdev = NULL; 221 int res = 0; 222 #else 223 // Linux 224 #endif 225 226 assert(raidlist != NULL); 227 assert_string_is_neither_NULL_nor_zerolength(device); 228 229 #ifdef __FreeBSD__ 230 for (i = 0; i < raidlist->entries; i++) { 231 mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname); 232 res = strcmp(device, vdev); 233 mr_free(vdev); 234 235 if (!res) 236 break; 237 } 238 #else 239 240 for (i = 0; 241 strcmp(raidlist->el[i].raid_device, device) 242 && i < raidlist->entries; i++); 243 #endif 244 if (i == raidlist->entries) { 245 return (-1); 246 } else { 247 return (i); 248 } 249 } 250 251 252 /** 253 * Redraw the disklist. 254 * @param disklist The disklist to read from. 128 255 * @param keylist The list of keys for @p listbox. 256 * @param listbox The Newt listbox component to redraw. 257 * @ingroup restoreGuiDisklist 258 */ 259 void 260 redraw_disklist(struct list_of_disks *disklist, 261 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox) 262 { 263 264 /** long **************************************************************/ 265 long i = 0; 266 char *tmp = NULL; 267 268 assert(disklist != NULL); 269 assert(keylist != NULL); 270 assert(listbox != NULL); 271 272 newtListboxClear(listbox); 273 274 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 275 keylist[i] = (void *) i; 276 } 277 for (i = 0; i < disklist->entries; i++) { 278 tmp = disklist_entry_to_string(disklist, i); 279 newtListboxAppendEntry(listbox, tmp, keylist[i]); 280 mr_free(tmp); 281 } 282 } 283 284 285 286 /** 287 * Delete entry number @p currline from @p disklist. 288 * @param disklist The disklist to remove the entry from. 289 * @param raid_device The RAID device containing the partition we're removing. 290 * Used only in the popup "are you sure?" box. 291 * @param currline The line number (starting from 0) of the item to delete. 292 * @ingroup restoreGuiDisklist 293 */ 294 void 295 delete_disklist_entry(struct list_of_disks *disklist, char *raid_device, 296 int currline) 297 { 298 299 /** int ***************************************************************/ 300 int pos = 0; 301 int res = 0; 302 303 /** buffers ***********************************************************/ 304 char *tmp = NULL; 305 306 assert(disklist != NULL); 307 assert_string_is_neither_NULL_nor_zerolength(raid_device); 308 309 mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device); 310 res = ask_me_yes_or_no(tmp); 311 mr_free(tmp); 312 313 if (!res) { 314 return; 315 } 316 for (pos = currline; pos < disklist->entries - 1; pos++) { 317 strcpy(disklist->el[pos].device, disklist->el[pos + 1].device); 318 } 319 disklist->entries--; 320 } 321 322 323 324 /** 325 * Select the RAID disks to use in @p raidrec. 326 * @param mountlist_dontedit The mountlist (will not be edited). 327 * @param raidlist The raidlist to modify. 328 * @param raidrec The RAID device record in @p raidlist to work on. 329 * @param description_of_list The type of disks we're selecting (e.g. "data"). 330 * @param disklist The disklist to put the user-selected disks in. 129 331 * @ingroup restoreGuiMountlist 130 332 */ 131 333 void 132 add_mountlist_entry(struct mountlist_itself *mountlist, 133 struct raidlist_itself *raidlist, 134 newtComponent listbox, int currline, void *keylist[]) 334 select_raid_disks(struct mountlist_itself *mountlist_dontedit, 335 struct raidlist_itself *raidlist, 336 struct raid_device_record *raidrec, 337 char *description_of_list, 338 struct list_of_disks *disklist) 339 { 340 void *curr_choice; 341 342 /** ??? ***************************************************************/ 343 344 /** structures ********************************************************/ 345 struct raidlist_itself *bkp_raidlist; 346 struct raid_device_record *bkp_raidrec; 347 struct list_of_disks *bkp_disklist; 348 struct mountlist_itself *unallocated_raid_partitions; 349 350 /** newt **************************************************************/ 351 newtComponent myForm = NULL; 352 newtComponent bAdd = NULL; 353 newtComponent bDelete = NULL; 354 newtComponent bOK = NULL; 355 newtComponent bCancel = NULL; 356 newtComponent b_res = NULL; 357 newtComponent partitionsListbox = NULL; 358 newtComponent headerMsg = NULL; 359 360 /** buffers **********************************************************/ 361 void *keylist[ARBITRARY_MAXIMUM]; 362 char *tmp = NULL; 363 char *help_text = NULL; 364 char *title_of_window = NULL; 365 char sz_res[MAX_STR_LEN]; 366 char *header_text = NULL; 367 368 /** int **************************************************************/ 369 int i = 0; 370 int currline = 0; 371 372 assert(mountlist_dontedit != NULL); 373 assert(raidlist != NULL); 374 assert(raidrec != NULL); 375 assert(description_of_list != NULL); 376 assert(disklist != NULL); 377 378 log_it("malloc'ing"); 379 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record)); 380 bkp_disklist = mr_malloc(sizeof(struct list_of_disks)); 381 bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself)); 382 unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself)); 383 384 memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself)); 385 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record)); 386 memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks)); 387 388 log_it("Post-malloc"); 389 mr_asprintf(help_text, " Edit this RAID device's list of partitions. Choose OK or Cancel when done."); 390 mr_asprintf(header_text, "%-24s %s", "Device", "Index"); 391 mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device); 392 newtPushHelpLine(help_text); 393 for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) { 394 headerMsg = newtLabel(1, 1, header_text); 395 partitionsListbox = 396 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 397 redraw_disklist(disklist, keylist, partitionsListbox); 398 i = 1; 399 bAdd = newtCompactButton(i, 9, " Add "); 400 bDelete = newtCompactButton(i += 8, 9, "Delete"); 401 bOK = newtCompactButton(i += 9, 9, " OK "); 402 bCancel = newtCompactButton(i += 9, 9, "Cancel"); 403 newtOpenWindow(21, 7, 38, 10, title_of_window); 404 myForm = newtForm(NULL, NULL, 0); 405 if (disklist->entries == 0) { 406 newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK, 407 bCancel, NULL); 408 } else { 409 newtFormAddComponents(myForm, headerMsg, partitionsListbox, 410 bAdd, bDelete, bOK, bCancel, NULL); 411 } 412 b_res = newtRunForm(myForm); 413 if (b_res == bOK || b_res == bCancel) { /* do nothing */ 414 // That's OK. At the end of this subroutine (after this do/while loop), 415 // we'll throw away the changes if Cancel was pushed. 416 } else { 417 curr_choice = newtListboxGetCurrent(partitionsListbox); 418 for (i = 0; i < disklist->entries && keylist[i] != curr_choice; 419 i++); 420 if (i == disklist->entries && disklist->entries > 0) { 421 log_to_screen("I don't know what that button does!"); 422 } else { 423 currline = i; 424 if (b_res == bAdd) { 425 log_it("Making list of unallocated RAID slices"); 426 make_list_of_unallocated_raid_partitions 427 (unallocated_raid_partitions, mountlist_dontedit, 428 raidlist); 429 if (unallocated_raid_partitions->entries <= 0) { 430 popup_and_OK 431 ("There are no unallocated partitions marked for RAID."); 432 } else { 433 log_it 434 ("Done. The user may add one or more of the above to RAID device"); 435 add_disklist_entry(disklist, raidrec->raid_device, 436 unallocated_raid_partitions); 437 log_it("I have finished adding a disklist entry."); 438 redraw_disklist(disklist, keylist, 439 partitionsListbox); 440 } 441 } else if (b_res == bDelete) { 442 delete_disklist_entry(disklist, raidrec->raid_device, 443 currline); 444 redraw_disklist(disklist, keylist, partitionsListbox); 445 } else { 446 mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index); 447 sprintf(sz_res, "%d", disklist->el[currline].index); 448 if (popup_and_get_string("Set index", tmp, sz_res, 10)) { 449 disklist->el[currline].index = atoi(sz_res); 450 } 451 mr_free(tmp); 452 453 redraw_disklist(disklist, keylist, partitionsListbox); 454 } 455 } 456 } 457 newtFormDestroy(myForm); 458 newtPopWindow(); 459 } 460 newtPopHelpLine(); 461 mr_free(help_text); 462 mr_free(header_text); 463 mr_free(title_of_window); 464 465 if (b_res == bCancel) { 466 memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself)); 467 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record)); 468 memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks)); 469 } 470 mr_free(bkp_raidrec); 471 mr_free(bkp_disklist); 472 mr_free(bkp_raidlist); 473 mr_free(unallocated_raid_partitions); 474 } 475 476 477 #ifndef __FreeBSD__ 478 /** 479 * Insert the RAID variables not stored in the "additional RAID variables" list there too. 480 * @param raidrec The RAID device record to operate on. 481 * @ingroup restoreGuiVarslist 482 */ 483 void insert_essential_additionalvars(struct raid_device_record *raidrec) 135 484 { 136 485 137 486 /** int **************************************************************/ 487 int items = 0; 488 489 assert(raidrec != NULL); 490 491 items = raidrec->additional_vars.entries; 492 write_variableINT_to_raid_var_line(raidrec, items++, 493 "persistent-superblock", 494 raidrec->persistent_superblock); 495 write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size", 496 raidrec->chunk_size); 497 raidrec->additional_vars.entries = items; 498 } 499 500 #endif 501 502 503 #ifndef __FreeBSD__ 504 /** 505 * Redraw the list of additional RAID variables. 506 * @param additional_vars The list of additional RAID varibals. 507 * @param keylist The list of keys for @p listbox. 508 * @param listbox The Newt listbox component to redraw. 509 * @ingroup restoreGuiVarslist 510 */ 511 void 512 redraw_varslist(struct additional_raid_variables *additional_vars, 513 void *keylist[], newtComponent listbox) 514 { 515 /** long ************************************************************/ 516 long i = 0; 517 518 /** buffers *********************************************************/ 519 char tmp[MAX_STR_LEN]; 520 521 assert(additional_vars != NULL); 522 assert(keylist != NULL); 523 assert(listbox != NULL); 524 525 newtListboxClear(listbox); 526 527 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 528 keylist[i] = (void *) i; 529 } 530 for (i = 0; i < additional_vars->entries; i++) { 531 sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label, 532 additional_vars->el[i].value); 533 newtListboxAppendEntry(listbox, tmp, keylist[i]); 534 } 535 } 536 537 #endif 538 539 540 #ifndef __FreeBSD__ 541 /** 542 * Remove variable @p label from the RAID variables list in @p raidrec. 543 * @param raidrec The RAID device record to remove the variable from. 544 * @param label The variable name to remove. 545 * @return The value of the variable removed. 546 * @ingroup restoreUtilityGroup 547 */ 548 int 549 read_variableINT_and_remove_from_raidvars(struct 550 OSSWAP (raid_device_record, 551 vinum_volume) * raidrec, 552 char *label) 553 { 554 /** int ***************************************************************/ 138 555 int i = 0; 139 140 /** newt *************************************************************/ 141 newtComponent myForm; 556 int res = 0; 557 558 559 assert(raidrec != NULL); 560 assert(label != NULL); 561 562 for (i = 0; 563 i < raidrec->additional_vars.entries 564 && strcmp(raidrec->additional_vars.el[i].label, label); i++); 565 if (i == raidrec->additional_vars.entries) { 566 res = -1; 567 } else { 568 res = atoi(raidrec->additional_vars.el[i].value); 569 for (i++; i < raidrec->additional_vars.entries; i++) { 570 memcpy((void *) &raidrec->additional_vars.el[i - 1], 571 (void *) &raidrec->additional_vars.el[i], 572 sizeof(struct raid_var_line)); 573 } 574 raidrec->additional_vars.entries--; 575 } 576 return (res); 577 } 578 #endif 579 580 #ifndef __FreeBSD__ 581 /** 582 * Remove the essential RAID variables from the "additional variables" section. 583 * If they have been changed, set them in their normal locations too. 584 * @param raidrec The RAID device record to operate on. 585 * @ingroup restoreUtilityVarslist 586 */ 587 void remove_essential_additionalvars(struct raid_device_record *raidrec) 588 { 589 590 /** int **************************************************************/ 591 int res = 0; 592 593 assert(raidrec != NULL); 594 595 res = 596 read_variableINT_and_remove_from_raidvars(raidrec, 597 "persistent-superblock"); 598 if (res > 0) { 599 raidrec->persistent_superblock = res; 600 } 601 res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size"); 602 if (res > 0) { 603 raidrec->chunk_size = res; 604 } 605 res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size"); 606 } 607 608 #endif 609 610 611 612 /** 613 * Choose the RAID level for the RAID device record in @p raidrec. 614 * @param raidrec The RAID device record to set the RAID level of. 615 * @ingroup restoreGuiMountlist 616 */ 617 void 618 choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec) 619 { 620 621 #ifdef __FreeBSD__ 622 623 /** int ***************************************************************/ 624 int res = 0; 625 int out = 0; 626 627 /** buffers ***********************************************************/ 628 char tmp[MAX_STR_LEN]; 629 char *prompt = NULL; 630 char sz[MAX_STR_LEN]; 631 632 mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)"); 633 if (raidrec->raidlevel == -1) { 634 strcpy(tmp, "concat"); 635 } else if (raidrec->raidlevel == 0) { 636 strcpy(tmp, "striped"); 637 } else { 638 sprintf(tmp, "raid%i", raidrec->raidlevel); 639 } 640 for (out = 999; out == 999;) { 641 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 642 if (!res) { 643 mr_free(prompt); 644 return; 645 } 646 strip_spaces(tmp); 647 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 648 strcpy(sz, tmp); 649 strncpy(tmp, sz + 1, strlen(sz) - 2); 650 tmp[strlen(sz) - 2] = '\0'; 651 } 652 if (!strcmp(tmp, "concat")) { 653 out = -1; 654 } else if (!strcmp(tmp, "striped")) { 655 out = 0; 656 } else if (!strcmp(tmp, "raid5")) { 657 out = 5; 658 } 659 log_it(tmp); 660 if (is_this_raid_personality_registered(out)) { 661 log_it("Groovy. You've picked a RAID personality which is registered."); 662 } else { 663 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) 664 { 665 out = 999; 666 } 667 } 668 } 669 mr_free(prompt); 670 671 raidrec->raidlevel = out; 672 #else 673 /** buffers ***********************************************************/ 674 char tmp[MAX_STR_LEN]; 675 char *personalities = NULL; 676 char *prompt = NULL; 677 char sz[MAX_STR_LEN]; 678 int out = 0; 679 int res = 0; 680 681 682 assert(raidrec != NULL); 683 paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null"); 684 mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt")); 685 mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities); 686 mr_free(personalities); 687 688 if (raidrec->raid_level == -1) { 689 strcpy(tmp, "linear"); 690 } else { 691 sprintf(tmp, "%d", raidrec->raid_level); 692 } 693 for (out = 999; 694 out != -1 && out != 0 && out != 1 && out != 4 && out != 5 695 && out != 10;) { 696 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 697 if (!res) { 698 return; 699 } 700 strip_spaces(tmp); 701 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 702 strcpy(sz, tmp); 703 strncpy(tmp, sz + 1, strlen(sz) - 2); 704 tmp[strlen(sz) - 2] = '\0'; 705 } 706 if (!strcmp(tmp, "linear")) { 707 out = -1; 708 } else if (!strncmp(tmp, "raid", 4)) { 709 out = atoi(tmp + 4); 710 } else { 711 out = atoi(tmp); 712 } 713 log_it(tmp); 714 if (is_this_raid_personality_registered(out)) { 715 log_it("Groovy. You've picked a RAID personality which is registered."); 716 } else { 717 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) { 718 out = 999; 719 } 720 } 721 } 722 mr_free(prompt); 723 724 raidrec->raid_level = out; 725 #endif 726 } 727 728 729 #ifdef __FreeBSD__ 730 731 /** 732 * Edit the plex @p raidrec in @p raidlist. 733 * @param mountlist The mountlist to get some of the information from. 734 * @param raidlist The raidlist containing information about RAID devices. 735 * @param raidrec The plex to edit. 736 * @param currline The line number (starting from 0) of the RAID device in @p mountlist. 737 * @param currline2 The line number (starting from 0) of the plex within the RAID device. 738 * @author Joshua Oreman 739 * @ingroup restoreGuiMountlist 740 */ 741 void 742 edit_raidlist_plex(struct mountlist_itself *mountlist, 743 struct raidlist_itself *raidlist, 744 struct vinum_plex *raidrec, int currline, int currline2) 745 { 746 747 /** structures ********************************************************/ 748 struct vinum_plex bkp_raidrec; 749 750 751 /** buffers ***********************************************************/ 752 char *title_of_editraidForm_window = NULL; 753 754 /** newt **************************************************************/ 755 newtComponent editraidForm; 142 756 newtComponent bOK; 143 757 newtComponent bCancel; 758 newtComponent bEdit; 759 newtComponent bAdd; 760 newtComponent bDelete; 144 761 newtComponent b_res; 145 newtComponent mountpointComp; 146 newtComponent label0; 147 newtComponent label1; 148 newtComponent label2; 149 newtComponent label3; 150 newtComponent sizeComp; 151 newtComponent deviceComp; 152 newtComponent formatComp; 153 154 /** buffers **********************************************************/ 155 char *drive_to_add = NULL; 156 char *mountpoint_str = NULL; 157 char *size_str = NULL; 158 char *device_str = NULL; 159 char *format_str = NULL; 160 161 /** pointers *********************************************************/ 162 char *mountpoint_here; 163 char *size_here; 164 char *device_here; 165 char *format_here; 166 167 assert(mountlist != NULL); 168 assert(raidlist != NULL); 169 assert(listbox != NULL); 170 assert(keylist != NULL); 171 172 mr_asprintf(device_str, "/dev/"); 173 mr_asprintf(mountpoint_str, "/"); 174 mr_asprintf(size_str, ""); 175 #ifdef __FreeBSD__ 176 mr_asprintf(format_str, "ufs"); 762 newtComponent unallocListbox, allocListbox; 763 newtComponent bLevel, sLevel; 764 newtComponent bStripeSize, sStripeSize; 765 newtComponent bAlloc, bUnalloc; 766 767 void *keylist[ARBITRARY_MAXIMUM]; 768 void *curr_choice_a, *curr_choice_u; 769 int currline_a, currline_u; 770 771 char *p = NULL; 772 char *tmp = NULL; 773 char *entry = NULL; 774 775 struct mountlist_itself *unallocparts; 776 777 unallocparts = malloc(sizeof(struct mountlist_itself)); 778 779 log_it("Started edit_raidlist_entry"); 780 memcpy((void *) &bkp_raidrec, (void *) raidrec, 781 sizeof(struct vinum_plex)); 782 mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2); 783 newtPushHelpLine 784 (" Please select a subdisk to edit, or edit this plex's parameters"); 785 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window); 786 mr_free(title_of_editraidForm_window); 787 788 for (;;) { 789 int i; 790 791 switch (raidrec->raidlevel) { 792 case -1: 793 mr_asprintf(tmp, "concat"); 794 break; 795 case 0: 796 mr_asprintf(tmp, "striped"); 797 break; 798 case 5: 799 mr_asprintf(tmp, "raid5"); 800 break; 801 default: 802 mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel); 803 break; 804 } 805 bLevel = newtCompactButton(2, 2, " RAID level "); 806 sLevel = newtLabel(19, 2, tmp); 807 mr_free(tmp); 808 809 if (raidrec->raidlevel >= 0) { 810 mr_asprintf(tmp, "%ik", raidrec->stripesize); 811 bStripeSize = newtCompactButton(2, 4, " Stripe size "); 812 } else { 813 mr_asprintf(tmp, "N/A"); 814 bStripeSize = newtLabel(2, 4, "Stripe size:"); 815 } 816 sStripeSize = newtLabel(19, 4, tmp); 817 mr_free(tmp); 818 819 bOK = newtCompactButton(2, 16, " OK "); 820 bCancel = newtCompactButton(12, 16, "Cancel"); 821 bAdd = newtCompactButton(22, 16, " Add "); 822 bEdit = newtCompactButton(32, 16, " Edit "); 823 bDelete = newtCompactButton(42, 16, "Delete"); 824 825 826 unallocListbox = 827 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 828 allocListbox = 829 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 830 bAlloc = newtButton(23, 7, " -> "); 831 bUnalloc = newtButton(23, 11, " <- "); 832 833 editraidForm = newtForm(NULL, NULL, 0); 834 835 newtListboxClear(allocListbox); 836 newtListboxClear(unallocListbox); 837 bzero(unallocparts, sizeof(struct mountlist_itself)); 838 make_list_of_unallocated_raid_partitions(unallocparts, mountlist, 839 raidlist); 840 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) { 841 keylist[i] = (void *) i; 842 if (i < raidrec->subdisks) { 843 mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device)); 844 newtListboxAppendEntry(allocListbox, entry, keylist[i]); 845 mr_free(entry); 846 } 847 if (i < unallocparts->entries) { 848 mr_asprintf(entry, "%-17s", unallocparts->el[i].device); 849 newtListboxAppendEntry(unallocListbox, entry, keylist[i]); 850 mr_free(entry); 851 } 852 } 853 854 #define COMP(x) newtFormAddComponent (editraidForm, x) 855 #define UCOMP(x) if (unallocparts->entries > 0) COMP(x) 856 #define ACOMP(x) if (raidrec->subdisks > 0) COMP(x) 857 editraidForm = newtForm(NULL, NULL, 0); 858 UCOMP(unallocListbox); 859 UCOMP(bAlloc); 860 ACOMP(allocListbox); 861 ACOMP(bUnalloc); 862 COMP(bOK); 863 COMP(bCancel); 864 COMP(bLevel); 865 COMP(sLevel); 866 if (raidrec->raidlevel != -1) { 867 COMP(bStripeSize); 868 COMP(sStripeSize); 869 } 870 #undef COMP 871 #undef UCOMP 872 #undef ACOMP 873 874 newtDrawForm(editraidForm); 875 newtRefresh(); 876 b_res = newtRunForm(editraidForm); 877 if (b_res == bOK || b_res == bCancel) { 878 break; 879 } 880 881 curr_choice_a = (raidrec->subdisks > 0) ? 882 newtListboxGetCurrent(allocListbox) : (void *) 1234; 883 curr_choice_u = (unallocparts->entries > 0) ? 884 newtListboxGetCurrent(unallocListbox) : (void *) 1234; 885 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) { 886 if (currline_a > ARBITRARY_MAXIMUM) 887 break; 888 if (keylist[currline_a] == curr_choice_a) 889 break; 890 } 891 for (currline_u = 0; currline_u < unallocparts->entries; 892 ++currline_u) { 893 if (currline_u > ARBITRARY_MAXIMUM) 894 break; 895 if (keylist[currline_u] == curr_choice_u) 896 break; 897 } 898 if (b_res == bLevel) { 899 choose_raid_level(raidrec); 900 } else if (b_res == bStripeSize) { 901 char tmp1[64]; 902 sprintf(tmp1, "%i", raidrec->stripesize); 903 if (popup_and_get_string 904 ("Stripe size", 905 "Please enter the stripe size in kilobytes.", tmp1, 20)) { 906 raidrec->stripesize = atoi(tmp1); 907 } 908 } else if ((b_res == bAlloc) || (b_res == unallocListbox)) { 909 if (currline_u <= unallocparts->entries) 910 add_raid_subdisk(raidlist, raidrec, 911 unallocparts->el[currline_u].device); 912 } else if ((b_res == bUnalloc) || (b_res == allocListbox)) { 913 if (currline_a <= raidrec->subdisks) { 914 memcpy((void *) &raidrec->sd[currline_a], 915 (void *) &raidrec->sd[raidrec->subdisks - 1], 916 sizeof(struct vinum_subdisk)); 917 raidrec->subdisks--; 918 } 919 } 920 newtFormDestroy(editraidForm); 921 newtRefresh(); 922 } 923 924 if (b_res == bCancel) { 925 memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex)); 926 } 927 newtPopWindow(); 928 newtPopHelpLine(); 929 } 177 930 #else 178 mr_asprintf(format_str, "ext3"); 931 /** 932 * Edit additional RAID variable number @p lino. 933 * @param raidrec The RAID device record to edit the variable in. 934 * @param lino The line number (starting from 0) of the variable to edit. 935 * @ingroup restoreGuiVarslist 936 */ 937 void edit_varslist_entry(struct raid_device_record *raidrec, int lino) 938 { 939 940 /** buffers ***********************************************************/ 941 char *header = NULL; 942 char *comment = NULL; 943 char sz_out[MAX_STR_LEN]; 944 945 assert(raidrec != 0); 946 assert(lino >= 0); 947 948 strcpy(sz_out, raidrec->additional_vars.el[lino].value); 949 mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label); 950 mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out); 951 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) { 952 strip_spaces(sz_out); 953 strcpy(raidrec->additional_vars.el[lino].value, sz_out); 954 } 955 mr_free(header); 956 mr_free(comment); 957 } 179 958 #endif 180 newtOpenWindow(20, 5, 48, 10, "Add entry");181 label0 = newtLabel(2, 1, "Device: ");182 label1 = newtLabel(2, 2, "Mountpoint:");183 label2 = newtLabel(2, 3, "Size (MB): ");184 label3 = newtLabel(2, 4, "Format: ");185 deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0);186 mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0);187 formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0);188 sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0);189 bOK = newtButton(5, 6, " OK ");190 bCancel = newtButton(17, 6, "Cancel");191 newtPushHelpLine192 ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'");193 myForm = newtForm(NULL, NULL, 0);194 newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp,195 formatComp, label0, label1, label2, label3, bOK,196 bCancel, NULL);197 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {198 b_res = newtRunForm(myForm);199 mr_free(device_str);200 device_str = mr_strip_spaces(device_here);201 202 mr_free(mountpoint_str);203 mountpoint_str = mr_strip_spaces(mountpoint_here);204 205 mr_free(format_str);206 format_str = mr_strip_spaces(format_here);207 208 mr_free(size_str);209 size_str = mr_strip_spaces(size_here);210 211 if (b_res == bOK) {212 if (device_str[strlen(device_str) - 1] == '/') {213 popup_and_OK("You left the device nearly blank!");214 b_res = NULL;215 }216 if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) {217 popup_and_OK("Can't add this - you've got one already!");218 b_res = NULL;219 }220 }221 }222 newtFormDestroy(myForm);223 newtPopHelpLine();224 newtPopWindow();225 if (b_res == bCancel) {226 return;227 }228 mr_asprintf(drive_to_add, "%s", device_str);229 for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--);230 mr_free(drive_to_add);231 232 currline = mountlist->entries;233 strcpy(mountlist->el[currline].device, device_str);234 strcpy(mountlist->el[currline].mountpoint, mountpoint_str);235 mr_free(mountpoint_str);236 237 strcpy(mountlist->el[currline].format, format_str);238 mr_free(format_str);239 240 mountlist->el[currline].size = atol(size_str) * 1024L;241 mr_free(size_str);242 243 mountlist->entries++;244 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {245 initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str);246 }247 mr_free(device_str);248 249 redraw_mountlist(mountlist, keylist, listbox);250 }251 959 252 960 … … 289 997 } 290 998 #endif 999 1000 1001 #ifndef __FreeBSD__ 1002 /** 1003 * Delete entry number @p lino in the additional RAID variables section of @p raidrec. 1004 * @param raidrec The RAID device record containing the RAID variable to delete. 1005 * @param lino The line number (starting from 0) of the variable to delete. 1006 * @ingroup restoreGuiVarslist 1007 */ 1008 void delete_varslist_entry(struct raid_device_record *raidrec, int lino) 1009 { 1010 1011 /** buffers ************************************************************/ 1012 char *tmp = NULL; 1013 int res = 0; 1014 1015 /** structures *********************************************************/ 1016 struct additional_raid_variables *av; 1017 1018 assert(raidrec != NULL); 1019 1020 av = &raidrec->additional_vars; 1021 mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label); 1022 res = ask_me_yes_or_no(tmp); 1023 mr_free(tmp); 1024 1025 if (res) { 1026 if (!strcmp(av->el[lino].label, "persistent-superblock") 1027 || !strcmp(av->el[lino].label, "chunk-size")) { 1028 mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label); 1029 popup_and_OK(tmp); 1030 mr_free(tmp); 1031 } else { 1032 memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--], 1033 sizeof(struct raid_var_line)); 1034 } 1035 } 1036 } 1037 #endif 1038 1039 1040 1041 #ifndef __FreeBSD__ 1042 /** 1043 * Edit the additional RAID variables in @p raidrec. 1044 * @param raidrec The RAID device record to edit the RAID variables in. 1045 * @ingroup restoreGuiVarslist 1046 */ 1047 void edit_raidrec_additional_vars(struct raid_device_record *raidrec) 1048 { 1049 1050 /** structure *********************************************************/ 1051 struct raid_device_record bkp_raidrec; 1052 1053 /** newt **************************************************************/ 1054 newtComponent myForm; 1055 newtComponent bAdd; 1056 newtComponent bEdit; 1057 newtComponent bDelete; 1058 newtComponent bOK; 1059 newtComponent bCancel; 1060 newtComponent b_res; 1061 newtComponent varsListbox; 1062 newtComponent headerMsg; 1063 1064 /** ?? ***************************************************************/ 1065 void *keylist[ARBITRARY_MAXIMUM], *curr_choice; 1066 1067 /** buffers **********************************************************/ 1068 char title_of_window[MAX_STR_LEN]; 1069 1070 /** int **************************************************************/ 1071 int i = 0; 1072 int currline = 0; 1073 1074 1075 assert(raidrec != NULL); 1076 1077 memcpy((void *) &bkp_raidrec, (void *) raidrec, 1078 sizeof(struct raid_device_record)); 1079 sprintf(title_of_window, "Additional variables"); 1080 newtPushHelpLine 1081 (" Edit the additional fields to your heart's content, then click OK or Cancel."); 1082 headerMsg = newtLabel(1, 1, "Label Value"); 1083 varsListbox = 1084 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 1085 i = 1; 1086 bAdd = newtCompactButton(i, 9, " Add "); 1087 bEdit = newtCompactButton(i += 8, 9, " Edit "); 1088 bDelete = newtCompactButton(i += 9, 9, "Delete"); 1089 bOK = newtCompactButton(i += 9, 9, " OK "); 1090 bCancel = newtCompactButton(i += 9, 9, "Cancel"); 1091 newtOpenWindow(17, 7, 46, 10, title_of_window); 1092 myForm = newtForm(NULL, NULL, 0); 1093 newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit, 1094 bDelete, bOK, bCancel, NULL); 1095 insert_essential_additionalvars(raidrec); 1096 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox); 1097 for (b_res = NULL; b_res != bOK && b_res != bCancel;) { 1098 b_res = newtRunForm(myForm); 1099 curr_choice = newtListboxGetCurrent(varsListbox); 1100 for (currline = 0; 1101 currline < raidrec->additional_vars.entries 1102 && keylist[currline] != curr_choice; currline++); 1103 if (currline == raidrec->additional_vars.entries 1104 && raidrec->additional_vars.entries > 0) { 1105 log_it("Warning - I don't know what this button does"); 1106 } 1107 if (b_res == bOK) { /* do nothing */ 1108 } else if (b_res == bCancel) { /* do nothing */ 1109 } else if (b_res == bAdd) { 1110 add_varslist_entry(raidrec); 1111 } else if (b_res == bDelete) { 1112 delete_varslist_entry(raidrec, currline); 1113 } else { 1114 edit_varslist_entry(raidrec, currline); 1115 } 1116 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox); 1117 } 1118 remove_essential_additionalvars(raidrec); 1119 newtFormDestroy(myForm); 1120 newtPopWindow(); 1121 newtPopHelpLine(); 1122 if (b_res == bCancel) { 1123 memcpy((void *) raidrec, (void *) &bkp_raidrec, 1124 sizeof(struct raid_device_record)); 1125 } 1126 return; 1127 } 1128 #endif 1129 291 1130 292 1131 /** … … 445 1284 446 1285 /** 447 * Choose the RAID level for the RAID device record in @p raidrec. 448 * @param raidrec The RAID device record to set the RAID level of. 1286 * Edit the entry for @p raidrec in @p raidlist. 1287 * @param mountlist The mountlist to get some information from. 1288 * @param raidlist The raidlist containing information about RAID devices. 1289 * @param raidrec The RAID device record for this partition. 1290 * @param currline The line number (starting from 0) in the mountlist of the RAID device. 449 1291 * @ingroup restoreGuiMountlist 450 1292 */ 1293 void edit_raidlist_entry(struct mountlist_itself *mountlist, 1294 struct raidlist_itself *raidlist, 1295 struct OSSWAP (raid_device_record, 1296 vinum_volume) * raidrec, int currline) 1297 { 1298 1299 #ifdef __FreeBSD__ 1300 /** structures ********************************************************/ 1301 struct vinum_volume bkp_raidrec; 1302 1303 1304 /** buffers ***********************************************************/ 1305 char title_of_editraidForm_window[MAX_STR_LEN]; 1306 1307 /** newt **************************************************************/ 1308 newtComponent editraidForm; 1309 newtComponent bOK; 1310 newtComponent bCancel; 1311 newtComponent bEdit; 1312 newtComponent bAdd; 1313 newtComponent bDelete; 1314 newtComponent b_res; 1315 newtComponent plexesListbox; 1316 newtComponent plexesHeader; 1317 1318 void *keylist[10]; 1319 void *curr_choice; 1320 char *raidlevel = NULL; 1321 char *chunksize = NULL; 1322 char *msg = NULL; 1323 1324 int currline2 = 0; 1325 int res = 0; 1326 1327 log_it("Started edit_raidlist_entry"); 1328 memcpy((void *) &bkp_raidrec, (void *) raidrec, 1329 sizeof(struct vinum_volume)); 1330 sprintf(title_of_editraidForm_window, "Plexes on %s", 1331 raidrec->volname); 1332 newtPushHelpLine(" Please select a plex to edit"); 1333 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window); 1334 for (;;) { 1335 int i; 1336 char *headerstr = NULL; 1337 mr_asprintf(headerstr, "%-14s %-8s %11s %8s", "Plex", "Level", "Stripe Size", "Subdisks"); 1338 1339 bOK = newtCompactButton(2, 13, " OK "); 1340 bCancel = newtCompactButton(12, 13, "Cancel"); 1341 bAdd = newtCompactButton(22, 13, " Add "); 1342 bEdit = newtCompactButton(32, 13, " Edit "); 1343 bDelete = newtCompactButton(42, 13, "Delete"); 1344 1345 plexesListbox = 1346 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); 1347 plexesHeader = newtLabel(2, 2, headerstr); 1348 mr_free(headerstr); 1349 editraidForm = newtForm(NULL, NULL, 0); 1350 1351 newtListboxClear(plexesListbox); 1352 for (i = 0; i < 10; ++i) { 1353 keylist[i] = (void *) i; 1354 if (i < raidrec->plexes) { 1355 char *pname; 1356 char *entry; 1357 switch (raidrec->plex[i].raidlevel) { 1358 case -1: 1359 mr_asprintf(raidlevel, "concat"); 1360 break; 1361 case 0: 1362 mr_asprintf(raidlevel, "striped"); 1363 break; 1364 case 5: 1365 mr_asprintf(raidlevel, "raid5"); 1366 break; 1367 default: 1368 mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel); 1369 break; 1370 } 1371 1372 if (raidrec->plex[i].raidlevel == -1) { 1373 mr_asprintf(chunksize, "N/A"); 1374 } else { 1375 mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize); 1376 } 1377 mr_asprintf(pname, "%s.p%i", raidrec->volname, i); 1378 mr_asprintf(entry, "%-14s %-8s %11s %8d", pname, raidlevel, chunksize, raidrec->plex[i].subdisks); 1379 mr_free(pname); 1380 mr_free(raidlevel); 1381 mr_free(chunksize); 1382 1383 newtListboxAppendEntry(plexesListbox, entry, keylist[i]); 1384 mr_free(entry); 1385 } 1386 } 1387 1388 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit, 1389 bDelete, plexesListbox, plexesHeader, NULL); 1390 1391 b_res = newtRunForm(editraidForm); 1392 if (b_res == bOK || b_res == bCancel) { 1393 break; 1394 } 1395 1396 curr_choice = newtListboxGetCurrent(plexesListbox); 1397 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) { 1398 if (currline2 > 9) 1399 break; 1400 if (keylist[currline2] == curr_choice) 1401 break; 1402 } 1403 1404 if (b_res == bDelete) { 1405 mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2); 1406 res = ask_me_yes_or_no(msg); 1407 mr_free(msg); 1408 1409 if (res) { 1410 log_it("Deleting RAID plex"); 1411 memcpy((void *) &raidrec->plex[currline2], 1412 (void *) &raidrec->plex[raidrec->plexes - 1], 1413 sizeof(struct vinum_plex)); 1414 raidrec->plexes--; 1415 } 1416 continue; 1417 } 1418 if (b_res == bAdd) { 1419 raidrec->plex[raidrec->plexes].raidlevel = 0; 1420 raidrec->plex[raidrec->plexes].stripesize = 279; 1421 raidrec->plex[raidrec->plexes].subdisks = 0; 1422 currline2 = raidrec->plexes++; 1423 } 1424 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2], 1425 currline, currline2); 1426 newtFormDestroy(editraidForm); 1427 } 1428 if (b_res == bCancel) { 1429 memcpy((void *) raidrec, (void *) &bkp_raidrec, 1430 sizeof(struct vinum_volume)); 1431 } 1432 newtPopHelpLine(); 1433 newtPopWindow(); 1434 mountlist->el[currline].size = 1435 calculate_raid_device_size(mountlist, raidlist, raidrec->volname); 1436 #else 1437 /** structures ********************************************************/ 1438 struct raid_device_record *bkp_raidrec; 1439 1440 1441 /** buffers ***********************************************************/ 1442 char *title_of_editraidForm_window; 1443 char *sz_raid_level = NULL; 1444 char *sz_data_disks = NULL; 1445 char *sz_spare_disks = NULL; 1446 char *sz_parity_disks = NULL; 1447 char *sz_failed_disks = NULL; 1448 1449 /** newt **************************************************************/ 1450 newtComponent editraidForm; 1451 newtComponent bOK; 1452 newtComponent bCancel; 1453 newtComponent bAdditional; 1454 newtComponent bChangeRaid; 1455 newtComponent bSelectData; 1456 newtComponent bSelectSpare; 1457 newtComponent bSelectParity; 1458 newtComponent bSelectFailed; 1459 newtComponent b_res; 1460 1461 assert(mountlist != NULL); 1462 assert(raidlist != NULL); 1463 assert(raidrec != NULL); 1464 1465 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record)); 1466 log_it("Started edit_raidlist_entry"); 1467 1468 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record)); 1469 mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device); 1470 log_msg(2, "Opening newt window"); 1471 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window); 1472 for (;;) { 1473 log_msg(2, "Main loop"); 1474 mr_free(title_of_editraidForm_window); 1475 mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device); 1476 sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level); 1477 sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data"); 1478 sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare"); 1479 sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity"); 1480 sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed"); 1481 bSelectData = newtButton(1, 1, sz_data_disks); 1482 bSelectSpare = newtButton(20, 1, sz_spare_disks); 1483 bSelectParity = newtButton(1, 5, sz_parity_disks); 1484 bSelectFailed = newtButton(20, 5, sz_failed_disks); 1485 bChangeRaid = newtButton(1, 9, sz_raid_level); 1486 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, " OK "); 1487 bCancel = newtButton(28, 9, "Cancel"); 1488 bAdditional = 1489 newtCompactButton(1, 13, 1490 "Additional settings and information"); 1491 newtPushHelpLine 1492 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel."); 1493 editraidForm = newtForm(NULL, NULL, 0); 1494 newtFormAddComponents(editraidForm, bSelectData, bSelectParity, 1495 bChangeRaid, bSelectSpare, bSelectFailed, 1496 bOK, bCancel, bAdditional); 1497 b_res = newtRunForm(editraidForm); 1498 if (b_res == bChangeRaid) { 1499 choose_raid_level(raidrec); 1500 } else if (b_res == bSelectData) { 1501 select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks); 1502 } else if (b_res == bSelectSpare) { 1503 select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks); 1504 } else if (b_res == bSelectParity) { 1505 select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks); 1506 } else if (b_res == bSelectFailed) { 1507 select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks); 1508 } else if (b_res == bAdditional) { 1509 edit_raidrec_additional_vars(raidrec); 1510 } 1511 newtFormDestroy(editraidForm); 1512 if (b_res == bOK || b_res == bCancel) { 1513 break; 1514 } 1515 mr_free(sz_data_disks); 1516 mr_free(sz_spare_disks); 1517 mr_free(sz_parity_disks); 1518 mr_free(sz_failed_disks); 1519 } 1520 if (b_res == bCancel) { 1521 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record)); 1522 } 1523 newtPopHelpLine(); 1524 newtPopWindow(); 1525 mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device); 1526 mr_free(title_of_editraidForm_window); 1527 mr_free(sz_raid_level); 1528 paranoid_free(bkp_raidrec); 1529 #endif 1530 } 1531 1532 1533 /** 1534 * Create a new raidtab entry for @p device in @p raidlist. 1535 * @param raidlist The raidlist to add the device to. 1536 * @param mountlist The mountlist containing information about the user's partitions. 1537 * @param currline The selected line in the mountlist. 1538 * @param device The RAID device (e.g. /dev/md0) to use. 1539 * @ingroup restoreGuiMountlist 1540 */ 451 1541 void 452 choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec) 453 { 454 1542 initiate_new_raidlist_entry(struct raidlist_itself *raidlist, 1543 struct mountlist_itself *mountlist, 1544 int currline, char *device) 1545 { 1546 1547 /** structure *********************************************************/ 1548 struct OSSWAP (raid_device_record, vinum_volume) * raidrec; 1549 1550 /** int ***************************************************************/ 1551 int pos_in_raidlist = 0; 1552 1553 assert(raidlist != NULL); 1554 assert(mountlist != NULL); 1555 assert_string_is_neither_NULL_nor_zerolength(device); 1556 1557 pos_in_raidlist = 1558 find_raid_device_in_raidlist(raidlist, 1559 mountlist->el[currline].device); 1560 if (pos_in_raidlist >= 0) { 1561 fatal_error("Sorry, that RAID device already exists. Weird."); 1562 } 1563 pos_in_raidlist = raidlist->entries++; 1564 raidrec = &raidlist->el[pos_in_raidlist]; 1565 initialize_raidrec(raidrec); 1566 strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device))); 1567 #ifndef __FreeBSD__ 1568 choose_raid_level(raidrec); 1569 select_raid_disks(mountlist, raidlist, raidrec, "data", 1570 &raidrec->data_disks); 1571 #endif 1572 edit_raidlist_entry(mountlist, raidlist, raidrec, currline); 1573 } 1574 1575 1576 /** 1577 * Redraw the mountlist. 1578 * @param mountlist The mountlist to read from. 1579 * @param keylist The list of keys for @p listbox. 1580 * @param listbox The Newt listbox component to redraw. 1581 * @ingroup restoreGuiMountlist 1582 */ 1583 void 1584 redraw_mountlist(struct mountlist_itself *mountlist, 1585 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox) 1586 { 1587 1588 /** long **************************************************************/ 1589 long i = 0; 1590 char * tmp = NULL; 1591 1592 assert(mountlist != NULL); 1593 assert(keylist != NULL); 1594 assert(listbox != NULL); 1595 1596 newtListboxClear(listbox); 1597 // sort_mountlist_by_device (mountlist); 1598 for (i = 0; i < ARBITRARY_MAXIMUM; i++) { 1599 keylist[i] = (void *) i; 1600 } 1601 for (i = 0; i < mountlist->entries; i++) { 1602 tmp = mountlist_entry_to_string(mountlist, i); 1603 newtListboxAppendEntry(listbox, tmp, keylist[i]); 1604 mr_free(tmp); 1605 } 1606 } 1607 1608 1609 1610 1611 /** 1612 * Add an entry to @p mountlist. 1613 * @param mountlist The mountlist to add an entry to. 1614 * @param raidlist The raidlist that accompanies @p mountlist. 1615 * @param listbox The listbox component in the mountlist editor. 1616 * @param currline The line selected in @p listbox. 1617 * @param keylist The list of keys for @p listbox. 1618 * @ingroup restoreGuiMountlist 1619 */ 1620 void 1621 add_mountlist_entry(struct mountlist_itself *mountlist, 1622 struct raidlist_itself *raidlist, 1623 newtComponent listbox, int currline, void *keylist[]) 1624 { 1625 1626 /** int **************************************************************/ 1627 int i = 0; 1628 1629 /** newt *************************************************************/ 1630 newtComponent myForm; 1631 newtComponent bOK; 1632 newtComponent bCancel; 1633 newtComponent b_res; 1634 newtComponent mountpointComp; 1635 newtComponent label0; 1636 newtComponent label1; 1637 newtComponent label2; 1638 newtComponent label3; 1639 newtComponent sizeComp; 1640 newtComponent deviceComp; 1641 newtComponent formatComp; 1642 1643 /** buffers **********************************************************/ 1644 char *drive_to_add = NULL; 1645 char *mountpoint_str = NULL; 1646 char *size_str = NULL; 1647 char *device_str = NULL; 1648 char *format_str = NULL; 1649 1650 /** pointers *********************************************************/ 1651 char *mountpoint_here; 1652 char *size_here; 1653 char *device_here; 1654 char *format_here; 1655 1656 assert(mountlist != NULL); 1657 assert(raidlist != NULL); 1658 assert(listbox != NULL); 1659 assert(keylist != NULL); 1660 1661 mr_asprintf(device_str, "/dev/"); 1662 mr_asprintf(mountpoint_str, "/"); 1663 mr_asprintf(size_str, ""); 455 1664 #ifdef __FreeBSD__ 456 457 /** int ***************************************************************/ 458 int res = 0; 459 int out = 0; 460 461 /** buffers ***********************************************************/ 462 char tmp[MAX_STR_LEN]; 463 char *prompt = NULL; 464 char sz[MAX_STR_LEN]; 465 466 mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)"); 467 if (raidrec->raidlevel == -1) { 468 strcpy(tmp, "concat"); 469 } else if (raidrec->raidlevel == 0) { 470 strcpy(tmp, "striped"); 471 } else { 472 sprintf(tmp, "raid%i", raidrec->raidlevel); 473 } 474 for (out = 999; out == 999;) { 475 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 476 if (!res) { 477 mr_free(prompt); 478 return; 479 } 480 strip_spaces(tmp); 481 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 482 strcpy(sz, tmp); 483 strncpy(tmp, sz + 1, strlen(sz) - 2); 484 tmp[strlen(sz) - 2] = '\0'; 485 } 486 if (!strcmp(tmp, "concat")) { 487 out = -1; 488 } else if (!strcmp(tmp, "striped")) { 489 out = 0; 490 } else if (!strcmp(tmp, "raid5")) { 491 out = 5; 492 } 493 log_it(tmp); 494 if (is_this_raid_personality_registered(out)) { 495 log_it("Groovy. You've picked a RAID personality which is registered."); 496 } else { 497 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) 498 { 499 out = 999; 1665 mr_asprintf(format_str, "ufs"); 1666 #else 1667 mr_asprintf(format_str, "ext3"); 1668 #endif 1669 newtOpenWindow(20, 5, 48, 10, "Add entry"); 1670 label0 = newtLabel(2, 1, "Device: "); 1671 label1 = newtLabel(2, 2, "Mountpoint:"); 1672 label2 = newtLabel(2, 3, "Size (MB): "); 1673 label3 = newtLabel(2, 4, "Format: "); 1674 deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0); 1675 mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0); 1676 formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0); 1677 sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0); 1678 bOK = newtButton(5, 6, " OK "); 1679 bCancel = newtButton(17, 6, "Cancel"); 1680 newtPushHelpLine 1681 ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'"); 1682 myForm = newtForm(NULL, NULL, 0); 1683 newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp, 1684 formatComp, label0, label1, label2, label3, bOK, 1685 bCancel, NULL); 1686 for (b_res = NULL; b_res != bOK && b_res != bCancel;) { 1687 b_res = newtRunForm(myForm); 1688 mr_free(device_str); 1689 device_str = mr_strip_spaces(device_here); 1690 1691 mr_free(mountpoint_str); 1692 mountpoint_str = mr_strip_spaces(mountpoint_here); 1693 1694 mr_free(format_str); 1695 format_str = mr_strip_spaces(format_here); 1696 1697 mr_free(size_str); 1698 size_str = mr_strip_spaces(size_here); 1699 1700 if (b_res == bOK) { 1701 if (device_str[strlen(device_str) - 1] == '/') { 1702 popup_and_OK("You left the device nearly blank!"); 1703 b_res = NULL; 500 1704 } 501 } 502 } 503 mr_free(prompt); 504 505 raidrec->raidlevel = out; 506 #else 507 /** buffers ***********************************************************/ 508 char tmp[MAX_STR_LEN]; 509 char *personalities = NULL; 510 char *prompt = NULL; 511 char sz[MAX_STR_LEN]; 512 int out = 0; 513 int res = 0; 514 515 516 assert(raidrec != NULL); 517 paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null"); 518 mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt")); 519 mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities); 520 mr_free(personalities); 521 522 if (raidrec->raid_level == -1) { 523 strcpy(tmp, "linear"); 524 } else { 525 sprintf(tmp, "%d", raidrec->raid_level); 526 } 527 for (out = 999; 528 out != -1 && out != 0 && out != 1 && out != 4 && out != 5 529 && out != 10;) { 530 res = popup_and_get_string("Specify RAID level", prompt, tmp, 10); 531 if (!res) { 532 return; 533 } 534 strip_spaces(tmp); 535 if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') { 536 strcpy(sz, tmp); 537 strncpy(tmp, sz + 1, strlen(sz) - 2); 538 tmp[strlen(sz) - 2] = '\0'; 539 } 540 if (!strcmp(tmp, "linear")) { 541 out = -1; 542 } else if (!strncmp(tmp, "raid", 4)) { 543 out = atoi(tmp + 4); 544 } else { 545 out = atoi(tmp); 546 } 547 log_it(tmp); 548 if (is_this_raid_personality_registered(out)) { 549 log_it("Groovy. You've picked a RAID personality which is registered."); 550 } else { 551 if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) { 552 out = 999; 1705 if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) { 1706 popup_and_OK("Can't add this - you've got one already!"); 1707 b_res = NULL; 553 1708 } 554 1709 } 555 1710 } 556 mr_free(prompt); 557 558 raidrec->raid_level = out; 559 #endif 1711 newtFormDestroy(myForm); 1712 newtPopHelpLine(); 1713 newtPopWindow(); 1714 if (b_res == bCancel) { 1715 return; 1716 } 1717 mr_asprintf(drive_to_add, "%s", device_str); 1718 for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--); 1719 mr_free(drive_to_add); 1720 1721 currline = mountlist->entries; 1722 strcpy(mountlist->el[currline].device, device_str); 1723 strcpy(mountlist->el[currline].mountpoint, mountpoint_str); 1724 mr_free(mountpoint_str); 1725 1726 strcpy(mountlist->el[currline].format, format_str); 1727 mr_free(format_str); 1728 1729 mountlist->el[currline].size = atol(size_str) * 1024L; 1730 mr_free(size_str); 1731 1732 mountlist->entries++; 1733 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) { 1734 initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str); 1735 } 1736 mr_free(device_str); 1737 1738 redraw_mountlist(mountlist, keylist, listbox); 560 1739 } 561 1740 … … 601 1780 602 1781 603 604 /**605 * Delete entry number @p currline from @p disklist.606 * @param disklist The disklist to remove the entry from.607 * @param raid_device The RAID device containing the partition we're removing.608 * Used only in the popup "are you sure?" box.609 * @param currline The line number (starting from 0) of the item to delete.610 * @ingroup restoreGuiDisklist611 */612 void613 delete_disklist_entry(struct list_of_disks *disklist, char *raid_device,614 int currline)615 {616 617 /** int ***************************************************************/618 int pos = 0;619 int res = 0;620 621 /** buffers ***********************************************************/622 char *tmp = NULL;623 624 assert(disklist != NULL);625 assert_string_is_neither_NULL_nor_zerolength(raid_device);626 627 mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device);628 res = ask_me_yes_or_no(tmp);629 mr_free(tmp);630 631 if (!res) {632 return;633 }634 for (pos = currline; pos < disklist->entries - 1; pos++) {635 strcpy(disklist->el[pos].device, disklist->el[pos + 1].device);636 }637 disklist->entries--;638 }639 640 641 642 /**643 * Delete entry number @p currline from @p mountlist.644 * @param mountlist The mountlist to delete the entry from.645 * @param raidlist The raidlist that goes with @p mountlist.646 * @param listbox The Newt listbox component in the mountlist editor.647 * @param currline The line number (starting from 0) of the item to delete.648 * @param keylist The list of keys for @p listbox.649 * @ingroup restoreGuiMountlist650 */651 void652 delete_mountlist_entry(struct mountlist_itself *mountlist,653 struct raidlist_itself *raidlist,654 newtComponent listbox, int currline,655 void *keylist[])656 {657 658 /** int ***************************************************************/659 int pos = 0;660 int res = 0;661 662 /** buffers ***********************************************************/663 char *tmp = NULL;664 char *device = NULL;665 666 667 assert(mountlist != NULL);668 assert(raidlist != NULL);669 assert(listbox != NULL);670 assert(keylist != NULL);671 672 pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device);673 if (pos >= 0) {674 mr_asprintf(tmp, "Cannot delete %s: it is in use by RAID device %s", mountlist->el[currline].device, raidlist->el[pos].OSSWAP(raid_device, volname));675 popup_and_OK(tmp);676 mr_free(tmp);677 return;678 }679 mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device);680 res = ask_me_yes_or_no(tmp);681 mr_free(tmp);682 683 if (!res) {684 return;685 }686 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {687 mr_asprintf(device, "%s", mountlist->el[currline].device);688 delete_raidlist_entry(mountlist, raidlist, device);689 for (currline = 0;690 currline < mountlist->entries691 && strcmp(mountlist->el[currline].device, device);692 currline++);693 mr_free(device);694 695 if (currline == mountlist->entries) {696 log_it("Dev is gone. I can't delete it. Ho-hum");697 return;698 }699 }700 memcpy((void *) &mountlist->el[currline],701 (void *) &mountlist->el[mountlist->entries - 1],702 sizeof(struct mountlist_line));703 mountlist->entries--;704 redraw_mountlist(mountlist, keylist, listbox);705 }706 707 708 1782 /** 709 1783 * Delete @p device from @p raidlist. … … 713 1787 * @ingroup restoreGuiMountlist 714 1788 */ 715 void 716 delete_raidlist_entry(struct mountlist_itself *mountlist, 1789 void delete_raidlist_entry(struct mountlist_itself *mountlist, 717 1790 struct raidlist_itself *raidlist, char *device) 718 1791 { … … 783 1856 784 1857 785 #ifndef __FreeBSD__ 786 /** 787 * Delete entry number @p lino in the additional RAID variables section of @p raidrec. 788 * @param raidrec The RAID device record containing the RAID variable to delete. 789 * @param lino The line number (starting from 0) of the variable to delete. 790 * @ingroup restoreGuiVarslist 791 */ 792 void delete_varslist_entry(struct raid_device_record *raidrec, int lino) 793 { 794 795 /** buffers ************************************************************/ 1858 1859 /** 1860 * Delete entry number @p currline from @p mountlist. 1861 * @param mountlist The mountlist to delete the entry from. 1862 * @param raidlist The raidlist that goes with @p mountlist. 1863 * @param listbox The Newt listbox component in the mountlist editor. 1864 * @param currline The line number (starting from 0) of the item to delete. 1865 * @param keylist The list of keys for @p listbox. 1866 * @ingroup restoreGuiMountlist 1867 */ 1868 void 1869 delete_mountlist_entry(struct mountlist_itself *mountlist, 1870 struct raidlist_itself *raidlist, 1871 newtComponent listbox, int currline, 1872 void *keylist[]) 1873 { 1874 1875 /** int ***************************************************************/ 1876 int pos = 0; 1877 int res = 0; 1878 1879 /** buffers ***********************************************************/ 796 1880 char *tmp = NULL; 797 int res = 0; 798 799 /** structures *********************************************************/ 800 struct additional_raid_variables *av; 801 802 assert(raidrec != NULL); 803 804 av = &raidrec->additional_vars; 805 mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label); 1881 char *device = NULL; 1882 1883 1884 assert(mountlist != NULL); 1885 assert(raidlist != NULL); 1886 assert(listbox != NULL); 1887 assert(keylist != NULL); 1888 1889 pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device); 1890 if (pos >= 0) { 1891 mr_asprintf(tmp, "Cannot delete %s: it is in use by RAID device %s", mountlist->el[currline].device, raidlist->el[pos].OSSWAP(raid_device, volname)); 1892 popup_and_OK(tmp); 1893 mr_free(tmp); 1894 return; 1895 } 1896 mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device); 806 1897 res = ask_me_yes_or_no(tmp); 807 1898 mr_free(tmp); 808 1899 809 if (res) { 810 if (!strcmp(av->el[lino].label, "persistent-superblock") 811 || !strcmp(av->el[lino].label, "chunk-size")) { 812 mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label); 813 popup_and_OK(tmp); 814 mr_free(tmp); 1900 if (!res) { 1901 return; 1902 } 1903 if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) { 1904 mr_asprintf(device, "%s", mountlist->el[currline].device); 1905 delete_raidlist_entry(mountlist, raidlist, device); 1906 for (currline = 0; 1907 currline < mountlist->entries 1908 && strcmp(mountlist->el[currline].device, device); 1909 currline++); 1910 mr_free(device); 1911 1912 if (currline == mountlist->entries) { 1913 log_it("Dev is gone. I can't delete it. Ho-hum"); 1914 return; 1915 } 1916 } 1917 memcpy((void *) &mountlist->el[currline], 1918 (void *) &mountlist->el[mountlist->entries - 1], 1919 sizeof(struct mountlist_line)); 1920 mountlist->entries--; 1921 redraw_mountlist(mountlist, keylist, listbox); 1922 } 1923 1924 1925 /** 1926 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename). 1927 * @param tmp The path to strip. 1928 * @return The stripped path. 1929 * @author Conor Daly 1930 * @ingroup restoreUtilityGroup 1931 */ 1932 char *strip_path(char *tmp) 1933 { 1934 1935 int i = 0, j = 0, slashcount = 0; 1936 int slashloc = 0, lastslashloc = 0; 1937 1938 while (tmp[i] != '\0') { /* Count the slashes in tmp 1939 1 slash per dir */ 1940 if (tmp[i] == '/') { 1941 slashcount++; 1942 lastslashloc = slashloc; 1943 slashloc = i; 1944 if (tmp[i + 1] == '\0') { /* if this slash is last char, back off */ 1945 slashcount--; 1946 slashloc = lastslashloc; 1947 } 1948 } 1949 i++; 1950 } 1951 if (slashcount > 0) 1952 slashcount--; /* Keep one slash 'cos Hugh does... */ 1953 1954 for (i = 0; i < slashcount; i++) { /* Replace each dir with a space char */ 1955 tmpnopath[i] = ' '; 1956 } 1957 1958 i = slashloc; 1959 j = slashcount; 1960 while (tmp[i] != '\0') { /* Now add what's left of tmp */ 1961 if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^') 1962 && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) { /* Add a pointer upwards if this is not in the same dir as line above */ 1963 tmpnopath[j - 1] = '^'; 815 1964 } else { 816 memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--], 817 sizeof(struct raid_var_line)); 818 } 819 } 820 } 821 #endif 1965 tmpnopath[j++] = tmp[i++]; 1966 } 1967 } 1968 tmpnopath[j] = '\0'; 1969 1970 strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */ 1971 1972 return (tmpnopath); 1973 } 1974 822 1975 823 1976 … … 924 2077 return (0); 925 2078 } 926 }927 928 929 /**930 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename).931 * @param tmp The path to strip.932 * @return The stripped path.933 * @author Conor Daly934 * @ingroup restoreUtilityGroup935 */936 char *strip_path(char *tmp)937 {938 939 int i = 0, j = 0, slashcount = 0;940 int slashloc = 0, lastslashloc = 0;941 942 while (tmp[i] != '\0') { /* Count the slashes in tmp943 1 slash per dir */944 if (tmp[i] == '/') {945 slashcount++;946 lastslashloc = slashloc;947 slashloc = i;948 if (tmp[i + 1] == '\0') { /* if this slash is last char, back off */949 slashcount--;950 slashloc = lastslashloc;951 }952 }953 i++;954 }955 if (slashcount > 0)956 slashcount--; /* Keep one slash 'cos Hugh does... */957 958 for (i = 0; i < slashcount; i++) { /* Replace each dir with a space char */959 tmpnopath[i] = ' ';960 }961 962 i = slashloc;963 j = slashcount;964 while (tmp[i] != '\0') { /* Now add what's left of tmp */965 if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^')966 && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) { /* Add a pointer upwards if this is not in the same dir as line above */967 tmpnopath[j - 1] = '^';968 } else {969 tmpnopath[j++] = tmp[i++];970 }971 }972 tmpnopath[j] = '\0';973 974 strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */975 976 return (tmpnopath);977 2079 } 978 2080 … … 1113 2215 1114 2216 /** 2217 * Change all RAID devices to use @p new_dev instead of @p old_dev. 2218 * @param raidlist The raidlist to make the changes in. 2219 * @param old_dev The old name of the device (what it used to be). 2220 * @param new_dev The new name of the device (what it is now). 2221 * @ingroup restoreGuiMountlist 2222 */ 2223 void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself 2224 *raidlist, 2225 char *old_dev, 2226 char *new_dev) 2227 { 2228 /** int ************************************************************/ 2229 int pos = 0; 2230 int j = 0; 2231 2232 assert(raidlist != NULL); 2233 assert_string_is_neither_NULL_nor_zerolength(old_dev); 2234 assert_string_is_neither_NULL_nor_zerolength(new_dev); 2235 2236 pos = which_raid_device_is_using_this_partition(raidlist, old_dev); 2237 if (pos < 0) { 2238 log_it("No need to rejig %s in raidlist: it's not listed.", old_dev); 2239 } else { 2240 if ((j = 2241 where_in_drivelist_is_drive(&raidlist-> 2242 OSSWAP(el[pos].data_disks, disks), 2243 old_dev)) >= 0) { 2244 strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev); 2245 } else 2246 if ((j = 2247 where_in_drivelist_is_drive(&raidlist-> 2248 OSSWAP(el[pos].spare_disks, 2249 spares), 2250 old_dev)) >= 0) { 2251 strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev); 2252 } 2253 #ifndef __FreeBSD__ 2254 else if ((j = 2255 where_in_drivelist_is_drive(&raidlist->el[pos]. 2256 parity_disks, 2257 old_dev)) >= 0) { 2258 strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev); 2259 } else 2260 if ((j = 2261 where_in_drivelist_is_drive(&raidlist->el[pos]. 2262 failed_disks, 2263 old_dev)) >= 0) { 2264 strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev); 2265 } 2266 #endif 2267 else { 2268 log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev); 2269 } 2270 } 2271 } 2272 2273 2274 /** 1115 2275 * Edit an entry in @p mountlist. 1116 2276 * @param mountlist The mountlist containing information about the user's partitions. … … 1380 2540 struct vinum_plex *raidrec, int currline, 1381 2541 int currline2); 1382 1383 #endif1384 1385 1386 /**1387 * Edit the entry for @p raidrec in @p raidlist.1388 * @param mountlist The mountlist to get some information from.1389 * @param raidlist The raidlist containing information about RAID devices.1390 * @param raidrec The RAID device record for this partition.1391 * @param currline The line number (starting from 0) in the mountlist of the RAID device.1392 * @ingroup restoreGuiMountlist1393 */1394 void1395 edit_raidlist_entry(struct mountlist_itself *mountlist,1396 struct raidlist_itself *raidlist,1397 struct OSSWAP (raid_device_record,1398 vinum_volume) * raidrec, int currline)1399 {1400 1401 #ifdef __FreeBSD__1402 /** structures ********************************************************/1403 struct vinum_volume bkp_raidrec;1404 1405 1406 /** buffers ***********************************************************/1407 char title_of_editraidForm_window[MAX_STR_LEN];1408 1409 /** newt **************************************************************/1410 newtComponent editraidForm;1411 newtComponent bOK;1412 newtComponent bCancel;1413 newtComponent bEdit;1414 newtComponent bAdd;1415 newtComponent bDelete;1416 newtComponent b_res;1417 newtComponent plexesListbox;1418 newtComponent plexesHeader;1419 1420 void *keylist[10];1421 void *curr_choice;1422 char *raidlevel = NULL;1423 char *chunksize = NULL;1424 char *msg = NULL;1425 1426 int currline2 = 0;1427 int res = 0;1428 1429 log_it("Started edit_raidlist_entry");1430 memcpy((void *) &bkp_raidrec, (void *) raidrec,1431 sizeof(struct vinum_volume));1432 sprintf(title_of_editraidForm_window, "Plexes on %s",1433 raidrec->volname);1434 newtPushHelpLine(" Please select a plex to edit");1435 newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);1436 for (;;) {1437 int i;1438 char *headerstr = NULL;1439 mr_asprintf(headerstr, "%-14s %-8s %11s %8s", "Plex", "Level", "Stripe Size", "Subdisks");1440 1441 bOK = newtCompactButton(2, 13, " OK ");1442 bCancel = newtCompactButton(12, 13, "Cancel");1443 bAdd = newtCompactButton(22, 13, " Add ");1444 bEdit = newtCompactButton(32, 13, " Edit ");1445 bDelete = newtCompactButton(42, 13, "Delete");1446 1447 plexesListbox =1448 newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);1449 plexesHeader = newtLabel(2, 2, headerstr);1450 mr_free(headerstr);1451 editraidForm = newtForm(NULL, NULL, 0);1452 1453 newtListboxClear(plexesListbox);1454 for (i = 0; i < 10; ++i) {1455 keylist[i] = (void *) i;1456 if (i < raidrec->plexes) {1457 char *pname;1458 char *entry;1459 switch (raidrec->plex[i].raidlevel) {1460 case -1:1461 mr_asprintf(raidlevel, "concat");1462 break;1463 case 0:1464 mr_asprintf(raidlevel, "striped");1465 break;1466 case 5:1467 mr_asprintf(raidlevel, "raid5");1468 break;1469 default:1470 mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel);1471 break;1472 }1473 1474 if (raidrec->plex[i].raidlevel == -1) {1475 mr_asprintf(chunksize, "N/A");1476 } else {1477 mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize);1478 }1479 mr_asprintf(pname, "%s.p%i", raidrec->volname, i);1480 mr_asprintf(entry, "%-14s %-8s %11s %8d", pname, raidlevel, chunksize, raidrec->plex[i].subdisks);1481 mr_free(pname);1482 mr_free(raidlevel);1483 mr_free(chunksize);1484 1485 newtListboxAppendEntry(plexesListbox, entry, keylist[i]);1486 mr_free(entry);1487 }1488 }1489 1490 newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,1491 bDelete, plexesListbox, plexesHeader, NULL);1492 1493 b_res = newtRunForm(editraidForm);1494 if (b_res == bOK || b_res == bCancel) {1495 break;1496 }1497 1498 curr_choice = newtListboxGetCurrent(plexesListbox);1499 for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {1500 if (currline2 > 9)1501 break;1502 if (keylist[currline2] == curr_choice)1503 break;1504 }1505 1506 if (b_res == bDelete) {1507 mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2);1508 res = ask_me_yes_or_no(msg);1509 mr_free(msg);1510 1511 if (res) {1512 log_it("Deleting RAID plex");1513 memcpy((void *) &raidrec->plex[currline2],1514 (void *) &raidrec->plex[raidrec->plexes - 1],1515 sizeof(struct vinum_plex));1516 raidrec->plexes--;1517 }1518 continue;1519 }1520 if (b_res == bAdd) {1521 raidrec->plex[raidrec->plexes].raidlevel = 0;1522 raidrec->plex[raidrec->plexes].stripesize = 279;1523 raidrec->plex[raidrec->plexes].subdisks = 0;1524 currline2 = raidrec->plexes++;1525 }1526 edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],1527 currline, currline2);1528 newtFormDestroy(editraidForm);1529 }1530 if (b_res == bCancel) {1531 memcpy((void *) raidrec, (void *) &bkp_raidrec,1532 sizeof(struct vinum_volume));1533 }1534 newtPopHelpLine();1535 newtPopWindow();1536 mountlist->el[currline].size =1537 calculate_raid_device_size(mountlist, raidlist, raidrec->volname);1538 #else1539 /** structures ********************************************************/1540 struct raid_device_record *bkp_raidrec;1541 1542 1543 /** buffers ***********************************************************/1544 char *title_of_editraidForm_window;1545 char *sz_raid_level = NULL;1546 char *sz_data_disks = NULL;1547 char *sz_spare_disks = NULL;1548 char *sz_parity_disks = NULL;1549 char *sz_failed_disks = NULL;1550 1551 /** newt **************************************************************/1552 newtComponent editraidForm;1553 newtComponent bOK;1554 newtComponent bCancel;1555 newtComponent bAdditional;1556 newtComponent bChangeRaid;1557 newtComponent bSelectData;1558 newtComponent bSelectSpare;1559 newtComponent bSelectParity;1560 newtComponent bSelectFailed;1561 newtComponent b_res;1562 1563 assert(mountlist != NULL);1564 assert(raidlist != NULL);1565 assert(raidrec != NULL);1566 1567 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));1568 log_it("Started edit_raidlist_entry");1569 1570 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));1571 mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device);1572 log_msg(2, "Opening newt window");1573 newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);1574 for (;;) {1575 log_msg(2, "Main loop");1576 mr_free(title_of_editraidForm_window);1577 mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device);1578 sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level);1579 sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data");1580 sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare");1581 sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity");1582 sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed");1583 bSelectData = newtButton(1, 1, sz_data_disks);1584 bSelectSpare = newtButton(20, 1, sz_spare_disks);1585 bSelectParity = newtButton(1, 5, sz_parity_disks);1586 bSelectFailed = newtButton(20, 5, sz_failed_disks);1587 bChangeRaid = newtButton(1, 9, sz_raid_level);1588 bOK = newtButton(16 + (raidrec->raid_level == -1), 9, " OK ");1589 bCancel = newtButton(28, 9, "Cancel");1590 bAdditional =1591 newtCompactButton(1, 13,1592 "Additional settings and information");1593 newtPushHelpLine1594 (" Edit the RAID device's settings to your heart's content, then hit OK/Cancel.");1595 editraidForm = newtForm(NULL, NULL, 0);1596 newtFormAddComponents(editraidForm, bSelectData, bSelectParity,1597 bChangeRaid, bSelectSpare, bSelectFailed,1598 bOK, bCancel, bAdditional);1599 b_res = newtRunForm(editraidForm);1600 if (b_res == bChangeRaid) {1601 choose_raid_level(raidrec);1602 } else if (b_res == bSelectData) {1603 select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks);1604 } else if (b_res == bSelectSpare) {1605 select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks);1606 } else if (b_res == bSelectParity) {1607 select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks);1608 } else if (b_res == bSelectFailed) {1609 select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks);1610 } else if (b_res == bAdditional) {1611 edit_raidrec_additional_vars(raidrec);1612 }1613 newtFormDestroy(editraidForm);1614 if (b_res == bOK || b_res == bCancel) {1615 break;1616 }1617 mr_free(sz_data_disks);1618 mr_free(sz_spare_disks);1619 mr_free(sz_parity_disks);1620 mr_free(sz_failed_disks);1621 }1622 if (b_res == bCancel) {1623 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));1624 }1625 newtPopHelpLine();1626 newtPopWindow();1627 mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device);1628 mr_free(title_of_editraidForm_window);1629 mr_free(sz_raid_level);1630 paranoid_free(bkp_raidrec);1631 #endif1632 }1633 1634 #ifdef __FreeBSD__1635 1636 /**1637 * Edit the plex @p raidrec in @p raidlist.1638 * @param mountlist The mountlist to get some of the information from.1639 * @param raidlist The raidlist containing information about RAID devices.1640 * @param raidrec The plex to edit.1641 * @param currline The line number (starting from 0) of the RAID device in @p mountlist.1642 * @param currline2 The line number (starting from 0) of the plex within the RAID device.1643 * @author Joshua Oreman1644 * @ingroup restoreGuiMountlist1645 */1646 void1647 edit_raidlist_plex(struct mountlist_itself *mountlist,1648 struct raidlist_itself *raidlist,1649 struct vinum_plex *raidrec, int currline, int currline2)1650 {1651 1652 /** structures ********************************************************/1653 struct vinum_plex bkp_raidrec;1654 1655 1656 /** buffers ***********************************************************/1657 char *title_of_editraidForm_window = NULL;1658 1659 /** newt **************************************************************/1660 newtComponent editraidForm;1661 newtComponent bOK;1662 newtComponent bCancel;1663 newtComponent bEdit;1664 newtComponent bAdd;1665 newtComponent bDelete;1666 newtComponent b_res;1667 newtComponent unallocListbox, allocListbox;1668 newtComponent bLevel, sLevel;1669 newtComponent bStripeSize, sStripeSize;1670 newtComponent bAlloc, bUnalloc;1671 1672 void *keylist[ARBITRARY_MAXIMUM];1673 void *curr_choice_a, *curr_choice_u;1674 int currline_a, currline_u;1675 1676 char *p = NULL;1677 char *tmp = NULL;1678 char *entry = NULL;1679 1680 struct mountlist_itself *unallocparts;1681 1682 unallocparts = malloc(sizeof(struct mountlist_itself));1683 1684 log_it("Started edit_raidlist_entry");1685 memcpy((void *) &bkp_raidrec, (void *) raidrec,1686 sizeof(struct vinum_plex));1687 mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2);1688 newtPushHelpLine1689 (" Please select a subdisk to edit, or edit this plex's parameters");1690 newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);1691 mr_free(title_of_editraidForm_window);1692 1693 for (;;) {1694 int i;1695 1696 switch (raidrec->raidlevel) {1697 case -1:1698 mr_asprintf(tmp, "concat");1699 break;1700 case 0:1701 mr_asprintf(tmp, "striped");1702 break;1703 case 5:1704 mr_asprintf(tmp, "raid5");1705 break;1706 default:1707 mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel);1708 break;1709 }1710 bLevel = newtCompactButton(2, 2, " RAID level ");1711 sLevel = newtLabel(19, 2, tmp);1712 mr_free(tmp);1713 1714 if (raidrec->raidlevel >= 0) {1715 mr_asprintf(tmp, "%ik", raidrec->stripesize);1716 bStripeSize = newtCompactButton(2, 4, " Stripe size ");1717 } else {1718 mr_asprintf(tmp, "N/A");1719 bStripeSize = newtLabel(2, 4, "Stripe size:");1720 }1721 sStripeSize = newtLabel(19, 4, tmp);1722 mr_free(tmp);1723 1724 bOK = newtCompactButton(2, 16, " OK ");1725 bCancel = newtCompactButton(12, 16, "Cancel");1726 bAdd = newtCompactButton(22, 16, " Add ");1727 bEdit = newtCompactButton(32, 16, " Edit ");1728 bDelete = newtCompactButton(42, 16, "Delete");1729 1730 1731 unallocListbox =1732 newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);1733 allocListbox =1734 newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);1735 bAlloc = newtButton(23, 7, " -> ");1736 bUnalloc = newtButton(23, 11, " <- ");1737 1738 editraidForm = newtForm(NULL, NULL, 0);1739 1740 newtListboxClear(allocListbox);1741 newtListboxClear(unallocListbox);1742 bzero(unallocparts, sizeof(struct mountlist_itself));1743 make_list_of_unallocated_raid_partitions(unallocparts, mountlist,1744 raidlist);1745 for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {1746 keylist[i] = (void *) i;1747 if (i < raidrec->subdisks) {1748 mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device));1749 newtListboxAppendEntry(allocListbox, entry, keylist[i]);1750 mr_free(entry);1751 }1752 if (i < unallocparts->entries) {1753 mr_asprintf(entry, "%-17s", unallocparts->el[i].device);1754 newtListboxAppendEntry(unallocListbox, entry, keylist[i]);1755 mr_free(entry);1756 }1757 }1758 1759 #define COMP(x) newtFormAddComponent (editraidForm, x)1760 #define UCOMP(x) if (unallocparts->entries > 0) COMP(x)1761 #define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)1762 editraidForm = newtForm(NULL, NULL, 0);1763 UCOMP(unallocListbox);1764 UCOMP(bAlloc);1765 ACOMP(allocListbox);1766 ACOMP(bUnalloc);1767 COMP(bOK);1768 COMP(bCancel);1769 COMP(bLevel);1770 COMP(sLevel);1771 if (raidrec->raidlevel != -1) {1772 COMP(bStripeSize);1773 COMP(sStripeSize);1774 }1775 #undef COMP1776 #undef UCOMP1777 #undef ACOMP1778 1779 newtDrawForm(editraidForm);1780 newtRefresh();1781 b_res = newtRunForm(editraidForm);1782 if (b_res == bOK || b_res == bCancel) {1783 break;1784 }1785 1786 curr_choice_a = (raidrec->subdisks > 0) ?1787 newtListboxGetCurrent(allocListbox) : (void *) 1234;1788 curr_choice_u = (unallocparts->entries > 0) ?1789 newtListboxGetCurrent(unallocListbox) : (void *) 1234;1790 for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {1791 if (currline_a > ARBITRARY_MAXIMUM)1792 break;1793 if (keylist[currline_a] == curr_choice_a)1794 break;1795 }1796 for (currline_u = 0; currline_u < unallocparts->entries;1797 ++currline_u) {1798 if (currline_u > ARBITRARY_MAXIMUM)1799 break;1800 if (keylist[currline_u] == curr_choice_u)1801 break;1802 }1803 if (b_res == bLevel) {1804 choose_raid_level(raidrec);1805 } else if (b_res == bStripeSize) {1806 char tmp1[64];1807 sprintf(tmp1, "%i", raidrec->stripesize);1808 if (popup_and_get_string1809 ("Stripe size",1810 "Please enter the stripe size in kilobytes.", tmp1, 20)) {1811 raidrec->stripesize = atoi(tmp1);1812 }1813 } else if ((b_res == bAlloc) || (b_res == unallocListbox)) {1814 if (currline_u <= unallocparts->entries)1815 add_raid_subdisk(raidlist, raidrec,1816 unallocparts->el[currline_u].device);1817 } else if ((b_res == bUnalloc) || (b_res == allocListbox)) {1818 if (currline_a <= raidrec->subdisks) {1819 memcpy((void *) &raidrec->sd[currline_a],1820 (void *) &raidrec->sd[raidrec->subdisks - 1],1821 sizeof(struct vinum_subdisk));1822 raidrec->subdisks--;1823 }1824 }1825 newtFormDestroy(editraidForm);1826 newtRefresh();1827 }1828 1829 if (b_res == bCancel) {1830 memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex));1831 }1832 newtPopWindow();1833 newtPopHelpLine();1834 }1835 #else1836 /**1837 * Edit additional RAID variable number @p lino.1838 * @param raidrec The RAID device record to edit the variable in.1839 * @param lino The line number (starting from 0) of the variable to edit.1840 * @ingroup restoreGuiVarslist1841 */1842 void edit_varslist_entry(struct raid_device_record *raidrec, int lino)1843 {1844 1845 /** buffers ***********************************************************/1846 char *header = NULL;1847 char *comment = NULL;1848 char sz_out[MAX_STR_LEN];1849 1850 assert(raidrec != 0);1851 assert(lino >= 0);1852 1853 strcpy(sz_out, raidrec->additional_vars.el[lino].value);1854 mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label);1855 mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out);1856 if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {1857 strip_spaces(sz_out);1858 strcpy(raidrec->additional_vars.el[lino].value, sz_out);1859 }1860 mr_free(header);1861 mr_free(comment);1862 }1863 2542 1864 2543 #endif … … 2048 2727 } 2049 2728 2050 2051 2052 2053 #ifndef __FreeBSD__2054 /**2055 * Edit the additional RAID variables in @p raidrec.2056 * @param raidrec The RAID device record to edit the RAID variables in.2057 * @ingroup restoreGuiVarslist2058 */2059 void edit_raidrec_additional_vars(struct raid_device_record *raidrec)2060 {2061 2062 /** structure *********************************************************/2063 struct raid_device_record bkp_raidrec;2064 2065 /** newt **************************************************************/2066 newtComponent myForm;2067 newtComponent bAdd;2068 newtComponent bEdit;2069 newtComponent bDelete;2070 newtComponent bOK;2071 newtComponent bCancel;2072 newtComponent b_res;2073 newtComponent varsListbox;2074 newtComponent headerMsg;2075 2076 /** ?? ***************************************************************/2077 void *keylist[ARBITRARY_MAXIMUM], *curr_choice;2078 2079 /** buffers **********************************************************/2080 char title_of_window[MAX_STR_LEN];2081 2082 /** int **************************************************************/2083 int i = 0;2084 int currline = 0;2085 2086 2087 assert(raidrec != NULL);2088 2089 memcpy((void *) &bkp_raidrec, (void *) raidrec,2090 sizeof(struct raid_device_record));2091 sprintf(title_of_window, "Additional variables");2092 newtPushHelpLine2093 (" Edit the additional fields to your heart's content, then click OK or Cancel.");2094 headerMsg = newtLabel(1, 1, "Label Value");2095 varsListbox =2096 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);2097 i = 1;2098 bAdd = newtCompactButton(i, 9, " Add ");2099 bEdit = newtCompactButton(i += 8, 9, " Edit ");2100 bDelete = newtCompactButton(i += 9, 9, "Delete");2101 bOK = newtCompactButton(i += 9, 9, " OK ");2102 bCancel = newtCompactButton(i += 9, 9, "Cancel");2103 newtOpenWindow(17, 7, 46, 10, title_of_window);2104 myForm = newtForm(NULL, NULL, 0);2105 newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit,2106 bDelete, bOK, bCancel, NULL);2107 insert_essential_additionalvars(raidrec);2108 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);2109 for (b_res = NULL; b_res != bOK && b_res != bCancel;) {2110 b_res = newtRunForm(myForm);2111 curr_choice = newtListboxGetCurrent(varsListbox);2112 for (currline = 0;2113 currline < raidrec->additional_vars.entries2114 && keylist[currline] != curr_choice; currline++);2115 if (currline == raidrec->additional_vars.entries2116 && raidrec->additional_vars.entries > 0) {2117 log_it("Warning - I don't know what this button does");2118 }2119 if (b_res == bOK) { /* do nothing */2120 } else if (b_res == bCancel) { /* do nothing */2121 } else if (b_res == bAdd) {2122 add_varslist_entry(raidrec);2123 } else if (b_res == bDelete) {2124 delete_varslist_entry(raidrec, currline);2125 } else {2126 edit_varslist_entry(raidrec, currline);2127 }2128 redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);2129 }2130 remove_essential_additionalvars(raidrec);2131 newtFormDestroy(myForm);2132 newtPopWindow();2133 newtPopHelpLine();2134 if (b_res == bCancel) {2135 memcpy((void *) raidrec, (void *) &bkp_raidrec,2136 sizeof(struct raid_device_record));2137 }2138 return;2139 }2140 #endif2141 2142 2143 /**2144 * Find the next free location to place a disk in @p disklist.2145 * @param disklist The disklist to operate on.2146 * @return The next free location (starting from 0).2147 * @ingroup restoreGuiDisklist2148 */2149 int find_next_free_index_in_disklist(struct list_of_disks *disklist)2150 {2151 2152 /** int ***************************************************************/2153 int index = -1;2154 int pos = 0;2155 2156 /** bool **************************************************************/2157 bool done;2158 2159 assert(disklist != NULL);2160 2161 for (done = FALSE; !done;) {2162 for (pos = 0;2163 pos < disklist->entries && disklist->el[pos].index <= index;2164 pos++);2165 if (pos >= disklist->entries) {2166 done = TRUE;2167 } else {2168 index = disklist->el[pos].index;2169 }2170 }2171 return (index + 1);2172 }2173 2174 2175 2176 /**2177 * Locate @p device in @p raidlist.2178 * @param raidlist The raidlist ot search in.2179 * @param device The RAID device to search for.2180 * @return The index of the device, or -1 if it could not be found.2181 * @ingroup restoreGuiMountlist2182 */2183 int2184 find_raid_device_in_raidlist(struct raidlist_itself *raidlist,2185 char *device)2186 {2187 2188 /** int ***************************************************************/2189 int i = 0;2190 #ifdef __FreeBSD__2191 char *vdev = NULL;2192 int res = 0;2193 #else2194 // Linux2195 #endif2196 2197 assert(raidlist != NULL);2198 assert_string_is_neither_NULL_nor_zerolength(device);2199 2200 #ifdef __FreeBSD__2201 for (i = 0; i < raidlist->entries; i++) {2202 mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname);2203 res = strcmp(device, vdev);2204 mr_free(vdev);2205 2206 if (!res)2207 break;2208 }2209 #else2210 2211 for (i = 0;2212 strcmp(raidlist->el[i].raid_device, device)2213 && i < raidlist->entries; i++);2214 #endif2215 if (i == raidlist->entries) {2216 return (-1);2217 } else {2218 return (i);2219 }2220 }2221 2222 2223 /**2224 * Create a new raidtab entry for @p device in @p raidlist.2225 * @param raidlist The raidlist to add the device to.2226 * @param mountlist The mountlist containing information about the user's partitions.2227 * @param currline The selected line in the mountlist.2228 * @param device The RAID device (e.g. /dev/md0) to use.2229 * @ingroup restoreGuiMountlist2230 */2231 void2232 initiate_new_raidlist_entry(struct raidlist_itself *raidlist,2233 struct mountlist_itself *mountlist,2234 int currline, char *device)2235 {2236 2237 /** structure *********************************************************/2238 struct OSSWAP (raid_device_record, vinum_volume) * raidrec;2239 2240 /** int ***************************************************************/2241 int pos_in_raidlist = 0;2242 2243 assert(raidlist != NULL);2244 assert(mountlist != NULL);2245 assert_string_is_neither_NULL_nor_zerolength(device);2246 2247 pos_in_raidlist =2248 find_raid_device_in_raidlist(raidlist,2249 mountlist->el[currline].device);2250 if (pos_in_raidlist >= 0) {2251 fatal_error("Sorry, that RAID device already exists. Weird.");2252 }2253 pos_in_raidlist = raidlist->entries++;2254 raidrec = &raidlist->el[pos_in_raidlist];2255 initialize_raidrec(raidrec);2256 strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device)));2257 #ifndef __FreeBSD__2258 choose_raid_level(raidrec);2259 select_raid_disks(mountlist, raidlist, raidrec, "data",2260 &raidrec->data_disks);2261 #endif2262 edit_raidlist_entry(mountlist, raidlist, raidrec, currline);2263 }2264 2265 2266 #ifndef __FreeBSD__2267 /**2268 * Insert the RAID variables not stored in the "additional RAID variables" list there too.2269 * @param raidrec The RAID device record to operate on.2270 * @ingroup restoreGuiVarslist2271 */2272 void insert_essential_additionalvars(struct raid_device_record *raidrec)2273 {2274 2275 /** int **************************************************************/2276 int items = 0;2277 2278 assert(raidrec != NULL);2279 2280 items = raidrec->additional_vars.entries;2281 write_variableINT_to_raid_var_line(raidrec, items++,2282 "persistent-superblock",2283 raidrec->persistent_superblock);2284 write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size",2285 raidrec->chunk_size);2286 raidrec->additional_vars.entries = items;2287 }2288 2289 #endif2290 2291 2729 /** 2292 2730 * Dummy function that proves that we can get to the point where Mondo is run. … … 2314 2752 newtPopHelpLine(); 2315 2753 } 2316 2317 2318 2319 /**2320 * Redraw the disklist.2321 * @param disklist The disklist to read from.2322 * @param keylist The list of keys for @p listbox.2323 * @param listbox The Newt listbox component to redraw.2324 * @ingroup restoreGuiDisklist2325 */2326 void2327 redraw_disklist(struct list_of_disks *disklist,2328 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)2329 {2330 2331 /** long **************************************************************/2332 long i = 0;2333 char *tmp = NULL;2334 2335 assert(disklist != NULL);2336 assert(keylist != NULL);2337 assert(listbox != NULL);2338 2339 newtListboxClear(listbox);2340 2341 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2342 keylist[i] = (void *) i;2343 }2344 for (i = 0; i < disklist->entries; i++) {2345 tmp = disklist_entry_to_string(disklist, i);2346 newtListboxAppendEntry(listbox, tmp, keylist[i]);2347 mr_free(tmp);2348 }2349 }2350 2351 2352 /**2353 * Redraw the mountlist.2354 * @param mountlist The mountlist to read from.2355 * @param keylist The list of keys for @p listbox.2356 * @param listbox The Newt listbox component to redraw.2357 * @ingroup restoreGuiMountlist2358 */2359 void2360 redraw_mountlist(struct mountlist_itself *mountlist,2361 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)2362 {2363 2364 /** long **************************************************************/2365 long i = 0;2366 char * tmp = NULL;2367 2368 assert(mountlist != NULL);2369 assert(keylist != NULL);2370 assert(listbox != NULL);2371 2372 newtListboxClear(listbox);2373 // sort_mountlist_by_device (mountlist);2374 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2375 keylist[i] = (void *) i;2376 }2377 for (i = 0; i < mountlist->entries; i++) {2378 tmp = mountlist_entry_to_string(mountlist, i);2379 newtListboxAppendEntry(listbox, tmp, keylist[i]);2380 mr_free(tmp);2381 }2382 }2383 2384 2385 2386 2387 /**2388 * Redraw the list of unallocated RAID partitions.2389 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions.2390 * @param keylist The list of keys for @p listbox.2391 * @param listbox The Newt listbox component to redraw.2392 * @ingroup restoreGuiDisklist2393 */2394 void redraw_unallocpartnslist(struct mountlist_itself2395 *unallocated_raid_partitions,2396 void *keylist[ARBITRARY_MAXIMUM],2397 newtComponent listbox)2398 {2399 2400 /** long *************************************************************/2401 long i = 0;2402 2403 /** buffers **********************************************************/2404 char tmp[MAX_STR_LEN];2405 2406 assert(unallocated_raid_partitions != NULL);2407 assert(keylist != NULL);2408 assert(listbox != NULL);2409 2410 newtListboxClear(listbox);2411 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2412 keylist[i] = (void *) i;2413 }2414 for (i = 0; i < unallocated_raid_partitions->entries; i++) {2415 sprintf(tmp, "%-22s %8lld",2416 unallocated_raid_partitions->el[i].device,2417 unallocated_raid_partitions->el[i].size / 1024L);2418 newtListboxAppendEntry(listbox, tmp, keylist[i]);2419 }2420 }2421 2422 #ifndef __FreeBSD__2423 /**2424 * Redraw the list of additional RAID variables.2425 * @param additional_vars The list of additional RAID varibals.2426 * @param keylist The list of keys for @p listbox.2427 * @param listbox The Newt listbox component to redraw.2428 * @ingroup restoreGuiVarslist2429 */2430 void2431 redraw_varslist(struct additional_raid_variables *additional_vars,2432 void *keylist[], newtComponent listbox)2433 {2434 /** long ************************************************************/2435 long i = 0;2436 2437 /** buffers *********************************************************/2438 char tmp[MAX_STR_LEN];2439 2440 assert(additional_vars != NULL);2441 assert(keylist != NULL);2442 assert(listbox != NULL);2443 2444 newtListboxClear(listbox);2445 2446 for (i = 0; i < ARBITRARY_MAXIMUM; i++) {2447 keylist[i] = (void *) i;2448 }2449 for (i = 0; i < additional_vars->entries; i++) {2450 sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label,2451 additional_vars->el[i].value);2452 newtListboxAppendEntry(listbox, tmp, keylist[i]);2453 }2454 }2455 2456 2457 /**2458 * Remove variable @p label from the RAID variables list in @p raidrec.2459 * @param raidrec The RAID device record to remove the variable from.2460 * @param label The variable name to remove.2461 * @return The value of the variable removed.2462 * @ingroup restoreUtilityGroup2463 */2464 int2465 read_variableINT_and_remove_from_raidvars(struct2466 OSSWAP (raid_device_record,2467 vinum_volume) * raidrec,2468 char *label)2469 {2470 /** int ***************************************************************/2471 int i = 0;2472 int res = 0;2473 2474 2475 assert(raidrec != NULL);2476 assert(label != NULL);2477 2478 for (i = 0;2479 i < raidrec->additional_vars.entries2480 && strcmp(raidrec->additional_vars.el[i].label, label); i++);2481 if (i == raidrec->additional_vars.entries) {2482 res = -1;2483 } else {2484 res = atoi(raidrec->additional_vars.el[i].value);2485 for (i++; i < raidrec->additional_vars.entries; i++) {2486 memcpy((void *) &raidrec->additional_vars.el[i - 1],2487 (void *) &raidrec->additional_vars.el[i],2488 sizeof(struct raid_var_line));2489 }2490 raidrec->additional_vars.entries--;2491 }2492 return (res);2493 }2494 #endif2495 2496 /**2497 * Change all RAID devices to use @p new_dev instead of @p old_dev.2498 * @param raidlist The raidlist to make the changes in.2499 * @param old_dev The old name of the device (what it used to be).2500 * @param new_dev The new name of the device (what it is now).2501 * @ingroup restoreGuiMountlist2502 */2503 void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself2504 *raidlist,2505 char *old_dev,2506 char *new_dev)2507 {2508 /** int ************************************************************/2509 int pos = 0;2510 int j = 0;2511 2512 assert(raidlist != NULL);2513 assert_string_is_neither_NULL_nor_zerolength(old_dev);2514 assert_string_is_neither_NULL_nor_zerolength(new_dev);2515 2516 pos = which_raid_device_is_using_this_partition(raidlist, old_dev);2517 if (pos < 0) {2518 log_it("No need to rejig %s in raidlist: it's not listed.", old_dev);2519 } else {2520 if ((j =2521 where_in_drivelist_is_drive(&raidlist->2522 OSSWAP(el[pos].data_disks, disks),2523 old_dev)) >= 0) {2524 strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev);2525 } else2526 if ((j =2527 where_in_drivelist_is_drive(&raidlist->2528 OSSWAP(el[pos].spare_disks,2529 spares),2530 old_dev)) >= 0) {2531 strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev);2532 }2533 #ifndef __FreeBSD__2534 else if ((j =2535 where_in_drivelist_is_drive(&raidlist->el[pos].2536 parity_disks,2537 old_dev)) >= 0) {2538 strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev);2539 } else2540 if ((j =2541 where_in_drivelist_is_drive(&raidlist->el[pos].2542 failed_disks,2543 old_dev)) >= 0) {2544 strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev);2545 }2546 #endif2547 else {2548 log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev);2549 }2550 }2551 }2552 2553 2554 #ifndef __FreeBSD__2555 /**2556 * Remove the essential RAID variables from the "additional variables" section.2557 * If they have been changed, set them in their normal locations too.2558 * @param raidrec The RAID device record to operate on.2559 * @ingroup restoreUtilityVarslist2560 */2561 void remove_essential_additionalvars(struct raid_device_record *raidrec)2562 {2563 2564 /** int **************************************************************/2565 int res = 0;2566 2567 assert(raidrec != NULL);2568 2569 res =2570 read_variableINT_and_remove_from_raidvars(raidrec,2571 "persistent-superblock");2572 if (res > 0) {2573 raidrec->persistent_superblock = res;2574 }2575 res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size");2576 if (res > 0) {2577 raidrec->chunk_size = res;2578 }2579 res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size");2580 }2581 2582 /**2583 * Select the RAID disks to use in @p raidrec.2584 * @param mountlist_dontedit The mountlist (will not be edited).2585 * @param raidlist The raidlist to modify.2586 * @param raidrec The RAID device record in @p raidlist to work on.2587 * @param description_of_list The type of disks we're selecting (e.g. "data").2588 * @param disklist The disklist to put the user-selected disks in.2589 * @ingroup restoreGuiMountlist2590 */2591 void2592 select_raid_disks(struct mountlist_itself *mountlist_dontedit,2593 struct raidlist_itself *raidlist,2594 struct raid_device_record *raidrec,2595 char *description_of_list,2596 struct list_of_disks *disklist)2597 {2598 void *curr_choice;2599 2600 /** ??? ***************************************************************/2601 2602 /** structures ********************************************************/2603 struct raidlist_itself *bkp_raidlist;2604 struct raid_device_record *bkp_raidrec;2605 struct list_of_disks *bkp_disklist;2606 struct mountlist_itself *unallocated_raid_partitions;2607 2608 /** newt **************************************************************/2609 newtComponent myForm = NULL;2610 newtComponent bAdd = NULL;2611 newtComponent bDelete = NULL;2612 newtComponent bOK = NULL;2613 newtComponent bCancel = NULL;2614 newtComponent b_res = NULL;2615 newtComponent partitionsListbox = NULL;2616 newtComponent headerMsg = NULL;2617 2618 /** buffers **********************************************************/2619 void *keylist[ARBITRARY_MAXIMUM];2620 char *tmp = NULL;2621 char *help_text = NULL;2622 char *title_of_window = NULL;2623 char sz_res[MAX_STR_LEN];2624 char *header_text = NULL;2625 2626 /** int **************************************************************/2627 int i = 0;2628 int currline = 0;2629 2630 assert(mountlist_dontedit != NULL);2631 assert(raidlist != NULL);2632 assert(raidrec != NULL);2633 assert(description_of_list != NULL);2634 assert(disklist != NULL);2635 2636 log_it("malloc'ing");2637 bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));2638 bkp_disklist = mr_malloc(sizeof(struct list_of_disks));2639 bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself));2640 unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself));2641 2642 memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself));2643 memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));2644 memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks));2645 2646 log_it("Post-malloc");2647 mr_asprintf(help_text, " Edit this RAID device's list of partitions. Choose OK or Cancel when done.");2648 mr_asprintf(header_text, "%-24s %s", "Device", "Index");2649 mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device);2650 newtPushHelpLine(help_text);2651 for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) {2652 headerMsg = newtLabel(1, 1, header_text);2653 partitionsListbox =2654 newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);2655 redraw_disklist(disklist, keylist, partitionsListbox);2656 i = 1;2657 bAdd = newtCompactButton(i, 9, " Add ");2658 bDelete = newtCompactButton(i += 8, 9, "Delete");2659 bOK = newtCompactButton(i += 9, 9, " OK ");2660 bCancel = newtCompactButton(i += 9, 9, "Cancel");2661 newtOpenWindow(21, 7, 38, 10, title_of_window);2662 myForm = newtForm(NULL, NULL, 0);2663 if (disklist->entries == 0) {2664 newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK,2665 bCancel, NULL);2666 } else {2667 newtFormAddComponents(myForm, headerMsg, partitionsListbox,2668 bAdd, bDelete, bOK, bCancel, NULL);2669 }2670 b_res = newtRunForm(myForm);2671 if (b_res == bOK || b_res == bCancel) { /* do nothing */2672 // That's OK. At the end of this subroutine (after this do/while loop),2673 // we'll throw away the changes if Cancel was pushed.2674 } else {2675 curr_choice = newtListboxGetCurrent(partitionsListbox);2676 for (i = 0; i < disklist->entries && keylist[i] != curr_choice;2677 i++);2678 if (i == disklist->entries && disklist->entries > 0) {2679 log_to_screen("I don't know what that button does!");2680 } else {2681 currline = i;2682 if (b_res == bAdd) {2683 log_it("Making list of unallocated RAID slices");2684 make_list_of_unallocated_raid_partitions2685 (unallocated_raid_partitions, mountlist_dontedit,2686 raidlist);2687 if (unallocated_raid_partitions->entries <= 0) {2688 popup_and_OK2689 ("There are no unallocated partitions marked for RAID.");2690 } else {2691 log_it2692 ("Done. The user may add one or more of the above to RAID device");2693 add_disklist_entry(disklist, raidrec->raid_device,2694 unallocated_raid_partitions);2695 log_it("I have finished adding a disklist entry.");2696 redraw_disklist(disklist, keylist,2697 partitionsListbox);2698 }2699 } else if (b_res == bDelete) {2700 delete_disklist_entry(disklist, raidrec->raid_device,2701 currline);2702 redraw_disklist(disklist, keylist, partitionsListbox);2703 } else {2704 mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index);2705 sprintf(sz_res, "%d", disklist->el[currline].index);2706 if (popup_and_get_string("Set index", tmp, sz_res, 10)) {2707 disklist->el[currline].index = atoi(sz_res);2708 }2709 mr_free(tmp);2710 2711 redraw_disklist(disklist, keylist, partitionsListbox);2712 }2713 }2714 }2715 newtFormDestroy(myForm);2716 newtPopWindow();2717 }2718 newtPopHelpLine();2719 mr_free(help_text);2720 mr_free(header_text);2721 mr_free(title_of_window);2722 2723 if (b_res == bCancel) {2724 memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself));2725 memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));2726 memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks));2727 }2728 mr_free(bkp_raidrec);2729 mr_free(bkp_disklist);2730 mr_free(bkp_raidlist);2731 mr_free(unallocated_raid_partitions);2732 }2733 #endif2734 2735 2736 2754 2737 2755 /** -
branches/3.3/mondo/src/mondorestore/mondo-rstr-tools.c
r3876 r3879 10 10 #include "mr_file.h" 11 11 #include "mr_sys.h" 12 #include "../common/mondostructures.h" 13 #include "../common/libmondo.h" 14 #include "mr-externs.h" 15 #include "mondo-rstr-tools.h" 12 #include "mondostructures.h" 16 13 #include "libmondo-mountlist-EXT.h" 14 #include "libmondo-tools-EXT.h" 15 #include "libmondo-filelist-EXT.h" 16 #include "libmondo-files-EXT.h" 17 #include "libmondo-devices-EXT.h" 18 #include "libmondo-string-EXT.h" 19 #include "libmondo-raid-EXT.h" 20 #include "libmondo-fork-EXT.h" 17 21 #include "newt-specific-EXT.h" 22 // no include for now in mondo-rstr-newt.c 23 extern int edit_filelist(struct s_node *); 18 24 19 25 /** … … 74 80 extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored 75 81 extern char *g_mondo_home; // homedir of Mondo; usually /usr/local/share/mondo 82 extern int g_currentY; 83 extern bool g_restoring_live_from_cd; 84 extern bool g_text_mode; 85 extern int g_current_media_number; 76 86 77 87 extern t_bkptype g_backup_media_type; … … 169 179 170 180 171 181 /** 182 * Extract mondorestore.cfg and the mountlist from the tape inserted 183 * to the ./tmp/ directory. 184 * @param dev The tape device to read from. 185 * @return 0 for success, nonzero for failure. 186 */ 187 int extract_cfg_file_and_mountlist_from_tape_dev(char *dev) 188 { 189 char *command = NULL; 190 int res = 0; 191 192 if (bkpinfo->use_obdr) { 193 skip_obdr(); 194 } else { 195 // TODO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0 196 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 197 } 198 199 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); 200 log_msg(2, "command = '%s'", command); 201 res = run_program_and_log_output(command, -1); 202 mr_free(command); 203 204 if (res != 0) { 205 if (does_file_exist(MONDO_CFG_FILE_STUB)) { 206 res = 0; 207 } else { 208 /* Doing that allow us to remain compatible with pre-2.2.5 versions */ 209 log_msg(2, "pre-2.2.4 compatible mode on"); 210 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); 211 log_msg(2, "command = '%s'", command); 212 res = run_program_and_log_output(command, -1); 213 mr_free(command); 214 if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) { 215 res = 0; 216 } 217 } 218 } 219 paranoid_free(command); 220 return (res); 221 } 222 223 224 225 226 227 /** 228 * Get the configuration file from the tape, or CD. 229 * @param bkpinfo The backup information structure. Fields used: 230 * - @c bkpinfo->backup_media_type 231 * - @c bkpinfo->media_device 232 * - @c bkpinfo->tmpdir 233 * @return 0 for success, nonzero for failure. 234 */ 235 int get_cfg_file_from_archive() 236 { 237 int retval = 0; 238 239 /** malloc *****/ 240 char *command = NULL; 241 char *cfg_file = NULL; 242 char *tmp = NULL; 243 char *tmp1 = NULL; 244 char *mountpt = NULL; 245 char *mountlist_file = NULL; 246 bool extract_mountlist_stub = FALSE; 247 bool extract_i_want_my_lvm = FALSE; 248 249 bool try_plan_B; 250 251 assert(bkpinfo != NULL); 252 log_msg(2, "gcffa --- starting"); 253 log_to_screen("I'm thinking..."); 254 mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir); 255 if (chdir(bkpinfo->tmpdir)) { 256 // FIXME 257 } 258 mr_asprintf(cfg_file, "%s", MONDO_CFG_FILE_STUB); 259 unlink(cfg_file); // cfg_file[] is missing the '/' at the start, FYI, by intent 260 mr_free(cfg_file); 261 262 unlink(FILELIST_FULL_STUB); 263 unlink(BIGGIELIST_TXT_STUB); 264 mr_asprintf(command, "mkdir -p %s", mountpt); 265 run_program_and_log_output(command, FALSE); 266 mr_free(command); 267 268 mr_asprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB); 269 mr_asprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB); 270 log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file); 271 mr_free(mountpt); 272 273 if (!does_file_exist(cfg_file)) { 274 log_msg(2, "gcffa --- we don't have cfg file yet."); 275 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) { 276 try_plan_B = TRUE; 277 } else { 278 log_msg(2, "gcffa --- calling mount_media now :)"); 279 if (!mount_media(MNT_CDROM)) { 280 log_msg(2, "gcffa --- managed to mount CD; so, no need for Plan B"); 281 try_plan_B = FALSE; 282 } else { 283 try_plan_B = TRUE; 284 } 285 if (what_number_cd_is_this() > 1) { 286 insist_on_this_cd_number((g_current_media_number = 1)); 287 } 288 } 289 if (try_plan_B) { 290 log_msg(2, "gcffa --- OK, switching to Plan B"); 291 if (chdir(bkpinfo->tmpdir)) { 292 // FIXME 293 } 294 run_program_and_log_output("mkdir -p tmp", FALSE); 295 296 if (bkpinfo->media_device == NULL) { 297 mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0"); 298 log_msg(2, "media_device is blank; assuming %s", bkpinfo->media_device); 299 } 300 mr_asprintf(tmp, "%s", bkpinfo->media_device); 301 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) { 302 mr_free(bkpinfo->media_device); 303 mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0"); 304 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) { 305 mr_free(bkpinfo->media_device); 306 mr_asprintf(bkpinfo->media_device, "%s", "/dev/osst0"); 307 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) { 308 mr_free(bkpinfo->media_device); 309 mr_asprintf(bkpinfo->media_device, "%s", "/dev/ht0"); 310 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) { 311 log_msg(3, "I tried lots of devices but none worked."); 312 mr_free(bkpinfo->media_device); 313 } 314 } 315 } 316 } 317 if (bkpinfo->media_device == NULL) { 318 bkpinfo->media_device = tmp; 319 } else { 320 mr_free(tmp); 321 } 322 323 if (!does_file_exist("tmp/mondorestore.cfg")) { 324 log_to_screen("Cannot find config info on media"); 325 return (1); 326 } 327 } else { 328 if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) { 329 extract_mountlist_stub = FALSE; 330 } else { 331 extract_mountlist_stub = TRUE; 332 } 333 if (does_file_exist("/"IWANTMYLVM_STUB)) { 334 extract_i_want_my_lvm = FALSE; 335 } else { 336 extract_i_want_my_lvm = TRUE; 337 } 338 339 log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz"); 340 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary 341 run_program_and_log_output(command, TRUE); 342 mr_free(command); 343 344 if (!does_file_exist(MONDO_CFG_FILE_STUB)) { 345 /* Doing that allow us to remain compatible with pre-2.2.5 versions */ 346 log_msg(2, "pre-2.2.4 compatible mode on"); 347 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary 348 run_program_and_log_output(command, TRUE); 349 mr_free(command); 350 if (!does_file_exist(MONDO_CFG_FILE_STUB)) { 351 fatal_error 352 ("Please reinsert the disk/CD and try again."); 353 } 354 } 355 } 356 } 357 if (does_file_exist(MONDO_CFG_FILE_STUB)) { 358 log_msg(1, "gcffa --- great! We've got the config file"); 359 tmp1 = call_program_and_get_last_line_of_output("pwd"); 360 mr_asprintf(tmp, "%s/%s", tmp1, MONDO_CFG_FILE_STUB); 361 mr_asprintf(command, "cp -f %s %s", tmp, cfg_file); 362 log_it("%s",command); 363 if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) { 364 log_msg(1, 365 "... but an error occurred when I tried to move it to %s", 366 cfg_file); 367 } else { 368 log_msg(1, "... and I moved it successfully to %s", cfg_file); 369 } 370 mr_free(command); 371 372 mr_asprintf(command, "cp -f %s/%s %s", tmp1, MOUNTLIST_FNAME_STUB, mountlist_file); 373 mr_free(tmp1); 374 log_it("%s",command); 375 if (extract_mountlist_stub) { 376 if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) { 377 log_msg(1, "Failed to get mountlist"); 378 } else { 379 log_msg(1, "Got mountlist too"); 380 mr_free(command); 381 mr_asprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname); 382 if (run_program_and_log_output(command, 1)) { 383 log_msg(1, "Failed to copy mountlist to /tmp"); 384 } else { 385 log_msg(1, "Copied mountlist to /tmp as well OK"); 386 mr_free(command); 387 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB); 388 run_program_and_log_output(command, 1); 389 } 390 } 391 } 392 mr_free(command); 393 mr_free(tmp); 394 } 395 396 run_program_and_log_output("umount -d " MNT_CDROM, FALSE); 397 if (!does_file_exist(cfg_file)) { 398 log_it("%s",cfg_file); 399 log_msg(1, "%s not found", cfg_file); 400 log_to_screen("Oh dear. Unable to recover configuration file from boot disk"); 401 return (1); 402 } 403 404 log_to_screen("Recovered mondorestore.cfg"); 405 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) { 406 log_to_screen("...but not mountlist.txt - a pity, really..."); 407 } else { 408 /* Is this code really useful ??? */ 409 if (extract_mountlist_stub) { 410 mr_asprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB); 411 run_program_and_log_output(command, FALSE); 412 mr_free(command); 413 } 414 } 415 416 mr_asprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB); 417 mr_free(cfg_file); 418 419 run_program_and_log_output(command, FALSE); 420 mr_free(command); 421 422 if (extract_mountlist_stub) { 423 mr_asprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB); 424 run_program_and_log_output(command, FALSE); 425 mr_free(command); 426 } 427 mr_free(mountlist_file); 428 429 mr_asprintf(command, "cp -f etc/raidtab /etc/"); 430 run_program_and_log_output(command, FALSE); 431 mr_free(command); 432 433 if (extract_i_want_my_lvm) { 434 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB); 435 run_program_and_log_output(command, FALSE); 436 mr_free(command); 437 } 438 g_backup_media_type = bkpinfo->backup_media_type; 439 return (retval); 440 } 441 442 /************************************************************************** 443 *END_GET_CFG_FILE_FROM_ARCHIVE * 444 **************************************************************************/ 172 445 173 446 … … 642 915 /** add mallocs **/ 643 916 char value[MAX_STR_LEN]; 917 char *tmp = NULL; 644 918 char *tmp1 = NULL; 645 919 char *envtmp1 = NULL; … … 683 957 run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1); 684 958 } 685 if (does_file_exist( MNT_CDROM"/archives/filelist.0")) {959 if (does_file_exist(ARCHIVES_PATH "/filelist.0")) { 686 960 bkpinfo->backup_media_type = cdr; 687 961 run_program_and_log_output("umount -d "MNT_CDROM, 1); … … 1284 1558 1285 1559 /** 1286 * Install the user's boot loader in the MBR.1287 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.1288 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.1289 * @return 0 for success, nonzero for failure.1290 */1291 int run_boot_loader(bool offer_to_hack_scripts)1292 {1293 int res;1294 int retval = 0;1295 1296 /** malloc *******/1297 char *device = NULL;1298 char *disk = NULL;1299 char *name = NULL;1300 char *type = NULL;1301 char *cmd = NULL;1302 1303 malloc_string(device);1304 malloc_string(name);1305 malloc_string(type);1306 1307 /* In order to have a working bootloader, we need to have all devices1308 * ready in the chroot. If they are not there (udev) then copy them from1309 * the current /dev location1310 */1311 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);1312 run_program_and_log_output(cmd, 3);1313 mr_free(cmd);1314 1315 backup_crucial_file(MNT_RESTORING, "/etc/fstab");1316 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");1317 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");1318 backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");1319 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");1320 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");1321 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");1322 backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");1323 backup_crucial_file(MNT_RESTORING, "/etc/mtab");1324 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);1325 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);1326 read_cfg_var(g_mondo_cfg_file, "boot-type", type);1327 log_msg(2, "run_boot_loader: device='%s', name='%s', type='%s'", device, name, type);1328 sync();1329 1330 offer_to_make_initrd();1331 1332 disk = truncate_to_drive_name(device);1333 if (strcmp(type,"BIOS") == 0) {1334 // Force installation of a MBR bootloader brought by mindi on the disk1335 // in case none was available and we then start from a partition1336 log_msg(2, "Reinstalling mbr.bin on %s", disk);1337 mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/mbr.bin of=%s &> /dev/null",disk);1338 } else {1339 // Same for GPT1340 log_msg(2, "Reinstalling gptmbr.bin on %s", disk);1341 mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/gptmbr.bin of=%s &> /dev/null",disk);1342 }1343 1344 // Now reinstall bootloader1345 if (!strcmp(name, "LILO")) {1346 res = run_lilo(offer_to_hack_scripts);1347 } else if (!strcmp(name, "ELILO")) {1348 res = run_elilo(offer_to_hack_scripts);1349 } else if (!strcmp(name, "GRUB")) {1350 res = run_grub(offer_to_hack_scripts, device);1351 } else if (!strcmp(name, "RAW")) {1352 res = run_raw_mbr(offer_to_hack_scripts, device);1353 }1354 #ifdef __FreeBSD__1355 else if (!strcmp(name, "BOOT0")) {1356 mr_asprintf(tmp, "boot0cfg -B %s", device);1357 res = run_program_and_log_output(tmp, FALSE);1358 paranoid_free(tmp);1359 } else {1360 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);1361 if (!system(tmp)) {1362 mr_free(tmp);1363 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);1364 res = run_program_and_log_output(tmp, 3);1365 } else {1366 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");1367 }1368 mr_free(tmp);1369 }1370 #else1371 else {1372 log_to_screen1373 ("Unable to determine type of boot loader. Defaulting to LILO.");1374 res = run_lilo(offer_to_hack_scripts);1375 }1376 #endif1377 retval += res;1378 if (res) {1379 log_to_screen("Your boot loader returned an error");1380 } else {1381 log_to_screen("Your boot loader ran OK");1382 }1383 paranoid_free(device);1384 paranoid_free(name);1385 return (retval);1386 }1387 1388 /**************************************************************************1389 *END_ RUN_BOOT_LOADER *1390 **************************************************************************/1391 1392 1393 1394 /**1395 1560 * Attempt to find the user's editor. 1396 1561 * @return The editor found ("vi" if none could be found). … … 1417 1582 return (output); 1418 1583 } 1584 1585 1586 1587 1588 /** 1589 * Install LILO on the user's boot drive (determined by /etc/lilo.conf). 1590 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them. 1591 * @return 0 for success, nonzero for failure. 1592 */ 1593 int run_lilo(bool offer_to_run_stablilo) 1594 { 1595 /** malloc **/ 1596 char *command = NULL; 1597 char *tmp = NULL; 1598 char *editor = NULL; 1599 1600 int res; 1601 int done; 1602 bool run_lilo_M = FALSE; 1603 1604 if (!run_program_and_log_output 1605 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) { 1606 run_lilo_M = TRUE; 1607 } 1608 1609 if (offer_to_run_stablilo 1610 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) 1611 1612 /* interactive mode */ 1613 { 1614 mvaddstr_and_log_it(g_currentY, 1615 0, 1616 "Modifying fstab and lilo.conf, and running LILO... "); 1617 mr_asprintf(command, "mr-stablilo-me"); 1618 res = run_program_and_log_output(command, 3); 1619 mr_free(command); 1620 1621 if (res) { 1622 popup_and_OK 1623 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."); 1624 for (done = FALSE; !done;) { 1625 editor = find_my_editor(); 1626 if (editor == NULL) { 1627 popup_and_OK("No editor found. You won't be able to edit conf files"); 1628 } else { 1629 if (!g_text_mode) { 1630 newtSuspend(); 1631 } 1632 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor); 1633 paranoid_system(tmp); 1634 mr_free(tmp); 1635 1636 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor); 1637 paranoid_system(tmp); 1638 mr_free(tmp); 1639 mr_free(editor); 1640 1641 if (!g_text_mode) { 1642 newtResume(); 1643 } 1644 // newtCls(); 1645 if (ask_me_yes_or_no("Edit them again?")) { 1646 continue; 1647 } 1648 } 1649 mr_free(editor); 1650 1651 res = run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 3); 1652 if (res) { 1653 res = run_program_and_log_output("chroot " MNT_RESTORING " lilo", 3); 1654 } 1655 if (res) { 1656 done = ask_me_yes_or_no("LILO failed. Re-edit system files?"); 1657 } else { 1658 done = TRUE; 1659 } 1660 } 1661 } else { 1662 log_to_screen("lilo.conf and fstab were modified OK"); 1663 } 1664 } else 1665 /* nuke mode */ 1666 { 1667 mvaddstr_and_log_it(g_currentY, 1668 0, 1669 "Running LILO... "); 1670 res = 1671 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 1672 3); 1673 if (res) { 1674 res = 1675 run_program_and_log_output("chroot " MNT_RESTORING " lilo", 1676 3); 1677 } 1678 if (res) { 1679 mvaddstr_and_log_it(g_currentY++, 74, "Failed."); 1680 log_to_screen 1681 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."); 1682 } else { 1683 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1684 } 1685 } 1686 if (run_lilo_M) { 1687 run_program_and_log_output("chroot " MNT_RESTORING 1688 " lilo -M /dev/hda", 3); 1689 run_program_and_log_output("chroot " MNT_RESTORING 1690 " lilo -M /dev/sda", 3); 1691 } 1692 return (res); 1693 } 1694 1695 /************************************************************************** 1696 *END_RUN_LILO * 1697 **************************************************************************/ 1698 1699 1700 /** 1701 * Install a raw MBR onto @p bd. 1702 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them. 1703 * @param bd The device to copy the stored MBR to. 1704 * @return 0 for success, nonzero for failure. 1705 */ 1706 int run_raw_mbr(bool offer_to_hack_scripts, char *bd) 1707 { 1708 /** malloc **/ 1709 char *command = NULL; 1710 char *boot_device = NULL; 1711 char *tmp = NULL; 1712 char *editor; 1713 int res; 1714 int done; 1715 1716 malloc_string(boot_device); 1717 assert_string_is_neither_NULL_nor_zerolength(bd); 1718 1719 strcpy(boot_device, bd); 1720 1721 if (offer_to_hack_scripts 1722 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) { 1723 /* interactive mode */ 1724 mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and restoring MBR... "); 1725 for (done = FALSE; !done;) { 1726 popup_and_OK("You will now edit fstab"); 1727 editor = find_my_editor(); 1728 if (editor == NULL) { 1729 popup_and_OK("No editor found. You won't be able to edit conf files"); 1730 } else { 1731 if (!g_text_mode) { 1732 newtSuspend(); 1733 } 1734 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor); 1735 1736 paranoid_system(tmp); 1737 mr_free(tmp); 1738 if (!g_text_mode) { 1739 newtResume(); 1740 } 1741 } 1742 mr_free(editor); 1743 1744 popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4); 1745 mr_asprintf(command, "mr-stabraw-me %s", boot_device); 1746 res = run_program_and_log_output(command, 3); 1747 mr_free(command); 1748 1749 if (res) { 1750 done = ask_me_yes_or_no("Modifications failed. Re-try?"); 1751 } else { 1752 done = TRUE; 1753 } 1754 } 1755 } else { 1756 /* nuke mode */ 1757 mr_asprintf(command, "mr-raw %s /"MOUNTLIST_FNAME_STUB, boot_device); 1758 log_msg(2, "run_raw_mbr() --- command='%s'", command); 1759 1760 mvaddstr_and_log_it(g_currentY, 0, "Restoring MBR... "); 1761 res = run_program_and_log_output(command, 3); 1762 mr_free(command); 1763 } 1764 if (res) { 1765 mvaddstr_and_log_it(g_currentY++, 74, "Failed."); 1766 log_to_screen("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE); 1767 } else { 1768 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1769 } 1770 paranoid_free(boot_device); 1771 return (res); 1772 } 1773 1774 /************************************************************************** 1775 *END_RUN_RAW_MBR * 1776 **************************************************************************/ 1419 1777 1420 1778 … … 1465 1823 popup_and_OK("The mountlist was changed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install"); 1466 1824 } 1467 editor = find_my_editor() );1825 editor = find_my_editor(); 1468 1826 if (editor == NULL) { 1469 1827 popup_and_OK("No editor found. You won't be able to edit conf files"); … … 1644 2002 1645 2003 1646 /** 1647 * Install LILO on the user's boot drive (determined by /etc/lilo.conf). 1648 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them. 2004 2005 /** 2006 * Install the user's boot loader in the MBR. 2007 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported. 2008 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them. 1649 2009 * @return 0 for success, nonzero for failure. 1650 2010 */ 1651 int run_ lilo(bool offer_to_run_stablilo)2011 int run_boot_loader(bool offer_to_hack_scripts) 1652 2012 { 1653 /** malloc **/1654 char *command = NULL;1655 char *tmp = NULL;1656 char *editor = NULL;1657 1658 2013 int res; 1659 int done; 1660 bool run_lilo_M = FALSE; 1661 1662 if (!run_program_and_log_output 1663 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) { 1664 run_lilo_M = TRUE; 1665 } 1666 1667 if (offer_to_run_stablilo 1668 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) 1669 1670 /* interactive mode */ 1671 { 1672 mvaddstr_and_log_it(g_currentY, 1673 0, 1674 "Modifying fstab and lilo.conf, and running LILO... "); 1675 mr_asprintf(command, "mr-stablilo-me"); 1676 res = run_program_and_log_output(command, 3); 1677 mr_free(command); 1678 1679 if (res) { 1680 popup_and_OK 1681 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."); 1682 for (done = FALSE; !done;) { 1683 editor = find_my_editor(); 1684 if (editor == NULL) { 1685 popup_and_OK("No editor found. You won't be able to edit conf files"); 1686 } else { 1687 if (!g_text_mode) { 1688 newtSuspend(); 1689 } 1690 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor); 1691 paranoid_system(tmp); 1692 mr_free(tmp); 1693 1694 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor); 1695 paranoid_system(tmp); 1696 mr_free(tmp); 1697 mr_free(editor); 1698 1699 if (!g_text_mode) { 1700 newtResume(); 1701 } 1702 // newtCls(); 1703 if (ask_me_yes_or_no("Edit them again?")) { 1704 continue; 1705 } 1706 } 1707 mr_free(editor); 1708 1709 res = run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 3); 1710 if (res) { 1711 res = run_program_and_log_output("chroot " MNT_RESTORING " lilo", 3); 1712 } 1713 if (res) { 1714 done = ask_me_yes_or_no("LILO failed. Re-edit system files?"); 1715 } else { 1716 done = TRUE; 1717 } 1718 } 2014 int retval = 0; 2015 2016 /** malloc *******/ 2017 char *device = NULL; 2018 char *disk = NULL; 2019 char *name = NULL; 2020 char *type = NULL; 2021 char *cmd = NULL; 2022 2023 malloc_string(device); 2024 malloc_string(name); 2025 malloc_string(type); 2026 2027 /* In order to have a working bootloader, we need to have all devices 2028 * ready in the chroot. If they are not there (udev) then copy them from 2029 * the current /dev location 2030 */ 2031 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING); 2032 run_program_and_log_output(cmd, 3); 2033 mr_free(cmd); 2034 2035 backup_crucial_file(MNT_RESTORING, "/etc/fstab"); 2036 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst"); 2037 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg"); 2038 backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg"); 2039 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf"); 2040 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf"); 2041 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map"); 2042 backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map"); 2043 backup_crucial_file(MNT_RESTORING, "/etc/mtab"); 2044 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device); 2045 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name); 2046 read_cfg_var(g_mondo_cfg_file, "boot-type", type); 2047 log_msg(2, "run_boot_loader: device='%s', name='%s', type='%s'", device, name, type); 2048 sync(); 2049 2050 offer_to_make_initrd(); 2051 2052 disk = truncate_to_drive_name(device); 2053 if (strcmp(type,"BIOS") == 0) { 2054 // Force installation of a MBR bootloader brought by mindi on the disk 2055 // in case none was available and we then start from a partition 2056 log_msg(2, "Reinstalling mbr.bin on %s", disk); 2057 mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/mbr.bin of=%s &> /dev/null",disk); 2058 } else { 2059 // Same for GPT 2060 log_msg(2, "Reinstalling gptmbr.bin on %s", disk); 2061 mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/gptmbr.bin of=%s &> /dev/null",disk); 2062 } 2063 2064 // Now reinstall bootloader 2065 if (!strcmp(name, "LILO")) { 2066 res = run_lilo(offer_to_hack_scripts); 2067 } else if (!strcmp(name, "ELILO")) { 2068 res = run_elilo(offer_to_hack_scripts); 2069 } else if (!strcmp(name, "GRUB")) { 2070 res = run_grub(offer_to_hack_scripts, device); 2071 } else if (!strcmp(name, "RAW")) { 2072 res = run_raw_mbr(offer_to_hack_scripts, device); 2073 } 2074 #ifdef __FreeBSD__ 2075 else if (!strcmp(name, "BOOT0")) { 2076 mr_asprintf(tmp, "boot0cfg -B %s", device); 2077 res = run_program_and_log_output(tmp, FALSE); 2078 paranoid_free(tmp); 2079 } else { 2080 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device); 2081 if (!system(tmp)) { 2082 mr_free(tmp); 2083 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device); 2084 res = run_program_and_log_output(tmp, 3); 1719 2085 } else { 1720 log_to_screen("lilo.conf and fstab were modified OK"); 1721 } 1722 } else 1723 /* nuke mode */ 1724 { 1725 mvaddstr_and_log_it(g_currentY, 1726 0, 1727 "Running LILO... "); 1728 res = 1729 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 1730 3); 1731 if (res) { 1732 res = 1733 run_program_and_log_output("chroot " MNT_RESTORING " lilo", 1734 3); 1735 } 1736 if (res) { 1737 mvaddstr_and_log_it(g_currentY++, 74, "Failed."); 1738 log_to_screen 1739 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."); 1740 } else { 1741 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1742 } 1743 } 1744 if (run_lilo_M) { 1745 run_program_and_log_output("chroot " MNT_RESTORING 1746 " lilo -M /dev/hda", 3); 1747 run_program_and_log_output("chroot " MNT_RESTORING 1748 " lilo -M /dev/sda", 3); 1749 } 1750 return (res); 2086 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up."); 2087 } 2088 mr_free(tmp); 2089 } 2090 #else 2091 else { 2092 log_to_screen 2093 ("Unable to determine type of boot loader. Defaulting to LILO."); 2094 res = run_lilo(offer_to_hack_scripts); 2095 } 2096 #endif 2097 retval += res; 2098 if (res) { 2099 log_to_screen("Your boot loader returned an error"); 2100 } else { 2101 log_to_screen("Your boot loader ran OK"); 2102 } 2103 paranoid_free(device); 2104 paranoid_free(name); 2105 return (retval); 1751 2106 } 1752 2107 1753 2108 /************************************************************************** 1754 *END_RUN_LILO * 1755 **************************************************************************/ 1756 1757 1758 /** 1759 * Install a raw MBR onto @p bd. 1760 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them. 1761 * @param bd The device to copy the stored MBR to. 1762 * @return 0 for success, nonzero for failure. 1763 */ 1764 int run_raw_mbr(bool offer_to_hack_scripts, char *bd) 1765 { 1766 /** malloc **/ 1767 char *command = NULL; 1768 char *boot_device = NULL; 1769 char *tmp = NULL; 1770 char *editor; 1771 int res; 1772 int done; 1773 1774 malloc_string(boot_device); 1775 assert_string_is_neither_NULL_nor_zerolength(bd); 1776 1777 strcpy(boot_device, bd); 1778 1779 if (offer_to_hack_scripts 1780 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) { 1781 /* interactive mode */ 1782 mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and restoring MBR... "); 1783 for (done = FALSE; !done;) { 1784 popup_and_OK("You will now edit fstab"); 1785 editor = find_my_editor()); 1786 if (editor == NULL) { 1787 popup_and_OK("No editor found. You won't be able to edit conf files"); 1788 } else { 1789 if (!g_text_mode) { 1790 newtSuspend(); 1791 } 1792 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor); 1793 1794 paranoid_system(tmp); 1795 mr_free(tmp); 1796 if (!g_text_mode) { 1797 newtResume(); 1798 } 1799 } 1800 mr_free(editor); 1801 1802 popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4); 1803 mr_asprintf(command, "mr-stabraw-me %s", boot_device); 1804 res = run_program_and_log_output(command, 3); 1805 mr_free(command); 1806 1807 if (res) { 1808 done = ask_me_yes_or_no("Modifications failed. Re-try?"); 1809 } else { 1810 done = TRUE; 1811 } 1812 } 1813 } else { 1814 /* nuke mode */ 1815 mr_asprintf(command, "mr-raw %s /"MOUNTLIST_FNAME_STUB, boot_device); 1816 log_msg(2, "run_raw_mbr() --- command='%s'", command); 1817 1818 mvaddstr_and_log_it(g_currentY, 0, "Restoring MBR... "); 1819 res = run_program_and_log_output(command, 3); 1820 mr_free(command); 1821 } 1822 if (res) { 1823 mvaddstr_and_log_it(g_currentY++, 74, "Failed."); 1824 log_to_screen("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE); 1825 } else { 1826 mvaddstr_and_log_it(g_currentY++, 74, "Done."); 1827 } 1828 paranoid_free(boot_device); 1829 return (res); 1830 } 1831 1832 /************************************************************************** 1833 *END_RUN_RAW_MBR * 2109 *END_ RUN_BOOT_LOADER * 1834 2110 **************************************************************************/ 1835 2111 … … 2068 2344 *END_UNMOUNT_ALL_DEVICES * 2069 2345 **************************************************************************/ 2070 2071 /**2072 * Extract mondorestore.cfg and the mountlist from the tape inserted2073 * to the ./tmp/ directory.2074 * @param dev The tape device to read from.2075 * @return 0 for success, nonzero for failure.2076 */2077 int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)2078 {2079 char *command = NULL;2080 int res = 0;2081 2082 if (bkpinfo->use_obdr) {2083 skip_obdr();2084 } else {2085 // TODO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.02086 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);2087 }2088 2089 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);2090 log_msg(2, "command = '%s'", command);2091 res = run_program_and_log_output(command, -1);2092 mr_free(command);2093 2094 if (res != 0) {2095 if (does_file_exist(MONDO_CFG_FILE_STUB)) {2096 res = 0;2097 } else {2098 /* Doing that allow us to remain compatible with pre-2.2.5 versions */2099 log_msg(2, "pre-2.2.4 compatible mode on");2100 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);2101 log_msg(2, "command = '%s'", command);2102 res = run_program_and_log_output(command, -1);2103 mr_free(command);2104 if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {2105 res = 0;2106 }2107 }2108 }2109 paranoid_free(command);2110 return (res);2111 }2112 2113 2114 /**2115 * Get the configuration file from the tape, or CD.2116 * @param bkpinfo The backup information structure. Fields used:2117 * - @c bkpinfo->backup_media_type2118 * - @c bkpinfo->media_device2119 * - @c bkpinfo->tmpdir2120 * @return 0 for success, nonzero for failure.2121 */2122 int get_cfg_file_from_archive()2123 {2124 int retval = 0;2125 2126 /** malloc *****/2127 char *command = NULL;2128 char *cfg_file = NULL;2129 char *tmp = NULL;2130 char *tmp1 = NULL;2131 char *mountpt = NULL;2132 char *mountlist_file = NULL;2133 bool extract_mountlist_stub = FALSE;2134 bool extract_i_want_my_lvm = FALSE;2135 2136 bool try_plan_B;2137 2138 assert(bkpinfo != NULL);2139 log_msg(2, "gcffa --- starting");2140 log_to_screen("I'm thinking...");2141 mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);2142 if (chdir(bkpinfo->tmpdir)) {2143 // FIXME2144 }2145 mr_asprintf(cfg_file, "%s", MONDO_CFG_FILE_STUB);2146 unlink(cfg_file); // cfg_file[] is missing the '/' at the start, FYI, by intent2147 mr_free(cfg_file);2148 2149 unlink(FILELIST_FULL_STUB);2150 unlink(BIGGIELIST_TXT_STUB);2151 mr_asprintf(command, "mkdir -p %s", mountpt);2152 run_program_and_log_output(command, FALSE);2153 mr_free(command);2154 2155 mr_asprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);2156 mr_asprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);2157 log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);2158 mr_free(mountpt);2159 2160 if (!does_file_exist(cfg_file)) {2161 log_msg(2, "gcffa --- we don't have cfg file yet.");2162 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {2163 try_plan_B = TRUE;2164 } else {2165 log_msg(2, "gcffa --- calling mount_media now :)");2166 if (!mount_media(MNT_CDROM)) {2167 log_msg(2, "gcffa --- managed to mount CD; so, no need for Plan B");2168 try_plan_B = FALSE;2169 } else {2170 try_plan_B = TRUE;2171 }2172 if (what_number_cd_is_this() > 1) {2173 insist_on_this_cd_number((g_current_media_number = 1));2174 }2175 }2176 if (try_plan_B) {2177 log_msg(2, "gcffa --- OK, switching to Plan B");2178 if (chdir(bkpinfo->tmpdir)) {2179 // FIXME2180 }2181 run_program_and_log_output("mkdir -p tmp", FALSE);2182 2183 if (bkpinfo->media_device == NULL) {2184 mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0");2185 log_msg(2, "media_device is blank; assuming %s", bkpinfo->media_device);2186 }2187 mr_asprintf(tmp, "%s", bkpinfo->media_device);2188 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {2189 mr_free(bkpinfo->media_device);2190 mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0");2191 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {2192 mr_free(bkpinfo->media_device);2193 mr_asprintf(bkpinfo->media_device, "%s", "/dev/osst0");2194 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {2195 mr_free(bkpinfo->media_device);2196 mr_asprintf(bkpinfo->media_device, "%s", "/dev/ht0");2197 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {2198 log_msg(3, "I tried lots of devices but none worked.");2199 mr_free(bkpinfo->media_device);2200 }2201 }2202 }2203 }2204 if (bkpinfo->media_device == NULL) {2205 bkpinfo->media_device = tmp;2206 } else {2207 mr_free(tmp);2208 }2209 2210 if (!does_file_exist("tmp/mondorestore.cfg")) {2211 log_to_screen("Cannot find config info on media");2212 return (1);2213 }2214 } else {2215 if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {2216 extract_mountlist_stub = FALSE;2217 } else {2218 extract_mountlist_stub = TRUE;2219 }2220 if (does_file_exist("/"IWANTMYLVM_STUB)) {2221 extract_i_want_my_lvm = FALSE;2222 } else {2223 extract_i_want_my_lvm = TRUE;2224 }2225 2226 log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");2227 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary2228 run_program_and_log_output(command, TRUE);2229 mr_free(command);2230 2231 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {2232 /* Doing that allow us to remain compatible with pre-2.2.5 versions */2233 log_msg(2, "pre-2.2.4 compatible mode on");2234 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary2235 run_program_and_log_output(command, TRUE);2236 mr_free(command);2237 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {2238 fatal_error2239 ("Please reinsert the disk/CD and try again.");2240 }2241 }2242 }2243 }2244 if (does_file_exist(MONDO_CFG_FILE_STUB)) {2245 log_msg(1, "gcffa --- great! We've got the config file");2246 tmp1 = call_program_and_get_last_line_of_output("pwd");2247 mr_asprintf(tmp, "%s/%s", tmp1, MONDO_CFG_FILE_STUB);2248 mr_asprintf(command, "cp -f %s %s", tmp, cfg_file);2249 log_it("%s",command);2250 if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {2251 log_msg(1,2252 "... but an error occurred when I tried to move it to %s",2253 cfg_file);2254 } else {2255 log_msg(1, "... and I moved it successfully to %s", cfg_file);2256 }2257 mr_free(command);2258 2259 mr_asprintf(command, "cp -f %s/%s %s", tmp1, MOUNTLIST_FNAME_STUB, mountlist_file);2260 mr_free(tmp1);2261 log_it("%s",command);2262 if (extract_mountlist_stub) {2263 if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {2264 log_msg(1, "Failed to get mountlist");2265 } else {2266 log_msg(1, "Got mountlist too");2267 mr_free(command);2268 mr_asprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname);2269 if (run_program_and_log_output(command, 1)) {2270 log_msg(1, "Failed to copy mountlist to /tmp");2271 } else {2272 log_msg(1, "Copied mountlist to /tmp as well OK");2273 mr_free(command);2274 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);2275 run_program_and_log_output(command, 1);2276 }2277 }2278 }2279 mr_free(command);2280 mr_free(tmp);2281 }2282 2283 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);2284 if (!does_file_exist(cfg_file)) {2285 log_it("%s",cfg_file);2286 log_msg(1, "%s not found", cfg_file);2287 log_to_screen("Oh dear. Unable to recover configuration file from boot disk");2288 return (1);2289 }2290 2291 log_to_screen("Recovered mondorestore.cfg");2292 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {2293 log_to_screen("...but not mountlist.txt - a pity, really...");2294 } else {2295 /* Is this code really useful ??? */2296 if (extract_mountlist_stub) {2297 mr_asprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);2298 run_program_and_log_output(command, FALSE);2299 mr_free(command);2300 }2301 }2302 2303 mr_asprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);2304 mr_free(cfg_file);2305 2306 run_program_and_log_output(command, FALSE);2307 mr_free(command);2308 2309 if (extract_mountlist_stub) {2310 mr_asprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);2311 run_program_and_log_output(command, FALSE);2312 mr_free(command);2313 }2314 mr_free(mountlist_file);2315 2316 mr_asprintf(command, "cp -f etc/raidtab /etc/");2317 run_program_and_log_output(command, FALSE);2318 mr_free(command);2319 2320 if (extract_i_want_my_lvm) {2321 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);2322 run_program_and_log_output(command, FALSE);2323 mr_free(command);2324 }2325 g_backup_media_type = bkpinfo->backup_media_type;2326 return (retval);2327 }2328 2329 /**************************************************************************2330 *END_GET_CFG_FILE_FROM_ARCHIVE *2331 **************************************************************************/2332 2333 2346 /* @} - end restoreUtilityGroup */ 2334 2347 -
branches/3.3/mondo/src/mondorestore/mondorestore.c
r3876 r3879 13 13 #include "mr_mem.h" 14 14 #include "mr_file.h" 15 #include "../common/mondostructures.h" 16 #include "../common/libmondo.h" 17 #include "mr-externs.h" 15 #include "mondostructures.h" 18 16 #include "mondorestore.h" 19 17 #include "mr_msg.h" … … 21 19 #include "mondo-rstr-tools-EXT.h" 22 20 #include "libmondo-mountlist-EXT.h" 21 #include "libmondo-tools-EXT.h" 22 #include "libmondo-gui-EXT.h" 23 #include "libmondo-devices-EXT.h" 24 #include "libmondo-fork-EXT.h" 25 #include "libmondo-string-EXT.h" 26 #include "libmondo-archive-EXT.h" 27 #include "libmondo-raid-EXT.h" 28 #include "libmondo-filelist-EXT.h" 29 #include "libmondo-files-EXT.h" 30 #include "libmondo-stream-EXT.h" 31 #include "libmondo-cli-EXT.h" 23 32 #include "newt-specific-EXT.h" 24 33 25 34 extern void wait_until_software_raids_are_prepped(char *, int); 26 35 extern void twenty_seconds_til_yikes(void); 36 // in mondo-prep.c 37 extern void resize_mountlist_proportionately_to_suit_new_drives(struct mountlist_itself *); 38 extern int format_everything(struct mountlist_itself *, bool , struct raidlist_itself *); 39 extern int partition_everything(struct mountlist_itself *); 40 extern int fput_string_one_char_at_a_time(FILE *, char *); 41 extern int do_my_funky_lvm_stuff(bool, bool ); 42 extern int stop_all_raid_devices(struct mountlist_itself *); 43 44 // in mondo-rstr-newt.c 45 extern int edit_mountlist(char *, struct mountlist_itself *, struct raidlist_itself *); 46 47 // from libmondo-devices.c 48 extern bool g_restoring_live_from_cd; 49 extern bool g_restoring_live_from_netfs; 50 51 extern int g_currentY; 27 52 28 53 /* We don't have a cleanup function yet */ … … 53 78 extern int g_partition_table_locked_up; 54 79 extern int g_noof_rows; 55 56 extern int partition_everything(struct mountlist_itself *mountlist); 57 extern int handle_incoming_parameters(int argc, char *argv[]); 80 extern int g_current_media_number; 58 81 59 82 /** … … 121 144 char *g_getfattr; 122 145 146 extern long g_current_progress; 147 extern int g_currentY; 148 extern int g_current_media_number; 149 150 123 151 /* @} - end of "Restore-Time Globals" in globalGroup */ 124 152 125 126 127 extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,128 char direction);129 153 130 154 … … 580 604 just_changed_cds = FALSE; 581 605 log_msg(3, "I'll continue to scan this CD for bigfiles to be restored."); 582 } else if (does_file_exist( MNT_CDROM "/archives/NOT-THE-LAST")) {606 } else if (does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST")) { 583 607 insist_on_this_cd_number(++g_current_media_number); 584 608 log_to_screen("Restoring from %s #%d", mds, g_current_media_number); … … 691 715 paranoid_free(command); 692 716 693 mr_asprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld", current_tarball_number);717 mr_asprintf(filelist_name, ARCHIVES_PATH "/filelist.%ld", current_tarball_number); 694 718 if (length_of_file(filelist_name) <= 2) { 695 719 log_msg(2, "There are _zero_ files in filelist '%s'", filelist_name); … … 726 750 if (filelist == NULL || matches > 0) { 727 751 if (g_getfattr) { 728 mr_asprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);752 mr_asprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ, ARCHIVES_PATH, current_tarball_number); 729 753 } 730 754 if (g_getfacl) { 731 mr_asprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);755 mr_asprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, ARCHIVES_PATH, current_tarball_number); 732 756 } 733 757 if (strstr(tarball_fname, ".bz2")) { … … 922 946 mr_free(progress_str); 923 947 924 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2", current_tarball_number);948 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.bz2", current_tarball_number); 925 949 if (!does_file_exist(tarball_fname)) { 926 950 mr_free(tarball_fname); 927 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz", current_tarball_number);951 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.gz", current_tarball_number); 928 952 } 929 953 if (!does_file_exist(tarball_fname)) { 930 954 mr_free(tarball_fname); 931 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzma", current_tarball_number);955 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.lzma", current_tarball_number); 932 956 } 933 957 if (!does_file_exist(tarball_fname)) { 934 958 mr_free(tarball_fname); 935 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo", current_tarball_number);959 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.lzo", current_tarball_number); 936 960 } 937 961 if (!does_file_exist(tarball_fname)) { 938 962 mr_free(tarball_fname); 939 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.", current_tarball_number);963 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.", current_tarball_number); 940 964 } 941 965 if (!does_file_exist(tarball_fname)) { 942 966 mr_free(tarball_fname); 943 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2", current_tarball_number);967 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.star.bz2", current_tarball_number); 944 968 } 945 969 if (!does_file_exist(tarball_fname)) { 946 970 mr_free(tarball_fname); 947 mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.", current_tarball_number);971 mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.star.", current_tarball_number); 948 972 } 949 973 if (!does_file_exist(tarball_fname)) { … … 954 978 return (0); 955 979 } 956 if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST") 957 || system("find " MNT_CDROM 958 "/archives/slice* > /dev/null 2> /dev/null") == 980 if (!does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST") 981 || system("find " ARCHIVES_PATH "/slice* > /dev/null 2> /dev/null") == 959 982 0) { 960 983 break; -
branches/3.3/mondo/test/Makefile.am
r3614 r3879 1 AM_CPPFLAGS = -DMONDO_CONF_DIR=\"$(sysconfdir)/mondo\" -I${top_builddir}/src/include -I${top_builddir}/src/common 1 AM_CPPFLAGS = -DMONDO_CONF_DIR=\"$(sysconfdir)/mondo\" -I${top_builddir}/src/include -I${top_builddir}/src/common -I${top_builddir}/src/mondoarchive -I${top_builddir}/src/mondorestore 2 2 AUTOMAKE_OPTIONS = subdir-objects 3 3 -
branches/3.3/mondo/test/test-mountlist.c
r3825 r3879 8 8 #include "my-stuff.h" 9 9 #include "mr_mem.h" 10 #include "../common/mondostructures.h" 11 #include "../common/libmondo.h" 12 #include "../mondorestore/mondorestore.h" 13 #include "../mondorestore/mr-externs.h" 14 #include "../mondorestore/libmondo-mountlist-EXT.h" 15 10 #include "mondostructures.h" 11 #include "mondorestore.h" 12 #include "libmondo-mountlist-EXT.h" 13 #include "libmondo-raid-EXT.h" 14 #include "libmondo-tools-EXT.h" 15 #include "newt-specific-EXT.h" 16 extern void resize_mountlist_proportionately_to_suit_new_drives(struct mountlist_itself *); 17 extern int edit_mountlist(char *, struct mountlist_itself *, struct raidlist_itself *); 16 18 17 19 #define RAIDTAB_TEST "/tmp/raidtab" -
branches/3.3/mondo/test/test-truncname.c
r3819 r3879 8 8 #include "my-stuff.h" 9 9 #include "mr_mem.h" 10 #include "../common/mondostructures.h" 11 #include "../common/libmondo.h" 12 #include "../mondoarchive/mondoarchive.h" 10 #include "mondostructures.h" 11 #include "mondoarchive.h" 12 #include "libmondo-tools-EXT.h" 13 #include "newt-specific-EXT.h" 13 14 14 15 extern void twenty_seconds_til_yikes(void);
Note:
See TracChangeset
for help on using the changeset viewer.