xref: /titanic_50/usr/src/lib/libdiskmgt/common/entry.c (revision 46657f8d750bdb71753495ce2919170f126b8e34)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
599653d4eSeschrock  * Common Development and Distribution License (the "License").
699653d4eSeschrock  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*46657f8dSmmusante  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <fcntl.h>
297c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <unistd.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
363e1bd7a2Ssjelinek #include <libintl.h>
373e1bd7a2Ssjelinek #include <locale.h>
383e1bd7a2Ssjelinek #include <sys/debug.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
417c478bd9Sstevel@tonic-gate #include "disks_private.h"
427c478bd9Sstevel@tonic-gate #include "partition.h"
437c478bd9Sstevel@tonic-gate 
443e1bd7a2Ssjelinek extern	char	*getfullblkname();
453e1bd7a2Ssjelinek 
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate extern dm_desc_type_t drive_assoc_types[];
487c478bd9Sstevel@tonic-gate extern dm_desc_type_t bus_assoc_types[];
497c478bd9Sstevel@tonic-gate extern dm_desc_type_t controller_assoc_types[];
507c478bd9Sstevel@tonic-gate extern dm_desc_type_t media_assoc_types[];
517c478bd9Sstevel@tonic-gate extern dm_desc_type_t slice_assoc_types[];
527c478bd9Sstevel@tonic-gate extern dm_desc_type_t partition_assoc_types[];
537c478bd9Sstevel@tonic-gate extern dm_desc_type_t path_assoc_types[];
547c478bd9Sstevel@tonic-gate extern dm_desc_type_t alias_assoc_types[];
557c478bd9Sstevel@tonic-gate 
563e1bd7a2Ssjelinek 
577c478bd9Sstevel@tonic-gate static dm_descriptor_t *ptr_array_to_desc_array(descriptor_t **ptrs, int *errp);
587c478bd9Sstevel@tonic-gate static descriptor_t **desc_array_to_ptr_array(dm_descriptor_t *da, int *errp);
593e1bd7a2Ssjelinek static int build_usage_string(char *dname, char *by, char *data, char **use,
603e1bd7a2Ssjelinek 	int *found, int *errp);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate void
637c478bd9Sstevel@tonic-gate dm_free_descriptor(dm_descriptor_t desc)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	if (desc == NULL) {
687c478bd9Sstevel@tonic-gate 	    return;
697c478bd9Sstevel@tonic-gate 	}
7069fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	cache_wlock();
737c478bd9Sstevel@tonic-gate 	cache_free_descriptor(dp);
747c478bd9Sstevel@tonic-gate 	cache_unlock();
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate void
787c478bd9Sstevel@tonic-gate dm_free_descriptors(dm_descriptor_t *desc_list)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate 	descriptor_t	**dp;
817c478bd9Sstevel@tonic-gate 	int		error;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	if (desc_list == NULL) {
847c478bd9Sstevel@tonic-gate 	    return;
857c478bd9Sstevel@tonic-gate 	}
867c478bd9Sstevel@tonic-gate 	dp = desc_array_to_ptr_array(desc_list, &error);
877c478bd9Sstevel@tonic-gate 	if (error != 0) {
887c478bd9Sstevel@tonic-gate 	    free(desc_list);
897c478bd9Sstevel@tonic-gate 	    return;
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	cache_wlock();
937c478bd9Sstevel@tonic-gate 	cache_free_descriptors(dp);
947c478bd9Sstevel@tonic-gate 	cache_unlock();
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
987c478bd9Sstevel@tonic-gate void
997c478bd9Sstevel@tonic-gate dm_free_name(char *name)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	free(name);
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate dm_descriptor_t *
1057c478bd9Sstevel@tonic-gate dm_get_associated_descriptors(dm_descriptor_t desc, dm_desc_type_t type,
1067c478bd9Sstevel@tonic-gate     int *errp)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	descriptor_t **descs = NULL;
1097c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 
11269fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	cache_wlock();
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
1177c478bd9Sstevel@tonic-gate 	    cache_unlock();
1187c478bd9Sstevel@tonic-gate 	    *errp = EBADF;
1197c478bd9Sstevel@tonic-gate 	    return (NULL);
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
1237c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
1247c478bd9Sstevel@tonic-gate 	    cache_unlock();
1257c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
1267c478bd9Sstevel@tonic-gate 	    return (NULL);
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	switch (dp->type) {
1307c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
1317c478bd9Sstevel@tonic-gate 	    descs = drive_get_assoc_descriptors(dp, type, errp);
1327c478bd9Sstevel@tonic-gate 	    break;
1337c478bd9Sstevel@tonic-gate 	case DM_BUS:
1347c478bd9Sstevel@tonic-gate 	    descs = bus_get_assoc_descriptors(dp, type, errp);
1357c478bd9Sstevel@tonic-gate 	    break;
1367c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
1377c478bd9Sstevel@tonic-gate 	    descs = controller_get_assoc_descriptors(dp, type, errp);
1387c478bd9Sstevel@tonic-gate 	    break;
1397c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
1407c478bd9Sstevel@tonic-gate 	    descs = media_get_assoc_descriptors(dp, type, errp);
1417c478bd9Sstevel@tonic-gate 	    break;
1427c478bd9Sstevel@tonic-gate 	case DM_SLICE:
1437c478bd9Sstevel@tonic-gate 	    descs = slice_get_assoc_descriptors(dp, type, errp);
1447c478bd9Sstevel@tonic-gate 	    break;
1457c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
1467c478bd9Sstevel@tonic-gate 	    descs = partition_get_assoc_descriptors(dp, type, errp);
1477c478bd9Sstevel@tonic-gate 	    break;
1487c478bd9Sstevel@tonic-gate 	case DM_PATH:
1497c478bd9Sstevel@tonic-gate 	    descs = path_get_assoc_descriptors(dp, type, errp);
1507c478bd9Sstevel@tonic-gate 	    break;
1517c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
1527c478bd9Sstevel@tonic-gate 	    descs = alias_get_assoc_descriptors(dp, type, errp);
1537c478bd9Sstevel@tonic-gate 	    break;
1547c478bd9Sstevel@tonic-gate 	default:
1557c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
1567c478bd9Sstevel@tonic-gate 	    break;
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	cache_unlock();
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	return (ptr_array_to_desc_array(descs, errp));
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate dm_desc_type_t *
1657c478bd9Sstevel@tonic-gate dm_get_associated_types(dm_desc_type_t type)
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate 	switch (type) {
1687c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
1697c478bd9Sstevel@tonic-gate 	    return (drive_assoc_types);
1707c478bd9Sstevel@tonic-gate 	case DM_BUS:
1717c478bd9Sstevel@tonic-gate 	    return (bus_assoc_types);
1727c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
1737c478bd9Sstevel@tonic-gate 	    return (controller_assoc_types);
1747c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
1757c478bd9Sstevel@tonic-gate 	    return (media_assoc_types);
1767c478bd9Sstevel@tonic-gate 	case DM_SLICE:
1777c478bd9Sstevel@tonic-gate 	    return (slice_assoc_types);
1787c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
1797c478bd9Sstevel@tonic-gate 	    return (partition_assoc_types);
1807c478bd9Sstevel@tonic-gate 	case DM_PATH:
1817c478bd9Sstevel@tonic-gate 	    return (path_assoc_types);
1827c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
1837c478bd9Sstevel@tonic-gate 	    return (alias_assoc_types);
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	return (NULL);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate nvlist_t *
1907c478bd9Sstevel@tonic-gate dm_get_attributes(dm_descriptor_t desc, int *errp)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
1937c478bd9Sstevel@tonic-gate 	nvlist_t	*attrs = NULL;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 
19669fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	cache_rlock();
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
2017c478bd9Sstevel@tonic-gate 	    cache_unlock();
2027c478bd9Sstevel@tonic-gate 	    *errp = EBADF;
2037c478bd9Sstevel@tonic-gate 	    return (NULL);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
2077c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
2087c478bd9Sstevel@tonic-gate 	    cache_unlock();
2097c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
2107c478bd9Sstevel@tonic-gate 	    return (NULL);
2117c478bd9Sstevel@tonic-gate 	}
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	switch (dp->type) {
2147c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
2157c478bd9Sstevel@tonic-gate 	    attrs = drive_get_attributes(dp, errp);
2167c478bd9Sstevel@tonic-gate 	    break;
2177c478bd9Sstevel@tonic-gate 	case DM_BUS:
2187c478bd9Sstevel@tonic-gate 	    attrs = bus_get_attributes(dp, errp);
2197c478bd9Sstevel@tonic-gate 	    break;
2207c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
2217c478bd9Sstevel@tonic-gate 	    attrs = controller_get_attributes(dp, errp);
2227c478bd9Sstevel@tonic-gate 	    break;
2237c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
2247c478bd9Sstevel@tonic-gate 	    attrs = media_get_attributes(dp, errp);
2257c478bd9Sstevel@tonic-gate 	    break;
2267c478bd9Sstevel@tonic-gate 	case DM_SLICE:
2277c478bd9Sstevel@tonic-gate 	    attrs = slice_get_attributes(dp, errp);
2287c478bd9Sstevel@tonic-gate 	    break;
2297c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
2307c478bd9Sstevel@tonic-gate 	    attrs = partition_get_attributes(dp, errp);
2317c478bd9Sstevel@tonic-gate 	    break;
2327c478bd9Sstevel@tonic-gate 	case DM_PATH:
2337c478bd9Sstevel@tonic-gate 	    attrs = path_get_attributes(dp, errp);
2347c478bd9Sstevel@tonic-gate 	    break;
2357c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
2367c478bd9Sstevel@tonic-gate 	    attrs = alias_get_attributes(dp, errp);
2377c478bd9Sstevel@tonic-gate 	    break;
2387c478bd9Sstevel@tonic-gate 	default:
2397c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
2407c478bd9Sstevel@tonic-gate 	    break;
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	cache_unlock();
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	return (attrs);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate dm_descriptor_t
2497c478bd9Sstevel@tonic-gate dm_get_descriptor_by_name(dm_desc_type_t desc_type, char *name, int *errp)
2507c478bd9Sstevel@tonic-gate {
2517c478bd9Sstevel@tonic-gate 	dm_descriptor_t desc = NULL;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	cache_wlock();
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	switch (desc_type) {
2577c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
2587c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)drive_get_descriptor_by_name(name, errp);
2597c478bd9Sstevel@tonic-gate 	    break;
2607c478bd9Sstevel@tonic-gate 	case DM_BUS:
2617c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)bus_get_descriptor_by_name(name, errp);
2627c478bd9Sstevel@tonic-gate 	    break;
2637c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
2647c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)controller_get_descriptor_by_name(name,
2657c478bd9Sstevel@tonic-gate 		errp);
2667c478bd9Sstevel@tonic-gate 	    break;
2677c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
2687c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)media_get_descriptor_by_name(name, errp);
2697c478bd9Sstevel@tonic-gate 	    break;
2707c478bd9Sstevel@tonic-gate 	case DM_SLICE:
2717c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)slice_get_descriptor_by_name(name, errp);
2727c478bd9Sstevel@tonic-gate 	    break;
2737c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
2747c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)partition_get_descriptor_by_name(name,
2757c478bd9Sstevel@tonic-gate 		errp);
2767c478bd9Sstevel@tonic-gate 	    break;
2777c478bd9Sstevel@tonic-gate 	case DM_PATH:
2787c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)path_get_descriptor_by_name(name, errp);
2797c478bd9Sstevel@tonic-gate 	    break;
2807c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
2817c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)alias_get_descriptor_by_name(name, errp);
2827c478bd9Sstevel@tonic-gate 	    break;
2837c478bd9Sstevel@tonic-gate 	default:
2847c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
2857c478bd9Sstevel@tonic-gate 	    break;
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	cache_unlock();
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	return (desc);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate dm_descriptor_t *
2947c478bd9Sstevel@tonic-gate dm_get_descriptors(dm_desc_type_t type, int filter[], int *errp)
2957c478bd9Sstevel@tonic-gate {
2967c478bd9Sstevel@tonic-gate 	descriptor_t **descs = NULL;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	cache_wlock();
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	switch (type) {
3027c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
3037c478bd9Sstevel@tonic-gate 	    descs = drive_get_descriptors(filter, errp);
3047c478bd9Sstevel@tonic-gate 	    break;
3057c478bd9Sstevel@tonic-gate 	case DM_BUS:
3067c478bd9Sstevel@tonic-gate 	    descs = bus_get_descriptors(filter, errp);
3077c478bd9Sstevel@tonic-gate 	    break;
3087c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
3097c478bd9Sstevel@tonic-gate 	    descs = controller_get_descriptors(filter, errp);
3107c478bd9Sstevel@tonic-gate 	    break;
3117c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
3127c478bd9Sstevel@tonic-gate 	    descs = media_get_descriptors(filter, errp);
3137c478bd9Sstevel@tonic-gate 	    break;
3147c478bd9Sstevel@tonic-gate 	case DM_SLICE:
3157c478bd9Sstevel@tonic-gate 	    descs = slice_get_descriptors(filter, errp);
3167c478bd9Sstevel@tonic-gate 	    break;
3177c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
3187c478bd9Sstevel@tonic-gate 	    descs = partition_get_descriptors(filter, errp);
3197c478bd9Sstevel@tonic-gate 	    break;
3207c478bd9Sstevel@tonic-gate 	case DM_PATH:
3217c478bd9Sstevel@tonic-gate 	    descs = path_get_descriptors(filter, errp);
3227c478bd9Sstevel@tonic-gate 	    break;
3237c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
3247c478bd9Sstevel@tonic-gate 	    descs = alias_get_descriptors(filter, errp);
3257c478bd9Sstevel@tonic-gate 	    break;
3267c478bd9Sstevel@tonic-gate 	default:
3277c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
3287c478bd9Sstevel@tonic-gate 	    break;
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	cache_unlock();
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	return (ptr_array_to_desc_array(descs, errp));
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate char *
3377c478bd9Sstevel@tonic-gate dm_get_name(dm_descriptor_t desc, int *errp)
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
3407c478bd9Sstevel@tonic-gate 	char		*nm = NULL;
3417c478bd9Sstevel@tonic-gate 	char		*name = NULL;
3427c478bd9Sstevel@tonic-gate 
34369fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	cache_rlock();
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
3487c478bd9Sstevel@tonic-gate 	    cache_unlock();
3497c478bd9Sstevel@tonic-gate 	    *errp = EBADF;
3507c478bd9Sstevel@tonic-gate 	    return (NULL);
3517c478bd9Sstevel@tonic-gate 	}
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
3547c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
3557c478bd9Sstevel@tonic-gate 	    cache_unlock();
3567c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
3577c478bd9Sstevel@tonic-gate 	    return (NULL);
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	switch (dp->type) {
3617c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
3627c478bd9Sstevel@tonic-gate 	    nm = (drive_get_name(dp));
3637c478bd9Sstevel@tonic-gate 	    break;
3647c478bd9Sstevel@tonic-gate 	case DM_BUS:
3657c478bd9Sstevel@tonic-gate 	    nm = (bus_get_name(dp));
3667c478bd9Sstevel@tonic-gate 	    break;
3677c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
3687c478bd9Sstevel@tonic-gate 	    nm = (controller_get_name(dp));
3697c478bd9Sstevel@tonic-gate 	    break;
3707c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
3717c478bd9Sstevel@tonic-gate 	    nm = (media_get_name(dp));
3727c478bd9Sstevel@tonic-gate 	    break;
3737c478bd9Sstevel@tonic-gate 	case DM_SLICE:
3747c478bd9Sstevel@tonic-gate 	    nm = (slice_get_name(dp));
3757c478bd9Sstevel@tonic-gate 	    break;
3767c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
3777c478bd9Sstevel@tonic-gate 	    nm = (partition_get_name(dp));
3787c478bd9Sstevel@tonic-gate 	    break;
3797c478bd9Sstevel@tonic-gate 	case DM_PATH:
3807c478bd9Sstevel@tonic-gate 	    nm = (path_get_name(dp));
3817c478bd9Sstevel@tonic-gate 	    break;
3827c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
3837c478bd9Sstevel@tonic-gate 	    nm = (alias_get_name(dp));
3847c478bd9Sstevel@tonic-gate 	    break;
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	cache_unlock();
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	*errp = 0;
3907c478bd9Sstevel@tonic-gate 	if (nm != NULL) {
3917c478bd9Sstevel@tonic-gate 	    name = strdup(nm);
3927c478bd9Sstevel@tonic-gate 	    if (name == NULL) {
3937c478bd9Sstevel@tonic-gate 		*errp = ENOMEM;
3947c478bd9Sstevel@tonic-gate 		return (NULL);
3957c478bd9Sstevel@tonic-gate 	    }
3967c478bd9Sstevel@tonic-gate 	    return (name);
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate 	return (NULL);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate nvlist_t *
4027c478bd9Sstevel@tonic-gate dm_get_stats(dm_descriptor_t desc, int stat_type, int *errp)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
4057c478bd9Sstevel@tonic-gate 	nvlist_t	*stats = NULL;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 
40869fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	cache_rlock();
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
4137c478bd9Sstevel@tonic-gate 		cache_unlock();
4147c478bd9Sstevel@tonic-gate 		*errp = EBADF;
4157c478bd9Sstevel@tonic-gate 		return (NULL);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
4197c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
4207c478bd9Sstevel@tonic-gate 		cache_unlock();
4217c478bd9Sstevel@tonic-gate 		*errp = ENODEV;
4227c478bd9Sstevel@tonic-gate 		return (NULL);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	switch (dp->type) {
4267c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
4277c478bd9Sstevel@tonic-gate 		stats = drive_get_stats(dp, stat_type, errp);
4287c478bd9Sstevel@tonic-gate 		break;
4297c478bd9Sstevel@tonic-gate 	case DM_BUS:
4307c478bd9Sstevel@tonic-gate 		stats = bus_get_stats(dp, stat_type, errp);
4317c478bd9Sstevel@tonic-gate 		break;
4327c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
4337c478bd9Sstevel@tonic-gate 		stats = controller_get_stats(dp, stat_type, errp);
4347c478bd9Sstevel@tonic-gate 		break;
4357c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
4367c478bd9Sstevel@tonic-gate 		stats = media_get_stats(dp, stat_type, errp);
4377c478bd9Sstevel@tonic-gate 		break;
4387c478bd9Sstevel@tonic-gate 	case DM_SLICE:
4393e1bd7a2Ssjelinek 		if (stat_type == DM_SLICE_STAT_USE) {
4403e1bd7a2Ssjelinek 			/*
4413e1bd7a2Ssjelinek 			 * If NOINUSE_CHECK is set, we do not perform
4423e1bd7a2Ssjelinek 			 * the in use checking if the user has set stat_type
4433e1bd7a2Ssjelinek 			 * DM_SLICE_STAT_USE
4443e1bd7a2Ssjelinek 			 */
44582d71480Ssjelinek 			if (NOINUSE_SET) {
4463e1bd7a2Ssjelinek 				stats = NULL;
4473e1bd7a2Ssjelinek 				break;
4483e1bd7a2Ssjelinek 			}
4493e1bd7a2Ssjelinek 		}
4507c478bd9Sstevel@tonic-gate 		stats = slice_get_stats(dp, stat_type, errp);
4517c478bd9Sstevel@tonic-gate 		break;
4527c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
4537c478bd9Sstevel@tonic-gate 		stats = partition_get_stats(dp, stat_type, errp);
4547c478bd9Sstevel@tonic-gate 		break;
4557c478bd9Sstevel@tonic-gate 	case DM_PATH:
4567c478bd9Sstevel@tonic-gate 		stats = path_get_stats(dp, stat_type, errp);
4577c478bd9Sstevel@tonic-gate 		break;
4587c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
4597c478bd9Sstevel@tonic-gate 		stats = alias_get_stats(dp, stat_type, errp);
4607c478bd9Sstevel@tonic-gate 		break;
4617c478bd9Sstevel@tonic-gate 	default:
4627c478bd9Sstevel@tonic-gate 		*errp = EINVAL;
4637c478bd9Sstevel@tonic-gate 		break;
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	cache_unlock();
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	return (stats);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate dm_desc_type_t
4727c478bd9Sstevel@tonic-gate dm_get_type(dm_descriptor_t desc)
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
4757c478bd9Sstevel@tonic-gate 
47669fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	cache_rlock();
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
4817c478bd9Sstevel@tonic-gate 	    cache_unlock();
4827c478bd9Sstevel@tonic-gate 	    return (-1);
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	cache_unlock();
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	return (dp->type);
4887c478bd9Sstevel@tonic-gate }
4893e1bd7a2Ssjelinek /*
4903e1bd7a2Ssjelinek  * Returns, via slices paramater, a dm_descriptor_t list of
4913e1bd7a2Ssjelinek  * slices for the named disk drive.
4923e1bd7a2Ssjelinek  */
4933e1bd7a2Ssjelinek void
4943e1bd7a2Ssjelinek dm_get_slices(char *drive, dm_descriptor_t **slices, int *errp)
4953e1bd7a2Ssjelinek {
4963e1bd7a2Ssjelinek 	dm_descriptor_t alias;
4973e1bd7a2Ssjelinek 	dm_descriptor_t	*media;
4983e1bd7a2Ssjelinek 	dm_descriptor_t *disk;
4997c478bd9Sstevel@tonic-gate 
5003e1bd7a2Ssjelinek 	*slices = NULL;
5013e1bd7a2Ssjelinek 	*errp = 0;
5023e1bd7a2Ssjelinek 
5033e1bd7a2Ssjelinek 	if (drive == NULL) {
5043e1bd7a2Ssjelinek 		return;
5053e1bd7a2Ssjelinek 	}
5063e1bd7a2Ssjelinek 
5073e1bd7a2Ssjelinek 	alias = dm_get_descriptor_by_name(DM_ALIAS, drive, errp);
5083e1bd7a2Ssjelinek 
5093e1bd7a2Ssjelinek 	/*
5103e1bd7a2Ssjelinek 	 * Errors must be handled by the caller. The dm_descriptor_t *
5113e1bd7a2Ssjelinek 	 * values will be NULL if an error occured in these calls.
5123e1bd7a2Ssjelinek 	 */
5133e1bd7a2Ssjelinek 
5143e1bd7a2Ssjelinek 	if (alias != NULL) {
5153e1bd7a2Ssjelinek 		disk = dm_get_associated_descriptors(alias, DM_DRIVE, errp);
5163e1bd7a2Ssjelinek 		dm_free_descriptor(alias);
5173e1bd7a2Ssjelinek 		if (disk != NULL) {
5183e1bd7a2Ssjelinek 			media = dm_get_associated_descriptors(*disk,
5193e1bd7a2Ssjelinek 			    DM_MEDIA, errp);
5203e1bd7a2Ssjelinek 			dm_free_descriptors(disk);
5213e1bd7a2Ssjelinek 			if (media != NULL) {
5223e1bd7a2Ssjelinek 				*slices = dm_get_associated_descriptors(*media,
5233e1bd7a2Ssjelinek 				    DM_SLICE, errp);
5243e1bd7a2Ssjelinek 				dm_free_descriptors(media);
5253e1bd7a2Ssjelinek 			}
5263e1bd7a2Ssjelinek 		}
5273e1bd7a2Ssjelinek 	}
5283e1bd7a2Ssjelinek }
5293e1bd7a2Ssjelinek /*
5303e1bd7a2Ssjelinek  * Convenience function to get slice stats
5313e1bd7a2Ssjelinek  */
5323e1bd7a2Ssjelinek void
5333e1bd7a2Ssjelinek dm_get_slice_stats(char *slice, nvlist_t **dev_stats, int *errp)
5343e1bd7a2Ssjelinek {
5353e1bd7a2Ssjelinek 	dm_descriptor_t	devp;
5363e1bd7a2Ssjelinek 
5373e1bd7a2Ssjelinek 	*dev_stats = NULL;
5383e1bd7a2Ssjelinek 	*errp = 0;
5393e1bd7a2Ssjelinek 
5403e1bd7a2Ssjelinek 	if (slice == NULL) {
5413e1bd7a2Ssjelinek 		return;
5423e1bd7a2Ssjelinek 	}
5433e1bd7a2Ssjelinek 
5443e1bd7a2Ssjelinek 	/*
5453e1bd7a2Ssjelinek 	 * Errors must be handled by the caller. The dm_descriptor_t *
5463e1bd7a2Ssjelinek 	 * values will be NULL if an error occured in these calls.
5473e1bd7a2Ssjelinek 	 */
5483e1bd7a2Ssjelinek 	devp = dm_get_descriptor_by_name(DM_SLICE, slice, errp);
5493e1bd7a2Ssjelinek 	if (devp != NULL) {
5503e1bd7a2Ssjelinek 		*dev_stats = dm_get_stats(devp, DM_SLICE_STAT_USE,
5513e1bd7a2Ssjelinek 		    errp);
5523e1bd7a2Ssjelinek 		dm_free_descriptor(devp);
5533e1bd7a2Ssjelinek 	}
5543e1bd7a2Ssjelinek }
5553e1bd7a2Ssjelinek 
5563e1bd7a2Ssjelinek /*
55746a2abf2Seschrock  * Checks for overlapping slices.   If the given device is a slice, and it
55846a2abf2Seschrock  * overlaps with any non-backup slice on the disk, return true with a detailed
55946a2abf2Seschrock  * description similar to dm_inuse().
56046a2abf2Seschrock  */
56146a2abf2Seschrock int
56246a2abf2Seschrock dm_isoverlapping(char *slicename, char **overlaps_with, int *errp)
56346a2abf2Seschrock {
56446a2abf2Seschrock 	dm_descriptor_t slice = NULL;
56546a2abf2Seschrock 	dm_descriptor_t *media = NULL;
56646a2abf2Seschrock 	dm_descriptor_t *slices = NULL;
56746a2abf2Seschrock 	int 		i = 0;
56846a2abf2Seschrock 	uint32_t	in_snum;
56946a2abf2Seschrock 	uint64_t 	start_block = 0;
57046a2abf2Seschrock 	uint64_t 	end_block = 0;
57146a2abf2Seschrock 	uint64_t 	media_size = 0;
57246a2abf2Seschrock 	uint64_t 	size = 0;
57346a2abf2Seschrock 	nvlist_t 	*media_attrs = NULL;
57446a2abf2Seschrock 	nvlist_t 	*slice_attrs = NULL;
57546a2abf2Seschrock 	int		ret = 0;
57646a2abf2Seschrock 
57746a2abf2Seschrock 	slice = dm_get_descriptor_by_name(DM_SLICE, slicename, errp);
57846a2abf2Seschrock 	if (slice == NULL)
57946a2abf2Seschrock 		goto out;
58046a2abf2Seschrock 
58146a2abf2Seschrock 	/*
58246a2abf2Seschrock 	 * Get the list of slices be fetching the associated media, and then all
58346a2abf2Seschrock 	 * associated slices.
58446a2abf2Seschrock 	 */
58546a2abf2Seschrock 	media = dm_get_associated_descriptors(slice, DM_MEDIA, errp);
58646a2abf2Seschrock 	if (media == NULL || *media == NULL || *errp != 0)
58746a2abf2Seschrock 		goto out;
58846a2abf2Seschrock 
58946a2abf2Seschrock 	slices = dm_get_associated_descriptors(*media, DM_SLICE, errp);
59046a2abf2Seschrock 	if (slices == NULL || *slices == NULL || *errp != 0)
59146a2abf2Seschrock 		goto out;
59246a2abf2Seschrock 
59346a2abf2Seschrock 	media_attrs = dm_get_attributes(*media, errp);
59446a2abf2Seschrock 	if (media_attrs == NULL || *errp)
59546a2abf2Seschrock 		goto out;
59646a2abf2Seschrock 
59746a2abf2Seschrock 	*errp = nvlist_lookup_uint64(media_attrs, DM_NACCESSIBLE, &media_size);
59846a2abf2Seschrock 	if (*errp != 0)
59946a2abf2Seschrock 		goto out;
60046a2abf2Seschrock 
60146a2abf2Seschrock 	slice_attrs = dm_get_attributes(slice, errp);
60246a2abf2Seschrock 	if (slice_attrs == NULL || *errp != 0)
60346a2abf2Seschrock 		goto out;
60446a2abf2Seschrock 
60546a2abf2Seschrock 	*errp = nvlist_lookup_uint64(slice_attrs, DM_START, &start_block);
60646a2abf2Seschrock 	if (*errp != 0)
60746a2abf2Seschrock 		goto out;
60846a2abf2Seschrock 
60946a2abf2Seschrock 	*errp = nvlist_lookup_uint64(slice_attrs, DM_SIZE, &size);
61046a2abf2Seschrock 	if (*errp != 0)
61146a2abf2Seschrock 		goto out;
61246a2abf2Seschrock 
61346a2abf2Seschrock 	*errp = nvlist_lookup_uint32(slice_attrs, DM_INDEX, &in_snum);
61446a2abf2Seschrock 	if (*errp != 0)
61546a2abf2Seschrock 		goto out;
61646a2abf2Seschrock 
61746a2abf2Seschrock 	end_block = (start_block + size) - 1;
61846a2abf2Seschrock 
61946a2abf2Seschrock 	for (i = 0; slices[i]; i ++) {
62046a2abf2Seschrock 		uint64_t other_start;
62146a2abf2Seschrock 		uint64_t other_end;
62246a2abf2Seschrock 		uint64_t other_size;
62346a2abf2Seschrock 		uint32_t snum;
62446a2abf2Seschrock 
62546a2abf2Seschrock 		nvlist_t *other_attrs = dm_get_attributes(slices[i], errp);
62646a2abf2Seschrock 
62746a2abf2Seschrock 		if (other_attrs == NULL)
62846a2abf2Seschrock 			continue;
62946a2abf2Seschrock 
63046a2abf2Seschrock 		if (*errp != 0)
63146a2abf2Seschrock 			goto out;
63246a2abf2Seschrock 
63346a2abf2Seschrock 		*errp = nvlist_lookup_uint64(other_attrs, DM_START,
63446a2abf2Seschrock 		    &other_start);
63546a2abf2Seschrock 		if (*errp) {
63646a2abf2Seschrock 			nvlist_free(other_attrs);
63746a2abf2Seschrock 			goto out;
63846a2abf2Seschrock 		}
63946a2abf2Seschrock 
64046a2abf2Seschrock 		*errp = nvlist_lookup_uint64(other_attrs, DM_SIZE,
64146a2abf2Seschrock 		    &other_size);
64246a2abf2Seschrock 
64346a2abf2Seschrock 		if (*errp) {
64446a2abf2Seschrock 			nvlist_free(other_attrs);
64546a2abf2Seschrock 			ret = -1;
64646a2abf2Seschrock 			goto out;
64746a2abf2Seschrock 		}
64846a2abf2Seschrock 
64946a2abf2Seschrock 		other_end = (other_size + other_start) - 1;
65046a2abf2Seschrock 
65146a2abf2Seschrock 		*errp = nvlist_lookup_uint32(other_attrs, DM_INDEX,
65246a2abf2Seschrock 		    &snum);
65346a2abf2Seschrock 
65446a2abf2Seschrock 		if (*errp) {
65546a2abf2Seschrock 			nvlist_free(other_attrs);
65646a2abf2Seschrock 			ret = -1;
65746a2abf2Seschrock 			goto out;
65846a2abf2Seschrock 		}
65946a2abf2Seschrock 
66046a2abf2Seschrock 		/*
66146a2abf2Seschrock 		 * Check to see if there are > 2 overlapping regions
66246a2abf2Seschrock 		 * on this media in the same region as this slice.
66346a2abf2Seschrock 		 * This is done by assuming the following:
66446a2abf2Seschrock 		 *   	Slice 2 is the backup slice if it is the size
66546a2abf2Seschrock 		 *	of the whole disk
66646a2abf2Seschrock 		 * If slice 2 is the overlap and slice 2 is the size of
66746a2abf2Seschrock 		 * the whole disk, continue. If another slice is found
66846a2abf2Seschrock 		 * that overlaps with our slice, return it.
66946a2abf2Seschrock 		 * There is the potential that there is more than one slice
67046a2abf2Seschrock 		 * that our slice overlaps with, however, we only return
67146a2abf2Seschrock 		 * the first overlapping slice we find.
67246a2abf2Seschrock 		 *
67346a2abf2Seschrock 		 */
67446a2abf2Seschrock 		if (start_block >= other_start && start_block <= other_end) {
67546a2abf2Seschrock 			if ((snum == 2 && (other_size == media_size)) ||
67646a2abf2Seschrock 			    snum == in_snum) {
67746a2abf2Seschrock 				continue;
67846a2abf2Seschrock 			} else {
67946a2abf2Seschrock 				char *str = dm_get_name(slices[i], errp);
68046a2abf2Seschrock 				if (*errp != 0) {
68146a2abf2Seschrock 					nvlist_free(other_attrs);
68246a2abf2Seschrock 					ret = -1;
68346a2abf2Seschrock 					goto out;
68446a2abf2Seschrock 				}
68546a2abf2Seschrock 				*overlaps_with = strdup(str);
68646a2abf2Seschrock 				dm_free_name(str);
68746a2abf2Seschrock 				nvlist_free(other_attrs);
68846a2abf2Seschrock 				ret = 1;
68946a2abf2Seschrock 				goto out;
69046a2abf2Seschrock 			}
69146a2abf2Seschrock 		} else if (other_start >= start_block &&
69246a2abf2Seschrock 		    other_start <= end_block) {
69346a2abf2Seschrock 			if ((snum == 2 && (other_size == media_size)) ||
69446a2abf2Seschrock 			    snum == in_snum) {
69546a2abf2Seschrock 				continue;
69646a2abf2Seschrock 			} else {
69746a2abf2Seschrock 				char *str = dm_get_name(slices[i], errp);
69846a2abf2Seschrock 				if (*errp != 0) {
69946a2abf2Seschrock 					nvlist_free(other_attrs);
70046a2abf2Seschrock 					ret = -1;
70146a2abf2Seschrock 					goto out;
70246a2abf2Seschrock 				}
70346a2abf2Seschrock 				*overlaps_with = strdup(str);
70446a2abf2Seschrock 				dm_free_name(str);
70546a2abf2Seschrock 				nvlist_free(other_attrs);
70646a2abf2Seschrock 				ret = 1;
70746a2abf2Seschrock 				goto out;
70846a2abf2Seschrock 			}
70946a2abf2Seschrock 		}
71046a2abf2Seschrock 		nvlist_free(other_attrs);
71146a2abf2Seschrock 	}
71246a2abf2Seschrock 
71346a2abf2Seschrock out:
71446a2abf2Seschrock 	if (media_attrs)
71546a2abf2Seschrock 		nvlist_free(media_attrs);
71646a2abf2Seschrock 	if (slice_attrs)
71746a2abf2Seschrock 		nvlist_free(slice_attrs);
71846a2abf2Seschrock 
71946a2abf2Seschrock 	if (slices)
72046a2abf2Seschrock 		dm_free_descriptors(slices);
72146a2abf2Seschrock 	if (media)
72246a2abf2Seschrock 		dm_free_descriptors(media);
72346a2abf2Seschrock 	if (slice)
72446a2abf2Seschrock 		dm_free_descriptor(slice);
72546a2abf2Seschrock 
72646a2abf2Seschrock 	return (ret);
72746a2abf2Seschrock }
72846a2abf2Seschrock 
72946a2abf2Seschrock /*
7303e1bd7a2Ssjelinek  * Returns 'in use' details, if found, about a specific dev_name,
7313e1bd7a2Ssjelinek  * based on the caller(who). It is important to note that it is possible
7323e1bd7a2Ssjelinek  * for there to be more than one 'in use' statistic regarding a dev_name.
7333e1bd7a2Ssjelinek  * The **msg parameter returns a list of 'in use' details. This message
7343e1bd7a2Ssjelinek  * is formatted via gettext().
7353e1bd7a2Ssjelinek  */
7363e1bd7a2Ssjelinek int
7373e1bd7a2Ssjelinek dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
7383e1bd7a2Ssjelinek {
7393e1bd7a2Ssjelinek 	nvlist_t *dev_stats = NULL;
7403e1bd7a2Ssjelinek 	char *by, *data;
7413e1bd7a2Ssjelinek 	nvpair_t *nvwhat = NULL;
7423e1bd7a2Ssjelinek 	nvpair_t *nvdesc = NULL;
7433e1bd7a2Ssjelinek 	int	found = 0;
7443e1bd7a2Ssjelinek 	char	*dname = NULL;
7453e1bd7a2Ssjelinek 
7463e1bd7a2Ssjelinek 	*errp = 0;
7473e1bd7a2Ssjelinek 	*msg = NULL;
7483e1bd7a2Ssjelinek 
74982d71480Ssjelinek 	/*
75082d71480Ssjelinek 	 * If the user doesn't want to do in use checking, return.
75182d71480Ssjelinek 	 */
75282d71480Ssjelinek 
75382d71480Ssjelinek 	if (NOINUSE_SET)
75482d71480Ssjelinek 		return (0);
75582d71480Ssjelinek 
7563e1bd7a2Ssjelinek 	dname = getfullblkname(dev_name);
7573e1bd7a2Ssjelinek 	/*
7583e1bd7a2Ssjelinek 	 * If we cannot find the block name, we cannot check the device
7593e1bd7a2Ssjelinek 	 * for in use statistics. So, return found, which is == 0.
7603e1bd7a2Ssjelinek 	 */
7613e1bd7a2Ssjelinek 	if (dname == NULL || *dname == '\0') {
7623e1bd7a2Ssjelinek 		return (found);
7633e1bd7a2Ssjelinek 	}
7643e1bd7a2Ssjelinek 
7653e1bd7a2Ssjelinek 	dm_get_slice_stats(dname, &dev_stats, errp);
7663e1bd7a2Ssjelinek 	if (dev_stats == NULL) {
7673e1bd7a2Ssjelinek 		/*
7683e1bd7a2Ssjelinek 		 * If there is an error, but it isn't a no device found error
7693e1bd7a2Ssjelinek 		 * return the error as recorded. Otherwise, with a full
7703e1bd7a2Ssjelinek 		 * block name, we might not be able to get the slice
7713e1bd7a2Ssjelinek 		 * associated, and will get an ENODEV error. For example,
7723e1bd7a2Ssjelinek 		 * an SVM metadevice will return a value from getfullblkname()
7733e1bd7a2Ssjelinek 		 * but libdiskmgt won't be able to find this device for
7743e1bd7a2Ssjelinek 		 * statistics gathering. This is expected and we should not
7753e1bd7a2Ssjelinek 		 * report errnoneous errors.
7763e1bd7a2Ssjelinek 		 */
7773e1bd7a2Ssjelinek 		if (*errp) {
7783e1bd7a2Ssjelinek 			if (*errp == ENODEV) {
7793e1bd7a2Ssjelinek 				*errp = 0;
7803e1bd7a2Ssjelinek 			}
7813e1bd7a2Ssjelinek 		}
7823e1bd7a2Ssjelinek 		free(dname);
7833e1bd7a2Ssjelinek 		return (found);
7843e1bd7a2Ssjelinek 	}
7853e1bd7a2Ssjelinek 
7863e1bd7a2Ssjelinek 	for (;;) {
7873e1bd7a2Ssjelinek 
7883e1bd7a2Ssjelinek 		nvwhat = nvlist_next_nvpair(dev_stats, nvdesc);
7893e1bd7a2Ssjelinek 		nvdesc = nvlist_next_nvpair(dev_stats, nvwhat);
7903e1bd7a2Ssjelinek 
7913e1bd7a2Ssjelinek 		/*
7923e1bd7a2Ssjelinek 		 * End of the list found.
7933e1bd7a2Ssjelinek 		 */
7943e1bd7a2Ssjelinek 		if (nvwhat == NULL || nvdesc == NULL) {
7953e1bd7a2Ssjelinek 			break;
7963e1bd7a2Ssjelinek 		}
7973e1bd7a2Ssjelinek 		/*
7983e1bd7a2Ssjelinek 		 * Otherwise, we check to see if this client(who) cares
7993e1bd7a2Ssjelinek 		 * about this in use scenario
8003e1bd7a2Ssjelinek 		 */
8013e1bd7a2Ssjelinek 
8023e1bd7a2Ssjelinek 		ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0);
8033e1bd7a2Ssjelinek 		ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0);
8043e1bd7a2Ssjelinek 		/*
8053e1bd7a2Ssjelinek 		 * If we error getting the string value continue on
8063e1bd7a2Ssjelinek 		 * to the next pair(if there is one)
8073e1bd7a2Ssjelinek 		 */
8083e1bd7a2Ssjelinek 		if (nvpair_value_string(nvwhat, &by)) {
8093e1bd7a2Ssjelinek 			continue;
8103e1bd7a2Ssjelinek 		}
8113e1bd7a2Ssjelinek 		if (nvpair_value_string(nvdesc, &data)) {
8123e1bd7a2Ssjelinek 			continue;
8133e1bd7a2Ssjelinek 		}
8143e1bd7a2Ssjelinek 
8153e1bd7a2Ssjelinek 		switch (who) {
8163e1bd7a2Ssjelinek 			case DM_WHO_MKFS:
8173e1bd7a2Ssjelinek 				/*
8183e1bd7a2Ssjelinek 				 * mkfs is not in use for these cases.
8193e1bd7a2Ssjelinek 				 * All others are in use.
8203e1bd7a2Ssjelinek 				 */
8213e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_LU) == 0 ||
82246a2abf2Seschrock 				    strcmp(by, DM_USE_FS) == 0 ||
82346a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
8243e1bd7a2Ssjelinek 					break;
8253e1bd7a2Ssjelinek 				}
8263e1bd7a2Ssjelinek 				if (build_usage_string(dname,
8273e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
8283e1bd7a2Ssjelinek 					if (*errp) {
8293e1bd7a2Ssjelinek 						goto out;
8303e1bd7a2Ssjelinek 					}
8313e1bd7a2Ssjelinek 				}
8323e1bd7a2Ssjelinek 				break;
8333e1bd7a2Ssjelinek 			case DM_WHO_SWAP:
8343e1bd7a2Ssjelinek 				/*
8353e1bd7a2Ssjelinek 				 * Not in use for this.
8363e1bd7a2Ssjelinek 				 */
8373e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_DUMP) == 0 ||
83846a2abf2Seschrock 				    strcmp(by, DM_USE_FS) == 0 ||
83946a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
8403e1bd7a2Ssjelinek 					break;
8413e1bd7a2Ssjelinek 				}
8423e1bd7a2Ssjelinek 
8433e1bd7a2Ssjelinek 				if (build_usage_string(dname,
8443e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
8453e1bd7a2Ssjelinek 					if (*errp) {
8463e1bd7a2Ssjelinek 						goto out;
8473e1bd7a2Ssjelinek 					}
8483e1bd7a2Ssjelinek 				}
8493e1bd7a2Ssjelinek 				break;
8503e1bd7a2Ssjelinek 			case DM_WHO_DUMP:
8513e1bd7a2Ssjelinek 				/*
8523e1bd7a2Ssjelinek 				 * Not in use for this.
8533e1bd7a2Ssjelinek 				 */
8543e1bd7a2Ssjelinek 				if ((strcmp(by, DM_USE_MOUNT) == 0 &&
8553e1bd7a2Ssjelinek 				    strcmp(data, "swap") == 0) ||
8563e1bd7a2Ssjelinek 				    strcmp(by, DM_USE_DUMP) == 0 ||
85746a2abf2Seschrock 				    strcmp(by, DM_USE_FS) == 0 ||
85846a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
8593e1bd7a2Ssjelinek 					break;
8603e1bd7a2Ssjelinek 				}
8613e1bd7a2Ssjelinek 				if (build_usage_string(dname,
8623e1bd7a2Ssjelinek 				    by, data, msg, &found, errp)) {
8633e1bd7a2Ssjelinek 					if (*errp) {
8643e1bd7a2Ssjelinek 						goto out;
8653e1bd7a2Ssjelinek 					}
8663e1bd7a2Ssjelinek 				}
8673e1bd7a2Ssjelinek 				break;
8683e1bd7a2Ssjelinek 
8693e1bd7a2Ssjelinek 			case DM_WHO_FORMAT:
87046a2abf2Seschrock 				if (strcmp(by, DM_USE_FS) == 0 ||
87146a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
8723e1bd7a2Ssjelinek 					break;
8733e1bd7a2Ssjelinek 				if (build_usage_string(dname,
8743e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
8753e1bd7a2Ssjelinek 					if (*errp) {
8763e1bd7a2Ssjelinek 						goto out;
8773e1bd7a2Ssjelinek 					}
8783e1bd7a2Ssjelinek 				}
8793e1bd7a2Ssjelinek 				break;
88046a2abf2Seschrock 
88146a2abf2Seschrock 			case DM_WHO_ZPOOL_FORCE:
88246a2abf2Seschrock 				if (strcmp(by, DM_USE_FS) == 0 ||
88346a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
88446a2abf2Seschrock 					break;
88546a2abf2Seschrock 				/* FALLTHROUGH */
88646a2abf2Seschrock 			case DM_WHO_ZPOOL:
88746a2abf2Seschrock 				if (build_usage_string(dname,
88846a2abf2Seschrock 				    by, data, msg, &found, errp) != 0) {
88946a2abf2Seschrock 					if (*errp)
89046a2abf2Seschrock 						goto out;
89146a2abf2Seschrock 				}
89246a2abf2Seschrock 				break;
89346a2abf2Seschrock 
894*46657f8dSmmusante 			case DM_WHO_ZPOOL_SPARE:
895*46657f8dSmmusante 				if (strcmp(by, DM_USE_SPARE_ZPOOL) != 0) {
896*46657f8dSmmusante 					if (build_usage_string(dname, by,
897*46657f8dSmmusante 					    data, msg, &found, errp) != 0) {
898*46657f8dSmmusante 						if (*errp)
899*46657f8dSmmusante 							goto out;
900*46657f8dSmmusante 					}
901*46657f8dSmmusante 				}
902*46657f8dSmmusante 				break;
903*46657f8dSmmusante 
9043e1bd7a2Ssjelinek 			default:
9053e1bd7a2Ssjelinek 				/*
9063e1bd7a2Ssjelinek 				 * nothing found in use for this client
9073e1bd7a2Ssjelinek 				 * of libdiskmgt. Default is 'not in use'.
9083e1bd7a2Ssjelinek 				 */
9093e1bd7a2Ssjelinek 				break;
9103e1bd7a2Ssjelinek 		}
9113e1bd7a2Ssjelinek 	}
9123e1bd7a2Ssjelinek out:
9133e1bd7a2Ssjelinek 	if (dname != NULL)
9143e1bd7a2Ssjelinek 		free(dname);
9153e1bd7a2Ssjelinek 	if (dev_stats != NULL)
9163e1bd7a2Ssjelinek 		nvlist_free(dev_stats);
9173e1bd7a2Ssjelinek 
9183e1bd7a2Ssjelinek 	return (found);
9193e1bd7a2Ssjelinek }
9203e1bd7a2Ssjelinek 
9213e1bd7a2Ssjelinek void
9223e1bd7a2Ssjelinek dm_get_usage_string(char *what, char *how, char **usage_string)
9233e1bd7a2Ssjelinek {
9243e1bd7a2Ssjelinek 
9253e1bd7a2Ssjelinek 
9263e1bd7a2Ssjelinek 	if (usage_string == NULL || what == NULL) {
9273e1bd7a2Ssjelinek 		return;
9283e1bd7a2Ssjelinek 	}
9293e1bd7a2Ssjelinek 	*usage_string = NULL;
9303e1bd7a2Ssjelinek 
9313e1bd7a2Ssjelinek 	if (strcmp(what, DM_USE_MOUNT) == 0) {
9323e1bd7a2Ssjelinek 		if (strcmp(how, "swap") == 0) {
9333e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
9343e1bd7a2Ssjelinek 			    "%s is currently used by swap. Please see swap(1M)."
9353e1bd7a2Ssjelinek 			    "\n");
9363e1bd7a2Ssjelinek 		} else {
9373e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
9383e1bd7a2Ssjelinek 			    "%s is currently mounted on %s."
9393e1bd7a2Ssjelinek 			    " Please see umount(1M).\n");
9403e1bd7a2Ssjelinek 		}
9413e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_VFSTAB) == 0) {
9423e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
9433e1bd7a2Ssjelinek 		    "%s is normally mounted on %s according to /etc/vfstab. "
9443e1bd7a2Ssjelinek 		    "Please remove this entry to use this device.\n");
9453e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_FS) == 0) {
9463e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
94746a2abf2Seschrock 		    "%s contains a %s filesystem.\n");
9483e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_SVM) == 0) {
9493e1bd7a2Ssjelinek 		if (strcmp(how, "mdb") == 0) {
9503e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
9513e1bd7a2Ssjelinek 			    "%s contains an SVM %s. Please see "
9523e1bd7a2Ssjelinek 			    "metadb(1M).\n");
9533e1bd7a2Ssjelinek 		} else {
9543e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
9553e1bd7a2Ssjelinek 			    "%s is part of SVM volume %s. "
9563e1bd7a2Ssjelinek 			    "Please see metaclear(1M).\n");
9573e1bd7a2Ssjelinek 		}
9583e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_VXVM) == 0) {
9593e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
9603e1bd7a2Ssjelinek 		    "%s is part of VxVM volume %s.\n");
9613e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_LU) == 0) {
9623e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
9633e1bd7a2Ssjelinek 		    "%s is in use for live upgrade %s. Please see ludelete(1M)."
9643e1bd7a2Ssjelinek 		    "\n");
9653e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_DUMP) == 0) {
9663e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
9673e1bd7a2Ssjelinek 		    "%s is in use by %s. Please see dumpadm(1M)."
9683e1bd7a2Ssjelinek 		    "\n");
96946a2abf2Seschrock 	} else if (strcmp(what, DM_USE_EXPORTED_ZPOOL) == 0) {
9703e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
97146a2abf2Seschrock 		    "%s is part of exported or potentially active ZFS pool %s. "
97246a2abf2Seschrock 		    "Please see zpool(1M).\n");
97346a2abf2Seschrock 	} else if (strcmp(what, DM_USE_ACTIVE_ZPOOL) == 0) {
97446a2abf2Seschrock 		*usage_string = dgettext(TEXT_DOMAIN,
97546a2abf2Seschrock 		    "%s is part of active ZFS pool %s. Please see zpool(1M)."
9763e1bd7a2Ssjelinek 		    "\n");
97799653d4eSeschrock 	} else if (strcmp(what, DM_USE_SPARE_ZPOOL) == 0) {
97899653d4eSeschrock 		*usage_string = dgettext(TEXT_DOMAIN,
97999653d4eSeschrock 		    "%s is reserved as a hot spare for ZFS pool %s.  Please "
98099653d4eSeschrock 		    "see zpool(1M).\n");
9813e1bd7a2Ssjelinek 	}
9823e1bd7a2Ssjelinek }
9837c478bd9Sstevel@tonic-gate void
9847c478bd9Sstevel@tonic-gate libdiskmgt_add_str(nvlist_t *attrs, char *name, char *val, int *errp)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate 	if (*errp == 0) {
9877c478bd9Sstevel@tonic-gate 		*errp = nvlist_add_string(attrs, name, val);
9887c478bd9Sstevel@tonic-gate 	}
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate descriptor_t **
9927c478bd9Sstevel@tonic-gate libdiskmgt_empty_desc_array(int *errp)
9937c478bd9Sstevel@tonic-gate {
9947c478bd9Sstevel@tonic-gate 	descriptor_t	**empty;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	empty = (descriptor_t **)calloc(1, sizeof (descriptor_t *));
9977c478bd9Sstevel@tonic-gate 	if (empty == NULL) {
9987c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
9997c478bd9Sstevel@tonic-gate 	    return (NULL);
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 	empty[0] = NULL;
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	*errp = 0;
10047c478bd9Sstevel@tonic-gate 	return (empty);
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate void
10087c478bd9Sstevel@tonic-gate libdiskmgt_init_debug()
10097c478bd9Sstevel@tonic-gate {
10107c478bd9Sstevel@tonic-gate 	char	*valp;
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	if ((valp = getenv(DM_DEBUG)) != NULL) {
10137c478bd9Sstevel@tonic-gate 	    dm_debug = atoi(valp);
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate int
10187c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(char *nm1, char *nm2)
10197c478bd9Sstevel@tonic-gate {
10207c478bd9Sstevel@tonic-gate 	if (nm1 == NULL) {
10217c478bd9Sstevel@tonic-gate 	    if (dm_debug) {
10227c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "WARNING: str_eq nm1 NULL\n");
10237c478bd9Sstevel@tonic-gate 	    }
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	    if (nm2 == NULL) {
10267c478bd9Sstevel@tonic-gate 		return (1);
10277c478bd9Sstevel@tonic-gate 	    } else {
10287c478bd9Sstevel@tonic-gate 		return (0);
10297c478bd9Sstevel@tonic-gate 	    }
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	/* nm1 != NULL */
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	if (nm2 == NULL) {
10357c478bd9Sstevel@tonic-gate 	    if (dm_debug) {
10367c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "WARNING: str_eq nm2 NULL\n");
10377c478bd9Sstevel@tonic-gate 	    }
10387c478bd9Sstevel@tonic-gate 	    return (0);
10397c478bd9Sstevel@tonic-gate 	}
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	if (strcmp(nm1, nm2) == 0) {
10427c478bd9Sstevel@tonic-gate 	    return (1);
10437c478bd9Sstevel@tonic-gate 	}
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	return (0);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10497c478bd9Sstevel@tonic-gate static descriptor_t **
10507c478bd9Sstevel@tonic-gate desc_array_to_ptr_array(dm_descriptor_t *descs, int *errp)
10517c478bd9Sstevel@tonic-gate {
10527c478bd9Sstevel@tonic-gate #ifdef _LP64
10537c478bd9Sstevel@tonic-gate 	return ((descriptor_t **)descs);
10547c478bd9Sstevel@tonic-gate #else
10557c478bd9Sstevel@tonic-gate 	/* convert the 64 bit descriptors to 32 bit ptrs */
10567c478bd9Sstevel@tonic-gate 	int	cnt;
10577c478bd9Sstevel@tonic-gate 	int	i;
10587c478bd9Sstevel@tonic-gate 	descriptor_t **da;
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	for (cnt = 0; descs[cnt]; cnt++);
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	da = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
10637c478bd9Sstevel@tonic-gate 	if (da == NULL) {
10647c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
10657c478bd9Sstevel@tonic-gate 	    return (NULL);
10667c478bd9Sstevel@tonic-gate 	}
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 	for (i = 0; descs[i]; i++) {
106969fb9702Smike_s 	    da[i] = (descriptor_t *)(uintptr_t)descs[i];
10707c478bd9Sstevel@tonic-gate 	}
10717c478bd9Sstevel@tonic-gate 	*errp = 0;
10727c478bd9Sstevel@tonic-gate 	free(descs);
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	return (da);
10757c478bd9Sstevel@tonic-gate #endif
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10797c478bd9Sstevel@tonic-gate static dm_descriptor_t *
10807c478bd9Sstevel@tonic-gate ptr_array_to_desc_array(descriptor_t **ptrs, int *errp)
10817c478bd9Sstevel@tonic-gate {
10827c478bd9Sstevel@tonic-gate #ifdef _LP64
10837c478bd9Sstevel@tonic-gate 	return ((dm_descriptor_t *)ptrs);
10847c478bd9Sstevel@tonic-gate #else
10857c478bd9Sstevel@tonic-gate 	/* convert the 32 bit ptrs to the 64 bit descriptors */
10867c478bd9Sstevel@tonic-gate 	int	cnt;
10877c478bd9Sstevel@tonic-gate 	int	i;
10887c478bd9Sstevel@tonic-gate 	dm_descriptor_t *da;
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 	if (*errp != 0 || ptrs == NULL) {
10917c478bd9Sstevel@tonic-gate 	    return (NULL);
10927c478bd9Sstevel@tonic-gate 	}
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	for (cnt = 0; ptrs[cnt]; cnt++);
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	da = (dm_descriptor_t *)calloc(cnt + 1, sizeof (dm_descriptor_t));
10977c478bd9Sstevel@tonic-gate 	if (da == NULL) {
10987c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
10997c478bd9Sstevel@tonic-gate 	    return (NULL);
11007c478bd9Sstevel@tonic-gate 	}
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	for (i = 0; ptrs[i]; i++) {
11037c478bd9Sstevel@tonic-gate 	    da[i] = (uintptr_t)ptrs[i];
11047c478bd9Sstevel@tonic-gate 	}
11057c478bd9Sstevel@tonic-gate 	*errp = 0;
11067c478bd9Sstevel@tonic-gate 	free(ptrs);
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 	return (da);
11097c478bd9Sstevel@tonic-gate #endif
11107c478bd9Sstevel@tonic-gate }
11113e1bd7a2Ssjelinek /*
11123e1bd7a2Ssjelinek  * Build the usage string for the in use data. Return the build string in
11133e1bd7a2Ssjelinek  * the msg parameter. This function takes care of reallocing all the memory
11143e1bd7a2Ssjelinek  * for this usage string. Usage string is returned already formatted for
11153e1bd7a2Ssjelinek  * localization.
11163e1bd7a2Ssjelinek  */
11173e1bd7a2Ssjelinek static int
11183e1bd7a2Ssjelinek build_usage_string(char *dname, char *by, char *data, char **msg,
11193e1bd7a2Ssjelinek     int *found, int *errp)
11203e1bd7a2Ssjelinek {
11213e1bd7a2Ssjelinek 	int	len0;
11223e1bd7a2Ssjelinek 	int	len1;
11233e1bd7a2Ssjelinek 	char	*use;
11243e1bd7a2Ssjelinek 	char	*p;
11253e1bd7a2Ssjelinek 
11263e1bd7a2Ssjelinek 	*errp = 0;
11273e1bd7a2Ssjelinek 
11283e1bd7a2Ssjelinek 	dm_get_usage_string(by, data, &use);
11293e1bd7a2Ssjelinek 	if (!use) {
11303e1bd7a2Ssjelinek 		return (-1);
11313e1bd7a2Ssjelinek 	}
11323e1bd7a2Ssjelinek 
11333e1bd7a2Ssjelinek 	if (*msg)
11343e1bd7a2Ssjelinek 		len0 = strlen(*msg);
11353e1bd7a2Ssjelinek 	else
11363e1bd7a2Ssjelinek 		len0 = 0;
11373e1bd7a2Ssjelinek 	/* LINTED */
11383e1bd7a2Ssjelinek 	len1 = snprintf(NULL, 0, use, dname, data);
11393e1bd7a2Ssjelinek 
11403e1bd7a2Ssjelinek 	/*
11413e1bd7a2Ssjelinek 	 * If multiple in use details they
11423e1bd7a2Ssjelinek 	 * are listed 1 per line for ease of
11433e1bd7a2Ssjelinek 	 * reading. dm_find_usage_string
11443e1bd7a2Ssjelinek 	 * formats these appropriately.
11453e1bd7a2Ssjelinek 	 */
11463e1bd7a2Ssjelinek 	if ((p = realloc(*msg, len0 + len1 + 1)) == NULL) {
11473e1bd7a2Ssjelinek 		*errp = errno;
11483e1bd7a2Ssjelinek 		free(*msg);
11493e1bd7a2Ssjelinek 		return (-1);
11503e1bd7a2Ssjelinek 	}
11513e1bd7a2Ssjelinek 	*msg = p;
11523e1bd7a2Ssjelinek 
11533e1bd7a2Ssjelinek 	/* LINTED */
11543e1bd7a2Ssjelinek 	(void) snprintf(*msg + len0, len1 + 1, use, dname, data);
11553e1bd7a2Ssjelinek 	(*found)++;
11563e1bd7a2Ssjelinek 	return (0);
11573e1bd7a2Ssjelinek }
1158