/* * * registry.c * * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.c,v $ * $Revision: 1.6 $ * $Date: 2007/11/21 00:09:12 $ * * 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 _MSC_VER #include #include #include #endif #ifdef OPENSSL #include #endif #include #include #include "registry.h" #include "registry_int.h" #include "r_assoc.h" #include "r_log.h" #include "r_errors.h" #include "r_macros.h" static int reg_initted = 0; /* must be in the order the types are numbered */ static const char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" }; int NR_LOG_REGISTRY=0; NR_registry_name NR_TOP_LEVEL_REGISTRY = ""; int NR_reg_init() { int r, _status; #ifdef SANITY_CHECKS NR_registry registry; #endif if (reg_initted) { return(0); } reg_initted = 1; if ((r=nr_reg_local_init())) ABORT(r); #ifdef SANITY_CHECKS if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry))) ABORT(r); assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0); #endif r_log_init(); r_log_register("registry",&NR_LOG_REGISTRY); _status=0; abort: r_log(NR_LOG_REGISTRY, (_status ? LOG_ERR : LOG_INFO), (_status ? "Couldn't initialize registry" : "Initialized registry")); return(_status); } int NR_reg_initted(void) { return reg_initted!=0; } #define NRREGGET(func, TYPE, type) \ int \ func(NR_registry_name name, type *out) \ { \ return nr_reg_get(name, TYPE, out); \ } NRREGGET(NR_reg_get_char, NR_REG_TYPE_CHAR, char) NRREGGET(NR_reg_get_uchar, NR_REG_TYPE_UCHAR, UCHAR) NRREGGET(NR_reg_get_uint2, NR_REG_TYPE_UINT2, UINT2) NRREGGET(NR_reg_get_int4, NR_REG_TYPE_INT4, INT4) NRREGGET(NR_reg_get_uint4, NR_REG_TYPE_UINT4, UINT4) NRREGGET(NR_reg_get_uint8, NR_REG_TYPE_UINT8, UINT8) NRREGGET(NR_reg_get_double, NR_REG_TYPE_DOUBLE, double) int NR_reg_get_registry(NR_registry_name 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, (nr_registry_node**)&node, &free_node))) ABORT(r); strncpy(out, name, sizeof(NR_registry)); _status=0; abort: if (free_node) RFREE(node); return(_status); } int NR_reg_get_bytes(NR_registry_name 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_get_string(NR_registry_name name, char *out, size_t size) { return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0); } int NR_reg_get_length(NR_registry_name name, size_t *length) { return nr_reg_local_get_length(name, length); } #define NRREGSET(func, TYPE, type) \ int \ func(NR_registry_name name, type data) \ { \ return nr_reg_set(name, TYPE, &data); \ } NRREGSET(NR_reg_set_char, NR_REG_TYPE_CHAR, char) NRREGSET(NR_reg_set_uchar, NR_REG_TYPE_UCHAR, UCHAR) NRREGSET(NR_reg_set_int4, NR_REG_TYPE_INT4, INT4) NRREGSET(NR_reg_set_uint4, NR_REG_TYPE_UINT4, UINT4) int NR_reg_set_string(NR_registry_name name, const char *data) { return nr_reg_set_array(name, NR_REG_TYPE_STRING, (const UCHAR*)data, strlen(data)+1); } int NR_reg_set_registry(NR_registry_name name) { return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0); } int NR_reg_set_bytes(NR_registry_name name, const unsigned char *data, size_t length) { return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length); } int NR_reg_del(NR_registry_name name) { return nr_reg_local_del(name); } int NR_reg_get_child_count(NR_registry_name parent, unsigned int *count) { assert(sizeof(count) == sizeof(size_t)); return nr_reg_local_get_child_count(parent, (size_t*)count); } int NR_reg_get_child_registry(NR_registry_name parent, unsigned int i, NR_registry child) { int r, _status; size_t count; NR_registry *children=0; if ((r=nr_reg_local_get_child_count(parent, &count))) ABORT(r); if (i >= count) ABORT(R_NOT_FOUND); else { count++; children = R_NEW_CNT(NR_registry, count); if (!children) ABORT(R_NO_MEMORY); if ((r=nr_reg_local_get_children(parent, children, count, &count))) ABORT(r); if (i >= count) ABORT(R_NOT_FOUND); strncpy(child, children[i], sizeof(NR_registry)); } _status=0; abort: RFREE(children); return(_status); } // convenience methods, call RFREE on the returned data int NR_reg_alloc_data(NR_registry_name name, Data *data) { int r, _status; size_t length; UCHAR *tmp = 0; size_t sanity_check; if ((r=NR_reg_get_length(name, &length))) ABORT(r); if (!(tmp = (UCHAR*)RMALLOC(length))) ABORT(R_NO_MEMORY); if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check))) ABORT(r); assert(length == sanity_check); data->len = length; data->data = tmp; _status=0; abort: if (_status) { if (tmp) RFREE(tmp); } return(_status); } int NR_reg_alloc_string(NR_registry_name name, char **data) { int r, _status; size_t length; char *tmp = 0; if ((r=NR_reg_get_length(name, &length))) ABORT(r); if (!(tmp = (char*)RMALLOC(length+1))) ABORT(R_NO_MEMORY); if ((r=NR_reg_get_string(name, tmp, length+1))) ABORT(r); assert(length == strlen(tmp)); *data = tmp; _status=0; abort: if (_status) { if (tmp) RFREE(tmp); } return(_status); } const char * nr_reg_type_name(int type) { if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY)) return(NULL); return(typenames[type]); } /* More convenience functions: the same as their parents but they take a prefix and a suffix */ #define NRGET2(func, type, get) \ int \ func(NR_registry_name parent, const char *child, type *out) \ { \ int r, _status; \ NR_registry registry; \ \ if ((r = NR_reg_make_registry(parent, child, registry))) \ ABORT(r); \ \ if ((r = get(registry, out))) { \ ABORT(r); \ } \ \ _status = 0; \ abort: \ return (_status); \ } NRGET2(NR_reg_get2_char, char, NR_reg_get_char) NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar) NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2) NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string) NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data) /* More convenience functions: the same as their parents but they take a prefix and a suffix */ #define NRSET2(func, type, set) \ int \ func(NR_registry_name parent, const char *child, type in) \ { \ int r, _status; \ NR_registry registry; \ \ if ((r = NR_reg_make_registry(parent, child, registry))) \ ABORT(r); \ \ if ((r = set(registry, in))) { \ ABORT(r); \ } \ \ _status = 0; \ abort: \ return (_status); \ } NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar) NRSET2(NR_reg_set2_string, const char*, NR_reg_set_string) /* requires parent already in legal form */ int NR_reg_make_registry(NR_registry_name parent, const char *child, NR_registry out) { int r, _status; size_t plen; size_t clen; char *c = 0; size_t i; if ((r=nr_reg_is_valid(parent))) ABORT(r); if (*child == '.') ABORT(R_BAD_ARGS); clen = strlen(child); if (!clen) ABORT(R_BAD_ARGS); plen = strlen(parent); if ((plen + clen + 2) > sizeof(NR_registry)) ABORT(R_BAD_ARGS); if (out != parent) strcpy(out, parent); c = &(out[plen]); if (parent[0] != '\0') { *c = '.'; ++c; } for (i = 0; i < clen; ++i, ++c) { *c = child[i]; if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c)) *c = '_'; } *c = '\0'; _status = 0; abort: return _status; }