xref: /dragonfly/usr.sbin/nscd/config.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3*86d7f5d3SJohn Marino  * All rights reserved.
4*86d7f5d3SJohn Marino  *
5*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino  * are met:
8*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino  *
14*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino  * SUCH DAMAGE.
25*86d7f5d3SJohn Marino  *
26*86d7f5d3SJohn Marino  * $FreeBSD: src/usr.sbin/nscd/config.c,v 1.3 2008/10/12 00:44:27 delphij Exp $
27*86d7f5d3SJohn Marino  */
28*86d7f5d3SJohn Marino 
29*86d7f5d3SJohn Marino #include <assert.h>
30*86d7f5d3SJohn Marino #include <math.h>
31*86d7f5d3SJohn Marino #include <stdio.h>
32*86d7f5d3SJohn Marino #include <stdlib.h>
33*86d7f5d3SJohn Marino #include <string.h>
34*86d7f5d3SJohn Marino #include "config.h"
35*86d7f5d3SJohn Marino #include "debug.h"
36*86d7f5d3SJohn Marino #include "log.h"
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino /*
39*86d7f5d3SJohn Marino  * Default entries, which always exist in the configuration
40*86d7f5d3SJohn Marino  */
41*86d7f5d3SJohn Marino const char *c_default_entries[6] = {
42*86d7f5d3SJohn Marino 	NSDB_PASSWD,
43*86d7f5d3SJohn Marino 	NSDB_GROUP,
44*86d7f5d3SJohn Marino 	NSDB_HOSTS,
45*86d7f5d3SJohn Marino 	NSDB_SERVICES,
46*86d7f5d3SJohn Marino 	NSDB_PROTOCOLS,
47*86d7f5d3SJohn Marino 	NSDB_RPC
48*86d7f5d3SJohn Marino 	};
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino static int configuration_entry_cmp(const void *, const void *);
51*86d7f5d3SJohn Marino static int configuration_entry_sort_cmp(const void *, const void *);
52*86d7f5d3SJohn Marino static int configuration_entry_cache_mp_sort_cmp(const void *, const void *);
53*86d7f5d3SJohn Marino static int configuration_entry_cache_mp_cmp(const void *, const void *);
54*86d7f5d3SJohn Marino static int configuration_entry_cache_mp_part_cmp(const void *, const void *);
55*86d7f5d3SJohn Marino static struct configuration_entry *create_configuration_entry(const char *,
56*86d7f5d3SJohn Marino 	struct timeval const *, struct timeval const *,
57*86d7f5d3SJohn Marino 	struct common_cache_entry_params const *,
58*86d7f5d3SJohn Marino 	struct common_cache_entry_params const *,
59*86d7f5d3SJohn Marino 	struct mp_cache_entry_params const *);
60*86d7f5d3SJohn Marino 
61*86d7f5d3SJohn Marino static int
configuration_entry_sort_cmp(const void * e1,const void * e2)62*86d7f5d3SJohn Marino configuration_entry_sort_cmp(const void *e1, const void *e2)
63*86d7f5d3SJohn Marino {
64*86d7f5d3SJohn Marino 	return (strcmp((*((struct configuration_entry **)e1))->name,
65*86d7f5d3SJohn Marino 		(*((struct configuration_entry **)e2))->name
66*86d7f5d3SJohn Marino 		));
67*86d7f5d3SJohn Marino }
68*86d7f5d3SJohn Marino 
69*86d7f5d3SJohn Marino static int
configuration_entry_cmp(const void * e1,const void * e2)70*86d7f5d3SJohn Marino configuration_entry_cmp(const void *e1, const void *e2)
71*86d7f5d3SJohn Marino {
72*86d7f5d3SJohn Marino 	return (strcmp((const char *)e1,
73*86d7f5d3SJohn Marino 		(*((struct configuration_entry **)e2))->name
74*86d7f5d3SJohn Marino 		));
75*86d7f5d3SJohn Marino }
76*86d7f5d3SJohn Marino 
77*86d7f5d3SJohn Marino static int
configuration_entry_cache_mp_sort_cmp(const void * e1,const void * e2)78*86d7f5d3SJohn Marino configuration_entry_cache_mp_sort_cmp(const void *e1, const void *e2)
79*86d7f5d3SJohn Marino {
80*86d7f5d3SJohn Marino 	return (strcmp((*((cache_entry *)e1))->params->entry_name,
81*86d7f5d3SJohn Marino 		(*((cache_entry *)e2))->params->entry_name
82*86d7f5d3SJohn Marino 		));
83*86d7f5d3SJohn Marino }
84*86d7f5d3SJohn Marino 
85*86d7f5d3SJohn Marino static int
configuration_entry_cache_mp_cmp(const void * e1,const void * e2)86*86d7f5d3SJohn Marino configuration_entry_cache_mp_cmp(const void *e1, const void *e2)
87*86d7f5d3SJohn Marino {
88*86d7f5d3SJohn Marino 	return (strcmp((const char *)e1,
89*86d7f5d3SJohn Marino 		(*((cache_entry *)e2))->params->entry_name
90*86d7f5d3SJohn Marino 		));
91*86d7f5d3SJohn Marino }
92*86d7f5d3SJohn Marino 
93*86d7f5d3SJohn Marino static int
configuration_entry_cache_mp_part_cmp(const void * e1,const void * e2)94*86d7f5d3SJohn Marino configuration_entry_cache_mp_part_cmp(const void *e1, const void *e2)
95*86d7f5d3SJohn Marino {
96*86d7f5d3SJohn Marino 	return (strncmp((const char *)e1,
97*86d7f5d3SJohn Marino 		(*((cache_entry *)e2))->params->entry_name,
98*86d7f5d3SJohn Marino 		strlen((const char *)e1)
99*86d7f5d3SJohn Marino 		));
100*86d7f5d3SJohn Marino }
101*86d7f5d3SJohn Marino 
102*86d7f5d3SJohn Marino static struct configuration_entry *
create_configuration_entry(const char * name,struct timeval const * common_timeout,struct timeval const * mp_timeout,struct common_cache_entry_params const * positive_params,struct common_cache_entry_params const * negative_params,struct mp_cache_entry_params const * mp_params)103*86d7f5d3SJohn Marino create_configuration_entry(const char *name,
104*86d7f5d3SJohn Marino 	struct timeval const *common_timeout,
105*86d7f5d3SJohn Marino 	struct timeval const *mp_timeout,
106*86d7f5d3SJohn Marino 	struct common_cache_entry_params const *positive_params,
107*86d7f5d3SJohn Marino 	struct common_cache_entry_params const *negative_params,
108*86d7f5d3SJohn Marino 	struct mp_cache_entry_params const *mp_params)
109*86d7f5d3SJohn Marino {
110*86d7f5d3SJohn Marino 	struct configuration_entry *retval;
111*86d7f5d3SJohn Marino 	size_t	size;
112*86d7f5d3SJohn Marino 	int res;
113*86d7f5d3SJohn Marino 
114*86d7f5d3SJohn Marino 	TRACE_IN(create_configuration_entry);
115*86d7f5d3SJohn Marino 	assert(name != NULL);
116*86d7f5d3SJohn Marino 	assert(positive_params != NULL);
117*86d7f5d3SJohn Marino 	assert(negative_params != NULL);
118*86d7f5d3SJohn Marino 	assert(mp_params != NULL);
119*86d7f5d3SJohn Marino 
120*86d7f5d3SJohn Marino 	retval = (struct configuration_entry *)calloc(1,
121*86d7f5d3SJohn Marino 		sizeof(struct configuration_entry));
122*86d7f5d3SJohn Marino 	assert(retval != NULL);
123*86d7f5d3SJohn Marino 
124*86d7f5d3SJohn Marino 	res = pthread_mutex_init(&retval->positive_cache_lock, NULL);
125*86d7f5d3SJohn Marino 	if (res != 0) {
126*86d7f5d3SJohn Marino 		free(retval);
127*86d7f5d3SJohn Marino 		LOG_ERR_2("create_configuration_entry",
128*86d7f5d3SJohn Marino 			"can't create positive cache lock");
129*86d7f5d3SJohn Marino 		TRACE_OUT(create_configuration_entry);
130*86d7f5d3SJohn Marino 		return (NULL);
131*86d7f5d3SJohn Marino 	}
132*86d7f5d3SJohn Marino 
133*86d7f5d3SJohn Marino 	res = pthread_mutex_init(&retval->negative_cache_lock, NULL);
134*86d7f5d3SJohn Marino 	if (res != 0) {
135*86d7f5d3SJohn Marino 		pthread_mutex_destroy(&retval->positive_cache_lock);
136*86d7f5d3SJohn Marino 		free(retval);
137*86d7f5d3SJohn Marino 		LOG_ERR_2("create_configuration_entry",
138*86d7f5d3SJohn Marino 			"can't create negative cache lock");
139*86d7f5d3SJohn Marino 		TRACE_OUT(create_configuration_entry);
140*86d7f5d3SJohn Marino 		return (NULL);
141*86d7f5d3SJohn Marino 	}
142*86d7f5d3SJohn Marino 
143*86d7f5d3SJohn Marino 	res = pthread_mutex_init(&retval->mp_cache_lock, NULL);
144*86d7f5d3SJohn Marino 	if (res != 0) {
145*86d7f5d3SJohn Marino 		pthread_mutex_destroy(&retval->positive_cache_lock);
146*86d7f5d3SJohn Marino 		pthread_mutex_destroy(&retval->negative_cache_lock);
147*86d7f5d3SJohn Marino 		free(retval);
148*86d7f5d3SJohn Marino 		LOG_ERR_2("create_configuration_entry",
149*86d7f5d3SJohn Marino 			"can't create negative cache lock");
150*86d7f5d3SJohn Marino 		TRACE_OUT(create_configuration_entry);
151*86d7f5d3SJohn Marino 		return (NULL);
152*86d7f5d3SJohn Marino 	}
153*86d7f5d3SJohn Marino 
154*86d7f5d3SJohn Marino 	memcpy(&retval->positive_cache_params, positive_params,
155*86d7f5d3SJohn Marino 		sizeof(struct common_cache_entry_params));
156*86d7f5d3SJohn Marino 	memcpy(&retval->negative_cache_params, negative_params,
157*86d7f5d3SJohn Marino 		sizeof(struct common_cache_entry_params));
158*86d7f5d3SJohn Marino 	memcpy(&retval->mp_cache_params, mp_params,
159*86d7f5d3SJohn Marino 		sizeof(struct mp_cache_entry_params));
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino 	size = strlen(name);
162*86d7f5d3SJohn Marino 	retval->name = (char *)calloc(1, size + 1);
163*86d7f5d3SJohn Marino 	assert(retval->name != NULL);
164*86d7f5d3SJohn Marino 	memcpy(retval->name, name, size);
165*86d7f5d3SJohn Marino 
166*86d7f5d3SJohn Marino 	memcpy(&retval->common_query_timeout, common_timeout,
167*86d7f5d3SJohn Marino 		sizeof(struct timeval));
168*86d7f5d3SJohn Marino 	memcpy(&retval->mp_query_timeout, mp_timeout,
169*86d7f5d3SJohn Marino 		sizeof(struct timeval));
170*86d7f5d3SJohn Marino 
171*86d7f5d3SJohn Marino 	asprintf(&retval->positive_cache_params.entry_name, "%s+", name);
172*86d7f5d3SJohn Marino 	assert(retval->positive_cache_params.entry_name != NULL);
173*86d7f5d3SJohn Marino 
174*86d7f5d3SJohn Marino 	asprintf(&retval->negative_cache_params.entry_name, "%s-", name);
175*86d7f5d3SJohn Marino 	assert(retval->negative_cache_params.entry_name != NULL);
176*86d7f5d3SJohn Marino 
177*86d7f5d3SJohn Marino 	asprintf(&retval->mp_cache_params.entry_name, "%s*", name);
178*86d7f5d3SJohn Marino 	assert(retval->mp_cache_params.entry_name != NULL);
179*86d7f5d3SJohn Marino 
180*86d7f5d3SJohn Marino 	TRACE_OUT(create_configuration_entry);
181*86d7f5d3SJohn Marino 	return (retval);
182*86d7f5d3SJohn Marino }
183*86d7f5d3SJohn Marino 
184*86d7f5d3SJohn Marino /*
185*86d7f5d3SJohn Marino  * Creates configuration entry and fills it with default values
186*86d7f5d3SJohn Marino  */
187*86d7f5d3SJohn Marino struct configuration_entry *
create_def_configuration_entry(const char * name)188*86d7f5d3SJohn Marino create_def_configuration_entry(const char *name)
189*86d7f5d3SJohn Marino {
190*86d7f5d3SJohn Marino 	struct common_cache_entry_params positive_params, negative_params;
191*86d7f5d3SJohn Marino 	struct mp_cache_entry_params mp_params;
192*86d7f5d3SJohn Marino 	struct timeval default_common_timeout, default_mp_timeout;
193*86d7f5d3SJohn Marino 
194*86d7f5d3SJohn Marino 	struct configuration_entry *res = NULL;
195*86d7f5d3SJohn Marino 
196*86d7f5d3SJohn Marino 	TRACE_IN(create_def_configuration_entry);
197*86d7f5d3SJohn Marino 	memset(&positive_params, 0,
198*86d7f5d3SJohn Marino 		sizeof(struct common_cache_entry_params));
199*86d7f5d3SJohn Marino 	positive_params.entry_type = CET_COMMON;
200*86d7f5d3SJohn Marino 	positive_params.cache_entries_size = DEFAULT_CACHE_HT_SIZE;
201*86d7f5d3SJohn Marino 	positive_params.max_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE;
202*86d7f5d3SJohn Marino 	positive_params.satisf_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE / 2;
203*86d7f5d3SJohn Marino 	positive_params.max_lifetime.tv_sec = DEFAULT_POSITIVE_LIFETIME;
204*86d7f5d3SJohn Marino 	positive_params.policy = CPT_LRU;
205*86d7f5d3SJohn Marino 
206*86d7f5d3SJohn Marino 	memcpy(&negative_params, &positive_params,
207*86d7f5d3SJohn Marino 		sizeof(struct common_cache_entry_params));
208*86d7f5d3SJohn Marino 	negative_params.max_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE;
209*86d7f5d3SJohn Marino 	negative_params.satisf_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE / 2;
210*86d7f5d3SJohn Marino 	negative_params.max_lifetime.tv_sec = DEFAULT_NEGATIVE_LIFETIME;
211*86d7f5d3SJohn Marino 	negative_params.policy = CPT_FIFO;
212*86d7f5d3SJohn Marino 
213*86d7f5d3SJohn Marino 	memset(&default_common_timeout, 0, sizeof(struct timeval));
214*86d7f5d3SJohn Marino 	default_common_timeout.tv_sec = DEFAULT_COMMON_ENTRY_TIMEOUT;
215*86d7f5d3SJohn Marino 
216*86d7f5d3SJohn Marino 	memset(&default_mp_timeout, 0, sizeof(struct timeval));
217*86d7f5d3SJohn Marino 	default_mp_timeout.tv_sec = DEFAULT_MP_ENTRY_TIMEOUT;
218*86d7f5d3SJohn Marino 
219*86d7f5d3SJohn Marino 	memset(&mp_params, 0,
220*86d7f5d3SJohn Marino 		sizeof(struct mp_cache_entry_params));
221*86d7f5d3SJohn Marino 	mp_params.entry_type = CET_MULTIPART;
222*86d7f5d3SJohn Marino 	mp_params.max_elemsize = DEFAULT_MULTIPART_ELEMENTS_SIZE;
223*86d7f5d3SJohn Marino 	mp_params.max_sessions = DEFAULT_MULITPART_SESSIONS_SIZE;
224*86d7f5d3SJohn Marino 	mp_params.max_lifetime.tv_sec = DEFAULT_MULITPART_LIFETIME;
225*86d7f5d3SJohn Marino 
226*86d7f5d3SJohn Marino 	res = create_configuration_entry(name, &default_common_timeout,
227*86d7f5d3SJohn Marino 		&default_mp_timeout, &positive_params, &negative_params,
228*86d7f5d3SJohn Marino 		&mp_params);
229*86d7f5d3SJohn Marino 
230*86d7f5d3SJohn Marino 	TRACE_OUT(create_def_configuration_entry);
231*86d7f5d3SJohn Marino 	return (res);
232*86d7f5d3SJohn Marino }
233*86d7f5d3SJohn Marino 
234*86d7f5d3SJohn Marino void
destroy_configuration_entry(struct configuration_entry * entry)235*86d7f5d3SJohn Marino destroy_configuration_entry(struct configuration_entry *entry)
236*86d7f5d3SJohn Marino {
237*86d7f5d3SJohn Marino 	TRACE_IN(destroy_configuration_entry);
238*86d7f5d3SJohn Marino 	assert(entry != NULL);
239*86d7f5d3SJohn Marino 	pthread_mutex_destroy(&entry->positive_cache_lock);
240*86d7f5d3SJohn Marino 	pthread_mutex_destroy(&entry->negative_cache_lock);
241*86d7f5d3SJohn Marino 	pthread_mutex_destroy(&entry->mp_cache_lock);
242*86d7f5d3SJohn Marino 	free(entry->name);
243*86d7f5d3SJohn Marino 	free(entry->positive_cache_params.entry_name);
244*86d7f5d3SJohn Marino 	free(entry->negative_cache_params.entry_name);
245*86d7f5d3SJohn Marino 	free(entry->mp_cache_params.entry_name);
246*86d7f5d3SJohn Marino 	free(entry->mp_cache_entries);
247*86d7f5d3SJohn Marino 	free(entry);
248*86d7f5d3SJohn Marino 	TRACE_OUT(destroy_configuration_entry);
249*86d7f5d3SJohn Marino }
250*86d7f5d3SJohn Marino 
251*86d7f5d3SJohn Marino int
add_configuration_entry(struct configuration * config,struct configuration_entry * entry)252*86d7f5d3SJohn Marino add_configuration_entry(struct configuration *config,
253*86d7f5d3SJohn Marino 	struct configuration_entry *entry)
254*86d7f5d3SJohn Marino {
255*86d7f5d3SJohn Marino 	TRACE_IN(add_configuration_entry);
256*86d7f5d3SJohn Marino 	assert(entry != NULL);
257*86d7f5d3SJohn Marino 	assert(entry->name != NULL);
258*86d7f5d3SJohn Marino 	if (configuration_find_entry(config, entry->name) != NULL) {
259*86d7f5d3SJohn Marino 		TRACE_OUT(add_configuration_entry);
260*86d7f5d3SJohn Marino 		return (-1);
261*86d7f5d3SJohn Marino 	}
262*86d7f5d3SJohn Marino 
263*86d7f5d3SJohn Marino 	if (config->entries_size == config->entries_capacity) {
264*86d7f5d3SJohn Marino 		struct configuration_entry **new_entries;
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino 		config->entries_capacity *= 2;
267*86d7f5d3SJohn Marino 		new_entries = (struct configuration_entry **)calloc(1,
268*86d7f5d3SJohn Marino 			sizeof(struct configuration_entry *) *
269*86d7f5d3SJohn Marino 			config->entries_capacity);
270*86d7f5d3SJohn Marino 		assert(new_entries != NULL);
271*86d7f5d3SJohn Marino 		memcpy(new_entries, config->entries,
272*86d7f5d3SJohn Marino 			sizeof(struct configuration_entry *) *
273*86d7f5d3SJohn Marino 		        config->entries_size);
274*86d7f5d3SJohn Marino 
275*86d7f5d3SJohn Marino 		free(config->entries);
276*86d7f5d3SJohn Marino 		config->entries = new_entries;
277*86d7f5d3SJohn Marino 	}
278*86d7f5d3SJohn Marino 
279*86d7f5d3SJohn Marino 	config->entries[config->entries_size++] = entry;
280*86d7f5d3SJohn Marino 	qsort(config->entries, config->entries_size,
281*86d7f5d3SJohn Marino 		sizeof(struct configuration_entry *),
282*86d7f5d3SJohn Marino 		configuration_entry_sort_cmp);
283*86d7f5d3SJohn Marino 
284*86d7f5d3SJohn Marino 	TRACE_OUT(add_configuration_entry);
285*86d7f5d3SJohn Marino 	return (0);
286*86d7f5d3SJohn Marino }
287*86d7f5d3SJohn Marino 
288*86d7f5d3SJohn Marino size_t
configuration_get_entries_size(struct configuration * config)289*86d7f5d3SJohn Marino configuration_get_entries_size(struct configuration *config)
290*86d7f5d3SJohn Marino {
291*86d7f5d3SJohn Marino 	TRACE_IN(configuration_get_entries_size);
292*86d7f5d3SJohn Marino 	assert(config != NULL);
293*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_get_entries_size);
294*86d7f5d3SJohn Marino 	return (config->entries_size);
295*86d7f5d3SJohn Marino }
296*86d7f5d3SJohn Marino 
297*86d7f5d3SJohn Marino struct configuration_entry *
configuration_get_entry(struct configuration * config,size_t index)298*86d7f5d3SJohn Marino configuration_get_entry(struct configuration *config, size_t index)
299*86d7f5d3SJohn Marino {
300*86d7f5d3SJohn Marino 	TRACE_IN(configuration_get_entry);
301*86d7f5d3SJohn Marino 	assert(config != NULL);
302*86d7f5d3SJohn Marino 	assert(index < config->entries_size);
303*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_get_entry);
304*86d7f5d3SJohn Marino 	return (config->entries[index]);
305*86d7f5d3SJohn Marino }
306*86d7f5d3SJohn Marino 
307*86d7f5d3SJohn Marino struct configuration_entry *
configuration_find_entry(struct configuration * config,const char * name)308*86d7f5d3SJohn Marino configuration_find_entry(struct configuration *config,
309*86d7f5d3SJohn Marino 	const char *name)
310*86d7f5d3SJohn Marino {
311*86d7f5d3SJohn Marino 	struct configuration_entry	**retval;
312*86d7f5d3SJohn Marino 
313*86d7f5d3SJohn Marino 	TRACE_IN(configuration_find_entry);
314*86d7f5d3SJohn Marino 
315*86d7f5d3SJohn Marino 	retval = bsearch(name, config->entries, config->entries_size,
316*86d7f5d3SJohn Marino 		sizeof(struct configuration_entry *), configuration_entry_cmp);
317*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_find_entry);
318*86d7f5d3SJohn Marino 
319*86d7f5d3SJohn Marino 	return ((retval != NULL) ? *retval : NULL);
320*86d7f5d3SJohn Marino }
321*86d7f5d3SJohn Marino 
322*86d7f5d3SJohn Marino /*
323*86d7f5d3SJohn Marino  * All multipart cache entries are stored in the configuration_entry in the
324*86d7f5d3SJohn Marino  * sorted array (sorted by names). The 3 functions below manage this array.
325*86d7f5d3SJohn Marino  */
326*86d7f5d3SJohn Marino 
327*86d7f5d3SJohn Marino int
configuration_entry_add_mp_cache_entry(struct configuration_entry * config_entry,cache_entry c_entry)328*86d7f5d3SJohn Marino configuration_entry_add_mp_cache_entry(struct configuration_entry *config_entry,
329*86d7f5d3SJohn Marino 	cache_entry c_entry)
330*86d7f5d3SJohn Marino {
331*86d7f5d3SJohn Marino 	cache_entry *new_mp_entries, *old_mp_entries;
332*86d7f5d3SJohn Marino 
333*86d7f5d3SJohn Marino 	TRACE_IN(configuration_entry_add_mp_cache_entry);
334*86d7f5d3SJohn Marino 	++config_entry->mp_cache_entries_size;
335*86d7f5d3SJohn Marino 	new_mp_entries = (cache_entry *)malloc(sizeof(cache_entry) *
336*86d7f5d3SJohn Marino 		config_entry->mp_cache_entries_size);
337*86d7f5d3SJohn Marino 	assert(new_mp_entries != NULL);
338*86d7f5d3SJohn Marino 	new_mp_entries[0] = c_entry;
339*86d7f5d3SJohn Marino 
340*86d7f5d3SJohn Marino 	if (config_entry->mp_cache_entries_size - 1 > 0) {
341*86d7f5d3SJohn Marino 		memcpy(new_mp_entries + 1,
342*86d7f5d3SJohn Marino 		    config_entry->mp_cache_entries,
343*86d7f5d3SJohn Marino 		    (config_entry->mp_cache_entries_size - 1) *
344*86d7f5d3SJohn Marino 		    sizeof(cache_entry));
345*86d7f5d3SJohn Marino 	}
346*86d7f5d3SJohn Marino 
347*86d7f5d3SJohn Marino 	old_mp_entries = config_entry->mp_cache_entries;
348*86d7f5d3SJohn Marino 	config_entry->mp_cache_entries = new_mp_entries;
349*86d7f5d3SJohn Marino 	free(old_mp_entries);
350*86d7f5d3SJohn Marino 
351*86d7f5d3SJohn Marino 	qsort(config_entry->mp_cache_entries,
352*86d7f5d3SJohn Marino 		config_entry->mp_cache_entries_size,
353*86d7f5d3SJohn Marino 		sizeof(cache_entry),
354*86d7f5d3SJohn Marino 		configuration_entry_cache_mp_sort_cmp);
355*86d7f5d3SJohn Marino 
356*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_entry_add_mp_cache_entry);
357*86d7f5d3SJohn Marino 	return (0);
358*86d7f5d3SJohn Marino }
359*86d7f5d3SJohn Marino 
360*86d7f5d3SJohn Marino cache_entry
configuration_entry_find_mp_cache_entry(struct configuration_entry * config_entry,const char * mp_name)361*86d7f5d3SJohn Marino configuration_entry_find_mp_cache_entry(
362*86d7f5d3SJohn Marino 	struct configuration_entry *config_entry, const char *mp_name)
363*86d7f5d3SJohn Marino {
364*86d7f5d3SJohn Marino 	cache_entry *result;
365*86d7f5d3SJohn Marino 
366*86d7f5d3SJohn Marino 	TRACE_IN(configuration_entry_find_mp_cache_entry);
367*86d7f5d3SJohn Marino 	result = bsearch(mp_name, config_entry->mp_cache_entries,
368*86d7f5d3SJohn Marino 		config_entry->mp_cache_entries_size,
369*86d7f5d3SJohn Marino 		sizeof(cache_entry), configuration_entry_cache_mp_cmp);
370*86d7f5d3SJohn Marino 
371*86d7f5d3SJohn Marino 	if (result == NULL) {
372*86d7f5d3SJohn Marino 		TRACE_OUT(configuration_entry_find_mp_cache_entry);
373*86d7f5d3SJohn Marino 		return (NULL);
374*86d7f5d3SJohn Marino 	} else {
375*86d7f5d3SJohn Marino 		TRACE_OUT(configuration_entry_find_mp_cache_entry);
376*86d7f5d3SJohn Marino 		return (*result);
377*86d7f5d3SJohn Marino 	}
378*86d7f5d3SJohn Marino }
379*86d7f5d3SJohn Marino 
380*86d7f5d3SJohn Marino /*
381*86d7f5d3SJohn Marino  * Searches for all multipart entries with names starting with mp_name.
382*86d7f5d3SJohn Marino  * Needed for cache flushing.
383*86d7f5d3SJohn Marino  */
384*86d7f5d3SJohn Marino int
configuration_entry_find_mp_cache_entries(struct configuration_entry * config_entry,const char * mp_name,cache_entry ** start,cache_entry ** finish)385*86d7f5d3SJohn Marino configuration_entry_find_mp_cache_entries(
386*86d7f5d3SJohn Marino 	struct configuration_entry *config_entry, const char *mp_name,
387*86d7f5d3SJohn Marino 	cache_entry **start, cache_entry **finish)
388*86d7f5d3SJohn Marino {
389*86d7f5d3SJohn Marino 	cache_entry *result;
390*86d7f5d3SJohn Marino 
391*86d7f5d3SJohn Marino 	TRACE_IN(configuration_entry_find_mp_cache_entries);
392*86d7f5d3SJohn Marino 	result = bsearch(mp_name, config_entry->mp_cache_entries,
393*86d7f5d3SJohn Marino 		config_entry->mp_cache_entries_size,
394*86d7f5d3SJohn Marino 		sizeof(cache_entry), configuration_entry_cache_mp_part_cmp);
395*86d7f5d3SJohn Marino 
396*86d7f5d3SJohn Marino 	if (result == NULL) {
397*86d7f5d3SJohn Marino 		TRACE_OUT(configuration_entry_find_mp_cache_entries);
398*86d7f5d3SJohn Marino 		return (-1);
399*86d7f5d3SJohn Marino 	}
400*86d7f5d3SJohn Marino 
401*86d7f5d3SJohn Marino 	*start = result;
402*86d7f5d3SJohn Marino 	*finish = result + 1;
403*86d7f5d3SJohn Marino 
404*86d7f5d3SJohn Marino 	while (*start != config_entry->mp_cache_entries) {
405*86d7f5d3SJohn Marino 	    if (configuration_entry_cache_mp_part_cmp(mp_name, *start - 1) == 0)
406*86d7f5d3SJohn Marino 		*start = *start - 1;
407*86d7f5d3SJohn Marino 	    else
408*86d7f5d3SJohn Marino 		break;
409*86d7f5d3SJohn Marino 	}
410*86d7f5d3SJohn Marino 
411*86d7f5d3SJohn Marino 	while (*finish != config_entry->mp_cache_entries +
412*86d7f5d3SJohn Marino 		config_entry->mp_cache_entries_size) {
413*86d7f5d3SJohn Marino 
414*86d7f5d3SJohn Marino 	    if (configuration_entry_cache_mp_part_cmp(
415*86d7f5d3SJohn Marino 		mp_name, *finish) == 0)
416*86d7f5d3SJohn Marino 		*finish = *finish + 1;
417*86d7f5d3SJohn Marino 	    else
418*86d7f5d3SJohn Marino 		break;
419*86d7f5d3SJohn Marino 	}
420*86d7f5d3SJohn Marino 
421*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_entry_find_mp_cache_entries);
422*86d7f5d3SJohn Marino 	return (0);
423*86d7f5d3SJohn Marino }
424*86d7f5d3SJohn Marino 
425*86d7f5d3SJohn Marino /*
426*86d7f5d3SJohn Marino  * Configuration entry uses rwlock to handle access to its fields.
427*86d7f5d3SJohn Marino  */
428*86d7f5d3SJohn Marino void
configuration_lock_rdlock(struct configuration * config)429*86d7f5d3SJohn Marino configuration_lock_rdlock(struct configuration *config)
430*86d7f5d3SJohn Marino {
431*86d7f5d3SJohn Marino     TRACE_IN(configuration_lock_rdlock);
432*86d7f5d3SJohn Marino     pthread_rwlock_rdlock(&config->rwlock);
433*86d7f5d3SJohn Marino     TRACE_OUT(configuration_lock_rdlock);
434*86d7f5d3SJohn Marino }
435*86d7f5d3SJohn Marino 
436*86d7f5d3SJohn Marino void
configuration_lock_wrlock(struct configuration * config)437*86d7f5d3SJohn Marino configuration_lock_wrlock(struct configuration *config)
438*86d7f5d3SJohn Marino {
439*86d7f5d3SJohn Marino     TRACE_IN(configuration_lock_wrlock);
440*86d7f5d3SJohn Marino     pthread_rwlock_wrlock(&config->rwlock);
441*86d7f5d3SJohn Marino     TRACE_OUT(configuration_lock_wrlock);
442*86d7f5d3SJohn Marino }
443*86d7f5d3SJohn Marino 
444*86d7f5d3SJohn Marino void
configuration_unlock(struct configuration * config)445*86d7f5d3SJohn Marino configuration_unlock(struct configuration *config)
446*86d7f5d3SJohn Marino {
447*86d7f5d3SJohn Marino     TRACE_IN(configuration_unlock);
448*86d7f5d3SJohn Marino     pthread_rwlock_unlock(&config->rwlock);
449*86d7f5d3SJohn Marino     TRACE_OUT(configuration_unlock);
450*86d7f5d3SJohn Marino }
451*86d7f5d3SJohn Marino 
452*86d7f5d3SJohn Marino /*
453*86d7f5d3SJohn Marino  * Configuration entry uses 3 mutexes to handle cache operations. They are
454*86d7f5d3SJohn Marino  * acquired by configuration_lock_entry and configuration_unlock_entry
455*86d7f5d3SJohn Marino  * functions.
456*86d7f5d3SJohn Marino  */
457*86d7f5d3SJohn Marino void
configuration_lock_entry(struct configuration_entry * entry,enum config_entry_lock_type lock_type)458*86d7f5d3SJohn Marino configuration_lock_entry(struct configuration_entry *entry,
459*86d7f5d3SJohn Marino 	enum config_entry_lock_type lock_type)
460*86d7f5d3SJohn Marino {
461*86d7f5d3SJohn Marino 	TRACE_IN(configuration_lock_entry);
462*86d7f5d3SJohn Marino 	assert(entry != NULL);
463*86d7f5d3SJohn Marino 
464*86d7f5d3SJohn Marino 	switch (lock_type) {
465*86d7f5d3SJohn Marino 	case CELT_POSITIVE:
466*86d7f5d3SJohn Marino 		pthread_mutex_lock(&entry->positive_cache_lock);
467*86d7f5d3SJohn Marino 		break;
468*86d7f5d3SJohn Marino 	case CELT_NEGATIVE:
469*86d7f5d3SJohn Marino 		pthread_mutex_lock(&entry->negative_cache_lock);
470*86d7f5d3SJohn Marino 		break;
471*86d7f5d3SJohn Marino 	case CELT_MULTIPART:
472*86d7f5d3SJohn Marino 		pthread_mutex_lock(&entry->mp_cache_lock);
473*86d7f5d3SJohn Marino 		break;
474*86d7f5d3SJohn Marino 	default:
475*86d7f5d3SJohn Marino 		/* should be unreachable */
476*86d7f5d3SJohn Marino 		break;
477*86d7f5d3SJohn Marino 	}
478*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_lock_entry);
479*86d7f5d3SJohn Marino }
480*86d7f5d3SJohn Marino 
481*86d7f5d3SJohn Marino void
configuration_unlock_entry(struct configuration_entry * entry,enum config_entry_lock_type lock_type)482*86d7f5d3SJohn Marino configuration_unlock_entry(struct configuration_entry *entry,
483*86d7f5d3SJohn Marino 	enum config_entry_lock_type lock_type)
484*86d7f5d3SJohn Marino {
485*86d7f5d3SJohn Marino 	TRACE_IN(configuration_unlock_entry);
486*86d7f5d3SJohn Marino 	assert(entry != NULL);
487*86d7f5d3SJohn Marino 
488*86d7f5d3SJohn Marino 	switch (lock_type) {
489*86d7f5d3SJohn Marino 	case CELT_POSITIVE:
490*86d7f5d3SJohn Marino 		pthread_mutex_unlock(&entry->positive_cache_lock);
491*86d7f5d3SJohn Marino 		break;
492*86d7f5d3SJohn Marino 	case CELT_NEGATIVE:
493*86d7f5d3SJohn Marino 		pthread_mutex_unlock(&entry->negative_cache_lock);
494*86d7f5d3SJohn Marino 		break;
495*86d7f5d3SJohn Marino 	case CELT_MULTIPART:
496*86d7f5d3SJohn Marino 		pthread_mutex_unlock(&entry->mp_cache_lock);
497*86d7f5d3SJohn Marino 		break;
498*86d7f5d3SJohn Marino 	default:
499*86d7f5d3SJohn Marino 		/* should be unreachable */
500*86d7f5d3SJohn Marino 		break;
501*86d7f5d3SJohn Marino 	}
502*86d7f5d3SJohn Marino 	TRACE_OUT(configuration_unlock_entry);
503*86d7f5d3SJohn Marino }
504*86d7f5d3SJohn Marino 
505*86d7f5d3SJohn Marino struct configuration *
init_configuration(void)506*86d7f5d3SJohn Marino init_configuration(void)
507*86d7f5d3SJohn Marino {
508*86d7f5d3SJohn Marino 	struct configuration	*retval;
509*86d7f5d3SJohn Marino 
510*86d7f5d3SJohn Marino 	TRACE_IN(init_configuration);
511*86d7f5d3SJohn Marino 	retval = (struct configuration *)calloc(1, sizeof(struct configuration));
512*86d7f5d3SJohn Marino 	assert(retval != NULL);
513*86d7f5d3SJohn Marino 
514*86d7f5d3SJohn Marino 	retval->entries_capacity = INITIAL_ENTRIES_CAPACITY;
515*86d7f5d3SJohn Marino 	retval->entries = (struct configuration_entry **)calloc(1,
516*86d7f5d3SJohn Marino 		sizeof(struct configuration_entry *) *
517*86d7f5d3SJohn Marino 		retval->entries_capacity);
518*86d7f5d3SJohn Marino 	assert(retval->entries != NULL);
519*86d7f5d3SJohn Marino 
520*86d7f5d3SJohn Marino 	pthread_rwlock_init(&retval->rwlock, NULL);
521*86d7f5d3SJohn Marino 
522*86d7f5d3SJohn Marino 	TRACE_OUT(init_configuration);
523*86d7f5d3SJohn Marino 	return (retval);
524*86d7f5d3SJohn Marino }
525*86d7f5d3SJohn Marino 
526*86d7f5d3SJohn Marino void
fill_configuration_defaults(struct configuration * config)527*86d7f5d3SJohn Marino fill_configuration_defaults(struct configuration *config)
528*86d7f5d3SJohn Marino {
529*86d7f5d3SJohn Marino 	size_t	len, i;
530*86d7f5d3SJohn Marino 
531*86d7f5d3SJohn Marino 	TRACE_IN(fill_configuration_defaults);
532*86d7f5d3SJohn Marino 	assert(config != NULL);
533*86d7f5d3SJohn Marino 
534*86d7f5d3SJohn Marino 	if (config->socket_path != NULL)
535*86d7f5d3SJohn Marino 		free(config->socket_path);
536*86d7f5d3SJohn Marino 
537*86d7f5d3SJohn Marino 	len = strlen(DEFAULT_SOCKET_PATH);
538*86d7f5d3SJohn Marino 	config->socket_path = (char *)calloc(1, len + 1);
539*86d7f5d3SJohn Marino 	assert(config->socket_path != NULL);
540*86d7f5d3SJohn Marino 	memcpy(config->socket_path, DEFAULT_SOCKET_PATH, len);
541*86d7f5d3SJohn Marino 
542*86d7f5d3SJohn Marino 	len = strlen(DEFAULT_PIDFILE_PATH);
543*86d7f5d3SJohn Marino 	config->pidfile_path = (char *)calloc(1, len + 1);
544*86d7f5d3SJohn Marino 	assert(config->pidfile_path != NULL);
545*86d7f5d3SJohn Marino 	memcpy(config->pidfile_path, DEFAULT_PIDFILE_PATH, len);
546*86d7f5d3SJohn Marino 
547*86d7f5d3SJohn Marino 	config->socket_mode =  S_IFSOCK | S_IRUSR | S_IWUSR |
548*86d7f5d3SJohn Marino 		S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
549*86d7f5d3SJohn Marino 	config->force_unlink = 1;
550*86d7f5d3SJohn Marino 
551*86d7f5d3SJohn Marino 	config->query_timeout = DEFAULT_QUERY_TIMEOUT;
552*86d7f5d3SJohn Marino 	config->threads_num = DEFAULT_THREADS_NUM;
553*86d7f5d3SJohn Marino 
554*86d7f5d3SJohn Marino 	for (i = 0; i < config->entries_size; ++i)
555*86d7f5d3SJohn Marino 		destroy_configuration_entry(config->entries[i]);
556*86d7f5d3SJohn Marino 	config->entries_size = 0;
557*86d7f5d3SJohn Marino 
558*86d7f5d3SJohn Marino 	TRACE_OUT(fill_configuration_defaults);
559*86d7f5d3SJohn Marino }
560*86d7f5d3SJohn Marino 
561*86d7f5d3SJohn Marino void
destroy_configuration(struct configuration * config)562*86d7f5d3SJohn Marino destroy_configuration(struct configuration *config)
563*86d7f5d3SJohn Marino {
564*86d7f5d3SJohn Marino 	int	i;
565*86d7f5d3SJohn Marino 	TRACE_IN(destroy_configuration);
566*86d7f5d3SJohn Marino 	assert(config != NULL);
567*86d7f5d3SJohn Marino 	free(config->pidfile_path);
568*86d7f5d3SJohn Marino 	free(config->socket_path);
569*86d7f5d3SJohn Marino 
570*86d7f5d3SJohn Marino 	for (i = 0; i < config->entries_size; ++i)
571*86d7f5d3SJohn Marino 		destroy_configuration_entry(config->entries[i]);
572*86d7f5d3SJohn Marino 	free(config->entries);
573*86d7f5d3SJohn Marino 
574*86d7f5d3SJohn Marino 	pthread_rwlock_destroy(&config->rwlock);
575*86d7f5d3SJohn Marino 	free(config);
576*86d7f5d3SJohn Marino 	TRACE_OUT(destroy_configuration);
577*86d7f5d3SJohn Marino }
578