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