Changeset 3879 in MondoRescue for branches/3.3/mondo/src/common/libmondo-devices.c
- Timestamp:
- Mar 9, 2024, 3:10:04 AM (4 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mondo/src/common/libmondo-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);
Note:
See TracChangeset
for help on using the changeset viewer.