/* * * registry.c * * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_local.c,v $ * $Revision: 1.4 $ * $Date: 2007/11/21 00:09:13 $ * * Datastore for tracking configuration and related info. * * * Copyright (C) 2005, Network Resonance, Inc. * Copyright (C) 2006, Network Resonance, Inc. * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Network Resonance, Inc. nor the name of any * contributors to this software may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * */ #include #include #ifndef WIN32 #include #include #include #endif #ifdef OPENSSL #include #endif #include #include "registry.h" #include "registry_int.h" #include "registry_vtbl.h" #include "r_assoc.h" #include "nr_common.h" #include "r_log.h" #include "r_errors.h" #include "r_macros.h" /* if C were an object-oriented language, nr_scalar_registry_node and * nr_array_registry_node would subclass nr_registry_node, but it isn't * object-oriented language, so this is used in cases where the pointer * could be of either type */ typedef struct nr_registry_node_ { unsigned char type; } nr_registry_node; typedef struct nr_scalar_registry_node_ { unsigned char type; union { char _char; UCHAR _uchar; INT2 _nr_int2; UINT2 _nr_uint2; INT4 _nr_int4; UINT4 _nr_uint4; INT8 _nr_int8; UINT8 _nr_uint8; double _double; } scalar; } nr_scalar_registry_node; /* string, bytes */ typedef struct nr_array_registry_node_ { unsigned char type; struct { unsigned int length; unsigned char data[1]; } array; } nr_array_registry_node; static int nr_reg_local_init(nr_registry_module *me); static int nr_reg_local_get_char(NR_registry name, char *data); static int nr_reg_local_get_uchar(NR_registry name, UCHAR *data); static int nr_reg_local_get_int2(NR_registry name, INT2 *data); static int nr_reg_local_get_uint2(NR_registry name, UINT2 *data); static int nr_reg_local_get_int4(NR_registry name, INT4 *data); static int nr_reg_local_get_uint4(NR_registry name, UINT4 *data); static int nr_reg_local_get_int8(NR_registry name, INT8 *data); static int nr_reg_local_get_uint8(NR_registry name, UINT8 *data); static int nr_reg_local_get_double(NR_registry name, double *data); static int nr_reg_local_get_registry(NR_registry name, NR_registry data); static int nr_reg_local_get_bytes(NR_registry name, UCHAR *data, size_t size, size_t *length); static int nr_reg_local_get_string(NR_registry name, char *data, size_t size); static int nr_reg_local_get_length(NR_registry name, size_t *len); static int nr_reg_local_get_type(NR_registry name, NR_registry_type type); static int nr_reg_local_set_char(NR_registry name, char data); static int nr_reg_local_set_uchar(NR_registry name, UCHAR data); static int nr_reg_local_set_int2(NR_registry name, INT2 data); static int nr_reg_local_set_uint2(NR_registry name, UINT2 data); static int nr_reg_local_set_int4(NR_registry name, INT4 data); static int nr_reg_local_set_uint4(NR_registry name, UINT4 data); static int nr_reg_local_set_int8(NR_registry name, INT8 data); static int nr_reg_local_set_uint8(NR_registry name, UINT8 data); static int nr_reg_local_set_double(NR_registry name, double data); static int nr_reg_local_set_registry(NR_registry name); static int nr_reg_local_set_bytes(NR_registry name, UCHAR *data, size_t length); static int nr_reg_local_set_string(NR_registry name, char *data); static int nr_reg_local_del(NR_registry name); static int nr_reg_local_get_child_count(NR_registry parent, size_t *count); static int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length); static int nr_reg_local_fin(NR_registry name); static int nr_reg_local_dump(int sorted); static int nr_reg_insert_node(char *name, void *node); static int nr_reg_change_node(char *name, void *node, void *old); static int nr_reg_get(char *name, int type, void *out); static int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out); static int nr_reg_get_array(char *name, unsigned char type, UCHAR *out, size_t size, size_t *length); static int nr_reg_set(char *name, int type, void *data); static int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length); static int nr_reg_set_parent_registries(char *name); /* make these static OLD_REGISTRY */ #if 0 static int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node); static char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit); #else int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node); char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit); #endif static int nr_reg_rfree(void *ptr); #if 0 /* Unused currently */ static int nr_reg_noop(void *ptr); #endif static int nr_reg_compute_length(char *name, nr_registry_node *node, size_t *length); char *nr_reg_action_name(int action); /* the registry, containing mappings like "foo.bar.baz" to registry * nodes, which are either of type nr_scalar_registry_node or * nr_array_registry_node */ static r_assoc *nr_registry = 0; #if 0 /* Unused currently */ static nr_array_registry_node nr_top_level_node; #endif typedef struct nr_reg_find_children_arg_ { size_t size; NR_registry *children; size_t length; } nr_reg_find_children_arg; static int 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); static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); static int nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); int 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) { int r, _status; r_assoc_iterator iter; char *name; int namel; nr_registry_node *node; int prefixl; if (prefix == 0) ABORT(R_INTERNAL); if ((r=r_assoc_init_iter(nr_registry, &iter))) ABORT(r); prefixl = strlen(prefix); for (;;) { if ((r=r_assoc_iter(&iter, (void*)&name, &namel, (void*)&node))) { if (r == R_EOD) break; else ABORT(r); } /* subtract to remove the '\0' character from the string length */ --namel; /* sanity check that the name is null-terminated */ assert(namel >= 0); assert(name[namel] == '\0'); if (namel < 0 || name[namel] != '\0' || node == 0) break; /* 3 cases where action will be called: * 1) prefix == "" * 2) prefix == name * 3) name == prefix + '.' */ if (prefixl == 0 || ((namel == prefixl || (namel > prefixl && name[prefixl] == '.')) && !strncmp(prefix, name, prefixl))) { if ((r=action(ptr, &iter, prefix, name, node))) ABORT(r); } } _status=0; abort: return(_status); } int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) { int r, _status; if ((r=r_assoc_iter_delete(iter))) ABORT(r); _status=0; abort: return(_status); } int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) { int _status; int prefixl = strlen(prefix); char *dot; nr_reg_find_children_arg *arg = (void*)ptr; assert(sizeof(*(arg->children)) == sizeof(NR_registry)); /* only grovel through immediate children */ if (prefixl == 0 || name[prefixl] == '.') { if (name[prefixl] != '\0') { dot = strchr(&name[prefixl+1], '.'); if (dot == 0) { strncpy(arg->children[arg->length], name, sizeof(NR_registry)-1); ++arg->length; /* only grab as many as there are room for */ if (arg->length >= arg->size) ABORT(R_INTERRUPTED); } } } _status = 0; abort: return _status; } int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) { int prefixl = strlen(prefix); char *dot; /* only count children */ if (name[prefixl] == '.') { dot = strchr(&name[prefixl+1], '.'); if (dot == 0) ++(*(unsigned int *)ptr); } else if (name[0] != '\0') { if (prefixl == 0) ++(*(unsigned int *)ptr); } return 0; } int nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) { int _status; int freeit = 0; char *data; /* only print leaf nodes */ if (node->type != NR_REG_TYPE_REGISTRY) { data = nr_reg_alloc_node_data(name, node, &freeit); if (ptr) fprintf((FILE*)ptr, "%s: %s\n", name, data); else r_log(NR_LOG_REGISTRY, LOG_INFO, "%s: %s", name, data); if (freeit) RFREE(data); } _status=0; //abort: return(_status); } #if 0 /* Unused currently */ int nr_reg_noop(void *ptr) { return 0; } #endif int nr_reg_rfree(void *ptr) { RFREE(ptr); return 0; } int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node) { int r, _status; *node = 0; *free_node = 0; if ((r=nr_reg_is_valid(name))) ABORT(r); if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)node))) ABORT(r); if ((*node)->type != type) ABORT(R_FAILED); _status=0; abort: if (_status) { if (*node) r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s'), found '%s' instead", name, nr_reg_type_name(type), nr_reg_type_name((*node)->type)); else r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s')", name, nr_reg_type_name(type)); } else { r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Fetched node '%s' ('%s')", name, nr_reg_type_name(type)); } return(_status); } int nr_reg_insert_node(char *name, void *node) { int r, _status; if ((r=nr_reg_is_valid(name))) ABORT(r); /* since the registry application is not multi-threaded, a node being * inserted should always be a new node because the registry app must * have looked for a node with this key but not found it, so it is * being created/inserted now using R_ASSOC_NEW */ if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_NEW))) ABORT(r); if ((r=nr_reg_set_parent_registries(name))) ABORT(r); if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_ADD))) ABORT(r); _status=0; abort: if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) { int freeit; char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit); r_log(NR_LOG_REGISTRY, LOG_INFO, "insert '%s' (%s) %s: %s", name, nr_reg_type_name(((nr_registry_node*)node)->type), (_status ? "FAILED" : "succeeded"), data); if (freeit) RFREE(data); } return(_status); } int nr_reg_change_node(char *name, void *node, void *old) { int r, _status; if ((r=nr_reg_is_valid(name))) ABORT(r); if (old != node) { if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_REPLACE))) ABORT(r); } if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_CHANGE))) ABORT(r); _status=0; abort: if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) { int freeit; char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit); r_log(NR_LOG_REGISTRY, LOG_INFO, "change '%s' (%s) %s: %s", name, nr_reg_type_name(((nr_registry_node*)node)->type), (_status ? "FAILED" : "succeeded"), data); if (freeit) RFREE(data); } return(_status); } char * nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit) { char *s = 0; int len; int alloc = 0; unsigned int i; *freeit = 0; switch (node->type) { default: alloc = 100; /* plenty of room for any of the scalar types */ break; case NR_REG_TYPE_REGISTRY: alloc = strlen(name) + 1; break; case NR_REG_TYPE_BYTES: alloc = (2 * ((nr_array_registry_node*)node)->array.length) + 1; break; case NR_REG_TYPE_STRING: alloc = 0; break; } if (alloc > 0) { s = (void*)RMALLOC(alloc); if (!s) return ""; *freeit = 1; } len = alloc; switch (node->type) { case NR_REG_TYPE_CHAR: i = ((nr_scalar_registry_node*)node)->scalar._char; if (isprint(i) && ! isspace(i)) snprintf(s, len, "%c", (char)i); else snprintf(s, len, "\\%03o", (char)i); break; case NR_REG_TYPE_UCHAR: snprintf(s, len, "0x%02x", ((nr_scalar_registry_node*)node)->scalar._uchar); break; case NR_REG_TYPE_INT2: snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int2); break; case NR_REG_TYPE_UINT2: snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint2); break; case NR_REG_TYPE_INT4: snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int4); break; case NR_REG_TYPE_UINT4: snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint4); break; case NR_REG_TYPE_INT8: snprintf(s, len, "%lld", ((nr_scalar_registry_node*)node)->scalar._nr_int8); break; case NR_REG_TYPE_UINT8: snprintf(s, len, "%llu", ((nr_scalar_registry_node*)node)->scalar._nr_uint8); break; case NR_REG_TYPE_DOUBLE: snprintf(s, len, "%#f", ((nr_scalar_registry_node*)node)->scalar._double); break; case NR_REG_TYPE_REGISTRY: snprintf(s, len, "%s", name); break; case NR_REG_TYPE_BYTES: for (i = 0; i < ((nr_array_registry_node*)node)->array.length; ++i) { sprintf(&s[2*i], "%02x", ((nr_array_registry_node*)node)->array.data[i]); } break; case NR_REG_TYPE_STRING: s = (char*)((nr_array_registry_node*)node)->array.data; break; default: assert(0); /* bad value */ *freeit = 0; s = ""; break; } return s; } int nr_reg_get(char *name, int type, void *out) { int r, _status; nr_scalar_registry_node *node = 0; int free_node = 0; if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) ABORT(r); if ((r=nr_reg_get_data(name, node, out))) ABORT(r); _status=0; abort: if (free_node) RFREE(node); return(_status); } int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out) { int _status; switch (node->type) { case NR_REG_TYPE_CHAR: *(char*)out = node->scalar._char; break; case NR_REG_TYPE_UCHAR: *(UCHAR*)out = node->scalar._uchar; break; case NR_REG_TYPE_INT2: *(INT2*)out = node->scalar._nr_int2; break; case NR_REG_TYPE_UINT2: *(UINT2*)out = node->scalar._nr_uint2; break; case NR_REG_TYPE_INT4: *(INT4*)out = node->scalar._nr_int4; break; case NR_REG_TYPE_UINT4: *(UINT4*)out = node->scalar._nr_uint4; break; case NR_REG_TYPE_INT8: *(INT8*)out = node->scalar._nr_int8; break; case NR_REG_TYPE_UINT8: *(UINT8*)out = node->scalar._nr_uint8; break; case NR_REG_TYPE_DOUBLE: *(double*)out = node->scalar._double; break; default: ABORT(R_INTERNAL); break; } _status=0; abort: return(_status); } int nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size, size_t *length) { int r, _status; nr_array_registry_node *node = 0; int free_node = 0; if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) ABORT(r); if (size < node->array.length) ABORT(R_BAD_ARGS); if (out != 0) memcpy(out, node->array.data, node->array.length); if (length != 0) *length = node->array.length; _status=0; abort: if (node && free_node) RFREE(node); return(_status); } int nr_reg_set(char *name, int type, void *data) { int r, _status; nr_scalar_registry_node *node = 0; int create_node = 0; int changed = 0; int free_node = 0; if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) if (r == R_NOT_FOUND) { create_node = 1; free_node = 1; } else ABORT(r); if (create_node) { if (!(node=(void*)RCALLOC(sizeof(nr_scalar_registry_node)))) ABORT(R_NO_MEMORY); node->type = type; } else { if (node->type != type) ABORT(R_BAD_ARGS); } switch (type) { #define CASE(TYPE, _name, type) \ case TYPE: \ if (node->scalar._name != *(type*)data) { \ node->scalar._name = *(type*)data; \ if (! create_node) \ changed = 1; \ } \ break; CASE(NR_REG_TYPE_CHAR, _char, char) CASE(NR_REG_TYPE_UCHAR, _uchar, UCHAR) CASE(NR_REG_TYPE_INT2, _nr_int2, INT2) CASE(NR_REG_TYPE_UINT2, _nr_uint2, UINT2) CASE(NR_REG_TYPE_INT4, _nr_int4, INT4) CASE(NR_REG_TYPE_UINT4, _nr_uint4, UINT4) CASE(NR_REG_TYPE_INT8, _nr_int8, INT8) CASE(NR_REG_TYPE_UINT8, _nr_uint8, UINT8) CASE(NR_REG_TYPE_DOUBLE, _double, double) #undef CASE case NR_REG_TYPE_REGISTRY: /* do nothing */ break; default: ABORT(R_INTERNAL); break; } if (create_node) { if ((r=nr_reg_insert_node(name, node))) ABORT(r); free_node = 0; } else { if (changed) { if ((r=nr_reg_change_node(name, node, node))) ABORT(r); free_node = 0; } } _status=0; abort: if (_status) { if (node && free_node) RFREE(node); } return(_status); } int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) { int r, _status; nr_array_registry_node *old = 0; nr_array_registry_node *node = 0; int free_node = 0; int added = 0; int changed = 0; if ((r=nr_reg_fetch_node(name, type, (void*)&old, &free_node))) { if (r != R_NOT_FOUND) ABORT(r); } else { assert(free_node == 0); } if (old) { if (old->type != type) ABORT(R_BAD_ARGS); if (old->array.length != length || memcmp(old->array.data, data, length)) { changed = 1; if (old->array.length < length) { if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length))) ABORT(R_NO_MEMORY); } else { node = old; } } } else { if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length))) ABORT(R_NO_MEMORY); added = 1; } if (added || changed) { node->type = type; node->array.length = length; memcpy(node->array.data, data, length); } if (added) { if ((r=nr_reg_insert_node(name, node))) ABORT(r); } else if (changed) { if ((r=nr_reg_change_node(name, node, old))) ABORT(r); } _status=0; abort: return(_status); } int nr_reg_set_parent_registries(char *name) { int r, _status; char *parent = 0; char *dot; if ((parent = r_strdup(name)) == 0) ABORT(R_NO_MEMORY); if ((dot = strrchr(parent, '.')) != 0) { *dot = '\0'; if ((r=NR_reg_set_registry(parent))) ABORT(r); } _status=0; abort: if (parent) RFREE(parent); return(_status); } /* NON-STATIC METHODS */ int nr_reg_is_valid(NR_registry name) { int _status; unsigned int length; unsigned int i; if (name == 0) ABORT(R_BAD_ARGS); /* make sure the key is null-terminated */ if (memchr(name, '\0', sizeof(NR_registry)) == 0) ABORT(R_BAD_ARGS); length = strlen(name); /* cannot begin or end with a period */ if (name[0] == '.') ABORT(R_BAD_ARGS); if (strlen(name) > 0 && name[length-1] == '.') ABORT(R_BAD_ARGS); /* all characters cannot be space, and must be printable and not / */ for (i = 0; i < length; ++i) { if (isspace(name[i]) || !isprint(name[i]) || name[i] == '/') ABORT(R_BAD_ARGS); } _status=0; abort: if (_status) { r_log(NR_LOG_REGISTRY, LOG_DEBUG, "invalid name '%s'", name); } return(_status); } int nr_reg_compute_length(char *name, nr_registry_node *in, size_t *length) { int _status; nr_array_registry_node *node = (nr_array_registry_node*)in; switch (node->type) { case NR_REG_TYPE_STRING: *length = node->array.length - 1; break; case NR_REG_TYPE_BYTES: *length = node->array.length; break; case NR_REG_TYPE_CHAR: *length = sizeof(char); break; case NR_REG_TYPE_UCHAR: *length = sizeof(UCHAR); break; case NR_REG_TYPE_INT2: case NR_REG_TYPE_UINT2: *length = 2; break; case NR_REG_TYPE_INT4: case NR_REG_TYPE_UINT4: *length = 4; break; case NR_REG_TYPE_INT8: case NR_REG_TYPE_UINT8: *length = 8; break; case NR_REG_TYPE_DOUBLE: *length = sizeof(double); break; case NR_REG_TYPE_REGISTRY: *length = strlen(name); break; default: ABORT(R_INTERNAL); break; } _status=0; abort: return(_status); } /* VTBL METHODS */ int nr_reg_local_init(nr_registry_module *me) { int r, _status; if (nr_registry == 0) { if ((r=r_assoc_create(&nr_registry, r_assoc_crc32_hash_compute, 12))) ABORT(r); if ((r=nr_reg_cb_init())) ABORT(r); /* make sure NR_TOP_LEVEL_REGISTRY always exists */ if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY))) ABORT(r); } _status=0; abort: return(_status); } #define NRREGLOCALGET(func, TYPE, type) \ int \ func(NR_registry name, type *out) \ { \ return nr_reg_get(name, TYPE, out); \ } NRREGLOCALGET(nr_reg_local_get_char, NR_REG_TYPE_CHAR, char) NRREGLOCALGET(nr_reg_local_get_uchar, NR_REG_TYPE_UCHAR, UCHAR) NRREGLOCALGET(nr_reg_local_get_int2, NR_REG_TYPE_INT2, INT2) NRREGLOCALGET(nr_reg_local_get_uint2, NR_REG_TYPE_UINT2, UINT2) NRREGLOCALGET(nr_reg_local_get_int4, NR_REG_TYPE_INT4, INT4) NRREGLOCALGET(nr_reg_local_get_uint4, NR_REG_TYPE_UINT4, UINT4) NRREGLOCALGET(nr_reg_local_get_int8, NR_REG_TYPE_INT8, INT8) NRREGLOCALGET(nr_reg_local_get_uint8, NR_REG_TYPE_UINT8, UINT8) NRREGLOCALGET(nr_reg_local_get_double, NR_REG_TYPE_DOUBLE, double) int nr_reg_local_get_registry(NR_registry name, NR_registry out) { int r, _status; nr_scalar_registry_node *node = 0; int free_node = 0; if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node))) ABORT(r); strncpy(out, name, sizeof(NR_registry)); _status=0; abort: if (free_node) RFREE(node); return(_status); } int nr_reg_local_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length) { return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length); } int nr_reg_local_get_string(NR_registry name, char *out, size_t size) { return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0); } int nr_reg_local_get_length(NR_registry name, size_t *length) { int r, _status; nr_registry_node *node = 0; if ((r=nr_reg_is_valid(name))) ABORT(r); if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node))) ABORT(r); if ((r=nr_reg_compute_length(name, node, length))) ABORT(r); _status=0; abort: return(_status); } int nr_reg_local_get_type(NR_registry name, NR_registry_type type) { int r, _status; nr_registry_node *node = 0; char *str; if ((r=nr_reg_is_valid(name))) ABORT(r); if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node))) ABORT(r); str = nr_reg_type_name(node->type); if (! str) ABORT(R_BAD_ARGS); strncpy(type, str, sizeof(NR_registry_type)); _status=0; abort: return(_status); } #define NRREGLOCALSET(func, TYPE, type) \ int \ func(NR_registry name, type data) \ { \ return nr_reg_set(name, TYPE, &data); \ } NRREGLOCALSET(nr_reg_local_set_char, NR_REG_TYPE_CHAR, char) NRREGLOCALSET(nr_reg_local_set_uchar, NR_REG_TYPE_UCHAR, UCHAR) NRREGLOCALSET(nr_reg_local_set_int2, NR_REG_TYPE_INT2, INT2) NRREGLOCALSET(nr_reg_local_set_uint2, NR_REG_TYPE_UINT2, UINT2) NRREGLOCALSET(nr_reg_local_set_int4, NR_REG_TYPE_INT4, INT4) NRREGLOCALSET(nr_reg_local_set_uint4, NR_REG_TYPE_UINT4, UINT4) NRREGLOCALSET(nr_reg_local_set_int8, NR_REG_TYPE_INT8, INT8) NRREGLOCALSET(nr_reg_local_set_uint8, NR_REG_TYPE_UINT8, UINT8) NRREGLOCALSET(nr_reg_local_set_double, NR_REG_TYPE_DOUBLE, double) int nr_reg_local_set_registry(NR_registry name) { return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0); } int nr_reg_local_set_bytes(NR_registry name, unsigned char *data, size_t length) { return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length); } int nr_reg_local_set_string(NR_registry name, char *data) { return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1); } int nr_reg_local_del(NR_registry name) { int r, _status; if ((r=nr_reg_is_valid(name))) ABORT(r); /* delete from NR_registry */ if ((r=nr_reg_local_iter(name, nr_reg_local_iter_delete, 0))) ABORT(r); if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_DELETE))) ABORT(r); /* if deleting from the root, re-insert the root */ if (! strcasecmp(name, NR_TOP_LEVEL_REGISTRY)) { if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY))) ABORT(r); } _status=0; abort: r_log(NR_LOG_REGISTRY, (_status ? LOG_INFO : LOG_INFO), "delete of '%s' %s", name, (_status ? "FAILED" : "succeeded")); return(_status); } int nr_reg_local_get_child_count(NR_registry parent, size_t *count) { int r, _status; nr_registry_node *ignore1; int ignore2; if ((r=nr_reg_is_valid(parent))) ABORT(r); /* test to see whether it is present */ if ((r=nr_reg_fetch_node(parent, NR_REG_TYPE_REGISTRY, &ignore1, &ignore2))) ABORT(r); /* sanity check that there isn't any memory to free */ assert(ignore2 == 0); *count = 0; if ((r=nr_reg_local_iter(parent, nr_reg_local_count_children, count))) ABORT(r); _status=0; abort: return(_status); } int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length) { int r, _status; nr_reg_find_children_arg arg; if ((r=nr_reg_is_valid(parent))) ABORT(r); arg.children = data; arg.size = size; arg.length = 0; if ((r=nr_reg_local_iter(parent, nr_reg_local_find_children, (void*)&arg))) { if (r == R_INTERRUPTED) ABORT(R_BAD_ARGS); else ABORT(r); } assert(sizeof(*arg.children) == sizeof(NR_registry)); qsort(arg.children, arg.length, sizeof(*arg.children), (void*)strcasecmp); *length = arg.length; _status = 0; abort: return(_status); } int nr_reg_local_fin(NR_registry name) { int r, _status; if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_FINAL))) ABORT(r); _status=0; abort: return(_status); } int nr_reg_local_dump(int sorted) { int r, _status; if ((r=nr_reg_local_iter(NR_TOP_LEVEL_REGISTRY, nr_reg_local_dump_print, 0))) ABORT(r); _status=0; abort: return(_status); } static nr_registry_module_vtbl nr_reg_local_vtbl = { nr_reg_local_init, nr_reg_local_get_char, nr_reg_local_get_uchar, nr_reg_local_get_int2, nr_reg_local_get_uint2, nr_reg_local_get_int4, nr_reg_local_get_uint4, nr_reg_local_get_int8, nr_reg_local_get_uint8, nr_reg_local_get_double, nr_reg_local_get_registry, nr_reg_local_get_bytes, nr_reg_local_get_string, nr_reg_local_get_length, nr_reg_local_get_type, nr_reg_local_set_char, nr_reg_local_set_uchar, nr_reg_local_set_int2, nr_reg_local_set_uint2, nr_reg_local_set_int4, nr_reg_local_set_uint4, nr_reg_local_set_int8, nr_reg_local_set_uint8, nr_reg_local_set_double, nr_reg_local_set_registry, nr_reg_local_set_bytes, nr_reg_local_set_string, nr_reg_local_del, nr_reg_local_get_child_count, nr_reg_local_get_children, nr_reg_local_fin, nr_reg_local_dump }; static nr_registry_module nr_reg_local_module = { 0, &nr_reg_local_vtbl }; void *NR_REG_MODE_LOCAL = &nr_reg_local_module;