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
dat_sr_init(void)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
dat_sr_fini(void)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
dat_sr_insert(IN const DAT_PROVIDER_INFO * info,IN DAT_SR_ENTRY * entry)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
dat_sr_size(OUT DAT_COUNT * size)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
dat_sr_list(IN DAT_COUNT max_to_return,OUT DAT_COUNT * entries_returned,OUT DAT_PROVIDER_INFO * (dat_provider_list[]))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
dat_sr_provider_open(IN const DAT_PROVIDER_INFO * info)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
dat_sr_provider_close(IN const DAT_PROVIDER_INFO * info)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