Home | History | Annotate | Line # | Download | only in libppath
      1 /* $NetBSD: ppath.c,v 1.5 2020/06/06 22:28:07 thorpej Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by David Young <dyoung (at) NetBSD.org>.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: ppath.c,v 1.5 2020/06/06 22:28:07 thorpej Exp $");
     34 
     35 #ifdef _KERNEL
     36 #include <sys/systm.h>
     37 #endif
     38 #include <ppath/ppath.h>
     39 #include <ppath/ppath_impl.h>
     40 
     41 enum _ppath_type {
     42 	  PPATH_T_IDX = 0
     43 	, PPATH_T_KEY = 1
     44 };
     45 
     46 typedef enum _ppath_type ppath_type_t;
     47 
     48 struct _ppath_component {
     49 	unsigned int	pc_refcnt;
     50 	ppath_type_t	pc_type;
     51 	union {
     52 		char *u_key;
     53 		unsigned int u_idx;
     54 	} pc_u;
     55 #define pc_key pc_u.u_key
     56 #define pc_idx pc_u.u_idx
     57 };
     58 
     59 struct _ppath {
     60 	unsigned int	p_refcnt;
     61 	unsigned int	p_len;
     62 	ppath_component_t *p_cmpt[PPATH_MAX_COMPONENTS];
     63 };
     64 
     65 static int ppath_copydel_object_of_type(prop_object_t, prop_object_t *,
     66     const ppath_t *, prop_type_t);
     67 static int ppath_copyset_object_helper(prop_object_t, prop_object_t *,
     68     const ppath_t *, const prop_object_t);
     69 
     70 static void
     71 ppath_strfree(char *s)
     72 {
     73 	size_t size = strlen(s) + 1;
     74 
     75 	ppath_free(s, size);
     76 }
     77 
     78 static char *
     79 ppath_strdup(const char *s)
     80 {
     81 	size_t size = strlen(s) + 1;
     82 	char *p;
     83 
     84 	if ((p = ppath_alloc(size)) == NULL)
     85 		return NULL;
     86 
     87 	return strcpy(p, s);
     88 }
     89 
     90 int
     91 ppath_component_idx(const ppath_component_t *pc)
     92 {
     93 	if (pc->pc_type != PPATH_T_IDX)
     94 		return -1;
     95 	return pc->pc_idx;
     96 }
     97 
     98 const char *
     99 ppath_component_key(const ppath_component_t *pc)
    100 {
    101 	if (pc->pc_type != PPATH_T_KEY)
    102 		return NULL;
    103 	return pc->pc_key;
    104 }
    105 
    106 ppath_component_t *
    107 ppath_idx(unsigned int idx)
    108 {
    109 	ppath_component_t *pc;
    110 
    111 	if ((pc = ppath_alloc(sizeof(*pc))) == NULL)
    112 		return NULL;
    113 	pc->pc_idx = idx;
    114 	pc->pc_type = PPATH_T_IDX;
    115 	pc->pc_refcnt = 1;
    116 	ppath_component_extant_inc();
    117 	return pc;
    118 }
    119 
    120 ppath_component_t *
    121 ppath_key(const char *key)
    122 {
    123 	ppath_component_t *pc;
    124 
    125 	if ((pc = ppath_alloc(sizeof(*pc))) == NULL)
    126 		return NULL;
    127 
    128 	if ((pc->pc_key = ppath_strdup(key)) == NULL) {
    129 		ppath_free(pc, sizeof(*pc));
    130 		return NULL;
    131 	}
    132 	pc->pc_type = PPATH_T_KEY;
    133 	pc->pc_refcnt = 1;
    134 	ppath_component_extant_inc();
    135 	return pc;
    136 }
    137 
    138 ppath_component_t *
    139 ppath_component_retain(ppath_component_t *pc)
    140 {
    141 	ppath_assert(pc->pc_refcnt != 0);
    142 	pc->pc_refcnt++;
    143 
    144 	return pc;
    145 }
    146 
    147 void
    148 ppath_component_release(ppath_component_t *pc)
    149 {
    150 	ppath_assert(pc->pc_refcnt != 0);
    151 
    152 	if (--pc->pc_refcnt != 0)
    153 		return;
    154 	if (pc->pc_type == PPATH_T_KEY)
    155 		ppath_strfree(pc->pc_key);
    156 	ppath_component_extant_dec();
    157 	ppath_free(pc, sizeof(*pc));
    158 }
    159 
    160 ppath_t *
    161 ppath_create(void)
    162 {
    163 	ppath_t *p;
    164 
    165 	if ((p = ppath_alloc(sizeof(*p))) == NULL)
    166 		return NULL;
    167 
    168 	p->p_refcnt = 1;
    169 	ppath_extant_inc();
    170 
    171 	return p;
    172 }
    173 
    174 ppath_t *
    175 ppath_pop(ppath_t *p, ppath_component_t **pcp)
    176 {
    177 	ppath_component_t *pc;
    178 
    179 	if (p == NULL || p->p_len == 0)
    180 		return NULL;
    181 
    182 	pc = p->p_cmpt[--p->p_len];
    183 
    184 	if (pcp != NULL)
    185 		*pcp = pc;
    186 	else
    187 		ppath_component_release(pc);
    188 
    189 	return p;
    190 }
    191 
    192 ppath_t *
    193 ppath_push(ppath_t *p, ppath_component_t *pc)
    194 {
    195 	if (p == NULL || p->p_len == __arraycount(p->p_cmpt))
    196 		return NULL;
    197 
    198 	p->p_cmpt[p->p_len++] = ppath_component_retain(pc);
    199 
    200 	return p;
    201 }
    202 
    203 ppath_component_t *
    204 ppath_component_at(const ppath_t *p, unsigned int i)
    205 {
    206 	ppath_component_t *pc;
    207 
    208 	if (p == NULL || i >= p->p_len)
    209 		return NULL;
    210 
    211 	pc = p->p_cmpt[i];
    212 
    213 	return ppath_component_retain(pc);
    214 }
    215 
    216 unsigned int
    217 ppath_length(const ppath_t *p)
    218 {
    219 	return p->p_len;
    220 }
    221 
    222 ppath_t *
    223 ppath_subpath(const ppath_t *p, unsigned int first, unsigned int exclast)
    224 {
    225 	unsigned int i;
    226 	ppath_t *np;
    227 	ppath_component_t *pc;
    228 
    229 	if (p == NULL || (np = ppath_create()) == NULL)
    230 		return NULL;
    231 
    232 	for (i = first; i < exclast; i++) {
    233 		if ((pc = ppath_component_at(p, i)) == NULL)
    234 			break;
    235 		ppath_push(np, pc);
    236 		ppath_component_release(pc);
    237 	}
    238 	return np;
    239 }
    240 
    241 ppath_t *
    242 ppath_push_idx(ppath_t *p0, unsigned int idx)
    243 {
    244 	ppath_component_t *pc;
    245 	ppath_t *p;
    246 
    247 	if ((pc = ppath_idx(idx)) == NULL)
    248 		return NULL;
    249 
    250 	p = ppath_push(p0, pc);
    251 	ppath_component_release(pc);
    252 	return p;
    253 }
    254 
    255 ppath_t *
    256 ppath_push_key(ppath_t *p0, const char *key)
    257 {
    258 	ppath_component_t *pc;
    259 	ppath_t *p;
    260 
    261 	if ((pc = ppath_key(key)) == NULL)
    262 		return NULL;
    263 
    264 	p = ppath_push(p0, pc);
    265 	ppath_component_release(pc);
    266 	return p;
    267 }
    268 
    269 ppath_t *
    270 ppath_replace_idx(ppath_t *p, unsigned int idx)
    271 {
    272 	ppath_component_t *pc0, *pc;
    273 
    274 	if (p == NULL || p->p_len == 0)
    275 		return NULL;
    276 
    277 	pc0 = p->p_cmpt[p->p_len - 1];
    278 
    279 	if (pc0->pc_type != PPATH_T_IDX)
    280 		return NULL;
    281 
    282 	if ((pc = ppath_idx(idx)) == NULL)
    283 		return NULL;
    284 
    285 	p->p_cmpt[p->p_len - 1] = pc;
    286 	ppath_component_release(pc0);
    287 
    288 	return p;
    289 }
    290 
    291 ppath_t *
    292 ppath_replace_key(ppath_t *p, const char *key)
    293 {
    294 	ppath_component_t *pc0, *pc;
    295 
    296 	if (p == NULL || p->p_len == 0)
    297 		return NULL;
    298 
    299 	pc0 = p->p_cmpt[p->p_len - 1];
    300 
    301 	if (pc0->pc_type != PPATH_T_KEY)
    302 		return NULL;
    303 
    304 	if ((pc = ppath_key(key)) == NULL)
    305 		return NULL;
    306 
    307 	p->p_cmpt[p->p_len - 1] = pc;
    308 	ppath_component_release(pc0);
    309 
    310 	return p;
    311 }
    312 
    313 ppath_t *
    314 ppath_copy(const ppath_t *p0)
    315 {
    316 	ppath_t *p;
    317 	unsigned int i;
    318 
    319 	if ((p = ppath_create()) == NULL)
    320 		return NULL;
    321 
    322 	for (i = 0; i < p0->p_len; i++)
    323 		p->p_cmpt[i] = ppath_component_retain(p0->p_cmpt[i]);
    324 	p->p_len = p0->p_len;
    325 	return p;
    326 }
    327 
    328 ppath_t *
    329 ppath_retain(ppath_t *p)
    330 {
    331 	assert(p->p_refcnt != 0);
    332 
    333 	p->p_refcnt++;
    334 
    335 	return p;
    336 }
    337 
    338 void
    339 ppath_release(ppath_t *p)
    340 {
    341 	unsigned int i;
    342 
    343 	assert(p->p_refcnt != 0);
    344 
    345 	if (--p->p_refcnt != 0)
    346 		return;
    347 
    348 	for (i = 0; i < p->p_len; i++)
    349 		ppath_component_release(p->p_cmpt[i]);
    350 
    351 	ppath_extant_dec();
    352 	ppath_free(p, sizeof(*p));
    353 }
    354 
    355 static prop_object_t
    356 ppath_lookup_helper(prop_object_t o0, const ppath_t *p, prop_object_t *pop,
    357     ppath_component_t **pcp, unsigned int *ip)
    358 {
    359 	unsigned int i;
    360 	prop_object_t o, po;
    361 	ppath_type_t t;
    362 	ppath_component_t *pc = NULL;
    363 
    364 	for (po = NULL, o = o0, i = 0; i < p->p_len && o != NULL; i++) {
    365 		pc = p->p_cmpt[i];
    366 		t = pc->pc_type;
    367 		switch (prop_object_type(o)) {
    368 		case PROP_TYPE_ARRAY:
    369 			po = o;
    370 			o = (t == PPATH_T_IDX)
    371 			    ? prop_array_get(o, pc->pc_idx)
    372 			    : NULL;
    373 			break;
    374 		case PROP_TYPE_DICTIONARY:
    375 			po = o;
    376 			o = (t == PPATH_T_KEY)
    377 			    ? prop_dictionary_get(o, pc->pc_key)
    378 			    : NULL;
    379 			break;
    380 		default:
    381 			o = NULL;
    382 			break;
    383 		}
    384 	}
    385 	if (pop != NULL)
    386 		*pop = po;
    387 	if (pcp != NULL)
    388 		*pcp = pc;
    389 	if (ip != NULL)
    390 		*ip = i;
    391 	return o;
    392 }
    393 
    394 prop_object_t
    395 ppath_lookup(prop_object_t o, const ppath_t *p)
    396 {
    397 	return ppath_lookup_helper(o, p, NULL, NULL, NULL);
    398 }
    399 
    400 static int
    401 ppath_create_object_and_release(prop_object_t o, const ppath_t *p,
    402     prop_object_t v)
    403 {
    404 	int rc;
    405 
    406 	rc = ppath_create_object(o, p, v);
    407 	prop_object_release(v);
    408 	return rc;
    409 }
    410 
    411 int
    412 ppath_create_string(prop_object_t o, const ppath_t *p, const char *s)
    413 {
    414 	return ppath_create_object_and_release(o, p,
    415 	    prop_string_create_copy(s));
    416 }
    417 
    418 int
    419 ppath_create_data(prop_object_t o, const ppath_t *p,
    420     const void *data, size_t size)
    421 {
    422 	return ppath_create_object_and_release(o, p,
    423 	    prop_data_create_copy(data, size));
    424 }
    425 
    426 int
    427 ppath_create_uint64(prop_object_t o, const ppath_t *p, uint64_t u)
    428 {
    429 	return ppath_create_object_and_release(o, p,
    430 	    prop_number_create_unsigned(u));
    431 }
    432 
    433 int
    434 ppath_create_int64(prop_object_t o, const ppath_t *p, int64_t i)
    435 {
    436 	return ppath_create_object_and_release(o, p,
    437 	    prop_number_create_signed(i));
    438 }
    439 
    440 int
    441 ppath_create_bool(prop_object_t o, const ppath_t *p, bool b)
    442 {
    443 	return ppath_create_object_and_release(o, p, prop_bool_create(b));
    444 }
    445 
    446 int
    447 ppath_create_object(prop_object_t o, const ppath_t *p, prop_object_t v)
    448 {
    449 	unsigned int i;
    450 	ppath_component_t *pc;
    451 	prop_object_t po;
    452 
    453 	if (ppath_lookup_helper(o, p, &po, &pc, &i) != NULL)
    454 		return EEXIST;
    455 
    456 	if (i != ppath_length(p))
    457 		return ENOENT;
    458 
    459 	switch (pc->pc_type) {
    460 	case PPATH_T_IDX:
    461 		return prop_array_set(po, pc->pc_idx, v) ? 0 : ENOMEM;
    462 	case PPATH_T_KEY:
    463 		return prop_dictionary_set(po, pc->pc_key, v) ? 0 : ENOMEM;
    464 	default:
    465 		return ENOENT;
    466 	}
    467 }
    468 
    469 int
    470 ppath_set_object(prop_object_t o, const ppath_t *p, prop_object_t v)
    471 {
    472 	ppath_component_t *pc;
    473 	prop_object_t po;
    474 
    475 	if (ppath_lookup_helper(o, p, &po, &pc, NULL) == NULL)
    476 		return ENOENT;
    477 
    478 	switch (pc->pc_type) {
    479 	case PPATH_T_IDX:
    480 		return prop_array_set(po, pc->pc_idx, v) ? 0 : ENOMEM;
    481 	case PPATH_T_KEY:
    482 		return prop_dictionary_set(po, pc->pc_key, v) ? 0 : ENOMEM;
    483 	default:
    484 		return ENOENT;
    485 	}
    486 }
    487 
    488 static int
    489 ppath_set_object_and_release(prop_object_t o, const ppath_t *p, prop_object_t v)
    490 {
    491 	prop_object_t ov;
    492 	int rc;
    493 
    494 	if (v == NULL)
    495 		return ENOMEM;
    496 
    497 	if ((ov = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    498 		return ENOENT;
    499 
    500 	if (prop_object_type(ov) != prop_object_type(v))
    501 		return EFTYPE;
    502 
    503 	rc = ppath_set_object(o, p, v);
    504 	prop_object_release(v);
    505 	return rc;
    506 }
    507 
    508 int
    509 ppath_get_object(prop_object_t o, const ppath_t *p, prop_object_t *vp)
    510 {
    511 	prop_object_t v;
    512 
    513 	if ((v = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    514 		return ENOENT;
    515 
    516 	if (vp != NULL)
    517 		*vp = v;
    518 	return 0;
    519 }
    520 
    521 static int
    522 ppath_get_object_of_type(prop_object_t o, const ppath_t *p, prop_object_t *vp,
    523     prop_type_t t)
    524 {
    525 	int rc;
    526 
    527 	if ((rc = ppath_get_object(o, p, vp)) != 0)
    528 		return rc;
    529 
    530 	return (prop_object_type(*vp) == t) ? 0 : EFTYPE;
    531 }
    532 
    533 int
    534 ppath_delete_object(prop_object_t o, const ppath_t *p)
    535 {
    536 	ppath_component_t *pc;
    537 	prop_object_t po;
    538 
    539 	if (ppath_lookup_helper(o, p, &po, &pc, NULL) == NULL)
    540 		return ENOENT;
    541 
    542 	switch (pc->pc_type) {
    543 	case PPATH_T_IDX:
    544 		prop_array_remove(po, pc->pc_idx);
    545 		return 0;
    546 	case PPATH_T_KEY:
    547 		prop_dictionary_remove(po, pc->pc_key);
    548 		return 0;
    549 	default:
    550 		return ENOENT;
    551 	}
    552 }
    553 
    554 static int
    555 ppath_delete_object_of_type(prop_object_t o, const ppath_t *p, prop_type_t t)
    556 {
    557 	prop_object_t v;
    558 
    559 	if ((v = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    560 		return ENOENT;
    561 
    562 	if (prop_object_type(v) != t)
    563 		return EFTYPE;
    564 
    565 	return ppath_delete_object(o, p);
    566 }
    567 
    568 int
    569 ppath_copydel_string(prop_object_t o, prop_object_t *op, const ppath_t *p)
    570 {
    571 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_STRING);
    572 }
    573 
    574 int
    575 ppath_copydel_data(prop_object_t o, prop_object_t *op, const ppath_t *p)
    576 {
    577 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_DATA);
    578 }
    579 
    580 int
    581 ppath_copydel_uint64(prop_object_t o, prop_object_t *op, const ppath_t *p)
    582 {
    583 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_NUMBER);
    584 }
    585 
    586 int
    587 ppath_copydel_int64(prop_object_t o, prop_object_t *op, const ppath_t *p)
    588 {
    589 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_NUMBER);
    590 }
    591 
    592 int
    593 ppath_copydel_bool(prop_object_t o, prop_object_t *op, const ppath_t *p)
    594 {
    595 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_BOOL);
    596 }
    597 
    598 static int
    599 ppath_copydel_object_of_type(prop_object_t o, prop_object_t *op,
    600     const ppath_t *p, prop_type_t t)
    601 {
    602 	prop_object_t v;
    603 
    604 	if ((v = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    605 		return ENOENT;
    606 
    607 	if (prop_object_type(v) != t)
    608 		return EFTYPE;
    609 
    610 	return ppath_copydel_object(o, op, p);
    611 }
    612 
    613 int
    614 ppath_copydel_object(prop_object_t o, prop_object_t *op, const ppath_t *p)
    615 {
    616 	return ppath_copyset_object_helper(o, op, p, NULL);
    617 }
    618 
    619 int
    620 ppath_copyset_object(prop_object_t o, prop_object_t *op, const ppath_t *p,
    621     const prop_object_t v)
    622 {
    623 	ppath_assert(v != NULL);
    624 	return ppath_copyset_object_helper(o, op, p, v);
    625 }
    626 
    627 static int
    628 ppath_copyset_object_helper(prop_object_t o, prop_object_t *op,
    629     const ppath_t *p0, const prop_object_t v0)
    630 {
    631 	bool copy, success;
    632 	ppath_component_t *npc, *pc;
    633 	ppath_t *cp, *p;
    634 	prop_object_t npo = NULL, po, v;
    635 
    636 	for (cp = p = ppath_copy(p0), v = v0;
    637 	     p != NULL;
    638 	     p = ppath_pop(p, NULL), v = npo) {
    639 
    640 		if (ppath_lookup_helper(o, p, &po, &pc, NULL) == NULL)
    641 			return ENOENT;
    642 
    643 		if (pc == NULL)
    644 			break;
    645 
    646 		if (ppath_lookup_helper(*op, p, &npo, &npc, NULL) == NULL)
    647 			npo = po;
    648 
    649 		copy = (npo == po);
    650 
    651 		switch (pc->pc_type) {
    652 		case PPATH_T_IDX:
    653 			if (copy && (npo = prop_array_copy_mutable(po)) == NULL)
    654 				return ENOMEM;
    655 			success = (v == NULL)
    656 			    ? (prop_array_remove(npo, pc->pc_idx), true)
    657 			    : prop_array_set(npo, pc->pc_idx, v);
    658 			break;
    659 		case PPATH_T_KEY:
    660 			if (copy &&
    661 			    (npo = prop_dictionary_copy_mutable(po)) == NULL)
    662 				return ENOMEM;
    663 			success = (v == NULL)
    664 			    ? (prop_dictionary_remove(npo, pc->pc_key), true)
    665 			    : prop_dictionary_set(npo, pc->pc_key, v);
    666 			break;
    667 		default:
    668 			return ENOENT;
    669 		}
    670 		if (!success) {
    671 			if (copy)
    672 				prop_object_release(npo);
    673 			return ENOMEM;
    674 		}
    675 	}
    676 
    677 	if (cp == NULL)
    678 		return ENOMEM;
    679 
    680 	ppath_release(cp);
    681 
    682 	if (op != NULL && npo != NULL)
    683 		*op = npo;
    684 	else if (npo != NULL)
    685 		prop_object_release(npo);
    686 
    687 	return 0;
    688 }
    689 
    690 static int
    691 ppath_copyset_object_and_release(prop_object_t o, prop_object_t *op,
    692     const ppath_t *p, prop_object_t v)
    693 {
    694 	prop_object_t ov;
    695 	int rc;
    696 
    697 	if (v == NULL)
    698 		return ENOMEM;
    699 
    700 	if ((ov = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    701 		return ENOENT;
    702 
    703 	if (prop_object_type(ov) != prop_object_type(v))
    704 		return EFTYPE;
    705 
    706 	rc = ppath_copyset_object(o, op, p, v);
    707 	prop_object_release(v);
    708 	return rc;
    709 }
    710 
    711 int
    712 ppath_copyset_bool(prop_object_t o, prop_object_t *op, const ppath_t *p, bool b)
    713 {
    714 	return ppath_copyset_object_and_release(o, op, p, prop_bool_create(b));
    715 }
    716 
    717 int
    718 ppath_set_bool(prop_object_t o, const ppath_t *p, bool b)
    719 {
    720 	return ppath_set_object_and_release(o, p, prop_bool_create(b));
    721 }
    722 
    723 int
    724 ppath_get_bool(prop_object_t o, const ppath_t *p, bool *bp)
    725 {
    726 	prop_object_t v;
    727 	int rc;
    728 
    729 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_BOOL)) != 0)
    730 		return rc;
    731 
    732 	if (bp != NULL)
    733 		*bp = prop_bool_true(v);
    734 
    735 	return 0;
    736 }
    737 
    738 int
    739 ppath_delete_bool(prop_object_t o, const ppath_t *p)
    740 {
    741 	return ppath_delete_object_of_type(o, p, PROP_TYPE_BOOL);
    742 }
    743 
    744 int
    745 ppath_copyset_data(prop_object_t o, prop_object_t *op, const ppath_t *p,
    746     const void *data, size_t size)
    747 {
    748 	return ppath_copyset_object_and_release(o, op, p,
    749 	    prop_data_create_copy(data, size));
    750 }
    751 
    752 int
    753 ppath_set_data(prop_object_t o, const ppath_t *p, const void *data, size_t size)
    754 {
    755 	return ppath_set_object_and_release(o, p,
    756 	    prop_data_create_copy(data, size));
    757 }
    758 
    759 int
    760 ppath_get_data(prop_object_t o, const ppath_t *p, const void **datap,
    761     size_t *sizep)
    762 {
    763 	prop_object_t v;
    764 	int rc;
    765 
    766 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    767 		return rc;
    768 
    769 	if (datap != NULL)
    770 		*datap = prop_data_value(v);
    771 	if (sizep != NULL)
    772 		*sizep = prop_data_size(v);
    773 
    774 	return 0;
    775 }
    776 
    777 int
    778 ppath_dup_data(prop_object_t o, const ppath_t *p, void **datap, size_t *sizep)
    779 {
    780 	prop_object_t v;
    781 	int rc;
    782 
    783 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    784 		return rc;
    785 
    786 	const size_t data_size = prop_data_size(v);
    787 
    788 	if (datap != NULL) {
    789 		void *buf = ppath_alloc(data_size);
    790 		if (buf != NULL)
    791 			(void) prop_data_copy_value(v, buf, data_size);
    792 		*datap = buf;
    793 	}
    794 	if (sizep != NULL)
    795 		*sizep = data_size;
    796 
    797 	return 0;
    798 }
    799 
    800 int
    801 ppath_delete_data(prop_object_t o, const ppath_t *p)
    802 {
    803 	return ppath_delete_object_of_type(o, p, PROP_TYPE_DATA);
    804 }
    805 
    806 int
    807 ppath_copyset_int64(prop_object_t o, prop_object_t *op, const ppath_t *p,
    808     int64_t i)
    809 {
    810 	return ppath_copyset_object_and_release(o, op, p,
    811 	    prop_number_create_signed(i));
    812 }
    813 
    814 int
    815 ppath_set_int64(prop_object_t o, const ppath_t *p, int64_t i)
    816 {
    817 	return ppath_set_object_and_release(o, p,
    818 	    prop_number_create_signed(i));
    819 }
    820 
    821 int
    822 ppath_get_int64(prop_object_t o, const ppath_t *p, int64_t *ip)
    823 {
    824 	prop_object_t v;
    825 	int rc;
    826 
    827 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    828 		return rc;
    829 
    830 	if (prop_number_unsigned(v))
    831 		return EFTYPE;
    832 
    833 	if (ip != NULL)
    834 		*ip = prop_number_signed_value(v);
    835 
    836 	return 0;
    837 }
    838 
    839 int
    840 ppath_delete_int64(prop_object_t o, const ppath_t *p)
    841 {
    842 	return ppath_delete_object_of_type(o, p, PROP_TYPE_NUMBER);
    843 }
    844 
    845 int
    846 ppath_copyset_string(prop_object_t o, prop_object_t *op, const ppath_t *p,
    847     const char *s)
    848 {
    849 	return ppath_copyset_object_and_release(o, op, p,
    850 	    prop_string_create_copy(s));
    851 }
    852 
    853 int
    854 ppath_set_string(prop_object_t o, const ppath_t *p, const char *s)
    855 {
    856 	return ppath_set_object_and_release(o, p,
    857 	    prop_string_create_copy(s));
    858 }
    859 
    860 int
    861 ppath_get_string(prop_object_t o, const ppath_t *p, const char **sp)
    862 {
    863 	int rc;
    864 	prop_object_t v;
    865 
    866 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_STRING)) != 0)
    867 		return rc;
    868 
    869 	if (sp != NULL)
    870 		*sp = prop_string_value(v);
    871 
    872 	return 0;
    873 }
    874 
    875 int
    876 ppath_dup_string(prop_object_t o, const ppath_t *p, char **sp)
    877 {
    878 	int rc;
    879 	prop_object_t v;
    880 
    881 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_STRING)) != 0)
    882 		return rc;
    883 
    884 	const size_t string_size = prop_string_size(v);
    885 
    886 	if (sp != NULL) {
    887 		char *cp = ppath_alloc(string_size + 1);
    888 		if (cp != NULL)
    889 			(void)prop_string_copy_value(v, cp, string_size + 1);
    890 		*sp = cp;
    891 	}
    892 
    893 	return 0;
    894 }
    895 
    896 int
    897 ppath_delete_string(prop_object_t o, const ppath_t *p)
    898 {
    899 	return ppath_delete_object_of_type(o, p, PROP_TYPE_STRING);
    900 }
    901 
    902 int
    903 ppath_copyset_uint64(prop_object_t o, prop_object_t *op, const ppath_t *p,
    904     uint64_t u)
    905 {
    906 	return ppath_copyset_object_and_release(o, op, p,
    907 	    prop_number_create_unsigned(u));
    908 }
    909 
    910 int
    911 ppath_set_uint64(prop_object_t o, const ppath_t *p, uint64_t u)
    912 {
    913 	return ppath_set_object_and_release(o, p,
    914 	    prop_number_create_unsigned(u));
    915 }
    916 
    917 int
    918 ppath_get_uint64(prop_object_t o, const ppath_t *p, uint64_t *up)
    919 {
    920 	prop_object_t v;
    921 	int rc;
    922 
    923 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    924 		return rc;
    925 
    926 	if (!prop_number_unsigned(v))
    927 		return EFTYPE;
    928 
    929 	if (up != NULL)
    930 		*up = prop_number_unsigned_value(v);
    931 
    932 	return 0;
    933 }
    934 
    935 int
    936 ppath_delete_uint64(prop_object_t o, const ppath_t *p)
    937 {
    938 	return ppath_delete_object_of_type(o, p, PROP_TYPE_NUMBER);
    939 }
    940