libc/libpthread: Add clock_getcpuclockid() and pthread_getcpuclockid().
[dragonfly.git] / lib / libc / net / nscache.c
blobc9d66144fa083d51249264695c02ae5047d91604
1 /*-
2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 * $FreeBSD: src/lib/libc/net/nscache.c,v 1.2 2007/10/17 23:20:49 tmclaugh Exp $
29 #include "namespace.h"
30 #include <nsswitch.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include "un-namespace.h"
34 #include "nscachedcli.h"
35 #include "nscache.h"
37 #define NSS_CACHE_KEY_INITIAL_SIZE (256)
38 #define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4)
40 #define NSS_CACHE_BUFFER_INITIAL_SIZE (1024)
41 #define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
43 #define CACHED_SOCKET_PATH "/var/run/nscd"
45 int
46 __nss_cache_handler(void *retval __unused, void *mdata __unused,
47 va_list ap __unused)
49 return (NS_UNAVAIL);
52 int
53 __nss_common_cache_read(void *retval, void *mdata, va_list ap)
55 struct cached_connection_params params;
56 cached_connection connection;
58 char *buffer;
59 size_t buffer_size, size;
61 nss_cache_info const *cache_info;
62 nss_cache_data *cache_data;
63 va_list ap_new;
64 int res;
66 cache_data = (nss_cache_data *)mdata;
67 cache_info = cache_data->info;
69 memset(&params, 0, sizeof(struct cached_connection_params));
70 params.socket_path = CACHED_SOCKET_PATH;
72 cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
73 memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
74 cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
75 va_copy(ap_new, ap);
77 do {
78 size = cache_data->key_size;
79 res = cache_info->id_func(cache_data->key, &size, ap_new,
80 cache_info->mdata);
81 va_end(ap_new);
82 if (res == NS_RETURN) {
83 if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
84 break;
86 cache_data->key_size <<= 1;
87 cache_data->key = realloc(cache_data->key,
88 cache_data->key_size);
89 memset(cache_data->key, 0, cache_data->key_size);
90 va_copy(ap_new, ap);
92 } while (res == NS_RETURN);
94 if (res != NS_SUCCESS) {
95 free(cache_data->key);
96 cache_data->key = NULL;
97 cache_data->key_size = 0;
98 return (res);
99 } else
100 cache_data->key_size = size;
102 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
103 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
104 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
106 do {
107 connection = __open_cached_connection(&params);
108 if (connection == NULL) {
109 res = -1;
110 break;
112 res = __cached_read(connection, cache_info->entry_name,
113 cache_data->key, cache_data->key_size, buffer,
114 &buffer_size);
115 __close_cached_connection(connection);
116 if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
117 buffer = (char *)realloc(buffer, buffer_size);
118 memset(buffer, 0, buffer_size);
120 } while (res == -2);
122 if (res == 0) {
123 if (buffer_size == 0) {
124 free(buffer);
125 free(cache_data->key);
126 cache_data->key = NULL;
127 cache_data->key_size = 0;
128 return (NS_RETURN);
131 va_copy(ap_new, ap);
132 res = cache_info->unmarshal_func(buffer, buffer_size, retval,
133 ap_new, cache_info->mdata);
134 va_end(ap_new);
136 if (res != NS_SUCCESS) {
137 free(buffer);
138 free(cache_data->key);
139 cache_data->key = NULL;
140 cache_data->key_size = 0;
141 return (res);
142 } else
143 res = 0;
146 if (res == 0) {
147 free(cache_data->key);
148 cache_data->key = NULL;
149 cache_data->key_size = 0;
152 free(buffer);
153 return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
157 __nss_common_cache_write(void *retval, void *mdata, va_list ap)
159 struct cached_connection_params params;
160 cached_connection connection;
162 char *buffer;
163 size_t buffer_size;
165 nss_cache_info const *cache_info;
166 nss_cache_data *cache_data;
167 va_list ap_new;
168 int res;
170 cache_data = (nss_cache_data *)mdata;
171 cache_info = cache_data->info;
173 if (cache_data->key == NULL)
174 return (NS_UNAVAIL);
176 memset(&params, 0, sizeof(struct cached_connection_params));
177 params.socket_path = CACHED_SOCKET_PATH;
179 connection = __open_cached_connection(&params);
180 if (connection == NULL) {
181 free(cache_data->key);
182 return (NS_UNAVAIL);
185 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
186 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
187 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
189 do {
190 size_t size;
192 size = buffer_size;
193 va_copy(ap_new, ap);
194 res = cache_info->marshal_func(buffer, &size, retval, ap_new,
195 cache_info->mdata);
196 va_end(ap_new);
198 if (res == NS_RETURN) {
199 if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
200 break;
202 buffer_size <<= 1;
203 buffer = (char *)realloc(buffer, buffer_size);
204 memset(buffer, 0, buffer_size);
206 } while (res == NS_RETURN);
208 if (res != NS_SUCCESS) {
209 __close_cached_connection(connection);
210 free(cache_data->key);
211 free(buffer);
212 return (res);
215 res = __cached_write(connection, cache_info->entry_name,
216 cache_data->key, cache_data->key_size, buffer, buffer_size);
217 __close_cached_connection(connection);
219 free(cache_data->key);
220 free(buffer);
222 return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
226 __nss_common_cache_write_negative(void *mdata)
228 struct cached_connection_params params;
229 cached_connection connection;
230 int res;
232 nss_cache_info const *cache_info;
233 nss_cache_data *cache_data;
235 cache_data = (nss_cache_data *)mdata;
236 cache_info = cache_data->info;
238 if (cache_data->key == NULL)
239 return (NS_UNAVAIL);
241 memset(&params, 0, sizeof(struct cached_connection_params));
242 params.socket_path = CACHED_SOCKET_PATH;
244 connection = __open_cached_connection(&params);
245 if (connection == NULL) {
246 free(cache_data->key);
247 return (NS_UNAVAIL);
250 res = __cached_write(connection, cache_info->entry_name,
251 cache_data->key, cache_data->key_size, NULL, 0);
252 __close_cached_connection(connection);
254 free(cache_data->key);
255 return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
259 __nss_mp_cache_read(void *retval, void *mdata, va_list ap)
261 struct cached_connection_params params;
262 cached_mp_read_session rs;
264 char *buffer;
265 size_t buffer_size;
267 nss_cache_info const *cache_info;
268 nss_cache_data *cache_data;
269 va_list ap_new;
270 int res;
272 cache_data = (nss_cache_data *)mdata;
273 cache_info = cache_data->info;
275 if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
276 return (NS_UNAVAIL);
278 rs = cache_info->get_mp_rs_func();
279 if (rs == INVALID_CACHED_MP_READ_SESSION) {
280 memset(&params, 0, sizeof(struct cached_connection_params));
281 params.socket_path = CACHED_SOCKET_PATH;
283 rs = __open_cached_mp_read_session(&params,
284 cache_info->entry_name);
285 if (rs == INVALID_CACHED_MP_READ_SESSION)
286 return (NS_UNAVAIL);
288 cache_info->set_mp_rs_func(rs);
291 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
292 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
293 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
295 do {
296 res = __cached_mp_read(rs, buffer, &buffer_size);
297 if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
298 buffer = (char *)realloc(buffer, buffer_size);
299 memset(buffer, 0, buffer_size);
301 } while (res == -2);
303 if (res == 0) {
304 va_copy(ap_new, ap);
305 res = cache_info->unmarshal_func(buffer, buffer_size, retval,
306 ap_new, cache_info->mdata);
307 va_end(ap_new);
309 if (res != NS_SUCCESS) {
310 free(buffer);
311 return (res);
312 } else
313 res = 0;
314 } else {
315 free(buffer);
316 __close_cached_mp_read_session(rs);
317 rs = INVALID_CACHED_MP_READ_SESSION;
318 cache_info->set_mp_rs_func(rs);
319 return (res == -1 ? NS_RETURN : NS_UNAVAIL);
322 free(buffer);
323 return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
327 __nss_mp_cache_write(void *retval, void *mdata, va_list ap)
329 struct cached_connection_params params;
330 cached_mp_write_session ws;
332 char *buffer;
333 size_t buffer_size;
335 nss_cache_info const *cache_info;
336 nss_cache_data *cache_data;
337 va_list ap_new;
338 int res;
340 cache_data = (nss_cache_data *)mdata;
341 cache_info = cache_data->info;
343 ws = cache_info->get_mp_ws_func();
344 if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
345 memset(&params, 0, sizeof(struct cached_connection_params));
346 params.socket_path = CACHED_SOCKET_PATH;
348 ws = __open_cached_mp_write_session(&params,
349 cache_info->entry_name);
350 if (ws == INVALID_CACHED_MP_WRITE_SESSION)
351 return (NS_UNAVAIL);
353 cache_info->set_mp_ws_func(ws);
356 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
357 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
358 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
360 do {
361 size_t size;
363 size = buffer_size;
364 va_copy(ap_new, ap);
365 res = cache_info->marshal_func(buffer, &size, retval, ap_new,
366 cache_info->mdata);
367 va_end(ap_new);
369 if (res == NS_RETURN) {
370 if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
371 break;
373 buffer_size <<= 1;
374 buffer = (char *)realloc(buffer, buffer_size);
375 memset(buffer, 0, buffer_size);
377 } while (res == NS_RETURN);
379 if (res != NS_SUCCESS) {
380 free(buffer);
381 return (res);
384 res = __cached_mp_write(ws, buffer, buffer_size);
386 free(buffer);
387 return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
391 __nss_mp_cache_write_submit(void *retval __unused, void *mdata,
392 va_list ap __unused)
394 cached_mp_write_session ws;
396 nss_cache_info const *cache_info;
397 nss_cache_data *cache_data;
399 cache_data = (nss_cache_data *)mdata;
400 cache_info = cache_data->info;
402 ws = cache_info->get_mp_ws_func();
403 if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
404 __close_cached_mp_write_session(ws);
405 ws = INVALID_CACHED_MP_WRITE_SESSION;
406 cache_info->set_mp_ws_func(ws);
408 return (NS_UNAVAIL);
412 __nss_mp_cache_end(void *retval __unused, void *mdata, va_list ap __unused)
414 cached_mp_write_session ws;
415 cached_mp_read_session rs;
417 nss_cache_info const *cache_info;
418 nss_cache_data *cache_data;
420 cache_data = (nss_cache_data *)mdata;
421 cache_info = cache_data->info;
423 ws = cache_info->get_mp_ws_func();
424 if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
425 __abandon_cached_mp_write_session(ws);
426 ws = INVALID_CACHED_MP_WRITE_SESSION;
427 cache_info->set_mp_ws_func(ws);
430 rs = cache_info->get_mp_rs_func();
431 if (rs != INVALID_CACHED_MP_READ_SESSION) {
432 __close_cached_mp_read_session(rs);
433 rs = INVALID_CACHED_MP_READ_SESSION;
434 cache_info->set_mp_rs_func(rs);
437 return (NS_UNAVAIL);