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