media/mtransport/third_party/nrappkit/src/registry/registry.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.c,v $
michael@0 6 * $Revision: 1.6 $
michael@0 7 * $Date: 2007/11/21 00:09:12 $
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 _MSC_VER
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 #include "c2ru.h"
michael@0 65
michael@0 66 /* vtbl used to switch hit between local and remote invocations */
michael@0 67 static nr_registry_module *reg_vtbl = 0;
michael@0 68
michael@0 69 /* must be in the order the types are numbered */
michael@0 70 static char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" };
michael@0 71
michael@0 72 int NR_LOG_REGISTRY=0;
michael@0 73
michael@0 74 NR_registry NR_TOP_LEVEL_REGISTRY = "";
michael@0 75
michael@0 76 int
michael@0 77 NR_reg_init(void *mode)
michael@0 78 {
michael@0 79 int r, _status;
michael@0 80 nr_registry_module *module = (nr_registry_module*)mode;
michael@0 81 #ifdef SANITY_CHECKS
michael@0 82 NR_registry registry;
michael@0 83 #endif
michael@0 84
michael@0 85 if (reg_vtbl) {
michael@0 86 if (reg_vtbl != module) {
michael@0 87 r_log(LOG_GENERIC,LOG_ERR,"Can't reinitialize registry in different mode");
michael@0 88 ABORT(R_INTERNAL);
michael@0 89 }
michael@0 90
michael@0 91 return(0);
michael@0 92 }
michael@0 93
michael@0 94 reg_vtbl = module;
michael@0 95
michael@0 96 if ((r=reg_vtbl->vtbl->init(mode)))
michael@0 97 ABORT(r);
michael@0 98
michael@0 99 #ifdef SANITY_CHECKS
michael@0 100 if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry)))
michael@0 101 ABORT(r);
michael@0 102 assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0);
michael@0 103 #endif
michael@0 104
michael@0 105 r_log_init();
michael@0 106 r_log_register("registry",&NR_LOG_REGISTRY);
michael@0 107
michael@0 108 _status=0;
michael@0 109 abort:
michael@0 110 r_log(NR_LOG_REGISTRY,
michael@0 111 (_status ? LOG_ERR : LOG_INFO),
michael@0 112 (_status ? "Couldn't initialize registry" : "Initialized registry"));
michael@0 113 return(_status);
michael@0 114 }
michael@0 115
michael@0 116 int
michael@0 117 NR_reg_initted(void)
michael@0 118 {
michael@0 119 return reg_vtbl!=0;
michael@0 120 }
michael@0 121
michael@0 122 #define NRREGGET(func, method, type) \
michael@0 123 int \
michael@0 124 func(NR_registry name, type *out) \
michael@0 125 { \
michael@0 126 return reg_vtbl->vtbl->method(name, out); \
michael@0 127 }
michael@0 128
michael@0 129 NRREGGET(NR_reg_get_char, get_char, char)
michael@0 130 NRREGGET(NR_reg_get_uchar, get_uchar, UCHAR)
michael@0 131 NRREGGET(NR_reg_get_int2, get_int2, INT2)
michael@0 132 NRREGGET(NR_reg_get_uint2, get_uint2, UINT2)
michael@0 133 NRREGGET(NR_reg_get_int4, get_int4, INT4)
michael@0 134 NRREGGET(NR_reg_get_uint4, get_uint4, UINT4)
michael@0 135 NRREGGET(NR_reg_get_int8, get_int8, INT8)
michael@0 136 NRREGGET(NR_reg_get_uint8, get_uint8, UINT8)
michael@0 137 NRREGGET(NR_reg_get_double, get_double, double)
michael@0 138
michael@0 139 int
michael@0 140 NR_reg_get_registry(NR_registry name, NR_registry out)
michael@0 141 {
michael@0 142 return reg_vtbl->vtbl->get_registry(name, out);
michael@0 143 }
michael@0 144
michael@0 145 int
michael@0 146 NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
michael@0 147 {
michael@0 148 return reg_vtbl->vtbl->get_bytes(name, out, size, length);
michael@0 149 }
michael@0 150
michael@0 151 int
michael@0 152 NR_reg_get_string(NR_registry name, char *out, size_t size)
michael@0 153 {
michael@0 154 return reg_vtbl->vtbl->get_string(name, out, size);
michael@0 155 }
michael@0 156
michael@0 157 int
michael@0 158 NR_reg_get_length(NR_registry name, size_t *length)
michael@0 159 {
michael@0 160 return reg_vtbl->vtbl->get_length(name, length);
michael@0 161 }
michael@0 162
michael@0 163 int
michael@0 164 NR_reg_get_type(NR_registry name, NR_registry_type type)
michael@0 165 {
michael@0 166 return reg_vtbl->vtbl->get_type(name, type);
michael@0 167 }
michael@0 168
michael@0 169 #define NRREGSET(func, method, type) \
michael@0 170 int \
michael@0 171 func(NR_registry name, type data) \
michael@0 172 { \
michael@0 173 return reg_vtbl->vtbl->method(name, data); \
michael@0 174 }
michael@0 175
michael@0 176 NRREGSET(NR_reg_set_char, set_char, char)
michael@0 177 NRREGSET(NR_reg_set_uchar, set_uchar, UCHAR)
michael@0 178 NRREGSET(NR_reg_set_int2, set_int2, INT2)
michael@0 179 NRREGSET(NR_reg_set_uint2, set_uint2, UINT2)
michael@0 180 NRREGSET(NR_reg_set_int4, set_int4, INT4)
michael@0 181 NRREGSET(NR_reg_set_uint4, set_uint4, UINT4)
michael@0 182 NRREGSET(NR_reg_set_int8, set_int8, INT8)
michael@0 183 NRREGSET(NR_reg_set_uint8, set_uint8, UINT8)
michael@0 184 NRREGSET(NR_reg_set_double, set_double, double)
michael@0 185 NRREGSET(NR_reg_set_string, set_string, char*)
michael@0 186
michael@0 187 int
michael@0 188 NR_reg_set_registry(NR_registry name)
michael@0 189 {
michael@0 190 return reg_vtbl->vtbl->set_registry(name);
michael@0 191 }
michael@0 192
michael@0 193 int
michael@0 194 NR_reg_set_bytes(NR_registry name, unsigned char *data, size_t length)
michael@0 195 {
michael@0 196 return reg_vtbl->vtbl->set_bytes(name, data, length);
michael@0 197 }
michael@0 198
michael@0 199
michael@0 200 int
michael@0 201 NR_reg_del(NR_registry name)
michael@0 202 {
michael@0 203 return reg_vtbl->vtbl->del(name);
michael@0 204 }
michael@0 205
michael@0 206 int
michael@0 207 NR_reg_fin(NR_registry name)
michael@0 208 {
michael@0 209 return reg_vtbl->vtbl->fin(name);
michael@0 210 }
michael@0 211
michael@0 212 int
michael@0 213 NR_reg_get_child_count(char *parent, unsigned int *count)
michael@0 214 {
michael@0 215 assert(sizeof(count) == sizeof(size_t));
michael@0 216 return reg_vtbl->vtbl->get_child_count(parent, (size_t*)count);
michael@0 217 }
michael@0 218
michael@0 219 int
michael@0 220 NR_reg_get_child_registry(char *parent, unsigned int i, NR_registry child)
michael@0 221 {
michael@0 222 int r, _status;
michael@0 223 size_t count;
michael@0 224 NR_registry *children=0;
michael@0 225
michael@0 226 if ((r=reg_vtbl->vtbl->get_child_count(parent, &count)))
michael@0 227 ABORT(r);
michael@0 228
michael@0 229 if (i >= count)
michael@0 230 ABORT(R_NOT_FOUND);
michael@0 231 else {
michael@0 232 count++;
michael@0 233 children = (NR_registry *)RCALLOC(count * sizeof(NR_registry));
michael@0 234 if (!children)
michael@0 235 ABORT(R_NO_MEMORY);
michael@0 236
michael@0 237 if ((r=reg_vtbl->vtbl->get_children(parent, children, count, &count)))
michael@0 238 ABORT(r);
michael@0 239
michael@0 240 if (i >= count)
michael@0 241 ABORT(R_NOT_FOUND);
michael@0 242
michael@0 243 strncpy(child, children[i], sizeof(NR_registry));
michael@0 244 }
michael@0 245
michael@0 246 _status=0;
michael@0 247 abort:
michael@0 248 RFREE(children);
michael@0 249 return(_status);
michael@0 250 }
michael@0 251
michael@0 252 int
michael@0 253 NR_reg_get_children(NR_registry parent, NR_registry *children, size_t size, size_t *length)
michael@0 254 {
michael@0 255 return reg_vtbl->vtbl->get_children(parent, children, size, length);
michael@0 256 }
michael@0 257
michael@0 258 int
michael@0 259 NR_reg_dump()
michael@0 260 {
michael@0 261 int r, _status;
michael@0 262
michael@0 263 if ((r=reg_vtbl->vtbl->dump(0)))
michael@0 264 ABORT(r);
michael@0 265
michael@0 266 _status=0;
michael@0 267 abort:
michael@0 268 return(_status);
michael@0 269 }
michael@0 270
michael@0 271 // convenience methods, call RFREE on the returned data
michael@0 272 int
michael@0 273 NR_reg_alloc_data(NR_registry name, Data *data)
michael@0 274 {
michael@0 275 int r, _status;
michael@0 276 size_t length;
michael@0 277 UCHAR *tmp = 0;
michael@0 278 size_t sanity_check;
michael@0 279
michael@0 280 if ((r=NR_reg_get_length(name, &length)))
michael@0 281 ABORT(r);
michael@0 282
michael@0 283 if (!(tmp = (void*)RMALLOC(length)))
michael@0 284 ABORT(R_NO_MEMORY);
michael@0 285
michael@0 286 if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check)))
michael@0 287 ABORT(r);
michael@0 288
michael@0 289 assert(length == sanity_check);
michael@0 290
michael@0 291 data->len = length;
michael@0 292 data->data = tmp;
michael@0 293
michael@0 294 _status=0;
michael@0 295 abort:
michael@0 296 if (_status) {
michael@0 297 if (tmp) RFREE(tmp);
michael@0 298 }
michael@0 299 return(_status);
michael@0 300 }
michael@0 301
michael@0 302 int
michael@0 303 NR_reg_alloc_string(NR_registry name, char **data)
michael@0 304 {
michael@0 305 int r, _status;
michael@0 306 size_t length;
michael@0 307 char *tmp = 0;
michael@0 308
michael@0 309 if ((r=NR_reg_get_length(name, &length)))
michael@0 310 ABORT(r);
michael@0 311
michael@0 312 if (!(tmp = (void*)RMALLOC(length+1)))
michael@0 313 ABORT(R_NO_MEMORY);
michael@0 314
michael@0 315 if ((r=NR_reg_get_string(name, tmp, length+1)))
michael@0 316 ABORT(r);
michael@0 317
michael@0 318 assert(length == strlen(tmp));
michael@0 319
michael@0 320 *data = tmp;
michael@0 321
michael@0 322 _status=0;
michael@0 323 abort:
michael@0 324 if (_status) {
michael@0 325 if (tmp) RFREE(tmp);
michael@0 326 }
michael@0 327 return(_status);
michael@0 328 }
michael@0 329
michael@0 330
michael@0 331 char *
michael@0 332 nr_reg_type_name(int type)
michael@0 333 {
michael@0 334 if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY))
michael@0 335 return(NULL);
michael@0 336
michael@0 337 return(typenames[type]);
michael@0 338 }
michael@0 339
michael@0 340 int
michael@0 341 nr_reg_compute_type(char *typename, int *type)
michael@0 342 {
michael@0 343 int _status;
michael@0 344 int i;
michael@0 345
michael@0 346 #ifdef SANITY_CHECKS
michael@0 347 assert(!strcasecmp(typenames[NR_REG_TYPE_CHAR], "char"));
michael@0 348 assert(!strcasecmp(typenames[NR_REG_TYPE_UCHAR], "UCHAR"));
michael@0 349 assert(!strcasecmp(typenames[NR_REG_TYPE_INT2], "INT2"));
michael@0 350 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT2], "UINT2"));
michael@0 351 assert(!strcasecmp(typenames[NR_REG_TYPE_INT4], "INT4"));
michael@0 352 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT4], "UINT4"));
michael@0 353 assert(!strcasecmp(typenames[NR_REG_TYPE_INT8], "INT8"));
michael@0 354 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT8], "UINT8"));
michael@0 355 assert(!strcasecmp(typenames[NR_REG_TYPE_DOUBLE], "double"));
michael@0 356 assert(!strcasecmp(typenames[NR_REG_TYPE_BYTES], "Data"));
michael@0 357 assert(!strcasecmp(typenames[NR_REG_TYPE_STRING], "string"));
michael@0 358 assert(!strcasecmp(typenames[NR_REG_TYPE_REGISTRY], "registry"));
michael@0 359 assert(sizeof(typenames)/sizeof(*typenames) == (NR_REG_TYPE_REGISTRY+1));
michael@0 360 #endif
michael@0 361
michael@0 362 for (i = 0; i < sizeof(typenames)/sizeof(*typenames); ++i) {
michael@0 363 if (!strcasecmp(typenames[i], typename)) {
michael@0 364 *type = i;
michael@0 365 return 0;
michael@0 366 }
michael@0 367 }
michael@0 368 ABORT(R_BAD_ARGS);
michael@0 369
michael@0 370 _status=0;
michael@0 371 abort:
michael@0 372 return(_status);
michael@0 373 }
michael@0 374
michael@0 375 /* More convenience functions: the same as their parents but they
michael@0 376 take a prefix and a suffix */
michael@0 377 #define NRGET2(func, type, get) \
michael@0 378 int \
michael@0 379 func(NR_registry parent, char *child, type *out) \
michael@0 380 { \
michael@0 381 int r, _status; \
michael@0 382 NR_registry registry; \
michael@0 383 \
michael@0 384 if ((r = NR_reg_make_registry(parent, child, registry))) \
michael@0 385 ABORT(r); \
michael@0 386 \
michael@0 387 if ((r = get(registry, out))) { \
michael@0 388 ABORT(r); \
michael@0 389 } \
michael@0 390 \
michael@0 391 _status = 0; \
michael@0 392 abort: \
michael@0 393 return (_status); \
michael@0 394 }
michael@0 395
michael@0 396 NRGET2(NR_reg_get2_char, char, NR_reg_get_char)
michael@0 397 NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar)
michael@0 398 NRGET2(NR_reg_get2_int2, INT2, NR_reg_get_int2)
michael@0 399 NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2)
michael@0 400 NRGET2(NR_reg_get2_int4, INT4, NR_reg_get_int4)
michael@0 401 NRGET2(NR_reg_get2_uint4, UINT4, NR_reg_get_uint4)
michael@0 402 NRGET2(NR_reg_get2_int8, INT8, NR_reg_get_int8)
michael@0 403 NRGET2(NR_reg_get2_uint8, UINT8, NR_reg_get_uint8)
michael@0 404 NRGET2(NR_reg_get2_double, double, NR_reg_get_double)
michael@0 405 NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string)
michael@0 406 NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data)
michael@0 407
michael@0 408 int
michael@0 409 NR_reg_get2_bytes(NR_registry parent, char *child, UCHAR *out, size_t size, size_t *length)
michael@0 410 {
michael@0 411 int r, _status;
michael@0 412 NR_registry registry;
michael@0 413
michael@0 414 if ((r=NR_reg_make_registry(parent, child, registry)))
michael@0 415 ABORT(r);
michael@0 416
michael@0 417 if ((r=NR_reg_get_bytes(registry, out, size, length)))
michael@0 418 ABORT(r);
michael@0 419
michael@0 420 _status = 0;
michael@0 421 abort:
michael@0 422 return (_status);
michael@0 423 }
michael@0 424
michael@0 425 int
michael@0 426 NR_reg_get2_string(NR_registry parent, char *child, char *out, size_t size)
michael@0 427 {
michael@0 428 int r, _status;
michael@0 429 NR_registry registry;
michael@0 430
michael@0 431 if ((r=NR_reg_make_registry(parent, child, registry)))
michael@0 432 ABORT(r);
michael@0 433
michael@0 434 if ((r=NR_reg_get_string(registry, out, size)))
michael@0 435 ABORT(r);
michael@0 436
michael@0 437 _status = 0;
michael@0 438 abort:
michael@0 439 return (_status);
michael@0 440 }
michael@0 441
michael@0 442 /* More convenience functions: the same as their parents but they
michael@0 443 take a prefix and a suffix */
michael@0 444 #define NRSET2(func, type, set) \
michael@0 445 int \
michael@0 446 func(NR_registry parent, char *child, type in) \
michael@0 447 { \
michael@0 448 int r, _status; \
michael@0 449 NR_registry registry; \
michael@0 450 \
michael@0 451 if ((r = NR_reg_make_registry(parent, child, registry))) \
michael@0 452 ABORT(r); \
michael@0 453 \
michael@0 454 if ((r = set(registry, in))) { \
michael@0 455 ABORT(r); \
michael@0 456 } \
michael@0 457 \
michael@0 458 _status = 0; \
michael@0 459 abort: \
michael@0 460 return (_status); \
michael@0 461 }
michael@0 462
michael@0 463 NRSET2(NR_reg_set2_char, char, NR_reg_set_char)
michael@0 464 NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar)
michael@0 465 NRSET2(NR_reg_set2_int2, INT2, NR_reg_set_int2)
michael@0 466 NRSET2(NR_reg_set2_uint2, UINT2, NR_reg_set_uint2)
michael@0 467 NRSET2(NR_reg_set2_int4, INT4, NR_reg_set_int4)
michael@0 468 NRSET2(NR_reg_set2_uint4, UINT4, NR_reg_set_uint4)
michael@0 469 NRSET2(NR_reg_set2_int8, INT8, NR_reg_set_int8)
michael@0 470 NRSET2(NR_reg_set2_uint8, UINT8, NR_reg_set_uint8)
michael@0 471 NRSET2(NR_reg_set2_double, double, NR_reg_set_double)
michael@0 472 NRSET2(NR_reg_set2_string, char*, NR_reg_set_string)
michael@0 473
michael@0 474 int
michael@0 475 NR_reg_set2_bytes(NR_registry prefix, char *name, UCHAR *data, size_t length)
michael@0 476 {
michael@0 477 int r, _status;
michael@0 478 NR_registry registry;
michael@0 479
michael@0 480 if ((r = NR_reg_make_registry(prefix, name, registry)))
michael@0 481 ABORT(r);
michael@0 482
michael@0 483 if ((r = NR_reg_set_bytes(registry, data, length)))
michael@0 484 ABORT(r);
michael@0 485
michael@0 486 _status = 0;
michael@0 487 abort:
michael@0 488 return (_status);
michael@0 489 }
michael@0 490
michael@0 491
michael@0 492 int
michael@0 493 NR_reg_make_child_registry(NR_registry parent, NR_registry descendant, unsigned int generation, NR_registry child)
michael@0 494 {
michael@0 495 int _status;
michael@0 496 size_t length;
michael@0 497
michael@0 498 length = strlen(parent);
michael@0 499
michael@0 500 if (strncasecmp(parent, descendant, length))
michael@0 501 ABORT(R_BAD_ARGS);
michael@0 502
michael@0 503 while (descendant[length] != '\0') {
michael@0 504 if (descendant[length] == '.') {
michael@0 505 if (generation == 0)
michael@0 506 break;
michael@0 507
michael@0 508 --generation;
michael@0 509 }
michael@0 510
michael@0 511 ++length;
michael@0 512 if (length >= sizeof(NR_registry))
michael@0 513 ABORT(R_BAD_ARGS);
michael@0 514 }
michael@0 515
michael@0 516 strncpy(child, descendant, length);
michael@0 517 child[length] = '\0';
michael@0 518
michael@0 519 _status=0;
michael@0 520 abort:
michael@0 521 return(_status);
michael@0 522 }
michael@0 523
michael@0 524 int
michael@0 525 NR_reg_get2_child_count(NR_registry base, NR_registry name, unsigned int *count)
michael@0 526 {
michael@0 527 int r, _status;
michael@0 528 NR_registry registry;
michael@0 529
michael@0 530 if ((r=nr_c2ru_make_registry(base, name, registry)))
michael@0 531 ABORT(r);
michael@0 532
michael@0 533 if (r=NR_reg_get_child_count(registry,count))
michael@0 534 ABORT(r);
michael@0 535
michael@0 536 _status=0;
michael@0 537 abort:
michael@0 538 return(_status);
michael@0 539 }
michael@0 540
michael@0 541 int
michael@0 542 NR_reg_get2_child_registry(NR_registry base, NR_registry name, unsigned int i, NR_registry child)
michael@0 543 {
michael@0 544 int r, _status;
michael@0 545 NR_registry registry;
michael@0 546
michael@0 547 if ((r=nr_c2ru_make_registry(base, name, registry)))
michael@0 548 ABORT(r);
michael@0 549
michael@0 550 if (r=NR_reg_get_child_registry(registry, i, child))
michael@0 551 ABORT(r);
michael@0 552
michael@0 553 _status=0;
michael@0 554 abort:
michael@0 555 return(_status);
michael@0 556 }
michael@0 557
michael@0 558
michael@0 559 /* requires parent already in legal form */
michael@0 560 int
michael@0 561 NR_reg_make_registry(NR_registry parent, char *child, NR_registry out)
michael@0 562 {
michael@0 563 int r, _status;
michael@0 564 int plen;
michael@0 565 int clen;
michael@0 566 char *c;
michael@0 567 int i;
michael@0 568
michael@0 569 if ((r=nr_reg_is_valid(parent)))
michael@0 570 ABORT(r);
michael@0 571
michael@0 572 if (*child == '.')
michael@0 573 ABORT(R_BAD_ARGS);
michael@0 574
michael@0 575 plen = strlen(parent);
michael@0 576 clen = strlen(child);
michael@0 577 if ((plen + clen + 2) > sizeof(NR_registry))
michael@0 578 ABORT(R_BAD_ARGS);
michael@0 579
michael@0 580 if (out != parent)
michael@0 581 strcpy(out, parent);
michael@0 582
michael@0 583 c = &(out[plen]);
michael@0 584
michael@0 585 if (parent[0] != '\0') {
michael@0 586 *c = '.';
michael@0 587 ++c;
michael@0 588 }
michael@0 589
michael@0 590 for (i = 0; i < clen; ++i, ++c) {
michael@0 591 *c = child[i];
michael@0 592 if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c))
michael@0 593 *c = '_';
michael@0 594 }
michael@0 595 if (i == 0 || child[i-1] == '.')
michael@0 596 ABORT(R_BAD_ARGS);
michael@0 597
michael@0 598 *c = '\0';
michael@0 599
michael@0 600 _status = 0;
michael@0 601 abort:
michael@0 602 return _status;
michael@0 603 }
michael@0 604

mercurial