1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <fcntl.h>
27 #include <libdevinfo.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/sunddi.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <dirent.h>
35 #include <unistd.h>
36 #include <sys/dkio.h>
37
38 #if defined(i386) || defined(__amd64)
39 #include <sys/dktp/fdisk.h>
40 #include <libfdisk.h>
41 #endif
42
43 #include "libdiskmgt.h"
44 #include "disks_private.h"
45 #include "partition.h"
46
47 #ifdef sparc
48 #define les(val) ((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
49 #define lel(val) (((unsigned)(les((val)&0x0000FFFF))<<16) | \
50 (les((unsigned)((val)&0xffff0000)>>16)))
51 #else
52 #define les(val) (val)
53 #define lel(val) (val)
54 #endif
55
56 #define TOTAL_NUMPART (FD_NUMPART + MAX_EXT_PARTS)
57
58 #define ISIZE FD_NUMPART * sizeof (struct ipart)
59
60 static int desc_ok(descriptor_t *dp);
61 static int get_attrs(descriptor_t *dp, struct ipart *iparts,
62 nvlist_t *attrs);
63 static int get_parts(disk_t *disk, struct ipart *iparts, char *opath,
64 int opath_len);
65 static int open_disk(disk_t *diskp, char *opath, int len);
66 static int has_slices(descriptor_t *desc, int *errp);
67
68 descriptor_t **
partition_get_assoc_descriptors(descriptor_t * desc,dm_desc_type_t type,int * errp)69 partition_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
70 int *errp)
71 {
72 if (!desc_ok(desc)) {
73 *errp = ENODEV;
74 return (NULL);
75 }
76
77 switch (type) {
78 case DM_MEDIA:
79 return (media_get_assocs(desc, errp));
80 case DM_SLICE:
81 if (!has_slices(desc, errp)) {
82 if (*errp != 0) {
83 return (NULL);
84 }
85 return (libdiskmgt_empty_desc_array(errp));
86 }
87 return (slice_get_assocs(desc, errp));
88 }
89
90 *errp = EINVAL;
91 return (NULL);
92 }
93
94 /*
95 * This is called by media/slice to get the associated partitions.
96 * For a media desc. we just get all the partitions, but for a slice desc.
97 * we just get the active solaris partition.
98 */
99 descriptor_t **
partition_get_assocs(descriptor_t * desc,int * errp)100 partition_get_assocs(descriptor_t *desc, int *errp)
101 {
102 descriptor_t **partitions;
103 int pos;
104 int i;
105 struct ipart iparts[TOTAL_NUMPART];
106 char pname[MAXPATHLEN];
107 int conv_flag = 0;
108 #if defined(i386) || defined(__amd64)
109 int len;
110 #endif
111
112 if (get_parts(desc->p.disk, iparts, pname, sizeof (pname)) != 0) {
113 return (libdiskmgt_empty_desc_array(errp));
114 }
115
116 /* allocate the array for the descriptors */
117 partitions = (descriptor_t **)calloc(TOTAL_NUMPART + 1,
118 sizeof (descriptor_t *));
119 if (partitions == NULL) {
120 *errp = ENOMEM;
121 return (NULL);
122 }
123
124 #if defined(i386) || defined(__amd64)
125 /* convert part. name (e.g. c0d0p1) */
126 len = strlen(pname);
127 if (len > 1 && *(pname + (len - 2)) == 'p') {
128 conv_flag = 1;
129 *(pname + (len - 1)) = 0;
130 }
131 #endif
132
133 /*
134 * If this is a slice desc. we need the first active solaris partition
135 * and if there isn't one then we need the first solaris partition.
136 */
137 if (desc->type == DM_SLICE) {
138 for (i = 0; i < TOTAL_NUMPART; i++) {
139 if (iparts[i].bootid == ACTIVE &&
140 (iparts[i].systid == SUNIXOS ||
141 iparts[i].systid == SUNIXOS2)) {
142 break;
143 }
144 }
145
146 /*
147 * no active solaris part.,*try to get the first solaris part.
148 */
149 if (i >= TOTAL_NUMPART) {
150 for (i = 0; i < TOTAL_NUMPART; i++) {
151 if (iparts[i].systid == SUNIXOS ||
152 iparts[i].systid == SUNIXOS2) {
153 break;
154 }
155 }
156 }
157
158 if (i < TOTAL_NUMPART) {
159 /* we found a solaris partition to use */
160 char part_name[MAXPATHLEN];
161
162 if (conv_flag) {
163 /* convert part. name (e.g. c0d0p1) */
164 (void) snprintf(part_name, sizeof (part_name),
165 "%s%d", pname, i+1);
166 } else {
167 (void) snprintf(part_name, sizeof (part_name),
168 "%d", i+1);
169 }
170
171 /* the media name comes from the slice desc. */
172 partitions[0] = cache_get_desc(DM_PARTITION,
173 desc->p.disk, part_name, desc->secondary_name,
174 errp);
175 if (*errp != 0) {
176 cache_free_descriptors(partitions);
177 return (NULL);
178 }
179 partitions[1] = NULL;
180
181 return (partitions);
182 }
183
184 return (libdiskmgt_empty_desc_array(errp));
185 }
186
187 /* Must be for media, so get all the parts. */
188
189 pos = 0;
190 for (i = 0; i < TOTAL_NUMPART; i++) {
191 if (iparts[i].systid != UNUSED) {
192 char part_name[MAXPATHLEN];
193
194 /*
195 * Process the descriptors and modify the cxdxpx
196 * format so that it refers to the fdisk partition
197 * number and not to the physical disk. This is
198 * achieved by i+1, where i is the number of the
199 * physical disk partition.
200 */
201 if (conv_flag) {
202 /* convert part. name (e.g. c0d0p1) */
203 (void) snprintf(part_name, sizeof (part_name),
204 "%s%d", pname, i+1);
205 } else {
206 (void) snprintf(part_name, sizeof (part_name),
207 "%d", i+1);
208 }
209
210 /* the media name comes from the media desc. */
211 partitions[pos] = cache_get_desc(DM_PARTITION,
212 desc->p.disk, part_name, desc->name, errp);
213 if (*errp != 0) {
214 cache_free_descriptors(partitions);
215 return (NULL);
216 }
217
218 pos++;
219 }
220 }
221 partitions[pos] = NULL;
222
223 *errp = 0;
224 return (partitions);
225 }
226
227 nvlist_t *
partition_get_attributes(descriptor_t * dp,int * errp)228 partition_get_attributes(descriptor_t *dp, int *errp)
229 {
230 nvlist_t *attrs = NULL;
231 struct ipart iparts[TOTAL_NUMPART];
232
233 if (!desc_ok(dp)) {
234 *errp = ENODEV;
235 return (NULL);
236 }
237
238 if ((*errp = get_parts(dp->p.disk, iparts, NULL, 0)) != 0) {
239 return (NULL);
240 }
241
242 if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
243 *errp = ENOMEM;
244 return (NULL);
245 }
246
247 if ((*errp = get_attrs(dp, iparts, attrs)) != 0) {
248 nvlist_free(attrs);
249 attrs = NULL;
250 }
251
252 return (attrs);
253 }
254
255 /*
256 * Look for the partition by the partition number (which is not too useful).
257 */
258 descriptor_t *
partition_get_descriptor_by_name(char * name,int * errp)259 partition_get_descriptor_by_name(char *name, int *errp)
260 {
261 descriptor_t **partitions;
262 int i;
263 descriptor_t *partition = NULL;
264
265 partitions = cache_get_descriptors(DM_PARTITION, errp);
266 if (*errp != 0) {
267 return (NULL);
268 }
269
270 for (i = 0; partitions[i]; i++) {
271 if (libdiskmgt_str_eq(name, partitions[i]->name)) {
272 partition = partitions[i];
273 } else {
274 /* clean up the unused descriptors */
275 cache_free_descriptor(partitions[i]);
276 }
277 }
278 free(partitions);
279
280 if (partition == NULL) {
281 *errp = ENODEV;
282 }
283
284 return (partition);
285 }
286
287 /* ARGSUSED */
288 descriptor_t **
partition_get_descriptors(int filter[],int * errp)289 partition_get_descriptors(int filter[], int *errp)
290 {
291 return (cache_get_descriptors(DM_PARTITION, errp));
292 }
293
294 char *
partition_get_name(descriptor_t * desc)295 partition_get_name(descriptor_t *desc)
296 {
297 return (desc->name);
298 }
299
300 /* ARGSUSED */
301 nvlist_t *
partition_get_stats(descriptor_t * dp,int stat_type,int * errp)302 partition_get_stats(descriptor_t *dp, int stat_type, int *errp)
303 {
304 /* There are no stat types defined for partitions */
305 *errp = EINVAL;
306 return (NULL);
307 }
308
309 /* ARGSUSED */
310 int
partition_has_fdisk(disk_t * dp,int fd)311 partition_has_fdisk(disk_t *dp, int fd)
312 {
313 char bootsect[512 * 3]; /* 3 sectors to be safe */
314
315 #ifdef sparc
316 if (dp->drv_type == DM_DT_FIXED) {
317 /* on sparc, only removable media can have fdisk parts. */
318 return (0);
319 }
320 #endif
321
322 /*
323 * We assume the caller already made sure media was inserted and
324 * spun up.
325 */
326
327 if ((ioctl(fd, DKIOCGMBOOT, bootsect) < 0) && (errno != ENOTTY)) {
328 return (0);
329 }
330
331 return (1);
332 }
333
334 /*
335 * partition_make_descriptors
336 *
337 * A partition descriptor points to a disk, the name is the partition number
338 * and the secondary name is the media name. The iparts parameter returned
339 * by the get_parts function contains the structures of all of the identified
340 * partitions found on each disk on a system. These are processed into an array
341 * of descriptors. A descriptor contains all of the information about a
342 * specific partition.
343 *
344 * Parameters: none
345 *
346 * Returns: 0 on success
347 * Error value on failure
348 *
349 */
350
351 int
partition_make_descriptors()352 partition_make_descriptors()
353 {
354 int error;
355 disk_t *dp;
356
357 dp = cache_get_disklist();
358 while (dp != NULL) {
359 struct ipart iparts[TOTAL_NUMPART];
360 char pname[MAXPATHLEN];
361
362 if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) {
363 int i;
364 char mname[MAXPATHLEN];
365 int conv_flag = 0;
366 #if defined(i386) || defined(__amd64)
367 /* convert part. name (e.g. c0d0p1) */
368 int len;
369
370 len = strlen(pname);
371 if (len > 1 && *(pname + (len - 2)) == 'p') {
372 conv_flag = 1;
373 *(pname + (len - 1)) = 0;
374 }
375 #endif
376
377 mname[0] = 0;
378 (void) media_read_name(dp, mname, sizeof (mname));
379
380 /*
381 * Process the descriptors and modify the cxdxpx
382 * format so that it refers to the fdisk partition
383 * number and not to the physical disk. This is
384 * achieved by i+1, where i is the number of the
385 * physical disk partition.
386 */
387 for (i = 0; i < TOTAL_NUMPART; i++) {
388 if (iparts[i].systid != UNUSED) {
389 char part_name[MAXPATHLEN];
390
391 if (conv_flag) {
392 /*
393 * convert partition name
394 * (e.g. c0d0p1)
395 */
396 (void) snprintf(part_name,
397 sizeof (part_name),
398 "%s%d", pname, i+1);
399 } else {
400 (void) snprintf(part_name,
401 sizeof (part_name),
402 "%d", i+1);
403 }
404
405 cache_load_desc(DM_PARTITION, dp,
406 part_name, mname, &error);
407 if (error != 0) {
408 return (error);
409 }
410 }
411 }
412 }
413 dp = dp->next;
414 }
415
416 return (0);
417 }
418
419 static int
get_attrs(descriptor_t * dp,struct ipart * iparts,nvlist_t * attrs)420 get_attrs(descriptor_t *dp, struct ipart *iparts, nvlist_t *attrs)
421 {
422 char *p;
423 int part_num;
424
425 /*
426 * We already made sure the media was loaded and ready in the
427 * get_parts call within partition_get_attributes.
428 */
429
430 p = strrchr(dp->name, 'p');
431 if (p == NULL) {
432 p = dp->name;
433 } else {
434 p++;
435 }
436 part_num = atoi(p);
437 if (part_num > TOTAL_NUMPART ||
438 iparts[part_num - 1].systid == UNUSED) {
439 return (ENODEV);
440 }
441
442 /*
443 * A partition has been found. Determine what type of
444 * partition it is: logical, extended, or primary.
445 * Collect the information for the partition.
446 */
447 #if defined(i386) || defined(__amd64)
448 if (part_num > FD_NUMPART) {
449 if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
450 DM_LOGICAL) != 0) {
451 return (ENOMEM);
452 }
453 } else if (fdisk_is_dos_extended(iparts[part_num - 1].systid)) {
454 if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
455 DM_EXTENDED) != 0) {
456 return (ENOMEM);
457 }
458
459 } else {
460 if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
461 DM_PRIMARY) != 0) {
462 return (ENOMEM);
463 }
464 }
465 #endif
466
467 #ifdef sparc
468 if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
469 DM_PRIMARY) != 0) {
470 return (ENOMEM);
471 }
472 #endif
473
474
475 if (nvlist_add_uint32(attrs, DM_BOOTID,
476 (unsigned int)iparts[part_num - 1].bootid) != 0) {
477 return (ENOMEM);
478 }
479
480 if (nvlist_add_uint32(attrs, DM_PTYPE,
481 (unsigned int)iparts[part_num - 1].systid) != 0) {
482 return (ENOMEM);
483 }
484
485 if (nvlist_add_uint32(attrs, DM_BHEAD,
486 (unsigned int)iparts[part_num - 1].beghead) != 0) {
487 return (ENOMEM);
488 }
489
490 if (nvlist_add_uint32(attrs, DM_BSECT,
491 (unsigned int)((iparts[part_num - 1].begsect) & 0x3f)) != 0) {
492 return (ENOMEM);
493 }
494
495 if (nvlist_add_uint32(attrs, DM_BCYL, (unsigned int)
496 ((iparts[part_num - 1].begcyl & 0xff) |
497 ((iparts[part_num - 1].begsect & 0xc0) << 2))) != 0) {
498 return (ENOMEM);
499 }
500
501 if (nvlist_add_uint32(attrs, DM_EHEAD,
502 (unsigned int)iparts[part_num - 1].endhead) != 0) {
503 return (ENOMEM);
504 }
505
506 if (nvlist_add_uint32(attrs, DM_ESECT,
507 (unsigned int)((iparts[part_num - 1].endsect) & 0x3f)) != 0) {
508 return (ENOMEM);
509 }
510
511 if (nvlist_add_uint32(attrs, DM_ECYL, (unsigned int)
512 ((iparts[part_num - 1].endcyl & 0xff) |
513 ((iparts[part_num - 1].endsect & 0xc0) << 2))) != 0) {
514 return (ENOMEM);
515 }
516
517 if (nvlist_add_uint32(attrs, DM_RELSECT,
518 (unsigned int)iparts[part_num - 1].relsect) != 0) {
519 return (ENOMEM);
520 }
521
522 if (nvlist_add_uint32(attrs, DM_NSECTORS,
523 (unsigned int)iparts[part_num - 1].numsect) != 0) {
524 return (ENOMEM);
525 }
526
527 return (0);
528 }
529
530 /*
531 * get_parts
532 * Discovers the primary, extended, and logical partitions that have
533 * been created on a disk. get_parts loops through the partitions,
534 * collects the information on each partition and stores it in a
535 * partition table.
536 *
537 * Parameters;
538 * disk -The disk device to be evaluated for partitions
539 * iparts -The structure that holds information about
540 * the partitions
541 * opath -The device path
542 * opath_len -Buffer size used with opath
543 * Returns:
544 * 0 on Successful completion
545 * Error Value on failure
546 *
547 */
548 static int
get_parts(disk_t * disk,struct ipart * iparts,char * opath,int opath_len)549 get_parts(disk_t *disk, struct ipart *iparts, char *opath, int opath_len)
550 {
551 int fd;
552 struct dk_minfo minfo;
553 struct mboot bootblk;
554 char bootsect[512];
555 int i;
556
557 #if defined(i386) || defined(__amd64)
558 int j, ret;
559 ext_part_t *epp; /* extended partition structure */
560 char *device; /* name of fixed disk drive */
561 size_t len;
562 logical_drive_t *log_drv; /* logical drive structure */
563 uint64_t tmpsect;
564 #endif
565
566 /* Can't use drive_open_disk since we need the partition dev name. */
567 if ((fd = open_disk(disk, opath, opath_len)) < 0) {
568 return (ENODEV);
569 }
570
571 /* First make sure media is inserted and spun up. */
572 if (!media_read_info(fd, &minfo)) {
573 (void) close(fd);
574 return (ENODEV);
575 }
576
577 if (!partition_has_fdisk(disk, fd)) {
578 (void) close(fd);
579 return (ENOTTY);
580 }
581
582 if (lseek(fd, 0, 0) == -1) {
583 (void) close(fd);
584 return (ENODEV);
585 }
586
587 if (read(fd, bootsect, 512) != 512) {
588 (void) close(fd);
589 return (ENODEV);
590 }
591 (void) close(fd);
592
593 (void) memcpy(&bootblk, bootsect, sizeof (bootblk));
594
595 if (les(bootblk.signature) != MBB_MAGIC) {
596 return (ENOTTY);
597 }
598
599 /*
600 * Initialize the memory space to clear unknown garbage
601 * that might create confusing results.
602 */
603 for (i = 0; i < TOTAL_NUMPART; i++) {
604 (void) memset(&iparts[i], 0, sizeof (struct ipart));
605 iparts[i].systid = UNUSED;
606 }
607
608 (void) memcpy(iparts, bootblk.parts, ISIZE);
609
610 /*
611 * Check to see if a valid partition exists. If a valid partition
612 * exists, check to see if it is an extended partition.
613 * If an extended partition exists, collect the logical partition
614 * data.
615 */
616 for (i = 0; i < FD_NUMPART; i++) {
617 if (iparts[i].systid == UNUSED)
618 continue;
619
620 iparts[i].relsect = lel(iparts[i].relsect);
621 iparts[i].numsect = lel(iparts[i].numsect);
622
623 #if defined(i386) || defined(__amd64)
624 if (!fdisk_is_dos_extended(iparts[i].systid))
625 continue;
626
627 len = strlen(disk->aliases->alias) + 1;
628 if ((device = malloc(len)) == NULL) {
629 if (device)
630 free(device);
631 continue;
632 }
633
634 (void) snprintf(device, len, "%s", disk->aliases->alias);
635
636 if ((ret = libfdisk_init(&epp, device, &iparts[i],
637 FDISK_READ_DISK)) != FDISK_SUCCESS) {
638
639 switch (ret) {
640 /*
641 * The first 2 error cases indicate that
642 * there is no Solaris logical partition,
643 * which is a valid condition,
644 * so iterating through the disk continues.
645 * Any other error cases indicate there is
646 * a potential problem with the disk, so
647 * don't continue iterating through the disk
648 * and return an error.
649 */
650 case FDISK_EBADLOGDRIVE:
651 case FDISK_ENOLOGDRIVE:
652 free(device);
653 libfdisk_fini(&epp);
654 continue;
655 case FDISK_EBADMAGIC:
656 free(device);
657 libfdisk_fini(&epp);
658 return (ENOTTY);
659 default:
660 free(device);
661 libfdisk_fini(&epp);
662 return (ENODEV);
663 }
664 }
665
666 /*
667 * Collect logical drive information
668 */
669 for (log_drv = fdisk_get_ld_head(epp), j = FD_NUMPART,
670 tmpsect = 0; (j < TOTAL_NUMPART) && (log_drv != NULL);
671 log_drv = log_drv->next, j++) {
672 iparts[j].bootid = log_drv->parts[0].bootid;
673 iparts[j].beghead = log_drv->parts[0].beghead;
674 iparts[j].begsect = log_drv->parts[0].begsect;
675 iparts[j].begcyl = log_drv->parts[0].begcyl;
676 iparts[j].systid = log_drv->parts[0].systid;
677 iparts[j].endhead = log_drv->parts[0].endhead;
678 iparts[j].endsect = log_drv->parts[0].endsect;
679 iparts[j].endcyl = log_drv->parts[0].endcyl;
680 iparts[j].relsect = (tmpsect +
681 lel(log_drv->parts[0].relsect) + epp->ext_beg_sec);
682 iparts[j].numsect = lel(log_drv->parts[0].numsect);
683 tmpsect = lel(log_drv->parts[1].relsect);
684 }
685
686 /* free the device and the epp memory. */
687 free(device);
688 libfdisk_fini(&epp);
689 #endif
690 }
691
692 return (0);
693 }
694
695 /* return 1 if the partition descriptor is still valid, 0 if not. */
696 static int
desc_ok(descriptor_t * dp)697 desc_ok(descriptor_t *dp)
698 {
699 /* First verify the media name for removable media */
700 if (dp->p.disk->removable) {
701 char mname[MAXPATHLEN];
702
703 if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
704 return (0);
705 }
706
707 if (mname[0] == 0) {
708 return (libdiskmgt_str_eq(dp->secondary_name, NULL));
709 } else {
710 return (libdiskmgt_str_eq(dp->secondary_name, mname));
711 }
712 }
713
714 /*
715 * We could verify the partition is still there but this is kind of
716 * expensive and other code down the line will do that (e.g. see
717 * get_attrs).
718 */
719
720 return (1);
721 }
722
723 /*
724 * Return 1 if partition has slices, 0 if not.
725 */
726 static int
has_slices(descriptor_t * desc,int * errp)727 has_slices(descriptor_t *desc, int *errp)
728 {
729 int pnum;
730 int i;
731 char *p;
732 struct ipart iparts[TOTAL_NUMPART];
733
734 if (get_parts(desc->p.disk, iparts, NULL, 0) != 0) {
735 *errp = ENODEV;
736 return (0);
737 }
738
739 p = strrchr(desc->name, 'p');
740 if (p == NULL) {
741 p = desc->name;
742 } else {
743 p++;
744 }
745 pnum = atoi(p);
746
747 /*
748 * Slices are associated with the active solaris partition or if there
749 * is no active solaris partition, then the first solaris partition.
750 */
751
752 *errp = 0;
753 if (iparts[pnum].bootid == ACTIVE &&
754 (iparts[pnum].systid == SUNIXOS ||
755 iparts[pnum].systid == SUNIXOS2)) {
756 return (1);
757 } else {
758 int active = 0;
759
760 /* Check if there are no active solaris partitions. */
761 for (i = 0; i < TOTAL_NUMPART; i++) {
762 if (iparts[i].bootid == ACTIVE &&
763 (iparts[i].systid == SUNIXOS ||
764 iparts[i].systid == SUNIXOS2)) {
765 active = 1;
766 break;
767 }
768 }
769
770 if (!active) {
771 /* Check if this is the first solaris partition. */
772 for (i = 0; i < TOTAL_NUMPART; i++) {
773 if (iparts[i].systid == SUNIXOS ||
774 iparts[i].systid == SUNIXOS2) {
775 break;
776 }
777 }
778
779 if (i < TOTAL_NUMPART && i == pnum) {
780 return (1);
781 }
782 }
783 }
784
785 return (0);
786 }
787
788 static int
open_disk(disk_t * diskp,char * opath,int len)789 open_disk(disk_t *diskp, char *opath, int len)
790 {
791 /*
792 * Just open the first devpath.
793 */
794 if (diskp->aliases != NULL && diskp->aliases->devpaths != NULL) {
795 #ifdef sparc
796 if (opath != NULL) {
797 (void) strlcpy(opath, diskp->aliases->devpaths->devpath, len);
798 }
799 return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY));
800 #else
801 /* On intel we need to open partition device (e.g. c0d0p1). */
802 char part_dev[MAXPATHLEN];
803 char *p;
804
805 (void) strlcpy(part_dev, diskp->aliases->devpaths->devpath,
806 sizeof (part_dev));
807 p = strrchr(part_dev, '/');
808 if (p == NULL) {
809 p = strrchr(part_dev, 's');
810 if (p != NULL) {
811 *p = 'p';
812 }
813 } else {
814 char *ps;
815
816 *p = 0;
817 ps = strrchr((p + 1), 's');
818 if (ps != NULL) {
819 *ps = 'p';
820 }
821 *p = '/';
822 }
823
824 if (opath != NULL) {
825 (void) strlcpy(opath, part_dev, len);
826 }
827 return (open(part_dev, O_RDONLY|O_NDELAY));
828 #endif
829 }
830
831 return (-1);
832 }
833