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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * Miscelleneous routines for rmformat.
32 #include <sys/types.h>
34 #include <sys/mnttab.h>
39 #include <sys/termios.h>
40 #include <sys/mount.h>
45 #include <priv_utils.h>
52 #define SENSE_KEY(rqbuf) (rqbuf[2] & 0xf) /* scsi error category */
53 #define ASC(rqbuf) (rqbuf[12]) /* additional sense code */
54 #define ASCQ(rqbuf) (rqbuf[13]) /* ASC qualifier */
56 #define DEFAULT_SCSI_TIMEOUT 60
57 #define INQUIRY_CMD 0x12
59 #define CD_RW 1 /* CD_RW/CD-R */
60 #define WRITE_10_CMD 0x2A
61 #define READ_INFO_CMD 0x51
62 #define SYNC_CACHE_CMD 0x35
63 #define CLOSE_TRACK_CMD 0x5B
64 #define MODE_SENSE_10_CMD 0x5A
65 #define DEVFS_PREFIX "/devices"
67 int uscsi_error
; /* used for debugging failed uscsi */
69 static uint_t total_retries
;
70 static struct uscsi_cmd uscmd
;
72 uchar_t uscsi_status
, rqstatus
, rqresid
;
73 int total_devices_found
= 0;
74 int removable_found
= 0;
76 extern char *global_intr_msg
;
77 extern int vol_running
;
78 extern char *dev_name
;
79 extern int32_t m_flag
;
82 * ON-private functions from libvolmgt
84 int _dev_mounted(char *path
);
87 * Function prototypes.
89 static int my_umount(char *mountp
);
90 static int my_volrmmount(char *real_name
);
91 static int vol_name_to_dev_node(char *vname
, char *found
);
92 static int vol_lookup(char *supplied
, char *found
);
93 static device_t
*get_device(char *user_supplied
, char *node
);
94 static char *get_physical_name(char *path
);
95 static int lookup_device(char *supplied
, char *found
);
96 static void fini_device(device_t
*dev
);
97 static int is_cd(char *node
);
98 void *my_zalloc(size_t size
);
99 void err_msg(char *fmt
, ...);
100 int inquiry(int fd
, uchar_t
*inq
);
101 struct uscsi_cmd
*get_uscsi_cmd(void);
102 int uscsi(int fd
, struct uscsi_cmd
*scmd
);
103 int get_mode_page(int fd
, int page_no
, int pc
, int buf_len
,
105 int mode_sense(int fd
, uchar_t pc
, int dbd
, int page_len
,
107 uint16_t read_scsi16(void *addr
);
108 int check_device(device_t
*dev
, int cond
);
109 static void get_media_info(device_t
*t_dev
, char *sdev
,
110 char *pname
, char *sn
);
112 extern void process_p_flag(smedia_handle_t handle
, int32_t fd
);
115 my_perror(char *err_string
)
123 (void) fprintf(stderr
, "%s", err_string
);
124 (void) fprintf(stderr
, gettext(" : "));
134 (void) fprintf(stderr
, gettext("Do you want to continue? (y/n)"));
136 if (c
== 'y' || c
== 'Y')
138 else if (c
== 'n' || c
== 'N')
141 (void) fprintf(stderr
, gettext("Invalid choice\n"));
148 get_passwd(struct smwp_state
*wp
, int32_t confirm
)
150 char passwd
[256], re_passwd
[256];
153 int32_t echo_off
= 0;
158 in
= fopen("/dev/tty", "r+");
166 /* Turn echoing off if it is on now. */
168 if (tcgetattr(fileno(in
), &tio
) < 0) {
169 PERROR("Echo off ioctl failed");
172 if (tio
.c_lflag
& ECHO
) {
173 tio
.c_lflag
&= ~ECHO
;
174 /* echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0; */
175 echo_off
= tcsetattr(fileno(in
), TCSAFLUSH
, &tio
) == 0;
182 gettext("Please enter password (32 chars maximum):"),
185 buf
= fgets(passwd
, (size_t)256, in
);
188 PERROR("Error reading password");
191 len
= strlen(passwd
);
192 (void) fputc('\n', out
);
193 len
--; /* To offset the \n */
194 if ((len
<= 0) || (len
> 32)) {
195 (void) fprintf(stderr
,
196 gettext("Invalid length of password \n"));
197 (void) fputs("Try again\n", out
);
204 (void) fputs("Please reenter password:", out
);
206 buf
= fgets(re_passwd
, (size_t)256, in
);
208 (void) fputc('\n', out
);
209 if ((buf
== NULL
) || strcmp(passwd
, re_passwd
)) {
210 (void) fputs("passwords did not match\n", out
);
211 (void) fputs("Try again\n", out
);
216 wp
->sm_passwd_len
= len
;
217 (void) strncpy(wp
->sm_passwd
, passwd
, wp
->sm_passwd_len
);
218 wp
->sm_version
= SMWP_STATE_V_1
;
220 /* Restore echoing. */
222 (void) tcsetattr(fileno(in
), TCSAFLUSH
, &tio
);
227 check_and_unmount_vold(char *device_name
, int32_t flag
)
231 char tmp_path_name
[PATH_MAX
];
232 struct stat stat_buf
;
238 DPRINTF1("Device name %s\n", device_name
);
240 if (volmgt_running() == 0) {
241 DPRINTF("Vold not running\n");
244 if ((nm
= volmgt_symname(device_name
)) == NULL
) {
245 DPRINTF("path not managed\n");
246 real_name
= media_findname(device_name
);
248 DPRINTF1("path managed as %s\n", nm
);
249 real_name
= media_findname(nm
);
250 DPRINTF1("real name %s\n", real_name
);
253 if (real_name
== NULL
)
257 * To find out whether the device has been mounted by
260 * Convert the real name to a block device address.
261 * Do a partial match with the mnttab entries.
262 * Make sure the match is in the beginning to avoid if
263 * anybody puts a label similiar to volume manager path names.
264 * Then use "volrmmount -e <dev_name>" if -U flag is set.
267 nl
= strlen("/vol/dev/");
269 if (strncmp(real_name
, "/vol/dev/", nl
) != 0)
271 if (real_name
[nl
] == 'r') {
272 (void) snprintf(tmp_path_name
, PATH_MAX
, "%s%s", "/vol/dev/",
275 (void) snprintf(tmp_path_name
, PATH_MAX
, "%s", real_name
);
277 DPRINTF1("%s \n", tmp_path_name
);
278 ret_val
= stat(tmp_path_name
, &stat_buf
);
280 PERROR("Could not stat");
284 fp
= fopen("/etc/mnttab", "r");
287 PERROR("Could not open /etc/mnttab");
291 mntp
= (struct mnttab
*)malloc(sizeof (struct mnttab
));
293 PERROR("malloc failed");
298 while (getmntent(fp
, mntp
) == 0) {
300 PERROR("Error with mnttab");
304 /* Is it a probable entry? */
305 DPRINTF1(" %s \n", mntp
->mnt_special
);
306 if (strstr(mntp
->mnt_special
, tmp_path_name
) !=
308 /* Skip to next entry */
311 DPRINTF1("Found!! %s\n", mntp
->mnt_special
);
319 if (my_volrmmount(real_name
) < 0) {
332 * This routine checks if a device has mounted partitions. The
333 * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can
334 * be used for SCSI and PCMCIA cards.
337 * 1 : if successfully unmounted
338 * -1 : Any error or umount failed
342 check_and_unmount_scsi(char *device_name
, int32_t flag
)
345 struct mnttab
*mntrefp
;
348 char block_dev_name
[PATH_MAX
];
349 char tmp_name
[PATH_MAX
];
351 int32_t unmounted
= 0;
354 * If the device name is not a character special, anyway we
355 * can not progress further
358 if (strncmp(device_name
, "/dev/rdsk/c", strlen("/dev/rdsk/c")) != 0)
361 (void) snprintf(block_dev_name
, PATH_MAX
, "/dev/%s",
362 &device_name
[strlen("/dev/r")]);
363 fp
= fopen("/etc/mnttab", "r");
366 PERROR("Could not open /etc/mnttab");
370 mntrefp
= (struct mnttab
*)malloc(sizeof (struct mnttab
));
371 if (mntrefp
== NULL
) {
372 PERROR("malloc failed");
377 mntp
= (struct mnttab
*)malloc(sizeof (struct mnttab
));
379 PERROR("malloc failed");
385 /* Try all the partitions */
387 (void) snprintf(tmp_name
, PATH_MAX
, "/dev/%s",
388 &device_name
[strlen("/dev/r")]);
390 tmp_name
[strlen("/dev/dsk/c0t0d0s")] = '\0';
393 while (getmntent(fp
, mntp
) == 0) {
395 PERROR("Error with mnttab");
399 /* Is it a probable entry? */
400 if (strncmp(mntp
->mnt_special
, tmp_name
, strlen(tmp_name
))) {
401 /* Skip to next entry */
404 for (i
= 0; i
< NDKMAP
; i
++) {
405 /* Check for ufs style mount devices */
406 (void) snprintf(block_dev_name
, PATH_MAX
,
407 "%s%d", tmp_name
, i
);
409 if (strcmp(mntp
->mnt_special
, block_dev_name
) == 0) {
411 if (my_umount(mntp
->mnt_mountp
) < 0) {
420 /* Skip to next entry */
424 /* Try for :1 -> :24 for pcfs */
426 for (j
= 1; j
< 24; j
++) {
427 (void) snprintf(block_dev_name
, PATH_MAX
,
428 "%s%d:%d", tmp_name
, i
, j
);
430 if (strcmp(mntp
->mnt_special
,
431 block_dev_name
) == 0) {
433 if (my_umount(mntp
->mnt_mountp
)
443 /* Skip to next entry */
446 (void) snprintf(block_dev_name
, PATH_MAX
,
447 "%s%d:%c", tmp_name
, i
, 'b' + j
);
449 if (strcmp(mntp
->mnt_special
,
450 block_dev_name
) == 0) {
452 if (my_umount(mntp
->mnt_mountp
)
462 /* Skip to next entry */
476 * This routine checks if a device has mounted partitions. The
477 * device name is assumed to be /dev/rdiskette. So, this can
478 * be used for Floppy controllers
481 * 1 : if successfully unmounted
482 * -1 : Any error or unmount failed
486 check_and_unmount_floppy(int32_t fd
, int32_t flag
)
490 struct dk_cinfo dkinfo
, dkinfo_tmp
;
491 struct mnttab mnt_record
;
492 struct mnttab
*mp
= &mnt_record
;
494 char raw_device
[PATH_MAX
];
498 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) < 0) {
502 if ((fp
= fopen(MNTTAB
, "r")) == NULL
) {
503 PERROR("Could not open /etc/mnttab");
508 while (getmntent(fp
, mp
) == 0) {
509 if (strstr(mp
->mnt_special
, "/dev/fd") == NULL
&&
510 strstr(mp
->mnt_special
, "/dev/disket") == NULL
&&
511 strstr(mp
->mnt_special
, "/dev/c") == NULL
) {
515 (void) strcpy(raw_device
, "/dev/r");
516 (void) strcat(raw_device
, mp
->mnt_special
+ strlen("/dev/"));
520 * Attempt to open the device. If it fails, skip it.
523 /* Turn on the privileges. */
524 (void) __priv_bracket(PRIV_ON
);
526 mfd
= open(raw_device
, O_RDWR
| O_NDELAY
);
528 /* Turn off the privileges. */
529 (void) __priv_bracket(PRIV_OFF
);
536 * Must be a character device
538 if (fstat(mfd
, &stbuf
) < 0 || !S_ISCHR(stbuf
.st_mode
)) {
543 * Attempt to read the configuration info on the disk.
545 if (ioctl(mfd
, DKIOCINFO
, &dkinfo_tmp
) < 0) {
550 * Finished with the opened device
555 * If it's not the disk we're interested in, it doesn't apply.
557 if (dkinfo
.dki_ctype
!= dkinfo_tmp
.dki_ctype
||
558 dkinfo
.dki_cnum
!= dkinfo_tmp
.dki_cnum
||
559 dkinfo
.dki_unit
!= dkinfo_tmp
.dki_unit
) {
563 * It's a mount on the disk we're checking. If we are
564 * checking whole disk, then we found trouble. We can
569 if (my_umount(mp
->mnt_mountp
) < 0) {
582 my_open(char *device_name
, int32_t flags
)
586 char tmp_path_name
[PATH_MAX
];
587 struct stat stat_buf
;
590 int32_t have_read_priv
= 0;
594 DPRINTF1("Device name %s\n", device_name
);
596 if ((nm
= volmgt_symname(device_name
)) == NULL
) {
597 DPRINTF("path not managed\n");
598 real_name
= media_findname(device_name
);
600 DPRINTF1("path managed as %s\n", nm
);
601 real_name
= media_findname(nm
);
602 DPRINTF1("real name %s\n", real_name
);
605 if (real_name
== NULL
)
608 (void) strcpy(tmp_path_name
, real_name
);
609 ret_val
= stat(tmp_path_name
, &stat_buf
);
611 PERROR("Could not stat");
614 if (S_ISDIR(stat_buf
.st_mode
)) {
617 * Open the directory and look for the
618 * first non '.' entry.
619 * Since raw_read and raw_writes are used, we don't
620 * need to access the backup slice.
621 * For PCMCIA Memory cards, raw_read and raw_writes are
622 * not supported, but that is not a problem as, only slice2
623 * is allowed on PCMCIA memory cards.
627 * First make sure we are operating with a /vol/....
628 * Otherwise it can dangerous,
629 * e.g. rmformat -s /dev/rdsk
630 * We should not look into the directory contents here.
632 if (strncmp(tmp_path_name
, "/vol/dev/", strlen("/vol/dev/"))
634 (void) fprintf(stderr
, gettext("The specified device \
635 is not a raw device.\n"));
639 /* Turn on the privileges. */
640 (void) __priv_bracket(PRIV_ON
);
642 dirp
= opendir(tmp_path_name
);
644 /* Turn off the privileges. */
645 (void) __priv_bracket(PRIV_OFF
);
651 /* Turn on the privileges. */
652 (void) __priv_bracket(PRIV_ON
);
655 while ((dp
= readdir(dirp
)) != NULL
) {
657 /* Turn off the privileges. */
658 (void) __priv_bracket(PRIV_OFF
);
661 DPRINTF1("Found %s\n", dp
->d_name
);
662 if ((strcmp(dp
->d_name
, ".") != 0) &&
663 (strcmp(dp
->d_name
, "..") != 0)) {
664 (void) snprintf(tmp_path_name
, PATH_MAX
,
665 "%s/%s", tmp_path_name
, dp
->d_name
);
667 DPRINTF1("tmp_pathname is %s\n", tmp_path_name
);
671 /* Turn on the privileges. */
672 (void) __priv_bracket(PRIV_ON
);
676 if (have_read_priv
) {
677 /* drop the file_dac_read privilege */
678 (void) __priv_bracket(PRIV_OFF
);
682 (void) closedir(dirp
);
686 if (volmgt_running() == 0) {
687 /* Turn on privileges. */
688 (void) __priv_bracket(PRIV_ON
);
692 fd
= open(tmp_path_name
, flags
);
694 if (have_read_priv
) {
695 /* Turn off privileges. */
696 (void) __priv_bracket(PRIV_OFF
);
700 DPRINTF1("path opened %s\n", tmp_path_name
);
713 if (isdigit(*tmp_ptr
))
722 if (strlen(tmp_ptr
) < 3) {
725 if (*tmp_ptr
++ != '0' || (*tmp_ptr
!= 'x' && *tmp_ptr
!= 'X')) {
730 if (isxdigit(*tmp_ptr
))
737 ret_val
= (uint64_t)strtoull(ptr
, (char **)NULL
, 0);
742 write_sunos_label(int32_t fd
, int32_t media_type
)
745 struct extvtoc v_toc
;
748 (void) memset(&v_toc
, 0, sizeof (struct extvtoc
));
750 /* Initialize the vtoc information */
752 if (media_type
== SM_FLOPPY
) {
753 struct fd_char fdchar
;
756 if (ioctl(fd
, FDIOGCHAR
, &fdchar
) < 0) {
757 PERROR("FDIOGCHAR failed");
761 /* SPARC and x86 fd drivers use fdc_medium differently */
763 mult_factor
= (fdchar
.fdc_medium
) ? 2 : 1;
765 mult_factor
= (fdchar
.fdc_medium
== 5) ? 2 : 1;
767 #error No Platform defined
768 #endif /* defined(__sparc) */
770 /* initialize the vtoc structure */
773 v_toc
.v_part
[0].p_start
= 0;
774 v_toc
.v_part
[0].p_size
= (fdchar
.fdc_ncyl
- 1) * 2 *
775 fdchar
.fdc_secptrack
* mult_factor
;
776 v_toc
.v_part
[1].p_start
= (fdchar
.fdc_ncyl
- 1) * 2 *
777 fdchar
.fdc_secptrack
* mult_factor
;
778 v_toc
.v_part
[1].p_size
= 2 * fdchar
.fdc_secptrack
* mult_factor
;
780 v_toc
.v_part
[2].p_start
= 0;
781 v_toc
.v_part
[2].p_size
= fdchar
.fdc_ncyl
* 2 *
782 fdchar
.fdc_secptrack
* mult_factor
;
784 } else if (media_type
== SM_SCSI_FLOPPY
) {
786 smedia_handle_t handle
;
787 smmedium_prop_t med_info
;
788 struct dk_geom dkgeom
;
792 * call smedia_get_medium_property to get the
793 * correct media information, since DKIOCGMEDIAINFO
794 * may fail for unformatted media.
797 handle
= smedia_get_handle(fd
);
798 if (handle
== NULL
) {
799 (void) fprintf(stderr
,
800 gettext("Failed to get libsmedia handle.\n"));
807 if (smedia_get_medium_property(handle
, &med_info
) < 0) {
808 (void) fprintf(stderr
,
809 gettext("Get medium property failed \n"));
811 (void) smedia_release_handle(handle
);
816 /* Fill in our own geometry information */
818 dkgeom
.dkg_pcyl
= med_info
.sm_pcyl
;
819 dkgeom
.dkg_ncyl
= med_info
.sm_pcyl
;
820 dkgeom
.dkg_nhead
= med_info
.sm_nhead
;
821 dkgeom
.dkg_nsect
= med_info
.sm_nsect
;
824 dkgeom
.dkg_intrlv
= 0;
828 * Try to set vtoc, if not successful we will
829 * continue to use the faked geometry information.
832 (void) ioctl(fd
, DKIOCSGEOM
, &dkgeom
);
834 (void) smedia_release_handle(handle
);
836 /* we want the same partitioning as used for normal floppies */
838 v_toc
.v_part
[0].p_start
= 0;
839 v_toc
.v_part
[0].p_size
= (diskaddr_t
)(dkgeom
.dkg_ncyl
- 1) *
840 dkgeom
.dkg_nhead
* dkgeom
.dkg_nsect
;
842 v_toc
.v_part
[1].p_start
= (diskaddr_t
)(dkgeom
.dkg_ncyl
- 1) *
843 dkgeom
.dkg_nhead
* dkgeom
.dkg_nsect
;
844 v_toc
.v_part
[1].p_size
= dkgeom
.dkg_nhead
* dkgeom
.dkg_nsect
;
846 v_toc
.v_part
[2].p_start
= 0;
847 v_toc
.v_part
[2].p_size
= (diskaddr_t
)dkgeom
.dkg_ncyl
*
848 dkgeom
.dkg_nhead
* dkgeom
.dkg_nsect
;
850 /* both write_vtoc and DKIOCSVTOC require V_NUMPAR partitions */
851 v_toc
.v_nparts
= V_NUMPAR
;
858 v_toc
.v_sanity
= VTOC_SANE
;
859 v_toc
.v_version
= V_VERSION
;
862 * The label structure is set up for DEV_BSIZE(512 byte) blocks,
863 * even though a medium density diskette has 1024 byte blocks
864 * See dklabel.h for more details.
866 v_toc
.v_sectorsz
= DEV_BSIZE
;
868 /* let the fd driver finish constructing the label and writing it. */
871 /* Turn on the privileges. */
872 (void) __priv_bracket(PRIV_ON
);
874 ret
= write_extvtoc(fd
, &v_toc
);
876 /* Turn off the privileges. */
877 (void) __priv_bracket(PRIV_OFF
);
880 PERROR("Write vtoc");
881 DPRINTF1("Write vtoc failed errno:%d\n", errno
);
893 (void) fprintf(stderr
, gettext(global_intr_msg
));
894 (void) fprintf(stderr
,
895 gettext("\nDo you want to stop formatting?(y/n)"));
896 (void) fflush(stdout
);
898 while ((c
= getchar()) == -1)
900 if (c
== 'y' || c
== 'Y') {
901 (void) fprintf(stderr
, gettext("Format interrupted\n"));
903 } else if (c
== 'n' || c
== 'N')
906 (void) fprintf(stderr
, gettext("Did not interrupt\n"));
911 static struct sigaction act
, oact
;
916 act
.sa_handler
= intr_sig_handler
;
917 (void) memset(&act
.sa_mask
, 0, sizeof (sigset_t
));
918 act
.sa_flags
= SA_RESTART
; /* | SA_NODEFER; */
919 if (sigaction(SIGINT
, &act
, &oact
) < 0) {
920 DPRINTF("sigset failed\n");
928 if (sigaction(SIGINT
, &oact
, NULL
) < 0) {
929 DPRINTF("sigunset failed\n");
935 verify(smedia_handle_t handle
, int32_t fd
, diskaddr_t start_sector
,
936 uint32_t nblocks
, char *buf
,
937 int32_t flag
, int32_t blocksize
, int32_t no_raw_rw
)
941 DPRINTF("ANALYSE MEDIA \n");
944 if ((flag
== VERIFY_READ
) && (!no_raw_rw
)) {
946 /* Turn on the privileges. */
947 (void) __priv_bracket(PRIV_ON
);
949 ret
= smedia_raw_read(handle
, start_sector
, buf
, nblocks
*
952 /* Turn off the privileges. */
953 (void) __priv_bracket(PRIV_OFF
);
955 if (ret
!= (nblocks
* blocksize
))
959 } else if ((flag
== VERIFY_WRITE
) && (!no_raw_rw
)) {
961 /* Turn on privileges. */
962 (void) __priv_bracket(PRIV_ON
);
964 ret
= smedia_raw_write(handle
, start_sector
, buf
, nblocks
*
967 /* Turn off the privileges. */
968 (void) __priv_bracket(PRIV_OFF
);
970 if (ret
!= (blocksize
* nblocks
))
974 } else if ((flag
== VERIFY_READ
) && (no_raw_rw
)) {
975 ret
= llseek(fd
, start_sector
* blocksize
, SEEK_SET
);
976 if (ret
!= start_sector
* blocksize
) {
977 (void) fprintf(stderr
, gettext("Seek failed\n"));
981 /* Turn on the privileges. */
982 (void) __priv_bracket(PRIV_ON
);
984 ret
= read(fd
, buf
, nblocks
* blocksize
);
986 /* Turn off the privileges. */
987 (void) __priv_bracket(PRIV_OFF
);
989 if (ret
!= nblocks
* blocksize
) {
993 } else if ((flag
== VERIFY_WRITE
) && (no_raw_rw
)) {
994 ret
= llseek(fd
, start_sector
* blocksize
, SEEK_SET
);
995 if (ret
!= start_sector
* blocksize
) {
996 (void) fprintf(stderr
, gettext("Seek failed\n"));
1000 /* Turn on the privileges. */
1001 (void) __priv_bracket(PRIV_ON
);
1003 ret
= write(fd
, buf
, nblocks
* blocksize
);
1005 /* Turn off the privileges. */
1006 (void) __priv_bracket(PRIV_OFF
);
1008 if (ret
!= nblocks
* blocksize
) {
1013 DPRINTF("Illegal parameter to verify_analysis!\n");
1019 my_umount(char *mountp
)
1021 pid_t pid
; /* forked proc's pid */
1022 int rval
; /* proc's return value */
1025 /* create a child to unmount the path */
1027 /* Turn on the privileges */
1028 (void) __priv_bracket(PRIV_ON
);
1032 /* Turn off the privileges. */
1033 (void) __priv_bracket(PRIV_OFF
);
1036 PERROR("fork failed");
1042 /* get rid of those nasty err messages */
1043 DPRINTF1("call_unmount_prog: calling %s \n", mountp
);
1045 /* Turn on the priviliges. */
1046 (void) __priv_bracket(PRIV_ON
);
1048 if (execl("/usr/sbin/umount", "/usr/sbin/umount", mountp
,
1050 perror("exec failed");
1051 /* Turn off the privileges */
1052 (void) __priv_bracket(PRIV_OFF
);
1057 /* wait for the umount command to exit */
1059 if (waitpid(pid
, &rval
, 0) == pid
) {
1060 if (WIFEXITED(rval
)) {
1061 if (WEXITSTATUS(rval
) == 0) {
1062 DPRINTF("umount : Success\n");
1071 my_volrmmount(char *real_name
)
1075 /* Turn on the privileges. */
1076 (void) __priv_bracket(PRIV_ON
);
1080 /* Turn off the privileges. */
1081 (void) __priv_bracket(PRIV_OFF
);
1083 /* create a child to unmount the path */
1085 PERROR("fork failed");
1091 /* get rid of those nasty err messages */
1092 DPRINTF1("call_unmount_prog: calling %s \n",
1093 "/usr/bin/volrmmount");
1095 /* Turn on the privileges. */
1096 (void) __priv_bracket(PRIV_ON
);
1097 if (execl("/usr/bin/volrmmount", "/usr/bin/volrmmount", "-e",
1098 real_name
, NULL
) < 0) {
1099 PERROR("volrmmount exec failed");
1100 /* Turn off the privileges */
1101 (void) __priv_bracket(PRIV_OFF
);
1104 } else if (waitpid(pid
, &rval
, 0) == pid
) {
1105 if (WIFEXITED(rval
)) {
1106 if (WEXITSTATUS(rval
) == 0) {
1107 DPRINTF("volrmmount: Success\n");
1116 find_device(int defer
, char *tmpstr
)
1119 struct dirent
*dirent
;
1120 char sdev
[PATH_MAX
], dev
[PATH_MAX
], *pname
;
1123 int device_type
= 0;
1124 int hotpluggable
= 0;
1125 struct dk_minfo mediainfo
;
1126 static int found
= 0;
1128 dir
= opendir("/dev/rdsk");
1132 total_devices_found
= 0;
1133 while ((dirent
= readdir(dir
)) != NULL
) {
1134 if (dirent
->d_name
[0] == '.') {
1137 (void) snprintf(sdev
, PATH_MAX
, "/dev/rdsk/%s",
1140 if (!strstr(sdev
, "s2")) {
1145 if (!(strstr(sdev
, "s2") || strstr(sdev
, "p0"))) {
1149 if (!strstr(sdev
, "p0")) {
1154 if (!lookup_device(sdev
, dev
)) {
1157 if ((t_dev
= get_device(NULL
, dev
)) == NULL
) {
1160 total_devices_found
++;
1162 if ((!defer
) && !found
) {
1165 * dev_name is an optional command line input.
1168 if (strstr(dirent
->d_name
, tmpstr
)) {
1170 } else if (!vol_running
) {
1175 * volmgt_symname() returns NULL if the device
1176 * is not managed by volmgt.
1178 sn
= volmgt_symname(sdev
);
1180 if (vol_running
&& (sn
!= NULL
)) {
1181 if (strstr(sn
, "dev") == NULL
) {
1182 tmpbuf
= (char *)my_zalloc(PATH_MAX
);
1183 (void) strcpy(tmpbuf
,
1184 "/vol/dev/aliases/");
1185 (void) strcat(tmpbuf
, sn
);
1189 if (dev_name
&& !found
) {
1190 if (!strstr(tmpbuf
, tmpstr
)) {
1199 * Get device type information for CD/DVD devices.
1202 if (check_device(t_dev
,
1203 CHECK_DEVICE_IS_DVD_WRITABLE
)) {
1204 device_type
= DK_DVDR
;
1205 } else if (check_device(t_dev
,
1206 CHECK_DEVICE_IS_DVD_READABLE
)) {
1207 device_type
= DK_DVDROM
;
1208 } else if (check_device(t_dev
,
1209 CHECK_DEVICE_IS_CD_WRITABLE
)) {
1210 device_type
= DK_CDR
;
1212 device_type
= DK_CDROM
;
1215 device_type
= ioctl(t_dev
->d_fd
,
1216 DKIOCGMEDIAINFO
, &mediainfo
);
1217 if (device_type
< 0)
1220 device_type
= mediainfo
.dki_media_type
;
1223 if (!ioctl(t_dev
->d_fd
, DKIOCREMOVABLE
, &removable
) &&
1224 !ioctl(t_dev
->d_fd
, DKIOCHOTPLUGGABLE
,
1226 if (removable
|| hotpluggable
) {
1228 pname
= get_physical_name(sdev
);
1230 (void) printf(" %4d. "
1231 "Volmgt Node: %s\n",
1232 removable_found
, sn
);
1234 "Logical Node: %s\n", sdev
);
1236 "Physical Node: %s\n",
1239 (void) printf(" %4d. "
1240 "Logical Node: %s\n",
1241 removable_found
, sdev
);
1243 "Physical Node: %s\n",
1246 (void) printf(" Connected "
1247 "Device: %-8.8s %-16.16s "
1252 (void) printf(" Device "
1259 switch (device_type
) {
1261 (void) printf("CD Reader\n");
1265 (void) printf("CD Reader/Writer\n");
1268 (void) printf("DVD Reader\n");
1272 (void) printf("DVD Reader/Writer\n");
1275 if (strstr((const char *)
1276 &t_dev
->d_inq
[16], "FD") ||
1277 strstr((const char *)
1278 &t_dev
->d_inq
[16], "LS-120"))
1279 (void) printf("Floppy "
1282 (void) printf("Removable\n");
1285 (void) printf("Floppy drive\n");
1288 (void) printf("Zip drive\n");
1291 (void) printf("Jaz drive\n");
1294 (void) printf("<Unknown>\n");
1295 DPRINTF1("\t %d\n", device_type
);
1298 get_media_info(t_dev
, sdev
, pname
, sn
);
1303 (void) closedir(dir
);
1304 return (removable_found
);
1308 * Returns a device_t handle for a node returned by lookup_device()
1309 * and takes the user supplied name and stores it inside the node.
1312 get_device(char *user_supplied
, char *node
)
1316 char devnode
[PATH_MAX
];
1320 * we need to resolve any link paths to avoid fake files
1321 * such as /dev/rdsk/../../export/file.
1323 size
= resolvepath(node
, devnode
, PATH_MAX
);
1324 if ((size
<= 0) || (size
>= (PATH_MAX
- 1)))
1327 /* resolvepath may not return a null terminated string */
1328 devnode
[size
] = '\0';
1331 /* the device node must be in /devices/ or /vol/dev/rdsk */
1333 if ((strncmp(devnode
, "/devices/", 9) != 0) &&
1334 (strncmp(devnode
, "/vol/dev/rdsk", 13) != 0))
1337 /* Turn on the privileges. */
1338 (void) __priv_bracket(PRIV_ON
);
1341 * Since we are currently running with the user euid it is
1342 * safe to try to open the file without checking access.
1345 fd
= open(devnode
, O_RDONLY
|O_NDELAY
);
1347 /* Turn off the privileges. */
1348 (void) __priv_bracket(PRIV_OFF
);
1354 dev
= (device_t
*)my_zalloc(sizeof (device_t
));
1356 dev
->d_node
= (char *)my_zalloc(strlen(devnode
) + 1);
1357 (void) strcpy(dev
->d_node
, devnode
);
1361 dev
->d_inq
= (uchar_t
*)my_zalloc(INQUIRY_DATA_LENGTH
);
1363 /* Turn on privileges. */
1364 (void) __priv_bracket(PRIV_ON
);
1365 if (!inquiry(fd
, dev
->d_inq
)) {
1366 DPRINTF1("USCSI ioctl failed %d\n",
1370 (void) close(dev
->d_fd
);
1372 /* Turn off privileges. */
1373 (void) __priv_bracket(PRIV_OFF
);
1376 /* Turn off privileges. */
1377 (void) __priv_bracket(PRIV_OFF
);
1379 if (user_supplied
) {
1380 dev
->d_name
= (char *)my_zalloc(strlen(user_supplied
) + 1);
1381 (void) strcpy(dev
->d_name
, user_supplied
);
1387 * Check for device specific characteristics.
1390 check_device(device_t
*dev
, int cond
)
1392 uchar_t page_code
[4];
1394 /* Look at the capabilities page for this information */
1395 if (cond
& CHECK_DEVICE_IS_CD_WRITABLE
) {
1396 if (get_mode_page(dev
->d_fd
, 0x2a, 0, 4, page_code
) &&
1397 (page_code
[3] & 1)) {
1402 if (cond
& CHECK_DEVICE_IS_DVD_WRITABLE
) {
1403 if (get_mode_page(dev
->d_fd
, 0x2a, 0, 4, page_code
) &&
1404 (page_code
[3] & 0x10)) {
1409 if (cond
& CHECK_DEVICE_IS_DVD_READABLE
) {
1410 if (get_mode_page(dev
->d_fd
, 0x2a, 0, 4, page_code
) &&
1411 (page_code
[2] & 0x8)) {
1420 * Builds an open()able device path from a user supplied node which can be
1421 * of the * form of /dev/[r]dsk/cxtxdx[sx] or cxtxdx[sx] or volmgt-name like
1423 * Returns the path found in 'found' and returns 1. Otherwise returns 0.
1426 lookup_device(char *supplied
, char *found
)
1428 struct stat statbuf
;
1430 char tmpstr
[PATH_MAX
];
1432 /* Turn on privileges */
1433 (void) __priv_bracket(PRIV_ON
);
1435 /* If everything is fine and proper, no need to analyze */
1436 if ((stat(supplied
, &statbuf
) == 0) && S_ISCHR(statbuf
.st_mode
) &&
1437 ((fd
= open(supplied
, O_RDONLY
|O_NDELAY
)) >= 0)) {
1439 (void) strlcpy(found
, supplied
, PATH_MAX
);
1440 /* Turn off privilege */
1441 (void) __priv_bracket(PRIV_OFF
);
1445 /* Turn off privileges. */
1446 (void) __priv_bracket(PRIV_OFF
);
1448 if (strncmp(supplied
, "/dev/rdsk/", 10) == 0)
1449 return (vol_lookup(supplied
, found
));
1450 if (strncmp(supplied
, "/dev/dsk/", 9) == 0) {
1451 (void) snprintf(tmpstr
, PATH_MAX
, "/dev/rdsk/%s",
1452 (char *)strrchr(supplied
, '/'));
1454 if ((fd
= open(tmpstr
, O_RDONLY
|O_NDELAY
)) >= 0) {
1456 (void) strlcpy(found
, supplied
, PATH_MAX
);
1459 if ((access(tmpstr
, F_OK
) == 0) && vol_running
)
1460 return (vol_lookup(tmpstr
, found
));
1464 if ((strncmp(supplied
, "cdrom", 5) != 0) &&
1465 (strlen(supplied
) < 32)) {
1466 (void) snprintf(tmpstr
, sizeof (tmpstr
), "/dev/rdsk/%s",
1468 if (access(tmpstr
, F_OK
) < 0) {
1469 (void) strcat(tmpstr
, "s2");
1471 if ((fd
= open(tmpstr
, O_RDONLY
|O_NDELAY
)) >= 0) {
1473 (void) strlcpy(found
, tmpstr
, PATH_MAX
);
1476 if ((access(tmpstr
, F_OK
) == 0) && vol_running
)
1477 return (vol_lookup(tmpstr
, found
));
1479 return (vol_name_to_dev_node(supplied
, found
));
1486 struct dk_cinfo cinfo
;
1488 fd
= open(node
, O_RDONLY
|O_NDELAY
);
1491 if (ioctl(fd
, DKIOCINFO
, &cinfo
) < 0) {
1495 if (cinfo
.dki_ctype
!= DKC_CDROM
)
1503 /* l10n_NOTE : Column spacing should be kept same */
1504 (void) printf(gettext(" Node "
1505 "Connected Device"));
1506 /* l10n_NOTE : Column spacing should be kept same */
1507 (void) printf(gettext(" Device type\n"));
1509 "---------------------------+---------------------------");
1510 (void) printf("-----+----------------\n");
1517 "---------------------------+---------------------------");
1518 (void) printf("-----+----------------\n");
1522 fini_device(device_t
*dev
)
1526 (void) close(dev
->d_fd
);
1532 my_zalloc(size_t size
)
1539 /* Lets wait a sec. and try again */
1540 if (errno
== EAGAIN
) {
1546 (void) err_msg("%s\n", gettext(strerror(errno
)));
1547 (void) err_msg(gettext(
1548 "Memory allocation failure, Exiting...\n"));
1552 (void) memset(ret
, 0, size
);
1557 vol_name_to_dev_node(char *vname
, char *found
)
1559 struct stat statbuf
;
1566 (void) volmgt_check(vname
);
1567 p1
= media_findname(vname
);
1570 if (stat(p1
, &statbuf
) < 0) {
1574 if (S_ISDIR(statbuf
.st_mode
)) {
1575 for (i
= 0; i
< 16; i
++) {
1576 (void) snprintf(found
, PATH_MAX
, "%s/s%d", p1
, i
);
1577 if (access(found
, F_OK
) >= 0)
1585 (void) strlcpy(found
, p1
, PATH_MAX
);
1592 * Searches for volume manager's equivalent char device for the
1593 * supplied pathname which is of the form of /dev/rdsk/cxtxdxsx
1596 vol_lookup(char *supplied
, char *found
)
1598 char tmpstr
[PATH_MAX
], tmpstr1
[PATH_MAX
], *p
;
1601 (void) strlcpy(tmpstr
, supplied
, PATH_MAX
);
1602 if ((p
= volmgt_symname(tmpstr
)) == NULL
) {
1603 if (strstr(tmpstr
, "s2") != NULL
) {
1604 *((char *)(strrchr(tmpstr
, 's') + 1)) = 0;
1605 for (i
= 0; i
< 16; i
++) {
1606 (void) snprintf(tmpstr1
, PATH_MAX
, "%s%d",
1608 if ((p
= volmgt_symname(tmpstr1
)) != NULL
)
1611 } else if (strstr(tmpstr
, "p0") != NULL
) {
1612 *((char *)(strrchr(tmpstr
, 'p') + 1)) = 0;
1613 for (i
= 0; i
< 5; i
++) {
1614 (void) snprintf(tmpstr1
, PATH_MAX
, "%s%d",
1616 if ((p
= volmgt_symname(tmpstr1
)) != NULL
)
1625 ret
= vol_name_to_dev_node(p
, found
);
1632 err_msg(char *fmt
, ...)
1637 (void) vfprintf(stderr
, fmt
, ap
);
1642 inquiry(int fd
, uchar_t
*inq
)
1644 struct uscsi_cmd
*scmd
;
1646 scmd
= get_uscsi_cmd();
1647 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
1648 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
1649 scmd
->uscsi_cdb
[0] = INQUIRY_CMD
;
1650 scmd
->uscsi_cdb
[4] = INQUIRY_DATA_LENGTH
;
1651 scmd
->uscsi_cdblen
= 6;
1652 scmd
->uscsi_bufaddr
= (char *)inq
;
1653 scmd
->uscsi_buflen
= INQUIRY_DATA_LENGTH
;
1654 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
1662 (void) memset(&uscmd
, 0, sizeof (uscmd
));
1663 (void) memset(ucdb
, 0, 16);
1664 uscmd
.uscsi_cdb
= ucdb
;
1669 uscsi(int fd
, struct uscsi_cmd
*scmd
)
1671 int ret
, global_rqsense
;
1672 int retries
, max_retries
= 5;
1675 /* set up for request sense extensions */
1676 if (!(scmd
->uscsi_flags
& USCSI_RQENABLE
)) {
1677 scmd
->uscsi_flags
|= USCSI_RQENABLE
;
1678 scmd
->uscsi_rqlen
= RQBUFLEN
;
1679 scmd
->uscsi_rqbuf
= rqbuf
;
1686 * The device may be busy or slow and fail with a not ready status.
1687 * we'll allow a limited number of retries to give the drive time
1690 for (retries
= 0; retries
< max_retries
; retries
++) {
1692 scmd
->uscsi_status
= 0;
1695 (void) memset(rqbuf
, 0, RQBUFLEN
);
1698 for (i
= 0; i
< scmd
->uscsi_cdblen
; i
++)
1700 (uchar_t
)scmd
->uscsi_cdb
[i
]);
1704 * We need to have root privledges in order to use
1705 * uscsi commands on the device.
1708 ret
= ioctl(fd
, USCSICMD
, scmd
);
1710 /* maintain consistency in case of sgen */
1711 if ((ret
== 0) && (scmd
->uscsi_status
== 2)) {
1716 /* if error and extended request sense, retrieve errors */
1717 if (global_rqsense
&& (ret
< 0) && (scmd
->uscsi_status
== 2)) {
1719 * The drive is not ready to recieve commands but
1720 * may be in the process of becoming ready.
1721 * sleep for a short time then retry command.
1722 * SENSE/ASC = 2/4 : not ready
1723 * ASCQ = 0 Not Reportable.
1724 * ASCQ = 1 Becoming ready.
1726 if ((SENSE_KEY(rqbuf
) == 2) && (ASC(rqbuf
) == 4) &&
1727 ((ASCQ(rqbuf
) == 0) || (ASCQ(rqbuf
) == 1))) {
1734 * Device is not ready to transmit or a device reset
1735 * has occurred. wait for a short period of time then
1736 * retry the command.
1738 if ((SENSE_KEY(rqbuf
) == 6) && ((ASC(rqbuf
) == 0x28) ||
1739 (ASC(rqbuf
) == 0x29))) {
1745 DPRINTF3("cmd: 0x%02x ret:%i status:%02x ",
1746 (uchar_t
)scmd
->uscsi_cdb
[0], ret
,
1747 scmd
->uscsi_status
);
1748 DPRINTF3(" sense: %02x ASC: %02x ASCQ:%02x\n",
1749 (uchar_t
)SENSE_KEY(rqbuf
),
1750 (uchar_t
)ASC(rqbuf
), (uchar_t
)ASCQ(rqbuf
));
1753 /* no errors we'll return */
1757 /* store the error status for later debug printing */
1758 if ((ret
< 0) && (global_rqsense
)) {
1759 uscsi_status
= scmd
->uscsi_status
;
1760 rqstatus
= scmd
->uscsi_rqstatus
;
1761 rqresid
= scmd
->uscsi_rqresid
;
1765 DPRINTF1("total retries: %d\n", total_retries
);
1771 * will get the mode page only i.e. will strip off the header.
1774 get_mode_page(int fd
, int page_no
, int pc
, int buf_len
, uchar_t
*buffer
)
1777 uchar_t byte2
, *buf
;
1778 uint_t header_len
, page_len
, copy_cnt
;
1780 byte2
= (uchar_t
)(((pc
<< 6) & 0xC0) | (page_no
& 0x3f));
1781 buf
= (uchar_t
*)my_zalloc(256);
1783 /* Ask 254 bytes only to make our IDE driver happy */
1784 ret
= mode_sense(fd
, byte2
, 1, 254, buf
);
1790 header_len
= 8 + read_scsi16(&buf
[6]);
1791 page_len
= buf
[header_len
+ 1] + 2;
1793 copy_cnt
= (page_len
> buf_len
) ? buf_len
: page_len
;
1794 (void) memcpy(buffer
, &buf
[header_len
], copy_cnt
);
1801 mode_sense(int fd
, uchar_t pc
, int dbd
, int page_len
, uchar_t
*buffer
)
1803 struct uscsi_cmd
*scmd
;
1805 scmd
= get_uscsi_cmd();
1806 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
1807 scmd
->uscsi_buflen
= page_len
;
1808 scmd
->uscsi_bufaddr
= (char *)buffer
;
1809 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
1810 scmd
->uscsi_cdblen
= 0xa;
1811 scmd
->uscsi_cdb
[0] = MODE_SENSE_10_CMD
;
1813 /* don't return any block descriptors */
1814 scmd
->uscsi_cdb
[1] = 0x8;
1816 /* the page code we want */
1817 scmd
->uscsi_cdb
[2] = pc
;
1818 /* allocation length */
1819 scmd
->uscsi_cdb
[7] = (page_len
>> 8) & 0xff;
1820 scmd
->uscsi_cdb
[8] = page_len
& 0xff;
1822 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
1828 read_scsi16(void *addr
)
1830 uchar_t
*ad
= (uchar_t
*)addr
;
1833 ret
= ((((uint16_t)ad
[0]) << 8) | ad
[1]);
1838 * Allocate space for and return a pointer to a string
1839 * on the stack. If the string is null, create
1841 * Use destroy_data() to free when no longer used.
1850 ns
= (char *)my_zalloc(1);
1852 ns
= (char *)my_zalloc(strlen(s
) + 1);
1853 (void) strcpy(ns
, s
);
1859 * Follow symbolic links from the logical device name to
1860 * the /devfs physical device name. To be complete, we
1861 * handle the case of multiple links. This function
1862 * either returns NULL (no links, or some other error),
1863 * or the physical device name, alloc'ed on the heap.
1865 * Note that the standard /devices prefix is stripped from
1866 * the final pathname, if present. The trailing options
1867 * are also removed (":c, raw").
1870 get_physical_name(char *path
)
1877 char buf
[MAXPATHLEN
];
1878 char dir
[MAXPATHLEN
];
1879 char savedir
[MAXPATHLEN
];
1880 char *result
= NULL
;
1882 if (getcwd(savedir
, sizeof (savedir
)) == NULL
) {
1883 DPRINTF1("getcwd() failed - %s\n", strerror(errno
));
1887 (void) strcpy(s
, path
);
1888 if ((p
= strrchr(s
, '/')) != NULL
) {
1892 (void) strcpy(s
, "/");
1894 if (chdir(s
) == -1) {
1895 DPRINTF2("cannot chdir() to %s - %s\n",
1896 s
, strerror(errno
));
1901 (void) strcpy(s
, path
);
1904 * See if there's a real file out there. If not,
1905 * we have a dangling link and we ignore it.
1907 if (stat(s
, &stbuf
) == -1) {
1910 if (lstat(s
, &stbuf
) == -1) {
1911 DPRINTF2("%s: lstat() failed - %s\n",
1912 s
, strerror(errno
));
1916 * If the file is not a link, we're done one
1917 * way or the other. If there were links,
1918 * return the full pathname of the resulting
1921 if (!S_ISLNK(stbuf
.st_mode
)) {
1924 * Strip trailing options from the
1925 * physical device name
1927 if ((p
= strrchr(s
, ':')) != NULL
) {
1931 * Get the current directory, and
1932 * glue the pieces together.
1934 if (getcwd(dir
, sizeof (dir
)) == NULL
) {
1935 DPRINTF1("getcwd() failed - %s\n",
1939 (void) strcat(dir
, "/");
1940 (void) strcat(dir
, s
);
1942 * If we have the standard fixed
1943 * /devices prefix, remove it.
1945 p
= (strstr(dir
, DEVFS_PREFIX
) == dir
) ?
1946 dir
+strlen(DEVFS_PREFIX
) : dir
;
1947 result
= alloc_string(p
);
1951 i
= readlink(s
, buf
, sizeof (buf
));
1953 DPRINTF2("%s: readlink() failed - %s\n",
1954 s
, strerror(errno
));
1961 * Break up the pathname into the directory
1962 * reference, if applicable and simple filename.
1963 * chdir()'ing to the directory allows us to
1964 * handle links with relative pathnames correctly.
1966 (void) strcpy(dir
, buf
);
1967 if ((p
= strrchr(dir
, '/')) != NULL
) {
1969 if (chdir(dir
) == -1) {
1970 DPRINTF2("cannot chdir() to %s - %s\n",
1971 dir
, strerror(errno
));
1974 (void) strcpy(s
, p
+1);
1976 (void) strcpy(s
, buf
);
1981 if (chdir(savedir
) == -1) {
1982 (void) printf("cannot chdir() to %s - %s\n",
1983 savedir
, strerror(errno
));
1990 get_media_info(device_t
*t_dev
, char *sdev
, char *pname
, char *sn
)
1992 struct dk_cinfo cinfo
;
1993 struct extvtoc vtocinfo
;
1996 smedia_handle_t handle
;
1997 struct dk_minfo mediainfo
;
2000 device_type
= ioctl(t_dev
->d_fd
, DKIOCGMEDIAINFO
, &mediainfo
);
2003 * Determine bus type.
2005 if (!ioctl(t_dev
->d_fd
, DKIOCINFO
, &cinfo
)) {
2006 if (strstr(cinfo
.dki_cname
, "usb") || strstr(pname
, "usb")) {
2007 (void) printf("\tBus: USB\n");
2008 } else if (strstr(cinfo
.dki_cname
, "firewire") ||
2009 strstr(pname
, "firewire")) {
2010 (void) printf("\tBus: Firewire\n");
2011 } else if (strstr(cinfo
.dki_cname
, "ide") ||
2012 strstr(pname
, "ide")) {
2013 (void) printf("\tBus: IDE\n");
2014 } else if (strstr(cinfo
.dki_cname
, "scsi") ||
2015 strstr(pname
, "scsi")) {
2016 (void) printf("\tBus: SCSI\n");
2018 (void) printf("\tBus: <Unknown>\n");
2021 (void) printf("\tBus: <Unknown>\n");
2025 * Calculate size of media.
2028 (!ioctl(t_dev
->d_fd
, DKIOCGMEDIAINFO
, &mediainfo
))) {
2029 size
= (mediainfo
.dki_lbsize
*
2030 mediainfo
.dki_capacity
)/(1024.0*1024.0);
2032 (void) printf("\tSize: %.1f MB\n", size
);
2035 (void) printf("\tSize: %.1f GB\n", size
);
2038 (void) printf("\tSize: <Unknown>\n");
2044 if (!device_type
&& (read_extvtoc(t_dev
->d_fd
, &vtocinfo
) >= 0)) {
2045 if (*vtocinfo
.v_volume
) {
2046 (void) printf("\tLabel: %s\n", vtocinfo
.v_volume
);
2048 (void) printf("\tLabel: <None>\n");
2051 (void) printf("\tLabel: <Unknown>\n");
2055 * Acess permissions.
2058 (void) printf("\tAccess permissions: <Unknown>\n");
2062 (void) fprintf(stdout
, gettext("\tAccess permissions: "));
2065 * Set dev_name for process_p_flag().
2068 fd
= my_open(sn
, O_RDONLY
|O_NDELAY
);
2071 fd
= my_open(sdev
, O_RDONLY
|O_NDELAY
);
2074 (void) printf("<Unknown>\n");
2075 DPRINTF("Could not open device.\n");
2078 /* register the fd with the libsmedia */
2079 handle
= smedia_get_handle(fd
);
2080 if (handle
== NULL
) {
2081 (void) printf("<Unknown>\n");
2082 DPRINTF("Failed to get libsmedia handle.\n");
2085 process_p_flag(handle
, fd
);
2088 /* Clear dev_name */