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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
2369fb9702Smike_s  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <fcntl.h>
307c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
37*3e1bd7a2Ssjelinek #include <libintl.h>
38*3e1bd7a2Ssjelinek #include <locale.h>
39*3e1bd7a2Ssjelinek #include <sys/debug.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
427c478bd9Sstevel@tonic-gate #include "disks_private.h"
437c478bd9Sstevel@tonic-gate #include "partition.h"
447c478bd9Sstevel@tonic-gate 
45*3e1bd7a2Ssjelinek extern	char	*getfullblkname();
46*3e1bd7a2Ssjelinek 
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate extern dm_desc_type_t drive_assoc_types[];
497c478bd9Sstevel@tonic-gate extern dm_desc_type_t bus_assoc_types[];
507c478bd9Sstevel@tonic-gate extern dm_desc_type_t controller_assoc_types[];
517c478bd9Sstevel@tonic-gate extern dm_desc_type_t media_assoc_types[];
527c478bd9Sstevel@tonic-gate extern dm_desc_type_t slice_assoc_types[];
537c478bd9Sstevel@tonic-gate extern dm_desc_type_t partition_assoc_types[];
547c478bd9Sstevel@tonic-gate extern dm_desc_type_t path_assoc_types[];
557c478bd9Sstevel@tonic-gate extern dm_desc_type_t alias_assoc_types[];
567c478bd9Sstevel@tonic-gate 
57*3e1bd7a2Ssjelinek 
587c478bd9Sstevel@tonic-gate static dm_descriptor_t *ptr_array_to_desc_array(descriptor_t **ptrs, int *errp);
597c478bd9Sstevel@tonic-gate static descriptor_t **desc_array_to_ptr_array(dm_descriptor_t *da, int *errp);
60*3e1bd7a2Ssjelinek static int build_usage_string(char *dname, char *by, char *data, char **use,
61*3e1bd7a2Ssjelinek 	int *found, int *errp);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate void
647c478bd9Sstevel@tonic-gate dm_free_descriptor(dm_descriptor_t desc)
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	if (desc == NULL) {
697c478bd9Sstevel@tonic-gate 	    return;
707c478bd9Sstevel@tonic-gate 	}
7169fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	cache_wlock();
747c478bd9Sstevel@tonic-gate 	cache_free_descriptor(dp);
757c478bd9Sstevel@tonic-gate 	cache_unlock();
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate void
797c478bd9Sstevel@tonic-gate dm_free_descriptors(dm_descriptor_t *desc_list)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	descriptor_t	**dp;
827c478bd9Sstevel@tonic-gate 	int		error;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (desc_list == NULL) {
857c478bd9Sstevel@tonic-gate 	    return;
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	dp = desc_array_to_ptr_array(desc_list, &error);
887c478bd9Sstevel@tonic-gate 	if (error != 0) {
897c478bd9Sstevel@tonic-gate 	    free(desc_list);
907c478bd9Sstevel@tonic-gate 	    return;
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	cache_wlock();
947c478bd9Sstevel@tonic-gate 	cache_free_descriptors(dp);
957c478bd9Sstevel@tonic-gate 	cache_unlock();
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*ARGSUSED*/
997c478bd9Sstevel@tonic-gate void
1007c478bd9Sstevel@tonic-gate dm_free_name(char *name)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	free(name);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate dm_descriptor_t *
1067c478bd9Sstevel@tonic-gate dm_get_associated_descriptors(dm_descriptor_t desc, dm_desc_type_t type,
1077c478bd9Sstevel@tonic-gate     int *errp)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	descriptor_t **descs = NULL;
1107c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 
11369fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	cache_wlock();
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
1187c478bd9Sstevel@tonic-gate 	    cache_unlock();
1197c478bd9Sstevel@tonic-gate 	    *errp = EBADF;
1207c478bd9Sstevel@tonic-gate 	    return (NULL);
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
1247c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
1257c478bd9Sstevel@tonic-gate 	    cache_unlock();
1267c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
1277c478bd9Sstevel@tonic-gate 	    return (NULL);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	switch (dp->type) {
1317c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
1327c478bd9Sstevel@tonic-gate 	    descs = drive_get_assoc_descriptors(dp, type, errp);
1337c478bd9Sstevel@tonic-gate 	    break;
1347c478bd9Sstevel@tonic-gate 	case DM_BUS:
1357c478bd9Sstevel@tonic-gate 	    descs = bus_get_assoc_descriptors(dp, type, errp);
1367c478bd9Sstevel@tonic-gate 	    break;
1377c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
1387c478bd9Sstevel@tonic-gate 	    descs = controller_get_assoc_descriptors(dp, type, errp);
1397c478bd9Sstevel@tonic-gate 	    break;
1407c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
1417c478bd9Sstevel@tonic-gate 	    descs = media_get_assoc_descriptors(dp, type, errp);
1427c478bd9Sstevel@tonic-gate 	    break;
1437c478bd9Sstevel@tonic-gate 	case DM_SLICE:
1447c478bd9Sstevel@tonic-gate 	    descs = slice_get_assoc_descriptors(dp, type, errp);
1457c478bd9Sstevel@tonic-gate 	    break;
1467c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
1477c478bd9Sstevel@tonic-gate 	    descs = partition_get_assoc_descriptors(dp, type, errp);
1487c478bd9Sstevel@tonic-gate 	    break;
1497c478bd9Sstevel@tonic-gate 	case DM_PATH:
1507c478bd9Sstevel@tonic-gate 	    descs = path_get_assoc_descriptors(dp, type, errp);
1517c478bd9Sstevel@tonic-gate 	    break;
1527c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
1537c478bd9Sstevel@tonic-gate 	    descs = alias_get_assoc_descriptors(dp, type, errp);
1547c478bd9Sstevel@tonic-gate 	    break;
1557c478bd9Sstevel@tonic-gate 	default:
1567c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
1577c478bd9Sstevel@tonic-gate 	    break;
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	cache_unlock();
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	return (ptr_array_to_desc_array(descs, errp));
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate dm_desc_type_t *
1667c478bd9Sstevel@tonic-gate dm_get_associated_types(dm_desc_type_t type)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	switch (type) {
1697c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
1707c478bd9Sstevel@tonic-gate 	    return (drive_assoc_types);
1717c478bd9Sstevel@tonic-gate 	case DM_BUS:
1727c478bd9Sstevel@tonic-gate 	    return (bus_assoc_types);
1737c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
1747c478bd9Sstevel@tonic-gate 	    return (controller_assoc_types);
1757c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
1767c478bd9Sstevel@tonic-gate 	    return (media_assoc_types);
1777c478bd9Sstevel@tonic-gate 	case DM_SLICE:
1787c478bd9Sstevel@tonic-gate 	    return (slice_assoc_types);
1797c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
1807c478bd9Sstevel@tonic-gate 	    return (partition_assoc_types);
1817c478bd9Sstevel@tonic-gate 	case DM_PATH:
1827c478bd9Sstevel@tonic-gate 	    return (path_assoc_types);
1837c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
1847c478bd9Sstevel@tonic-gate 	    return (alias_assoc_types);
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	return (NULL);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate nvlist_t *
1917c478bd9Sstevel@tonic-gate dm_get_attributes(dm_descriptor_t desc, int *errp)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
1947c478bd9Sstevel@tonic-gate 	nvlist_t	*attrs = NULL;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 
19769fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	cache_rlock();
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
2027c478bd9Sstevel@tonic-gate 	    cache_unlock();
2037c478bd9Sstevel@tonic-gate 	    *errp = EBADF;
2047c478bd9Sstevel@tonic-gate 	    return (NULL);
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
2087c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
2097c478bd9Sstevel@tonic-gate 	    cache_unlock();
2107c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
2117c478bd9Sstevel@tonic-gate 	    return (NULL);
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	switch (dp->type) {
2157c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
2167c478bd9Sstevel@tonic-gate 	    attrs = drive_get_attributes(dp, errp);
2177c478bd9Sstevel@tonic-gate 	    break;
2187c478bd9Sstevel@tonic-gate 	case DM_BUS:
2197c478bd9Sstevel@tonic-gate 	    attrs = bus_get_attributes(dp, errp);
2207c478bd9Sstevel@tonic-gate 	    break;
2217c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
2227c478bd9Sstevel@tonic-gate 	    attrs = controller_get_attributes(dp, errp);
2237c478bd9Sstevel@tonic-gate 	    break;
2247c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
2257c478bd9Sstevel@tonic-gate 	    attrs = media_get_attributes(dp, errp);
2267c478bd9Sstevel@tonic-gate 	    break;
2277c478bd9Sstevel@tonic-gate 	case DM_SLICE:
2287c478bd9Sstevel@tonic-gate 	    attrs = slice_get_attributes(dp, errp);
2297c478bd9Sstevel@tonic-gate 	    break;
2307c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
2317c478bd9Sstevel@tonic-gate 	    attrs = partition_get_attributes(dp, errp);
2327c478bd9Sstevel@tonic-gate 	    break;
2337c478bd9Sstevel@tonic-gate 	case DM_PATH:
2347c478bd9Sstevel@tonic-gate 	    attrs = path_get_attributes(dp, errp);
2357c478bd9Sstevel@tonic-gate 	    break;
2367c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
2377c478bd9Sstevel@tonic-gate 	    attrs = alias_get_attributes(dp, errp);
2387c478bd9Sstevel@tonic-gate 	    break;
2397c478bd9Sstevel@tonic-gate 	default:
2407c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
2417c478bd9Sstevel@tonic-gate 	    break;
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	cache_unlock();
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	return (attrs);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate dm_descriptor_t
2507c478bd9Sstevel@tonic-gate dm_get_descriptor_by_name(dm_desc_type_t desc_type, char *name, int *errp)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate 	dm_descriptor_t desc = NULL;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	cache_wlock();
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	switch (desc_type) {
2587c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
2597c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)drive_get_descriptor_by_name(name, errp);
2607c478bd9Sstevel@tonic-gate 	    break;
2617c478bd9Sstevel@tonic-gate 	case DM_BUS:
2627c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)bus_get_descriptor_by_name(name, errp);
2637c478bd9Sstevel@tonic-gate 	    break;
2647c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
2657c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)controller_get_descriptor_by_name(name,
2667c478bd9Sstevel@tonic-gate 		errp);
2677c478bd9Sstevel@tonic-gate 	    break;
2687c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
2697c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)media_get_descriptor_by_name(name, errp);
2707c478bd9Sstevel@tonic-gate 	    break;
2717c478bd9Sstevel@tonic-gate 	case DM_SLICE:
2727c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)slice_get_descriptor_by_name(name, errp);
2737c478bd9Sstevel@tonic-gate 	    break;
2747c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
2757c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)partition_get_descriptor_by_name(name,
2767c478bd9Sstevel@tonic-gate 		errp);
2777c478bd9Sstevel@tonic-gate 	    break;
2787c478bd9Sstevel@tonic-gate 	case DM_PATH:
2797c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)path_get_descriptor_by_name(name, errp);
2807c478bd9Sstevel@tonic-gate 	    break;
2817c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
2827c478bd9Sstevel@tonic-gate 	    desc = (uintptr_t)alias_get_descriptor_by_name(name, errp);
2837c478bd9Sstevel@tonic-gate 	    break;
2847c478bd9Sstevel@tonic-gate 	default:
2857c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
2867c478bd9Sstevel@tonic-gate 	    break;
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	cache_unlock();
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	return (desc);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate dm_descriptor_t *
2957c478bd9Sstevel@tonic-gate dm_get_descriptors(dm_desc_type_t type, int filter[], int *errp)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	descriptor_t **descs = NULL;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	cache_wlock();
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	switch (type) {
3037c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
3047c478bd9Sstevel@tonic-gate 	    descs = drive_get_descriptors(filter, errp);
3057c478bd9Sstevel@tonic-gate 	    break;
3067c478bd9Sstevel@tonic-gate 	case DM_BUS:
3077c478bd9Sstevel@tonic-gate 	    descs = bus_get_descriptors(filter, errp);
3087c478bd9Sstevel@tonic-gate 	    break;
3097c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
3107c478bd9Sstevel@tonic-gate 	    descs = controller_get_descriptors(filter, errp);
3117c478bd9Sstevel@tonic-gate 	    break;
3127c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
3137c478bd9Sstevel@tonic-gate 	    descs = media_get_descriptors(filter, errp);
3147c478bd9Sstevel@tonic-gate 	    break;
3157c478bd9Sstevel@tonic-gate 	case DM_SLICE:
3167c478bd9Sstevel@tonic-gate 	    descs = slice_get_descriptors(filter, errp);
3177c478bd9Sstevel@tonic-gate 	    break;
3187c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
3197c478bd9Sstevel@tonic-gate 	    descs = partition_get_descriptors(filter, errp);
3207c478bd9Sstevel@tonic-gate 	    break;
3217c478bd9Sstevel@tonic-gate 	case DM_PATH:
3227c478bd9Sstevel@tonic-gate 	    descs = path_get_descriptors(filter, errp);
3237c478bd9Sstevel@tonic-gate 	    break;
3247c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
3257c478bd9Sstevel@tonic-gate 	    descs = alias_get_descriptors(filter, errp);
3267c478bd9Sstevel@tonic-gate 	    break;
3277c478bd9Sstevel@tonic-gate 	default:
3287c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
3297c478bd9Sstevel@tonic-gate 	    break;
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	cache_unlock();
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	return (ptr_array_to_desc_array(descs, errp));
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate char *
3387c478bd9Sstevel@tonic-gate dm_get_name(dm_descriptor_t desc, int *errp)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
3417c478bd9Sstevel@tonic-gate 	char		*nm = NULL;
3427c478bd9Sstevel@tonic-gate 	char		*name = NULL;
3437c478bd9Sstevel@tonic-gate 
34469fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	cache_rlock();
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
3497c478bd9Sstevel@tonic-gate 	    cache_unlock();
3507c478bd9Sstevel@tonic-gate 	    *errp = EBADF;
3517c478bd9Sstevel@tonic-gate 	    return (NULL);
3527c478bd9Sstevel@tonic-gate 	}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
3557c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
3567c478bd9Sstevel@tonic-gate 	    cache_unlock();
3577c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
3587c478bd9Sstevel@tonic-gate 	    return (NULL);
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	switch (dp->type) {
3627c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
3637c478bd9Sstevel@tonic-gate 	    nm = (drive_get_name(dp));
3647c478bd9Sstevel@tonic-gate 	    break;
3657c478bd9Sstevel@tonic-gate 	case DM_BUS:
3667c478bd9Sstevel@tonic-gate 	    nm = (bus_get_name(dp));
3677c478bd9Sstevel@tonic-gate 	    break;
3687c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
3697c478bd9Sstevel@tonic-gate 	    nm = (controller_get_name(dp));
3707c478bd9Sstevel@tonic-gate 	    break;
3717c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
3727c478bd9Sstevel@tonic-gate 	    nm = (media_get_name(dp));
3737c478bd9Sstevel@tonic-gate 	    break;
3747c478bd9Sstevel@tonic-gate 	case DM_SLICE:
3757c478bd9Sstevel@tonic-gate 	    nm = (slice_get_name(dp));
3767c478bd9Sstevel@tonic-gate 	    break;
3777c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
3787c478bd9Sstevel@tonic-gate 	    nm = (partition_get_name(dp));
3797c478bd9Sstevel@tonic-gate 	    break;
3807c478bd9Sstevel@tonic-gate 	case DM_PATH:
3817c478bd9Sstevel@tonic-gate 	    nm = (path_get_name(dp));
3827c478bd9Sstevel@tonic-gate 	    break;
3837c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
3847c478bd9Sstevel@tonic-gate 	    nm = (alias_get_name(dp));
3857c478bd9Sstevel@tonic-gate 	    break;
3867c478bd9Sstevel@tonic-gate 	}
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	cache_unlock();
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	*errp = 0;
3917c478bd9Sstevel@tonic-gate 	if (nm != NULL) {
3927c478bd9Sstevel@tonic-gate 	    name = strdup(nm);
3937c478bd9Sstevel@tonic-gate 	    if (name == NULL) {
3947c478bd9Sstevel@tonic-gate 		*errp = ENOMEM;
3957c478bd9Sstevel@tonic-gate 		return (NULL);
3967c478bd9Sstevel@tonic-gate 	    }
3977c478bd9Sstevel@tonic-gate 	    return (name);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 	return (NULL);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate nvlist_t *
4037c478bd9Sstevel@tonic-gate dm_get_stats(dm_descriptor_t desc, int stat_type, int *errp)
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
4067c478bd9Sstevel@tonic-gate 	nvlist_t	*stats = NULL;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 
40969fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	cache_rlock();
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
414*3e1bd7a2Ssjelinek 		cache_unlock();
415*3e1bd7a2Ssjelinek 		*errp = EBADF;
416*3e1bd7a2Ssjelinek 		return (NULL);
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
4207c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
421*3e1bd7a2Ssjelinek 		cache_unlock();
422*3e1bd7a2Ssjelinek 		*errp = ENODEV;
423*3e1bd7a2Ssjelinek 		return (NULL);
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	switch (dp->type) {
4277c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
428*3e1bd7a2Ssjelinek 		stats = drive_get_stats(dp, stat_type, errp);
429*3e1bd7a2Ssjelinek 		break;
4307c478bd9Sstevel@tonic-gate 	case DM_BUS:
431*3e1bd7a2Ssjelinek 		stats = bus_get_stats(dp, stat_type, errp);
432*3e1bd7a2Ssjelinek 		break;
4337c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
434*3e1bd7a2Ssjelinek 		stats = controller_get_stats(dp, stat_type, errp);
435*3e1bd7a2Ssjelinek 		break;
4367c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
437*3e1bd7a2Ssjelinek 		stats = media_get_stats(dp, stat_type, errp);
438*3e1bd7a2Ssjelinek 		break;
4397c478bd9Sstevel@tonic-gate 	case DM_SLICE:
440*3e1bd7a2Ssjelinek 		if (stat_type == DM_SLICE_STAT_USE) {
441*3e1bd7a2Ssjelinek 			/*
442*3e1bd7a2Ssjelinek 			 * If NOINUSE_CHECK is set, we do not perform
443*3e1bd7a2Ssjelinek 			 * the in use checking if the user has set stat_type
444*3e1bd7a2Ssjelinek 			 * DM_SLICE_STAT_USE
445*3e1bd7a2Ssjelinek 			 */
446*3e1bd7a2Ssjelinek 			if (getenv("NOINUSE_CHECK") != NULL) {
447*3e1bd7a2Ssjelinek 				stats = NULL;
448*3e1bd7a2Ssjelinek 				break;
449*3e1bd7a2Ssjelinek 			}
450*3e1bd7a2Ssjelinek 		}
451*3e1bd7a2Ssjelinek 		stats = slice_get_stats(dp, stat_type, errp);
452*3e1bd7a2Ssjelinek 		break;
4537c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
454*3e1bd7a2Ssjelinek 		stats = partition_get_stats(dp, stat_type, errp);
455*3e1bd7a2Ssjelinek 		break;
4567c478bd9Sstevel@tonic-gate 	case DM_PATH:
457*3e1bd7a2Ssjelinek 		stats = path_get_stats(dp, stat_type, errp);
458*3e1bd7a2Ssjelinek 		break;
4597c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
460*3e1bd7a2Ssjelinek 		stats = alias_get_stats(dp, stat_type, errp);
461*3e1bd7a2Ssjelinek 		break;
4627c478bd9Sstevel@tonic-gate 	default:
463*3e1bd7a2Ssjelinek 		*errp = EINVAL;
464*3e1bd7a2Ssjelinek 		break;
4657c478bd9Sstevel@tonic-gate 	}
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	cache_unlock();
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	return (stats);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate dm_desc_type_t
4737c478bd9Sstevel@tonic-gate dm_get_type(dm_descriptor_t desc)
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
4767c478bd9Sstevel@tonic-gate 
47769fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	cache_rlock();
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
4827c478bd9Sstevel@tonic-gate 	    cache_unlock();
4837c478bd9Sstevel@tonic-gate 	    return (-1);
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	cache_unlock();
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	return (dp->type);
4897c478bd9Sstevel@tonic-gate }
490*3e1bd7a2Ssjelinek /*
491*3e1bd7a2Ssjelinek  * Returns, via slices paramater, a dm_descriptor_t list of
492*3e1bd7a2Ssjelinek  * slices for the named disk drive.
493*3e1bd7a2Ssjelinek  */
494*3e1bd7a2Ssjelinek void
495*3e1bd7a2Ssjelinek dm_get_slices(char *drive, dm_descriptor_t **slices, int *errp)
496*3e1bd7a2Ssjelinek {
497*3e1bd7a2Ssjelinek 	dm_descriptor_t alias;
498*3e1bd7a2Ssjelinek 	dm_descriptor_t	*media;
499*3e1bd7a2Ssjelinek 	dm_descriptor_t *disk;
5007c478bd9Sstevel@tonic-gate 
501*3e1bd7a2Ssjelinek 	*slices = NULL;
502*3e1bd7a2Ssjelinek 	*errp = 0;
503*3e1bd7a2Ssjelinek 
504*3e1bd7a2Ssjelinek 	if (drive == NULL) {
505*3e1bd7a2Ssjelinek 		return;
506*3e1bd7a2Ssjelinek 	}
507*3e1bd7a2Ssjelinek 
508*3e1bd7a2Ssjelinek 	alias = dm_get_descriptor_by_name(DM_ALIAS, drive, errp);
509*3e1bd7a2Ssjelinek 
510*3e1bd7a2Ssjelinek 	/*
511*3e1bd7a2Ssjelinek 	 * Errors must be handled by the caller. The dm_descriptor_t *
512*3e1bd7a2Ssjelinek 	 * values will be NULL if an error occured in these calls.
513*3e1bd7a2Ssjelinek 	 */
514*3e1bd7a2Ssjelinek 
515*3e1bd7a2Ssjelinek 	if (alias != NULL) {
516*3e1bd7a2Ssjelinek 		disk = dm_get_associated_descriptors(alias, DM_DRIVE, errp);
517*3e1bd7a2Ssjelinek 		dm_free_descriptor(alias);
518*3e1bd7a2Ssjelinek 		if (disk != NULL) {
519*3e1bd7a2Ssjelinek 			media = dm_get_associated_descriptors(*disk,
520*3e1bd7a2Ssjelinek 			    DM_MEDIA, errp);
521*3e1bd7a2Ssjelinek 			dm_free_descriptors(disk);
522*3e1bd7a2Ssjelinek 			if (media != NULL) {
523*3e1bd7a2Ssjelinek 				*slices = dm_get_associated_descriptors(*media,
524*3e1bd7a2Ssjelinek 				    DM_SLICE, errp);
525*3e1bd7a2Ssjelinek 				dm_free_descriptors(media);
526*3e1bd7a2Ssjelinek 			}
527*3e1bd7a2Ssjelinek 		}
528*3e1bd7a2Ssjelinek 	}
529*3e1bd7a2Ssjelinek }
530*3e1bd7a2Ssjelinek /*
531*3e1bd7a2Ssjelinek  * Convenience function to get slice stats
532*3e1bd7a2Ssjelinek  */
533*3e1bd7a2Ssjelinek void
534*3e1bd7a2Ssjelinek dm_get_slice_stats(char *slice, nvlist_t **dev_stats, int *errp)
535*3e1bd7a2Ssjelinek {
536*3e1bd7a2Ssjelinek 	dm_descriptor_t	devp;
537*3e1bd7a2Ssjelinek 
538*3e1bd7a2Ssjelinek 	*dev_stats = NULL;
539*3e1bd7a2Ssjelinek 	*errp = 0;
540*3e1bd7a2Ssjelinek 
541*3e1bd7a2Ssjelinek 	if (slice == NULL) {
542*3e1bd7a2Ssjelinek 		return;
543*3e1bd7a2Ssjelinek 	}
544*3e1bd7a2Ssjelinek 
545*3e1bd7a2Ssjelinek 	/*
546*3e1bd7a2Ssjelinek 	 * Errors must be handled by the caller. The dm_descriptor_t *
547*3e1bd7a2Ssjelinek 	 * values will be NULL if an error occured in these calls.
548*3e1bd7a2Ssjelinek 	 */
549*3e1bd7a2Ssjelinek 	devp = dm_get_descriptor_by_name(DM_SLICE, slice, errp);
550*3e1bd7a2Ssjelinek 	if (devp != NULL) {
551*3e1bd7a2Ssjelinek 		*dev_stats = dm_get_stats(devp, DM_SLICE_STAT_USE,
552*3e1bd7a2Ssjelinek 		    errp);
553*3e1bd7a2Ssjelinek 		dm_free_descriptor(devp);
554*3e1bd7a2Ssjelinek 	}
555*3e1bd7a2Ssjelinek }
556*3e1bd7a2Ssjelinek 
557*3e1bd7a2Ssjelinek /*
558*3e1bd7a2Ssjelinek  * Returns 'in use' details, if found, about a specific dev_name,
559*3e1bd7a2Ssjelinek  * based on the caller(who). It is important to note that it is possible
560*3e1bd7a2Ssjelinek  * for there to be more than one 'in use' statistic regarding a dev_name.
561*3e1bd7a2Ssjelinek  * The **msg parameter returns a list of 'in use' details. This message
562*3e1bd7a2Ssjelinek  * is formatted via gettext().
563*3e1bd7a2Ssjelinek  */
564*3e1bd7a2Ssjelinek int
565*3e1bd7a2Ssjelinek dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
566*3e1bd7a2Ssjelinek {
567*3e1bd7a2Ssjelinek 	nvlist_t *dev_stats = NULL;
568*3e1bd7a2Ssjelinek 	char *by, *data;
569*3e1bd7a2Ssjelinek 	nvpair_t *nvwhat = NULL;
570*3e1bd7a2Ssjelinek 	nvpair_t *nvdesc = NULL;
571*3e1bd7a2Ssjelinek 	int	found = 0;
572*3e1bd7a2Ssjelinek 	char	*dname = NULL;
573*3e1bd7a2Ssjelinek 
574*3e1bd7a2Ssjelinek 	*errp = 0;
575*3e1bd7a2Ssjelinek 	*msg = NULL;
576*3e1bd7a2Ssjelinek 
577*3e1bd7a2Ssjelinek 	dname = getfullblkname(dev_name);
578*3e1bd7a2Ssjelinek 	/*
579*3e1bd7a2Ssjelinek 	 * If we cannot find the block name, we cannot check the device
580*3e1bd7a2Ssjelinek 	 * for in use statistics. So, return found, which is == 0.
581*3e1bd7a2Ssjelinek 	 */
582*3e1bd7a2Ssjelinek 	if (dname == NULL || *dname == '\0') {
583*3e1bd7a2Ssjelinek 		return (found);
584*3e1bd7a2Ssjelinek 	}
585*3e1bd7a2Ssjelinek 
586*3e1bd7a2Ssjelinek 	dm_get_slice_stats(dname, &dev_stats, errp);
587*3e1bd7a2Ssjelinek 	if (dev_stats == NULL) {
588*3e1bd7a2Ssjelinek 		/*
589*3e1bd7a2Ssjelinek 		 * If there is an error, but it isn't a no device found error
590*3e1bd7a2Ssjelinek 		 * return the error as recorded. Otherwise, with a full
591*3e1bd7a2Ssjelinek 		 * block name, we might not be able to get the slice
592*3e1bd7a2Ssjelinek 		 * associated, and will get an ENODEV error. For example,
593*3e1bd7a2Ssjelinek 		 * an SVM metadevice will return a value from getfullblkname()
594*3e1bd7a2Ssjelinek 		 * but libdiskmgt won't be able to find this device for
595*3e1bd7a2Ssjelinek 		 * statistics gathering. This is expected and we should not
596*3e1bd7a2Ssjelinek 		 * report errnoneous errors.
597*3e1bd7a2Ssjelinek 		 */
598*3e1bd7a2Ssjelinek 		if (*errp) {
599*3e1bd7a2Ssjelinek 			if (*errp == ENODEV) {
600*3e1bd7a2Ssjelinek 				*errp = 0;
601*3e1bd7a2Ssjelinek 			}
602*3e1bd7a2Ssjelinek 		}
603*3e1bd7a2Ssjelinek 		free(dname);
604*3e1bd7a2Ssjelinek 		return (found);
605*3e1bd7a2Ssjelinek 	}
606*3e1bd7a2Ssjelinek 
607*3e1bd7a2Ssjelinek 	for (;;) {
608*3e1bd7a2Ssjelinek 
609*3e1bd7a2Ssjelinek 		nvwhat = nvlist_next_nvpair(dev_stats, nvdesc);
610*3e1bd7a2Ssjelinek 		nvdesc = nvlist_next_nvpair(dev_stats, nvwhat);
611*3e1bd7a2Ssjelinek 
612*3e1bd7a2Ssjelinek 		/*
613*3e1bd7a2Ssjelinek 		 * End of the list found.
614*3e1bd7a2Ssjelinek 		 */
615*3e1bd7a2Ssjelinek 		if (nvwhat == NULL || nvdesc == NULL) {
616*3e1bd7a2Ssjelinek 			break;
617*3e1bd7a2Ssjelinek 		}
618*3e1bd7a2Ssjelinek 		/*
619*3e1bd7a2Ssjelinek 		 * Otherwise, we check to see if this client(who) cares
620*3e1bd7a2Ssjelinek 		 * about this in use scenario
621*3e1bd7a2Ssjelinek 		 */
622*3e1bd7a2Ssjelinek 
623*3e1bd7a2Ssjelinek 		ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0);
624*3e1bd7a2Ssjelinek 		ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0);
625*3e1bd7a2Ssjelinek 		/*
626*3e1bd7a2Ssjelinek 		 * If we error getting the string value continue on
627*3e1bd7a2Ssjelinek 		 * to the next pair(if there is one)
628*3e1bd7a2Ssjelinek 		 */
629*3e1bd7a2Ssjelinek 		if (nvpair_value_string(nvwhat, &by)) {
630*3e1bd7a2Ssjelinek 			continue;
631*3e1bd7a2Ssjelinek 		}
632*3e1bd7a2Ssjelinek 		if (nvpair_value_string(nvdesc, &data)) {
633*3e1bd7a2Ssjelinek 			continue;
634*3e1bd7a2Ssjelinek 		}
635*3e1bd7a2Ssjelinek 
636*3e1bd7a2Ssjelinek 		switch (who) {
637*3e1bd7a2Ssjelinek 			case DM_WHO_MKFS:
638*3e1bd7a2Ssjelinek 				/*
639*3e1bd7a2Ssjelinek 				 * mkfs is not in use for these cases.
640*3e1bd7a2Ssjelinek 				 * All others are in use.
641*3e1bd7a2Ssjelinek 				 */
642*3e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_LU) == 0 ||
643*3e1bd7a2Ssjelinek 				    strcmp(by, DM_USE_FS) == 0) {
644*3e1bd7a2Ssjelinek 					break;
645*3e1bd7a2Ssjelinek 				}
646*3e1bd7a2Ssjelinek 				if (build_usage_string(dname,
647*3e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
648*3e1bd7a2Ssjelinek 					if (*errp) {
649*3e1bd7a2Ssjelinek 						goto out;
650*3e1bd7a2Ssjelinek 					}
651*3e1bd7a2Ssjelinek 				}
652*3e1bd7a2Ssjelinek 				break;
653*3e1bd7a2Ssjelinek 			case DM_WHO_SWAP:
654*3e1bd7a2Ssjelinek 				/*
655*3e1bd7a2Ssjelinek 				 * Not in use for this.
656*3e1bd7a2Ssjelinek 				 */
657*3e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_DUMP) == 0 ||
658*3e1bd7a2Ssjelinek 				    strcmp(by, DM_USE_FS) == 0) {
659*3e1bd7a2Ssjelinek 					break;
660*3e1bd7a2Ssjelinek 				}
661*3e1bd7a2Ssjelinek 
662*3e1bd7a2Ssjelinek 				if (build_usage_string(dname,
663*3e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
664*3e1bd7a2Ssjelinek 					if (*errp) {
665*3e1bd7a2Ssjelinek 						goto out;
666*3e1bd7a2Ssjelinek 					}
667*3e1bd7a2Ssjelinek 				}
668*3e1bd7a2Ssjelinek 				break;
669*3e1bd7a2Ssjelinek 			case DM_WHO_DUMP:
670*3e1bd7a2Ssjelinek 				/*
671*3e1bd7a2Ssjelinek 				 * Not in use for this.
672*3e1bd7a2Ssjelinek 				 */
673*3e1bd7a2Ssjelinek 				if ((strcmp(by, DM_USE_MOUNT) == 0 &&
674*3e1bd7a2Ssjelinek 				    strcmp(data, "swap") == 0) ||
675*3e1bd7a2Ssjelinek 				    strcmp(by, DM_USE_DUMP) == 0 ||
676*3e1bd7a2Ssjelinek 				    strcmp(by, DM_USE_FS) == 0) {
677*3e1bd7a2Ssjelinek 					break;
678*3e1bd7a2Ssjelinek 				}
679*3e1bd7a2Ssjelinek 				if (build_usage_string(dname,
680*3e1bd7a2Ssjelinek 				    by, data, msg, &found, errp)) {
681*3e1bd7a2Ssjelinek 					if (*errp) {
682*3e1bd7a2Ssjelinek 						goto out;
683*3e1bd7a2Ssjelinek 					}
684*3e1bd7a2Ssjelinek 				}
685*3e1bd7a2Ssjelinek 				break;
686*3e1bd7a2Ssjelinek 
687*3e1bd7a2Ssjelinek 			case DM_WHO_FORMAT:
688*3e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_FS) == 0)
689*3e1bd7a2Ssjelinek 					break;
690*3e1bd7a2Ssjelinek 				if (build_usage_string(dname,
691*3e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
692*3e1bd7a2Ssjelinek 					if (*errp) {
693*3e1bd7a2Ssjelinek 						goto out;
694*3e1bd7a2Ssjelinek 					}
695*3e1bd7a2Ssjelinek 				}
696*3e1bd7a2Ssjelinek 				break;
697*3e1bd7a2Ssjelinek 			default:
698*3e1bd7a2Ssjelinek 				/*
699*3e1bd7a2Ssjelinek 				 * nothing found in use for this client
700*3e1bd7a2Ssjelinek 				 * of libdiskmgt. Default is 'not in use'.
701*3e1bd7a2Ssjelinek 				 */
702*3e1bd7a2Ssjelinek 				break;
703*3e1bd7a2Ssjelinek 		}
704*3e1bd7a2Ssjelinek 	}
705*3e1bd7a2Ssjelinek out:
706*3e1bd7a2Ssjelinek 	if (dname != NULL)
707*3e1bd7a2Ssjelinek 		free(dname);
708*3e1bd7a2Ssjelinek 	if (dev_stats != NULL)
709*3e1bd7a2Ssjelinek 		nvlist_free(dev_stats);
710*3e1bd7a2Ssjelinek 
711*3e1bd7a2Ssjelinek 	return (found);
712*3e1bd7a2Ssjelinek }
713*3e1bd7a2Ssjelinek 
714*3e1bd7a2Ssjelinek void
715*3e1bd7a2Ssjelinek dm_get_usage_string(char *what, char *how, char **usage_string)
716*3e1bd7a2Ssjelinek {
717*3e1bd7a2Ssjelinek 
718*3e1bd7a2Ssjelinek 
719*3e1bd7a2Ssjelinek 	if (usage_string == NULL || what == NULL) {
720*3e1bd7a2Ssjelinek 		return;
721*3e1bd7a2Ssjelinek 	}
722*3e1bd7a2Ssjelinek 	*usage_string = NULL;
723*3e1bd7a2Ssjelinek 
724*3e1bd7a2Ssjelinek 	if (strcmp(what, DM_USE_MOUNT) == 0) {
725*3e1bd7a2Ssjelinek 		if (strcmp(how, "swap") == 0) {
726*3e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
727*3e1bd7a2Ssjelinek 			    "%s is currently used by swap. Please see swap(1M)."
728*3e1bd7a2Ssjelinek 			    "\n");
729*3e1bd7a2Ssjelinek 		} else {
730*3e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
731*3e1bd7a2Ssjelinek 			    "%s is currently mounted on %s."
732*3e1bd7a2Ssjelinek 			    " Please see umount(1M).\n");
733*3e1bd7a2Ssjelinek 		}
734*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_VFSTAB) == 0) {
735*3e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
736*3e1bd7a2Ssjelinek 		    "%s is normally mounted on %s according to /etc/vfstab. "
737*3e1bd7a2Ssjelinek 		    "Please remove this entry to use this device.\n");
738*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_FS) == 0) {
739*3e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
740*3e1bd7a2Ssjelinek 		    "Warning: %s contains a %s filesystem.\n");
741*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_SVM) == 0) {
742*3e1bd7a2Ssjelinek 		if (strcmp(how, "mdb") == 0) {
743*3e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
744*3e1bd7a2Ssjelinek 			    "%s contains an SVM %s. Please see "
745*3e1bd7a2Ssjelinek 			    "metadb(1M).\n");
746*3e1bd7a2Ssjelinek 		} else {
747*3e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
748*3e1bd7a2Ssjelinek 			    "%s is part of SVM volume %s. "
749*3e1bd7a2Ssjelinek 			    "Please see metaclear(1M).\n");
750*3e1bd7a2Ssjelinek 		}
751*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_VXVM) == 0) {
752*3e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
753*3e1bd7a2Ssjelinek 		    "%s is part of VxVM volume %s.\n");
754*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_LU) == 0) {
755*3e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
756*3e1bd7a2Ssjelinek 		    "%s is in use for live upgrade %s. Please see ludelete(1M)."
757*3e1bd7a2Ssjelinek 		    "\n");
758*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_DUMP) == 0) {
759*3e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
760*3e1bd7a2Ssjelinek 		    "%s is in use by %s. Please see dumpadm(1M)."
761*3e1bd7a2Ssjelinek 		    "\n");
762*3e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_ZPOOL) == 0) {
763*3e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
764*3e1bd7a2Ssjelinek 		    "%s is in use by zpool %s. Please see zpool(1M)."
765*3e1bd7a2Ssjelinek 		    "\n");
766*3e1bd7a2Ssjelinek 	}
767*3e1bd7a2Ssjelinek }
7687c478bd9Sstevel@tonic-gate void
7697c478bd9Sstevel@tonic-gate libdiskmgt_add_str(nvlist_t *attrs, char *name, char *val, int *errp)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	if (*errp == 0) {
7727c478bd9Sstevel@tonic-gate 		*errp = nvlist_add_string(attrs, name, val);
7737c478bd9Sstevel@tonic-gate 	}
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate descriptor_t **
7777c478bd9Sstevel@tonic-gate libdiskmgt_empty_desc_array(int *errp)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate 	descriptor_t	**empty;
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	empty = (descriptor_t **)calloc(1, sizeof (descriptor_t *));
7827c478bd9Sstevel@tonic-gate 	if (empty == NULL) {
7837c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
7847c478bd9Sstevel@tonic-gate 	    return (NULL);
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 	empty[0] = NULL;
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	*errp = 0;
7897c478bd9Sstevel@tonic-gate 	return (empty);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate void
7937c478bd9Sstevel@tonic-gate libdiskmgt_init_debug()
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate 	char	*valp;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	if ((valp = getenv(DM_DEBUG)) != NULL) {
7987c478bd9Sstevel@tonic-gate 	    dm_debug = atoi(valp);
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate int
8037c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(char *nm1, char *nm2)
8047c478bd9Sstevel@tonic-gate {
8057c478bd9Sstevel@tonic-gate 	if (nm1 == NULL) {
8067c478bd9Sstevel@tonic-gate 	    if (dm_debug) {
8077c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "WARNING: str_eq nm1 NULL\n");
8087c478bd9Sstevel@tonic-gate 	    }
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	    if (nm2 == NULL) {
8117c478bd9Sstevel@tonic-gate 		return (1);
8127c478bd9Sstevel@tonic-gate 	    } else {
8137c478bd9Sstevel@tonic-gate 		return (0);
8147c478bd9Sstevel@tonic-gate 	    }
8157c478bd9Sstevel@tonic-gate 	}
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	/* nm1 != NULL */
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	if (nm2 == NULL) {
8207c478bd9Sstevel@tonic-gate 	    if (dm_debug) {
8217c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "WARNING: str_eq nm2 NULL\n");
8227c478bd9Sstevel@tonic-gate 	    }
8237c478bd9Sstevel@tonic-gate 	    return (0);
8247c478bd9Sstevel@tonic-gate 	}
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	if (strcmp(nm1, nm2) == 0) {
8277c478bd9Sstevel@tonic-gate 	    return (1);
8287c478bd9Sstevel@tonic-gate 	}
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	return (0);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8347c478bd9Sstevel@tonic-gate static descriptor_t **
8357c478bd9Sstevel@tonic-gate desc_array_to_ptr_array(dm_descriptor_t *descs, int *errp)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate #ifdef _LP64
8387c478bd9Sstevel@tonic-gate 	return ((descriptor_t **)descs);
8397c478bd9Sstevel@tonic-gate #else
8407c478bd9Sstevel@tonic-gate 	/* convert the 64 bit descriptors to 32 bit ptrs */
8417c478bd9Sstevel@tonic-gate 	int	cnt;
8427c478bd9Sstevel@tonic-gate 	int	i;
8437c478bd9Sstevel@tonic-gate 	descriptor_t **da;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	for (cnt = 0; descs[cnt]; cnt++);
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	da = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
8487c478bd9Sstevel@tonic-gate 	if (da == NULL) {
8497c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
8507c478bd9Sstevel@tonic-gate 	    return (NULL);
8517c478bd9Sstevel@tonic-gate 	}
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	for (i = 0; descs[i]; i++) {
85469fb9702Smike_s 	    da[i] = (descriptor_t *)(uintptr_t)descs[i];
8557c478bd9Sstevel@tonic-gate 	}
8567c478bd9Sstevel@tonic-gate 	*errp = 0;
8577c478bd9Sstevel@tonic-gate 	free(descs);
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	return (da);
8607c478bd9Sstevel@tonic-gate #endif
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8647c478bd9Sstevel@tonic-gate static dm_descriptor_t *
8657c478bd9Sstevel@tonic-gate ptr_array_to_desc_array(descriptor_t **ptrs, int *errp)
8667c478bd9Sstevel@tonic-gate {
8677c478bd9Sstevel@tonic-gate #ifdef _LP64
8687c478bd9Sstevel@tonic-gate 	return ((dm_descriptor_t *)ptrs);
8697c478bd9Sstevel@tonic-gate #else
8707c478bd9Sstevel@tonic-gate 	/* convert the 32 bit ptrs to the 64 bit descriptors */
8717c478bd9Sstevel@tonic-gate 	int	cnt;
8727c478bd9Sstevel@tonic-gate 	int	i;
8737c478bd9Sstevel@tonic-gate 	dm_descriptor_t *da;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	if (*errp != 0 || ptrs == NULL) {
8767c478bd9Sstevel@tonic-gate 	    return (NULL);
8777c478bd9Sstevel@tonic-gate 	}
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	for (cnt = 0; ptrs[cnt]; cnt++);
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	da = (dm_descriptor_t *)calloc(cnt + 1, sizeof (dm_descriptor_t));
8827c478bd9Sstevel@tonic-gate 	if (da == NULL) {
8837c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
8847c478bd9Sstevel@tonic-gate 	    return (NULL);
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	for (i = 0; ptrs[i]; i++) {
8887c478bd9Sstevel@tonic-gate 	    da[i] = (uintptr_t)ptrs[i];
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 	*errp = 0;
8917c478bd9Sstevel@tonic-gate 	free(ptrs);
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	return (da);
8947c478bd9Sstevel@tonic-gate #endif
8957c478bd9Sstevel@tonic-gate }
896*3e1bd7a2Ssjelinek /*
897*3e1bd7a2Ssjelinek  * Build the usage string for the in use data. Return the build string in
898*3e1bd7a2Ssjelinek  * the msg parameter. This function takes care of reallocing all the memory
899*3e1bd7a2Ssjelinek  * for this usage string. Usage string is returned already formatted for
900*3e1bd7a2Ssjelinek  * localization.
901*3e1bd7a2Ssjelinek  */
902*3e1bd7a2Ssjelinek static int
903*3e1bd7a2Ssjelinek build_usage_string(char *dname, char *by, char *data, char **msg,
904*3e1bd7a2Ssjelinek     int *found, int *errp)
905*3e1bd7a2Ssjelinek {
906*3e1bd7a2Ssjelinek 	int	len0;
907*3e1bd7a2Ssjelinek 	int	len1;
908*3e1bd7a2Ssjelinek 	char	*use;
909*3e1bd7a2Ssjelinek 	char	*p;
910*3e1bd7a2Ssjelinek 
911*3e1bd7a2Ssjelinek 	*errp = 0;
912*3e1bd7a2Ssjelinek 
913*3e1bd7a2Ssjelinek 	dm_get_usage_string(by, data, &use);
914*3e1bd7a2Ssjelinek 	if (!use) {
915*3e1bd7a2Ssjelinek 		return (-1);
916*3e1bd7a2Ssjelinek 	}
917*3e1bd7a2Ssjelinek 
918*3e1bd7a2Ssjelinek 	if (*msg)
919*3e1bd7a2Ssjelinek 		len0 = strlen(*msg);
920*3e1bd7a2Ssjelinek 	else
921*3e1bd7a2Ssjelinek 		len0 = 0;
922*3e1bd7a2Ssjelinek 	/* LINTED */
923*3e1bd7a2Ssjelinek 	len1 = snprintf(NULL, 0, use, dname, data);
924*3e1bd7a2Ssjelinek 
925*3e1bd7a2Ssjelinek 	/*
926*3e1bd7a2Ssjelinek 	 * If multiple in use details they
927*3e1bd7a2Ssjelinek 	 * are listed 1 per line for ease of
928*3e1bd7a2Ssjelinek 	 * reading. dm_find_usage_string
929*3e1bd7a2Ssjelinek 	 * formats these appropriately.
930*3e1bd7a2Ssjelinek 	 */
931*3e1bd7a2Ssjelinek 	if ((p = realloc(*msg, len0 + len1 + 1)) == NULL) {
932*3e1bd7a2Ssjelinek 		*errp = errno;
933*3e1bd7a2Ssjelinek 		free(*msg);
934*3e1bd7a2Ssjelinek 		return (-1);
935*3e1bd7a2Ssjelinek 	}
936*3e1bd7a2Ssjelinek 	*msg = p;
937*3e1bd7a2Ssjelinek 
938*3e1bd7a2Ssjelinek 	/* LINTED */
939*3e1bd7a2Ssjelinek 	(void) snprintf(*msg + len0, len1 + 1, use, dname, data);
940*3e1bd7a2Ssjelinek 	(*found)++;
941*3e1bd7a2Ssjelinek 	return (0);
942*3e1bd7a2Ssjelinek }
943