1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * 33 * MODULE: dat_sr.c 34 * 35 * PURPOSE: static registry implementation 36 * 37 * $Id: dat_sr.c,v 1.12 2003/08/20 14:28:40 hobie16 Exp $ 38 */ 39 40 41 #include "dat_sr.h" 42 43 #include "dat_dictionary.h" 44 #include "udat_sr_parser.h" 45 46 47 /* 48 * 49 * Global Variables 50 * 51 */ 52 53 static DAT_OS_LOCK g_sr_lock; 54 static DAT_DICTIONARY *g_sr_dictionary = NULL; 55 56 57 /* 58 * 59 * External Functions 60 * 61 */ 62 63 64 /* 65 * Function: dat_sr_init 66 */ 67 68 DAT_RETURN 69 dat_sr_init(void) 70 { 71 DAT_RETURN status; 72 73 status = dat_os_lock_init(&g_sr_lock); 74 if (DAT_SUCCESS != status) { 75 return (status); 76 } 77 78 status = dat_dictionary_create(&g_sr_dictionary); 79 if (DAT_SUCCESS != status) { 80 return (status); 81 } 82 83 /* 84 * Since DAT allows providers to be loaded by either the static 85 * registry or explicitly through OS dependent methods, do not 86 * return an error if no providers are loaded via the static registry. 87 */ 88 89 (void) dat_sr_load(); 90 91 return (DAT_SUCCESS); 92 } 93 94 95 /* 96 * Function: dat_sr_fini 97 */ 98 99 extern DAT_RETURN 100 dat_sr_fini(void) 101 { 102 DAT_RETURN status; 103 104 status = dat_os_lock_destroy(&g_sr_lock); 105 if (DAT_SUCCESS != status) { 106 return (status); 107 } 108 109 status = dat_dictionary_destroy(g_sr_dictionary); 110 if (DAT_SUCCESS != status) { 111 return (status); 112 } 113 114 return (DAT_SUCCESS); 115 } 116 117 118 /* 119 * Function: dat_sr_insert 120 */ 121 122 extern DAT_RETURN 123 dat_sr_insert( 124 IN const DAT_PROVIDER_INFO *info, 125 IN DAT_SR_ENTRY *entry) 126 { 127 DAT_RETURN status; 128 DAT_SR_ENTRY *data; 129 DAT_OS_SIZE lib_path_size; 130 DAT_OS_SIZE lib_path_len; 131 DAT_OS_SIZE ia_params_size; 132 DAT_OS_SIZE ia_params_len; 133 DAT_DICTIONARY_ENTRY dict_entry; 134 135 if (NULL == (data = dat_os_alloc(sizeof (DAT_SR_ENTRY)))) { 136 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 137 DAT_RESOURCE_MEMORY); 138 goto bail; 139 } 140 141 lib_path_len = strlen(entry->lib_path); 142 lib_path_size = (lib_path_len + 1) * sizeof (char); 143 144 if (NULL == (data->lib_path = dat_os_alloc(lib_path_size))) { 145 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 146 DAT_RESOURCE_MEMORY); 147 goto bail; 148 } 149 150 (void) dat_os_strncpy(data->lib_path, entry->lib_path, lib_path_len); 151 data->lib_path[lib_path_len] = '\0'; 152 153 ia_params_len = strlen(entry->ia_params); 154 ia_params_size = (ia_params_len + 1) * sizeof (char); 155 156 if (NULL == (data->ia_params = dat_os_alloc(ia_params_size))) { 157 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 158 DAT_RESOURCE_MEMORY); 159 goto bail; 160 } 161 162 (void) dat_os_strncpy(data->ia_params, entry->ia_params, ia_params_len); 163 data->ia_params[ia_params_len] = '\0'; 164 165 data->info = entry->info; 166 data->lib_handle = entry->lib_handle; 167 data->ref_count = entry->ref_count; 168 169 dict_entry = NULL; 170 status = dat_dictionary_entry_create(&dict_entry); 171 if (DAT_SUCCESS != status) { 172 goto bail; 173 } 174 175 dat_os_lock(&g_sr_lock); 176 177 status = dat_dictionary_insert(g_sr_dictionary, 178 dict_entry, 179 info, 180 (DAT_DICTIONARY_DATA *)data); 181 dat_os_unlock(&g_sr_lock); 182 183 bail: 184 if (DAT_SUCCESS != status) { 185 if (NULL != data) { 186 if (NULL != data->lib_path) { 187 dat_os_free(data->lib_path, lib_path_size); 188 } 189 190 if (NULL != data->ia_params) { 191 dat_os_free(data->ia_params, ia_params_size); 192 } 193 194 dat_os_free(data, sizeof (DAT_SR_ENTRY)); 195 } 196 197 if (NULL != dict_entry) { 198 (void) dat_dictionary_entry_destroy(dict_entry); 199 } 200 } 201 202 return (status); 203 } 204 205 206 /* 207 * Function: dat_sr_size 208 */ 209 210 extern DAT_RETURN 211 dat_sr_size( 212 OUT DAT_COUNT *size) 213 { 214 return (dat_dictionary_size(g_sr_dictionary, size)); 215 } 216 217 218 /* 219 * Function: dat_sr_list 220 */ 221 222 extern DAT_RETURN 223 dat_sr_list( 224 IN DAT_COUNT max_to_return, 225 OUT DAT_COUNT *entries_returned, 226 OUT DAT_PROVIDER_INFO * (dat_provider_list[])) 227 { 228 DAT_SR_ENTRY **array; 229 DAT_COUNT array_size; 230 DAT_COUNT i; 231 DAT_RETURN status; 232 233 array = NULL; 234 status = DAT_SUCCESS; 235 236 /* 237 * The dictionary size may increase between the call to 238 * dat_dictionary_size() and dat_dictionary_enumerate(). 239 * Therefore we loop until a successful enumeration is made. 240 */ 241 *entries_returned = 0; 242 for (;;) { 243 status = dat_dictionary_size(g_sr_dictionary, &array_size); 244 if (DAT_SUCCESS != status) { 245 goto bail; 246 } 247 248 if (array_size == 0) { 249 status = DAT_SUCCESS; 250 goto bail; 251 } 252 253 array = dat_os_alloc(array_size * sizeof (DAT_SR_ENTRY *)); 254 if (array == NULL) { 255 status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 256 DAT_RESOURCE_MEMORY); 257 goto bail; 258 } 259 260 dat_os_lock(&g_sr_lock); 261 262 status = dat_dictionary_enumerate(g_sr_dictionary, 263 (DAT_DICTIONARY_DATA *) array, 264 array_size); 265 266 dat_os_unlock(&g_sr_lock); 267 268 if (DAT_SUCCESS == status) { 269 break; 270 } else { 271 dat_os_free(array, 272 array_size * sizeof (DAT_SR_ENTRY *)); 273 array = NULL; 274 continue; 275 } 276 } 277 278 for (i = 0; (i < max_to_return) && (i < array_size); i++) { 279 if (NULL == dat_provider_list[i]) { 280 status = DAT_ERROR(DAT_INVALID_PARAMETER, 281 DAT_INVALID_ARG3); 282 goto bail; 283 } 284 285 *dat_provider_list[i] = array[i]->info; 286 } 287 288 *entries_returned = i; 289 290 bail: 291 if (NULL != array) { 292 dat_os_free(array, array_size * sizeof (DAT_SR_ENTRY *)); 293 } 294 295 return (status); 296 } 297 298 299 300 /* 301 * Function: dat_sr_provider_open 302 */ 303 304 extern DAT_RETURN 305 dat_sr_provider_open( 306 IN const DAT_PROVIDER_INFO *info) 307 { 308 DAT_RETURN status; 309 DAT_SR_ENTRY *data; 310 311 dat_os_lock(&g_sr_lock); 312 313 status = dat_dictionary_search(g_sr_dictionary, 314 info, 315 (DAT_DICTIONARY_DATA *) &data); 316 317 if (DAT_SUCCESS == status) { 318 if (0 == data->ref_count) { 319 status = dat_os_library_load(data->lib_path, 320 &data->lib_handle); 321 if (status == DAT_SUCCESS) { 322 data->ref_count++; 323 } else { 324 dat_os_dbg_print(DAT_OS_DBG_TYPE_SR, 325 "DAT Registry: static registry unable to " 326 "load library %s\n", data->lib_path); 327 goto bail; 328 } 329 data->init_func = (DAT_PROVIDER_INIT_FUNC) 330 dat_os_library_sym(data->lib_handle, 331 DAT_PROVIDER_INIT_FUNC_STR); 332 data->fini_func = (DAT_PROVIDER_FINI_FUNC) 333 dat_os_library_sym(data->lib_handle, 334 DAT_PROVIDER_FINI_FUNC_STR); 335 336 if (NULL != data->init_func) { 337 (*data->init_func)(&data->info, 338 data->ia_params); 339 } 340 } else { 341 data->ref_count++; 342 } 343 } 344 345 bail: 346 dat_os_unlock(&g_sr_lock); 347 348 return (status); 349 } 350 351 352 /* 353 * Function: dat_sr_provider_close 354 */ 355 356 extern DAT_RETURN 357 dat_sr_provider_close( 358 IN const DAT_PROVIDER_INFO *info) 359 { 360 DAT_RETURN status; 361 DAT_SR_ENTRY *data; 362 363 dat_os_lock(&g_sr_lock); 364 365 status = dat_dictionary_search(g_sr_dictionary, 366 info, 367 (DAT_DICTIONARY_DATA *)&data); 368 369 if (DAT_SUCCESS == status) { 370 if (1 == data->ref_count) { 371 if (NULL != data->fini_func) { 372 (*data->fini_func)(&data->info); 373 } 374 375 status = dat_os_library_unload(data->lib_handle); 376 if (status == DAT_SUCCESS) { 377 data->ref_count--; 378 } 379 } else { 380 data->ref_count--; 381 } 382 } 383 384 dat_os_unlock(&g_sr_lock); 385 386 return (status); 387 } 388