1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 29 /* 30 * rmf_misc.c : 31 * Miscelleneous routines for rmformat. 32 */ 33 34 #include <sys/types.h> 35 #include <stdio.h> 36 #include <sys/mnttab.h> 37 #include <volmgt.h> 38 #include <sys/dkio.h> 39 #include <sys/fdio.h> 40 #include <sys/vtoc.h> 41 #include <sys/termios.h> 42 #include <sys/mount.h> 43 #include <ctype.h> 44 #include <signal.h> 45 #include <sys/wait.h> 46 #include <dirent.h> 47 #include <priv_utils.h> 48 #include <stdarg.h> 49 #include "rmformat.h" 50 /* 51 * These defines are from the PCMCIA memory driver driver 52 * header files (pcramio.h/pcramvar.h) and they are in 53 * the Platform Specific (PS) train. 54 */ 55 #ifndef PCRAM_PROBESIZE 56 #define PCRAMIOC ('P' << 8) 57 #define PCRAM_PROBESIZE (PCRAMIOC|22) /* Probe memory card size */ 58 #endif 59 60 /* 61 * Definitions. 62 */ 63 #define SENSE_KEY(rqbuf) (rqbuf[2] & 0xf) /* scsi error category */ 64 #define ASC(rqbuf) (rqbuf[12]) /* additional sense code */ 65 #define ASCQ(rqbuf) (rqbuf[13]) /* ASC qualifier */ 66 67 #define DEFAULT_SCSI_TIMEOUT 60 68 #define INQUIRY_CMD 0x12 69 #define RQBUFLEN 32 70 #define CD_RW 1 /* CD_RW/CD-R */ 71 #define WRITE_10_CMD 0x2A 72 #define READ_INFO_CMD 0x51 73 #define SYNC_CACHE_CMD 0x35 74 #define CLOSE_TRACK_CMD 0x5B 75 #define MODE_SENSE_10_CMD 0x5A 76 #define DEVFS_PREFIX "/devices" 77 78 int uscsi_error; /* used for debugging failed uscsi */ 79 char rqbuf[RQBUFLEN]; 80 static uint_t total_retries; 81 static struct uscsi_cmd uscmd; 82 static char ucdb[16]; 83 uchar_t uscsi_status, rqstatus, rqresid; 84 int total_devices_found = 0; 85 int removable_found = 0; 86 87 extern char *global_intr_msg; 88 extern int vol_running; 89 extern char *dev_name; 90 extern int32_t m_flag; 91 92 /* 93 * ON-private functions from libvolmgt 94 */ 95 int _dev_mounted(char *path); 96 97 /* 98 * Function prototypes. 99 */ 100 static int my_umount(char *mountp); 101 static int my_volrmmount(char *real_name); 102 static int vol_name_to_dev_node(char *vname, char *found); 103 static int vol_lookup(char *supplied, char *found); 104 static device_t *get_device(char *user_supplied, char *node); 105 static char *get_physical_name(char *path); 106 static int lookup_device(char *supplied, char *found); 107 static void fini_device(device_t *dev); 108 static int is_cd(char *node); 109 void *my_zalloc(size_t size); 110 void err_msg(char *fmt, ...); 111 int inquiry(int fd, uchar_t *inq); 112 struct uscsi_cmd *get_uscsi_cmd(void); 113 int uscsi(int fd, struct uscsi_cmd *scmd); 114 int get_mode_page(int fd, int page_no, int pc, int buf_len, 115 uchar_t *buffer); 116 int mode_sense(int fd, uchar_t pc, int dbd, int page_len, 117 uchar_t *buffer); 118 uint16_t read_scsi16(void *addr); 119 int check_device(device_t *dev, int cond); 120 static void get_media_info(device_t *t_dev, char *sdev, 121 char *pname, char *sn); 122 123 extern void process_p_flag(smedia_handle_t handle, int32_t fd); 124 125 void 126 my_perror(char *err_string) 127 { 128 129 int error_no; 130 if (errno == 0) 131 return; 132 133 error_no = errno; 134 (void) fprintf(stderr, "%s", err_string); 135 (void) fprintf(stderr, gettext(" : ")); 136 errno = error_no; 137 perror(""); 138 } 139 140 int32_t 141 get_confirmation() 142 { 143 char c; 144 145 (void) fprintf(stderr, gettext("Do you want to continue? (y/n)")); 146 c = getchar(); 147 if (c == 'y' || c == 'Y') 148 return (1); 149 else if (c == 'n' || c == 'N') 150 return (0); 151 else { 152 (void) fprintf(stderr, gettext("Invalid choice\n")); 153 return (0); 154 } 155 } 156 157 158 void 159 get_passwd(struct smwp_state *wp, int32_t confirm) 160 { 161 char passwd[256], re_passwd[256]; 162 int32_t len; 163 struct termios tio; 164 int32_t echo_off = 0; 165 FILE *in, *out; 166 char *buf; 167 168 169 in = fopen("/dev/tty", "r+"); 170 if (in == NULL) { 171 in = stdin; 172 out = stderr; 173 } else { 174 out = in; 175 } 176 177 /* Turn echoing off if it is on now. */ 178 179 if (tcgetattr(fileno(in), &tio) < 0) { 180 PERROR("Echo off ioctl failed"); 181 exit(1); 182 } 183 if (tio.c_lflag & ECHO) { 184 tio.c_lflag &= ~ECHO; 185 /* echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0; */ 186 echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0; 187 tio.c_lflag |= ECHO; 188 } 189 190 /* CONSTCOND */ 191 while (1) { 192 (void) fputs( 193 gettext("Please enter password (32 chars maximum):"), 194 out); 195 (void) fflush(out); 196 buf = fgets(passwd, (size_t)256, in); 197 rewind(in); 198 if (buf == NULL) { 199 PERROR("Error reading password"); 200 continue; 201 } 202 len = strlen(passwd); 203 (void) fputc('\n', out); 204 len--; /* To offset the \n */ 205 if ((len <= 0) || (len > 32)) { 206 (void) fprintf(stderr, 207 gettext("Invalid length of password \n")); 208 (void) fputs("Try again\n", out); 209 continue; 210 } 211 212 if (!confirm) 213 break; 214 215 (void) fputs("Please reenter password:", out); 216 (void) fflush(out); 217 buf = fgets(re_passwd, (size_t)256, in); 218 rewind(in); 219 (void) fputc('\n', out); 220 if ((buf == NULL) || strcmp(passwd, re_passwd)) { 221 (void) fputs("passwords did not match\n", out); 222 (void) fputs("Try again\n", out); 223 } else { 224 break; 225 } 226 } 227 wp->sm_passwd_len = len; 228 (void) strncpy(wp->sm_passwd, passwd, wp->sm_passwd_len); 229 wp->sm_version = SMWP_STATE_V_1; 230 231 /* Restore echoing. */ 232 if (echo_off) 233 (void) tcsetattr(fileno(in), TCSAFLUSH, &tio); 234 235 } 236 237 int32_t 238 check_and_unmount_vold(char *device_name, int32_t flag) 239 { 240 char *real_name; 241 char *nm; 242 char tmp_path_name[PATH_MAX]; 243 struct stat stat_buf; 244 int32_t ret_val = 0; 245 struct mnttab *mntp; 246 FILE *fp; 247 int nl; 248 249 DPRINTF1("Device name %s\n", device_name); 250 251 if (volmgt_running() == 0) { 252 DPRINTF("Vold not running\n"); 253 return (0); 254 } 255 if ((nm = volmgt_symname(device_name)) == NULL) { 256 DPRINTF("path not managed\n"); 257 real_name = media_findname(device_name); 258 } else { 259 DPRINTF1("path managed as %s\n", nm); 260 real_name = media_findname(nm); 261 DPRINTF1("real name %s\n", real_name); 262 } 263 264 if (real_name == NULL) 265 return (-1); 266 267 /* 268 * To find out whether the device has been mounted by 269 * volume manager... 270 * 271 * Convert the real name to a block device address. 272 * Do a partial match with the mnttab entries. 273 * Make sure the match is in the beginning to avoid if 274 * anybody puts a label similiar to volume manager path names. 275 * Then use "volrmmount -e <dev_name>" if -U flag is set. 276 */ 277 278 nl = strlen("/vol/dev/"); 279 280 if (strncmp(real_name, "/vol/dev/", nl) != 0) 281 return (0); 282 if (real_name[nl] == 'r') { 283 (void) snprintf(tmp_path_name, PATH_MAX, "%s%s", "/vol/dev/", 284 &real_name[nl + 1]); 285 } else { 286 (void) snprintf(tmp_path_name, PATH_MAX, "%s", real_name); 287 } 288 DPRINTF1("%s \n", tmp_path_name); 289 ret_val = stat(tmp_path_name, &stat_buf); 290 if (ret_val < 0) { 291 PERROR("Could not stat"); 292 return (-1); 293 } 294 295 fp = fopen("/etc/mnttab", "r"); 296 297 if (fp == NULL) { 298 PERROR("Could not open /etc/mnttab"); 299 return (-1); 300 } 301 302 mntp = (struct mnttab *)malloc(sizeof (struct mnttab)); 303 if (mntp == NULL) { 304 PERROR("malloc failed"); 305 (void) fclose(fp); 306 return (-1); 307 } 308 errno = 0; 309 while (getmntent(fp, mntp) == 0) { 310 if (errno != 0) { 311 PERROR("Error with mnttab"); 312 (void) fclose(fp); 313 return (-1); 314 } 315 /* Is it a probable entry? */ 316 DPRINTF1(" %s \n", mntp->mnt_special); 317 if (strstr(mntp->mnt_special, tmp_path_name) != 318 mntp->mnt_special) { 319 /* Skip to next entry */ 320 continue; 321 } else { 322 DPRINTF1("Found!! %s\n", mntp->mnt_special); 323 ret_val = 1; 324 break; 325 } 326 } 327 328 if (ret_val == 1) { 329 if (flag) { 330 if (my_volrmmount(real_name) < 0) { 331 ret_val = -1; 332 } 333 } else { 334 ret_val = -1; 335 } 336 } 337 (void) fclose(fp); 338 free(mntp); 339 return (ret_val); 340 } 341 342 /* 343 * This routine checks if a device has mounted partitions. The 344 * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can 345 * be used for SCSI and PCMCIA cards. 346 * Returns 347 * 0 : if not mounted 348 * 1 : if successfully unmounted 349 * -1 : Any error or umount failed 350 */ 351 352 int32_t 353 check_and_unmount_scsi(char *device_name, int32_t flag) 354 { 355 356 struct mnttab *mntrefp; 357 struct mnttab *mntp; 358 FILE *fp; 359 char block_dev_name[PATH_MAX]; 360 char tmp_name[PATH_MAX]; 361 int32_t i, j; 362 int32_t unmounted = 0; 363 364 /* 365 * If the device name is not a character special, anyway we 366 * can not progress further 367 */ 368 369 if (strncmp(device_name, "/dev/rdsk/c", strlen("/dev/rdsk/c")) != 0) 370 return (0); 371 372 (void) snprintf(block_dev_name, PATH_MAX, "/dev/%s", 373 &device_name[strlen("/dev/r")]); 374 fp = fopen("/etc/mnttab", "r"); 375 376 if (fp == NULL) { 377 PERROR("Could not open /etc/mnttab"); 378 return (-1); 379 } 380 381 mntrefp = (struct mnttab *)malloc(sizeof (struct mnttab)); 382 if (mntrefp == NULL) { 383 PERROR("malloc failed"); 384 (void) fclose(fp); 385 return (-1); 386 } 387 388 mntp = (struct mnttab *)malloc(sizeof (struct mnttab)); 389 if (mntp == NULL) { 390 PERROR("malloc failed"); 391 (void) fclose(fp); 392 free(mntrefp); 393 return (-1); 394 } 395 396 /* Try all the partitions */ 397 398 (void) snprintf(tmp_name, PATH_MAX, "/dev/%s", 399 &device_name[strlen("/dev/r")]); 400 401 tmp_name[strlen("/dev/dsk/c0t0d0s")] = '\0'; 402 403 errno = 0; 404 while (getmntent(fp, mntp) == 0) { 405 if (errno != 0) { 406 PERROR("Error with mnttab"); 407 (void) fclose(fp); 408 return (-1); 409 } 410 /* Is it a probable entry? */ 411 if (strncmp(mntp->mnt_special, tmp_name, strlen(tmp_name))) { 412 /* Skip to next entry */ 413 continue; 414 } 415 for (i = 0; i < NDKMAP; i++) { 416 /* Check for ufs style mount devices */ 417 (void) snprintf(block_dev_name, PATH_MAX, 418 "%s%d", tmp_name, i); 419 420 if (strcmp(mntp->mnt_special, block_dev_name) == 0) { 421 if (flag) { 422 if (my_umount(mntp->mnt_mountp) < 0) { 423 (void) fclose(fp); 424 return (-1); 425 } 426 unmounted = 1; 427 } else { 428 (void) fclose(fp); 429 return (-1); 430 } 431 /* Skip to next entry */ 432 continue; 433 } 434 435 /* Try for :1 -> :24 for pcfs */ 436 437 for (j = 1; j < 24; j++) { 438 (void) snprintf(block_dev_name, PATH_MAX, 439 "%s%d:%d", tmp_name, i, j); 440 441 if (strcmp(mntp->mnt_special, 442 block_dev_name) == 0) { 443 if (flag) { 444 if (my_umount(mntp->mnt_mountp) 445 < 0) { 446 (void) fclose(fp); 447 return (-1); 448 } 449 unmounted = 1; 450 } else { 451 (void) fclose(fp); 452 return (-1); 453 } 454 /* Skip to next entry */ 455 continue; 456 } 457 (void) snprintf(block_dev_name, PATH_MAX, 458 "%s%d:%c", tmp_name, i, 'b' + j); 459 460 if (strcmp(mntp->mnt_special, 461 block_dev_name) == 0) { 462 if (flag) { 463 if (my_umount(mntp->mnt_mountp) 464 < 0) { 465 (void) fclose(fp); 466 return (-1); 467 } 468 unmounted = 1; 469 } else { 470 (void) fclose(fp); 471 return (-1); 472 } 473 /* Skip to next entry */ 474 continue; 475 } 476 } 477 } 478 479 } 480 481 if (unmounted) 482 return (1); 483 return (0); 484 } 485 486 /* 487 * This routine checks if a device has mounted partitions. The 488 * device name is assumed to be /dev/rdiskette. So, this can 489 * be used for Floppy controllers 490 * Returns 491 * 0 : if not mounted 492 * 1 : if successfully unmounted 493 * -1 : Any error or unmount failed 494 */ 495 496 int32_t 497 check_and_unmount_floppy(int32_t fd, int32_t flag) 498 { 499 FILE *fp = NULL; 500 int32_t mfd; 501 struct dk_cinfo dkinfo, dkinfo_tmp; 502 struct mnttab mnt_record; 503 struct mnttab *mp = &mnt_record; 504 struct stat stbuf; 505 char raw_device[PATH_MAX]; 506 int32_t found = 0; 507 508 509 if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) { 510 return (-1); 511 } 512 513 if ((fp = fopen(MNTTAB, "r")) == NULL) { 514 PERROR("Could not open /etc/mnttab"); 515 (void) close(fd); 516 exit(3); 517 } 518 519 while (getmntent(fp, mp) == 0) { 520 if (strstr(mp->mnt_special, "/dev/fd") == NULL && 521 strstr(mp->mnt_special, "/dev/disket") == NULL && 522 strstr(mp->mnt_special, "/dev/c") == NULL) { 523 continue; 524 } 525 526 (void) strcpy(raw_device, "/dev/r"); 527 (void) strcat(raw_device, mp->mnt_special + strlen("/dev/")); 528 529 530 /* 531 * Attempt to open the device. If it fails, skip it. 532 */ 533 534 /* Turn on the privileges. */ 535 (void) __priv_bracket(PRIV_ON); 536 537 mfd = open(raw_device, O_RDWR | O_NDELAY); 538 539 /* Turn off the privileges. */ 540 (void) __priv_bracket(PRIV_OFF); 541 542 if (mfd < 0) { 543 continue; 544 } 545 546 /* 547 * Must be a character device 548 */ 549 if (fstat(mfd, &stbuf) < 0 || !S_ISCHR(stbuf.st_mode)) { 550 (void) close(mfd); 551 continue; 552 } 553 /* 554 * Attempt to read the configuration info on the disk. 555 */ 556 if (ioctl(mfd, DKIOCINFO, &dkinfo_tmp) < 0) { 557 (void) close(mfd); 558 continue; 559 } 560 /* 561 * Finished with the opened device 562 */ 563 (void) close(mfd); 564 565 /* 566 * If it's not the disk we're interested in, it doesn't apply. 567 */ 568 if (dkinfo.dki_ctype != dkinfo_tmp.dki_ctype || 569 dkinfo.dki_cnum != dkinfo_tmp.dki_cnum || 570 dkinfo.dki_unit != dkinfo_tmp.dki_unit) { 571 continue; 572 } 573 /* 574 * It's a mount on the disk we're checking. If we are 575 * checking whole disk, then we found trouble. We can 576 * quit searching. 577 */ 578 579 if (flag) { 580 if (my_umount(mp->mnt_mountp) < 0) { 581 return (-1); 582 } 583 found = 1; 584 } else { 585 return (-1); 586 } 587 } 588 return (found); 589 } 590 591 592 int32_t 593 my_open(char *device_name, int32_t flags) 594 { 595 char *real_name; 596 char *nm; 597 char tmp_path_name[PATH_MAX]; 598 struct stat stat_buf; 599 int32_t ret_val; 600 int32_t fd; 601 int32_t have_read_priv = 0; 602 DIR *dirp; 603 struct dirent *dp; 604 605 DPRINTF1("Device name %s\n", device_name); 606 607 if ((nm = volmgt_symname(device_name)) == NULL) { 608 DPRINTF("path not managed\n"); 609 real_name = media_findname(device_name); 610 } else { 611 DPRINTF1("path managed as %s\n", nm); 612 real_name = media_findname(nm); 613 DPRINTF1("real name %s\n", real_name); 614 } 615 616 if (real_name == NULL) 617 return (-1); 618 619 (void) strcpy(tmp_path_name, real_name); 620 ret_val = stat(tmp_path_name, &stat_buf); 621 if (ret_val < 0) { 622 PERROR("Could not stat"); 623 return (-1); 624 } 625 if (S_ISDIR(stat_buf.st_mode)) { 626 627 /* 628 * Open the directory and look for the 629 * first non '.' entry. 630 * Since raw_read and raw_writes are used, we don't 631 * need to access the backup slice. 632 * For PCMCIA Memory cards, raw_read and raw_writes are 633 * not supported, but that is not a problem as, only slice2 634 * is allowed on PCMCIA memory cards. 635 */ 636 637 /* 638 * First make sure we are operating with a /vol/.... 639 * Otherwise it can dangerous, 640 * e.g. rmformat -s /dev/rdsk 641 * We should not look into the directory contents here. 642 */ 643 if (strncmp(tmp_path_name, "/vol/dev/", strlen("/vol/dev/")) 644 != 0) { 645 (void) fprintf(stderr, gettext("The specified device \ 646 is not a raw device.\n")); 647 exit(1); 648 } 649 650 /* Turn on the privileges. */ 651 (void) __priv_bracket(PRIV_ON); 652 653 dirp = opendir(tmp_path_name); 654 655 /* Turn off the privileges. */ 656 (void) __priv_bracket(PRIV_OFF); 657 658 if (dirp == NULL) { 659 return (-1); 660 } 661 662 /* Turn on the privileges. */ 663 (void) __priv_bracket(PRIV_ON); 664 have_read_priv = 1; 665 666 while ((dp = readdir(dirp)) != NULL) { 667 668 /* Turn off the privileges. */ 669 (void) __priv_bracket(PRIV_OFF); 670 have_read_priv = 0; 671 672 DPRINTF1("Found %s\n", dp->d_name); 673 if ((strcmp(dp->d_name, ".") != 0) && 674 (strcmp(dp->d_name, "..") != 0)) { 675 (void) snprintf(tmp_path_name, PATH_MAX, 676 "%s/%s", tmp_path_name, dp->d_name); 677 678 DPRINTF1("tmp_pathname is %s\n", tmp_path_name); 679 break; 680 } 681 682 /* Turn on the privileges. */ 683 (void) __priv_bracket(PRIV_ON); 684 have_read_priv = 1; 685 } 686 687 if (have_read_priv) { 688 /* drop the file_dac_read privilege */ 689 (void) __priv_bracket(PRIV_OFF); 690 have_read_priv = 0; 691 } 692 693 (void) closedir(dirp); 694 } 695 696 697 if (volmgt_running() == 0) { 698 /* Turn on privileges. */ 699 (void) __priv_bracket(PRIV_ON); 700 have_read_priv = 1; 701 } 702 703 fd = open(tmp_path_name, flags); 704 705 if (have_read_priv) { 706 /* Turn off privileges. */ 707 (void) __priv_bracket(PRIV_OFF); 708 have_read_priv = 0; 709 } 710 711 DPRINTF1("path opened %s\n", tmp_path_name); 712 713 return (fd); 714 } 715 716 int64_t 717 my_atoll(char *ptr) 718 { 719 char *tmp_ptr = ptr; 720 int32_t base = 10; 721 int64_t ret_val; 722 723 while (*tmp_ptr) { 724 if (isdigit(*tmp_ptr)) 725 tmp_ptr++; 726 else { 727 base = 16; 728 break; 729 } 730 } 731 tmp_ptr = ptr; 732 if (base == 16) { 733 if (strlen(tmp_ptr) < 3) { 734 return (-1); 735 } 736 if (*tmp_ptr++ != '0' || (*tmp_ptr != 'x' && *tmp_ptr != 'X')) { 737 return (-1); 738 } 739 tmp_ptr++; 740 while (*tmp_ptr) { 741 if (isxdigit(*tmp_ptr)) 742 tmp_ptr++; 743 else { 744 return (-1); 745 } 746 } 747 } 748 ret_val = strtoll(ptr, (char **)NULL, 0); 749 return (ret_val); 750 } 751 752 int32_t 753 write_sunos_label(int32_t fd, int32_t media_type) 754 { 755 756 struct vtoc v_toc; 757 int32_t ret; 758 759 (void) memset(&v_toc, 0, sizeof (struct vtoc)); 760 761 /* Initialize the vtoc information */ 762 763 if (media_type == SM_FLOPPY) { 764 struct fd_char fdchar; 765 int32_t mult_factor; 766 767 if (ioctl(fd, FDIOGCHAR, &fdchar) < 0) { 768 PERROR("FDIOGCHAR failed"); 769 return (-1); 770 } 771 772 /* SPARC and x86 fd drivers use fdc_medium differently */ 773 #if defined(__sparc) 774 mult_factor = (fdchar.fdc_medium) ? 2 : 1; 775 #elif defined(__x86) 776 mult_factor = (fdchar.fdc_medium == 5) ? 2 : 1; 777 #else 778 #error No Platform defined 779 #endif /* defined(__sparc) */ 780 781 /* initialize the vtoc structure */ 782 v_toc.v_nparts = 3; 783 784 v_toc.v_part[0].p_start = 0; 785 v_toc.v_part[0].p_size = (fdchar.fdc_ncyl - 1) * 2 * 786 fdchar.fdc_secptrack * mult_factor; 787 v_toc.v_part[1].p_start = (fdchar.fdc_ncyl - 1) * 2 * 788 fdchar.fdc_secptrack * mult_factor; 789 v_toc.v_part[1].p_size = 2 * fdchar.fdc_secptrack * mult_factor; 790 791 v_toc.v_part[2].p_start = 0; 792 v_toc.v_part[2].p_size = fdchar.fdc_ncyl * 2 * 793 fdchar.fdc_secptrack * mult_factor; 794 795 } else if (media_type == SM_PCMCIA_MEM) { 796 797 static struct dk_geom dkg; 798 799 /* Get card cyl/head/secptrack info */ 800 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) { 801 /* 802 * Card doesn't have a CIS. So, ask driver 803 * to probe card size info 804 */ 805 if (ioctl(fd, PCRAM_PROBESIZE, &dkg) < 0) { 806 (void) fprintf(stderr, 807 gettext( 808 "Could not get card size information\n")); 809 (void) close(fd); 810 exit(3); 811 } 812 } 813 814 815 v_toc.v_part[2].p_start = 0; 816 v_toc.v_part[2].p_size = dkg.dkg_ncyl * dkg.dkg_nhead * 817 dkg.dkg_nsect; 818 819 /* v_nparts was 1 in fdformat. But write vtoc failes */ 820 v_toc.v_nparts = 3; 821 822 } else if (media_type == SM_SCSI_FLOPPY) { 823 824 smedia_handle_t handle; 825 smmedium_prop_t med_info; 826 struct dk_geom dkgeom; 827 828 829 /* 830 * call smedia_get_medium_property to get the 831 * correct media information, since DKIOCGMEDIAINFO 832 * may fail for unformatted media. 833 */ 834 835 handle = smedia_get_handle(fd); 836 if (handle == NULL) { 837 (void) fprintf(stderr, 838 gettext("Failed to get libsmedia handle.\n")); 839 840 (void) close(fd); 841 return (-1); 842 } 843 844 845 if (smedia_get_medium_property(handle, &med_info) < 0) { 846 (void) fprintf(stderr, 847 gettext("Get medium property failed \n")); 848 849 (void) smedia_release_handle(handle); 850 (void) close(fd); 851 return (-1); 852 } 853 854 /* Fill in our own geometry information */ 855 856 dkgeom.dkg_pcyl = med_info.sm_pcyl; 857 dkgeom.dkg_ncyl = med_info.sm_pcyl; 858 dkgeom.dkg_nhead = med_info.sm_nhead; 859 dkgeom.dkg_nsect = med_info.sm_nsect; 860 dkgeom.dkg_acyl = 0; 861 dkgeom.dkg_bcyl = 0; 862 dkgeom.dkg_intrlv = 0; 863 dkgeom.dkg_apc = 0; 864 865 /* 866 * Try to set vtoc, if not successful we will 867 * continue to use the faked geometry information. 868 */ 869 870 (void) ioctl(fd, DKIOCSGEOM, &dkgeom); 871 872 (void) smedia_release_handle(handle); 873 874 /* we want the same partitioning as used for normal floppies */ 875 876 v_toc.v_part[0].p_start = 0; 877 v_toc.v_part[0].p_size = (dkgeom.dkg_ncyl - 1) * 878 dkgeom.dkg_nhead * dkgeom.dkg_nsect; 879 880 v_toc.v_part[1].p_start = (dkgeom.dkg_ncyl - 1) * 881 dkgeom.dkg_nhead * dkgeom.dkg_nsect; 882 v_toc.v_part[1].p_size = dkgeom.dkg_nhead * dkgeom.dkg_nsect; 883 884 v_toc.v_part[2].p_start = 0; 885 v_toc.v_part[2].p_size = dkgeom.dkg_ncyl * 886 dkgeom.dkg_nhead * dkgeom.dkg_nsect; 887 888 /* both write_vtoc and DKIOCSVTOC require V_NUMPAR partitions */ 889 v_toc.v_nparts = V_NUMPAR; 890 891 } else { 892 893 return (0); 894 } 895 896 v_toc.v_sanity = VTOC_SANE; 897 v_toc.v_version = V_VERSION; 898 899 /* 900 * The label structure is set up for DEV_BSIZE(512 byte) blocks, 901 * even though a medium density diskette has 1024 byte blocks 902 * See dklabel.h for more details. 903 */ 904 v_toc.v_sectorsz = DEV_BSIZE; 905 906 /* let the fd driver finish constructing the label and writing it. */ 907 908 909 /* Turn on the privileges. */ 910 (void) __priv_bracket(PRIV_ON); 911 912 ret = write_vtoc(fd, &v_toc); 913 914 /* Turn off the privileges. */ 915 (void) __priv_bracket(PRIV_OFF); 916 917 if (ret < 0) { 918 PERROR("Write vtoc"); 919 DPRINTF1("Write vtoc failed errno:%d\n", errno); 920 return (-1); 921 } 922 923 return (0); 924 } 925 926 static void 927 intr_sig_handler() 928 { 929 char c; 930 931 (void) fprintf(stderr, gettext(global_intr_msg)); 932 (void) fprintf(stderr, 933 gettext("\nDo you want to stop formatting?(y/n)")); 934 (void) fflush(stdout); 935 rewind(stdin); 936 while ((c = getchar()) == -1); 937 if (c == 'y' || c == 'Y') { 938 (void) fprintf(stderr, gettext("Format interrupted\n")); 939 exit(1); 940 } else if (c == 'n' || c == 'N') 941 return; 942 else { 943 (void) fprintf(stderr, gettext("Did not interrupt\n")); 944 return; 945 } 946 } 947 948 static struct sigaction act, oact; 949 void 950 trap_SIGINT() 951 { 952 953 act.sa_handler = intr_sig_handler; 954 (void) memset(&act.sa_mask, 0, sizeof (sigset_t)); 955 act.sa_flags = SA_RESTART; /* | SA_NODEFER; */ 956 if (sigaction(SIGINT, &act, &oact) < 0) { 957 DPRINTF("sigset failed\n"); 958 return; 959 } 960 } 961 962 void 963 release_SIGINT() 964 { 965 if (sigaction(SIGINT, &oact, (struct sigaction *)NULL) < 0) { 966 DPRINTF("sigunset failed\n"); 967 return; 968 } 969 } 970 971 int32_t 972 verify(smedia_handle_t handle, int32_t fd, uint32_t start_sector, 973 uint32_t nblocks, char *buf, 974 int32_t flag, int32_t blocksize, int32_t no_raw_rw) 975 { 976 int32_t ret; 977 978 DPRINTF("ANALYSE MEDIA \n"); 979 980 981 if ((flag == VERIFY_READ) && (!no_raw_rw)) { 982 983 /* Turn on the privileges. */ 984 (void) __priv_bracket(PRIV_ON); 985 986 ret = smedia_raw_read(handle, start_sector, buf, nblocks * 987 blocksize); 988 989 /* Turn off the privileges. */ 990 (void) __priv_bracket(PRIV_OFF); 991 992 if ((ret < 0) || (ret != (nblocks * blocksize))) 993 return (-1); 994 return (0); 995 996 } else if ((flag == VERIFY_WRITE) && (!no_raw_rw)) { 997 998 /* Turn on privileges. */ 999 (void) __priv_bracket(PRIV_ON); 1000 1001 ret = smedia_raw_write(handle, start_sector, buf, nblocks * 1002 blocksize); 1003 1004 /* Turn off the privileges. */ 1005 (void) __priv_bracket(PRIV_OFF); 1006 1007 if ((ret < 0) || (ret != (blocksize * nblocks))) 1008 return (-1); 1009 return (0); 1010 1011 } else if ((flag == VERIFY_READ) && (no_raw_rw)) { 1012 ret = llseek(fd, start_sector * blocksize, SEEK_SET); 1013 if (ret != start_sector * blocksize) { 1014 (void) fprintf(stderr, gettext("Seek failed\n")); 1015 return (-2); 1016 } 1017 1018 /* Turn on the privileges. */ 1019 (void) __priv_bracket(PRIV_ON); 1020 1021 ret = read(fd, buf, nblocks * blocksize); 1022 1023 /* Turn off the privileges. */ 1024 (void) __priv_bracket(PRIV_OFF); 1025 1026 if (ret != nblocks * blocksize) { 1027 return (-1); 1028 } 1029 return (0); 1030 } else if ((flag == VERIFY_WRITE) && (no_raw_rw)) { 1031 ret = llseek(fd, start_sector * blocksize, SEEK_SET); 1032 if (ret != start_sector * blocksize) { 1033 (void) fprintf(stderr, gettext("Seek failed\n")); 1034 return (-2); 1035 } 1036 1037 /* Turn on the privileges. */ 1038 (void) __priv_bracket(PRIV_ON); 1039 1040 ret = write(fd, buf, nblocks * blocksize); 1041 1042 /* Turn off the privileges. */ 1043 (void) __priv_bracket(PRIV_OFF); 1044 1045 if (ret != nblocks * blocksize) { 1046 return (-1); 1047 } 1048 return (0); 1049 } else { 1050 DPRINTF("Illegal parameter to verify_analysis!\n"); 1051 return (-1); 1052 } 1053 } 1054 1055 static int 1056 my_umount(char *mountp) 1057 { 1058 pid_t pid; /* forked proc's pid */ 1059 int rval; /* proc's return value */ 1060 1061 1062 /* create a child to unmount the path */ 1063 1064 /* Turn on the privileges */ 1065 (void) __priv_bracket(PRIV_ON); 1066 1067 pid = fork(); 1068 1069 /* Turn off the privileges. */ 1070 (void) __priv_bracket(PRIV_OFF); 1071 1072 if (pid < 0) { 1073 PERROR("fork failed"); 1074 exit(0); 1075 } 1076 1077 if (pid == 0) { 1078 /* the child */ 1079 /* get rid of those nasty err messages */ 1080 DPRINTF1("call_unmount_prog: calling %s \n", mountp); 1081 1082 /* Turn on the priviliges. */ 1083 (void) __priv_bracket(PRIV_ON); 1084 1085 if (execl("/usr/sbin/umount", "/usr/sbin/umount", mountp, 1086 NULL) < 0) { 1087 perror("exec failed"); 1088 /* Turn off the privileges */ 1089 (void) __priv_bracket(PRIV_OFF); 1090 exit(-1); 1091 } 1092 } 1093 1094 /* wait for the umount command to exit */ 1095 rval = 0; 1096 if (waitpid(pid, &rval, 0) == pid) { 1097 if (WIFEXITED(rval)) { 1098 if (WEXITSTATUS(rval) == 0) { 1099 DPRINTF("umount : Success\n"); 1100 return (1); 1101 } 1102 } 1103 } 1104 return (-1); 1105 } 1106 1107 static int 1108 my_volrmmount(char *real_name) 1109 { 1110 int pid, rval; 1111 1112 /* Turn on the privileges. */ 1113 (void) __priv_bracket(PRIV_ON); 1114 1115 pid = fork(); 1116 1117 /* Turn off the privileges. */ 1118 (void) __priv_bracket(PRIV_OFF); 1119 1120 /* create a child to unmount the path */ 1121 if (pid < 0) { 1122 PERROR("fork failed"); 1123 exit(0); 1124 } 1125 1126 if (pid == 0) { 1127 /* the child */ 1128 /* get rid of those nasty err messages */ 1129 DPRINTF1("call_unmount_prog: calling %s \n", 1130 "/usr/bin/volrmmount"); 1131 1132 /* Turn on the privileges. */ 1133 (void) __priv_bracket(PRIV_ON); 1134 if (execl("/usr/bin/volrmmount", "/usr/bin/volrmmount", "-e", 1135 real_name, NULL) < 0) { 1136 PERROR("volrmmount exec failed"); 1137 /* Turn off the privileges */ 1138 (void) __priv_bracket(PRIV_OFF); 1139 exit(-1); 1140 } 1141 } else if (waitpid(pid, &rval, 0) == pid) { 1142 if (WIFEXITED(rval)) { 1143 if (WEXITSTATUS(rval) == 0) { 1144 DPRINTF("volrmmount: Success\n"); 1145 return (1); 1146 } 1147 } 1148 } 1149 return (-1); 1150 } 1151 1152 int 1153 find_device(int defer, char *tmpstr) 1154 { 1155 DIR *dir; 1156 struct dirent *dirent; 1157 char sdev[PATH_MAX], dev[PATH_MAX], *pname; 1158 device_t *t_dev; 1159 int removable = 0; 1160 int device_type = 0; 1161 int hotpluggable = 0; 1162 struct dk_minfo mediainfo; 1163 static int found = 0; 1164 1165 dir = opendir("/dev/rdsk"); 1166 if (dir == NULL) 1167 return (-1); 1168 1169 total_devices_found = 0; 1170 while ((dirent = readdir(dir)) != NULL) { 1171 if (dirent->d_name[0] == '.') { 1172 continue; 1173 } 1174 (void) snprintf(sdev, PATH_MAX, "/dev/rdsk/%s", 1175 dirent->d_name); 1176 #ifdef sparc 1177 if (!strstr(sdev, "s2")) { 1178 continue; 1179 } 1180 #else /* x86 */ 1181 if (vol_running) { 1182 if (!(strstr(sdev, "s2") || strstr(sdev, "p0"))) { 1183 continue; 1184 } 1185 } else { 1186 if (!strstr(sdev, "p0")) { 1187 continue; 1188 } 1189 } 1190 #endif 1191 if (!lookup_device(sdev, dev)) { 1192 continue; 1193 } 1194 if ((t_dev = get_device(NULL, dev)) == NULL) { 1195 continue; 1196 } 1197 total_devices_found++; 1198 1199 if ((!defer) && !found) { 1200 char *sn, *tmpbuf; 1201 /* 1202 * dev_name is an optional command line input. 1203 */ 1204 if (dev_name) { 1205 if (strstr(dirent->d_name, tmpstr)) { 1206 found = 1; 1207 } else if (!vol_running) { 1208 continue; 1209 } 1210 } 1211 /* 1212 * volmgt_symname() returns NULL if the device 1213 * is not managed by volmgt. 1214 */ 1215 sn = volmgt_symname(sdev); 1216 1217 if (vol_running && (sn != NULL)) { 1218 if (strstr(sn, "dev") == NULL) { 1219 tmpbuf = (char *)my_zalloc(PATH_MAX); 1220 (void) strcpy(tmpbuf, 1221 "/vol/dev/aliases/"); 1222 (void) strcat(tmpbuf, sn); 1223 free(sn); 1224 sn = tmpbuf; 1225 } 1226 if (dev_name && !found) { 1227 if (!strstr(tmpbuf, tmpstr)) { 1228 continue; 1229 } else { 1230 found = 1; 1231 } 1232 } 1233 } 1234 1235 /* 1236 * Get device type information for CD/DVD devices. 1237 */ 1238 if (is_cd(dev)) { 1239 if (check_device(t_dev, 1240 CHECK_DEVICE_IS_DVD_WRITABLE)) { 1241 device_type = DK_DVDR; 1242 } else if (check_device(t_dev, 1243 CHECK_DEVICE_IS_DVD_READABLE)) { 1244 device_type = DK_DVDROM; 1245 } else if (check_device(t_dev, 1246 CHECK_DEVICE_IS_CD_WRITABLE)) { 1247 device_type = DK_CDR; 1248 } else { 1249 device_type = DK_CDROM; 1250 } 1251 } else { 1252 device_type = ioctl(t_dev->d_fd, 1253 DKIOCGMEDIAINFO, &mediainfo); 1254 if (device_type < 0) 1255 device_type = 0; 1256 else 1257 device_type = mediainfo.dki_media_type; 1258 } 1259 1260 if (!ioctl(t_dev->d_fd, DKIOCREMOVABLE, &removable) && 1261 !ioctl(t_dev->d_fd, DKIOCHOTPLUGGABLE, 1262 &hotpluggable)) { 1263 if (removable || hotpluggable) { 1264 removable_found++; 1265 pname = get_physical_name(sdev); 1266 if (sn) { 1267 (void) printf(" %4d. " 1268 "Volmgt Node: %s\n", 1269 removable_found, sn); 1270 (void) printf(" " 1271 "Logical Node: %s\n", sdev); 1272 (void) printf(" " 1273 "Physical Node: %s\n", 1274 pname); 1275 } else { 1276 (void) printf(" %4d. " 1277 "Logical Node: %s\n", 1278 removable_found, sdev); 1279 (void) printf(" " 1280 "Physical Node: %s\n", 1281 pname); 1282 } 1283 (void) printf(" Connected " 1284 "Device: %-8.8s %-16.16s " 1285 "%-4.4s\n", 1286 &t_dev->d_inq[8], 1287 &t_dev->d_inq[16], 1288 &t_dev->d_inq[32]); 1289 (void) printf(" Device " 1290 "Type: "); 1291 } else 1292 continue; 1293 } else 1294 continue; 1295 1296 switch (device_type) { 1297 case DK_CDROM: 1298 (void) printf("CD Reader\n"); 1299 break; 1300 case DK_CDR: 1301 case DK_CDRW: 1302 (void) printf("CD Reader/Writer\n"); 1303 break; 1304 case DK_DVDROM: 1305 (void) printf("DVD Reader\n"); 1306 break; 1307 case DK_DVDR: 1308 case DK_DVDRAM: 1309 (void) printf("DVD Reader/Writer\n"); 1310 break; 1311 case DK_FIXED_DISK: 1312 if (strstr((const char *) 1313 &t_dev->d_inq[16], "FD") || 1314 strstr((const char *) 1315 &t_dev->d_inq[16], "LS-120")) 1316 (void) printf("Floppy " 1317 "drive\n"); 1318 else 1319 (void) printf("Removable\n"); 1320 break; 1321 case DK_FLOPPY: 1322 (void) printf("Floppy drive\n"); 1323 break; 1324 case DK_ZIP: 1325 (void) printf("Zip drive\n"); 1326 break; 1327 case DK_JAZ: 1328 (void) printf("Jaz drive\n"); 1329 break; 1330 default: 1331 (void) printf("<Unknown>\n"); 1332 DPRINTF1("\t %d\n", device_type); 1333 break; 1334 } 1335 get_media_info(t_dev, sdev, pname, sn); 1336 } 1337 fini_device(t_dev); 1338 } 1339 1340 (void) closedir(dir); 1341 return (removable_found); 1342 } 1343 1344 /* 1345 * Returns a device_t handle for a node returned by lookup_device() 1346 * and takes the user supplied name and stores it inside the node. 1347 */ 1348 static device_t * 1349 get_device(char *user_supplied, char *node) 1350 { 1351 device_t *dev; 1352 int fd; 1353 char devnode[PATH_MAX]; 1354 int size; 1355 1356 /* 1357 * we need to resolve any link paths to avoid fake files 1358 * such as /dev/rdsk/../../export/file. 1359 */ 1360 size = resolvepath(node, devnode, PATH_MAX); 1361 if ((size <= 0) || (size >= (PATH_MAX - 1))) 1362 return (NULL); 1363 1364 /* resolvepath may not return a null terminated string */ 1365 devnode[size] = '\0'; 1366 1367 1368 /* the device node must be in /devices/ or /vol/dev/rdsk */ 1369 1370 if ((strncmp(devnode, "/devices/", 9) != 0) && 1371 (strncmp(devnode, "/vol/dev/rdsk", 13) != 0)) 1372 return (NULL); 1373 1374 /* Turn on the privileges. */ 1375 (void) __priv_bracket(PRIV_ON); 1376 1377 /* 1378 * Since we are currently running with the user euid it is 1379 * safe to try to open the file without checking access. 1380 */ 1381 1382 fd = open(devnode, O_RDONLY|O_NDELAY); 1383 1384 /* Turn off the privileges. */ 1385 (void) __priv_bracket(PRIV_OFF); 1386 1387 if (fd < 0) { 1388 return (NULL); 1389 } 1390 1391 dev = (device_t *)my_zalloc(sizeof (device_t)); 1392 1393 dev->d_node = (char *)my_zalloc(strlen(devnode) + 1); 1394 (void) strcpy(dev->d_node, devnode); 1395 1396 dev->d_fd = fd; 1397 1398 dev->d_inq = (uchar_t *)my_zalloc(INQUIRY_DATA_LENGTH); 1399 1400 /* Turn on privileges. */ 1401 (void) __priv_bracket(PRIV_ON); 1402 if (!inquiry(fd, dev->d_inq)) { 1403 DPRINTF1("USCSI ioctl failed %d\n", 1404 uscsi_error); 1405 free(dev->d_inq); 1406 free(dev->d_node); 1407 (void) close(dev->d_fd); 1408 free(dev); 1409 /* Turn off privileges. */ 1410 (void) __priv_bracket(PRIV_OFF); 1411 return (NULL); 1412 } 1413 /* Turn off privileges. */ 1414 (void) __priv_bracket(PRIV_OFF); 1415 1416 if (user_supplied) { 1417 dev->d_name = (char *)my_zalloc(strlen(user_supplied) + 1); 1418 (void) strcpy(dev->d_name, user_supplied); 1419 } 1420 return (dev); 1421 } 1422 1423 /* 1424 * Check for device specific characteristics. 1425 */ 1426 int 1427 check_device(device_t *dev, int cond) 1428 { 1429 uchar_t page_code[4]; 1430 1431 /* Look at the capabilities page for this information */ 1432 if (cond & CHECK_DEVICE_IS_CD_WRITABLE) { 1433 if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) && 1434 (page_code[3] & 1)) { 1435 return (1); 1436 } 1437 } 1438 1439 if (cond & CHECK_DEVICE_IS_DVD_WRITABLE) { 1440 if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) && 1441 (page_code[3] & 0x10)) { 1442 return (1); 1443 } 1444 } 1445 1446 if (cond & CHECK_DEVICE_IS_DVD_READABLE) { 1447 if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) && 1448 (page_code[2] & 0x8)) { 1449 return (1); 1450 } 1451 } 1452 1453 return (0); 1454 } 1455 1456 /* 1457 * Builds an open()able device path from a user supplied node which can be 1458 * of the * form of /dev/[r]dsk/cxtxdx[sx] or cxtxdx[sx] or volmgt-name like 1459 * cdrom[n]. 1460 * Returns the path found in 'found' and returns 1. Otherwise returns 0. 1461 */ 1462 int 1463 lookup_device(char *supplied, char *found) 1464 { 1465 struct stat statbuf; 1466 int fd; 1467 char tmpstr[PATH_MAX]; 1468 1469 /* Turn on privileges */ 1470 (void) __priv_bracket(PRIV_ON); 1471 1472 /* If everything is fine and proper, no need to analyze */ 1473 if ((stat(supplied, &statbuf) == 0) && S_ISCHR(statbuf.st_mode) && 1474 ((fd = open(supplied, O_RDONLY|O_NDELAY)) >= 0)) { 1475 (void) close(fd); 1476 (void) strlcpy(found, supplied, PATH_MAX); 1477 /* Turn off privilege */ 1478 (void) __priv_bracket(PRIV_OFF); 1479 return (1); 1480 } 1481 1482 /* Turn off privileges. */ 1483 (void) __priv_bracket(PRIV_OFF); 1484 1485 if (strncmp(supplied, "/dev/rdsk/", 10) == 0) 1486 return (vol_lookup(supplied, found)); 1487 if (strncmp(supplied, "/dev/dsk/", 9) == 0) { 1488 (void) snprintf(tmpstr, PATH_MAX, "/dev/rdsk/%s", 1489 (char *)strrchr(supplied, '/')); 1490 1491 if ((fd = open(tmpstr, O_RDONLY|O_NDELAY)) >= 0) { 1492 (void) close(fd); 1493 (void) strlcpy(found, supplied, PATH_MAX); 1494 return (1); 1495 } 1496 if ((access(tmpstr, F_OK) == 0) && vol_running) 1497 return (vol_lookup(tmpstr, found)); 1498 else 1499 return (0); 1500 } 1501 if ((strncmp(supplied, "cdrom", 5) != 0) && 1502 (strlen(supplied) < 32)) { 1503 (void) snprintf(tmpstr, sizeof (tmpstr), "/dev/rdsk/%s", 1504 supplied); 1505 if (access(tmpstr, F_OK) < 0) { 1506 (void) strcat(tmpstr, "s2"); 1507 } 1508 if ((fd = open(tmpstr, O_RDONLY|O_NDELAY)) >= 0) { 1509 (void) close(fd); 1510 (void) strlcpy(found, tmpstr, PATH_MAX); 1511 return (1); 1512 } 1513 if ((access(tmpstr, F_OK) == 0) && vol_running) 1514 return (vol_lookup(tmpstr, found)); 1515 } 1516 return (vol_name_to_dev_node(supplied, found)); 1517 } 1518 1519 int 1520 is_cd(char *node) 1521 { 1522 int fd; 1523 struct dk_cinfo cinfo; 1524 1525 fd = open(node, O_RDONLY|O_NDELAY); 1526 if (fd < 0) 1527 return (0); 1528 if (ioctl(fd, DKIOCINFO, &cinfo) < 0) { 1529 (void) close(fd); 1530 return (0); 1531 } 1532 if (cinfo.dki_ctype != DKC_CDROM) 1533 return (0); 1534 return (1); 1535 } 1536 1537 void 1538 print_header(void) 1539 { 1540 /* l10n_NOTE : Column spacing should be kept same */ 1541 (void) printf(gettext(" Node " 1542 "Connected Device")); 1543 /* l10n_NOTE : Column spacing should be kept same */ 1544 (void) printf(gettext(" Device type\n")); 1545 (void) printf( 1546 "---------------------------+---------------------------"); 1547 (void) printf("-----+----------------\n"); 1548 } 1549 1550 void 1551 print_divider(void) 1552 { 1553 (void) printf( 1554 "---------------------------+---------------------------"); 1555 (void) printf("-----+----------------\n"); 1556 } 1557 1558 static void 1559 fini_device(device_t *dev) 1560 { 1561 free(dev->d_inq); 1562 free(dev->d_node); 1563 (void) close(dev->d_fd); 1564 if (dev->d_name) 1565 free(dev->d_name); 1566 free(dev); 1567 } 1568 1569 void * 1570 my_zalloc(size_t size) 1571 { 1572 void *ret; 1573 1574 ret = malloc(size); 1575 if (ret == NULL) { 1576 1577 /* Lets wait a sec. and try again */ 1578 if (errno == EAGAIN) { 1579 (void) sleep(1); 1580 ret = malloc(size); 1581 } 1582 1583 if (ret == NULL) { 1584 (void) err_msg("%s\n", gettext(strerror(errno))); 1585 (void) err_msg(gettext( 1586 "Memory allocation failure, Exiting...\n")); 1587 exit(1); 1588 } 1589 } 1590 (void) memset(ret, 0, size); 1591 return (ret); 1592 } 1593 1594 static int 1595 vol_name_to_dev_node(char *vname, char *found) 1596 { 1597 struct stat statbuf; 1598 char *p1; 1599 int i; 1600 1601 if (vname == NULL) 1602 return (0); 1603 if (vol_running) 1604 (void) volmgt_check(vname); 1605 p1 = media_findname(vname); 1606 if (p1 == NULL) 1607 return (0); 1608 if (stat(p1, &statbuf) < 0) { 1609 free(p1); 1610 return (0); 1611 } 1612 if (S_ISDIR(statbuf.st_mode)) { 1613 for (i = 0; i < 16; i++) { 1614 (void) snprintf(found, PATH_MAX, "%s/s%d", p1, i); 1615 if (access(found, F_OK) >= 0) 1616 break; 1617 } 1618 if (i == 16) { 1619 free(p1); 1620 return (0); 1621 } 1622 } else { 1623 (void) strlcpy(found, p1, PATH_MAX); 1624 } 1625 free(p1); 1626 return (1); 1627 } 1628 1629 /* 1630 * Searches for volume manager's equivalent char device for the 1631 * supplied pathname which is of the form of /dev/rdsk/cxtxdxsx 1632 */ 1633 static int 1634 vol_lookup(char *supplied, char *found) 1635 { 1636 char tmpstr[PATH_MAX], tmpstr1[PATH_MAX], *p; 1637 int i, ret; 1638 1639 (void) strlcpy(tmpstr, supplied, PATH_MAX); 1640 if ((p = volmgt_symname(tmpstr)) == NULL) { 1641 if (strstr(tmpstr, "s2") != NULL) { 1642 *((char *)(strrchr(tmpstr, 's') + 1)) = 0; 1643 for (i = 0; i < 16; i++) { 1644 (void) snprintf(tmpstr1, PATH_MAX, "%s%d", 1645 tmpstr, i); 1646 if ((p = volmgt_symname(tmpstr1)) != NULL) 1647 break; 1648 } 1649 } else if (strstr(tmpstr, "p0") != NULL) { 1650 *((char *)(strrchr(tmpstr, 'p') + 1)) = 0; 1651 for (i = 0; i < 5; i++) { 1652 (void) snprintf(tmpstr1, PATH_MAX, "%s%d", 1653 tmpstr, i); 1654 if ((p = volmgt_symname(tmpstr1)) != NULL) 1655 break; 1656 } 1657 } else 1658 return (0); 1659 if (p == NULL) 1660 return (0); 1661 } 1662 1663 ret = vol_name_to_dev_node(p, found); 1664 free(p); 1665 return (ret); 1666 } 1667 1668 /*PRINTFLIKE1*/ 1669 void 1670 err_msg(char *fmt, ...) 1671 { 1672 va_list ap; 1673 1674 va_start(ap, fmt); 1675 (void) vfprintf(stderr, fmt, ap); 1676 va_end(ap); 1677 } 1678 1679 int 1680 inquiry(int fd, uchar_t *inq) 1681 { 1682 struct uscsi_cmd *scmd; 1683 1684 scmd = get_uscsi_cmd(); 1685 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 1686 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 1687 scmd->uscsi_cdb[0] = INQUIRY_CMD; 1688 scmd->uscsi_cdb[4] = INQUIRY_DATA_LENGTH; 1689 scmd->uscsi_cdblen = 6; 1690 scmd->uscsi_bufaddr = (char *)inq; 1691 scmd->uscsi_buflen = INQUIRY_DATA_LENGTH; 1692 if ((uscsi_error = uscsi(fd, scmd)) < 0) 1693 return (0); 1694 return (1); 1695 } 1696 1697 struct uscsi_cmd * 1698 get_uscsi_cmd(void) 1699 { 1700 (void) memset(&uscmd, 0, sizeof (uscmd)); 1701 (void) memset(ucdb, 0, 16); 1702 uscmd.uscsi_cdb = ucdb; 1703 return (&uscmd); 1704 } 1705 1706 int 1707 uscsi(int fd, struct uscsi_cmd *scmd) 1708 { 1709 int ret, global_rqsense; 1710 int retries, max_retries = 5; 1711 int i; 1712 1713 /* set up for request sense extensions */ 1714 if (!(scmd->uscsi_flags & USCSI_RQENABLE)) { 1715 scmd->uscsi_flags |= USCSI_RQENABLE; 1716 scmd->uscsi_rqlen = RQBUFLEN; 1717 scmd->uscsi_rqbuf = rqbuf; 1718 global_rqsense = 1; 1719 } else { 1720 global_rqsense = 0; 1721 } 1722 1723 /* 1724 * The device may be busy or slow and fail with a not ready status. 1725 * we'll allow a limited number of retries to give the drive time 1726 * to recover. 1727 */ 1728 for (retries = 0; retries < max_retries; retries++) { 1729 1730 scmd->uscsi_status = 0; 1731 1732 if (global_rqsense) 1733 (void) memset(rqbuf, 0, RQBUFLEN); 1734 1735 DPRINTF("cmd:["); 1736 for (i = 0; i < scmd->uscsi_cdblen; i++) 1737 DPRINTF1("0x%02x ", 1738 (uchar_t)scmd->uscsi_cdb[i]); 1739 DPRINTF("]\n"); 1740 1741 /* 1742 * We need to have root privledges in order to use 1743 * uscsi commands on the device. 1744 */ 1745 1746 ret = ioctl(fd, USCSICMD, scmd); 1747 1748 /* maintain consistency in case of sgen */ 1749 if ((ret == 0) && (scmd->uscsi_status == 2)) { 1750 ret = -1; 1751 errno = EIO; 1752 } 1753 1754 /* if error and extended request sense, retrieve errors */ 1755 if (global_rqsense && (ret < 0) && (scmd->uscsi_status == 2)) { 1756 /* 1757 * The drive is not ready to recieve commands but 1758 * may be in the process of becoming ready. 1759 * sleep for a short time then retry command. 1760 * SENSE/ASC = 2/4 : not ready 1761 * ASCQ = 0 Not Reportable. 1762 * ASCQ = 1 Becoming ready. 1763 */ 1764 if ((SENSE_KEY(rqbuf) == 2) && (ASC(rqbuf) == 4) && 1765 ((ASCQ(rqbuf) == 0) || (ASCQ(rqbuf) == 1))) { 1766 total_retries++; 1767 (void) sleep(3); 1768 continue; 1769 } 1770 1771 /* 1772 * Device is not ready to transmit or a device reset 1773 * has occurred. wait for a short period of time then 1774 * retry the command. 1775 */ 1776 if ((SENSE_KEY(rqbuf) == 6) && ((ASC(rqbuf) == 0x28) || 1777 (ASC(rqbuf) == 0x29))) { 1778 (void) sleep(3); 1779 total_retries++; 1780 continue; 1781 } 1782 1783 DPRINTF3("cmd: 0x%02x ret:%i status:%02x ", 1784 (uchar_t)scmd->uscsi_cdb[0], ret, 1785 scmd->uscsi_status); 1786 DPRINTF3(" sense: %02x ASC: %02x ASCQ:%02x\n", 1787 (uchar_t)SENSE_KEY(rqbuf), 1788 (uchar_t)ASC(rqbuf), (uchar_t)ASCQ(rqbuf)); 1789 } 1790 1791 /* no errors we'll return */ 1792 break; 1793 } 1794 1795 /* store the error status for later debug printing */ 1796 if ((ret < 0) && (global_rqsense)) { 1797 uscsi_status = scmd->uscsi_status; 1798 rqstatus = scmd->uscsi_rqstatus; 1799 rqresid = scmd->uscsi_rqresid; 1800 1801 } 1802 1803 DPRINTF1("total retries: %d\n", total_retries); 1804 1805 return (ret); 1806 } 1807 1808 /* 1809 * will get the mode page only i.e. will strip off the header. 1810 */ 1811 int 1812 get_mode_page(int fd, int page_no, int pc, int buf_len, uchar_t *buffer) 1813 { 1814 int ret; 1815 uchar_t byte2, *buf; 1816 uint_t header_len, page_len, copy_cnt; 1817 1818 byte2 = (uchar_t)(((pc << 6) & 0xC0) | (page_no & 0x3f)); 1819 buf = (uchar_t *)my_zalloc(256); 1820 1821 /* Ask 254 bytes only to make our IDE driver happy */ 1822 ret = mode_sense(fd, byte2, 1, 254, buf); 1823 if (ret == 0) { 1824 free(buf); 1825 return (0); 1826 } 1827 1828 header_len = 8 + read_scsi16(&buf[6]); 1829 page_len = buf[header_len + 1] + 2; 1830 1831 copy_cnt = (page_len > buf_len) ? buf_len : page_len; 1832 (void) memcpy(buffer, &buf[header_len], copy_cnt); 1833 free(buf); 1834 1835 return (1); 1836 } 1837 1838 int 1839 mode_sense(int fd, uchar_t pc, int dbd, int page_len, uchar_t *buffer) 1840 { 1841 struct uscsi_cmd *scmd; 1842 1843 scmd = get_uscsi_cmd(); 1844 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 1845 scmd->uscsi_buflen = page_len; 1846 scmd->uscsi_bufaddr = (char *)buffer; 1847 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 1848 scmd->uscsi_cdblen = 0xa; 1849 scmd->uscsi_cdb[0] = MODE_SENSE_10_CMD; 1850 if (dbd) { 1851 /* don't return any block descriptors */ 1852 scmd->uscsi_cdb[1] = 0x8; 1853 } 1854 /* the page code we want */ 1855 scmd->uscsi_cdb[2] = pc; 1856 /* allocation length */ 1857 scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff; 1858 scmd->uscsi_cdb[8] = page_len & 0xff; 1859 1860 if ((uscsi_error = uscsi(fd, scmd)) < 0) 1861 return (0); 1862 return (1); 1863 } 1864 1865 uint16_t 1866 read_scsi16(void *addr) 1867 { 1868 uchar_t *ad = (uchar_t *)addr; 1869 uint16_t ret; 1870 1871 ret = ((((uint16_t)ad[0]) << 8) | ad[1]); 1872 return (ret); 1873 } 1874 1875 /* 1876 * Allocate space for and return a pointer to a string 1877 * on the stack. If the string is null, create 1878 * an empty string. 1879 * Use destroy_data() to free when no longer used. 1880 */ 1881 char * 1882 alloc_string(s) 1883 char *s; 1884 { 1885 char *ns; 1886 1887 if (s == (char *)NULL) { 1888 ns = (char *)my_zalloc(1); 1889 } else { 1890 ns = (char *)my_zalloc(strlen(s) + 1); 1891 (void) strcpy(ns, s); 1892 } 1893 return (ns); 1894 } 1895 1896 /* 1897 * Follow symbolic links from the logical device name to 1898 * the /devfs physical device name. To be complete, we 1899 * handle the case of multiple links. This function 1900 * either returns NULL (no links, or some other error), 1901 * or the physical device name, alloc'ed on the heap. 1902 * 1903 * Note that the standard /devices prefix is stripped from 1904 * the final pathname, if present. The trailing options 1905 * are also removed (":c, raw"). 1906 */ 1907 static char * 1908 get_physical_name(char *path) 1909 { 1910 struct stat stbuf; 1911 int i; 1912 int level; 1913 char *p; 1914 char s[MAXPATHLEN]; 1915 char buf[MAXPATHLEN]; 1916 char dir[MAXPATHLEN]; 1917 char savedir[MAXPATHLEN]; 1918 char *result = NULL; 1919 1920 if (getcwd(savedir, sizeof (savedir)) == NULL) { 1921 DPRINTF1("getcwd() failed - %s\n", strerror(errno)); 1922 return (NULL); 1923 } 1924 1925 (void) strcpy(s, path); 1926 if ((p = strrchr(s, '/')) != NULL) { 1927 *p = 0; 1928 } 1929 if (s[0] == 0) { 1930 (void) strcpy(s, "/"); 1931 } 1932 if (chdir(s) == -1) { 1933 DPRINTF2("cannot chdir() to %s - %s\n", 1934 s, strerror(errno)); 1935 goto exit; 1936 } 1937 1938 level = 0; 1939 (void) strcpy(s, path); 1940 for (;;) { 1941 /* 1942 * See if there's a real file out there. If not, 1943 * we have a dangling link and we ignore it. 1944 */ 1945 if (stat(s, &stbuf) == -1) { 1946 goto exit; 1947 } 1948 if (lstat(s, &stbuf) == -1) { 1949 DPRINTF2("%s: lstat() failed - %s\n", 1950 s, strerror(errno)); 1951 goto exit; 1952 } 1953 /* 1954 * If the file is not a link, we're done one 1955 * way or the other. If there were links, 1956 * return the full pathname of the resulting 1957 * file. 1958 */ 1959 if (!S_ISLNK(stbuf.st_mode)) { 1960 if (level > 0) { 1961 /* 1962 * Strip trailing options from the 1963 * physical device name 1964 */ 1965 if ((p = strrchr(s, ':')) != NULL) { 1966 *p = 0; 1967 } 1968 /* 1969 * Get the current directory, and 1970 * glue the pieces together. 1971 */ 1972 if (getcwd(dir, sizeof (dir)) == NULL) { 1973 DPRINTF1("getcwd() failed - %s\n", 1974 strerror(errno)); 1975 goto exit; 1976 } 1977 (void) strcat(dir, "/"); 1978 (void) strcat(dir, s); 1979 /* 1980 * If we have the standard fixed 1981 * /devices prefix, remove it. 1982 */ 1983 p = (strstr(dir, DEVFS_PREFIX) == dir) ? 1984 dir+strlen(DEVFS_PREFIX) : dir; 1985 result = alloc_string(p); 1986 } 1987 goto exit; 1988 } 1989 i = readlink(s, buf, sizeof (buf)); 1990 if (i == -1) { 1991 DPRINTF2("%s: readlink() failed - %s\n", 1992 s, strerror(errno)); 1993 goto exit; 1994 } 1995 level++; 1996 buf[i] = 0; 1997 1998 /* 1999 * Break up the pathname into the directory 2000 * reference, if applicable and simple filename. 2001 * chdir()'ing to the directory allows us to 2002 * handle links with relative pathnames correctly. 2003 */ 2004 (void) strcpy(dir, buf); 2005 if ((p = strrchr(dir, '/')) != NULL) { 2006 *p = 0; 2007 if (chdir(dir) == -1) { 2008 DPRINTF2("cannot chdir() to %s - %s\n", 2009 dir, strerror(errno)); 2010 goto exit; 2011 } 2012 (void) strcpy(s, p+1); 2013 } else { 2014 (void) strcpy(s, buf); 2015 } 2016 } 2017 2018 exit: 2019 if (chdir(savedir) == -1) { 2020 (void) printf("cannot chdir() to %s - %s\n", 2021 savedir, strerror(errno)); 2022 } 2023 2024 return (result); 2025 } 2026 2027 static void 2028 get_media_info(device_t *t_dev, char *sdev, char *pname, char *sn) 2029 { 2030 struct dk_cinfo cinfo; 2031 struct vtoc vtocinfo; 2032 float size; 2033 int32_t fd; 2034 smedia_handle_t handle; 2035 struct dk_minfo mediainfo; 2036 int device_type; 2037 2038 device_type = ioctl(t_dev->d_fd, DKIOCGMEDIAINFO, &mediainfo); 2039 2040 /* 2041 * Determine bus type. 2042 */ 2043 if (!ioctl(t_dev->d_fd, DKIOCINFO, &cinfo)) { 2044 if (strstr(cinfo.dki_cname, "usb") || strstr(pname, "usb")) { 2045 (void) printf("\tBus: USB\n"); 2046 } else if (strstr(cinfo.dki_cname, "firewire") || 2047 strstr(pname, "firewire")) { 2048 (void) printf("\tBus: Firewire\n"); 2049 } else if (strstr(cinfo.dki_cname, "ide") || 2050 strstr(pname, "ide")) { 2051 (void) printf("\tBus: IDE\n"); 2052 } else if (strstr(cinfo.dki_cname, "scsi") || 2053 strstr(pname, "scsi")) { 2054 (void) printf("\tBus: SCSI\n"); 2055 } else { 2056 (void) printf("\tBus: <Unknown>\n"); 2057 } 2058 } else { 2059 (void) printf("\tBus: <Unknown>\n"); 2060 } 2061 2062 /* 2063 * Calculate size of media. 2064 */ 2065 if (!device_type && 2066 (!ioctl(t_dev->d_fd, DKIOCGMEDIAINFO, &mediainfo))) { 2067 size = (mediainfo.dki_lbsize* 2068 mediainfo.dki_capacity)/(1024.0*1024.0); 2069 if (size < 1000) { 2070 (void) printf("\tSize: %.1f MB\n", size); 2071 } else { 2072 size = size/1000; 2073 (void) printf("\tSize: %.1f GB\n", size); 2074 } 2075 } else { 2076 (void) printf("\tSize: <Unknown>\n"); 2077 } 2078 2079 /* 2080 * Print label. 2081 */ 2082 if (!device_type && (!ioctl(t_dev->d_fd, DKIOCGVTOC, &vtocinfo))) { 2083 if (*vtocinfo.v_volume) { 2084 (void) printf("\tLabel: %s\n", vtocinfo.v_volume); 2085 } else { 2086 (void) printf("\tLabel: <None>\n"); 2087 } 2088 } else { 2089 (void) printf("\tLabel: <Unknown>\n"); 2090 } 2091 2092 /* 2093 * Acess permissions. 2094 */ 2095 if (device_type) { 2096 (void) printf("\tAccess permissions: <Unknown>\n"); 2097 return; 2098 } 2099 2100 (void) fprintf(stderr, gettext("\tAccess permissions: ")); 2101 if (sn) { 2102 /* 2103 * Set dev_name for process_p_flag(). 2104 */ 2105 dev_name = sn; 2106 fd = my_open(sn, O_RDONLY|O_NDELAY); 2107 } else { 2108 dev_name = sdev; 2109 fd = my_open(sdev, O_RDONLY|O_NDELAY); 2110 } 2111 if (fd < 0) { 2112 (void) printf("<Unknown>\n"); 2113 DPRINTF("Could not open device.\n"); 2114 (void) close(fd); 2115 } else { 2116 /* register the fd with the libsmedia */ 2117 handle = smedia_get_handle(fd); 2118 if (handle == NULL) { 2119 (void) printf("<Unknown>\n"); 2120 DPRINTF("Failed to get libsmedia handle.\n"); 2121 (void) close(fd); 2122 } else { 2123 process_p_flag(handle, fd); 2124 } 2125 } 2126 /* Clear dev_name */ 2127 dev_name = NULL; 2128 } 2129