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