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.

     1 /*
     2  *
     3  *    registry.c
     4  *
     5  *    $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_local.c,v $
     6  *    $Revision: 1.4 $
     7  *    $Date: 2007/11/21 00:09:13 $
     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  */
    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 "registry.h"
    57 #include "registry_int.h"
    58 #include "registry_vtbl.h"
    59 #include "r_assoc.h"
    60 #include "nr_common.h"
    61 #include "r_log.h"
    62 #include "r_errors.h"
    63 #include "r_macros.h"
    65 /* if C were an object-oriented language, nr_scalar_registry_node and
    66  * nr_array_registry_node would subclass nr_registry_node, but it isn't
    67  * object-oriented language, so this is used in cases where the pointer
    68  * could be of either type */
    69 typedef struct nr_registry_node_ {
    70     unsigned char  type;
    71 } nr_registry_node;
    73 typedef struct nr_scalar_registry_node_ {
    74     unsigned char  type;
    75     union {
    76         char          _char;
    77         UCHAR         _uchar;
    78         INT2       _nr_int2;
    79         UINT2      _nr_uint2;
    80         INT4       _nr_int4;
    81         UINT4      _nr_uint4;
    82         INT8       _nr_int8;
    83         UINT8      _nr_uint8;
    84         double        _double;
    85     } scalar;
    86 } nr_scalar_registry_node;
    88 /* string, bytes */
    89 typedef struct nr_array_registry_node_ {
    90     unsigned char    type;
    91     struct {
    92         unsigned int     length;
    93         unsigned char    data[1];
    94     } array;
    95 } nr_array_registry_node;
    97 static int nr_reg_local_init(nr_registry_module *me);
    98 static int nr_reg_local_get_char(NR_registry name, char *data);
    99 static int nr_reg_local_get_uchar(NR_registry name, UCHAR *data);
   100 static int nr_reg_local_get_int2(NR_registry name, INT2 *data);
   101 static int nr_reg_local_get_uint2(NR_registry name, UINT2 *data);
   102 static int nr_reg_local_get_int4(NR_registry name, INT4 *data);
   103 static int nr_reg_local_get_uint4(NR_registry name, UINT4 *data);
   104 static int nr_reg_local_get_int8(NR_registry name, INT8 *data);
   105 static int nr_reg_local_get_uint8(NR_registry name, UINT8 *data);
   106 static int nr_reg_local_get_double(NR_registry name, double *data);
   107 static int nr_reg_local_get_registry(NR_registry name, NR_registry data);
   108 static int nr_reg_local_get_bytes(NR_registry name, UCHAR *data, size_t size, size_t *length);
   109 static int nr_reg_local_get_string(NR_registry name, char *data, size_t size);
   110 static int nr_reg_local_get_length(NR_registry name, size_t *len);
   111 static int nr_reg_local_get_type(NR_registry name, NR_registry_type type);
   112 static int nr_reg_local_set_char(NR_registry name, char data);
   113 static int nr_reg_local_set_uchar(NR_registry name, UCHAR data);
   114 static int nr_reg_local_set_int2(NR_registry name, INT2 data);
   115 static int nr_reg_local_set_uint2(NR_registry name, UINT2 data);
   116 static int nr_reg_local_set_int4(NR_registry name, INT4 data);
   117 static int nr_reg_local_set_uint4(NR_registry name, UINT4 data);
   118 static int nr_reg_local_set_int8(NR_registry name, INT8 data);
   119 static int nr_reg_local_set_uint8(NR_registry name, UINT8 data);
   120 static int nr_reg_local_set_double(NR_registry name, double data);
   121 static int nr_reg_local_set_registry(NR_registry name);
   122 static int nr_reg_local_set_bytes(NR_registry name, UCHAR *data, size_t length);
   123 static int nr_reg_local_set_string(NR_registry name, char *data);
   124 static int nr_reg_local_del(NR_registry name);
   125 static int nr_reg_local_get_child_count(NR_registry parent, size_t *count);
   126 static int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length);
   127 static int nr_reg_local_fin(NR_registry name);
   128 static int nr_reg_local_dump(int sorted);
   129 static int nr_reg_insert_node(char *name, void *node);
   130 static int nr_reg_change_node(char *name, void *node, void *old);
   131 static int nr_reg_get(char *name, int type, void *out);
   132 static int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out);
   133 static int nr_reg_get_array(char *name, unsigned char type, UCHAR *out, size_t size, size_t *length);
   134 static int nr_reg_set(char *name, int type, void *data);
   135 static int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length);
   136 static int nr_reg_set_parent_registries(char *name);
   138 /* make these static OLD_REGISTRY */
   139 #if 0
   140 static int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node);
   141 static char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit);
   142 #else
   143 int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node);
   144 char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit);
   145 #endif
   146 static int nr_reg_rfree(void *ptr);
   147 #if 0  /* Unused currently */
   148 static int nr_reg_noop(void *ptr);
   149 #endif
   150 static int nr_reg_compute_length(char *name, nr_registry_node *node, size_t *length);
   151 char *nr_reg_action_name(int action);
   153 /* the registry, containing mappings like "foo.bar.baz" to registry
   154  * nodes, which are either of type nr_scalar_registry_node or
   155  * nr_array_registry_node */
   156 static r_assoc     *nr_registry = 0;
   158 #if 0  /* Unused currently */
   159 static nr_array_registry_node nr_top_level_node;
   160 #endif
   162 typedef struct nr_reg_find_children_arg_ {
   163     size_t         size;
   164     NR_registry   *children;
   165     size_t         length;
   166 } nr_reg_find_children_arg;
   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);
   169 static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
   170 static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
   171 static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
   172 static int nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
   176 int
   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)
   178 {
   179     int r, _status;
   180     r_assoc_iterator iter;
   181     char *name;
   182     int namel;
   183     nr_registry_node *node;
   184     int prefixl;
   186     if (prefix == 0)
   187         ABORT(R_INTERNAL);
   189     if ((r=r_assoc_init_iter(nr_registry, &iter)))
   190         ABORT(r);
   192     prefixl = strlen(prefix);
   194     for (;;) {
   195       if ((r=r_assoc_iter(&iter, (void*)&name, &namel, (void*)&node))) {
   196         if (r == R_EOD)
   197           break;
   198         else
   199           ABORT(r);
   200       }
   202       /* subtract to remove the '\0' character from the string length */
   203       --namel;
   205       /* sanity check that the name is null-terminated */
   206       assert(namel >= 0);
   207       assert(name[namel] == '\0');
   209       if (namel < 0 || name[namel] != '\0' || node == 0)
   210           break;
   212       /* 3 cases where action will be called:
   213        *   1) prefix == ""
   214        *   2) prefix == name
   215        *   3) name == prefix + '.'
   216        */
   217       if (prefixl == 0
   218        || ((namel == prefixl || (namel > prefixl && name[prefixl] == '.'))
   219          && !strncmp(prefix, name, prefixl))) {
   220         if ((r=action(ptr, &iter, prefix, name, node)))
   221           ABORT(r);
   222       }
   223     }
   225     _status=0;
   226   abort:
   228     return(_status);
   229 }
   231 int
   232 nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
   233 {
   234     int r, _status;
   236     if ((r=r_assoc_iter_delete(iter)))
   237       ABORT(r);
   239     _status=0;
   240   abort:
   241     return(_status);
   242 }
   244 int
   245 nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
   246 {
   247   int _status;
   248   int prefixl = strlen(prefix);
   249   char *dot;
   250   nr_reg_find_children_arg *arg = (void*)ptr;
   252   assert(sizeof(*(arg->children)) == sizeof(NR_registry));
   254   /* only grovel through immediate children */
   255   if (prefixl == 0 || name[prefixl] == '.') {
   256     if (name[prefixl] != '\0') {
   257       dot = strchr(&name[prefixl+1], '.');
   258       if (dot == 0) {
   259         strncpy(arg->children[arg->length], name, sizeof(NR_registry)-1);
   260         ++arg->length;
   262         /* only grab as many as there are room for */
   263         if (arg->length >= arg->size)
   264           ABORT(R_INTERRUPTED);
   265       }
   266     }
   267   }
   269   _status = 0;
   270  abort:
   271   return _status;
   272 }
   274 int
   275 nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
   276 {
   277   int prefixl = strlen(prefix);
   278   char *dot;
   280   /* only count children */
   281   if (name[prefixl] == '.') {
   282     dot = strchr(&name[prefixl+1], '.');
   283     if (dot == 0)
   284       ++(*(unsigned int *)ptr);
   285   }
   286   else if (name[0] != '\0') {
   287     if (prefixl == 0)
   288       ++(*(unsigned int *)ptr);
   289   }
   291   return 0;
   292 }
   294 int
   295 nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
   296 {
   297     int _status;
   298     int freeit = 0;
   299     char *data;
   301     /* only print leaf nodes */
   302     if (node->type != NR_REG_TYPE_REGISTRY) {
   303       data = nr_reg_alloc_node_data(name, node, &freeit);
   304       if (ptr)
   305         fprintf((FILE*)ptr, "%s: %s\n", name, data);
   306       else
   307         r_log(NR_LOG_REGISTRY, LOG_INFO, "%s: %s", name, data);
   308       if (freeit)
   309         RFREE(data);
   310     }
   312     _status=0;
   313   //abort:
   314     return(_status);
   315 }
   318 #if 0  /* Unused currently */
   319 int
   320 nr_reg_noop(void *ptr)
   321 {
   322     return 0;
   323 }
   324 #endif
   326 int
   327 nr_reg_rfree(void *ptr)
   328 {
   329     RFREE(ptr);
   330     return 0;
   331 }
   333 int
   334 nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node)
   335 {
   336     int r, _status;
   338     if ((r=nr_reg_is_valid(name)))
   339       ABORT(r);
   341     *node = 0;
   342     *free_node = 0;
   344     if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)node)))
   345       ABORT(r);
   347     if ((*node)->type != type)
   348       ABORT(R_FAILED);
   350     _status=0;
   351   abort:
   352     if (_status) {
   353         if (*node)
   354             r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s'), found '%s' instead",
   355               name, nr_reg_type_name(type), nr_reg_type_name((*node)->type));
   356         else
   357             r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s')",
   358               name, nr_reg_type_name(type));
   359     }
   360     else {
   361         r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Fetched node '%s' ('%s')",
   362               name, nr_reg_type_name(type));
   363     }
   364     return(_status);
   365 }
   367 int
   368 nr_reg_insert_node(char *name, void *node)
   369 {
   370     int r, _status;
   372     if ((r=nr_reg_is_valid(name)))
   373       ABORT(r);
   375     /* since the registry application is not multi-threaded, a node being
   376      * inserted should always be a new node because the registry app must
   377      * have looked for a node with this key but not found it, so it is
   378      * being created/inserted now using R_ASSOC_NEW */
   379     if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_NEW)))
   380       ABORT(r);
   382     if ((r=nr_reg_set_parent_registries(name)))
   383       ABORT(r);
   385     if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_ADD)))
   386       ABORT(r);
   388     _status=0;
   389   abort:
   390     if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) {
   391       int freeit;
   392       char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit);
   393       r_log(NR_LOG_REGISTRY, LOG_INFO,
   394              "insert '%s' (%s) %s: %s", name,
   395              nr_reg_type_name(((nr_registry_node*)node)->type),
   396              (_status ? "FAILED" : "succeeded"), data);
   397       if (freeit)
   398         RFREE(data);
   399     }
   400     return(_status);
   401 }
   403 int
   404 nr_reg_change_node(char *name, void *node, void *old)
   405 {
   406     int r, _status;
   408     if ((r=nr_reg_is_valid(name)))
   409       ABORT(r);
   411     if (old != node) {
   412         if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_REPLACE)))
   413           ABORT(r);
   414     }
   416     if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_CHANGE)))
   417       ABORT(r);
   419     _status=0;
   420   abort:
   421     if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) {
   422       int freeit;
   423       char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit);
   424       r_log(NR_LOG_REGISTRY, LOG_INFO,
   425              "change '%s' (%s) %s: %s", name,
   426              nr_reg_type_name(((nr_registry_node*)node)->type),
   427              (_status ? "FAILED" : "succeeded"), data);
   428       if (freeit)
   429         RFREE(data);
   430     }
   431     return(_status);
   432 }
   434 char *
   435 nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit)
   436 {
   437     char *s = 0;
   438     int len;
   439     int alloc = 0;
   440     unsigned int i;
   442     *freeit = 0;
   444     switch (node->type) {
   445     default:
   446       alloc = 100;    /* plenty of room for any of the scalar types */
   447       break;
   448     case NR_REG_TYPE_REGISTRY:
   449       alloc = strlen(name) + 1;
   450       break;
   451     case NR_REG_TYPE_BYTES:
   452       alloc = (2 * ((nr_array_registry_node*)node)->array.length) + 1;
   453       break;
   454     case NR_REG_TYPE_STRING:
   455       alloc = 0;
   456       break;
   457     }
   459     if (alloc > 0) {
   460       s = (void*)RMALLOC(alloc);
   461       if (!s)
   462         return "";
   464       *freeit = 1;
   465     }
   467     len = alloc;
   469     switch (node->type) {
   470     case NR_REG_TYPE_CHAR:
   471       i = ((nr_scalar_registry_node*)node)->scalar._char;
   472       if (isprint(i) && ! isspace(i))
   473           snprintf(s, len, "%c", (char)i);
   474       else
   475           snprintf(s, len, "\\%03o", (char)i);
   476       break;
   477     case NR_REG_TYPE_UCHAR:
   478       snprintf(s, len, "0x%02x", ((nr_scalar_registry_node*)node)->scalar._uchar);
   479       break;
   480     case NR_REG_TYPE_INT2:
   481       snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int2);
   482       break;
   483     case NR_REG_TYPE_UINT2:
   484       snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint2);
   485       break;
   486     case NR_REG_TYPE_INT4:
   487       snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int4);
   488       break;
   489     case NR_REG_TYPE_UINT4:
   490       snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint4);
   491       break;
   492     case NR_REG_TYPE_INT8:
   493       snprintf(s, len, "%lld", ((nr_scalar_registry_node*)node)->scalar._nr_int8);
   494       break;
   495     case NR_REG_TYPE_UINT8:
   496       snprintf(s, len, "%llu", ((nr_scalar_registry_node*)node)->scalar._nr_uint8);
   497       break;
   498     case NR_REG_TYPE_DOUBLE:
   499       snprintf(s, len, "%#f", ((nr_scalar_registry_node*)node)->scalar._double);
   500       break;
   501     case NR_REG_TYPE_REGISTRY:
   502       snprintf(s, len, "%s", name);
   503       break;
   504     case NR_REG_TYPE_BYTES:
   505       for (i = 0; i < ((nr_array_registry_node*)node)->array.length; ++i) {
   506         sprintf(&s[2*i], "%02x", ((nr_array_registry_node*)node)->array.data[i]);
   507       }
   508       break;
   509     case NR_REG_TYPE_STRING:
   510       s = (char*)((nr_array_registry_node*)node)->array.data;
   511       break;
   512     default:
   513       assert(0); /* bad value */
   514       *freeit = 0;
   515       s = "";
   516       break;
   517     }
   519     return s;
   520 }
   522 int
   523 nr_reg_get(char *name, int type, void *out)
   524 {
   525     int r, _status;
   526     nr_scalar_registry_node *node = 0;
   527     int free_node = 0;
   529     if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
   530       ABORT(r);
   532     if ((r=nr_reg_get_data(name, node, out)))
   533       ABORT(r);
   535     _status=0;
   536   abort:
   537     if (free_node) RFREE(node);
   538     return(_status);
   539 }
   541 int
   542 nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out)
   543 {
   544     int _status;
   546     switch (node->type) {
   547     case NR_REG_TYPE_CHAR:
   548       *(char*)out = node->scalar._char;
   549       break;
   550     case NR_REG_TYPE_UCHAR:
   551       *(UCHAR*)out = node->scalar._uchar;
   552       break;
   553     case NR_REG_TYPE_INT2:
   554       *(INT2*)out = node->scalar._nr_int2;
   555       break;
   556     case NR_REG_TYPE_UINT2:
   557       *(UINT2*)out = node->scalar._nr_uint2;
   558       break;
   559     case NR_REG_TYPE_INT4:
   560       *(INT4*)out = node->scalar._nr_int4;
   561       break;
   562     case NR_REG_TYPE_UINT4:
   563       *(UINT4*)out = node->scalar._nr_uint4;
   564       break;
   565     case NR_REG_TYPE_INT8:
   566       *(INT8*)out = node->scalar._nr_int8;
   567       break;
   568     case NR_REG_TYPE_UINT8:
   569       *(UINT8*)out = node->scalar._nr_uint8;
   570       break;
   571     case NR_REG_TYPE_DOUBLE:
   572       *(double*)out = node->scalar._double;
   573       break;
   574     default:
   575       ABORT(R_INTERNAL);
   576       break;
   577     }
   579     _status=0;
   580   abort:
   581     return(_status);
   582 }
   584 int
   585 nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size, size_t *length)
   586 {
   587     int r, _status;
   588     nr_array_registry_node *node = 0;
   589     int free_node = 0;
   591     if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
   592       ABORT(r);
   594     if (size < node->array.length)
   595       ABORT(R_BAD_ARGS);
   597     if (out != 0)
   598         memcpy(out, node->array.data, node->array.length);
   599     if (length != 0)
   600         *length = node->array.length;
   602     _status=0;
   603   abort:
   604     if (node && free_node) RFREE(node);
   605     return(_status);
   606 }
   608 int
   609 nr_reg_set(char *name, int type, void *data)
   610 {
   611     int r, _status;
   612     nr_scalar_registry_node *node = 0;
   613     int create_node = 0;
   614     int changed = 0;
   615     int free_node = 0;
   617     if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
   618       if (r == R_NOT_FOUND) {
   619         create_node = 1;
   620         free_node = 1;
   621       }
   622       else
   623         ABORT(r);
   625     if (create_node) {
   626       if (!(node=(void*)RCALLOC(sizeof(nr_scalar_registry_node))))
   627         ABORT(R_NO_MEMORY);
   629       node->type = type;
   630     }
   631     else {
   632       if (node->type != type)
   633         ABORT(R_BAD_ARGS);
   634     }
   636     switch (type) {
   637 #define CASE(TYPE, _name, type)                   \
   638     case TYPE:                                    \
   639       if (node->scalar._name != *(type*)data) {   \
   640         node->scalar._name = *(type*)data;        \
   641         if (! create_node)                        \
   642           changed = 1;                            \
   643       }                                           \
   644       break;
   645     CASE(NR_REG_TYPE_CHAR,       _char,       char)
   646     CASE(NR_REG_TYPE_UCHAR,      _uchar,      UCHAR)
   647     CASE(NR_REG_TYPE_INT2,    _nr_int2,    INT2)
   648     CASE(NR_REG_TYPE_UINT2,   _nr_uint2,   UINT2)
   649     CASE(NR_REG_TYPE_INT4,    _nr_int4,    INT4)
   650     CASE(NR_REG_TYPE_UINT4,   _nr_uint4,   UINT4)
   651     CASE(NR_REG_TYPE_INT8,    _nr_int8,    INT8)
   652     CASE(NR_REG_TYPE_UINT8,   _nr_uint8,   UINT8)
   653     CASE(NR_REG_TYPE_DOUBLE,     _double,     double)
   654 #undef CASE
   656     case NR_REG_TYPE_REGISTRY:
   657       /* do nothing */
   658       break;
   660     default:
   661       ABORT(R_INTERNAL);
   662       break;
   663     }
   665     if (create_node) {
   666       if ((r=nr_reg_insert_node(name, node)))
   667         ABORT(r);
   668       free_node = 0;
   669     }
   670     else {
   671       if (changed) {
   672         if ((r=nr_reg_change_node(name, node, node)))
   673           ABORT(r);
   674         free_node = 0;
   675       }
   676     }
   678     _status=0;
   679   abort:
   680     if (_status) {
   681       if (node && free_node) RFREE(node);
   682     }
   683     return(_status);
   684 }
   686 int
   687 nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length)
   688 {
   689     int r, _status;
   690     nr_array_registry_node *old = 0;
   691     nr_array_registry_node *node = 0;
   692     int free_node = 0;
   693     int added = 0;
   694     int changed = 0;
   696     if ((r=nr_reg_fetch_node(name, type, (void*)&old, &free_node))) {
   697         if (r != R_NOT_FOUND)
   698             ABORT(r);
   699     }
   700     else {
   701       assert(free_node == 0);
   702     }
   704     if (old) {
   705         if (old->type != type)
   706             ABORT(R_BAD_ARGS);
   708         if (old->array.length != length
   709          || memcmp(old->array.data, data, length)) {
   710             changed = 1;
   712             if (old->array.length < length) {
   713                 if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length)))
   714                     ABORT(R_NO_MEMORY);
   715             }
   716             else {
   717                 node = old;
   718             }
   719         }
   720     }
   721     else {
   722         if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length)))
   723             ABORT(R_NO_MEMORY);
   725         added = 1;
   726     }
   728     if (added || changed) {
   729         node->type = type;
   730         node->array.length = length;
   731         memcpy(node->array.data, data, length);
   732     }
   734     if (added) {
   735         if ((r=nr_reg_insert_node(name, node)))
   736             ABORT(r);
   737     }
   738     else if (changed) {
   739         if ((r=nr_reg_change_node(name, node, old)))
   740           ABORT(r);
   741     }
   743     _status=0;
   744   abort:
   745     return(_status);
   746 }
   748 int
   749 nr_reg_set_parent_registries(char *name)
   750 {
   751     int r, _status;
   752     char *parent = 0;
   753     char *dot;
   755     if ((parent = r_strdup(name)) == 0)
   756       ABORT(R_NO_MEMORY);
   758     if ((dot = strrchr(parent, '.')) != 0) {
   759       *dot = '\0';
   760       if ((r=NR_reg_set_registry(parent)))
   761         ABORT(r);
   762     }
   764     _status=0;
   765   abort:
   766     if (parent) RFREE(parent);
   767     return(_status);
   768 }
   774 /* NON-STATIC METHODS */
   776 int
   777 nr_reg_is_valid(NR_registry name)
   778 {
   779     int _status;
   780     unsigned int length;
   781     unsigned int i;
   783     if (name == 0)
   784       ABORT(R_BAD_ARGS);
   786     /* make sure the key is null-terminated */
   787     if (memchr(name, '\0', sizeof(NR_registry)) == 0)
   788       ABORT(R_BAD_ARGS);
   790     length = strlen(name);
   792     /* cannot begin or end with a period */
   793     if (name[0] == '.')
   794       ABORT(R_BAD_ARGS);
   795     if (strlen(name) > 0 && name[length-1] == '.')
   796       ABORT(R_BAD_ARGS);
   798     /* all characters cannot be space, and must be printable and not / */
   799     for (i = 0; i < length; ++i) {
   800       if (isspace(name[i]) || ! (isprint(name[i]) || name[i] == '/'))
   801         ABORT(R_BAD_ARGS);
   802     }
   804     _status=0;
   805   abort:
   806     if (_status) {
   807       r_log(NR_LOG_REGISTRY, LOG_DEBUG, "invalid name '%s'", name);
   808     }
   809     return(_status);
   810 }
   813 int
   814 nr_reg_compute_length(char *name, nr_registry_node *in, size_t *length)
   815 {
   816     int _status;
   817     nr_array_registry_node *node = (nr_array_registry_node*)in;
   819     switch (node->type) {
   820     case NR_REG_TYPE_STRING:
   821       *length = node->array.length - 1;
   822       break;
   823     case NR_REG_TYPE_BYTES:
   824       *length = node->array.length;
   825       break;
   826     case NR_REG_TYPE_CHAR:
   827       *length = sizeof(char);
   828       break;
   829     case NR_REG_TYPE_UCHAR:
   830       *length = sizeof(UCHAR);
   831       break;
   832     case NR_REG_TYPE_INT2:
   833     case NR_REG_TYPE_UINT2:
   834       *length = 2;
   835       break;
   836     case NR_REG_TYPE_INT4:
   837     case NR_REG_TYPE_UINT4:
   838       *length = 4;
   839       break;
   840     case NR_REG_TYPE_INT8:
   841     case NR_REG_TYPE_UINT8:
   842       *length = 8;
   843       break;
   844     case NR_REG_TYPE_DOUBLE:
   845       *length = sizeof(double);
   846       break;
   847     case NR_REG_TYPE_REGISTRY:
   848       *length = strlen(name);
   849       break;
   850     default:
   851       ABORT(R_INTERNAL);
   852       break;
   853     }
   855     _status=0;
   856   abort:
   857     return(_status);
   858 }
   861 /* VTBL METHODS */
   863 int
   864 nr_reg_local_init(nr_registry_module *me)
   865 {
   866     int r, _status;
   868     if (nr_registry == 0) {
   869       if ((r=r_assoc_create(&nr_registry, r_assoc_crc32_hash_compute, 12)))
   870         ABORT(r);
   872       if ((r=nr_reg_cb_init()))
   873             ABORT(r);
   875       /* make sure NR_TOP_LEVEL_REGISTRY always exists */
   876       if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY)))
   877           ABORT(r);
   878     }
   880     _status=0;
   881   abort:
   882     return(_status);
   883 }
   885 #define NRREGGET(func, TYPE, type)                                  \
   886 int                                                                 \
   887 func(NR_registry name, type *out)                                   \
   888 {                                                                   \
   889     return nr_reg_get(name, TYPE, out);                             \
   890 }
   892 NRREGGET(nr_reg_local_get_char,     NR_REG_TYPE_CHAR,     char)
   893 NRREGGET(nr_reg_local_get_uchar,    NR_REG_TYPE_UCHAR,    UCHAR)
   894 NRREGGET(nr_reg_local_get_int2,     NR_REG_TYPE_INT2,     INT2)
   895 NRREGGET(nr_reg_local_get_uint2,    NR_REG_TYPE_UINT2,    UINT2)
   896 NRREGGET(nr_reg_local_get_int4,     NR_REG_TYPE_INT4,     INT4)
   897 NRREGGET(nr_reg_local_get_uint4,    NR_REG_TYPE_UINT4,    UINT4)
   898 NRREGGET(nr_reg_local_get_int8,     NR_REG_TYPE_INT8,     INT8)
   899 NRREGGET(nr_reg_local_get_uint8,    NR_REG_TYPE_UINT8,    UINT8)
   900 NRREGGET(nr_reg_local_get_double,   NR_REG_TYPE_DOUBLE,   double)
   902 int
   903 nr_reg_local_get_registry(NR_registry name, NR_registry out)
   904 {
   905     int r, _status;
   906     nr_scalar_registry_node *node = 0;
   907     int free_node = 0;
   909     if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node)))
   910       ABORT(r);
   912     strncpy(out, name, sizeof(NR_registry));
   914     _status=0;
   915   abort:
   916     if (free_node) RFREE(node);
   917     return(_status);
   919 }
   921 int
   922 nr_reg_local_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
   923 {
   924     return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length);
   925 }
   927 int
   928 nr_reg_local_get_string(NR_registry name, char *out, size_t size)
   929 {
   930     return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0);
   931 }
   933 int
   934 nr_reg_local_get_length(NR_registry name, size_t *length)
   935 {
   936     int r, _status;
   937     nr_registry_node *node = 0;
   939     if ((r=nr_reg_is_valid(name)))
   940       ABORT(r);
   942     if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node)))
   943       ABORT(r);
   945     if ((r=nr_reg_compute_length(name, node, length)))
   946       ABORT(r);
   948     _status=0;
   949   abort:
   950     return(_status);
   951 }
   953 int
   954 nr_reg_local_get_type(NR_registry name, NR_registry_type type)
   955 {
   956     int r, _status;
   957     nr_registry_node *node = 0;
   958     char *str;
   960     if ((r=nr_reg_is_valid(name)))
   961       ABORT(r);
   963     if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node)))
   964       ABORT(r);
   966     str = nr_reg_type_name(node->type);
   967     if (! str)
   968         ABORT(R_BAD_ARGS);
   970     strncpy(type, str, sizeof(NR_registry_type));
   972     _status=0;
   973   abort:
   974     return(_status);
   975 }
   978 #define NRREGSET(func, TYPE, type)                              \
   979 int                                                             \
   980 func(NR_registry name, type data)                               \
   981 {                                                               \
   982     return nr_reg_set(name, TYPE, &data);                       \
   983 }
   985 NRREGSET(nr_reg_local_set_char,     NR_REG_TYPE_CHAR,     char)
   986 NRREGSET(nr_reg_local_set_uchar,    NR_REG_TYPE_UCHAR,    UCHAR)
   987 NRREGSET(nr_reg_local_set_int2,     NR_REG_TYPE_INT2,     INT2)
   988 NRREGSET(nr_reg_local_set_uint2,    NR_REG_TYPE_UINT2,    UINT2)
   989 NRREGSET(nr_reg_local_set_int4,     NR_REG_TYPE_INT4,     INT4)
   990 NRREGSET(nr_reg_local_set_uint4,    NR_REG_TYPE_UINT4,    UINT4)
   991 NRREGSET(nr_reg_local_set_int8,     NR_REG_TYPE_INT8,     INT8)
   992 NRREGSET(nr_reg_local_set_uint8,    NR_REG_TYPE_UINT8,    UINT8)
   993 NRREGSET(nr_reg_local_set_double,   NR_REG_TYPE_DOUBLE,   double)
   995 int
   996 nr_reg_local_set_registry(NR_registry name)
   997 {
   998     return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0);
   999 }
  1001 int
  1002 nr_reg_local_set_bytes(NR_registry name, unsigned char *data, size_t length)
  1004     return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length);
  1007 int
  1008 nr_reg_local_set_string(NR_registry name, char *data)
  1010     return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1);
  1013 int
  1014 nr_reg_local_del(NR_registry name)
  1016     int r, _status;
  1018     if ((r=nr_reg_is_valid(name)))
  1019       ABORT(r);
  1021     /* delete from NR_registry */
  1022     if ((r=nr_reg_local_iter(name, nr_reg_local_iter_delete, 0)))
  1023       ABORT(r);
  1025     if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_DELETE)))
  1026       ABORT(r);
  1028     /* if deleting from the root, re-insert the root */
  1029     if (! strcasecmp(name, NR_TOP_LEVEL_REGISTRY)) {
  1030       if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY)))
  1031           ABORT(r);
  1034     _status=0;
  1035   abort:
  1036     r_log(NR_LOG_REGISTRY,
  1037           (_status ? LOG_INFO               :  LOG_INFO),
  1038           "delete of '%s' %s", name,
  1039           (_status ? "FAILED"               : "succeeded"));
  1040     return(_status);
  1043 int
  1044 nr_reg_local_get_child_count(char *parent, size_t *count)
  1046     int r, _status;
  1047     nr_registry_node *ignore1;
  1048     int ignore2;
  1051     if ((r=nr_reg_is_valid(parent)))
  1052       ABORT(r);
  1054     /* test to see whether it is present */
  1055     if ((r=nr_reg_fetch_node(parent, NR_REG_TYPE_REGISTRY, &ignore1, &ignore2)))
  1056       ABORT(r);
  1058     /* sanity check that there isn't any memory to free */
  1059     assert(ignore2 == 0);
  1061     *count = 0;
  1063     if ((r=nr_reg_local_iter(parent, nr_reg_local_count_children, count)))
  1064       ABORT(r);
  1066     _status=0;
  1067   abort:
  1068     return(_status);
  1071 int
  1072 nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length)
  1074     int r, _status;
  1075     nr_reg_find_children_arg arg;
  1077     if ((r=nr_reg_is_valid(parent)))
  1078       ABORT(r);
  1080     arg.children = data;
  1081     arg.size = size;
  1082     arg.length = 0;
  1084     if ((r=nr_reg_local_iter(parent, nr_reg_local_find_children, (void*)&arg))) {
  1085         if (r == R_INTERRUPTED)
  1086             ABORT(R_BAD_ARGS);
  1087         else
  1088             ABORT(r);
  1091     assert(sizeof(*arg.children) == sizeof(NR_registry));
  1092     qsort(arg.children, arg.length, sizeof(*arg.children), (void*)strcasecmp);
  1094     *length = arg.length;
  1096     _status = 0;
  1097   abort:
  1098     return(_status);
  1101 int
  1102 nr_reg_local_fin(NR_registry name)
  1104     int r, _status;
  1106     if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_FINAL)))
  1107       ABORT(r);
  1109     _status=0;
  1110   abort:
  1111     return(_status);
  1114 int
  1115 nr_reg_local_dump(int sorted)
  1117     int r, _status;
  1119     if ((r=nr_reg_local_iter(NR_TOP_LEVEL_REGISTRY, nr_reg_local_dump_print, 0)))
  1120       ABORT(r);
  1122     _status=0;
  1123   abort:
  1124     return(_status);
  1129 static nr_registry_module_vtbl nr_reg_local_vtbl = {
  1130     nr_reg_local_init,
  1131     nr_reg_local_get_char,
  1132     nr_reg_local_get_uchar,
  1133     nr_reg_local_get_int2,
  1134     nr_reg_local_get_uint2,
  1135     nr_reg_local_get_int4,
  1136     nr_reg_local_get_uint4,
  1137     nr_reg_local_get_int8,
  1138     nr_reg_local_get_uint8,
  1139     nr_reg_local_get_double,
  1140     nr_reg_local_get_registry,
  1141     nr_reg_local_get_bytes,
  1142     nr_reg_local_get_string,
  1143     nr_reg_local_get_length,
  1144     nr_reg_local_get_type,
  1145     nr_reg_local_set_char,
  1146     nr_reg_local_set_uchar,
  1147     nr_reg_local_set_int2,
  1148     nr_reg_local_set_uint2,
  1149     nr_reg_local_set_int4,
  1150     nr_reg_local_set_uint4,
  1151     nr_reg_local_set_int8,
  1152     nr_reg_local_set_uint8,
  1153     nr_reg_local_set_double,
  1154     nr_reg_local_set_registry,
  1155     nr_reg_local_set_bytes,
  1156     nr_reg_local_set_string,
  1157     nr_reg_local_del,
  1158     nr_reg_local_get_child_count,
  1159     nr_reg_local_get_children,
  1160     nr_reg_local_fin,
  1161     nr_reg_local_dump
  1162 };
  1164 static nr_registry_module nr_reg_local_module = { 0, &nr_reg_local_vtbl };
  1166 void *NR_REG_MODE_LOCAL = &nr_reg_local_module;

mercurial