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 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <fcntl.h>
28 #include <libdevinfo.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <dirent.h>
33 #include <sys/dkio.h>
34 #include <sys/stat.h>
35 #include <sys/sunddi.h>
36 #include <sys/types.h>
37 #include <sys/vtoc.h>
38 #include <unistd.h>
39 #include <devid.h>
40 #include <dirent.h>
41 #include <sys/dktp/fdisk.h>
42 #include <sys/efi_partition.h>
43
44 #include "libdiskmgt.h"
45 #include "disks_private.h"
46 #include "partition.h"
47 #ifndef VT_ENOTSUP
48 #define VT_ENOTSUP (-5)
49 #endif
50
51 #define FMT_UNKNOWN 0
52 #define FMT_VTOC 1
53 #define FMT_EFI 2
54
55 typedef int (*detectorp)(char *, nvlist_t *, int *);
56
57 static detectorp detectors[] = {
58 inuse_mnt,
59 inuse_active_zpool,
60 inuse_lu,
61 inuse_dump,
62 inuse_vxvm,
63 inuse_exported_zpool,
64 inuse_fs, /* fs should always be last */
65 NULL
66 };
67
68 static int add_inuse(char *name, nvlist_t *attrs);
69 static int desc_ok(descriptor_t *dp);
70 static void dsk2rdsk(char *dsk, char *rdsk, int size);
71 static int get_attrs(descriptor_t *dp, int fd, nvlist_t *attrs);
72 static descriptor_t **get_fixed_assocs(descriptor_t *desc, int *errp);
73 static int get_slice_num(slice_t *devp);
74 static int match_fixed_name(disk_t *dp, char *name, int *errp);
75 static int make_fixed_descriptors(disk_t *dp);
76
77 descriptor_t **
slice_get_assoc_descriptors(descriptor_t * desc,dm_desc_type_t type,int * errp)78 slice_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
79 int *errp)
80 {
81 if (!desc_ok(desc)) {
82 *errp = ENODEV;
83 return (NULL);
84 }
85
86 switch (type) {
87 case DM_MEDIA:
88 return (media_get_assocs(desc, errp));
89 case DM_PARTITION:
90 return (partition_get_assocs(desc, errp));
91 }
92
93 *errp = EINVAL;
94 return (NULL);
95 }
96
97 /*
98 * This is called by media/partition to get the slice descriptors for the given
99 * media/partition descriptor.
100 * For media, just get the slices, but for a partition, it must be a solaris
101 * partition and if there are active partitions, it must be the active one.
102 */
103 descriptor_t **
slice_get_assocs(descriptor_t * desc,int * errp)104 slice_get_assocs(descriptor_t *desc, int *errp)
105 {
106 /* Just check the first drive name. */
107 if (desc->p.disk->aliases == NULL) {
108 *errp = 0;
109 return (libdiskmgt_empty_desc_array(errp));
110 }
111
112 return (get_fixed_assocs(desc, errp));
113 }
114
115 nvlist_t *
slice_get_attributes(descriptor_t * dp,int * errp)116 slice_get_attributes(descriptor_t *dp, int *errp)
117 {
118 nvlist_t *attrs = NULL;
119 int fd;
120 char devpath[MAXPATHLEN];
121
122 if (!desc_ok(dp)) {
123 *errp = ENODEV;
124 return (NULL);
125 }
126
127 if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
128 *errp = ENOMEM;
129 return (NULL);
130 }
131
132 /* dp->name is /dev/dsk, need to convert back to /dev/rdsk */
133 dsk2rdsk(dp->name, devpath, sizeof (devpath));
134 fd = open(devpath, O_RDONLY|O_NDELAY);
135
136 if ((*errp = get_attrs(dp, fd, attrs)) != 0) {
137 nvlist_free(attrs);
138 attrs = NULL;
139 }
140
141 if (fd >= 0) {
142 (void) close(fd);
143 }
144
145 return (attrs);
146 }
147
148 /*
149 * Look for the slice by the slice devpath.
150 */
151 descriptor_t *
slice_get_descriptor_by_name(char * name,int * errp)152 slice_get_descriptor_by_name(char *name, int *errp)
153 {
154 int found = 0;
155 disk_t *dp;
156
157 for (dp = cache_get_disklist(); dp != NULL; dp = dp->next) {
158 found = match_fixed_name(dp, name, errp);
159
160 if (found) {
161 char mname[MAXPATHLEN];
162
163 if (*errp != 0) {
164 return (NULL);
165 }
166
167 mname[0] = 0;
168 (void) media_read_name(dp, mname, sizeof (mname));
169
170 return (cache_get_desc(DM_SLICE, dp, name, mname,
171 errp));
172 }
173 }
174
175 *errp = ENODEV;
176 return (NULL);
177 }
178
179 /* ARGSUSED */
180 descriptor_t **
slice_get_descriptors(int filter[],int * errp)181 slice_get_descriptors(int filter[], int *errp)
182 {
183 return (cache_get_descriptors(DM_SLICE, errp));
184 }
185
186 char *
slice_get_name(descriptor_t * desc)187 slice_get_name(descriptor_t *desc)
188 {
189 return (desc->name);
190 }
191
192 nvlist_t *
slice_get_stats(descriptor_t * dp,int stat_type,int * errp)193 slice_get_stats(descriptor_t *dp, int stat_type, int *errp)
194 {
195 nvlist_t *stats;
196 char *str;
197
198 if (stat_type != DM_SLICE_STAT_USE) {
199 *errp = EINVAL;
200 return (NULL);
201 }
202
203 *errp = 0;
204
205 if (nvlist_alloc(&stats, NVATTRS_STAT, 0) != 0) {
206 *errp = ENOMEM;
207 return (NULL);
208 }
209
210 if ((*errp = add_inuse(dp->name, stats)) != 0) {
211 return (NULL);
212 }
213
214 /* if no cluster use, check for a use of the local name */
215 if (nvlist_lookup_string(stats, DM_USED_BY, &str) != 0) {
216 disk_t *diskp;
217
218 diskp = dp->p.disk;
219 if (diskp->aliases != NULL && diskp->aliases->cluster) {
220 slice_t *sp;
221 int snum = -1;
222 struct dk_minfo minfo;
223 struct dk_cinfo dkinfo;
224 char devpath[MAXPATHLEN];
225 int fd;
226
227 /* dp->name is /dev/dsk, need to convert back to /dev/rdsk */
228 dsk2rdsk(dp->name, devpath, sizeof (devpath));
229 fd = open(devpath, O_RDONLY|O_NDELAY);
230
231 if (fd >= 0 && media_read_info(fd, &minfo) &&
232 ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
233 snum = dkinfo.dki_partition;
234 }
235
236 if (fd >= 0) {
237 (void) close(fd);
238 }
239
240 if (snum >= 0) {
241 for (sp = diskp->aliases->orig_paths; sp != NULL;
242 sp = sp->next) {
243
244 if (sp->slice_num == snum) {
245 char localpath[MAXPATHLEN];
246
247 slice_rdsk2dsk(sp->devpath, localpath,
248 sizeof (localpath));
249
250 if ((*errp = add_inuse(localpath, stats)) != 0) {
251 return (NULL);
252 }
253
254 break;
255 }
256 }
257 }
258 }
259 }
260
261 return (stats);
262 }
263
264 /*
265 * A slice descriptor points to a disk, the name is the devpath and the
266 * secondary name is the media name.
267 */
268 int
slice_make_descriptors()269 slice_make_descriptors()
270 {
271 disk_t *dp;
272
273 dp = cache_get_disklist();
274 while (dp != NULL) {
275 int error;
276
277 error = make_fixed_descriptors(dp);
278 if (error != 0) {
279 return (error);
280 }
281
282 dp = dp->next;
283 }
284
285 return (0);
286 }
287
288 /* convert rdsk paths to dsk paths */
289 void
slice_rdsk2dsk(char * rdsk,char * dsk,int size)290 slice_rdsk2dsk(char *rdsk, char *dsk, int size)
291 {
292 char *strp;
293
294 (void) strlcpy(dsk, rdsk, size);
295
296 if ((strp = strstr(dsk, "/rdsk/")) == NULL) {
297 /* not rdsk, check for floppy */
298 strp = strstr(dsk, "/rdiskette");
299 }
300
301 if (strp != NULL) {
302 strp++; /* move ptr to the r in rdsk or rdiskette */
303
304 /* move the succeeding chars over by one */
305 do {
306 *strp = *(strp + 1);
307 strp++;
308 } while (*strp);
309 }
310 }
311
312 /*
313 * Check if/how the slice is used.
314 */
315 static int
add_inuse(char * name,nvlist_t * attrs)316 add_inuse(char *name, nvlist_t *attrs)
317 {
318 int i;
319 int error;
320
321 for (i = 0; detectors[i] != NULL; i ++) {
322 if (detectors[i](name, attrs, &error) || error != 0) {
323 if (error != 0) {
324 return (error);
325 }
326 break;
327 }
328 }
329
330 return (0);
331 }
332
333 /* return 1 if the slice descriptor is still valid, 0 if not. */
334 static int
desc_ok(descriptor_t * dp)335 desc_ok(descriptor_t *dp)
336 {
337 /* First verify the media name for removable media */
338 if (dp->p.disk->removable) {
339 char mname[MAXPATHLEN];
340
341 if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
342 return (0);
343 }
344
345 if (mname[0] == 0) {
346 return (libdiskmgt_str_eq(dp->secondary_name, NULL));
347 } else {
348 return (libdiskmgt_str_eq(dp->secondary_name, mname));
349 }
350 }
351
352 /*
353 * We could verify the slice is still there, but other code down the
354 * line already does these checks (e.g. see get_attrs).
355 */
356
357 return (1);
358 }
359
360 /* convert dsk paths to rdsk paths */
361 static void
dsk2rdsk(char * dsk,char * rdsk,int size)362 dsk2rdsk(char *dsk, char *rdsk, int size)
363 {
364 char *slashp;
365 size_t len;
366
367 (void) strlcpy(rdsk, dsk, size);
368
369 /* make sure there is enough room to add the r to dsk */
370 len = strlen(dsk);
371 if (len + 2 > size) {
372 return;
373 }
374
375 if ((slashp = strstr(rdsk, "/dsk/")) == NULL) {
376 /* not dsk, check for floppy */
377 slashp = strstr(rdsk, "/diskette");
378 }
379
380 if (slashp != NULL) {
381 char *endp;
382
383 endp = rdsk + len; /* point to terminating 0 */
384 /* move the succeeding chars over by one */
385 do {
386 *(endp + 1) = *endp;
387 endp--;
388 } while (endp != slashp);
389
390 *(endp + 1) = 'r';
391 }
392 }
393
394 static int
get_attrs(descriptor_t * dp,int fd,nvlist_t * attrs)395 get_attrs(descriptor_t *dp, int fd, nvlist_t *attrs)
396 {
397 struct dk_minfo minfo;
398 int status;
399 int data_format = FMT_UNKNOWN;
400 int snum = -1;
401 int error;
402 struct extvtoc vtoc;
403 struct dk_gpt *efip;
404 struct dk_cinfo dkinfo;
405 disk_t *diskp;
406 char localpath[MAXPATHLEN];
407 int cooked_fd;
408 struct stat buf;
409 int mntpnt = 0;
410
411 if (fd < 0) {
412 return (ENODEV);
413 }
414
415 /* First make sure media is inserted and spun up. */
416 if (!media_read_info(fd, &minfo)) {
417 return (ENODEV);
418 }
419
420 if ((status = read_extvtoc(fd, &vtoc)) >= 0) {
421 data_format = FMT_VTOC;
422 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) {
423 data_format = FMT_EFI;
424 if (nvlist_add_boolean(attrs, DM_EFI) != 0) {
425 efi_free(efip);
426 return (ENOMEM);
427 }
428 }
429
430 if (data_format == FMT_UNKNOWN) {
431 return (ENODEV);
432 }
433
434 if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
435 snum = dkinfo.dki_partition;
436 }
437
438 /* check the slice */
439 if (data_format == FMT_VTOC) {
440 if (snum < 0 || snum >= vtoc.v_nparts ||
441 vtoc.v_part[snum].p_size == 0) {
442 return (ENODEV);
443 }
444 } else { /* data_format == FMT_EFI */
445 if (snum < 0 || snum >= efip->efi_nparts ||
446 efip->efi_parts[snum].p_size == 0) {
447 efi_free(efip);
448 return (ENODEV);
449 }
450 }
451
452 /* the slice exists */
453
454 if (nvlist_add_uint32(attrs, DM_INDEX, snum) != 0) {
455 if (data_format == FMT_EFI) {
456 efi_free(efip);
457 }
458 return (ENOMEM);
459 }
460
461 if (data_format == FMT_VTOC) {
462 if (nvlist_add_uint64(attrs, DM_START, vtoc.v_part[snum].p_start)
463 != 0) {
464 return (ENOMEM);
465 }
466
467 if (nvlist_add_uint64(attrs, DM_SIZE, vtoc.v_part[snum].p_size)
468 != 0) {
469 return (ENOMEM);
470 }
471
472 if (nvlist_add_uint32(attrs, DM_TAG, vtoc.v_part[snum].p_tag)
473 != 0) {
474 return (ENOMEM);
475 }
476
477 if (nvlist_add_uint32(attrs, DM_FLAG, vtoc.v_part[snum].p_flag)
478 != 0) {
479 return (ENOMEM);
480 }
481
482 } else { /* data_format == FMT_EFI */
483 if (nvlist_add_uint64(attrs, DM_START,
484 efip->efi_parts[snum].p_start) != 0) {
485 efi_free(efip);
486 return (ENOMEM);
487 }
488
489 if (nvlist_add_uint64(attrs, DM_SIZE, efip->efi_parts[snum].p_size)
490 != 0) {
491 efi_free(efip);
492 return (ENOMEM);
493 }
494
495 if (efip->efi_parts[snum].p_name[0] != 0) {
496 char label[EFI_PART_NAME_LEN + 1];
497
498 (void) snprintf(label, sizeof (label), "%.*s",
499 EFI_PART_NAME_LEN, efip->efi_parts[snum].p_name);
500 if (nvlist_add_string(attrs, DM_EFI_NAME, label) != 0) {
501 efi_free(efip);
502 return (ENOMEM);
503 }
504 }
505 }
506
507 if (data_format == FMT_EFI) {
508 efi_free(efip);
509 }
510
511 if (inuse_mnt(dp->name, attrs, &error)) {
512 if (error != 0) {
513 return (error);
514 }
515 mntpnt = 1;
516 }
517
518 /*
519 * Some extra attrs for cluster slices.
520 *
521 * get localname and possible mnt point for localpath
522 */
523 localpath[0] = 0;
524 diskp = dp->p.disk;
525 if (diskp->aliases != NULL && diskp->aliases->cluster) {
526 slice_t *sp;
527
528 for (sp = diskp->aliases->orig_paths; sp != NULL; sp = sp->next) {
529 if (sp->slice_num == -1) {
530 /* determine the slice number for this path */
531 int sfd;
532 struct dk_cinfo dkinfo;
533
534 if ((sfd = open(sp->devpath, O_RDONLY|O_NDELAY)) >= 0) {
535 if (ioctl(sfd, DKIOCINFO, &dkinfo) >= 0) {
536 sp->slice_num = dkinfo.dki_partition;
537 }
538 (void) close(sfd);
539 }
540 }
541
542 if (sp->slice_num == snum) {
543 slice_rdsk2dsk(sp->devpath, localpath, sizeof (localpath));
544
545 if (nvlist_add_string(attrs, DM_LOCALNAME, localpath)
546 != 0) {
547 return (ENOMEM);
548 }
549
550 if (mntpnt == 0) {
551 if (inuse_mnt(localpath, attrs, &error)) {
552 if (error != 0) {
553 return (error);
554 }
555 }
556 }
557
558 break;
559 }
560 }
561 }
562
563 if (fstat(fd, &buf) != -1) {
564 if (nvlist_add_uint64(attrs, DM_DEVT, buf.st_rdev) != 0) {
565 return (ENOMEM);
566 }
567 }
568
569 /*
570 * We need to open the cooked slice (not the raw one) to get the
571 * correct devid. Also see if we need to read the localpath for the
572 * cluster disk, since the minor name is unavailable for the did pseudo
573 * device.
574 */
575 if (localpath[0] != 0) {
576 cooked_fd = open(localpath, O_RDONLY|O_NDELAY);
577 } else {
578 cooked_fd = open(dp->name, O_RDONLY|O_NDELAY);
579 }
580
581 if (cooked_fd >= 0) {
582 int no_mem = 0;
583 ddi_devid_t devid;
584
585 if (devid_get(cooked_fd, &devid) == 0) {
586 char *minor;
587
588 if (devid_get_minor_name(cooked_fd, &minor) == 0) {
589 char *devidstr;
590
591 if ((devidstr = devid_str_encode(devid, minor)) != 0) {
592
593 if (nvlist_add_string(attrs, DM_DEVICEID, devidstr)
594 != 0) {
595 no_mem = 1;
596 }
597
598 devid_str_free(devidstr);
599 }
600 devid_str_free(minor);
601 }
602 devid_free(devid);
603 }
604 (void) close(cooked_fd);
605
606 if (no_mem) {
607 return (ENOMEM);
608 }
609 }
610
611 return (0);
612 }
613
614 static descriptor_t **
get_fixed_assocs(descriptor_t * desc,int * errp)615 get_fixed_assocs(descriptor_t *desc, int *errp)
616 {
617 int fd;
618 int status;
619 int data_format = FMT_UNKNOWN;
620 int cnt;
621 struct extvtoc vtoc;
622 struct dk_gpt *efip;
623 int pos;
624 char *media_name = NULL;
625 slice_t *devp;
626 descriptor_t **slices;
627
628 if ((fd = drive_open_disk(desc->p.disk, NULL, 0)) < 0) {
629 *errp = ENODEV;
630 return (NULL);
631 }
632
633 if ((status = read_extvtoc(fd, &vtoc)) >= 0) {
634 data_format = FMT_VTOC;
635 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) {
636 data_format = FMT_EFI;
637 } else {
638 (void) close(fd);
639 *errp = 0;
640 return (libdiskmgt_empty_desc_array(errp));
641 }
642 (void) close(fd);
643
644 /* count the number of slices */
645 for (cnt = 0, devp = desc->p.disk->aliases->devpaths; devp != NULL;
646 devp = devp->next, cnt++);
647
648 /* allocate the array for the descriptors */
649 slices = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
650 if (slices == NULL) {
651 if (data_format == FMT_EFI) {
652 efi_free(efip);
653 }
654 *errp = ENOMEM;
655 return (NULL);
656 }
657
658 /* get the media name from the descriptor */
659 if (desc->type == DM_MEDIA) {
660 media_name = desc->name;
661 } else {
662 /* must be a DM_PARTITION */
663 media_name = desc->secondary_name;
664 }
665
666 pos = 0;
667 for (devp = desc->p.disk->aliases->devpaths; devp != NULL;
668 devp = devp->next) {
669
670 int slice_num;
671 char devpath[MAXPATHLEN];
672
673 slice_num = get_slice_num(devp);
674 /* can't get slicenum, so no need to keep trying the drive */
675 if (slice_num == -1) {
676 break;
677 }
678
679 if (data_format == FMT_VTOC) {
680 if (slice_num >= vtoc.v_nparts ||
681 vtoc.v_part[slice_num].p_size == 0) {
682 continue;
683 }
684 } else { /* data_format == FMT_EFI */
685 if (slice_num >= efip->efi_nparts ||
686 efip->efi_parts[slice_num].p_size == 0) {
687 continue;
688 }
689 }
690
691 slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath));
692 slices[pos] = cache_get_desc(DM_SLICE, desc->p.disk, devpath,
693 media_name, errp);
694 if (*errp != 0) {
695 cache_free_descriptors(slices);
696 if (data_format == FMT_EFI) {
697 efi_free(efip);
698 }
699 return (NULL);
700 }
701 pos++;
702 }
703 slices[pos] = NULL;
704
705 if (data_format == FMT_EFI) {
706 efi_free(efip);
707 }
708
709 *errp = 0;
710 return (slices);
711 }
712
713 static int
get_slice_num(slice_t * devp)714 get_slice_num(slice_t *devp)
715 {
716 /* check if we already determined the devpath slice number */
717 if (devp->slice_num == -1) {
718 int fd;
719
720 if ((fd = open(devp->devpath, O_RDONLY|O_NDELAY)) >= 0) {
721 struct dk_cinfo dkinfo;
722 if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
723 devp->slice_num = dkinfo.dki_partition;
724 }
725 (void) close(fd);
726 }
727 }
728
729 return (devp->slice_num);
730 }
731
732 static int
make_fixed_descriptors(disk_t * dp)733 make_fixed_descriptors(disk_t *dp)
734 {
735 int error = 0;
736 alias_t *ap;
737 slice_t *devp;
738 char mname[MAXPATHLEN];
739 int data_format = FMT_UNKNOWN;
740 struct extvtoc vtoc;
741 struct dk_gpt *efip;
742
743 /* Just check the first drive name. */
744 if ((ap = dp->aliases) == NULL) {
745 return (0);
746 }
747
748 mname[0] = 0;
749 (void) media_read_name(dp, mname, sizeof (mname));
750
751 for (devp = ap->devpaths; devp != NULL; devp = devp->next) {
752 int slice_num;
753 char devpath[MAXPATHLEN];
754
755 slice_num = get_slice_num(devp);
756 /* can't get slicenum, so no need to keep trying the drive */
757 if (slice_num == -1) {
758 break;
759 }
760
761 if (data_format == FMT_UNKNOWN) {
762 int fd;
763 int status;
764
765 if ((fd = drive_open_disk(dp, NULL, 0)) >= 0) {
766 if ((status = read_extvtoc(fd, &vtoc)) >= 0) {
767 data_format = FMT_VTOC;
768 } else if (status == VT_ENOTSUP &&
769 efi_alloc_and_read(fd, &efip) >= 0) {
770 data_format = FMT_EFI;
771 }
772 (void) close(fd);
773 }
774 }
775
776 /* can't get slice data, so no need to keep trying the drive */
777 if (data_format == FMT_UNKNOWN) {
778 break;
779 }
780
781 if (data_format == FMT_VTOC) {
782 if (slice_num >= vtoc.v_nparts ||
783 vtoc.v_part[slice_num].p_size == 0) {
784 continue;
785 }
786 } else { /* data_format == FMT_EFI */
787 if (slice_num >= efip->efi_nparts ||
788 efip->efi_parts[slice_num].p_size == 0) {
789 continue;
790 }
791 }
792
793 slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath));
794 cache_load_desc(DM_SLICE, dp, devpath, mname, &error);
795 if (error != 0) {
796 break;
797 }
798 }
799
800 if (data_format == FMT_EFI) {
801 efi_free(efip);
802 }
803
804 return (error);
805 }
806
807 /*
808 * Just look for the name on the devpaths we have cached. Return 1 if we
809 * find the name and the size of that slice is non-zero.
810 */
811 static int
match_fixed_name(disk_t * diskp,char * name,int * errp)812 match_fixed_name(disk_t *diskp, char *name, int *errp)
813 {
814 slice_t *dp = NULL;
815 alias_t *ap;
816 int slice_num;
817 int fd;
818 int status;
819 int data_format = FMT_UNKNOWN;
820 struct extvtoc vtoc;
821 struct dk_gpt *efip;
822
823 ap = diskp->aliases;
824 while (ap != NULL) {
825 slice_t *devp;
826
827 devp = ap->devpaths;
828 while (devp != NULL) {
829 char path[MAXPATHLEN];
830
831 slice_rdsk2dsk(devp->devpath, path, sizeof (path));
832 if (libdiskmgt_str_eq(path, name)) {
833 /* found it */
834 dp = devp;
835 break;
836 }
837
838 devp = devp->next;
839 }
840
841 if (dp != NULL) {
842 break;
843 }
844
845 ap = ap->next;
846 }
847
848 if (dp == NULL) {
849 *errp = 0;
850 return (0);
851 }
852
853 /*
854 * If we found a match on the name we now have to check that this
855 * slice really exists (non-0 size).
856 */
857
858 slice_num = get_slice_num(dp);
859 /* can't get slicenum, so no slice */
860 if (slice_num == -1) {
861 *errp = ENODEV;
862 return (1);
863 }
864
865 if ((fd = drive_open_disk(diskp, NULL, 0)) < 0) {
866 *errp = ENODEV;
867 return (1);
868 }
869
870 if ((status = read_extvtoc(fd, &vtoc)) >= 0) {
871 data_format = FMT_VTOC;
872 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) {
873 data_format = FMT_EFI;
874 } else {
875 (void) close(fd);
876 *errp = ENODEV;
877 return (1);
878 }
879 (void) close(fd);
880
881 if (data_format == FMT_VTOC) {
882 if (slice_num < vtoc.v_nparts &&
883 vtoc.v_part[slice_num].p_size > 0) {
884 *errp = 0;
885 return (1);
886 }
887 } else { /* data_format == FMT_EFI */
888 if (slice_num < efip->efi_nparts &&
889 efip->efi_parts[slice_num].p_size > 0) {
890 efi_free(efip);
891 *errp = 0;
892 return (1);
893 }
894 efi_free(efip);
895 }
896
897 *errp = ENODEV;
898 return (1);
899 }
900