registry.c (13099B)
1 /* 2 * 3 * registry.c 4 * 5 * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.c,v $ 6 * $Revision: 1.6 $ 7 * $Date: 2007/11/21 00:09:12 $ 8 * 9 * Datastore for tracking configuration and related info. 10 * 11 * 12 * Copyright (C) 2005, Network Resonance, Inc. 13 * Copyright (C) 2006, Network Resonance, Inc. 14 * All Rights Reserved 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of Network Resonance, Inc. nor the name of any 26 * contributors to this software may be used to endorse or promote 27 * products derived from this software without specific prior written 28 * permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 * POSSIBILITY OF SUCH DAMAGE. 41 * 42 * 43 */ 44 45 #include <assert.h> 46 #include <string.h> 47 #ifndef WIN32 48 #include <strings.h> 49 #include <sys/param.h> 50 #include <netinet/in.h> 51 #endif 52 #ifdef OPENSSL 53 #include <openssl/ssl.h> 54 #endif 55 #include <ctype.h> 56 #include <csi_platform.h> 57 #include "registry.h" 58 #include "registry_int.h" 59 #include "r_assoc.h" 60 #include "r_log.h" 61 #include "r_errors.h" 62 #include "r_macros.h" 63 64 static int reg_initted = 0; 65 66 /* must be in the order the types are numbered */ 67 static char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" }; 68 69 int NR_LOG_REGISTRY=0; 70 71 NR_registry NR_TOP_LEVEL_REGISTRY = ""; 72 73 int 74 NR_reg_init() 75 { 76 int r, _status; 77 #ifdef SANITY_CHECKS 78 NR_registry registry; 79 #endif 80 81 if (reg_initted) { 82 return(0); 83 } 84 85 reg_initted = 1; 86 87 if ((r=nr_reg_local_init())) 88 ABORT(r); 89 90 #ifdef SANITY_CHECKS 91 if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry))) 92 ABORT(r); 93 assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0); 94 #endif 95 96 r_log_init(); 97 r_log_register("registry",&NR_LOG_REGISTRY); 98 99 _status=0; 100 abort: 101 r_log(NR_LOG_REGISTRY, 102 (_status ? LOG_ERR : LOG_INFO), 103 (_status ? "Couldn't initialize registry" : "Initialized registry")); 104 return(_status); 105 } 106 107 int 108 NR_reg_initted(void) 109 { 110 return reg_initted!=0; 111 } 112 113 #define NRREGGET(func, TYPE, type) \ 114 int \ 115 func(NR_registry name, type *out) \ 116 { \ 117 return nr_reg_get(name, TYPE, out); \ 118 } 119 120 NRREGGET(NR_reg_get_char, NR_REG_TYPE_CHAR, char) 121 NRREGGET(NR_reg_get_uchar, NR_REG_TYPE_UCHAR, UCHAR) 122 NRREGGET(NR_reg_get_uint2, NR_REG_TYPE_UINT2, UINT2) 123 NRREGGET(NR_reg_get_int4, NR_REG_TYPE_INT4, INT4) 124 NRREGGET(NR_reg_get_uint4, NR_REG_TYPE_UINT4, UINT4) 125 NRREGGET(NR_reg_get_uint8, NR_REG_TYPE_UINT8, UINT8) 126 NRREGGET(NR_reg_get_double, NR_REG_TYPE_DOUBLE, double) 127 128 int 129 NR_reg_get_registry(NR_registry name, NR_registry out) 130 { 131 int r, _status; 132 nr_scalar_registry_node *node = 0; 133 int free_node = 0; 134 135 if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node))) 136 ABORT(r); 137 138 strncpy(out, name, sizeof(NR_registry)); 139 140 _status=0; 141 abort: 142 if (free_node) RFREE(node); 143 return(_status); 144 145 } 146 147 int 148 NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length) 149 { 150 return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length); 151 } 152 153 int 154 NR_reg_get_string(NR_registry name, char *out, size_t size) 155 { 156 return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0); 157 } 158 159 int 160 NR_reg_get_length(NR_registry name, size_t *length) 161 { 162 return nr_reg_local_get_length(name, length); 163 } 164 165 #define NRREGSET(func, TYPE, type) \ 166 int \ 167 func(NR_registry name, type data) \ 168 { \ 169 return nr_reg_set(name, TYPE, &data); \ 170 } 171 172 NRREGSET(NR_reg_set_char, NR_REG_TYPE_CHAR, char) 173 NRREGSET(NR_reg_set_uchar, NR_REG_TYPE_UCHAR, UCHAR) 174 NRREGSET(NR_reg_set_int4, NR_REG_TYPE_INT4, INT4) 175 NRREGSET(NR_reg_set_uint4, NR_REG_TYPE_UINT4, UINT4) 176 177 int 178 NR_reg_set_string(NR_registry name, char *data) 179 { 180 return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1); 181 } 182 183 int 184 NR_reg_set_registry(NR_registry name) 185 { 186 return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0); 187 } 188 189 int 190 NR_reg_set_bytes(NR_registry name, unsigned char *data, size_t length) 191 { 192 return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length); 193 } 194 195 196 int 197 NR_reg_del(NR_registry name) 198 { 199 return nr_reg_local_del(name); 200 } 201 202 int 203 NR_reg_get_child_count(NR_registry parent, unsigned int *count) 204 { 205 assert(sizeof(count) == sizeof(size_t)); 206 return nr_reg_local_get_child_count(parent, (size_t*)count); 207 } 208 209 int 210 NR_reg_get_child_registry(NR_registry parent, unsigned int i, NR_registry child) 211 { 212 int r, _status; 213 size_t count; 214 NR_registry *children=0; 215 216 if ((r=nr_reg_local_get_child_count(parent, &count))) 217 ABORT(r); 218 219 if (i >= count) 220 ABORT(R_NOT_FOUND); 221 else { 222 count++; 223 children = (NR_registry *)RCALLOC(count * sizeof(NR_registry)); 224 if (!children) 225 ABORT(R_NO_MEMORY); 226 227 if ((r=nr_reg_local_get_children(parent, children, count, &count))) 228 ABORT(r); 229 230 if (i >= count) 231 ABORT(R_NOT_FOUND); 232 233 strncpy(child, children[i], sizeof(NR_registry)); 234 } 235 236 _status=0; 237 abort: 238 RFREE(children); 239 return(_status); 240 } 241 242 // convenience methods, call RFREE on the returned data 243 int 244 NR_reg_alloc_data(NR_registry name, Data *data) 245 { 246 int r, _status; 247 size_t length; 248 UCHAR *tmp = 0; 249 size_t sanity_check; 250 251 if ((r=NR_reg_get_length(name, &length))) 252 ABORT(r); 253 254 if (!(tmp = (void*)RMALLOC(length))) 255 ABORT(R_NO_MEMORY); 256 257 if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check))) 258 ABORT(r); 259 260 assert(length == sanity_check); 261 262 data->len = length; 263 data->data = tmp; 264 265 _status=0; 266 abort: 267 if (_status) { 268 if (tmp) RFREE(tmp); 269 } 270 return(_status); 271 } 272 273 int 274 NR_reg_alloc_string(NR_registry name, char **data) 275 { 276 int r, _status; 277 size_t length; 278 char *tmp = 0; 279 280 if ((r=NR_reg_get_length(name, &length))) 281 ABORT(r); 282 283 if (!(tmp = (void*)RMALLOC(length+1))) 284 ABORT(R_NO_MEMORY); 285 286 if ((r=NR_reg_get_string(name, tmp, length+1))) 287 ABORT(r); 288 289 assert(length == strlen(tmp)); 290 291 *data = tmp; 292 293 _status=0; 294 abort: 295 if (_status) { 296 if (tmp) RFREE(tmp); 297 } 298 return(_status); 299 } 300 301 302 char * 303 nr_reg_type_name(int type) 304 { 305 if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY)) 306 return(NULL); 307 308 return(typenames[type]); 309 } 310 311 int 312 nr_reg_compute_type(char *typename, int *type) 313 { 314 int _status; 315 size_t i; 316 317 #ifdef SANITY_CHECKS 318 assert(!strcasecmp(typenames[NR_REG_TYPE_CHAR], "char")); 319 assert(!strcasecmp(typenames[NR_REG_TYPE_UCHAR], "UCHAR")); 320 assert(!strcasecmp(typenames[NR_REG_TYPE_INT2], "INT2")); 321 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT2], "UINT2")); 322 assert(!strcasecmp(typenames[NR_REG_TYPE_INT4], "INT4")); 323 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT4], "UINT4")); 324 assert(!strcasecmp(typenames[NR_REG_TYPE_INT8], "INT8")); 325 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT8], "UINT8")); 326 assert(!strcasecmp(typenames[NR_REG_TYPE_DOUBLE], "double")); 327 assert(!strcasecmp(typenames[NR_REG_TYPE_BYTES], "Data")); 328 assert(!strcasecmp(typenames[NR_REG_TYPE_STRING], "string")); 329 assert(!strcasecmp(typenames[NR_REG_TYPE_REGISTRY], "registry")); 330 assert(sizeof(typenames)/sizeof(*typenames) == (NR_REG_TYPE_REGISTRY+1)); 331 #endif 332 333 for (i = 0; i < sizeof(typenames)/sizeof(*typenames); ++i) { 334 if (!strcasecmp(typenames[i], typename)) { 335 *type = i; 336 return 0; 337 } 338 } 339 ABORT(R_BAD_ARGS); 340 341 _status=0; 342 abort: 343 return(_status); 344 } 345 346 /* More convenience functions: the same as their parents but they 347 take a prefix and a suffix */ 348 #define NRGET2(func, type, get) \ 349 int \ 350 func(NR_registry parent, char *child, type *out) \ 351 { \ 352 int r, _status; \ 353 NR_registry registry; \ 354 \ 355 if ((r = NR_reg_make_registry(parent, child, registry))) \ 356 ABORT(r); \ 357 \ 358 if ((r = get(registry, out))) { \ 359 ABORT(r); \ 360 } \ 361 \ 362 _status = 0; \ 363 abort: \ 364 return (_status); \ 365 } 366 367 NRGET2(NR_reg_get2_char, char, NR_reg_get_char) 368 NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar) 369 NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2) 370 NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string) 371 NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data) 372 373 /* More convenience functions: the same as their parents but they 374 take a prefix and a suffix */ 375 #define NRSET2(func, type, set) \ 376 int \ 377 func(NR_registry parent, char *child, type in) \ 378 { \ 379 int r, _status; \ 380 NR_registry registry; \ 381 \ 382 if ((r = NR_reg_make_registry(parent, child, registry))) \ 383 ABORT(r); \ 384 \ 385 if ((r = set(registry, in))) { \ 386 ABORT(r); \ 387 } \ 388 \ 389 _status = 0; \ 390 abort: \ 391 return (_status); \ 392 } 393 394 NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar) 395 NRSET2(NR_reg_set2_string, char*, NR_reg_set_string) 396 397 /* requires parent already in legal form */ 398 int 399 NR_reg_make_registry(NR_registry parent, char *child, NR_registry out) 400 { 401 int r, _status; 402 size_t plen; 403 size_t clen; 404 char *c = 0; 405 size_t i; 406 407 if ((r=nr_reg_is_valid(parent))) 408 ABORT(r); 409 410 if (*child == '.') 411 ABORT(R_BAD_ARGS); 412 413 clen = strlen(child); 414 if (!clen) 415 ABORT(R_BAD_ARGS); 416 plen = strlen(parent); 417 if ((plen + clen + 2) > sizeof(NR_registry)) 418 ABORT(R_BAD_ARGS); 419 420 if (out != parent) 421 strcpy(out, parent); 422 423 c = &(out[plen]); 424 425 if (parent[0] != '\0') { 426 *c = '.'; 427 ++c; 428 } 429 430 for (i = 0; i < clen; ++i, ++c) { 431 *c = child[i]; 432 if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c)) 433 *c = '_'; 434 } 435 436 *c = '\0'; 437 438 _status = 0; 439 abort: 440 return _status; 441 }