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