media/mtransport/third_party/nrappkit/src/registry/registry_local.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /*
michael@0 2 *
michael@0 3 * registry.c
michael@0 4 *
michael@0 5 * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_local.c,v $
michael@0 6 * $Revision: 1.4 $
michael@0 7 * $Date: 2007/11/21 00:09:13 $
michael@0 8 *
michael@0 9 * Datastore for tracking configuration and related info.
michael@0 10 *
michael@0 11 *
michael@0 12 * Copyright (C) 2005, Network Resonance, Inc.
michael@0 13 * Copyright (C) 2006, Network Resonance, Inc.
michael@0 14 * All Rights Reserved
michael@0 15 *
michael@0 16 * Redistribution and use in source and binary forms, with or without
michael@0 17 * modification, are permitted provided that the following conditions
michael@0 18 * are met:
michael@0 19 *
michael@0 20 * 1. Redistributions of source code must retain the above copyright
michael@0 21 * notice, this list of conditions and the following disclaimer.
michael@0 22 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 23 * notice, this list of conditions and the following disclaimer in the
michael@0 24 * documentation and/or other materials provided with the distribution.
michael@0 25 * 3. Neither the name of Network Resonance, Inc. nor the name of any
michael@0 26 * contributors to this software may be used to endorse or promote
michael@0 27 * products derived from this software without specific prior written
michael@0 28 * permission.
michael@0 29 *
michael@0 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
michael@0 31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
michael@0 34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
michael@0 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
michael@0 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
michael@0 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
michael@0 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
michael@0 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
michael@0 40 * POSSIBILITY OF SUCH DAMAGE.
michael@0 41 *
michael@0 42 *
michael@0 43 */
michael@0 44
michael@0 45 #include <assert.h>
michael@0 46 #include <string.h>
michael@0 47 #ifndef WIN32
michael@0 48 #include <strings.h>
michael@0 49 #include <sys/param.h>
michael@0 50 #include <netinet/in.h>
michael@0 51 #endif
michael@0 52 #ifdef OPENSSL
michael@0 53 #include <openssl/ssl.h>
michael@0 54 #endif
michael@0 55 #include <ctype.h>
michael@0 56 #include "registry.h"
michael@0 57 #include "registry_int.h"
michael@0 58 #include "registry_vtbl.h"
michael@0 59 #include "r_assoc.h"
michael@0 60 #include "nr_common.h"
michael@0 61 #include "r_log.h"
michael@0 62 #include "r_errors.h"
michael@0 63 #include "r_macros.h"
michael@0 64
michael@0 65 /* if C were an object-oriented language, nr_scalar_registry_node and
michael@0 66 * nr_array_registry_node would subclass nr_registry_node, but it isn't
michael@0 67 * object-oriented language, so this is used in cases where the pointer
michael@0 68 * could be of either type */
michael@0 69 typedef struct nr_registry_node_ {
michael@0 70 unsigned char type;
michael@0 71 } nr_registry_node;
michael@0 72
michael@0 73 typedef struct nr_scalar_registry_node_ {
michael@0 74 unsigned char type;
michael@0 75 union {
michael@0 76 char _char;
michael@0 77 UCHAR _uchar;
michael@0 78 INT2 _nr_int2;
michael@0 79 UINT2 _nr_uint2;
michael@0 80 INT4 _nr_int4;
michael@0 81 UINT4 _nr_uint4;
michael@0 82 INT8 _nr_int8;
michael@0 83 UINT8 _nr_uint8;
michael@0 84 double _double;
michael@0 85 } scalar;
michael@0 86 } nr_scalar_registry_node;
michael@0 87
michael@0 88 /* string, bytes */
michael@0 89 typedef struct nr_array_registry_node_ {
michael@0 90 unsigned char type;
michael@0 91 struct {
michael@0 92 unsigned int length;
michael@0 93 unsigned char data[1];
michael@0 94 } array;
michael@0 95 } nr_array_registry_node;
michael@0 96
michael@0 97 static int nr_reg_local_init(nr_registry_module *me);
michael@0 98 static int nr_reg_local_get_char(NR_registry name, char *data);
michael@0 99 static int nr_reg_local_get_uchar(NR_registry name, UCHAR *data);
michael@0 100 static int nr_reg_local_get_int2(NR_registry name, INT2 *data);
michael@0 101 static int nr_reg_local_get_uint2(NR_registry name, UINT2 *data);
michael@0 102 static int nr_reg_local_get_int4(NR_registry name, INT4 *data);
michael@0 103 static int nr_reg_local_get_uint4(NR_registry name, UINT4 *data);
michael@0 104 static int nr_reg_local_get_int8(NR_registry name, INT8 *data);
michael@0 105 static int nr_reg_local_get_uint8(NR_registry name, UINT8 *data);
michael@0 106 static int nr_reg_local_get_double(NR_registry name, double *data);
michael@0 107 static int nr_reg_local_get_registry(NR_registry name, NR_registry data);
michael@0 108 static int nr_reg_local_get_bytes(NR_registry name, UCHAR *data, size_t size, size_t *length);
michael@0 109 static int nr_reg_local_get_string(NR_registry name, char *data, size_t size);
michael@0 110 static int nr_reg_local_get_length(NR_registry name, size_t *len);
michael@0 111 static int nr_reg_local_get_type(NR_registry name, NR_registry_type type);
michael@0 112 static int nr_reg_local_set_char(NR_registry name, char data);
michael@0 113 static int nr_reg_local_set_uchar(NR_registry name, UCHAR data);
michael@0 114 static int nr_reg_local_set_int2(NR_registry name, INT2 data);
michael@0 115 static int nr_reg_local_set_uint2(NR_registry name, UINT2 data);
michael@0 116 static int nr_reg_local_set_int4(NR_registry name, INT4 data);
michael@0 117 static int nr_reg_local_set_uint4(NR_registry name, UINT4 data);
michael@0 118 static int nr_reg_local_set_int8(NR_registry name, INT8 data);
michael@0 119 static int nr_reg_local_set_uint8(NR_registry name, UINT8 data);
michael@0 120 static int nr_reg_local_set_double(NR_registry name, double data);
michael@0 121 static int nr_reg_local_set_registry(NR_registry name);
michael@0 122 static int nr_reg_local_set_bytes(NR_registry name, UCHAR *data, size_t length);
michael@0 123 static int nr_reg_local_set_string(NR_registry name, char *data);
michael@0 124 static int nr_reg_local_del(NR_registry name);
michael@0 125 static int nr_reg_local_get_child_count(NR_registry parent, size_t *count);
michael@0 126 static int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length);
michael@0 127 static int nr_reg_local_fin(NR_registry name);
michael@0 128 static int nr_reg_local_dump(int sorted);
michael@0 129 static int nr_reg_insert_node(char *name, void *node);
michael@0 130 static int nr_reg_change_node(char *name, void *node, void *old);
michael@0 131 static int nr_reg_get(char *name, int type, void *out);
michael@0 132 static int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out);
michael@0 133 static int nr_reg_get_array(char *name, unsigned char type, UCHAR *out, size_t size, size_t *length);
michael@0 134 static int nr_reg_set(char *name, int type, void *data);
michael@0 135 static int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length);
michael@0 136 static int nr_reg_set_parent_registries(char *name);
michael@0 137
michael@0 138 /* make these static OLD_REGISTRY */
michael@0 139 #if 0
michael@0 140 static int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node);
michael@0 141 static char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit);
michael@0 142 #else
michael@0 143 int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node);
michael@0 144 char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit);
michael@0 145 #endif
michael@0 146 static int nr_reg_rfree(void *ptr);
michael@0 147 #if 0 /* Unused currently */
michael@0 148 static int nr_reg_noop(void *ptr);
michael@0 149 #endif
michael@0 150 static int nr_reg_compute_length(char *name, nr_registry_node *node, size_t *length);
michael@0 151 char *nr_reg_action_name(int action);
michael@0 152
michael@0 153 /* the registry, containing mappings like "foo.bar.baz" to registry
michael@0 154 * nodes, which are either of type nr_scalar_registry_node or
michael@0 155 * nr_array_registry_node */
michael@0 156 static r_assoc *nr_registry = 0;
michael@0 157
michael@0 158 #if 0 /* Unused currently */
michael@0 159 static nr_array_registry_node nr_top_level_node;
michael@0 160 #endif
michael@0 161
michael@0 162 typedef struct nr_reg_find_children_arg_ {
michael@0 163 size_t size;
michael@0 164 NR_registry *children;
michael@0 165 size_t length;
michael@0 166 } nr_reg_find_children_arg;
michael@0 167
michael@0 168 static int nr_reg_local_iter(char *prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr);
michael@0 169 static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
michael@0 170 static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
michael@0 171 static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
michael@0 172 static int nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
michael@0 173
michael@0 174
michael@0 175
michael@0 176 int
michael@0 177 nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr)
michael@0 178 {
michael@0 179 int r, _status;
michael@0 180 r_assoc_iterator iter;
michael@0 181 char *name;
michael@0 182 int namel;
michael@0 183 nr_registry_node *node;
michael@0 184 int prefixl;
michael@0 185
michael@0 186 if (prefix == 0)
michael@0 187 ABORT(R_INTERNAL);
michael@0 188
michael@0 189 if ((r=r_assoc_init_iter(nr_registry, &iter)))
michael@0 190 ABORT(r);
michael@0 191
michael@0 192 prefixl = strlen(prefix);
michael@0 193
michael@0 194 for (;;) {
michael@0 195 if ((r=r_assoc_iter(&iter, (void*)&name, &namel, (void*)&node))) {
michael@0 196 if (r == R_EOD)
michael@0 197 break;
michael@0 198 else
michael@0 199 ABORT(r);
michael@0 200 }
michael@0 201
michael@0 202 /* subtract to remove the '\0' character from the string length */
michael@0 203 --namel;
michael@0 204
michael@0 205 /* sanity check that the name is null-terminated */
michael@0 206 assert(namel >= 0);
michael@0 207 assert(name[namel] == '\0');
michael@0 208
michael@0 209 if (namel < 0 || name[namel] != '\0' || node == 0)
michael@0 210 break;
michael@0 211
michael@0 212 /* 3 cases where action will be called:
michael@0 213 * 1) prefix == ""
michael@0 214 * 2) prefix == name
michael@0 215 * 3) name == prefix + '.'
michael@0 216 */
michael@0 217 if (prefixl == 0
michael@0 218 || ((namel == prefixl || (namel > prefixl && name[prefixl] == '.'))
michael@0 219 && !strncmp(prefix, name, prefixl))) {
michael@0 220 if ((r=action(ptr, &iter, prefix, name, node)))
michael@0 221 ABORT(r);
michael@0 222 }
michael@0 223 }
michael@0 224
michael@0 225 _status=0;
michael@0 226 abort:
michael@0 227
michael@0 228 return(_status);
michael@0 229 }
michael@0 230
michael@0 231 int
michael@0 232 nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
michael@0 233 {
michael@0 234 int r, _status;
michael@0 235
michael@0 236 if ((r=r_assoc_iter_delete(iter)))
michael@0 237 ABORT(r);
michael@0 238
michael@0 239 _status=0;
michael@0 240 abort:
michael@0 241 return(_status);
michael@0 242 }
michael@0 243
michael@0 244 int
michael@0 245 nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
michael@0 246 {
michael@0 247 int _status;
michael@0 248 int prefixl = strlen(prefix);
michael@0 249 char *dot;
michael@0 250 nr_reg_find_children_arg *arg = (void*)ptr;
michael@0 251
michael@0 252 assert(sizeof(*(arg->children)) == sizeof(NR_registry));
michael@0 253
michael@0 254 /* only grovel through immediate children */
michael@0 255 if (prefixl == 0 || name[prefixl] == '.') {
michael@0 256 if (name[prefixl] != '\0') {
michael@0 257 dot = strchr(&name[prefixl+1], '.');
michael@0 258 if (dot == 0) {
michael@0 259 strncpy(arg->children[arg->length], name, sizeof(NR_registry)-1);
michael@0 260 ++arg->length;
michael@0 261
michael@0 262 /* only grab as many as there are room for */
michael@0 263 if (arg->length >= arg->size)
michael@0 264 ABORT(R_INTERRUPTED);
michael@0 265 }
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 _status = 0;
michael@0 270 abort:
michael@0 271 return _status;
michael@0 272 }
michael@0 273
michael@0 274 int
michael@0 275 nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
michael@0 276 {
michael@0 277 int prefixl = strlen(prefix);
michael@0 278 char *dot;
michael@0 279
michael@0 280 /* only count children */
michael@0 281 if (name[prefixl] == '.') {
michael@0 282 dot = strchr(&name[prefixl+1], '.');
michael@0 283 if (dot == 0)
michael@0 284 ++(*(unsigned int *)ptr);
michael@0 285 }
michael@0 286 else if (name[0] != '\0') {
michael@0 287 if (prefixl == 0)
michael@0 288 ++(*(unsigned int *)ptr);
michael@0 289 }
michael@0 290
michael@0 291 return 0;
michael@0 292 }
michael@0 293
michael@0 294 int
michael@0 295 nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
michael@0 296 {
michael@0 297 int _status;
michael@0 298 int freeit = 0;
michael@0 299 char *data;
michael@0 300
michael@0 301 /* only print leaf nodes */
michael@0 302 if (node->type != NR_REG_TYPE_REGISTRY) {
michael@0 303 data = nr_reg_alloc_node_data(name, node, &freeit);
michael@0 304 if (ptr)
michael@0 305 fprintf((FILE*)ptr, "%s: %s\n", name, data);
michael@0 306 else
michael@0 307 r_log(NR_LOG_REGISTRY, LOG_INFO, "%s: %s", name, data);
michael@0 308 if (freeit)
michael@0 309 RFREE(data);
michael@0 310 }
michael@0 311
michael@0 312 _status=0;
michael@0 313 //abort:
michael@0 314 return(_status);
michael@0 315 }
michael@0 316
michael@0 317
michael@0 318 #if 0 /* Unused currently */
michael@0 319 int
michael@0 320 nr_reg_noop(void *ptr)
michael@0 321 {
michael@0 322 return 0;
michael@0 323 }
michael@0 324 #endif
michael@0 325
michael@0 326 int
michael@0 327 nr_reg_rfree(void *ptr)
michael@0 328 {
michael@0 329 RFREE(ptr);
michael@0 330 return 0;
michael@0 331 }
michael@0 332
michael@0 333 int
michael@0 334 nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node)
michael@0 335 {
michael@0 336 int r, _status;
michael@0 337
michael@0 338 if ((r=nr_reg_is_valid(name)))
michael@0 339 ABORT(r);
michael@0 340
michael@0 341 *node = 0;
michael@0 342 *free_node = 0;
michael@0 343
michael@0 344 if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)node)))
michael@0 345 ABORT(r);
michael@0 346
michael@0 347 if ((*node)->type != type)
michael@0 348 ABORT(R_FAILED);
michael@0 349
michael@0 350 _status=0;
michael@0 351 abort:
michael@0 352 if (_status) {
michael@0 353 if (*node)
michael@0 354 r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s'), found '%s' instead",
michael@0 355 name, nr_reg_type_name(type), nr_reg_type_name((*node)->type));
michael@0 356 else
michael@0 357 r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s')",
michael@0 358 name, nr_reg_type_name(type));
michael@0 359 }
michael@0 360 else {
michael@0 361 r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Fetched node '%s' ('%s')",
michael@0 362 name, nr_reg_type_name(type));
michael@0 363 }
michael@0 364 return(_status);
michael@0 365 }
michael@0 366
michael@0 367 int
michael@0 368 nr_reg_insert_node(char *name, void *node)
michael@0 369 {
michael@0 370 int r, _status;
michael@0 371
michael@0 372 if ((r=nr_reg_is_valid(name)))
michael@0 373 ABORT(r);
michael@0 374
michael@0 375 /* since the registry application is not multi-threaded, a node being
michael@0 376 * inserted should always be a new node because the registry app must
michael@0 377 * have looked for a node with this key but not found it, so it is
michael@0 378 * being created/inserted now using R_ASSOC_NEW */
michael@0 379 if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_NEW)))
michael@0 380 ABORT(r);
michael@0 381
michael@0 382 if ((r=nr_reg_set_parent_registries(name)))
michael@0 383 ABORT(r);
michael@0 384
michael@0 385 if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_ADD)))
michael@0 386 ABORT(r);
michael@0 387
michael@0 388 _status=0;
michael@0 389 abort:
michael@0 390 if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) {
michael@0 391 int freeit;
michael@0 392 char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit);
michael@0 393 r_log(NR_LOG_REGISTRY, LOG_INFO,
michael@0 394 "insert '%s' (%s) %s: %s", name,
michael@0 395 nr_reg_type_name(((nr_registry_node*)node)->type),
michael@0 396 (_status ? "FAILED" : "succeeded"), data);
michael@0 397 if (freeit)
michael@0 398 RFREE(data);
michael@0 399 }
michael@0 400 return(_status);
michael@0 401 }
michael@0 402
michael@0 403 int
michael@0 404 nr_reg_change_node(char *name, void *node, void *old)
michael@0 405 {
michael@0 406 int r, _status;
michael@0 407
michael@0 408 if ((r=nr_reg_is_valid(name)))
michael@0 409 ABORT(r);
michael@0 410
michael@0 411 if (old != node) {
michael@0 412 if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_REPLACE)))
michael@0 413 ABORT(r);
michael@0 414 }
michael@0 415
michael@0 416 if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_CHANGE)))
michael@0 417 ABORT(r);
michael@0 418
michael@0 419 _status=0;
michael@0 420 abort:
michael@0 421 if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) {
michael@0 422 int freeit;
michael@0 423 char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit);
michael@0 424 r_log(NR_LOG_REGISTRY, LOG_INFO,
michael@0 425 "change '%s' (%s) %s: %s", name,
michael@0 426 nr_reg_type_name(((nr_registry_node*)node)->type),
michael@0 427 (_status ? "FAILED" : "succeeded"), data);
michael@0 428 if (freeit)
michael@0 429 RFREE(data);
michael@0 430 }
michael@0 431 return(_status);
michael@0 432 }
michael@0 433
michael@0 434 char *
michael@0 435 nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit)
michael@0 436 {
michael@0 437 char *s = 0;
michael@0 438 int len;
michael@0 439 int alloc = 0;
michael@0 440 unsigned int i;
michael@0 441
michael@0 442 *freeit = 0;
michael@0 443
michael@0 444 switch (node->type) {
michael@0 445 default:
michael@0 446 alloc = 100; /* plenty of room for any of the scalar types */
michael@0 447 break;
michael@0 448 case NR_REG_TYPE_REGISTRY:
michael@0 449 alloc = strlen(name) + 1;
michael@0 450 break;
michael@0 451 case NR_REG_TYPE_BYTES:
michael@0 452 alloc = (2 * ((nr_array_registry_node*)node)->array.length) + 1;
michael@0 453 break;
michael@0 454 case NR_REG_TYPE_STRING:
michael@0 455 alloc = 0;
michael@0 456 break;
michael@0 457 }
michael@0 458
michael@0 459 if (alloc > 0) {
michael@0 460 s = (void*)RMALLOC(alloc);
michael@0 461 if (!s)
michael@0 462 return "";
michael@0 463
michael@0 464 *freeit = 1;
michael@0 465 }
michael@0 466
michael@0 467 len = alloc;
michael@0 468
michael@0 469 switch (node->type) {
michael@0 470 case NR_REG_TYPE_CHAR:
michael@0 471 i = ((nr_scalar_registry_node*)node)->scalar._char;
michael@0 472 if (isprint(i) && ! isspace(i))
michael@0 473 snprintf(s, len, "%c", (char)i);
michael@0 474 else
michael@0 475 snprintf(s, len, "\\%03o", (char)i);
michael@0 476 break;
michael@0 477 case NR_REG_TYPE_UCHAR:
michael@0 478 snprintf(s, len, "0x%02x", ((nr_scalar_registry_node*)node)->scalar._uchar);
michael@0 479 break;
michael@0 480 case NR_REG_TYPE_INT2:
michael@0 481 snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int2);
michael@0 482 break;
michael@0 483 case NR_REG_TYPE_UINT2:
michael@0 484 snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint2);
michael@0 485 break;
michael@0 486 case NR_REG_TYPE_INT4:
michael@0 487 snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int4);
michael@0 488 break;
michael@0 489 case NR_REG_TYPE_UINT4:
michael@0 490 snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint4);
michael@0 491 break;
michael@0 492 case NR_REG_TYPE_INT8:
michael@0 493 snprintf(s, len, "%lld", ((nr_scalar_registry_node*)node)->scalar._nr_int8);
michael@0 494 break;
michael@0 495 case NR_REG_TYPE_UINT8:
michael@0 496 snprintf(s, len, "%llu", ((nr_scalar_registry_node*)node)->scalar._nr_uint8);
michael@0 497 break;
michael@0 498 case NR_REG_TYPE_DOUBLE:
michael@0 499 snprintf(s, len, "%#f", ((nr_scalar_registry_node*)node)->scalar._double);
michael@0 500 break;
michael@0 501 case NR_REG_TYPE_REGISTRY:
michael@0 502 snprintf(s, len, "%s", name);
michael@0 503 break;
michael@0 504 case NR_REG_TYPE_BYTES:
michael@0 505 for (i = 0; i < ((nr_array_registry_node*)node)->array.length; ++i) {
michael@0 506 sprintf(&s[2*i], "%02x", ((nr_array_registry_node*)node)->array.data[i]);
michael@0 507 }
michael@0 508 break;
michael@0 509 case NR_REG_TYPE_STRING:
michael@0 510 s = (char*)((nr_array_registry_node*)node)->array.data;
michael@0 511 break;
michael@0 512 default:
michael@0 513 assert(0); /* bad value */
michael@0 514 *freeit = 0;
michael@0 515 s = "";
michael@0 516 break;
michael@0 517 }
michael@0 518
michael@0 519 return s;
michael@0 520 }
michael@0 521
michael@0 522 int
michael@0 523 nr_reg_get(char *name, int type, void *out)
michael@0 524 {
michael@0 525 int r, _status;
michael@0 526 nr_scalar_registry_node *node = 0;
michael@0 527 int free_node = 0;
michael@0 528
michael@0 529 if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
michael@0 530 ABORT(r);
michael@0 531
michael@0 532 if ((r=nr_reg_get_data(name, node, out)))
michael@0 533 ABORT(r);
michael@0 534
michael@0 535 _status=0;
michael@0 536 abort:
michael@0 537 if (free_node) RFREE(node);
michael@0 538 return(_status);
michael@0 539 }
michael@0 540
michael@0 541 int
michael@0 542 nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out)
michael@0 543 {
michael@0 544 int _status;
michael@0 545
michael@0 546 switch (node->type) {
michael@0 547 case NR_REG_TYPE_CHAR:
michael@0 548 *(char*)out = node->scalar._char;
michael@0 549 break;
michael@0 550 case NR_REG_TYPE_UCHAR:
michael@0 551 *(UCHAR*)out = node->scalar._uchar;
michael@0 552 break;
michael@0 553 case NR_REG_TYPE_INT2:
michael@0 554 *(INT2*)out = node->scalar._nr_int2;
michael@0 555 break;
michael@0 556 case NR_REG_TYPE_UINT2:
michael@0 557 *(UINT2*)out = node->scalar._nr_uint2;
michael@0 558 break;
michael@0 559 case NR_REG_TYPE_INT4:
michael@0 560 *(INT4*)out = node->scalar._nr_int4;
michael@0 561 break;
michael@0 562 case NR_REG_TYPE_UINT4:
michael@0 563 *(UINT4*)out = node->scalar._nr_uint4;
michael@0 564 break;
michael@0 565 case NR_REG_TYPE_INT8:
michael@0 566 *(INT8*)out = node->scalar._nr_int8;
michael@0 567 break;
michael@0 568 case NR_REG_TYPE_UINT8:
michael@0 569 *(UINT8*)out = node->scalar._nr_uint8;
michael@0 570 break;
michael@0 571 case NR_REG_TYPE_DOUBLE:
michael@0 572 *(double*)out = node->scalar._double;
michael@0 573 break;
michael@0 574 default:
michael@0 575 ABORT(R_INTERNAL);
michael@0 576 break;
michael@0 577 }
michael@0 578
michael@0 579 _status=0;
michael@0 580 abort:
michael@0 581 return(_status);
michael@0 582 }
michael@0 583
michael@0 584 int
michael@0 585 nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size, size_t *length)
michael@0 586 {
michael@0 587 int r, _status;
michael@0 588 nr_array_registry_node *node = 0;
michael@0 589 int free_node = 0;
michael@0 590
michael@0 591 if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
michael@0 592 ABORT(r);
michael@0 593
michael@0 594 if (size < node->array.length)
michael@0 595 ABORT(R_BAD_ARGS);
michael@0 596
michael@0 597 if (out != 0)
michael@0 598 memcpy(out, node->array.data, node->array.length);
michael@0 599 if (length != 0)
michael@0 600 *length = node->array.length;
michael@0 601
michael@0 602 _status=0;
michael@0 603 abort:
michael@0 604 if (node && free_node) RFREE(node);
michael@0 605 return(_status);
michael@0 606 }
michael@0 607
michael@0 608 int
michael@0 609 nr_reg_set(char *name, int type, void *data)
michael@0 610 {
michael@0 611 int r, _status;
michael@0 612 nr_scalar_registry_node *node = 0;
michael@0 613 int create_node = 0;
michael@0 614 int changed = 0;
michael@0 615 int free_node = 0;
michael@0 616
michael@0 617 if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
michael@0 618 if (r == R_NOT_FOUND) {
michael@0 619 create_node = 1;
michael@0 620 free_node = 1;
michael@0 621 }
michael@0 622 else
michael@0 623 ABORT(r);
michael@0 624
michael@0 625 if (create_node) {
michael@0 626 if (!(node=(void*)RCALLOC(sizeof(nr_scalar_registry_node))))
michael@0 627 ABORT(R_NO_MEMORY);
michael@0 628
michael@0 629 node->type = type;
michael@0 630 }
michael@0 631 else {
michael@0 632 if (node->type != type)
michael@0 633 ABORT(R_BAD_ARGS);
michael@0 634 }
michael@0 635
michael@0 636 switch (type) {
michael@0 637 #define CASE(TYPE, _name, type) \
michael@0 638 case TYPE: \
michael@0 639 if (node->scalar._name != *(type*)data) { \
michael@0 640 node->scalar._name = *(type*)data; \
michael@0 641 if (! create_node) \
michael@0 642 changed = 1; \
michael@0 643 } \
michael@0 644 break;
michael@0 645 CASE(NR_REG_TYPE_CHAR, _char, char)
michael@0 646 CASE(NR_REG_TYPE_UCHAR, _uchar, UCHAR)
michael@0 647 CASE(NR_REG_TYPE_INT2, _nr_int2, INT2)
michael@0 648 CASE(NR_REG_TYPE_UINT2, _nr_uint2, UINT2)
michael@0 649 CASE(NR_REG_TYPE_INT4, _nr_int4, INT4)
michael@0 650 CASE(NR_REG_TYPE_UINT4, _nr_uint4, UINT4)
michael@0 651 CASE(NR_REG_TYPE_INT8, _nr_int8, INT8)
michael@0 652 CASE(NR_REG_TYPE_UINT8, _nr_uint8, UINT8)
michael@0 653 CASE(NR_REG_TYPE_DOUBLE, _double, double)
michael@0 654 #undef CASE
michael@0 655
michael@0 656 case NR_REG_TYPE_REGISTRY:
michael@0 657 /* do nothing */
michael@0 658 break;
michael@0 659
michael@0 660 default:
michael@0 661 ABORT(R_INTERNAL);
michael@0 662 break;
michael@0 663 }
michael@0 664
michael@0 665 if (create_node) {
michael@0 666 if ((r=nr_reg_insert_node(name, node)))
michael@0 667 ABORT(r);
michael@0 668 free_node = 0;
michael@0 669 }
michael@0 670 else {
michael@0 671 if (changed) {
michael@0 672 if ((r=nr_reg_change_node(name, node, node)))
michael@0 673 ABORT(r);
michael@0 674 free_node = 0;
michael@0 675 }
michael@0 676 }
michael@0 677
michael@0 678 _status=0;
michael@0 679 abort:
michael@0 680 if (_status) {
michael@0 681 if (node && free_node) RFREE(node);
michael@0 682 }
michael@0 683 return(_status);
michael@0 684 }
michael@0 685
michael@0 686 int
michael@0 687 nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length)
michael@0 688 {
michael@0 689 int r, _status;
michael@0 690 nr_array_registry_node *old = 0;
michael@0 691 nr_array_registry_node *node = 0;
michael@0 692 int free_node = 0;
michael@0 693 int added = 0;
michael@0 694 int changed = 0;
michael@0 695
michael@0 696 if ((r=nr_reg_fetch_node(name, type, (void*)&old, &free_node))) {
michael@0 697 if (r != R_NOT_FOUND)
michael@0 698 ABORT(r);
michael@0 699 }
michael@0 700 else {
michael@0 701 assert(free_node == 0);
michael@0 702 }
michael@0 703
michael@0 704 if (old) {
michael@0 705 if (old->type != type)
michael@0 706 ABORT(R_BAD_ARGS);
michael@0 707
michael@0 708 if (old->array.length != length
michael@0 709 || memcmp(old->array.data, data, length)) {
michael@0 710 changed = 1;
michael@0 711
michael@0 712 if (old->array.length < length) {
michael@0 713 if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length)))
michael@0 714 ABORT(R_NO_MEMORY);
michael@0 715 }
michael@0 716 else {
michael@0 717 node = old;
michael@0 718 }
michael@0 719 }
michael@0 720 }
michael@0 721 else {
michael@0 722 if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length)))
michael@0 723 ABORT(R_NO_MEMORY);
michael@0 724
michael@0 725 added = 1;
michael@0 726 }
michael@0 727
michael@0 728 if (added || changed) {
michael@0 729 node->type = type;
michael@0 730 node->array.length = length;
michael@0 731 memcpy(node->array.data, data, length);
michael@0 732 }
michael@0 733
michael@0 734 if (added) {
michael@0 735 if ((r=nr_reg_insert_node(name, node)))
michael@0 736 ABORT(r);
michael@0 737 }
michael@0 738 else if (changed) {
michael@0 739 if ((r=nr_reg_change_node(name, node, old)))
michael@0 740 ABORT(r);
michael@0 741 }
michael@0 742
michael@0 743 _status=0;
michael@0 744 abort:
michael@0 745 return(_status);
michael@0 746 }
michael@0 747
michael@0 748 int
michael@0 749 nr_reg_set_parent_registries(char *name)
michael@0 750 {
michael@0 751 int r, _status;
michael@0 752 char *parent = 0;
michael@0 753 char *dot;
michael@0 754
michael@0 755 if ((parent = r_strdup(name)) == 0)
michael@0 756 ABORT(R_NO_MEMORY);
michael@0 757
michael@0 758 if ((dot = strrchr(parent, '.')) != 0) {
michael@0 759 *dot = '\0';
michael@0 760 if ((r=NR_reg_set_registry(parent)))
michael@0 761 ABORT(r);
michael@0 762 }
michael@0 763
michael@0 764 _status=0;
michael@0 765 abort:
michael@0 766 if (parent) RFREE(parent);
michael@0 767 return(_status);
michael@0 768 }
michael@0 769
michael@0 770
michael@0 771
michael@0 772
michael@0 773
michael@0 774 /* NON-STATIC METHODS */
michael@0 775
michael@0 776 int
michael@0 777 nr_reg_is_valid(NR_registry name)
michael@0 778 {
michael@0 779 int _status;
michael@0 780 unsigned int length;
michael@0 781 unsigned int i;
michael@0 782
michael@0 783 if (name == 0)
michael@0 784 ABORT(R_BAD_ARGS);
michael@0 785
michael@0 786 /* make sure the key is null-terminated */
michael@0 787 if (memchr(name, '\0', sizeof(NR_registry)) == 0)
michael@0 788 ABORT(R_BAD_ARGS);
michael@0 789
michael@0 790 length = strlen(name);
michael@0 791
michael@0 792 /* cannot begin or end with a period */
michael@0 793 if (name[0] == '.')
michael@0 794 ABORT(R_BAD_ARGS);
michael@0 795 if (strlen(name) > 0 && name[length-1] == '.')
michael@0 796 ABORT(R_BAD_ARGS);
michael@0 797
michael@0 798 /* all characters cannot be space, and must be printable and not / */
michael@0 799 for (i = 0; i < length; ++i) {
michael@0 800 if (isspace(name[i]) || ! (isprint(name[i]) || name[i] == '/'))
michael@0 801 ABORT(R_BAD_ARGS);
michael@0 802 }
michael@0 803
michael@0 804 _status=0;
michael@0 805 abort:
michael@0 806 if (_status) {
michael@0 807 r_log(NR_LOG_REGISTRY, LOG_DEBUG, "invalid name '%s'", name);
michael@0 808 }
michael@0 809 return(_status);
michael@0 810 }
michael@0 811
michael@0 812
michael@0 813 int
michael@0 814 nr_reg_compute_length(char *name, nr_registry_node *in, size_t *length)
michael@0 815 {
michael@0 816 int _status;
michael@0 817 nr_array_registry_node *node = (nr_array_registry_node*)in;
michael@0 818
michael@0 819 switch (node->type) {
michael@0 820 case NR_REG_TYPE_STRING:
michael@0 821 *length = node->array.length - 1;
michael@0 822 break;
michael@0 823 case NR_REG_TYPE_BYTES:
michael@0 824 *length = node->array.length;
michael@0 825 break;
michael@0 826 case NR_REG_TYPE_CHAR:
michael@0 827 *length = sizeof(char);
michael@0 828 break;
michael@0 829 case NR_REG_TYPE_UCHAR:
michael@0 830 *length = sizeof(UCHAR);
michael@0 831 break;
michael@0 832 case NR_REG_TYPE_INT2:
michael@0 833 case NR_REG_TYPE_UINT2:
michael@0 834 *length = 2;
michael@0 835 break;
michael@0 836 case NR_REG_TYPE_INT4:
michael@0 837 case NR_REG_TYPE_UINT4:
michael@0 838 *length = 4;
michael@0 839 break;
michael@0 840 case NR_REG_TYPE_INT8:
michael@0 841 case NR_REG_TYPE_UINT8:
michael@0 842 *length = 8;
michael@0 843 break;
michael@0 844 case NR_REG_TYPE_DOUBLE:
michael@0 845 *length = sizeof(double);
michael@0 846 break;
michael@0 847 case NR_REG_TYPE_REGISTRY:
michael@0 848 *length = strlen(name);
michael@0 849 break;
michael@0 850 default:
michael@0 851 ABORT(R_INTERNAL);
michael@0 852 break;
michael@0 853 }
michael@0 854
michael@0 855 _status=0;
michael@0 856 abort:
michael@0 857 return(_status);
michael@0 858 }
michael@0 859
michael@0 860
michael@0 861 /* VTBL METHODS */
michael@0 862
michael@0 863 int
michael@0 864 nr_reg_local_init(nr_registry_module *me)
michael@0 865 {
michael@0 866 int r, _status;
michael@0 867
michael@0 868 if (nr_registry == 0) {
michael@0 869 if ((r=r_assoc_create(&nr_registry, r_assoc_crc32_hash_compute, 12)))
michael@0 870 ABORT(r);
michael@0 871
michael@0 872 if ((r=nr_reg_cb_init()))
michael@0 873 ABORT(r);
michael@0 874
michael@0 875 /* make sure NR_TOP_LEVEL_REGISTRY always exists */
michael@0 876 if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY)))
michael@0 877 ABORT(r);
michael@0 878 }
michael@0 879
michael@0 880 _status=0;
michael@0 881 abort:
michael@0 882 return(_status);
michael@0 883 }
michael@0 884
michael@0 885 #define NRREGGET(func, TYPE, type) \
michael@0 886 int \
michael@0 887 func(NR_registry name, type *out) \
michael@0 888 { \
michael@0 889 return nr_reg_get(name, TYPE, out); \
michael@0 890 }
michael@0 891
michael@0 892 NRREGGET(nr_reg_local_get_char, NR_REG_TYPE_CHAR, char)
michael@0 893 NRREGGET(nr_reg_local_get_uchar, NR_REG_TYPE_UCHAR, UCHAR)
michael@0 894 NRREGGET(nr_reg_local_get_int2, NR_REG_TYPE_INT2, INT2)
michael@0 895 NRREGGET(nr_reg_local_get_uint2, NR_REG_TYPE_UINT2, UINT2)
michael@0 896 NRREGGET(nr_reg_local_get_int4, NR_REG_TYPE_INT4, INT4)
michael@0 897 NRREGGET(nr_reg_local_get_uint4, NR_REG_TYPE_UINT4, UINT4)
michael@0 898 NRREGGET(nr_reg_local_get_int8, NR_REG_TYPE_INT8, INT8)
michael@0 899 NRREGGET(nr_reg_local_get_uint8, NR_REG_TYPE_UINT8, UINT8)
michael@0 900 NRREGGET(nr_reg_local_get_double, NR_REG_TYPE_DOUBLE, double)
michael@0 901
michael@0 902 int
michael@0 903 nr_reg_local_get_registry(NR_registry name, NR_registry out)
michael@0 904 {
michael@0 905 int r, _status;
michael@0 906 nr_scalar_registry_node *node = 0;
michael@0 907 int free_node = 0;
michael@0 908
michael@0 909 if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node)))
michael@0 910 ABORT(r);
michael@0 911
michael@0 912 strncpy(out, name, sizeof(NR_registry));
michael@0 913
michael@0 914 _status=0;
michael@0 915 abort:
michael@0 916 if (free_node) RFREE(node);
michael@0 917 return(_status);
michael@0 918
michael@0 919 }
michael@0 920
michael@0 921 int
michael@0 922 nr_reg_local_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
michael@0 923 {
michael@0 924 return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length);
michael@0 925 }
michael@0 926
michael@0 927 int
michael@0 928 nr_reg_local_get_string(NR_registry name, char *out, size_t size)
michael@0 929 {
michael@0 930 return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0);
michael@0 931 }
michael@0 932
michael@0 933 int
michael@0 934 nr_reg_local_get_length(NR_registry name, size_t *length)
michael@0 935 {
michael@0 936 int r, _status;
michael@0 937 nr_registry_node *node = 0;
michael@0 938
michael@0 939 if ((r=nr_reg_is_valid(name)))
michael@0 940 ABORT(r);
michael@0 941
michael@0 942 if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node)))
michael@0 943 ABORT(r);
michael@0 944
michael@0 945 if ((r=nr_reg_compute_length(name, node, length)))
michael@0 946 ABORT(r);
michael@0 947
michael@0 948 _status=0;
michael@0 949 abort:
michael@0 950 return(_status);
michael@0 951 }
michael@0 952
michael@0 953 int
michael@0 954 nr_reg_local_get_type(NR_registry name, NR_registry_type type)
michael@0 955 {
michael@0 956 int r, _status;
michael@0 957 nr_registry_node *node = 0;
michael@0 958 char *str;
michael@0 959
michael@0 960 if ((r=nr_reg_is_valid(name)))
michael@0 961 ABORT(r);
michael@0 962
michael@0 963 if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node)))
michael@0 964 ABORT(r);
michael@0 965
michael@0 966 str = nr_reg_type_name(node->type);
michael@0 967 if (! str)
michael@0 968 ABORT(R_BAD_ARGS);
michael@0 969
michael@0 970 strncpy(type, str, sizeof(NR_registry_type));
michael@0 971
michael@0 972 _status=0;
michael@0 973 abort:
michael@0 974 return(_status);
michael@0 975 }
michael@0 976
michael@0 977
michael@0 978 #define NRREGSET(func, TYPE, type) \
michael@0 979 int \
michael@0 980 func(NR_registry name, type data) \
michael@0 981 { \
michael@0 982 return nr_reg_set(name, TYPE, &data); \
michael@0 983 }
michael@0 984
michael@0 985 NRREGSET(nr_reg_local_set_char, NR_REG_TYPE_CHAR, char)
michael@0 986 NRREGSET(nr_reg_local_set_uchar, NR_REG_TYPE_UCHAR, UCHAR)
michael@0 987 NRREGSET(nr_reg_local_set_int2, NR_REG_TYPE_INT2, INT2)
michael@0 988 NRREGSET(nr_reg_local_set_uint2, NR_REG_TYPE_UINT2, UINT2)
michael@0 989 NRREGSET(nr_reg_local_set_int4, NR_REG_TYPE_INT4, INT4)
michael@0 990 NRREGSET(nr_reg_local_set_uint4, NR_REG_TYPE_UINT4, UINT4)
michael@0 991 NRREGSET(nr_reg_local_set_int8, NR_REG_TYPE_INT8, INT8)
michael@0 992 NRREGSET(nr_reg_local_set_uint8, NR_REG_TYPE_UINT8, UINT8)
michael@0 993 NRREGSET(nr_reg_local_set_double, NR_REG_TYPE_DOUBLE, double)
michael@0 994
michael@0 995 int
michael@0 996 nr_reg_local_set_registry(NR_registry name)
michael@0 997 {
michael@0 998 return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0);
michael@0 999 }
michael@0 1000
michael@0 1001 int
michael@0 1002 nr_reg_local_set_bytes(NR_registry name, unsigned char *data, size_t length)
michael@0 1003 {
michael@0 1004 return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length);
michael@0 1005 }
michael@0 1006
michael@0 1007 int
michael@0 1008 nr_reg_local_set_string(NR_registry name, char *data)
michael@0 1009 {
michael@0 1010 return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1);
michael@0 1011 }
michael@0 1012
michael@0 1013 int
michael@0 1014 nr_reg_local_del(NR_registry name)
michael@0 1015 {
michael@0 1016 int r, _status;
michael@0 1017
michael@0 1018 if ((r=nr_reg_is_valid(name)))
michael@0 1019 ABORT(r);
michael@0 1020
michael@0 1021 /* delete from NR_registry */
michael@0 1022 if ((r=nr_reg_local_iter(name, nr_reg_local_iter_delete, 0)))
michael@0 1023 ABORT(r);
michael@0 1024
michael@0 1025 if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_DELETE)))
michael@0 1026 ABORT(r);
michael@0 1027
michael@0 1028 /* if deleting from the root, re-insert the root */
michael@0 1029 if (! strcasecmp(name, NR_TOP_LEVEL_REGISTRY)) {
michael@0 1030 if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY)))
michael@0 1031 ABORT(r);
michael@0 1032 }
michael@0 1033
michael@0 1034 _status=0;
michael@0 1035 abort:
michael@0 1036 r_log(NR_LOG_REGISTRY,
michael@0 1037 (_status ? LOG_INFO : LOG_INFO),
michael@0 1038 "delete of '%s' %s", name,
michael@0 1039 (_status ? "FAILED" : "succeeded"));
michael@0 1040 return(_status);
michael@0 1041 }
michael@0 1042
michael@0 1043 int
michael@0 1044 nr_reg_local_get_child_count(char *parent, size_t *count)
michael@0 1045 {
michael@0 1046 int r, _status;
michael@0 1047 nr_registry_node *ignore1;
michael@0 1048 int ignore2;
michael@0 1049
michael@0 1050
michael@0 1051 if ((r=nr_reg_is_valid(parent)))
michael@0 1052 ABORT(r);
michael@0 1053
michael@0 1054 /* test to see whether it is present */
michael@0 1055 if ((r=nr_reg_fetch_node(parent, NR_REG_TYPE_REGISTRY, &ignore1, &ignore2)))
michael@0 1056 ABORT(r);
michael@0 1057
michael@0 1058 /* sanity check that there isn't any memory to free */
michael@0 1059 assert(ignore2 == 0);
michael@0 1060
michael@0 1061 *count = 0;
michael@0 1062
michael@0 1063 if ((r=nr_reg_local_iter(parent, nr_reg_local_count_children, count)))
michael@0 1064 ABORT(r);
michael@0 1065
michael@0 1066 _status=0;
michael@0 1067 abort:
michael@0 1068 return(_status);
michael@0 1069 }
michael@0 1070
michael@0 1071 int
michael@0 1072 nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length)
michael@0 1073 {
michael@0 1074 int r, _status;
michael@0 1075 nr_reg_find_children_arg arg;
michael@0 1076
michael@0 1077 if ((r=nr_reg_is_valid(parent)))
michael@0 1078 ABORT(r);
michael@0 1079
michael@0 1080 arg.children = data;
michael@0 1081 arg.size = size;
michael@0 1082 arg.length = 0;
michael@0 1083
michael@0 1084 if ((r=nr_reg_local_iter(parent, nr_reg_local_find_children, (void*)&arg))) {
michael@0 1085 if (r == R_INTERRUPTED)
michael@0 1086 ABORT(R_BAD_ARGS);
michael@0 1087 else
michael@0 1088 ABORT(r);
michael@0 1089 }
michael@0 1090
michael@0 1091 assert(sizeof(*arg.children) == sizeof(NR_registry));
michael@0 1092 qsort(arg.children, arg.length, sizeof(*arg.children), (void*)strcasecmp);
michael@0 1093
michael@0 1094 *length = arg.length;
michael@0 1095
michael@0 1096 _status = 0;
michael@0 1097 abort:
michael@0 1098 return(_status);
michael@0 1099 }
michael@0 1100
michael@0 1101 int
michael@0 1102 nr_reg_local_fin(NR_registry name)
michael@0 1103 {
michael@0 1104 int r, _status;
michael@0 1105
michael@0 1106 if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_FINAL)))
michael@0 1107 ABORT(r);
michael@0 1108
michael@0 1109 _status=0;
michael@0 1110 abort:
michael@0 1111 return(_status);
michael@0 1112 }
michael@0 1113
michael@0 1114 int
michael@0 1115 nr_reg_local_dump(int sorted)
michael@0 1116 {
michael@0 1117 int r, _status;
michael@0 1118
michael@0 1119 if ((r=nr_reg_local_iter(NR_TOP_LEVEL_REGISTRY, nr_reg_local_dump_print, 0)))
michael@0 1120 ABORT(r);
michael@0 1121
michael@0 1122 _status=0;
michael@0 1123 abort:
michael@0 1124 return(_status);
michael@0 1125 }
michael@0 1126
michael@0 1127
michael@0 1128
michael@0 1129 static nr_registry_module_vtbl nr_reg_local_vtbl = {
michael@0 1130 nr_reg_local_init,
michael@0 1131 nr_reg_local_get_char,
michael@0 1132 nr_reg_local_get_uchar,
michael@0 1133 nr_reg_local_get_int2,
michael@0 1134 nr_reg_local_get_uint2,
michael@0 1135 nr_reg_local_get_int4,
michael@0 1136 nr_reg_local_get_uint4,
michael@0 1137 nr_reg_local_get_int8,
michael@0 1138 nr_reg_local_get_uint8,
michael@0 1139 nr_reg_local_get_double,
michael@0 1140 nr_reg_local_get_registry,
michael@0 1141 nr_reg_local_get_bytes,
michael@0 1142 nr_reg_local_get_string,
michael@0 1143 nr_reg_local_get_length,
michael@0 1144 nr_reg_local_get_type,
michael@0 1145 nr_reg_local_set_char,
michael@0 1146 nr_reg_local_set_uchar,
michael@0 1147 nr_reg_local_set_int2,
michael@0 1148 nr_reg_local_set_uint2,
michael@0 1149 nr_reg_local_set_int4,
michael@0 1150 nr_reg_local_set_uint4,
michael@0 1151 nr_reg_local_set_int8,
michael@0 1152 nr_reg_local_set_uint8,
michael@0 1153 nr_reg_local_set_double,
michael@0 1154 nr_reg_local_set_registry,
michael@0 1155 nr_reg_local_set_bytes,
michael@0 1156 nr_reg_local_set_string,
michael@0 1157 nr_reg_local_del,
michael@0 1158 nr_reg_local_get_child_count,
michael@0 1159 nr_reg_local_get_children,
michael@0 1160 nr_reg_local_fin,
michael@0 1161 nr_reg_local_dump
michael@0 1162 };
michael@0 1163
michael@0 1164 static nr_registry_module nr_reg_local_module = { 0, &nr_reg_local_vtbl };
michael@0 1165
michael@0 1166 void *NR_REG_MODE_LOCAL = &nr_reg_local_module;
michael@0 1167
michael@0 1168

mercurial