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 5*99653d4eSeschrock * Common Development and Distribution License (the "License"). 6*99653d4eSeschrock * 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 /* 2246a2abf2Seschrock * Copyright 2006 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)) { 4133e1bd7a2Ssjelinek cache_unlock(); 4143e1bd7a2Ssjelinek *errp = EBADF; 4153e1bd7a2Ssjelinek 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) { 4203e1bd7a2Ssjelinek cache_unlock(); 4213e1bd7a2Ssjelinek *errp = ENODEV; 4223e1bd7a2Ssjelinek return (NULL); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate switch (dp->type) { 4267c478bd9Sstevel@tonic-gate case DM_DRIVE: 4273e1bd7a2Ssjelinek stats = drive_get_stats(dp, stat_type, errp); 4283e1bd7a2Ssjelinek break; 4297c478bd9Sstevel@tonic-gate case DM_BUS: 4303e1bd7a2Ssjelinek stats = bus_get_stats(dp, stat_type, errp); 4313e1bd7a2Ssjelinek break; 4327c478bd9Sstevel@tonic-gate case DM_CONTROLLER: 4333e1bd7a2Ssjelinek stats = controller_get_stats(dp, stat_type, errp); 4343e1bd7a2Ssjelinek break; 4357c478bd9Sstevel@tonic-gate case DM_MEDIA: 4363e1bd7a2Ssjelinek stats = media_get_stats(dp, stat_type, errp); 4373e1bd7a2Ssjelinek 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 } 4503e1bd7a2Ssjelinek stats = slice_get_stats(dp, stat_type, errp); 4513e1bd7a2Ssjelinek break; 4527c478bd9Sstevel@tonic-gate case DM_PARTITION: 4533e1bd7a2Ssjelinek stats = partition_get_stats(dp, stat_type, errp); 4543e1bd7a2Ssjelinek break; 4557c478bd9Sstevel@tonic-gate case DM_PATH: 4563e1bd7a2Ssjelinek stats = path_get_stats(dp, stat_type, errp); 4573e1bd7a2Ssjelinek break; 4587c478bd9Sstevel@tonic-gate case DM_ALIAS: 4593e1bd7a2Ssjelinek stats = alias_get_stats(dp, stat_type, errp); 4603e1bd7a2Ssjelinek break; 4617c478bd9Sstevel@tonic-gate default: 4623e1bd7a2Ssjelinek *errp = EINVAL; 4633e1bd7a2Ssjelinek 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 55646a2abf2Seschrock /* 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 7293e1bd7a2Ssjelinek /* 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 74682d71480Ssjelinek 7473e1bd7a2Ssjelinek *errp = 0; 7483e1bd7a2Ssjelinek *msg = NULL; 7493e1bd7a2Ssjelinek 75082d71480Ssjelinek /* 75182d71480Ssjelinek * If the user doesn't want to do in use checking, return. 75282d71480Ssjelinek */ 75382d71480Ssjelinek 75482d71480Ssjelinek if (NOINUSE_SET) 75582d71480Ssjelinek return (0); 75682d71480Ssjelinek 7573e1bd7a2Ssjelinek dname = getfullblkname(dev_name); 7583e1bd7a2Ssjelinek /* 7593e1bd7a2Ssjelinek * If we cannot find the block name, we cannot check the device 7603e1bd7a2Ssjelinek * for in use statistics. So, return found, which is == 0. 7613e1bd7a2Ssjelinek */ 7623e1bd7a2Ssjelinek if (dname == NULL || *dname == '\0') { 7633e1bd7a2Ssjelinek return (found); 7643e1bd7a2Ssjelinek } 7653e1bd7a2Ssjelinek 7663e1bd7a2Ssjelinek dm_get_slice_stats(dname, &dev_stats, errp); 7673e1bd7a2Ssjelinek if (dev_stats == NULL) { 7683e1bd7a2Ssjelinek /* 7693e1bd7a2Ssjelinek * If there is an error, but it isn't a no device found error 7703e1bd7a2Ssjelinek * return the error as recorded. Otherwise, with a full 7713e1bd7a2Ssjelinek * block name, we might not be able to get the slice 7723e1bd7a2Ssjelinek * associated, and will get an ENODEV error. For example, 7733e1bd7a2Ssjelinek * an SVM metadevice will return a value from getfullblkname() 7743e1bd7a2Ssjelinek * but libdiskmgt won't be able to find this device for 7753e1bd7a2Ssjelinek * statistics gathering. This is expected and we should not 7763e1bd7a2Ssjelinek * report errnoneous errors. 7773e1bd7a2Ssjelinek */ 7783e1bd7a2Ssjelinek if (*errp) { 7793e1bd7a2Ssjelinek if (*errp == ENODEV) { 7803e1bd7a2Ssjelinek *errp = 0; 7813e1bd7a2Ssjelinek } 7823e1bd7a2Ssjelinek } 7833e1bd7a2Ssjelinek free(dname); 7843e1bd7a2Ssjelinek return (found); 7853e1bd7a2Ssjelinek } 7863e1bd7a2Ssjelinek 7873e1bd7a2Ssjelinek for (;;) { 7883e1bd7a2Ssjelinek 7893e1bd7a2Ssjelinek nvwhat = nvlist_next_nvpair(dev_stats, nvdesc); 7903e1bd7a2Ssjelinek nvdesc = nvlist_next_nvpair(dev_stats, nvwhat); 7913e1bd7a2Ssjelinek 7923e1bd7a2Ssjelinek /* 7933e1bd7a2Ssjelinek * End of the list found. 7943e1bd7a2Ssjelinek */ 7953e1bd7a2Ssjelinek if (nvwhat == NULL || nvdesc == NULL) { 7963e1bd7a2Ssjelinek break; 7973e1bd7a2Ssjelinek } 7983e1bd7a2Ssjelinek /* 7993e1bd7a2Ssjelinek * Otherwise, we check to see if this client(who) cares 8003e1bd7a2Ssjelinek * about this in use scenario 8013e1bd7a2Ssjelinek */ 8023e1bd7a2Ssjelinek 8033e1bd7a2Ssjelinek ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0); 8043e1bd7a2Ssjelinek ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0); 8053e1bd7a2Ssjelinek /* 8063e1bd7a2Ssjelinek * If we error getting the string value continue on 8073e1bd7a2Ssjelinek * to the next pair(if there is one) 8083e1bd7a2Ssjelinek */ 8093e1bd7a2Ssjelinek if (nvpair_value_string(nvwhat, &by)) { 8103e1bd7a2Ssjelinek continue; 8113e1bd7a2Ssjelinek } 8123e1bd7a2Ssjelinek if (nvpair_value_string(nvdesc, &data)) { 8133e1bd7a2Ssjelinek continue; 8143e1bd7a2Ssjelinek } 8153e1bd7a2Ssjelinek 8163e1bd7a2Ssjelinek switch (who) { 8173e1bd7a2Ssjelinek case DM_WHO_MKFS: 8183e1bd7a2Ssjelinek /* 8193e1bd7a2Ssjelinek * mkfs is not in use for these cases. 8203e1bd7a2Ssjelinek * All others are in use. 8213e1bd7a2Ssjelinek */ 8223e1bd7a2Ssjelinek if (strcmp(by, DM_USE_LU) == 0 || 82346a2abf2Seschrock strcmp(by, DM_USE_FS) == 0 || 82446a2abf2Seschrock strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { 8253e1bd7a2Ssjelinek break; 8263e1bd7a2Ssjelinek } 8273e1bd7a2Ssjelinek if (build_usage_string(dname, 8283e1bd7a2Ssjelinek by, data, msg, &found, errp) != 0) { 8293e1bd7a2Ssjelinek if (*errp) { 8303e1bd7a2Ssjelinek goto out; 8313e1bd7a2Ssjelinek } 8323e1bd7a2Ssjelinek } 8333e1bd7a2Ssjelinek break; 8343e1bd7a2Ssjelinek case DM_WHO_SWAP: 8353e1bd7a2Ssjelinek /* 8363e1bd7a2Ssjelinek * Not in use for this. 8373e1bd7a2Ssjelinek */ 8383e1bd7a2Ssjelinek if (strcmp(by, DM_USE_DUMP) == 0 || 83946a2abf2Seschrock strcmp(by, DM_USE_FS) == 0 || 84046a2abf2Seschrock strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { 8413e1bd7a2Ssjelinek break; 8423e1bd7a2Ssjelinek } 8433e1bd7a2Ssjelinek 8443e1bd7a2Ssjelinek if (build_usage_string(dname, 8453e1bd7a2Ssjelinek by, data, msg, &found, errp) != 0) { 8463e1bd7a2Ssjelinek if (*errp) { 8473e1bd7a2Ssjelinek goto out; 8483e1bd7a2Ssjelinek } 8493e1bd7a2Ssjelinek } 8503e1bd7a2Ssjelinek break; 8513e1bd7a2Ssjelinek case DM_WHO_DUMP: 8523e1bd7a2Ssjelinek /* 8533e1bd7a2Ssjelinek * Not in use for this. 8543e1bd7a2Ssjelinek */ 8553e1bd7a2Ssjelinek if ((strcmp(by, DM_USE_MOUNT) == 0 && 8563e1bd7a2Ssjelinek strcmp(data, "swap") == 0) || 8573e1bd7a2Ssjelinek strcmp(by, DM_USE_DUMP) == 0 || 85846a2abf2Seschrock strcmp(by, DM_USE_FS) == 0 || 85946a2abf2Seschrock strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { 8603e1bd7a2Ssjelinek break; 8613e1bd7a2Ssjelinek } 8623e1bd7a2Ssjelinek if (build_usage_string(dname, 8633e1bd7a2Ssjelinek by, data, msg, &found, errp)) { 8643e1bd7a2Ssjelinek if (*errp) { 8653e1bd7a2Ssjelinek goto out; 8663e1bd7a2Ssjelinek } 8673e1bd7a2Ssjelinek } 8683e1bd7a2Ssjelinek break; 8693e1bd7a2Ssjelinek 8703e1bd7a2Ssjelinek case DM_WHO_FORMAT: 87146a2abf2Seschrock if (strcmp(by, DM_USE_FS) == 0 || 87246a2abf2Seschrock strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) 8733e1bd7a2Ssjelinek break; 8743e1bd7a2Ssjelinek if (build_usage_string(dname, 8753e1bd7a2Ssjelinek by, data, msg, &found, errp) != 0) { 8763e1bd7a2Ssjelinek if (*errp) { 8773e1bd7a2Ssjelinek goto out; 8783e1bd7a2Ssjelinek } 8793e1bd7a2Ssjelinek } 8803e1bd7a2Ssjelinek break; 88146a2abf2Seschrock 88246a2abf2Seschrock case DM_WHO_ZPOOL_FORCE: 88346a2abf2Seschrock if (strcmp(by, DM_USE_FS) == 0 || 88446a2abf2Seschrock strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) 88546a2abf2Seschrock break; 88646a2abf2Seschrock /* FALLTHROUGH */ 88746a2abf2Seschrock case DM_WHO_ZPOOL: 88846a2abf2Seschrock if (build_usage_string(dname, 88946a2abf2Seschrock by, data, msg, &found, errp) != 0) { 89046a2abf2Seschrock if (*errp) 89146a2abf2Seschrock goto out; 89246a2abf2Seschrock } 89346a2abf2Seschrock break; 89446a2abf2Seschrock 8953e1bd7a2Ssjelinek default: 8963e1bd7a2Ssjelinek /* 8973e1bd7a2Ssjelinek * nothing found in use for this client 8983e1bd7a2Ssjelinek * of libdiskmgt. Default is 'not in use'. 8993e1bd7a2Ssjelinek */ 9003e1bd7a2Ssjelinek break; 9013e1bd7a2Ssjelinek } 9023e1bd7a2Ssjelinek } 9033e1bd7a2Ssjelinek out: 9043e1bd7a2Ssjelinek if (dname != NULL) 9053e1bd7a2Ssjelinek free(dname); 9063e1bd7a2Ssjelinek if (dev_stats != NULL) 9073e1bd7a2Ssjelinek nvlist_free(dev_stats); 9083e1bd7a2Ssjelinek 9093e1bd7a2Ssjelinek return (found); 9103e1bd7a2Ssjelinek } 9113e1bd7a2Ssjelinek 9123e1bd7a2Ssjelinek void 9133e1bd7a2Ssjelinek dm_get_usage_string(char *what, char *how, char **usage_string) 9143e1bd7a2Ssjelinek { 9153e1bd7a2Ssjelinek 9163e1bd7a2Ssjelinek 9173e1bd7a2Ssjelinek if (usage_string == NULL || what == NULL) { 9183e1bd7a2Ssjelinek return; 9193e1bd7a2Ssjelinek } 9203e1bd7a2Ssjelinek *usage_string = NULL; 9213e1bd7a2Ssjelinek 9223e1bd7a2Ssjelinek if (strcmp(what, DM_USE_MOUNT) == 0) { 9233e1bd7a2Ssjelinek if (strcmp(how, "swap") == 0) { 9243e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9253e1bd7a2Ssjelinek "%s is currently used by swap. Please see swap(1M)." 9263e1bd7a2Ssjelinek "\n"); 9273e1bd7a2Ssjelinek } else { 9283e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9293e1bd7a2Ssjelinek "%s is currently mounted on %s." 9303e1bd7a2Ssjelinek " Please see umount(1M).\n"); 9313e1bd7a2Ssjelinek } 9323e1bd7a2Ssjelinek } else if (strcmp(what, DM_USE_VFSTAB) == 0) { 9333e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9343e1bd7a2Ssjelinek "%s is normally mounted on %s according to /etc/vfstab. " 9353e1bd7a2Ssjelinek "Please remove this entry to use this device.\n"); 9363e1bd7a2Ssjelinek } else if (strcmp(what, DM_USE_FS) == 0) { 9373e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 93846a2abf2Seschrock "%s contains a %s filesystem.\n"); 9393e1bd7a2Ssjelinek } else if (strcmp(what, DM_USE_SVM) == 0) { 9403e1bd7a2Ssjelinek if (strcmp(how, "mdb") == 0) { 9413e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9423e1bd7a2Ssjelinek "%s contains an SVM %s. Please see " 9433e1bd7a2Ssjelinek "metadb(1M).\n"); 9443e1bd7a2Ssjelinek } else { 9453e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9463e1bd7a2Ssjelinek "%s is part of SVM volume %s. " 9473e1bd7a2Ssjelinek "Please see metaclear(1M).\n"); 9483e1bd7a2Ssjelinek } 9493e1bd7a2Ssjelinek } else if (strcmp(what, DM_USE_VXVM) == 0) { 9503e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9513e1bd7a2Ssjelinek "%s is part of VxVM volume %s.\n"); 9523e1bd7a2Ssjelinek } else if (strcmp(what, DM_USE_LU) == 0) { 9533e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9543e1bd7a2Ssjelinek "%s is in use for live upgrade %s. Please see ludelete(1M)." 9553e1bd7a2Ssjelinek "\n"); 9563e1bd7a2Ssjelinek } else if (strcmp(what, DM_USE_DUMP) == 0) { 9573e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 9583e1bd7a2Ssjelinek "%s is in use by %s. Please see dumpadm(1M)." 9593e1bd7a2Ssjelinek "\n"); 96046a2abf2Seschrock } else if (strcmp(what, DM_USE_EXPORTED_ZPOOL) == 0) { 96146a2abf2Seschrock *usage_string = dgettext(TEXT_DOMAIN, 96246a2abf2Seschrock "%s is part of exported or potentially active ZFS pool %s. " 96346a2abf2Seschrock "Please see zpool(1M).\n"); 96446a2abf2Seschrock } else if (strcmp(what, DM_USE_ACTIVE_ZPOOL) == 0) { 9653e1bd7a2Ssjelinek *usage_string = dgettext(TEXT_DOMAIN, 96646a2abf2Seschrock "%s is part of active ZFS pool %s. Please see zpool(1M)." 9673e1bd7a2Ssjelinek "\n"); 968*99653d4eSeschrock } else if (strcmp(what, DM_USE_SPARE_ZPOOL) == 0) { 969*99653d4eSeschrock *usage_string = dgettext(TEXT_DOMAIN, 970*99653d4eSeschrock "%s is reserved as a hot spare for ZFS pool %s. Please " 971*99653d4eSeschrock "see zpool(1M).\n"); 9723e1bd7a2Ssjelinek } 9733e1bd7a2Ssjelinek } 9747c478bd9Sstevel@tonic-gate void 9757c478bd9Sstevel@tonic-gate libdiskmgt_add_str(nvlist_t *attrs, char *name, char *val, int *errp) 9767c478bd9Sstevel@tonic-gate { 9777c478bd9Sstevel@tonic-gate if (*errp == 0) { 9787c478bd9Sstevel@tonic-gate *errp = nvlist_add_string(attrs, name, val); 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate descriptor_t ** 9837c478bd9Sstevel@tonic-gate libdiskmgt_empty_desc_array(int *errp) 9847c478bd9Sstevel@tonic-gate { 9857c478bd9Sstevel@tonic-gate descriptor_t **empty; 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate empty = (descriptor_t **)calloc(1, sizeof (descriptor_t *)); 9887c478bd9Sstevel@tonic-gate if (empty == NULL) { 9897c478bd9Sstevel@tonic-gate *errp = ENOMEM; 9907c478bd9Sstevel@tonic-gate return (NULL); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate empty[0] = NULL; 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate *errp = 0; 9957c478bd9Sstevel@tonic-gate return (empty); 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate void 9997c478bd9Sstevel@tonic-gate libdiskmgt_init_debug() 10007c478bd9Sstevel@tonic-gate { 10017c478bd9Sstevel@tonic-gate char *valp; 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if ((valp = getenv(DM_DEBUG)) != NULL) { 10047c478bd9Sstevel@tonic-gate dm_debug = atoi(valp); 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate int 10097c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(char *nm1, char *nm2) 10107c478bd9Sstevel@tonic-gate { 10117c478bd9Sstevel@tonic-gate if (nm1 == NULL) { 10127c478bd9Sstevel@tonic-gate if (dm_debug) { 10137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "WARNING: str_eq nm1 NULL\n"); 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate if (nm2 == NULL) { 10177c478bd9Sstevel@tonic-gate return (1); 10187c478bd9Sstevel@tonic-gate } else { 10197c478bd9Sstevel@tonic-gate return (0); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate /* nm1 != NULL */ 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate if (nm2 == NULL) { 10267c478bd9Sstevel@tonic-gate if (dm_debug) { 10277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "WARNING: str_eq nm2 NULL\n"); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate return (0); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate if (strcmp(nm1, nm2) == 0) { 10337c478bd9Sstevel@tonic-gate return (1); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate return (0); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 10407c478bd9Sstevel@tonic-gate static descriptor_t ** 10417c478bd9Sstevel@tonic-gate desc_array_to_ptr_array(dm_descriptor_t *descs, int *errp) 10427c478bd9Sstevel@tonic-gate { 10437c478bd9Sstevel@tonic-gate #ifdef _LP64 10447c478bd9Sstevel@tonic-gate return ((descriptor_t **)descs); 10457c478bd9Sstevel@tonic-gate #else 10467c478bd9Sstevel@tonic-gate /* convert the 64 bit descriptors to 32 bit ptrs */ 10477c478bd9Sstevel@tonic-gate int cnt; 10487c478bd9Sstevel@tonic-gate int i; 10497c478bd9Sstevel@tonic-gate descriptor_t **da; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate for (cnt = 0; descs[cnt]; cnt++); 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate da = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *)); 10547c478bd9Sstevel@tonic-gate if (da == NULL) { 10557c478bd9Sstevel@tonic-gate *errp = ENOMEM; 10567c478bd9Sstevel@tonic-gate return (NULL); 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate for (i = 0; descs[i]; i++) { 106069fb9702Smike_s da[i] = (descriptor_t *)(uintptr_t)descs[i]; 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate *errp = 0; 10637c478bd9Sstevel@tonic-gate free(descs); 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate return (da); 10667c478bd9Sstevel@tonic-gate #endif 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 10707c478bd9Sstevel@tonic-gate static dm_descriptor_t * 10717c478bd9Sstevel@tonic-gate ptr_array_to_desc_array(descriptor_t **ptrs, int *errp) 10727c478bd9Sstevel@tonic-gate { 10737c478bd9Sstevel@tonic-gate #ifdef _LP64 10747c478bd9Sstevel@tonic-gate return ((dm_descriptor_t *)ptrs); 10757c478bd9Sstevel@tonic-gate #else 10767c478bd9Sstevel@tonic-gate /* convert the 32 bit ptrs to the 64 bit descriptors */ 10777c478bd9Sstevel@tonic-gate int cnt; 10787c478bd9Sstevel@tonic-gate int i; 10797c478bd9Sstevel@tonic-gate dm_descriptor_t *da; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate if (*errp != 0 || ptrs == NULL) { 10827c478bd9Sstevel@tonic-gate return (NULL); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate for (cnt = 0; ptrs[cnt]; cnt++); 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate da = (dm_descriptor_t *)calloc(cnt + 1, sizeof (dm_descriptor_t)); 10887c478bd9Sstevel@tonic-gate if (da == NULL) { 10897c478bd9Sstevel@tonic-gate *errp = ENOMEM; 10907c478bd9Sstevel@tonic-gate return (NULL); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate for (i = 0; ptrs[i]; i++) { 10947c478bd9Sstevel@tonic-gate da[i] = (uintptr_t)ptrs[i]; 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate *errp = 0; 10977c478bd9Sstevel@tonic-gate free(ptrs); 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate return (da); 11007c478bd9Sstevel@tonic-gate #endif 11017c478bd9Sstevel@tonic-gate } 11023e1bd7a2Ssjelinek /* 11033e1bd7a2Ssjelinek * Build the usage string for the in use data. Return the build string in 11043e1bd7a2Ssjelinek * the msg parameter. This function takes care of reallocing all the memory 11053e1bd7a2Ssjelinek * for this usage string. Usage string is returned already formatted for 11063e1bd7a2Ssjelinek * localization. 11073e1bd7a2Ssjelinek */ 11083e1bd7a2Ssjelinek static int 11093e1bd7a2Ssjelinek build_usage_string(char *dname, char *by, char *data, char **msg, 11103e1bd7a2Ssjelinek int *found, int *errp) 11113e1bd7a2Ssjelinek { 11123e1bd7a2Ssjelinek int len0; 11133e1bd7a2Ssjelinek int len1; 11143e1bd7a2Ssjelinek char *use; 11153e1bd7a2Ssjelinek char *p; 11163e1bd7a2Ssjelinek 11173e1bd7a2Ssjelinek *errp = 0; 11183e1bd7a2Ssjelinek 11193e1bd7a2Ssjelinek dm_get_usage_string(by, data, &use); 11203e1bd7a2Ssjelinek if (!use) { 11213e1bd7a2Ssjelinek return (-1); 11223e1bd7a2Ssjelinek } 11233e1bd7a2Ssjelinek 11243e1bd7a2Ssjelinek if (*msg) 11253e1bd7a2Ssjelinek len0 = strlen(*msg); 11263e1bd7a2Ssjelinek else 11273e1bd7a2Ssjelinek len0 = 0; 11283e1bd7a2Ssjelinek /* LINTED */ 11293e1bd7a2Ssjelinek len1 = snprintf(NULL, 0, use, dname, data); 11303e1bd7a2Ssjelinek 11313e1bd7a2Ssjelinek /* 11323e1bd7a2Ssjelinek * If multiple in use details they 11333e1bd7a2Ssjelinek * are listed 1 per line for ease of 11343e1bd7a2Ssjelinek * reading. dm_find_usage_string 11353e1bd7a2Ssjelinek * formats these appropriately. 11363e1bd7a2Ssjelinek */ 11373e1bd7a2Ssjelinek if ((p = realloc(*msg, len0 + len1 + 1)) == NULL) { 11383e1bd7a2Ssjelinek *errp = errno; 11393e1bd7a2Ssjelinek free(*msg); 11403e1bd7a2Ssjelinek return (-1); 11413e1bd7a2Ssjelinek } 11423e1bd7a2Ssjelinek *msg = p; 11433e1bd7a2Ssjelinek 11443e1bd7a2Ssjelinek /* LINTED */ 11453e1bd7a2Ssjelinek (void) snprintf(*msg + len0, len1 + 1, use, dname, data); 11463e1bd7a2Ssjelinek (*found)++; 11473e1bd7a2Ssjelinek return (0); 11483e1bd7a2Ssjelinek } 1149