1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This is the main implementation file for the low-level repository 31*7c478bd9Sstevel@tonic-gate * interface. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "lowlevel_impl.h" 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include "repcache_protocol.h" 37*7c478bd9Sstevel@tonic-gate #include "scf_type.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <assert.h> 40*7c478bd9Sstevel@tonic-gate #include <alloca.h> 41*7c478bd9Sstevel@tonic-gate #include <door.h> 42*7c478bd9Sstevel@tonic-gate #include <errno.h> 43*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 44*7c478bd9Sstevel@tonic-gate #include <fnmatch.h> 45*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 46*7c478bd9Sstevel@tonic-gate #include <poll.h> 47*7c478bd9Sstevel@tonic-gate #include <pthread.h> 48*7c478bd9Sstevel@tonic-gate #include <stddef.h> 49*7c478bd9Sstevel@tonic-gate #include <stdio.h> 50*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 51*7c478bd9Sstevel@tonic-gate #include <string.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 54*7c478bd9Sstevel@tonic-gate #include <unistd.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #define ENV_SCF_DEBUG "LIBSCF_DEBUG" 57*7c478bd9Sstevel@tonic-gate #define ENV_SCF_DOORPATH "LIBSCF_DOORPATH" 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate static uint32_t default_debug = 0; 60*7c478bd9Sstevel@tonic-gate static const char *default_door_path = REPOSITORY_DOOR_NAME; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #define CALL_FAILED -1 63*7c478bd9Sstevel@tonic-gate #define RESULT_TOO_BIG -2 64*7c478bd9Sstevel@tonic-gate #define NOT_BOUND -3 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate static pthread_mutex_t lowlevel_init_lock; 67*7c478bd9Sstevel@tonic-gate static int32_t lowlevel_inited; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *tran_entry_pool; 70*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *datael_pool; 71*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *iter_pool; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * We want MUTEX_HELD, but we also want pthreads. 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate struct _lwp_mutex; 77*7c478bd9Sstevel@tonic-gate extern int _mutex_held(struct _lwp_mutex *); 78*7c478bd9Sstevel@tonic-gate #define MUTEX_HELD(m) _mutex_held((struct _lwp_mutex *)(m)) 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * no cancellation, please 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate struct _lwp_cond; 84*7c478bd9Sstevel@tonic-gate extern int _cond_wait(struct _lwp_cond *, struct _lwp_mutex *); 85*7c478bd9Sstevel@tonic-gate #define PTHREAD_COND_WAIT(cv, mx) \ 86*7c478bd9Sstevel@tonic-gate _cond_wait((struct _lwp_cond *)(cv), (struct _lwp_mutex *)(mx)) 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate #ifdef lint 89*7c478bd9Sstevel@tonic-gate #define assert_nolint(x) (void)0 90*7c478bd9Sstevel@tonic-gate #else 91*7c478bd9Sstevel@tonic-gate #define assert_nolint(x) assert(x) 92*7c478bd9Sstevel@tonic-gate #endif 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate static void scf_iter_reset_locked(scf_iter_t *iter); 95*7c478bd9Sstevel@tonic-gate static void scf_value_reset_locked(scf_value_t *val, int and_destroy); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate #define TYPE_VALUE (-100) 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * Hold and release subhandles. We only allow one thread access to the 101*7c478bd9Sstevel@tonic-gate * subhandles at a time, and he can use any subset, grabbing and releasing 102*7c478bd9Sstevel@tonic-gate * them in any order. The only restrictions are that you cannot hold an 103*7c478bd9Sstevel@tonic-gate * already-held subhandle, and all subhandles must be released before 104*7c478bd9Sstevel@tonic-gate * returning to the original caller. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate static void 107*7c478bd9Sstevel@tonic-gate handle_hold_subhandles(scf_handle_t *h, int mask) 108*7c478bd9Sstevel@tonic-gate { 109*7c478bd9Sstevel@tonic-gate assert(mask != 0 && (mask & ~RH_HOLD_ALL) == 0); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 112*7c478bd9Sstevel@tonic-gate while (h->rh_hold_flags != 0 && h->rh_holder != pthread_self()) 113*7c478bd9Sstevel@tonic-gate (void) PTHREAD_COND_WAIT(&h->rh_cv, &h->rh_lock); 114*7c478bd9Sstevel@tonic-gate if (h->rh_hold_flags == 0) 115*7c478bd9Sstevel@tonic-gate h->rh_holder = pthread_self(); 116*7c478bd9Sstevel@tonic-gate assert(!(h->rh_hold_flags & mask)); 117*7c478bd9Sstevel@tonic-gate h->rh_hold_flags |= mask; 118*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static void 122*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(scf_handle_t *h, int mask) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate assert(mask != 0 && (mask & ~RH_HOLD_ALL) == 0); 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 127*7c478bd9Sstevel@tonic-gate assert(h->rh_holder == pthread_self()); 128*7c478bd9Sstevel@tonic-gate assert((h->rh_hold_flags & mask)); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate h->rh_hold_flags &= ~mask; 131*7c478bd9Sstevel@tonic-gate if (h->rh_hold_flags == 0) 132*7c478bd9Sstevel@tonic-gate (void) pthread_cond_signal(&h->rh_cv); 133*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate #define HOLD_HANDLE(h, flag, field) \ 137*7c478bd9Sstevel@tonic-gate (handle_hold_subhandles((h), (flag)), (h)->field) 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate #define RELE_HANDLE(h, flag) \ 140*7c478bd9Sstevel@tonic-gate (handle_rele_subhandles((h), (flag))) 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * convenience macros, for functions that only need a one or two handles at 144*7c478bd9Sstevel@tonic-gate * any given time 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_ITER(h) HOLD_HANDLE((h), RH_HOLD_ITER, rh_iter) 147*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_SCOPE(h) HOLD_HANDLE((h), RH_HOLD_SCOPE, rh_scope) 148*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_SERVICE(h) HOLD_HANDLE((h), RH_HOLD_SERVICE, rh_service) 149*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_INSTANCE(h) HOLD_HANDLE((h), RH_HOLD_INSTANCE, rh_instance) 150*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_SNAPSHOT(h) HOLD_HANDLE((h), RH_HOLD_SNAPSHOT, rh_snapshot) 151*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_SNAPLVL(h) HOLD_HANDLE((h), RH_HOLD_SNAPLVL, rh_snaplvl) 152*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_PG(h) HOLD_HANDLE((h), RH_HOLD_PG, rh_pg) 153*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_PROPERTY(h) HOLD_HANDLE((h), RH_HOLD_PROPERTY, rh_property) 154*7c478bd9Sstevel@tonic-gate #define HANDLE_HOLD_VALUE(h) HOLD_HANDLE((h), RH_HOLD_VALUE, rh_value) 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_ITER(h) RELE_HANDLE((h), RH_HOLD_ITER) 157*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_SCOPE(h) RELE_HANDLE((h), RH_HOLD_SCOPE) 158*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_SERVICE(h) RELE_HANDLE((h), RH_HOLD_SERVICE) 159*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_INSTANCE(h) RELE_HANDLE((h), RH_HOLD_INSTANCE) 160*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_SNAPSHOT(h) RELE_HANDLE((h), RH_HOLD_SNAPSHOT) 161*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_SNAPLVL(h) RELE_HANDLE((h), RH_HOLD_SNAPLVL) 162*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_PG(h) RELE_HANDLE((h), RH_HOLD_PG) 163*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_PROPERTY(h) RELE_HANDLE((h), RH_HOLD_PROPERTY) 164*7c478bd9Sstevel@tonic-gate #define HANDLE_RELE_VALUE(h) RELE_HANDLE((h), RH_HOLD_VALUE) 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 167*7c478bd9Sstevel@tonic-gate static int 168*7c478bd9Sstevel@tonic-gate transaction_entry_compare(const void *l_arg, const void *r_arg, void *private) 169*7c478bd9Sstevel@tonic-gate { 170*7c478bd9Sstevel@tonic-gate const char *l_prop = 171*7c478bd9Sstevel@tonic-gate ((scf_transaction_entry_t *)l_arg)->entry_property; 172*7c478bd9Sstevel@tonic-gate const char *r_prop = 173*7c478bd9Sstevel@tonic-gate ((scf_transaction_entry_t *)r_arg)->entry_property; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate int ret; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate ret = strcmp(l_prop, r_prop); 178*7c478bd9Sstevel@tonic-gate if (ret > 0) 179*7c478bd9Sstevel@tonic-gate return (1); 180*7c478bd9Sstevel@tonic-gate else if (ret < 0) 181*7c478bd9Sstevel@tonic-gate return (-1); 182*7c478bd9Sstevel@tonic-gate return (0); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate static int 186*7c478bd9Sstevel@tonic-gate lowlevel_init(void) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate const char *debug; 189*7c478bd9Sstevel@tonic-gate const char *door_path; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&lowlevel_init_lock); 192*7c478bd9Sstevel@tonic-gate if (lowlevel_inited == 0) { 193*7c478bd9Sstevel@tonic-gate if (!issetugid() && 194*7c478bd9Sstevel@tonic-gate (debug = getenv(ENV_SCF_DEBUG)) != NULL && debug[0] != 0 && 195*7c478bd9Sstevel@tonic-gate uu_strtoint(debug, &default_debug, sizeof (default_debug), 196*7c478bd9Sstevel@tonic-gate 0, 0, 0) == -1) { 197*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "LIBSCF: $%s (%s): %s", 198*7c478bd9Sstevel@tonic-gate ENV_SCF_DEBUG, debug, 199*7c478bd9Sstevel@tonic-gate uu_strerror(uu_error())); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (!issetugid() && 203*7c478bd9Sstevel@tonic-gate (door_path = getenv(ENV_SCF_DOORPATH)) != NULL && 204*7c478bd9Sstevel@tonic-gate door_path[0] != 0) { 205*7c478bd9Sstevel@tonic-gate default_door_path = strdup(door_path); 206*7c478bd9Sstevel@tonic-gate if (default_door_path == NULL) 207*7c478bd9Sstevel@tonic-gate default_door_path = door_path; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate datael_pool = uu_list_pool_create("SUNW,libscf_datael", 211*7c478bd9Sstevel@tonic-gate sizeof (scf_datael_t), offsetof(scf_datael_t, rd_node), 212*7c478bd9Sstevel@tonic-gate NULL, UU_LIST_POOL_DEBUG); 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate iter_pool = uu_list_pool_create("SUNW,libscf_iter", 215*7c478bd9Sstevel@tonic-gate sizeof (scf_iter_t), offsetof(scf_iter_t, iter_node), 216*7c478bd9Sstevel@tonic-gate NULL, UU_LIST_POOL_DEBUG); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate assert_nolint(offsetof(scf_transaction_entry_t, 219*7c478bd9Sstevel@tonic-gate entry_property) == 0); 220*7c478bd9Sstevel@tonic-gate tran_entry_pool = uu_list_pool_create( 221*7c478bd9Sstevel@tonic-gate "SUNW,libscf_transaction_entity", 222*7c478bd9Sstevel@tonic-gate sizeof (scf_transaction_entry_t), 223*7c478bd9Sstevel@tonic-gate offsetof(scf_transaction_entry_t, entry_link), 224*7c478bd9Sstevel@tonic-gate transaction_entry_compare, UU_LIST_POOL_DEBUG); 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate if (datael_pool == NULL || iter_pool == NULL || 227*7c478bd9Sstevel@tonic-gate tran_entry_pool == NULL) { 228*7c478bd9Sstevel@tonic-gate lowlevel_inited = -1; 229*7c478bd9Sstevel@tonic-gate goto end; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if (!scf_setup_error()) { 233*7c478bd9Sstevel@tonic-gate lowlevel_inited = -1; 234*7c478bd9Sstevel@tonic-gate goto end; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate lowlevel_inited = 1; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate end: 239*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&lowlevel_init_lock); 240*7c478bd9Sstevel@tonic-gate if (lowlevel_inited > 0) 241*7c478bd9Sstevel@tonic-gate return (1); 242*7c478bd9Sstevel@tonic-gate return (0); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate static const struct { 246*7c478bd9Sstevel@tonic-gate scf_type_t ti_type; 247*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t ti_proto_type; 248*7c478bd9Sstevel@tonic-gate const char *ti_name; 249*7c478bd9Sstevel@tonic-gate } scf_type_info[] = { 250*7c478bd9Sstevel@tonic-gate {SCF_TYPE_BOOLEAN, REP_PROTOCOL_TYPE_BOOLEAN, "boolean"}, 251*7c478bd9Sstevel@tonic-gate {SCF_TYPE_COUNT, REP_PROTOCOL_TYPE_COUNT, "count"}, 252*7c478bd9Sstevel@tonic-gate {SCF_TYPE_INTEGER, REP_PROTOCOL_TYPE_INTEGER, "integer"}, 253*7c478bd9Sstevel@tonic-gate {SCF_TYPE_TIME, REP_PROTOCOL_TYPE_TIME, "time"}, 254*7c478bd9Sstevel@tonic-gate {SCF_TYPE_ASTRING, REP_PROTOCOL_TYPE_STRING, "astring"}, 255*7c478bd9Sstevel@tonic-gate {SCF_TYPE_OPAQUE, REP_PROTOCOL_TYPE_OPAQUE, "opaque"}, 256*7c478bd9Sstevel@tonic-gate {SCF_TYPE_USTRING, REP_PROTOCOL_SUBTYPE_USTRING, "ustring"}, 257*7c478bd9Sstevel@tonic-gate {SCF_TYPE_URI, REP_PROTOCOL_SUBTYPE_URI, "uri"}, 258*7c478bd9Sstevel@tonic-gate {SCF_TYPE_FMRI, REP_PROTOCOL_SUBTYPE_FMRI, "fmri"}, 259*7c478bd9Sstevel@tonic-gate {SCF_TYPE_HOST, REP_PROTOCOL_SUBTYPE_HOST, "host"}, 260*7c478bd9Sstevel@tonic-gate {SCF_TYPE_HOSTNAME, REP_PROTOCOL_SUBTYPE_HOSTNAME, "hostname"}, 261*7c478bd9Sstevel@tonic-gate {SCF_TYPE_NET_ADDR_V4, REP_PROTOCOL_SUBTYPE_NETADDR_V4, 262*7c478bd9Sstevel@tonic-gate "net_address_v4"}, 263*7c478bd9Sstevel@tonic-gate {SCF_TYPE_NET_ADDR_V6, REP_PROTOCOL_SUBTYPE_NETADDR_V6, 264*7c478bd9Sstevel@tonic-gate "net_address_v6"} 265*7c478bd9Sstevel@tonic-gate }; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate #define SCF_TYPE_INFO_COUNT (sizeof (scf_type_info) / sizeof (*scf_type_info)) 268*7c478bd9Sstevel@tonic-gate static rep_protocol_value_type_t 269*7c478bd9Sstevel@tonic-gate scf_type_to_protocol_type(scf_type_t t) 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate int i; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate for (i = 0; i < SCF_TYPE_INFO_COUNT; i++) 274*7c478bd9Sstevel@tonic-gate if (scf_type_info[i].ti_type == t) 275*7c478bd9Sstevel@tonic-gate return (scf_type_info[i].ti_proto_type); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_TYPE_INVALID); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate static scf_type_t 281*7c478bd9Sstevel@tonic-gate scf_protocol_type_to_type(rep_protocol_value_type_t t) 282*7c478bd9Sstevel@tonic-gate { 283*7c478bd9Sstevel@tonic-gate int i; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate for (i = 0; i < SCF_TYPE_INFO_COUNT; i++) 286*7c478bd9Sstevel@tonic-gate if (scf_type_info[i].ti_proto_type == t) 287*7c478bd9Sstevel@tonic-gate return (scf_type_info[i].ti_type); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate return (SCF_TYPE_INVALID); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate const char * 293*7c478bd9Sstevel@tonic-gate scf_type_to_string(scf_type_t ty) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate int i; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate for (i = 0; i < SCF_TYPE_INFO_COUNT; i++) 298*7c478bd9Sstevel@tonic-gate if (scf_type_info[i].ti_type == ty) 299*7c478bd9Sstevel@tonic-gate return (scf_type_info[i].ti_name); 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate return ("unknown"); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate scf_type_t 305*7c478bd9Sstevel@tonic-gate scf_string_to_type(const char *name) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate int i; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (scf_type_info) / sizeof (*scf_type_info); i++) 310*7c478bd9Sstevel@tonic-gate if (strcmp(scf_type_info[i].ti_name, name) == 0) 311*7c478bd9Sstevel@tonic-gate return (scf_type_info[i].ti_type); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate return (SCF_TYPE_INVALID); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate int 317*7c478bd9Sstevel@tonic-gate scf_type_base_type(scf_type_t type, scf_type_t *out) 318*7c478bd9Sstevel@tonic-gate { 319*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t t = scf_type_to_protocol_type(type); 320*7c478bd9Sstevel@tonic-gate if (t == REP_PROTOCOL_TYPE_INVALID) 321*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate *out = scf_protocol_type_to_type(scf_proto_underlying_type(t)); 324*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * Convert a protocol error code into an SCF_ERROR_* code. 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate static scf_error_t 331*7c478bd9Sstevel@tonic-gate proto_error(rep_protocol_responseid_t e) 332*7c478bd9Sstevel@tonic-gate { 333*7c478bd9Sstevel@tonic-gate switch (e) { 334*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_MISORDERED: 335*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_UNKNOWN_ID: 336*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_INVALID_TYPE: 337*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_TRUNCATED: 338*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_TYPE_MISMATCH: 339*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NOT_APPLICABLE: 340*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_UNKNOWN: 341*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_INTERNAL); 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_BAD_TX: 344*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_INVALID_ARGUMENT); 345*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_BAD_REQUEST: 346*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_INVALID_ARGUMENT); 347*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NO_RESOURCES: 348*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_NO_RESOURCES); 349*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NOT_FOUND: 350*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_NOT_FOUND); 351*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_DELETED: 352*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_DELETED); 353*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NOT_SET: 354*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_NOT_SET); 355*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_EXISTS: 356*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_EXISTS); 357*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_DUPLICATE_ID: 358*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_EXISTS); 359*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_PERMISSION_DENIED: 360*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_PERMISSION_DENIED); 361*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_BACKEND_ACCESS: 362*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_BACKEND_ACCESS); 363*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_BACKEND_READONLY: 364*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_BACKEND_READONLY); 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_SUCCESS: 367*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_DONE: 368*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NOT_LATEST: /* TX code should handle this */ 369*7c478bd9Sstevel@tonic-gate default: 370*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 371*7c478bd9Sstevel@tonic-gate uu_warn("%s:%d: Bad error code %d passed to proto_error().\n", 372*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__, e); 373*7c478bd9Sstevel@tonic-gate #endif 374*7c478bd9Sstevel@tonic-gate abort(); 375*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate ssize_t 380*7c478bd9Sstevel@tonic-gate scf_limit(uint32_t limit) 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate switch (limit) { 383*7c478bd9Sstevel@tonic-gate case SCF_LIMIT_MAX_NAME_LENGTH: 384*7c478bd9Sstevel@tonic-gate case SCF_LIMIT_MAX_PG_TYPE_LENGTH: 385*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_NAME_LEN - 1); 386*7c478bd9Sstevel@tonic-gate case SCF_LIMIT_MAX_VALUE_LENGTH: 387*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_VALUE_LEN - 1); 388*7c478bd9Sstevel@tonic-gate case SCF_LIMIT_MAX_FMRI_LENGTH: 389*7c478bd9Sstevel@tonic-gate return (SCF_FMRI_PREFIX_MAX_LEN + 390*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SCOPE_PREFIX) - 1 + 391*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SCOPE_SUFFIX) - 1 + 392*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SERVICE_PREFIX) - 1 + 393*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_INSTANCE_PREFIX) - 1 + 394*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_PROPERTYGRP_PREFIX) - 1 + 395*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_PROPERTY_PREFIX) - 1 + 396*7c478bd9Sstevel@tonic-gate 5 * (REP_PROTOCOL_NAME_LEN - 1)); 397*7c478bd9Sstevel@tonic-gate default: 398*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate static size_t 403*7c478bd9Sstevel@tonic-gate scf_opaque_decode(char *out_arg, const char *in, size_t max_out) 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate char a, b; 406*7c478bd9Sstevel@tonic-gate char *out = out_arg; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate while (max_out > 0 && (a = in[0]) != 0 && (b = in[1]) != 0) { 409*7c478bd9Sstevel@tonic-gate in += 2; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate if (a >= '0' && a <= '9') 412*7c478bd9Sstevel@tonic-gate a -= '0'; 413*7c478bd9Sstevel@tonic-gate else if (a >= 'a' && a <= 'f') 414*7c478bd9Sstevel@tonic-gate a = a - 'a' + 10; 415*7c478bd9Sstevel@tonic-gate else if (a >= 'A' && a <= 'F') 416*7c478bd9Sstevel@tonic-gate a = a - 'A' + 10; 417*7c478bd9Sstevel@tonic-gate else 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate if (b >= '0' && b <= '9') 421*7c478bd9Sstevel@tonic-gate b -= '0'; 422*7c478bd9Sstevel@tonic-gate else if (b >= 'a' && b <= 'f') 423*7c478bd9Sstevel@tonic-gate b = b - 'a' + 10; 424*7c478bd9Sstevel@tonic-gate else if (b >= 'A' && b <= 'F') 425*7c478bd9Sstevel@tonic-gate b = b - 'A' + 10; 426*7c478bd9Sstevel@tonic-gate else 427*7c478bd9Sstevel@tonic-gate break; 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate *out++ = (a << 4) | b; 430*7c478bd9Sstevel@tonic-gate max_out--; 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate return (out - out_arg); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate static size_t 437*7c478bd9Sstevel@tonic-gate scf_opaque_encode(char *out_arg, const char *in_arg, size_t in_sz) 438*7c478bd9Sstevel@tonic-gate { 439*7c478bd9Sstevel@tonic-gate uint8_t *in = (uint8_t *)in_arg; 440*7c478bd9Sstevel@tonic-gate uint8_t *end = in + in_sz; 441*7c478bd9Sstevel@tonic-gate char *out = out_arg; 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate if (out == NULL) 444*7c478bd9Sstevel@tonic-gate return (2 * in_sz); 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate while (in < end) { 447*7c478bd9Sstevel@tonic-gate uint8_t c = *in++; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate uint8_t a = (c & 0xf0) >> 4; 450*7c478bd9Sstevel@tonic-gate uint8_t b = (c & 0x0f); 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (a <= 9) 453*7c478bd9Sstevel@tonic-gate *out++ = a + '0'; 454*7c478bd9Sstevel@tonic-gate else 455*7c478bd9Sstevel@tonic-gate *out++ = a + 'a' - 10; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (b <= 9) 458*7c478bd9Sstevel@tonic-gate *out++ = b + '0'; 459*7c478bd9Sstevel@tonic-gate else 460*7c478bd9Sstevel@tonic-gate *out++ = b + 'a' - 10; 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate *out = 0; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate return (out - out_arg); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate static void 469*7c478bd9Sstevel@tonic-gate handle_do_close(scf_handle_t *h) 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 472*7c478bd9Sstevel@tonic-gate assert(h->rh_doorfd != -1); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* 475*7c478bd9Sstevel@tonic-gate * if there are any active FD users, we just move the FD over 476*7c478bd9Sstevel@tonic-gate * to rh_doorfd_old -- they'll close it when they finish. 477*7c478bd9Sstevel@tonic-gate */ 478*7c478bd9Sstevel@tonic-gate if (h->rh_fd_users > 0) { 479*7c478bd9Sstevel@tonic-gate h->rh_doorfd_old = h->rh_doorfd; 480*7c478bd9Sstevel@tonic-gate h->rh_doorfd = -1; 481*7c478bd9Sstevel@tonic-gate } else { 482*7c478bd9Sstevel@tonic-gate assert(h->rh_doorfd_old == -1); 483*7c478bd9Sstevel@tonic-gate (void) close(h->rh_doorfd); 484*7c478bd9Sstevel@tonic-gate h->rh_doorfd = -1; 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * Check if a handle is currently bound. fork()ing implicitly unbinds 490*7c478bd9Sstevel@tonic-gate * the handle in the child. 491*7c478bd9Sstevel@tonic-gate */ 492*7c478bd9Sstevel@tonic-gate static int 493*7c478bd9Sstevel@tonic-gate handle_is_bound(scf_handle_t *h) 494*7c478bd9Sstevel@tonic-gate { 495*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate if (h->rh_doorfd == -1) 498*7c478bd9Sstevel@tonic-gate return (0); 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate if (getpid() == h->rh_doorpid) 501*7c478bd9Sstevel@tonic-gate return (1); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate /* forked since our last bind -- initiate handle close */ 504*7c478bd9Sstevel@tonic-gate handle_do_close(h); 505*7c478bd9Sstevel@tonic-gate return (0); 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate static int 509*7c478bd9Sstevel@tonic-gate handle_has_server(scf_handle_t *h) 510*7c478bd9Sstevel@tonic-gate { 511*7c478bd9Sstevel@tonic-gate door_info_t i; 512*7c478bd9Sstevel@tonic-gate int ret; 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 515*7c478bd9Sstevel@tonic-gate ret = (handle_is_bound(h) && door_info(h->rh_doorfd, &i) != -1 && 516*7c478bd9Sstevel@tonic-gate i.di_target != -1); 517*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate return (ret); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate /* 523*7c478bd9Sstevel@tonic-gate * This makes a door request on the client door associated with handle h. 524*7c478bd9Sstevel@tonic-gate * It will automatically retry calls which fail on EINTR. If h is not bound, 525*7c478bd9Sstevel@tonic-gate * returns NOT_BOUND. If the door call fails or the server response is too 526*7c478bd9Sstevel@tonic-gate * small, returns CALL_FAILED. If the server response is too big, truncates the 527*7c478bd9Sstevel@tonic-gate * response and returns RESULT_TOO_BIG. Otherwise, the size of the result is 528*7c478bd9Sstevel@tonic-gate * returned. 529*7c478bd9Sstevel@tonic-gate */ 530*7c478bd9Sstevel@tonic-gate static ssize_t 531*7c478bd9Sstevel@tonic-gate make_door_call(scf_handle_t *h, const void *req, size_t req_sz, 532*7c478bd9Sstevel@tonic-gate void *res, size_t res_sz) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate door_arg_t arg; 535*7c478bd9Sstevel@tonic-gate int r; 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(h)) { 540*7c478bd9Sstevel@tonic-gate return (NOT_BOUND); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate arg.data_ptr = (void *)req; 544*7c478bd9Sstevel@tonic-gate arg.data_size = req_sz; 545*7c478bd9Sstevel@tonic-gate arg.desc_ptr = NULL; 546*7c478bd9Sstevel@tonic-gate arg.desc_num = 0; 547*7c478bd9Sstevel@tonic-gate arg.rbuf = res; 548*7c478bd9Sstevel@tonic-gate arg.rsize = res_sz; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate while ((r = door_call(h->rh_doorfd, &arg)) < 0) { 551*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 552*7c478bd9Sstevel@tonic-gate break; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (r < 0) { 556*7c478bd9Sstevel@tonic-gate return (CALL_FAILED); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if (arg.desc_num > 0) { 560*7c478bd9Sstevel@tonic-gate while (arg.desc_num > 0) { 561*7c478bd9Sstevel@tonic-gate if (arg.desc_ptr->d_attributes & DOOR_DESCRIPTOR) { 562*7c478bd9Sstevel@tonic-gate int cfd = arg.desc_ptr->d_data.d_desc.d_id; 563*7c478bd9Sstevel@tonic-gate (void) close(cfd); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate arg.desc_ptr++; 566*7c478bd9Sstevel@tonic-gate arg.desc_num--; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate } 569*7c478bd9Sstevel@tonic-gate if (arg.data_ptr != res && arg.data_size > 0) 570*7c478bd9Sstevel@tonic-gate (void) memmove(res, arg.data_ptr, MIN(arg.data_size, res_sz)); 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if (arg.rbuf != res) 573*7c478bd9Sstevel@tonic-gate (void) munmap(arg.rbuf, arg.rsize); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate if (arg.data_size > res_sz) 576*7c478bd9Sstevel@tonic-gate return (RESULT_TOO_BIG); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate if (arg.data_size < sizeof (uint32_t)) 579*7c478bd9Sstevel@tonic-gate return (CALL_FAILED); 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate return (arg.data_size); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate /* 585*7c478bd9Sstevel@tonic-gate * Should only be used when r < 0. 586*7c478bd9Sstevel@tonic-gate */ 587*7c478bd9Sstevel@tonic-gate #define DOOR_ERRORS_BLOCK(r) { \ 588*7c478bd9Sstevel@tonic-gate switch (r) { \ 589*7c478bd9Sstevel@tonic-gate case NOT_BOUND: \ 590*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_BOUND)); \ 591*7c478bd9Sstevel@tonic-gate \ 592*7c478bd9Sstevel@tonic-gate case CALL_FAILED: \ 593*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONNECTION_BROKEN)); \ 594*7c478bd9Sstevel@tonic-gate \ 595*7c478bd9Sstevel@tonic-gate case RESULT_TOO_BIG: \ 596*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); \ 597*7c478bd9Sstevel@tonic-gate \ 598*7c478bd9Sstevel@tonic-gate default: \ 599*7c478bd9Sstevel@tonic-gate assert(r == NOT_BOUND || r == CALL_FAILED || \ 600*7c478bd9Sstevel@tonic-gate r == RESULT_TOO_BIG); \ 601*7c478bd9Sstevel@tonic-gate abort(); \ 602*7c478bd9Sstevel@tonic-gate } \ 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate /* 606*7c478bd9Sstevel@tonic-gate * Like make_door_call(), but takes an fd instead of a handle, and expects 607*7c478bd9Sstevel@tonic-gate * a single file descriptor, returned via res_fd. 608*7c478bd9Sstevel@tonic-gate * 609*7c478bd9Sstevel@tonic-gate * If no file descriptor is returned, *res_fd == -1. 610*7c478bd9Sstevel@tonic-gate */ 611*7c478bd9Sstevel@tonic-gate static int 612*7c478bd9Sstevel@tonic-gate make_door_call_retfd(int fd, const void *req, size_t req_sz, void *res, 613*7c478bd9Sstevel@tonic-gate size_t res_sz, int *res_fd) 614*7c478bd9Sstevel@tonic-gate { 615*7c478bd9Sstevel@tonic-gate door_arg_t arg; 616*7c478bd9Sstevel@tonic-gate int r; 617*7c478bd9Sstevel@tonic-gate char rbuf[256]; 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate *res_fd = -1; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate if (fd == -1) 622*7c478bd9Sstevel@tonic-gate return (NOT_BOUND); 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate arg.data_ptr = (void *)req; 625*7c478bd9Sstevel@tonic-gate arg.data_size = req_sz; 626*7c478bd9Sstevel@tonic-gate arg.desc_ptr = NULL; 627*7c478bd9Sstevel@tonic-gate arg.desc_num = 0; 628*7c478bd9Sstevel@tonic-gate arg.rbuf = rbuf; 629*7c478bd9Sstevel@tonic-gate arg.rsize = sizeof (rbuf); 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate while ((r = door_call(fd, &arg)) < 0) { 632*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 633*7c478bd9Sstevel@tonic-gate break; 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate if (r < 0) 637*7c478bd9Sstevel@tonic-gate return (CALL_FAILED); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate if (arg.desc_num > 1) { 640*7c478bd9Sstevel@tonic-gate while (arg.desc_num > 0) { 641*7c478bd9Sstevel@tonic-gate if (arg.desc_ptr->d_attributes & DOOR_DESCRIPTOR) { 642*7c478bd9Sstevel@tonic-gate int cfd = 643*7c478bd9Sstevel@tonic-gate arg.desc_ptr->d_data.d_desc.d_descriptor; 644*7c478bd9Sstevel@tonic-gate (void) close(cfd); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate arg.desc_ptr++; 647*7c478bd9Sstevel@tonic-gate arg.desc_num--; 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate if (arg.desc_num == 1 && arg.desc_ptr->d_attributes & DOOR_DESCRIPTOR) 651*7c478bd9Sstevel@tonic-gate *res_fd = arg.desc_ptr->d_data.d_desc.d_descriptor; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate if (arg.data_size > 0) 654*7c478bd9Sstevel@tonic-gate (void) memmove(res, arg.data_ptr, MIN(arg.data_size, res_sz)); 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate if (arg.rbuf != rbuf) 657*7c478bd9Sstevel@tonic-gate (void) munmap(arg.rbuf, arg.rsize); 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate if (arg.data_size > res_sz) 660*7c478bd9Sstevel@tonic-gate return (RESULT_TOO_BIG); 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate if (arg.data_size < sizeof (uint32_t)) 663*7c478bd9Sstevel@tonic-gate return (CALL_FAILED); 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate return (arg.data_size); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate /* 669*7c478bd9Sstevel@tonic-gate * Fails with 670*7c478bd9Sstevel@tonic-gate * _VERSION_MISMATCH 671*7c478bd9Sstevel@tonic-gate * _NO_MEMORY 672*7c478bd9Sstevel@tonic-gate */ 673*7c478bd9Sstevel@tonic-gate scf_handle_t * 674*7c478bd9Sstevel@tonic-gate scf_handle_create(scf_version_t v) 675*7c478bd9Sstevel@tonic-gate { 676*7c478bd9Sstevel@tonic-gate scf_handle_t *ret; 677*7c478bd9Sstevel@tonic-gate int failed; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* 680*7c478bd9Sstevel@tonic-gate * This will need to be revisited when we bump SCF_VERSION 681*7c478bd9Sstevel@tonic-gate */ 682*7c478bd9Sstevel@tonic-gate if (v != SCF_VERSION) { 683*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_VERSION_MISMATCH); 684*7c478bd9Sstevel@tonic-gate return (NULL); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate if (!lowlevel_init()) { 688*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 689*7c478bd9Sstevel@tonic-gate return (NULL); 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 693*7c478bd9Sstevel@tonic-gate if (ret == NULL) { 694*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 695*7c478bd9Sstevel@tonic-gate return (NULL); 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate ret->rh_dataels = uu_list_create(datael_pool, ret, 0); 699*7c478bd9Sstevel@tonic-gate ret->rh_iters = uu_list_create(iter_pool, ret, 0); 700*7c478bd9Sstevel@tonic-gate if (ret->rh_dataels == NULL || ret->rh_iters == NULL) { 701*7c478bd9Sstevel@tonic-gate if (ret->rh_dataels != NULL) 702*7c478bd9Sstevel@tonic-gate uu_list_destroy(ret->rh_dataels); 703*7c478bd9Sstevel@tonic-gate if (ret->rh_iters != NULL) 704*7c478bd9Sstevel@tonic-gate uu_list_destroy(ret->rh_iters); 705*7c478bd9Sstevel@tonic-gate uu_free(ret); 706*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 707*7c478bd9Sstevel@tonic-gate return (NULL); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate ret->rh_doorfd = -1; 711*7c478bd9Sstevel@tonic-gate ret->rh_doorfd_old = -1; 712*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&ret->rh_lock, NULL); 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate handle_hold_subhandles(ret, RH_HOLD_ALL); 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate failed = ((ret->rh_iter = scf_iter_create(ret)) == NULL || 717*7c478bd9Sstevel@tonic-gate (ret->rh_scope = scf_scope_create(ret)) == NULL || 718*7c478bd9Sstevel@tonic-gate (ret->rh_service = scf_service_create(ret)) == NULL || 719*7c478bd9Sstevel@tonic-gate (ret->rh_instance = scf_instance_create(ret)) == NULL || 720*7c478bd9Sstevel@tonic-gate (ret->rh_snapshot = scf_snapshot_create(ret)) == NULL || 721*7c478bd9Sstevel@tonic-gate (ret->rh_snaplvl = scf_snaplevel_create(ret)) == NULL || 722*7c478bd9Sstevel@tonic-gate (ret->rh_pg = scf_pg_create(ret)) == NULL || 723*7c478bd9Sstevel@tonic-gate (ret->rh_property = scf_property_create(ret)) == NULL || 724*7c478bd9Sstevel@tonic-gate (ret->rh_value = scf_value_create(ret)) == NULL); 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate /* 727*7c478bd9Sstevel@tonic-gate * these subhandles count as internal references, not external ones. 728*7c478bd9Sstevel@tonic-gate */ 729*7c478bd9Sstevel@tonic-gate ret->rh_intrefs = ret->rh_extrefs; 730*7c478bd9Sstevel@tonic-gate ret->rh_extrefs = 0; 731*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(ret, RH_HOLD_ALL); 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate if (failed) { 734*7c478bd9Sstevel@tonic-gate scf_handle_destroy(ret); 735*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 736*7c478bd9Sstevel@tonic-gate return (NULL); 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate scf_value_set_count(ret->rh_value, default_debug); 740*7c478bd9Sstevel@tonic-gate (void) scf_handle_decorate(ret, "debug", ret->rh_value); 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate return (ret); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate int 746*7c478bd9Sstevel@tonic-gate scf_handle_decorate(scf_handle_t *handle, const char *name, scf_value_t *v) 747*7c478bd9Sstevel@tonic-gate { 748*7c478bd9Sstevel@tonic-gate if (v != SCF_DECORATE_CLEAR && handle != v->value_handle) 749*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 752*7c478bd9Sstevel@tonic-gate if (handle_is_bound(handle)) { 753*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 754*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_IN_USE)); 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate if (strcmp(name, "debug") == 0) { 759*7c478bd9Sstevel@tonic-gate if (v == SCF_DECORATE_CLEAR) { 760*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 761*7c478bd9Sstevel@tonic-gate handle->rh_debug = 0; 762*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 763*7c478bd9Sstevel@tonic-gate } else { 764*7c478bd9Sstevel@tonic-gate uint64_t val; 765*7c478bd9Sstevel@tonic-gate if (scf_value_get_count(v, &val) < 0) 766*7c478bd9Sstevel@tonic-gate return (-1); /* error already set */ 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 769*7c478bd9Sstevel@tonic-gate handle->rh_debug = (uid_t)val; 770*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate return (0); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate if (strcmp(name, "door_path") == 0) { 775*7c478bd9Sstevel@tonic-gate char name[sizeof (handle->rh_doorpath)]; 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate if (v == SCF_DECORATE_CLEAR) { 778*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 779*7c478bd9Sstevel@tonic-gate handle->rh_doorpath[0] = 0; 780*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 781*7c478bd9Sstevel@tonic-gate } else { 782*7c478bd9Sstevel@tonic-gate ssize_t len; 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate if ((len = scf_value_get_astring(v, name, 785*7c478bd9Sstevel@tonic-gate sizeof (name))) < 0) { 786*7c478bd9Sstevel@tonic-gate return (-1); /* error already set */ 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate if (len == 0 || len >= sizeof (name)) { 789*7c478bd9Sstevel@tonic-gate return (scf_set_error( 790*7c478bd9Sstevel@tonic-gate SCF_ERROR_INVALID_ARGUMENT)); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 793*7c478bd9Sstevel@tonic-gate (void) strlcpy(handle->rh_doorpath, name, 794*7c478bd9Sstevel@tonic-gate sizeof (handle->rh_doorpath)); 795*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate return (0); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 800*7c478bd9Sstevel@tonic-gate } 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate /* 803*7c478bd9Sstevel@tonic-gate * fails with INVALID_ARGUMENT and HANDLE_MISMATCH. 804*7c478bd9Sstevel@tonic-gate */ 805*7c478bd9Sstevel@tonic-gate int 806*7c478bd9Sstevel@tonic-gate _scf_handle_decorations(scf_handle_t *handle, scf_decoration_func *f, 807*7c478bd9Sstevel@tonic-gate scf_value_t *v, void *data) 808*7c478bd9Sstevel@tonic-gate { 809*7c478bd9Sstevel@tonic-gate scf_decoration_info_t i; 810*7c478bd9Sstevel@tonic-gate char name[sizeof (handle->rh_doorpath)]; 811*7c478bd9Sstevel@tonic-gate uint64_t debug; 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate if (f == NULL || v == NULL) 814*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate if (v->value_handle != handle) 817*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate i.sdi_name = (const char *)"debug"; 820*7c478bd9Sstevel@tonic-gate i.sdi_type = SCF_TYPE_COUNT; 821*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 822*7c478bd9Sstevel@tonic-gate debug = handle->rh_debug; 823*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 824*7c478bd9Sstevel@tonic-gate if (debug != 0) { 825*7c478bd9Sstevel@tonic-gate scf_value_set_count(v, debug); 826*7c478bd9Sstevel@tonic-gate i.sdi_value = v; 827*7c478bd9Sstevel@tonic-gate } else { 828*7c478bd9Sstevel@tonic-gate i.sdi_value = SCF_DECORATE_CLEAR; 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate if ((*f)(&i, data) == 0) 832*7c478bd9Sstevel@tonic-gate return (0); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate i.sdi_name = (const char *)"door_path"; 835*7c478bd9Sstevel@tonic-gate i.sdi_type = SCF_TYPE_ASTRING; 836*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 837*7c478bd9Sstevel@tonic-gate (void) strlcpy(name, handle->rh_doorpath, sizeof (name)); 838*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 839*7c478bd9Sstevel@tonic-gate if (name[0] != 0) { 840*7c478bd9Sstevel@tonic-gate (void) scf_value_set_astring(v, name); 841*7c478bd9Sstevel@tonic-gate i.sdi_value = v; 842*7c478bd9Sstevel@tonic-gate } else { 843*7c478bd9Sstevel@tonic-gate i.sdi_value = SCF_DECORATE_CLEAR; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate if ((*f)(&i, data) == 0) 847*7c478bd9Sstevel@tonic-gate return (0); 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate return (1); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * Fails if handle is not bound. 854*7c478bd9Sstevel@tonic-gate */ 855*7c478bd9Sstevel@tonic-gate static int 856*7c478bd9Sstevel@tonic-gate handle_unbind_unlocked(scf_handle_t *handle) 857*7c478bd9Sstevel@tonic-gate { 858*7c478bd9Sstevel@tonic-gate rep_protocol_request_t request; 859*7c478bd9Sstevel@tonic-gate rep_protocol_response_t response; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(handle)) 862*7c478bd9Sstevel@tonic-gate return (-1); 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_CLOSE; 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate (void) make_door_call(handle, &request, sizeof (request), 867*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate handle_do_close(handle); 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate /* 875*7c478bd9Sstevel@tonic-gate * Fails with 876*7c478bd9Sstevel@tonic-gate * _HANDLE_DESTROYED - dp's handle has been destroyed 877*7c478bd9Sstevel@tonic-gate * _INTERNAL - server response too big 878*7c478bd9Sstevel@tonic-gate * entity already set up with different type 879*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES - server out of memory 880*7c478bd9Sstevel@tonic-gate */ 881*7c478bd9Sstevel@tonic-gate static int 882*7c478bd9Sstevel@tonic-gate datael_attach(scf_datael_t *dp) 883*7c478bd9Sstevel@tonic-gate { 884*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_setup request; 887*7c478bd9Sstevel@tonic-gate rep_protocol_response_t response; 888*7c478bd9Sstevel@tonic-gate ssize_t r; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate dp->rd_reset = 0; /* setup implicitly resets */ 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate if (h->rh_flags & HANDLE_DEAD) 895*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_DESTROYED)); 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(h)) 898*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); /* nothing to do */ 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_SETUP; 901*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 902*7c478bd9Sstevel@tonic-gate request.rpr_entitytype = dp->rd_type; 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 905*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate if (r == NOT_BOUND || r == CALL_FAILED) 908*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 909*7c478bd9Sstevel@tonic-gate if (r == RESULT_TOO_BIG) 910*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 913*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate /* 919*7c478bd9Sstevel@tonic-gate * Fails with 920*7c478bd9Sstevel@tonic-gate * _HANDLE_DESTROYED - iter's handle has been destroyed 921*7c478bd9Sstevel@tonic-gate * _INTERNAL - server response too big 922*7c478bd9Sstevel@tonic-gate * iter already existed 923*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 924*7c478bd9Sstevel@tonic-gate */ 925*7c478bd9Sstevel@tonic-gate static int 926*7c478bd9Sstevel@tonic-gate iter_attach(scf_iter_t *iter) 927*7c478bd9Sstevel@tonic-gate { 928*7c478bd9Sstevel@tonic-gate scf_handle_t *h = iter->iter_handle; 929*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_request request; 930*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 931*7c478bd9Sstevel@tonic-gate int r; 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate if (h->rh_flags & HANDLE_DEAD) 936*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_DESTROYED)); 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(h)) 939*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); /* nothing to do */ 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_SETUP; 942*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 945*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if (r == NOT_BOUND || r == CALL_FAILED) 948*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 949*7c478bd9Sstevel@tonic-gate if (r == RESULT_TOO_BIG) 950*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 953*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate /* 959*7c478bd9Sstevel@tonic-gate * Fails with 960*7c478bd9Sstevel@tonic-gate * _IN_USE - handle already bound 961*7c478bd9Sstevel@tonic-gate * _NO_SERVER - server door could not be open()ed 962*7c478bd9Sstevel@tonic-gate * door call failed 963*7c478bd9Sstevel@tonic-gate * door_info() failed 964*7c478bd9Sstevel@tonic-gate * _VERSION_MISMATCH - server returned bad file descriptor 965*7c478bd9Sstevel@tonic-gate * server claimed bad request 966*7c478bd9Sstevel@tonic-gate * server reported version mismatch 967*7c478bd9Sstevel@tonic-gate * server refused with unknown reason 968*7c478bd9Sstevel@tonic-gate * _INVALID_ARGUMENT 969*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES - server is out of memory 970*7c478bd9Sstevel@tonic-gate * _PERMISSION_DENIED 971*7c478bd9Sstevel@tonic-gate * _INTERNAL - could not set up entities or iters 972*7c478bd9Sstevel@tonic-gate * server response too big 973*7c478bd9Sstevel@tonic-gate * 974*7c478bd9Sstevel@tonic-gate * perhaps this should try multiple times. 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate int 977*7c478bd9Sstevel@tonic-gate scf_handle_bind(scf_handle_t *handle) 978*7c478bd9Sstevel@tonic-gate { 979*7c478bd9Sstevel@tonic-gate scf_datael_t *el; 980*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate pid_t pid; 983*7c478bd9Sstevel@tonic-gate int fd; 984*7c478bd9Sstevel@tonic-gate int res; 985*7c478bd9Sstevel@tonic-gate door_info_t info; 986*7c478bd9Sstevel@tonic-gate repository_door_request_t request; 987*7c478bd9Sstevel@tonic-gate repository_door_response_t response; 988*7c478bd9Sstevel@tonic-gate const char *door_name = default_door_path; 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 991*7c478bd9Sstevel@tonic-gate if (handle_is_bound(handle)) { 992*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 993*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_IN_USE)); 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate /* wait until any active fd users have cleared out */ 997*7c478bd9Sstevel@tonic-gate while (handle->rh_fd_users > 0) 998*7c478bd9Sstevel@tonic-gate (void) PTHREAD_COND_WAIT(&handle->rh_cv, &handle->rh_lock); 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate /* check again, since we had to drop the lock */ 1001*7c478bd9Sstevel@tonic-gate if (handle_is_bound(handle)) { 1002*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1003*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_IN_USE)); 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate assert(handle->rh_doorfd == -1 && handle->rh_doorfd_old == -1); 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate if (handle->rh_doorpath[0] != 0) 1009*7c478bd9Sstevel@tonic-gate door_name = handle->rh_doorpath; 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate fd = open(door_name, O_RDONLY, 0); 1012*7c478bd9Sstevel@tonic-gate if (fd == -1) { 1013*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1014*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NO_SERVER)); 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate request.rdr_version = REPOSITORY_DOOR_VERSION; 1018*7c478bd9Sstevel@tonic-gate request.rdr_request = REPOSITORY_DOOR_REQUEST_CONNECT; 1019*7c478bd9Sstevel@tonic-gate request.rdr_flags = handle->rh_flags; 1020*7c478bd9Sstevel@tonic-gate request.rdr_debug = handle->rh_debug; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate pid = getpid(); 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate res = make_door_call_retfd(fd, &request, sizeof (request), 1025*7c478bd9Sstevel@tonic-gate &response, sizeof (response), &handle->rh_doorfd); 1026*7c478bd9Sstevel@tonic-gate 1027*7c478bd9Sstevel@tonic-gate (void) close(fd); 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate if (res < 0) { 1030*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate assert(res != NOT_BOUND); 1033*7c478bd9Sstevel@tonic-gate if (res == CALL_FAILED) 1034*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NO_SERVER)); 1035*7c478bd9Sstevel@tonic-gate assert(res == RESULT_TOO_BIG); 1036*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate if (handle->rh_doorfd < 0) { 1040*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate switch (response.rdr_status) { 1043*7c478bd9Sstevel@tonic-gate case REPOSITORY_DOOR_SUCCESS: 1044*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_VERSION_MISMATCH)); 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate case REPOSITORY_DOOR_FAIL_BAD_REQUEST: 1047*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_VERSION_MISMATCH)); 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate case REPOSITORY_DOOR_FAIL_VERSION_MISMATCH: 1050*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_VERSION_MISMATCH)); 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate case REPOSITORY_DOOR_FAIL_BAD_FLAG: 1053*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate case REPOSITORY_DOOR_FAIL_NO_RESOURCES: 1056*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NO_RESOURCES)); 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate case REPOSITORY_DOOR_FAIL_PERMISSION_DENIED: 1059*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_PERMISSION_DENIED)); 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate default: 1062*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_VERSION_MISMATCH)); 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate (void) fcntl(handle->rh_doorfd, F_SETFD, FD_CLOEXEC); 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate if (door_info(handle->rh_doorfd, &info) < 0) { 1069*7c478bd9Sstevel@tonic-gate (void) close(handle->rh_doorfd); 1070*7c478bd9Sstevel@tonic-gate handle->rh_doorfd = -1; 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1073*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NO_SERVER)); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate handle->rh_doorpid = pid; 1077*7c478bd9Sstevel@tonic-gate handle->rh_doorid = info.di_uniquifier; 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate /* 1080*7c478bd9Sstevel@tonic-gate * Now, re-attach everything 1081*7c478bd9Sstevel@tonic-gate */ 1082*7c478bd9Sstevel@tonic-gate for (el = uu_list_first(handle->rh_dataels); el != NULL; 1083*7c478bd9Sstevel@tonic-gate el = uu_list_next(handle->rh_dataels, el)) { 1084*7c478bd9Sstevel@tonic-gate if (datael_attach(el) == -1) { 1085*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_HANDLE_DESTROYED); 1086*7c478bd9Sstevel@tonic-gate (void) handle_unbind_unlocked(handle); 1087*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1088*7c478bd9Sstevel@tonic-gate return (-1); 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate for (iter = uu_list_first(handle->rh_iters); iter != NULL; 1093*7c478bd9Sstevel@tonic-gate iter = uu_list_next(handle->rh_iters, iter)) { 1094*7c478bd9Sstevel@tonic-gate if (iter_attach(iter) == -1) { 1095*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_HANDLE_DESTROYED); 1096*7c478bd9Sstevel@tonic-gate (void) handle_unbind_unlocked(handle); 1097*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1098*7c478bd9Sstevel@tonic-gate return (-1); 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate } 1101*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1102*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate int 1106*7c478bd9Sstevel@tonic-gate scf_handle_unbind(scf_handle_t *handle) 1107*7c478bd9Sstevel@tonic-gate { 1108*7c478bd9Sstevel@tonic-gate int ret; 1109*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 1110*7c478bd9Sstevel@tonic-gate ret = handle_unbind_unlocked(handle); 1111*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1112*7c478bd9Sstevel@tonic-gate return (ret == SCF_SUCCESS ? ret : scf_set_error(SCF_ERROR_NOT_BOUND)); 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate static scf_handle_t * 1116*7c478bd9Sstevel@tonic-gate handle_get(scf_handle_t *h) 1117*7c478bd9Sstevel@tonic-gate { 1118*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1119*7c478bd9Sstevel@tonic-gate if (h->rh_flags & HANDLE_DEAD) { 1120*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1121*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_HANDLE_DESTROYED); 1122*7c478bd9Sstevel@tonic-gate return (NULL); 1123*7c478bd9Sstevel@tonic-gate } 1124*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1125*7c478bd9Sstevel@tonic-gate return (h); 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate /* 1129*7c478bd9Sstevel@tonic-gate * Called when an object is removed from the handle. On the last remove, 1130*7c478bd9Sstevel@tonic-gate * cleans up and frees the handle. 1131*7c478bd9Sstevel@tonic-gate */ 1132*7c478bd9Sstevel@tonic-gate static void 1133*7c478bd9Sstevel@tonic-gate handle_unrefed(scf_handle_t *handle) 1134*7c478bd9Sstevel@tonic-gate { 1135*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 1136*7c478bd9Sstevel@tonic-gate scf_value_t *v; 1137*7c478bd9Sstevel@tonic-gate scf_scope_t *sc; 1138*7c478bd9Sstevel@tonic-gate scf_service_t *svc; 1139*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 1140*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 1141*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *snaplvl; 1142*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 1143*7c478bd9Sstevel@tonic-gate scf_property_t *prop; 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&handle->rh_lock)); 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate /* 1148*7c478bd9Sstevel@tonic-gate * Don't do anything if the handle has not yet been destroyed, there 1149*7c478bd9Sstevel@tonic-gate * are still external references, or we're already doing unrefed 1150*7c478bd9Sstevel@tonic-gate * handling. 1151*7c478bd9Sstevel@tonic-gate */ 1152*7c478bd9Sstevel@tonic-gate if (!(handle->rh_flags & HANDLE_DEAD) || 1153*7c478bd9Sstevel@tonic-gate handle->rh_extrefs > 0 || 1154*7c478bd9Sstevel@tonic-gate handle->rh_fd_users > 0 || 1155*7c478bd9Sstevel@tonic-gate (handle->rh_flags & HANDLE_UNREFED)) { 1156*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1157*7c478bd9Sstevel@tonic-gate return; 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate handle->rh_flags |= HANDLE_UNREFED; 1161*7c478bd9Sstevel@tonic-gate 1162*7c478bd9Sstevel@tonic-gate /* 1163*7c478bd9Sstevel@tonic-gate * Now that we know that there are no external references, and the 1164*7c478bd9Sstevel@tonic-gate * HANDLE_DEAD flag keeps new ones from appearing, we can clean up 1165*7c478bd9Sstevel@tonic-gate * our subhandles and destroy the handle completely. 1166*7c478bd9Sstevel@tonic-gate */ 1167*7c478bd9Sstevel@tonic-gate assert(handle->rh_intrefs >= 0); 1168*7c478bd9Sstevel@tonic-gate handle->rh_extrefs = handle->rh_intrefs; 1169*7c478bd9Sstevel@tonic-gate handle->rh_intrefs = 0; 1170*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate handle_hold_subhandles(handle, RH_HOLD_ALL); 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate iter = handle->rh_iter; 1175*7c478bd9Sstevel@tonic-gate sc = handle->rh_scope; 1176*7c478bd9Sstevel@tonic-gate svc = handle->rh_service; 1177*7c478bd9Sstevel@tonic-gate inst = handle->rh_instance; 1178*7c478bd9Sstevel@tonic-gate snap = handle->rh_snapshot; 1179*7c478bd9Sstevel@tonic-gate snaplvl = handle->rh_snaplvl; 1180*7c478bd9Sstevel@tonic-gate pg = handle->rh_pg; 1181*7c478bd9Sstevel@tonic-gate prop = handle->rh_property; 1182*7c478bd9Sstevel@tonic-gate v = handle->rh_value; 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate handle->rh_iter = NULL; 1185*7c478bd9Sstevel@tonic-gate handle->rh_scope = NULL; 1186*7c478bd9Sstevel@tonic-gate handle->rh_service = NULL; 1187*7c478bd9Sstevel@tonic-gate handle->rh_instance = NULL; 1188*7c478bd9Sstevel@tonic-gate handle->rh_snapshot = NULL; 1189*7c478bd9Sstevel@tonic-gate handle->rh_snaplvl = NULL; 1190*7c478bd9Sstevel@tonic-gate handle->rh_pg = NULL; 1191*7c478bd9Sstevel@tonic-gate handle->rh_property = NULL; 1192*7c478bd9Sstevel@tonic-gate handle->rh_value = NULL; 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate if (iter != NULL) 1195*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 1196*7c478bd9Sstevel@tonic-gate if (sc != NULL) 1197*7c478bd9Sstevel@tonic-gate scf_scope_destroy(sc); 1198*7c478bd9Sstevel@tonic-gate if (svc != NULL) 1199*7c478bd9Sstevel@tonic-gate scf_service_destroy(svc); 1200*7c478bd9Sstevel@tonic-gate if (inst != NULL) 1201*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 1202*7c478bd9Sstevel@tonic-gate if (snap != NULL) 1203*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 1204*7c478bd9Sstevel@tonic-gate if (snaplvl != NULL) 1205*7c478bd9Sstevel@tonic-gate scf_snaplevel_destroy(snaplvl); 1206*7c478bd9Sstevel@tonic-gate if (pg != NULL) 1207*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1208*7c478bd9Sstevel@tonic-gate if (prop != NULL) 1209*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1210*7c478bd9Sstevel@tonic-gate if (v != NULL) 1211*7c478bd9Sstevel@tonic-gate scf_value_destroy(v); 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate /* there should be no outstanding children at this point */ 1216*7c478bd9Sstevel@tonic-gate assert(handle->rh_extrefs == 0); 1217*7c478bd9Sstevel@tonic-gate assert(handle->rh_intrefs == 0); 1218*7c478bd9Sstevel@tonic-gate assert(handle->rh_values == 0); 1219*7c478bd9Sstevel@tonic-gate assert(handle->rh_entries == 0); 1220*7c478bd9Sstevel@tonic-gate assert(uu_list_numnodes(handle->rh_dataels) == 0); 1221*7c478bd9Sstevel@tonic-gate assert(uu_list_numnodes(handle->rh_iters) == 0); 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate uu_list_destroy(handle->rh_dataels); 1224*7c478bd9Sstevel@tonic-gate uu_list_destroy(handle->rh_iters); 1225*7c478bd9Sstevel@tonic-gate handle->rh_dataels = NULL; 1226*7c478bd9Sstevel@tonic-gate handle->rh_iters = NULL; 1227*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&handle->rh_lock); 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate uu_free(handle); 1232*7c478bd9Sstevel@tonic-gate } 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate void 1235*7c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_handle_t *handle) 1236*7c478bd9Sstevel@tonic-gate { 1237*7c478bd9Sstevel@tonic-gate if (handle == NULL) 1238*7c478bd9Sstevel@tonic-gate return; 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 1241*7c478bd9Sstevel@tonic-gate if (handle->rh_flags & HANDLE_DEAD) { 1242*7c478bd9Sstevel@tonic-gate /* 1243*7c478bd9Sstevel@tonic-gate * This is an error (you are not allowed to reference the 1244*7c478bd9Sstevel@tonic-gate * handle after it is destroyed), but we can't report it. 1245*7c478bd9Sstevel@tonic-gate */ 1246*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&handle->rh_lock); 1247*7c478bd9Sstevel@tonic-gate return; 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate handle->rh_flags |= HANDLE_DEAD; 1250*7c478bd9Sstevel@tonic-gate (void) handle_unbind_unlocked(handle); 1251*7c478bd9Sstevel@tonic-gate handle_unrefed(handle); 1252*7c478bd9Sstevel@tonic-gate } 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate ssize_t 1255*7c478bd9Sstevel@tonic-gate scf_myname(scf_handle_t *h, char *out, size_t len) 1256*7c478bd9Sstevel@tonic-gate { 1257*7c478bd9Sstevel@tonic-gate char *cp; 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate if (!handle_has_server(h)) 1260*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONNECTION_BROKEN)); 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate cp = getenv("SMF_FMRI"); 1263*7c478bd9Sstevel@tonic-gate if (cp == NULL) 1264*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate return (strlcpy(out, cp, len)); 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate static uint32_t 1270*7c478bd9Sstevel@tonic-gate handle_alloc_entityid(scf_handle_t *handle) 1271*7c478bd9Sstevel@tonic-gate { 1272*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&handle->rh_lock)); 1273*7c478bd9Sstevel@tonic-gate return (++handle->rh_nextentity); 1274*7c478bd9Sstevel@tonic-gate } 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate static uint32_t 1277*7c478bd9Sstevel@tonic-gate handle_alloc_iterid(scf_handle_t *handle) 1278*7c478bd9Sstevel@tonic-gate { 1279*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&handle->rh_lock)); 1280*7c478bd9Sstevel@tonic-gate return (++handle->rh_nextiter); 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate static uint32_t 1284*7c478bd9Sstevel@tonic-gate handle_alloc_changeid(scf_handle_t *handle) 1285*7c478bd9Sstevel@tonic-gate { 1286*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&handle->rh_lock)); 1287*7c478bd9Sstevel@tonic-gate return (++handle->rh_nextchangeid); 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* 1291*7c478bd9Sstevel@tonic-gate * Fails with 1292*7c478bd9Sstevel@tonic-gate * _INVALID_ARGUMENT - h is NULL 1293*7c478bd9Sstevel@tonic-gate * _HANDLE_DESTROYED 1294*7c478bd9Sstevel@tonic-gate * _INTERNAL - server response too big 1295*7c478bd9Sstevel@tonic-gate * entity already set up with different type 1296*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 1297*7c478bd9Sstevel@tonic-gate */ 1298*7c478bd9Sstevel@tonic-gate static int 1299*7c478bd9Sstevel@tonic-gate datael_init(scf_datael_t *dp, scf_handle_t *h, uint32_t type) 1300*7c478bd9Sstevel@tonic-gate { 1301*7c478bd9Sstevel@tonic-gate int ret; 1302*7c478bd9Sstevel@tonic-gate 1303*7c478bd9Sstevel@tonic-gate if (h == NULL) 1304*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate uu_list_node_init(dp, &dp->rd_node, datael_pool); 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate dp->rd_handle = h; 1309*7c478bd9Sstevel@tonic-gate dp->rd_type = type; 1310*7c478bd9Sstevel@tonic-gate dp->rd_reset = 0; 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1313*7c478bd9Sstevel@tonic-gate if (h->rh_flags & HANDLE_DEAD) { 1314*7c478bd9Sstevel@tonic-gate /* 1315*7c478bd9Sstevel@tonic-gate * we're in undefined territory (the user cannot use a handle 1316*7c478bd9Sstevel@tonic-gate * directly after it has been destroyed), but we don't want 1317*7c478bd9Sstevel@tonic-gate * to allow any new references to happen, so we fail here. 1318*7c478bd9Sstevel@tonic-gate */ 1319*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1320*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_DESTROYED)); 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate dp->rd_entity = handle_alloc_entityid(h); 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate ret = datael_attach(dp); 1325*7c478bd9Sstevel@tonic-gate if (ret == 0) { 1326*7c478bd9Sstevel@tonic-gate (void) uu_list_insert_before(h->rh_dataels, NULL, dp); 1327*7c478bd9Sstevel@tonic-gate h->rh_extrefs++; 1328*7c478bd9Sstevel@tonic-gate } else { 1329*7c478bd9Sstevel@tonic-gate uu_list_node_fini(dp, &dp->rd_node, datael_pool); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate return (ret); 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate static void 1337*7c478bd9Sstevel@tonic-gate datael_destroy(scf_datael_t *dp) 1338*7c478bd9Sstevel@tonic-gate { 1339*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_teardown request; 1342*7c478bd9Sstevel@tonic-gate rep_protocol_response_t response; 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1345*7c478bd9Sstevel@tonic-gate uu_list_remove(h->rh_dataels, dp); 1346*7c478bd9Sstevel@tonic-gate --h->rh_extrefs; 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate if (handle_is_bound(h)) { 1349*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_TEARDOWN; 1350*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate (void) make_door_call(h, &request, sizeof (request), 1353*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1354*7c478bd9Sstevel@tonic-gate } 1355*7c478bd9Sstevel@tonic-gate handle_unrefed(h); /* drops h->rh_lock */ 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate dp->rd_handle = NULL; 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate static scf_handle_t * 1361*7c478bd9Sstevel@tonic-gate datael_handle(const scf_datael_t *dp) 1362*7c478bd9Sstevel@tonic-gate { 1363*7c478bd9Sstevel@tonic-gate return (handle_get(dp->rd_handle)); 1364*7c478bd9Sstevel@tonic-gate } 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate /* 1367*7c478bd9Sstevel@tonic-gate * We delay ENTITY_RESETs until right before the entity is used. By doing 1368*7c478bd9Sstevel@tonic-gate * them lazily, we remove quite a few unnecessary calls. 1369*7c478bd9Sstevel@tonic-gate */ 1370*7c478bd9Sstevel@tonic-gate static void 1371*7c478bd9Sstevel@tonic-gate datael_do_reset_locked(scf_datael_t *dp) 1372*7c478bd9Sstevel@tonic-gate { 1373*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_reset request; 1376*7c478bd9Sstevel@tonic-gate rep_protocol_response_t response; 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 1379*7c478bd9Sstevel@tonic-gate 1380*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_RESET; 1381*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1382*7c478bd9Sstevel@tonic-gate 1383*7c478bd9Sstevel@tonic-gate (void) make_door_call(h, &request, sizeof (request), 1384*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1385*7c478bd9Sstevel@tonic-gate 1386*7c478bd9Sstevel@tonic-gate dp->rd_reset = 0; 1387*7c478bd9Sstevel@tonic-gate } 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate static void 1390*7c478bd9Sstevel@tonic-gate datael_reset_locked(scf_datael_t *dp) 1391*7c478bd9Sstevel@tonic-gate { 1392*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&dp->rd_handle->rh_lock)); 1393*7c478bd9Sstevel@tonic-gate dp->rd_reset = 1; 1394*7c478bd9Sstevel@tonic-gate } 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate static void 1397*7c478bd9Sstevel@tonic-gate datael_reset(scf_datael_t *dp) 1398*7c478bd9Sstevel@tonic-gate { 1399*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1400*7c478bd9Sstevel@tonic-gate 1401*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1402*7c478bd9Sstevel@tonic-gate dp->rd_reset = 1; 1403*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1404*7c478bd9Sstevel@tonic-gate } 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate static void 1407*7c478bd9Sstevel@tonic-gate datael_finish_reset(const scf_datael_t *dp_arg) 1408*7c478bd9Sstevel@tonic-gate { 1409*7c478bd9Sstevel@tonic-gate scf_datael_t *dp = (scf_datael_t *)dp_arg; 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate if (dp->rd_reset) 1412*7c478bd9Sstevel@tonic-gate datael_do_reset_locked(dp); 1413*7c478bd9Sstevel@tonic-gate } 1414*7c478bd9Sstevel@tonic-gate 1415*7c478bd9Sstevel@tonic-gate /* 1416*7c478bd9Sstevel@tonic-gate * Fails with _NOT_BOUND, _CONNECTION_BROKEN, _INTERNAL (server response too 1417*7c478bd9Sstevel@tonic-gate * big, bad entity id, request not applicable to entity, name too long for 1418*7c478bd9Sstevel@tonic-gate * buffer), _NOT_SET, _DELETED, or _CONSTRAINT_VIOLATED (snaplevel is not of an 1419*7c478bd9Sstevel@tonic-gate * instance). 1420*7c478bd9Sstevel@tonic-gate */ 1421*7c478bd9Sstevel@tonic-gate static ssize_t 1422*7c478bd9Sstevel@tonic-gate datael_get_name(const scf_datael_t *dp, char *buf, size_t size, uint32_t type) 1423*7c478bd9Sstevel@tonic-gate { 1424*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_name request; 1427*7c478bd9Sstevel@tonic-gate struct rep_protocol_name_response response; 1428*7c478bd9Sstevel@tonic-gate ssize_t r; 1429*7c478bd9Sstevel@tonic-gate 1430*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1431*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_NAME; 1432*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1433*7c478bd9Sstevel@tonic-gate request.rpr_answertype = type; 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1436*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1437*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1438*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1439*7c478bd9Sstevel@tonic-gate 1440*7c478bd9Sstevel@tonic-gate if (r < 0) 1441*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 1444*7c478bd9Sstevel@tonic-gate assert(response.rpr_response != REP_PROTOCOL_FAIL_BAD_REQUEST); 1445*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_FAIL_NOT_FOUND) 1446*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED)); 1447*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1448*7c478bd9Sstevel@tonic-gate } 1449*7c478bd9Sstevel@tonic-gate return (strlcpy(buf, response.rpr_name, size)); 1450*7c478bd9Sstevel@tonic-gate } 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate /* 1453*7c478bd9Sstevel@tonic-gate * Fails with _HANDLE_MISMATCH, _NOT_BOUND, _CONNECTION_BROKEN, _INTERNAL 1454*7c478bd9Sstevel@tonic-gate * (server response too big, bad element id), _EXISTS (elements have same id), 1455*7c478bd9Sstevel@tonic-gate * _NOT_SET, _DELETED, _CONSTRAINT_VIOLATED, _NOT_FOUND (scope has no parent), 1456*7c478bd9Sstevel@tonic-gate * or _SUCCESS. 1457*7c478bd9Sstevel@tonic-gate */ 1458*7c478bd9Sstevel@tonic-gate static int 1459*7c478bd9Sstevel@tonic-gate datael_get_parent(const scf_datael_t *dp, scf_datael_t *pp) 1460*7c478bd9Sstevel@tonic-gate { 1461*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_parent request; 1464*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate ssize_t r; 1467*7c478bd9Sstevel@tonic-gate 1468*7c478bd9Sstevel@tonic-gate if (h != pp->rd_handle) 1469*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1472*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_GET_PARENT; 1473*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1474*7c478bd9Sstevel@tonic-gate request.rpr_outid = pp->rd_entity; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1477*7c478bd9Sstevel@tonic-gate datael_finish_reset(pp); 1478*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1479*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1480*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate if (r < 0) 1483*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 1486*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_FAIL_TYPE_MISMATCH) 1487*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED)); 1488*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1489*7c478bd9Sstevel@tonic-gate } 1490*7c478bd9Sstevel@tonic-gate 1491*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate /* 1495*7c478bd9Sstevel@tonic-gate * Fails with _HANDLE_MISMATCH, _INVALID_ARGUMENT (out does not have type type, 1496*7c478bd9Sstevel@tonic-gate * name is invalid), _NOT_BOUND, _CONNECTION_BROKEN, _INTERNAL (server response 1497*7c478bd9Sstevel@tonic-gate * too big, bad id, iter already exists, element cannot have children of type, 1498*7c478bd9Sstevel@tonic-gate * type is invalid, iter was reset, sequence was bad, iter walks values, iter 1499*7c478bd9Sstevel@tonic-gate * does not walk type entities), _NOT_SET, _DELETED, _NO_RESOURCES, 1500*7c478bd9Sstevel@tonic-gate * _BACKEND_ACCESS. 1501*7c478bd9Sstevel@tonic-gate */ 1502*7c478bd9Sstevel@tonic-gate static int 1503*7c478bd9Sstevel@tonic-gate datael_get_child_composed_locked(const scf_datael_t *dp, const char *name, 1504*7c478bd9Sstevel@tonic-gate uint32_t type, scf_datael_t *out, scf_iter_t *iter) 1505*7c478bd9Sstevel@tonic-gate { 1506*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_start request; 1507*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_read read_request; 1508*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1511*7c478bd9Sstevel@tonic-gate ssize_t r; 1512*7c478bd9Sstevel@tonic-gate 1513*7c478bd9Sstevel@tonic-gate if (h != out->rd_handle) 1514*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 1515*7c478bd9Sstevel@tonic-gate 1516*7c478bd9Sstevel@tonic-gate if (out->rd_type != type) 1517*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 1520*7c478bd9Sstevel@tonic-gate assert(iter != NULL); 1521*7c478bd9Sstevel@tonic-gate 1522*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(iter); 1523*7c478bd9Sstevel@tonic-gate iter->iter_type = type; 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_START; 1526*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 1527*7c478bd9Sstevel@tonic-gate request.rpr_entity = dp->rd_entity; 1528*7c478bd9Sstevel@tonic-gate request.rpr_itertype = type; 1529*7c478bd9Sstevel@tonic-gate request.rpr_flags = RP_ITER_START_EXACT | RP_ITER_START_COMPOSED; 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate if (name == NULL || strlcpy(request.rpr_pattern, name, 1532*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_pattern)) >= sizeof (request.rpr_pattern)) { 1533*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 1534*7c478bd9Sstevel@tonic-gate } 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1537*7c478bd9Sstevel@tonic-gate datael_finish_reset(out); 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate /* 1540*7c478bd9Sstevel@tonic-gate * We hold the handle lock across both door calls, so that they 1541*7c478bd9Sstevel@tonic-gate * appear atomic. 1542*7c478bd9Sstevel@tonic-gate */ 1543*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1544*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate if (r < 0) 1547*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1548*7c478bd9Sstevel@tonic-gate 1549*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 1550*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate iter->iter_sequence++; 1553*7c478bd9Sstevel@tonic-gate 1554*7c478bd9Sstevel@tonic-gate read_request.rpr_request = REP_PROTOCOL_ITER_READ; 1555*7c478bd9Sstevel@tonic-gate read_request.rpr_iterid = iter->iter_id; 1556*7c478bd9Sstevel@tonic-gate read_request.rpr_sequence = iter->iter_sequence; 1557*7c478bd9Sstevel@tonic-gate read_request.rpr_entityid = out->rd_entity; 1558*7c478bd9Sstevel@tonic-gate 1559*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &read_request, sizeof (read_request), 1560*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(iter); 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate if (r < 0) 1565*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_DONE) { 1568*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_FOUND)); 1569*7c478bd9Sstevel@tonic-gate } 1570*7c478bd9Sstevel@tonic-gate 1571*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 1572*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_FAIL_NOT_SET || 1573*7c478bd9Sstevel@tonic-gate response.rpr_response == REP_PROTOCOL_FAIL_BAD_REQUEST) 1574*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 1575*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1576*7c478bd9Sstevel@tonic-gate } 1577*7c478bd9Sstevel@tonic-gate 1578*7c478bd9Sstevel@tonic-gate return (0); 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate /* 1582*7c478bd9Sstevel@tonic-gate * Fails with _HANDLE_MISMATCH, _INVALID_ARGUMENT (out does not have type type, 1583*7c478bd9Sstevel@tonic-gate * name is invalid), _NOT_BOUND, _CONNECTION_BROKEN, _INTERNAL (server response 1584*7c478bd9Sstevel@tonic-gate * too big, bad id, element cannot have children of type, type is invalid), 1585*7c478bd9Sstevel@tonic-gate * _NOT_SET, _DELETED, _NO_RESOURCES, _BACKEND_ACCESS. 1586*7c478bd9Sstevel@tonic-gate */ 1587*7c478bd9Sstevel@tonic-gate static int 1588*7c478bd9Sstevel@tonic-gate datael_get_child_locked(const scf_datael_t *dp, const char *name, 1589*7c478bd9Sstevel@tonic-gate uint32_t type, scf_datael_t *out) 1590*7c478bd9Sstevel@tonic-gate { 1591*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_get_child request; 1592*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1593*7c478bd9Sstevel@tonic-gate 1594*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1595*7c478bd9Sstevel@tonic-gate ssize_t r; 1596*7c478bd9Sstevel@tonic-gate 1597*7c478bd9Sstevel@tonic-gate if (h != out->rd_handle) 1598*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate if (out->rd_type != type) 1601*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 1602*7c478bd9Sstevel@tonic-gate 1603*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 1604*7c478bd9Sstevel@tonic-gate 1605*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_GET_CHILD; 1606*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1607*7c478bd9Sstevel@tonic-gate request.rpr_childid = out->rd_entity; 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate if (name == NULL || strlcpy(request.rpr_name, name, 1610*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_name)) >= sizeof (request.rpr_name)) { 1611*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 1612*7c478bd9Sstevel@tonic-gate } 1613*7c478bd9Sstevel@tonic-gate 1614*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1615*7c478bd9Sstevel@tonic-gate datael_finish_reset(out); 1616*7c478bd9Sstevel@tonic-gate 1617*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1618*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1619*7c478bd9Sstevel@tonic-gate 1620*7c478bd9Sstevel@tonic-gate if (r < 0) 1621*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 1624*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1625*7c478bd9Sstevel@tonic-gate return (0); 1626*7c478bd9Sstevel@tonic-gate } 1627*7c478bd9Sstevel@tonic-gate 1628*7c478bd9Sstevel@tonic-gate static int 1629*7c478bd9Sstevel@tonic-gate datael_get_child(const scf_datael_t *dp, const char *name, uint32_t type, 1630*7c478bd9Sstevel@tonic-gate scf_datael_t *out, boolean_t composed) 1631*7c478bd9Sstevel@tonic-gate { 1632*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1633*7c478bd9Sstevel@tonic-gate uint32_t held = 0; 1634*7c478bd9Sstevel@tonic-gate int ret; 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 1637*7c478bd9Sstevel@tonic-gate 1638*7c478bd9Sstevel@tonic-gate if (composed) 1639*7c478bd9Sstevel@tonic-gate iter = HANDLE_HOLD_ITER(h); 1640*7c478bd9Sstevel@tonic-gate 1641*7c478bd9Sstevel@tonic-gate if (out == NULL) { 1642*7c478bd9Sstevel@tonic-gate switch (type) { 1643*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SERVICE: 1644*7c478bd9Sstevel@tonic-gate out = &HANDLE_HOLD_SERVICE(h)->rd_d; 1645*7c478bd9Sstevel@tonic-gate held = RH_HOLD_SERVICE; 1646*7c478bd9Sstevel@tonic-gate break; 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_INSTANCE: 1649*7c478bd9Sstevel@tonic-gate out = &HANDLE_HOLD_INSTANCE(h)->rd_d; 1650*7c478bd9Sstevel@tonic-gate held = RH_HOLD_INSTANCE; 1651*7c478bd9Sstevel@tonic-gate break; 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPSHOT: 1654*7c478bd9Sstevel@tonic-gate out = &HANDLE_HOLD_SNAPSHOT(h)->rd_d; 1655*7c478bd9Sstevel@tonic-gate held = RH_HOLD_SNAPSHOT; 1656*7c478bd9Sstevel@tonic-gate break; 1657*7c478bd9Sstevel@tonic-gate 1658*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPLEVEL: 1659*7c478bd9Sstevel@tonic-gate out = &HANDLE_HOLD_SNAPLVL(h)->rd_d; 1660*7c478bd9Sstevel@tonic-gate held = RH_HOLD_SNAPLVL; 1661*7c478bd9Sstevel@tonic-gate break; 1662*7c478bd9Sstevel@tonic-gate 1663*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTYGRP: 1664*7c478bd9Sstevel@tonic-gate out = &HANDLE_HOLD_PG(h)->rd_d; 1665*7c478bd9Sstevel@tonic-gate held = RH_HOLD_PG; 1666*7c478bd9Sstevel@tonic-gate break; 1667*7c478bd9Sstevel@tonic-gate 1668*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTY: 1669*7c478bd9Sstevel@tonic-gate out = &HANDLE_HOLD_PROPERTY(h)->rd_d; 1670*7c478bd9Sstevel@tonic-gate held = RH_HOLD_PROPERTY; 1671*7c478bd9Sstevel@tonic-gate break; 1672*7c478bd9Sstevel@tonic-gate 1673*7c478bd9Sstevel@tonic-gate default: 1674*7c478bd9Sstevel@tonic-gate assert(0); 1675*7c478bd9Sstevel@tonic-gate abort(); 1676*7c478bd9Sstevel@tonic-gate } 1677*7c478bd9Sstevel@tonic-gate } 1678*7c478bd9Sstevel@tonic-gate 1679*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1680*7c478bd9Sstevel@tonic-gate if (composed) 1681*7c478bd9Sstevel@tonic-gate ret = datael_get_child_composed_locked(dp, name, type, out, 1682*7c478bd9Sstevel@tonic-gate iter); 1683*7c478bd9Sstevel@tonic-gate else 1684*7c478bd9Sstevel@tonic-gate ret = datael_get_child_locked(dp, name, type, out); 1685*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate if (composed) 1688*7c478bd9Sstevel@tonic-gate HANDLE_RELE_ITER(h); 1689*7c478bd9Sstevel@tonic-gate 1690*7c478bd9Sstevel@tonic-gate if (held) 1691*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, held); 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate return (ret); 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate 1696*7c478bd9Sstevel@tonic-gate /* 1697*7c478bd9Sstevel@tonic-gate * Fails with 1698*7c478bd9Sstevel@tonic-gate * _HANDLE_MISMATCH 1699*7c478bd9Sstevel@tonic-gate * _INVALID_ARGUMENT - name is too long 1700*7c478bd9Sstevel@tonic-gate * invalid changeid 1701*7c478bd9Sstevel@tonic-gate * name is invalid 1702*7c478bd9Sstevel@tonic-gate * cannot create children for dp's type of node 1703*7c478bd9Sstevel@tonic-gate * _NOT_BOUND - handle is not bound 1704*7c478bd9Sstevel@tonic-gate * _CONNECTION_BROKEN - server is not reachable 1705*7c478bd9Sstevel@tonic-gate * _INTERNAL - server response too big 1706*7c478bd9Sstevel@tonic-gate * dp or cp has unknown id 1707*7c478bd9Sstevel@tonic-gate * type is _PROPERTYGRP 1708*7c478bd9Sstevel@tonic-gate * type is invalid 1709*7c478bd9Sstevel@tonic-gate * dp cannot have children of type type 1710*7c478bd9Sstevel@tonic-gate * database is corrupt 1711*7c478bd9Sstevel@tonic-gate * _EXISTS - dp & cp have the same id 1712*7c478bd9Sstevel@tonic-gate * _EXISTS - child already exists 1713*7c478bd9Sstevel@tonic-gate * _DELETED - dp has been deleted 1714*7c478bd9Sstevel@tonic-gate * _NOT_SET - dp is reset 1715*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 1716*7c478bd9Sstevel@tonic-gate * _PERMISSION_DENIED 1717*7c478bd9Sstevel@tonic-gate * _BACKEND_ACCESS 1718*7c478bd9Sstevel@tonic-gate * _BACKEND_READONLY 1719*7c478bd9Sstevel@tonic-gate * _NOT_FOUND - could not allocate new id 1720*7c478bd9Sstevel@tonic-gate */ 1721*7c478bd9Sstevel@tonic-gate static int 1722*7c478bd9Sstevel@tonic-gate datael_add_child(const scf_datael_t *dp, const char *name, uint32_t type, 1723*7c478bd9Sstevel@tonic-gate scf_datael_t *cp) 1724*7c478bd9Sstevel@tonic-gate { 1725*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_create_child request; 1728*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1729*7c478bd9Sstevel@tonic-gate ssize_t r; 1730*7c478bd9Sstevel@tonic-gate uint32_t held = 0; 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 1733*7c478bd9Sstevel@tonic-gate switch (type) { 1734*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SCOPE: 1735*7c478bd9Sstevel@tonic-gate cp = &HANDLE_HOLD_SCOPE(h)->rd_d; 1736*7c478bd9Sstevel@tonic-gate held = RH_HOLD_SCOPE; 1737*7c478bd9Sstevel@tonic-gate break; 1738*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SERVICE: 1739*7c478bd9Sstevel@tonic-gate cp = &HANDLE_HOLD_SERVICE(h)->rd_d; 1740*7c478bd9Sstevel@tonic-gate held = RH_HOLD_SERVICE; 1741*7c478bd9Sstevel@tonic-gate break; 1742*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_INSTANCE: 1743*7c478bd9Sstevel@tonic-gate cp = &HANDLE_HOLD_INSTANCE(h)->rd_d; 1744*7c478bd9Sstevel@tonic-gate held = RH_HOLD_INSTANCE; 1745*7c478bd9Sstevel@tonic-gate break; 1746*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPSHOT: 1747*7c478bd9Sstevel@tonic-gate default: 1748*7c478bd9Sstevel@tonic-gate assert(0); 1749*7c478bd9Sstevel@tonic-gate abort(); 1750*7c478bd9Sstevel@tonic-gate } 1751*7c478bd9Sstevel@tonic-gate assert(h == cp->rd_handle); 1752*7c478bd9Sstevel@tonic-gate 1753*7c478bd9Sstevel@tonic-gate } else if (h != cp->rd_handle) { 1754*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 1755*7c478bd9Sstevel@tonic-gate } 1756*7c478bd9Sstevel@tonic-gate 1757*7c478bd9Sstevel@tonic-gate if (strlcpy(request.rpr_name, name, sizeof (request.rpr_name)) >= 1758*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_name)) { 1759*7c478bd9Sstevel@tonic-gate r = scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1760*7c478bd9Sstevel@tonic-gate goto err; 1761*7c478bd9Sstevel@tonic-gate } 1762*7c478bd9Sstevel@tonic-gate 1763*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1764*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_CREATE_CHILD; 1765*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1766*7c478bd9Sstevel@tonic-gate request.rpr_childtype = type; 1767*7c478bd9Sstevel@tonic-gate request.rpr_childid = cp->rd_entity; 1768*7c478bd9Sstevel@tonic-gate 1769*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1770*7c478bd9Sstevel@tonic-gate request.rpr_changeid = handle_alloc_changeid(h); 1771*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1772*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1773*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1774*7c478bd9Sstevel@tonic-gate 1775*7c478bd9Sstevel@tonic-gate if (held) 1776*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, held); 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate if (r < 0) 1779*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 1782*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1783*7c478bd9Sstevel@tonic-gate 1784*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 1785*7c478bd9Sstevel@tonic-gate 1786*7c478bd9Sstevel@tonic-gate err: 1787*7c478bd9Sstevel@tonic-gate if (held) 1788*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, held); 1789*7c478bd9Sstevel@tonic-gate return (r); 1790*7c478bd9Sstevel@tonic-gate } 1791*7c478bd9Sstevel@tonic-gate 1792*7c478bd9Sstevel@tonic-gate static int 1793*7c478bd9Sstevel@tonic-gate datael_add_pg(const scf_datael_t *dp, const char *name, const char *type, 1794*7c478bd9Sstevel@tonic-gate uint32_t flags, scf_datael_t *cp) 1795*7c478bd9Sstevel@tonic-gate { 1796*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1797*7c478bd9Sstevel@tonic-gate 1798*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_create_pg request; 1799*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1800*7c478bd9Sstevel@tonic-gate ssize_t r; 1801*7c478bd9Sstevel@tonic-gate 1802*7c478bd9Sstevel@tonic-gate int holding_els = 0; 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 1805*7c478bd9Sstevel@tonic-gate holding_els = 1; 1806*7c478bd9Sstevel@tonic-gate cp = &HANDLE_HOLD_PG(h)->rd_d; 1807*7c478bd9Sstevel@tonic-gate assert(h == cp->rd_handle); 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate } else if (h != cp->rd_handle) { 1810*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 1811*7c478bd9Sstevel@tonic-gate } 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_CREATE_PG; 1814*7c478bd9Sstevel@tonic-gate 1815*7c478bd9Sstevel@tonic-gate if (name == NULL || strlcpy(request.rpr_name, name, 1816*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_name)) > sizeof (request.rpr_name)) { 1817*7c478bd9Sstevel@tonic-gate r = scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1818*7c478bd9Sstevel@tonic-gate goto err; 1819*7c478bd9Sstevel@tonic-gate } 1820*7c478bd9Sstevel@tonic-gate 1821*7c478bd9Sstevel@tonic-gate if (type == NULL || strlcpy(request.rpr_type, type, 1822*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_type)) > sizeof (request.rpr_type)) { 1823*7c478bd9Sstevel@tonic-gate r = scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1824*7c478bd9Sstevel@tonic-gate goto err; 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate 1827*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1828*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1829*7c478bd9Sstevel@tonic-gate request.rpr_childid = cp->rd_entity; 1830*7c478bd9Sstevel@tonic-gate request.rpr_flags = flags; 1831*7c478bd9Sstevel@tonic-gate 1832*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1833*7c478bd9Sstevel@tonic-gate datael_finish_reset(cp); 1834*7c478bd9Sstevel@tonic-gate request.rpr_changeid = handle_alloc_changeid(h); 1835*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1836*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1837*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate if (holding_els) 1840*7c478bd9Sstevel@tonic-gate HANDLE_RELE_PG(h); 1841*7c478bd9Sstevel@tonic-gate 1842*7c478bd9Sstevel@tonic-gate if (r < 0) 1843*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1844*7c478bd9Sstevel@tonic-gate 1845*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 1846*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 1849*7c478bd9Sstevel@tonic-gate 1850*7c478bd9Sstevel@tonic-gate err: 1851*7c478bd9Sstevel@tonic-gate if (holding_els) 1852*7c478bd9Sstevel@tonic-gate HANDLE_RELE_PG(h); 1853*7c478bd9Sstevel@tonic-gate return (r); 1854*7c478bd9Sstevel@tonic-gate } 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate static int 1857*7c478bd9Sstevel@tonic-gate datael_delete(const scf_datael_t *dp) 1858*7c478bd9Sstevel@tonic-gate { 1859*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_delete request; 1862*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1863*7c478bd9Sstevel@tonic-gate ssize_t r; 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1866*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_DELETE; 1867*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 1868*7c478bd9Sstevel@tonic-gate 1869*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 1870*7c478bd9Sstevel@tonic-gate request.rpr_changeid = handle_alloc_changeid(h); 1871*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 1872*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1873*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1874*7c478bd9Sstevel@tonic-gate 1875*7c478bd9Sstevel@tonic-gate if (r < 0) 1876*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 1879*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 1880*7c478bd9Sstevel@tonic-gate 1881*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 1882*7c478bd9Sstevel@tonic-gate } 1883*7c478bd9Sstevel@tonic-gate 1884*7c478bd9Sstevel@tonic-gate /* 1885*7c478bd9Sstevel@tonic-gate * Fails with 1886*7c478bd9Sstevel@tonic-gate * _INVALID_ARGUMENT - h is NULL 1887*7c478bd9Sstevel@tonic-gate * _NO_MEMORY 1888*7c478bd9Sstevel@tonic-gate * _HANDLE_DESTROYED - h has been destroyed 1889*7c478bd9Sstevel@tonic-gate * _INTERNAL - server response too big 1890*7c478bd9Sstevel@tonic-gate * iter already exists 1891*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 1892*7c478bd9Sstevel@tonic-gate */ 1893*7c478bd9Sstevel@tonic-gate scf_iter_t * 1894*7c478bd9Sstevel@tonic-gate scf_iter_create(scf_handle_t *h) 1895*7c478bd9Sstevel@tonic-gate { 1896*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 1897*7c478bd9Sstevel@tonic-gate 1898*7c478bd9Sstevel@tonic-gate if (h == NULL) { 1899*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 1900*7c478bd9Sstevel@tonic-gate return (NULL); 1901*7c478bd9Sstevel@tonic-gate } 1902*7c478bd9Sstevel@tonic-gate 1903*7c478bd9Sstevel@tonic-gate iter = uu_zalloc(sizeof (*iter)); 1904*7c478bd9Sstevel@tonic-gate if (iter == NULL) { 1905*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 1906*7c478bd9Sstevel@tonic-gate return (NULL); 1907*7c478bd9Sstevel@tonic-gate } 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate uu_list_node_init(iter, &iter->iter_node, iter_pool); 1910*7c478bd9Sstevel@tonic-gate iter->iter_handle = h; 1911*7c478bd9Sstevel@tonic-gate iter->iter_sequence = 1; 1912*7c478bd9Sstevel@tonic-gate iter->iter_type = REP_PROTOCOL_ENTITY_NONE; 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 1915*7c478bd9Sstevel@tonic-gate iter->iter_id = handle_alloc_iterid(h); 1916*7c478bd9Sstevel@tonic-gate if (iter_attach(iter) == -1) { 1917*7c478bd9Sstevel@tonic-gate uu_list_node_fini(iter, &iter->iter_node, iter_pool); 1918*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1919*7c478bd9Sstevel@tonic-gate uu_free(iter); 1920*7c478bd9Sstevel@tonic-gate return (NULL); 1921*7c478bd9Sstevel@tonic-gate } 1922*7c478bd9Sstevel@tonic-gate (void) uu_list_insert_before(h->rh_iters, NULL, iter); 1923*7c478bd9Sstevel@tonic-gate h->rh_extrefs++; 1924*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 1925*7c478bd9Sstevel@tonic-gate return (iter); 1926*7c478bd9Sstevel@tonic-gate } 1927*7c478bd9Sstevel@tonic-gate 1928*7c478bd9Sstevel@tonic-gate scf_handle_t * 1929*7c478bd9Sstevel@tonic-gate scf_iter_handle(const scf_iter_t *iter) 1930*7c478bd9Sstevel@tonic-gate { 1931*7c478bd9Sstevel@tonic-gate return (handle_get(iter->iter_handle)); 1932*7c478bd9Sstevel@tonic-gate } 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate static void 1935*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(scf_iter_t *iter) 1936*7c478bd9Sstevel@tonic-gate { 1937*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_request request; 1938*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1939*7c478bd9Sstevel@tonic-gate 1940*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_RESET; 1941*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 1942*7c478bd9Sstevel@tonic-gate 1943*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&iter->iter_handle->rh_lock)); 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate (void) make_door_call(iter->iter_handle, 1946*7c478bd9Sstevel@tonic-gate &request, sizeof (request), &response, sizeof (response)); 1947*7c478bd9Sstevel@tonic-gate 1948*7c478bd9Sstevel@tonic-gate iter->iter_type = REP_PROTOCOL_ENTITY_NONE; 1949*7c478bd9Sstevel@tonic-gate iter->iter_sequence = 1; 1950*7c478bd9Sstevel@tonic-gate } 1951*7c478bd9Sstevel@tonic-gate 1952*7c478bd9Sstevel@tonic-gate void 1953*7c478bd9Sstevel@tonic-gate scf_iter_reset(scf_iter_t *iter) 1954*7c478bd9Sstevel@tonic-gate { 1955*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&iter->iter_handle->rh_lock); 1956*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(iter); 1957*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&iter->iter_handle->rh_lock); 1958*7c478bd9Sstevel@tonic-gate } 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate void 1961*7c478bd9Sstevel@tonic-gate scf_iter_destroy(scf_iter_t *iter) 1962*7c478bd9Sstevel@tonic-gate { 1963*7c478bd9Sstevel@tonic-gate scf_handle_t *handle; 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_request request; 1966*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate if (iter == NULL) 1969*7c478bd9Sstevel@tonic-gate return; 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate handle = iter->iter_handle; 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&handle->rh_lock); 1974*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_TEARDOWN; 1975*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 1976*7c478bd9Sstevel@tonic-gate 1977*7c478bd9Sstevel@tonic-gate (void) make_door_call(handle, &request, sizeof (request), 1978*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate uu_list_remove(handle->rh_iters, iter); 1981*7c478bd9Sstevel@tonic-gate --handle->rh_extrefs; 1982*7c478bd9Sstevel@tonic-gate handle_unrefed(handle); /* drops h->rh_lock */ 1983*7c478bd9Sstevel@tonic-gate iter->iter_handle = NULL; 1984*7c478bd9Sstevel@tonic-gate 1985*7c478bd9Sstevel@tonic-gate uu_list_node_fini(iter, &iter->iter_node, iter_pool); 1986*7c478bd9Sstevel@tonic-gate uu_free(iter); 1987*7c478bd9Sstevel@tonic-gate } 1988*7c478bd9Sstevel@tonic-gate 1989*7c478bd9Sstevel@tonic-gate static int 1990*7c478bd9Sstevel@tonic-gate handle_get_local_scope_locked(scf_handle_t *handle, scf_scope_t *out) 1991*7c478bd9Sstevel@tonic-gate { 1992*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_get request; 1993*7c478bd9Sstevel@tonic-gate struct rep_protocol_name_response response; 1994*7c478bd9Sstevel@tonic-gate ssize_t r; 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&handle->rh_lock)); 1997*7c478bd9Sstevel@tonic-gate 1998*7c478bd9Sstevel@tonic-gate if (handle != out->rd_d.rd_handle) 1999*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2000*7c478bd9Sstevel@tonic-gate 2001*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_GET; 2002*7c478bd9Sstevel@tonic-gate request.rpr_entityid = out->rd_d.rd_entity; 2003*7c478bd9Sstevel@tonic-gate request.rpr_object = RP_ENTITY_GET_MOST_LOCAL_SCOPE; 2004*7c478bd9Sstevel@tonic-gate 2005*7c478bd9Sstevel@tonic-gate datael_finish_reset(&out->rd_d); 2006*7c478bd9Sstevel@tonic-gate r = make_door_call(handle, &request, sizeof (request), 2007*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2008*7c478bd9Sstevel@tonic-gate 2009*7c478bd9Sstevel@tonic-gate if (r < 0) 2010*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 2013*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 2016*7c478bd9Sstevel@tonic-gate } 2017*7c478bd9Sstevel@tonic-gate 2018*7c478bd9Sstevel@tonic-gate int 2019*7c478bd9Sstevel@tonic-gate scf_iter_handle_scopes(scf_iter_t *iter, const scf_handle_t *handle) 2020*7c478bd9Sstevel@tonic-gate { 2021*7c478bd9Sstevel@tonic-gate scf_handle_t *h = iter->iter_handle; 2022*7c478bd9Sstevel@tonic-gate if (h != handle) 2023*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2024*7c478bd9Sstevel@tonic-gate 2025*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2026*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(iter); 2027*7c478bd9Sstevel@tonic-gate 2028*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(h)) { 2029*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2030*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_BOUND)); 2031*7c478bd9Sstevel@tonic-gate } 2032*7c478bd9Sstevel@tonic-gate 2033*7c478bd9Sstevel@tonic-gate if (!handle_has_server(h)) { 2034*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2035*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONNECTION_BROKEN)); 2036*7c478bd9Sstevel@tonic-gate } 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate iter->iter_type = REP_PROTOCOL_ENTITY_SCOPE; 2039*7c478bd9Sstevel@tonic-gate iter->iter_sequence = 1; 2040*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2041*7c478bd9Sstevel@tonic-gate return (0); 2042*7c478bd9Sstevel@tonic-gate } 2043*7c478bd9Sstevel@tonic-gate 2044*7c478bd9Sstevel@tonic-gate int 2045*7c478bd9Sstevel@tonic-gate scf_iter_next_scope(scf_iter_t *iter, scf_scope_t *out) 2046*7c478bd9Sstevel@tonic-gate { 2047*7c478bd9Sstevel@tonic-gate int ret; 2048*7c478bd9Sstevel@tonic-gate scf_handle_t *h = iter->iter_handle; 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate if (h != out->rd_d.rd_handle) 2051*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2052*7c478bd9Sstevel@tonic-gate 2053*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2054*7c478bd9Sstevel@tonic-gate if (iter->iter_type == REP_PROTOCOL_ENTITY_NONE) { 2055*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2056*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 2057*7c478bd9Sstevel@tonic-gate } 2058*7c478bd9Sstevel@tonic-gate if (iter->iter_type != REP_PROTOCOL_ENTITY_SCOPE) { 2059*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2060*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 2061*7c478bd9Sstevel@tonic-gate } 2062*7c478bd9Sstevel@tonic-gate if (iter->iter_sequence == 1) { 2063*7c478bd9Sstevel@tonic-gate if ((ret = handle_get_local_scope_locked(h, out)) == 2064*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2065*7c478bd9Sstevel@tonic-gate iter->iter_sequence++; 2066*7c478bd9Sstevel@tonic-gate ret = 1; 2067*7c478bd9Sstevel@tonic-gate } 2068*7c478bd9Sstevel@tonic-gate } else { 2069*7c478bd9Sstevel@tonic-gate datael_reset_locked(&out->rd_d); 2070*7c478bd9Sstevel@tonic-gate ret = 0; 2071*7c478bd9Sstevel@tonic-gate } 2072*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2073*7c478bd9Sstevel@tonic-gate return (ret); 2074*7c478bd9Sstevel@tonic-gate } 2075*7c478bd9Sstevel@tonic-gate 2076*7c478bd9Sstevel@tonic-gate int 2077*7c478bd9Sstevel@tonic-gate scf_handle_get_scope(scf_handle_t *h, const char *name, scf_scope_t *out) 2078*7c478bd9Sstevel@tonic-gate { 2079*7c478bd9Sstevel@tonic-gate int ret; 2080*7c478bd9Sstevel@tonic-gate 2081*7c478bd9Sstevel@tonic-gate if (h != out->rd_d.rd_handle) 2082*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2083*7c478bd9Sstevel@tonic-gate 2084*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2085*7c478bd9Sstevel@tonic-gate if (strcmp(name, SCF_SCOPE_LOCAL) == 0) { 2086*7c478bd9Sstevel@tonic-gate ret = handle_get_local_scope_locked(h, out); 2087*7c478bd9Sstevel@tonic-gate } else { 2088*7c478bd9Sstevel@tonic-gate datael_reset_locked(&out->rd_d); 2089*7c478bd9Sstevel@tonic-gate if (uu_check_name(name, 0) == -1) 2090*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 2091*7c478bd9Sstevel@tonic-gate else 2092*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_NOT_FOUND); 2093*7c478bd9Sstevel@tonic-gate } 2094*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2095*7c478bd9Sstevel@tonic-gate return (ret); 2096*7c478bd9Sstevel@tonic-gate } 2097*7c478bd9Sstevel@tonic-gate 2098*7c478bd9Sstevel@tonic-gate static int 2099*7c478bd9Sstevel@tonic-gate datael_setup_iter(scf_iter_t *iter, const scf_datael_t *dp, uint32_t res_type, 2100*7c478bd9Sstevel@tonic-gate boolean_t composed) 2101*7c478bd9Sstevel@tonic-gate { 2102*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 2103*7c478bd9Sstevel@tonic-gate 2104*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_start request; 2105*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate ssize_t r; 2108*7c478bd9Sstevel@tonic-gate 2109*7c478bd9Sstevel@tonic-gate if (h != iter->iter_handle) 2110*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2111*7c478bd9Sstevel@tonic-gate 2112*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2113*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(iter); 2114*7c478bd9Sstevel@tonic-gate iter->iter_type = res_type; 2115*7c478bd9Sstevel@tonic-gate 2116*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_START; 2117*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 2118*7c478bd9Sstevel@tonic-gate request.rpr_entity = dp->rd_entity; 2119*7c478bd9Sstevel@tonic-gate request.rpr_itertype = res_type; 2120*7c478bd9Sstevel@tonic-gate request.rpr_flags = RP_ITER_START_ALL | 2121*7c478bd9Sstevel@tonic-gate (composed ? RP_ITER_START_COMPOSED : 0); 2122*7c478bd9Sstevel@tonic-gate request.rpr_pattern[0] = 0; 2123*7c478bd9Sstevel@tonic-gate 2124*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 2125*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 2126*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2127*7c478bd9Sstevel@tonic-gate 2128*7c478bd9Sstevel@tonic-gate if (r < 0) { 2129*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2130*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2131*7c478bd9Sstevel@tonic-gate } 2132*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 2133*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2134*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2135*7c478bd9Sstevel@tonic-gate } 2136*7c478bd9Sstevel@tonic-gate iter->iter_sequence++; 2137*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2138*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 2139*7c478bd9Sstevel@tonic-gate } 2140*7c478bd9Sstevel@tonic-gate 2141*7c478bd9Sstevel@tonic-gate static int 2142*7c478bd9Sstevel@tonic-gate datael_setup_iter_pgtyped(scf_iter_t *iter, const scf_datael_t *dp, 2143*7c478bd9Sstevel@tonic-gate const char *pgtype, boolean_t composed) 2144*7c478bd9Sstevel@tonic-gate { 2145*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 2146*7c478bd9Sstevel@tonic-gate 2147*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_start request; 2148*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2149*7c478bd9Sstevel@tonic-gate 2150*7c478bd9Sstevel@tonic-gate ssize_t r; 2151*7c478bd9Sstevel@tonic-gate 2152*7c478bd9Sstevel@tonic-gate if (h != iter->iter_handle) 2153*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2154*7c478bd9Sstevel@tonic-gate 2155*7c478bd9Sstevel@tonic-gate if (pgtype == NULL || strlcpy(request.rpr_pattern, pgtype, 2156*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_pattern)) >= sizeof (request.rpr_pattern)) { 2157*7c478bd9Sstevel@tonic-gate scf_iter_reset(iter); 2158*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 2159*7c478bd9Sstevel@tonic-gate } 2160*7c478bd9Sstevel@tonic-gate 2161*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2162*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_START; 2163*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 2164*7c478bd9Sstevel@tonic-gate request.rpr_entity = dp->rd_entity; 2165*7c478bd9Sstevel@tonic-gate request.rpr_itertype = REP_PROTOCOL_ENTITY_PROPERTYGRP; 2166*7c478bd9Sstevel@tonic-gate request.rpr_flags = RP_ITER_START_PGTYPE | 2167*7c478bd9Sstevel@tonic-gate (composed ? RP_ITER_START_COMPOSED : 0); 2168*7c478bd9Sstevel@tonic-gate 2169*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 2170*7c478bd9Sstevel@tonic-gate scf_iter_reset_locked(iter); 2171*7c478bd9Sstevel@tonic-gate iter->iter_type = REP_PROTOCOL_ENTITY_PROPERTYGRP; 2172*7c478bd9Sstevel@tonic-gate 2173*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 2174*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2175*7c478bd9Sstevel@tonic-gate 2176*7c478bd9Sstevel@tonic-gate if (r < 0) { 2177*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2180*7c478bd9Sstevel@tonic-gate } 2181*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 2182*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2183*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2184*7c478bd9Sstevel@tonic-gate } 2185*7c478bd9Sstevel@tonic-gate iter->iter_sequence++; 2186*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2187*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 2188*7c478bd9Sstevel@tonic-gate } 2189*7c478bd9Sstevel@tonic-gate 2190*7c478bd9Sstevel@tonic-gate static int 2191*7c478bd9Sstevel@tonic-gate datael_iter_next(scf_iter_t *iter, scf_datael_t *out) 2192*7c478bd9Sstevel@tonic-gate { 2193*7c478bd9Sstevel@tonic-gate scf_handle_t *h = iter->iter_handle; 2194*7c478bd9Sstevel@tonic-gate 2195*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_read request; 2196*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2197*7c478bd9Sstevel@tonic-gate ssize_t r; 2198*7c478bd9Sstevel@tonic-gate 2199*7c478bd9Sstevel@tonic-gate if (h != out->rd_handle) 2200*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2201*7c478bd9Sstevel@tonic-gate 2202*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2203*7c478bd9Sstevel@tonic-gate if (iter->iter_type == REP_PROTOCOL_ENTITY_NONE || 2204*7c478bd9Sstevel@tonic-gate iter->iter_sequence == 1) { 2205*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2206*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 2207*7c478bd9Sstevel@tonic-gate } 2208*7c478bd9Sstevel@tonic-gate 2209*7c478bd9Sstevel@tonic-gate if (out->rd_type != iter->iter_type) { 2210*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2211*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 2212*7c478bd9Sstevel@tonic-gate } 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_READ; 2215*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 2216*7c478bd9Sstevel@tonic-gate request.rpr_sequence = iter->iter_sequence; 2217*7c478bd9Sstevel@tonic-gate request.rpr_entityid = out->rd_entity; 2218*7c478bd9Sstevel@tonic-gate 2219*7c478bd9Sstevel@tonic-gate datael_finish_reset(out); 2220*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 2221*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2222*7c478bd9Sstevel@tonic-gate 2223*7c478bd9Sstevel@tonic-gate if (r < 0) { 2224*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2225*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2226*7c478bd9Sstevel@tonic-gate } 2227*7c478bd9Sstevel@tonic-gate 2228*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_DONE) { 2229*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2230*7c478bd9Sstevel@tonic-gate return (0); 2231*7c478bd9Sstevel@tonic-gate } 2232*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 2233*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2234*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2235*7c478bd9Sstevel@tonic-gate } 2236*7c478bd9Sstevel@tonic-gate iter->iter_sequence++; 2237*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2238*7c478bd9Sstevel@tonic-gate 2239*7c478bd9Sstevel@tonic-gate return (1); 2240*7c478bd9Sstevel@tonic-gate } 2241*7c478bd9Sstevel@tonic-gate 2242*7c478bd9Sstevel@tonic-gate int 2243*7c478bd9Sstevel@tonic-gate scf_iter_scope_services(scf_iter_t *iter, const scf_scope_t *s) 2244*7c478bd9Sstevel@tonic-gate { 2245*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &s->rd_d, 2246*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SERVICE, 0)); 2247*7c478bd9Sstevel@tonic-gate } 2248*7c478bd9Sstevel@tonic-gate 2249*7c478bd9Sstevel@tonic-gate int 2250*7c478bd9Sstevel@tonic-gate scf_iter_next_service(scf_iter_t *iter, scf_service_t *out) 2251*7c478bd9Sstevel@tonic-gate { 2252*7c478bd9Sstevel@tonic-gate return (datael_iter_next(iter, &out->rd_d)); 2253*7c478bd9Sstevel@tonic-gate } 2254*7c478bd9Sstevel@tonic-gate 2255*7c478bd9Sstevel@tonic-gate int 2256*7c478bd9Sstevel@tonic-gate scf_iter_service_instances(scf_iter_t *iter, const scf_service_t *svc) 2257*7c478bd9Sstevel@tonic-gate { 2258*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &svc->rd_d, 2259*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_INSTANCE, 0)); 2260*7c478bd9Sstevel@tonic-gate } 2261*7c478bd9Sstevel@tonic-gate 2262*7c478bd9Sstevel@tonic-gate int 2263*7c478bd9Sstevel@tonic-gate scf_iter_next_instance(scf_iter_t *iter, scf_instance_t *out) 2264*7c478bd9Sstevel@tonic-gate { 2265*7c478bd9Sstevel@tonic-gate return (datael_iter_next(iter, &out->rd_d)); 2266*7c478bd9Sstevel@tonic-gate } 2267*7c478bd9Sstevel@tonic-gate 2268*7c478bd9Sstevel@tonic-gate int 2269*7c478bd9Sstevel@tonic-gate scf_iter_service_pgs(scf_iter_t *iter, const scf_service_t *svc) 2270*7c478bd9Sstevel@tonic-gate { 2271*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &svc->rd_d, 2272*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, 0)); 2273*7c478bd9Sstevel@tonic-gate } 2274*7c478bd9Sstevel@tonic-gate 2275*7c478bd9Sstevel@tonic-gate int 2276*7c478bd9Sstevel@tonic-gate scf_iter_service_pgs_typed(scf_iter_t *iter, const scf_service_t *svc, 2277*7c478bd9Sstevel@tonic-gate const char *type) 2278*7c478bd9Sstevel@tonic-gate { 2279*7c478bd9Sstevel@tonic-gate return (datael_setup_iter_pgtyped(iter, &svc->rd_d, type, 0)); 2280*7c478bd9Sstevel@tonic-gate } 2281*7c478bd9Sstevel@tonic-gate 2282*7c478bd9Sstevel@tonic-gate int 2283*7c478bd9Sstevel@tonic-gate scf_iter_instance_snapshots(scf_iter_t *iter, const scf_instance_t *inst) 2284*7c478bd9Sstevel@tonic-gate { 2285*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &inst->rd_d, 2286*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SNAPSHOT, 0)); 2287*7c478bd9Sstevel@tonic-gate } 2288*7c478bd9Sstevel@tonic-gate 2289*7c478bd9Sstevel@tonic-gate int 2290*7c478bd9Sstevel@tonic-gate scf_iter_next_snapshot(scf_iter_t *iter, scf_snapshot_t *out) 2291*7c478bd9Sstevel@tonic-gate { 2292*7c478bd9Sstevel@tonic-gate return (datael_iter_next(iter, &out->rd_d)); 2293*7c478bd9Sstevel@tonic-gate } 2294*7c478bd9Sstevel@tonic-gate 2295*7c478bd9Sstevel@tonic-gate int 2296*7c478bd9Sstevel@tonic-gate scf_iter_instance_pgs(scf_iter_t *iter, const scf_instance_t *inst) 2297*7c478bd9Sstevel@tonic-gate { 2298*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &inst->rd_d, 2299*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, 0)); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate int 2303*7c478bd9Sstevel@tonic-gate scf_iter_instance_pgs_typed(scf_iter_t *iter, const scf_instance_t *inst, 2304*7c478bd9Sstevel@tonic-gate const char *type) 2305*7c478bd9Sstevel@tonic-gate { 2306*7c478bd9Sstevel@tonic-gate return (datael_setup_iter_pgtyped(iter, &inst->rd_d, type, 0)); 2307*7c478bd9Sstevel@tonic-gate } 2308*7c478bd9Sstevel@tonic-gate 2309*7c478bd9Sstevel@tonic-gate int 2310*7c478bd9Sstevel@tonic-gate scf_iter_instance_pgs_composed(scf_iter_t *iter, const scf_instance_t *inst, 2311*7c478bd9Sstevel@tonic-gate const scf_snapshot_t *snap) 2312*7c478bd9Sstevel@tonic-gate { 2313*7c478bd9Sstevel@tonic-gate if (snap != NULL && inst->rd_d.rd_handle != snap->rd_d.rd_handle) 2314*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2315*7c478bd9Sstevel@tonic-gate 2316*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, snap ? &snap->rd_d : &inst->rd_d, 2317*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, 1)); 2318*7c478bd9Sstevel@tonic-gate } 2319*7c478bd9Sstevel@tonic-gate 2320*7c478bd9Sstevel@tonic-gate int 2321*7c478bd9Sstevel@tonic-gate scf_iter_instance_pgs_typed_composed(scf_iter_t *iter, 2322*7c478bd9Sstevel@tonic-gate const scf_instance_t *inst, const scf_snapshot_t *snap, const char *type) 2323*7c478bd9Sstevel@tonic-gate { 2324*7c478bd9Sstevel@tonic-gate if (snap != NULL && inst->rd_d.rd_handle != snap->rd_d.rd_handle) 2325*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2326*7c478bd9Sstevel@tonic-gate 2327*7c478bd9Sstevel@tonic-gate return (datael_setup_iter_pgtyped(iter, 2328*7c478bd9Sstevel@tonic-gate snap ? &snap->rd_d : &inst->rd_d, type, 1)); 2329*7c478bd9Sstevel@tonic-gate } 2330*7c478bd9Sstevel@tonic-gate 2331*7c478bd9Sstevel@tonic-gate int 2332*7c478bd9Sstevel@tonic-gate scf_iter_snaplevel_pgs(scf_iter_t *iter, const scf_snaplevel_t *inst) 2333*7c478bd9Sstevel@tonic-gate { 2334*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &inst->rd_d, 2335*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, 0)); 2336*7c478bd9Sstevel@tonic-gate } 2337*7c478bd9Sstevel@tonic-gate 2338*7c478bd9Sstevel@tonic-gate int 2339*7c478bd9Sstevel@tonic-gate scf_iter_snaplevel_pgs_typed(scf_iter_t *iter, const scf_snaplevel_t *inst, 2340*7c478bd9Sstevel@tonic-gate const char *type) 2341*7c478bd9Sstevel@tonic-gate { 2342*7c478bd9Sstevel@tonic-gate return (datael_setup_iter_pgtyped(iter, &inst->rd_d, type, 0)); 2343*7c478bd9Sstevel@tonic-gate } 2344*7c478bd9Sstevel@tonic-gate 2345*7c478bd9Sstevel@tonic-gate int 2346*7c478bd9Sstevel@tonic-gate scf_iter_next_pg(scf_iter_t *iter, scf_propertygroup_t *out) 2347*7c478bd9Sstevel@tonic-gate { 2348*7c478bd9Sstevel@tonic-gate return (datael_iter_next(iter, &out->rd_d)); 2349*7c478bd9Sstevel@tonic-gate } 2350*7c478bd9Sstevel@tonic-gate 2351*7c478bd9Sstevel@tonic-gate int 2352*7c478bd9Sstevel@tonic-gate scf_iter_pg_properties(scf_iter_t *iter, const scf_propertygroup_t *pg) 2353*7c478bd9Sstevel@tonic-gate { 2354*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &pg->rd_d, 2355*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTY, 0)); 2356*7c478bd9Sstevel@tonic-gate } 2357*7c478bd9Sstevel@tonic-gate 2358*7c478bd9Sstevel@tonic-gate int 2359*7c478bd9Sstevel@tonic-gate scf_iter_next_property(scf_iter_t *iter, scf_property_t *out) 2360*7c478bd9Sstevel@tonic-gate { 2361*7c478bd9Sstevel@tonic-gate return (datael_iter_next(iter, &out->rd_d)); 2362*7c478bd9Sstevel@tonic-gate } 2363*7c478bd9Sstevel@tonic-gate 2364*7c478bd9Sstevel@tonic-gate /* 2365*7c478bd9Sstevel@tonic-gate * Fails with 2366*7c478bd9Sstevel@tonic-gate * _INVALID_ARGUMENT - handle is NULL 2367*7c478bd9Sstevel@tonic-gate * _INTERNAL - server response too big 2368*7c478bd9Sstevel@tonic-gate * entity already set up with different type 2369*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 2370*7c478bd9Sstevel@tonic-gate * _NO_MEMORY 2371*7c478bd9Sstevel@tonic-gate */ 2372*7c478bd9Sstevel@tonic-gate scf_scope_t * 2373*7c478bd9Sstevel@tonic-gate scf_scope_create(scf_handle_t *handle) 2374*7c478bd9Sstevel@tonic-gate { 2375*7c478bd9Sstevel@tonic-gate scf_scope_t *ret; 2376*7c478bd9Sstevel@tonic-gate 2377*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 2378*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 2379*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 2380*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SCOPE) == -1) { 2381*7c478bd9Sstevel@tonic-gate uu_free(ret); 2382*7c478bd9Sstevel@tonic-gate return (NULL); 2383*7c478bd9Sstevel@tonic-gate } 2384*7c478bd9Sstevel@tonic-gate } else { 2385*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2386*7c478bd9Sstevel@tonic-gate } 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate return (ret); 2389*7c478bd9Sstevel@tonic-gate } 2390*7c478bd9Sstevel@tonic-gate 2391*7c478bd9Sstevel@tonic-gate scf_handle_t * 2392*7c478bd9Sstevel@tonic-gate scf_scope_handle(const scf_scope_t *val) 2393*7c478bd9Sstevel@tonic-gate { 2394*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 2395*7c478bd9Sstevel@tonic-gate } 2396*7c478bd9Sstevel@tonic-gate 2397*7c478bd9Sstevel@tonic-gate void 2398*7c478bd9Sstevel@tonic-gate scf_scope_destroy(scf_scope_t *val) 2399*7c478bd9Sstevel@tonic-gate { 2400*7c478bd9Sstevel@tonic-gate if (val == NULL) 2401*7c478bd9Sstevel@tonic-gate return; 2402*7c478bd9Sstevel@tonic-gate 2403*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 2404*7c478bd9Sstevel@tonic-gate uu_free(val); 2405*7c478bd9Sstevel@tonic-gate } 2406*7c478bd9Sstevel@tonic-gate 2407*7c478bd9Sstevel@tonic-gate ssize_t 2408*7c478bd9Sstevel@tonic-gate scf_scope_get_name(const scf_scope_t *rep, char *out, size_t len) 2409*7c478bd9Sstevel@tonic-gate { 2410*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, RP_ENTITY_NAME_NAME)); 2411*7c478bd9Sstevel@tonic-gate } 2412*7c478bd9Sstevel@tonic-gate 2413*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2414*7c478bd9Sstevel@tonic-gate int 2415*7c478bd9Sstevel@tonic-gate scf_scope_get_parent(const scf_scope_t *child, scf_scope_t *parent) 2416*7c478bd9Sstevel@tonic-gate { 2417*7c478bd9Sstevel@tonic-gate char name[1]; 2418*7c478bd9Sstevel@tonic-gate 2419*7c478bd9Sstevel@tonic-gate /* fake up the side-effects */ 2420*7c478bd9Sstevel@tonic-gate datael_reset(&parent->rd_d); 2421*7c478bd9Sstevel@tonic-gate if (scf_scope_get_name(child, name, sizeof (name)) < 0) 2422*7c478bd9Sstevel@tonic-gate return (-1); 2423*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_FOUND)); 2424*7c478bd9Sstevel@tonic-gate } 2425*7c478bd9Sstevel@tonic-gate 2426*7c478bd9Sstevel@tonic-gate /* 2427*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, _INTERNAL 2428*7c478bd9Sstevel@tonic-gate * (bad server response or id in use), _NO_RESOURCES, or _NO_MEMORY. 2429*7c478bd9Sstevel@tonic-gate */ 2430*7c478bd9Sstevel@tonic-gate scf_service_t * 2431*7c478bd9Sstevel@tonic-gate scf_service_create(scf_handle_t *handle) 2432*7c478bd9Sstevel@tonic-gate { 2433*7c478bd9Sstevel@tonic-gate scf_service_t *ret; 2434*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 2435*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 2436*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 2437*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SERVICE) == -1) { 2438*7c478bd9Sstevel@tonic-gate uu_free(ret); 2439*7c478bd9Sstevel@tonic-gate return (NULL); 2440*7c478bd9Sstevel@tonic-gate } 2441*7c478bd9Sstevel@tonic-gate } else { 2442*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2443*7c478bd9Sstevel@tonic-gate } 2444*7c478bd9Sstevel@tonic-gate 2445*7c478bd9Sstevel@tonic-gate return (ret); 2446*7c478bd9Sstevel@tonic-gate } 2447*7c478bd9Sstevel@tonic-gate 2448*7c478bd9Sstevel@tonic-gate int 2449*7c478bd9Sstevel@tonic-gate scf_scope_add_service(const scf_scope_t *scope, const char *name, 2450*7c478bd9Sstevel@tonic-gate scf_service_t *svc) 2451*7c478bd9Sstevel@tonic-gate { 2452*7c478bd9Sstevel@tonic-gate return (datael_add_child(&scope->rd_d, name, 2453*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SERVICE, (svc != NULL)? &svc->rd_d : NULL)); 2454*7c478bd9Sstevel@tonic-gate } 2455*7c478bd9Sstevel@tonic-gate 2456*7c478bd9Sstevel@tonic-gate int 2457*7c478bd9Sstevel@tonic-gate scf_scope_get_service(const scf_scope_t *s, const char *name, 2458*7c478bd9Sstevel@tonic-gate scf_service_t *svc) 2459*7c478bd9Sstevel@tonic-gate { 2460*7c478bd9Sstevel@tonic-gate return (datael_get_child(&s->rd_d, name, REP_PROTOCOL_ENTITY_SERVICE, 2461*7c478bd9Sstevel@tonic-gate svc ? &svc->rd_d : NULL, 0)); 2462*7c478bd9Sstevel@tonic-gate } 2463*7c478bd9Sstevel@tonic-gate 2464*7c478bd9Sstevel@tonic-gate scf_handle_t * 2465*7c478bd9Sstevel@tonic-gate scf_service_handle(const scf_service_t *val) 2466*7c478bd9Sstevel@tonic-gate { 2467*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 2468*7c478bd9Sstevel@tonic-gate } 2469*7c478bd9Sstevel@tonic-gate 2470*7c478bd9Sstevel@tonic-gate int 2471*7c478bd9Sstevel@tonic-gate scf_service_delete(scf_service_t *svc) 2472*7c478bd9Sstevel@tonic-gate { 2473*7c478bd9Sstevel@tonic-gate return (datael_delete(&svc->rd_d)); 2474*7c478bd9Sstevel@tonic-gate } 2475*7c478bd9Sstevel@tonic-gate 2476*7c478bd9Sstevel@tonic-gate int 2477*7c478bd9Sstevel@tonic-gate scf_instance_delete(scf_instance_t *inst) 2478*7c478bd9Sstevel@tonic-gate { 2479*7c478bd9Sstevel@tonic-gate return (datael_delete(&inst->rd_d)); 2480*7c478bd9Sstevel@tonic-gate } 2481*7c478bd9Sstevel@tonic-gate 2482*7c478bd9Sstevel@tonic-gate int 2483*7c478bd9Sstevel@tonic-gate scf_pg_delete(scf_propertygroup_t *pg) 2484*7c478bd9Sstevel@tonic-gate { 2485*7c478bd9Sstevel@tonic-gate return (datael_delete(&pg->rd_d)); 2486*7c478bd9Sstevel@tonic-gate } 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate int 2489*7c478bd9Sstevel@tonic-gate _scf_snapshot_delete(scf_snapshot_t *snap) 2490*7c478bd9Sstevel@tonic-gate { 2491*7c478bd9Sstevel@tonic-gate return (datael_delete(&snap->rd_d)); 2492*7c478bd9Sstevel@tonic-gate } 2493*7c478bd9Sstevel@tonic-gate 2494*7c478bd9Sstevel@tonic-gate int 2495*7c478bd9Sstevel@tonic-gate scf_service_add_instance(const scf_service_t *svc, const char *name, 2496*7c478bd9Sstevel@tonic-gate scf_instance_t *instance) 2497*7c478bd9Sstevel@tonic-gate { 2498*7c478bd9Sstevel@tonic-gate return (datael_add_child(&svc->rd_d, name, 2499*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_INSTANCE, 2500*7c478bd9Sstevel@tonic-gate (instance != NULL)? &instance->rd_d : NULL)); 2501*7c478bd9Sstevel@tonic-gate } 2502*7c478bd9Sstevel@tonic-gate 2503*7c478bd9Sstevel@tonic-gate int 2504*7c478bd9Sstevel@tonic-gate scf_service_get_instance(const scf_service_t *svc, const char *name, 2505*7c478bd9Sstevel@tonic-gate scf_instance_t *inst) 2506*7c478bd9Sstevel@tonic-gate { 2507*7c478bd9Sstevel@tonic-gate return (datael_get_child(&svc->rd_d, name, REP_PROTOCOL_ENTITY_INSTANCE, 2508*7c478bd9Sstevel@tonic-gate inst ? &inst->rd_d : NULL, 0)); 2509*7c478bd9Sstevel@tonic-gate } 2510*7c478bd9Sstevel@tonic-gate 2511*7c478bd9Sstevel@tonic-gate int 2512*7c478bd9Sstevel@tonic-gate scf_service_add_pg(const scf_service_t *svc, const char *name, 2513*7c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 2514*7c478bd9Sstevel@tonic-gate { 2515*7c478bd9Sstevel@tonic-gate return (datael_add_pg(&svc->rd_d, name, type, flags, 2516*7c478bd9Sstevel@tonic-gate (pg != NULL)?&pg->rd_d : NULL)); 2517*7c478bd9Sstevel@tonic-gate } 2518*7c478bd9Sstevel@tonic-gate 2519*7c478bd9Sstevel@tonic-gate int 2520*7c478bd9Sstevel@tonic-gate scf_service_get_pg(const scf_service_t *svc, const char *name, 2521*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg) 2522*7c478bd9Sstevel@tonic-gate { 2523*7c478bd9Sstevel@tonic-gate return (datael_get_child(&svc->rd_d, name, 2524*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, pg ? &pg->rd_d : NULL, 0)); 2525*7c478bd9Sstevel@tonic-gate } 2526*7c478bd9Sstevel@tonic-gate 2527*7c478bd9Sstevel@tonic-gate int 2528*7c478bd9Sstevel@tonic-gate scf_instance_add_pg(const scf_instance_t *inst, const char *name, 2529*7c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 2530*7c478bd9Sstevel@tonic-gate { 2531*7c478bd9Sstevel@tonic-gate return (datael_add_pg(&inst->rd_d, name, type, flags, 2532*7c478bd9Sstevel@tonic-gate (pg != NULL)?&pg->rd_d : NULL)); 2533*7c478bd9Sstevel@tonic-gate } 2534*7c478bd9Sstevel@tonic-gate 2535*7c478bd9Sstevel@tonic-gate int 2536*7c478bd9Sstevel@tonic-gate scf_instance_get_snapshot(const scf_instance_t *inst, const char *name, 2537*7c478bd9Sstevel@tonic-gate scf_snapshot_t *pg) 2538*7c478bd9Sstevel@tonic-gate { 2539*7c478bd9Sstevel@tonic-gate return (datael_get_child(&inst->rd_d, name, 2540*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SNAPSHOT, pg ? &pg->rd_d : NULL, 0)); 2541*7c478bd9Sstevel@tonic-gate } 2542*7c478bd9Sstevel@tonic-gate 2543*7c478bd9Sstevel@tonic-gate int 2544*7c478bd9Sstevel@tonic-gate scf_instance_get_pg(const scf_instance_t *inst, const char *name, 2545*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg) 2546*7c478bd9Sstevel@tonic-gate { 2547*7c478bd9Sstevel@tonic-gate return (datael_get_child(&inst->rd_d, name, 2548*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, pg ? &pg->rd_d : NULL, 0)); 2549*7c478bd9Sstevel@tonic-gate } 2550*7c478bd9Sstevel@tonic-gate 2551*7c478bd9Sstevel@tonic-gate int 2552*7c478bd9Sstevel@tonic-gate scf_instance_get_pg_composed(const scf_instance_t *inst, 2553*7c478bd9Sstevel@tonic-gate const scf_snapshot_t *snap, const char *name, scf_propertygroup_t *pg) 2554*7c478bd9Sstevel@tonic-gate { 2555*7c478bd9Sstevel@tonic-gate if (snap != NULL && inst->rd_d.rd_handle != snap->rd_d.rd_handle) 2556*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2557*7c478bd9Sstevel@tonic-gate 2558*7c478bd9Sstevel@tonic-gate return (datael_get_child(snap ? &snap->rd_d : &inst->rd_d, name, 2559*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, pg ? &pg->rd_d : NULL, 1)); 2560*7c478bd9Sstevel@tonic-gate } 2561*7c478bd9Sstevel@tonic-gate 2562*7c478bd9Sstevel@tonic-gate int 2563*7c478bd9Sstevel@tonic-gate scf_pg_get_property(const scf_propertygroup_t *pg, const char *name, 2564*7c478bd9Sstevel@tonic-gate scf_property_t *prop) 2565*7c478bd9Sstevel@tonic-gate { 2566*7c478bd9Sstevel@tonic-gate return (datael_get_child(&pg->rd_d, name, REP_PROTOCOL_ENTITY_PROPERTY, 2567*7c478bd9Sstevel@tonic-gate prop ? &prop->rd_d : NULL, 0)); 2568*7c478bd9Sstevel@tonic-gate } 2569*7c478bd9Sstevel@tonic-gate 2570*7c478bd9Sstevel@tonic-gate void 2571*7c478bd9Sstevel@tonic-gate scf_service_destroy(scf_service_t *val) 2572*7c478bd9Sstevel@tonic-gate { 2573*7c478bd9Sstevel@tonic-gate if (val == NULL) 2574*7c478bd9Sstevel@tonic-gate return; 2575*7c478bd9Sstevel@tonic-gate 2576*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 2577*7c478bd9Sstevel@tonic-gate uu_free(val); 2578*7c478bd9Sstevel@tonic-gate } 2579*7c478bd9Sstevel@tonic-gate 2580*7c478bd9Sstevel@tonic-gate ssize_t 2581*7c478bd9Sstevel@tonic-gate scf_service_get_name(const scf_service_t *rep, char *out, size_t len) 2582*7c478bd9Sstevel@tonic-gate { 2583*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, RP_ENTITY_NAME_NAME)); 2584*7c478bd9Sstevel@tonic-gate } 2585*7c478bd9Sstevel@tonic-gate 2586*7c478bd9Sstevel@tonic-gate /* 2587*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, _INTERNAL 2588*7c478bd9Sstevel@tonic-gate * (bad server response or id in use), _NO_RESOURCES, or _NO_MEMORY. 2589*7c478bd9Sstevel@tonic-gate */ 2590*7c478bd9Sstevel@tonic-gate scf_instance_t * 2591*7c478bd9Sstevel@tonic-gate scf_instance_create(scf_handle_t *handle) 2592*7c478bd9Sstevel@tonic-gate { 2593*7c478bd9Sstevel@tonic-gate scf_instance_t *ret; 2594*7c478bd9Sstevel@tonic-gate 2595*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 2596*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 2597*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 2598*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_INSTANCE) == -1) { 2599*7c478bd9Sstevel@tonic-gate uu_free(ret); 2600*7c478bd9Sstevel@tonic-gate return (NULL); 2601*7c478bd9Sstevel@tonic-gate } 2602*7c478bd9Sstevel@tonic-gate } else { 2603*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2604*7c478bd9Sstevel@tonic-gate } 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate return (ret); 2607*7c478bd9Sstevel@tonic-gate } 2608*7c478bd9Sstevel@tonic-gate 2609*7c478bd9Sstevel@tonic-gate scf_handle_t * 2610*7c478bd9Sstevel@tonic-gate scf_instance_handle(const scf_instance_t *val) 2611*7c478bd9Sstevel@tonic-gate { 2612*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 2613*7c478bd9Sstevel@tonic-gate } 2614*7c478bd9Sstevel@tonic-gate 2615*7c478bd9Sstevel@tonic-gate void 2616*7c478bd9Sstevel@tonic-gate scf_instance_destroy(scf_instance_t *val) 2617*7c478bd9Sstevel@tonic-gate { 2618*7c478bd9Sstevel@tonic-gate if (val == NULL) 2619*7c478bd9Sstevel@tonic-gate return; 2620*7c478bd9Sstevel@tonic-gate 2621*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 2622*7c478bd9Sstevel@tonic-gate uu_free(val); 2623*7c478bd9Sstevel@tonic-gate } 2624*7c478bd9Sstevel@tonic-gate 2625*7c478bd9Sstevel@tonic-gate ssize_t 2626*7c478bd9Sstevel@tonic-gate scf_instance_get_name(const scf_instance_t *rep, char *out, size_t len) 2627*7c478bd9Sstevel@tonic-gate { 2628*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, RP_ENTITY_NAME_NAME)); 2629*7c478bd9Sstevel@tonic-gate } 2630*7c478bd9Sstevel@tonic-gate 2631*7c478bd9Sstevel@tonic-gate /* 2632*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, _INTERNAL 2633*7c478bd9Sstevel@tonic-gate * (bad server response or id in use), _NO_RESOURCES, or _NO_MEMORY. 2634*7c478bd9Sstevel@tonic-gate */ 2635*7c478bd9Sstevel@tonic-gate scf_snapshot_t * 2636*7c478bd9Sstevel@tonic-gate scf_snapshot_create(scf_handle_t *handle) 2637*7c478bd9Sstevel@tonic-gate { 2638*7c478bd9Sstevel@tonic-gate scf_snapshot_t *ret; 2639*7c478bd9Sstevel@tonic-gate 2640*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 2641*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 2642*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 2643*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SNAPSHOT) == -1) { 2644*7c478bd9Sstevel@tonic-gate uu_free(ret); 2645*7c478bd9Sstevel@tonic-gate return (NULL); 2646*7c478bd9Sstevel@tonic-gate } 2647*7c478bd9Sstevel@tonic-gate } else { 2648*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2649*7c478bd9Sstevel@tonic-gate } 2650*7c478bd9Sstevel@tonic-gate 2651*7c478bd9Sstevel@tonic-gate return (ret); 2652*7c478bd9Sstevel@tonic-gate } 2653*7c478bd9Sstevel@tonic-gate 2654*7c478bd9Sstevel@tonic-gate scf_handle_t * 2655*7c478bd9Sstevel@tonic-gate scf_snapshot_handle(const scf_snapshot_t *val) 2656*7c478bd9Sstevel@tonic-gate { 2657*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 2658*7c478bd9Sstevel@tonic-gate } 2659*7c478bd9Sstevel@tonic-gate 2660*7c478bd9Sstevel@tonic-gate void 2661*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(scf_snapshot_t *val) 2662*7c478bd9Sstevel@tonic-gate { 2663*7c478bd9Sstevel@tonic-gate if (val == NULL) 2664*7c478bd9Sstevel@tonic-gate return; 2665*7c478bd9Sstevel@tonic-gate 2666*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 2667*7c478bd9Sstevel@tonic-gate uu_free(val); 2668*7c478bd9Sstevel@tonic-gate } 2669*7c478bd9Sstevel@tonic-gate 2670*7c478bd9Sstevel@tonic-gate ssize_t 2671*7c478bd9Sstevel@tonic-gate scf_snapshot_get_name(const scf_snapshot_t *rep, char *out, size_t len) 2672*7c478bd9Sstevel@tonic-gate { 2673*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, RP_ENTITY_NAME_NAME)); 2674*7c478bd9Sstevel@tonic-gate } 2675*7c478bd9Sstevel@tonic-gate 2676*7c478bd9Sstevel@tonic-gate /* 2677*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, _INTERNAL 2678*7c478bd9Sstevel@tonic-gate * (bad server response or id in use), _NO_RESOURCES, _NO_MEMORY. 2679*7c478bd9Sstevel@tonic-gate */ 2680*7c478bd9Sstevel@tonic-gate scf_snaplevel_t * 2681*7c478bd9Sstevel@tonic-gate scf_snaplevel_create(scf_handle_t *handle) 2682*7c478bd9Sstevel@tonic-gate { 2683*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *ret; 2684*7c478bd9Sstevel@tonic-gate 2685*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 2686*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 2687*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 2688*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SNAPLEVEL) == -1) { 2689*7c478bd9Sstevel@tonic-gate uu_free(ret); 2690*7c478bd9Sstevel@tonic-gate return (NULL); 2691*7c478bd9Sstevel@tonic-gate } 2692*7c478bd9Sstevel@tonic-gate } else { 2693*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2694*7c478bd9Sstevel@tonic-gate } 2695*7c478bd9Sstevel@tonic-gate 2696*7c478bd9Sstevel@tonic-gate return (ret); 2697*7c478bd9Sstevel@tonic-gate } 2698*7c478bd9Sstevel@tonic-gate 2699*7c478bd9Sstevel@tonic-gate scf_handle_t * 2700*7c478bd9Sstevel@tonic-gate scf_snaplevel_handle(const scf_snaplevel_t *val) 2701*7c478bd9Sstevel@tonic-gate { 2702*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 2703*7c478bd9Sstevel@tonic-gate } 2704*7c478bd9Sstevel@tonic-gate 2705*7c478bd9Sstevel@tonic-gate void 2706*7c478bd9Sstevel@tonic-gate scf_snaplevel_destroy(scf_snaplevel_t *val) 2707*7c478bd9Sstevel@tonic-gate { 2708*7c478bd9Sstevel@tonic-gate if (val == NULL) 2709*7c478bd9Sstevel@tonic-gate return; 2710*7c478bd9Sstevel@tonic-gate 2711*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 2712*7c478bd9Sstevel@tonic-gate uu_free(val); 2713*7c478bd9Sstevel@tonic-gate } 2714*7c478bd9Sstevel@tonic-gate 2715*7c478bd9Sstevel@tonic-gate ssize_t 2716*7c478bd9Sstevel@tonic-gate scf_snaplevel_get_scope_name(const scf_snaplevel_t *rep, char *out, size_t len) 2717*7c478bd9Sstevel@tonic-gate { 2718*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, 2719*7c478bd9Sstevel@tonic-gate RP_ENTITY_NAME_SNAPLEVEL_SCOPE)); 2720*7c478bd9Sstevel@tonic-gate } 2721*7c478bd9Sstevel@tonic-gate 2722*7c478bd9Sstevel@tonic-gate ssize_t 2723*7c478bd9Sstevel@tonic-gate scf_snaplevel_get_service_name(const scf_snaplevel_t *rep, char *out, 2724*7c478bd9Sstevel@tonic-gate size_t len) 2725*7c478bd9Sstevel@tonic-gate { 2726*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, 2727*7c478bd9Sstevel@tonic-gate RP_ENTITY_NAME_SNAPLEVEL_SERVICE)); 2728*7c478bd9Sstevel@tonic-gate } 2729*7c478bd9Sstevel@tonic-gate 2730*7c478bd9Sstevel@tonic-gate ssize_t 2731*7c478bd9Sstevel@tonic-gate scf_snaplevel_get_instance_name(const scf_snaplevel_t *rep, char *out, 2732*7c478bd9Sstevel@tonic-gate size_t len) 2733*7c478bd9Sstevel@tonic-gate { 2734*7c478bd9Sstevel@tonic-gate return (datael_get_name(&rep->rd_d, out, len, 2735*7c478bd9Sstevel@tonic-gate RP_ENTITY_NAME_SNAPLEVEL_INSTANCE)); 2736*7c478bd9Sstevel@tonic-gate } 2737*7c478bd9Sstevel@tonic-gate 2738*7c478bd9Sstevel@tonic-gate int 2739*7c478bd9Sstevel@tonic-gate scf_snaplevel_get_pg(const scf_snaplevel_t *snap, const char *name, 2740*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg) 2741*7c478bd9Sstevel@tonic-gate { 2742*7c478bd9Sstevel@tonic-gate return (datael_get_child(&snap->rd_d, name, 2743*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP, pg ? &pg->rd_d : NULL, 0)); 2744*7c478bd9Sstevel@tonic-gate } 2745*7c478bd9Sstevel@tonic-gate 2746*7c478bd9Sstevel@tonic-gate static int 2747*7c478bd9Sstevel@tonic-gate snaplevel_next(const scf_datael_t *src, scf_snaplevel_t *dst_arg) 2748*7c478bd9Sstevel@tonic-gate { 2749*7c478bd9Sstevel@tonic-gate scf_handle_t *h = src->rd_handle; 2750*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *dst = dst_arg; 2751*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_pair request; 2752*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2753*7c478bd9Sstevel@tonic-gate int r; 2754*7c478bd9Sstevel@tonic-gate int dups = 0; 2755*7c478bd9Sstevel@tonic-gate 2756*7c478bd9Sstevel@tonic-gate if (h != dst->rd_d.rd_handle) 2757*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 2758*7c478bd9Sstevel@tonic-gate 2759*7c478bd9Sstevel@tonic-gate if (src == &dst->rd_d) { 2760*7c478bd9Sstevel@tonic-gate dups = 1; 2761*7c478bd9Sstevel@tonic-gate dst = HANDLE_HOLD_SNAPLVL(h); 2762*7c478bd9Sstevel@tonic-gate } 2763*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2764*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_NEXT_SNAPLEVEL; 2765*7c478bd9Sstevel@tonic-gate request.rpr_entity_src = src->rd_entity; 2766*7c478bd9Sstevel@tonic-gate request.rpr_entity_dst = dst->rd_d.rd_entity; 2767*7c478bd9Sstevel@tonic-gate 2768*7c478bd9Sstevel@tonic-gate datael_finish_reset(src); 2769*7c478bd9Sstevel@tonic-gate datael_finish_reset(&dst->rd_d); 2770*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 2771*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2772*7c478bd9Sstevel@tonic-gate /* 2773*7c478bd9Sstevel@tonic-gate * if we succeeded, we need to swap dst and dst_arg's identity. We 2774*7c478bd9Sstevel@tonic-gate * take advantage of the fact that the only in-library knowledge is 2775*7c478bd9Sstevel@tonic-gate * their entity ids. 2776*7c478bd9Sstevel@tonic-gate */ 2777*7c478bd9Sstevel@tonic-gate if (dups && r >= 0 && 2778*7c478bd9Sstevel@tonic-gate (response.rpr_response == REP_PROTOCOL_SUCCESS || 2779*7c478bd9Sstevel@tonic-gate response.rpr_response == REP_PROTOCOL_DONE)) { 2780*7c478bd9Sstevel@tonic-gate int entity = dst->rd_d.rd_entity; 2781*7c478bd9Sstevel@tonic-gate 2782*7c478bd9Sstevel@tonic-gate dst->rd_d.rd_entity = dst_arg->rd_d.rd_entity; 2783*7c478bd9Sstevel@tonic-gate dst_arg->rd_d.rd_entity = entity; 2784*7c478bd9Sstevel@tonic-gate } 2785*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2786*7c478bd9Sstevel@tonic-gate 2787*7c478bd9Sstevel@tonic-gate if (dups) 2788*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SNAPLVL(h); 2789*7c478bd9Sstevel@tonic-gate 2790*7c478bd9Sstevel@tonic-gate if (r < 0) 2791*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2792*7c478bd9Sstevel@tonic-gate 2793*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS && 2794*7c478bd9Sstevel@tonic-gate response.rpr_response != REP_PROTOCOL_DONE) { 2795*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2796*7c478bd9Sstevel@tonic-gate } 2797*7c478bd9Sstevel@tonic-gate 2798*7c478bd9Sstevel@tonic-gate return (response.rpr_response == REP_PROTOCOL_SUCCESS) ? 2799*7c478bd9Sstevel@tonic-gate SCF_SUCCESS : SCF_COMPLETE; 2800*7c478bd9Sstevel@tonic-gate } 2801*7c478bd9Sstevel@tonic-gate 2802*7c478bd9Sstevel@tonic-gate int scf_snapshot_get_base_snaplevel(const scf_snapshot_t *base, 2803*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *out) 2804*7c478bd9Sstevel@tonic-gate { 2805*7c478bd9Sstevel@tonic-gate return (snaplevel_next(&base->rd_d, out)); 2806*7c478bd9Sstevel@tonic-gate } 2807*7c478bd9Sstevel@tonic-gate 2808*7c478bd9Sstevel@tonic-gate int scf_snaplevel_get_next_snaplevel(const scf_snaplevel_t *base, 2809*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *out) 2810*7c478bd9Sstevel@tonic-gate { 2811*7c478bd9Sstevel@tonic-gate return (snaplevel_next(&base->rd_d, out)); 2812*7c478bd9Sstevel@tonic-gate } 2813*7c478bd9Sstevel@tonic-gate 2814*7c478bd9Sstevel@tonic-gate /* 2815*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, _INTERNAL 2816*7c478bd9Sstevel@tonic-gate * (bad server response or id in use), _NO_RESOURCES, or _NO_MEMORY. 2817*7c478bd9Sstevel@tonic-gate */ 2818*7c478bd9Sstevel@tonic-gate scf_propertygroup_t * 2819*7c478bd9Sstevel@tonic-gate scf_pg_create(scf_handle_t *handle) 2820*7c478bd9Sstevel@tonic-gate { 2821*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *ret; 2822*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 2823*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 2824*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 2825*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP) == -1) { 2826*7c478bd9Sstevel@tonic-gate uu_free(ret); 2827*7c478bd9Sstevel@tonic-gate return (NULL); 2828*7c478bd9Sstevel@tonic-gate } 2829*7c478bd9Sstevel@tonic-gate } else { 2830*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 2831*7c478bd9Sstevel@tonic-gate } 2832*7c478bd9Sstevel@tonic-gate 2833*7c478bd9Sstevel@tonic-gate return (ret); 2834*7c478bd9Sstevel@tonic-gate } 2835*7c478bd9Sstevel@tonic-gate 2836*7c478bd9Sstevel@tonic-gate scf_handle_t * 2837*7c478bd9Sstevel@tonic-gate scf_pg_handle(const scf_propertygroup_t *val) 2838*7c478bd9Sstevel@tonic-gate { 2839*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 2840*7c478bd9Sstevel@tonic-gate } 2841*7c478bd9Sstevel@tonic-gate 2842*7c478bd9Sstevel@tonic-gate void 2843*7c478bd9Sstevel@tonic-gate scf_pg_destroy(scf_propertygroup_t *val) 2844*7c478bd9Sstevel@tonic-gate { 2845*7c478bd9Sstevel@tonic-gate if (val == NULL) 2846*7c478bd9Sstevel@tonic-gate return; 2847*7c478bd9Sstevel@tonic-gate 2848*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 2849*7c478bd9Sstevel@tonic-gate uu_free(val); 2850*7c478bd9Sstevel@tonic-gate } 2851*7c478bd9Sstevel@tonic-gate 2852*7c478bd9Sstevel@tonic-gate ssize_t 2853*7c478bd9Sstevel@tonic-gate scf_pg_get_name(const scf_propertygroup_t *pg, char *out, size_t len) 2854*7c478bd9Sstevel@tonic-gate { 2855*7c478bd9Sstevel@tonic-gate return (datael_get_name(&pg->rd_d, out, len, RP_ENTITY_NAME_NAME)); 2856*7c478bd9Sstevel@tonic-gate } 2857*7c478bd9Sstevel@tonic-gate 2858*7c478bd9Sstevel@tonic-gate ssize_t 2859*7c478bd9Sstevel@tonic-gate scf_pg_get_type(const scf_propertygroup_t *pg, char *out, size_t len) 2860*7c478bd9Sstevel@tonic-gate { 2861*7c478bd9Sstevel@tonic-gate return (datael_get_name(&pg->rd_d, out, len, RP_ENTITY_NAME_PGTYPE)); 2862*7c478bd9Sstevel@tonic-gate } 2863*7c478bd9Sstevel@tonic-gate 2864*7c478bd9Sstevel@tonic-gate int 2865*7c478bd9Sstevel@tonic-gate scf_pg_get_flags(const scf_propertygroup_t *pg, uint32_t *out) 2866*7c478bd9Sstevel@tonic-gate { 2867*7c478bd9Sstevel@tonic-gate char buf[REP_PROTOCOL_NAME_LEN]; 2868*7c478bd9Sstevel@tonic-gate ssize_t res; 2869*7c478bd9Sstevel@tonic-gate 2870*7c478bd9Sstevel@tonic-gate res = datael_get_name(&pg->rd_d, buf, sizeof (buf), 2871*7c478bd9Sstevel@tonic-gate RP_ENTITY_NAME_PGFLAGS); 2872*7c478bd9Sstevel@tonic-gate 2873*7c478bd9Sstevel@tonic-gate if (res == -1) 2874*7c478bd9Sstevel@tonic-gate return (-1); 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate if (uu_strtouint(buf, out, sizeof (*out), 0, 0, UINT32_MAX) == -1) 2877*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 2878*7c478bd9Sstevel@tonic-gate 2879*7c478bd9Sstevel@tonic-gate return (0); 2880*7c478bd9Sstevel@tonic-gate } 2881*7c478bd9Sstevel@tonic-gate 2882*7c478bd9Sstevel@tonic-gate static int 2883*7c478bd9Sstevel@tonic-gate datael_update(scf_datael_t *dp) 2884*7c478bd9Sstevel@tonic-gate { 2885*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dp->rd_handle; 2886*7c478bd9Sstevel@tonic-gate 2887*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_update request; 2888*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2889*7c478bd9Sstevel@tonic-gate 2890*7c478bd9Sstevel@tonic-gate int r; 2891*7c478bd9Sstevel@tonic-gate 2892*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2893*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_UPDATE; 2894*7c478bd9Sstevel@tonic-gate request.rpr_entityid = dp->rd_entity; 2895*7c478bd9Sstevel@tonic-gate 2896*7c478bd9Sstevel@tonic-gate datael_finish_reset(dp); 2897*7c478bd9Sstevel@tonic-gate request.rpr_changeid = handle_alloc_changeid(h); 2898*7c478bd9Sstevel@tonic-gate 2899*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 2900*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2901*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2902*7c478bd9Sstevel@tonic-gate 2903*7c478bd9Sstevel@tonic-gate if (r < 0) 2904*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2905*7c478bd9Sstevel@tonic-gate 2906*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS && 2907*7c478bd9Sstevel@tonic-gate response.rpr_response != REP_PROTOCOL_DONE) { 2908*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2909*7c478bd9Sstevel@tonic-gate } 2910*7c478bd9Sstevel@tonic-gate 2911*7c478bd9Sstevel@tonic-gate return (response.rpr_response == REP_PROTOCOL_SUCCESS) ? 2912*7c478bd9Sstevel@tonic-gate SCF_SUCCESS : SCF_COMPLETE; 2913*7c478bd9Sstevel@tonic-gate } 2914*7c478bd9Sstevel@tonic-gate 2915*7c478bd9Sstevel@tonic-gate int 2916*7c478bd9Sstevel@tonic-gate scf_pg_update(scf_propertygroup_t *pg) 2917*7c478bd9Sstevel@tonic-gate { 2918*7c478bd9Sstevel@tonic-gate return (datael_update(&pg->rd_d)); 2919*7c478bd9Sstevel@tonic-gate } 2920*7c478bd9Sstevel@tonic-gate 2921*7c478bd9Sstevel@tonic-gate int 2922*7c478bd9Sstevel@tonic-gate scf_snapshot_update(scf_snapshot_t *snap) 2923*7c478bd9Sstevel@tonic-gate { 2924*7c478bd9Sstevel@tonic-gate return (datael_update(&snap->rd_d)); 2925*7c478bd9Sstevel@tonic-gate } 2926*7c478bd9Sstevel@tonic-gate 2927*7c478bd9Sstevel@tonic-gate int 2928*7c478bd9Sstevel@tonic-gate _scf_pg_wait(scf_propertygroup_t *pg, int timeout) 2929*7c478bd9Sstevel@tonic-gate { 2930*7c478bd9Sstevel@tonic-gate scf_handle_t *h = pg->rd_d.rd_handle; 2931*7c478bd9Sstevel@tonic-gate 2932*7c478bd9Sstevel@tonic-gate struct rep_protocol_propertygrp_request request; 2933*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2934*7c478bd9Sstevel@tonic-gate 2935*7c478bd9Sstevel@tonic-gate struct pollfd pollfd; 2936*7c478bd9Sstevel@tonic-gate 2937*7c478bd9Sstevel@tonic-gate int r; 2938*7c478bd9Sstevel@tonic-gate 2939*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2940*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_PROPERTYGRP_SETUP_WAIT; 2941*7c478bd9Sstevel@tonic-gate request.rpr_entityid = pg->rd_d.rd_entity; 2942*7c478bd9Sstevel@tonic-gate 2943*7c478bd9Sstevel@tonic-gate datael_finish_reset(&pg->rd_d); 2944*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(h)) { 2945*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2946*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONNECTION_BROKEN)); 2947*7c478bd9Sstevel@tonic-gate } 2948*7c478bd9Sstevel@tonic-gate r = make_door_call_retfd(h->rh_doorfd, &request, sizeof (request), 2949*7c478bd9Sstevel@tonic-gate &response, sizeof (response), &pollfd.fd); 2950*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2951*7c478bd9Sstevel@tonic-gate 2952*7c478bd9Sstevel@tonic-gate if (r < 0) 2953*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2954*7c478bd9Sstevel@tonic-gate 2955*7c478bd9Sstevel@tonic-gate assert((response.rpr_response == REP_PROTOCOL_SUCCESS) == 2956*7c478bd9Sstevel@tonic-gate (pollfd.fd != -1)); 2957*7c478bd9Sstevel@tonic-gate 2958*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_FAIL_NOT_LATEST) 2959*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 2960*7c478bd9Sstevel@tonic-gate 2961*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 2962*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2963*7c478bd9Sstevel@tonic-gate 2964*7c478bd9Sstevel@tonic-gate pollfd.events = 0; 2965*7c478bd9Sstevel@tonic-gate pollfd.revents = 0; 2966*7c478bd9Sstevel@tonic-gate 2967*7c478bd9Sstevel@tonic-gate r = poll(&pollfd, 1, timeout * MILLISEC); 2968*7c478bd9Sstevel@tonic-gate 2969*7c478bd9Sstevel@tonic-gate (void) close(pollfd.fd); 2970*7c478bd9Sstevel@tonic-gate return (pollfd.revents ? SCF_SUCCESS : SCF_COMPLETE); 2971*7c478bd9Sstevel@tonic-gate } 2972*7c478bd9Sstevel@tonic-gate 2973*7c478bd9Sstevel@tonic-gate static int 2974*7c478bd9Sstevel@tonic-gate scf_notify_add_pattern(scf_handle_t *h, int type, const char *name) 2975*7c478bd9Sstevel@tonic-gate { 2976*7c478bd9Sstevel@tonic-gate struct rep_protocol_notify_request request; 2977*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 2978*7c478bd9Sstevel@tonic-gate int r; 2979*7c478bd9Sstevel@tonic-gate 2980*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 2981*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_CLIENT_ADD_NOTIFY; 2982*7c478bd9Sstevel@tonic-gate request.rpr_type = type; 2983*7c478bd9Sstevel@tonic-gate (void) strlcpy(request.rpr_pattern, name, sizeof (request.rpr_pattern)); 2984*7c478bd9Sstevel@tonic-gate 2985*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 2986*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 2987*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 2988*7c478bd9Sstevel@tonic-gate 2989*7c478bd9Sstevel@tonic-gate if (r < 0) 2990*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 2991*7c478bd9Sstevel@tonic-gate 2992*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 2993*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 2994*7c478bd9Sstevel@tonic-gate 2995*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 2996*7c478bd9Sstevel@tonic-gate } 2997*7c478bd9Sstevel@tonic-gate 2998*7c478bd9Sstevel@tonic-gate int 2999*7c478bd9Sstevel@tonic-gate _scf_notify_add_pgname(scf_handle_t *h, const char *name) 3000*7c478bd9Sstevel@tonic-gate { 3001*7c478bd9Sstevel@tonic-gate return (scf_notify_add_pattern(h, REP_PROTOCOL_NOTIFY_PGNAME, name)); 3002*7c478bd9Sstevel@tonic-gate } 3003*7c478bd9Sstevel@tonic-gate 3004*7c478bd9Sstevel@tonic-gate int 3005*7c478bd9Sstevel@tonic-gate _scf_notify_add_pgtype(scf_handle_t *h, const char *type) 3006*7c478bd9Sstevel@tonic-gate { 3007*7c478bd9Sstevel@tonic-gate return (scf_notify_add_pattern(h, REP_PROTOCOL_NOTIFY_PGTYPE, type)); 3008*7c478bd9Sstevel@tonic-gate } 3009*7c478bd9Sstevel@tonic-gate 3010*7c478bd9Sstevel@tonic-gate int 3011*7c478bd9Sstevel@tonic-gate _scf_notify_wait(scf_propertygroup_t *pg, char *out, size_t sz) 3012*7c478bd9Sstevel@tonic-gate { 3013*7c478bd9Sstevel@tonic-gate struct rep_protocol_wait_request request; 3014*7c478bd9Sstevel@tonic-gate struct rep_protocol_fmri_response response; 3015*7c478bd9Sstevel@tonic-gate 3016*7c478bd9Sstevel@tonic-gate scf_handle_t *h = pg->rd_d.rd_handle; 3017*7c478bd9Sstevel@tonic-gate int dummy; 3018*7c478bd9Sstevel@tonic-gate int fd; 3019*7c478bd9Sstevel@tonic-gate int r; 3020*7c478bd9Sstevel@tonic-gate 3021*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3022*7c478bd9Sstevel@tonic-gate datael_finish_reset(&pg->rd_d); 3023*7c478bd9Sstevel@tonic-gate if (!handle_is_bound(h)) { 3024*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3025*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_CONNECTION_BROKEN)); 3026*7c478bd9Sstevel@tonic-gate } 3027*7c478bd9Sstevel@tonic-gate fd = h->rh_doorfd; 3028*7c478bd9Sstevel@tonic-gate ++h->rh_fd_users; 3029*7c478bd9Sstevel@tonic-gate assert(h->rh_fd_users > 0); 3030*7c478bd9Sstevel@tonic-gate 3031*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_CLIENT_WAIT; 3032*7c478bd9Sstevel@tonic-gate request.rpr_entityid = pg->rd_d.rd_entity; 3033*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3034*7c478bd9Sstevel@tonic-gate 3035*7c478bd9Sstevel@tonic-gate r = make_door_call_retfd(fd, &request, sizeof (request), 3036*7c478bd9Sstevel@tonic-gate &response, sizeof (response), &dummy); 3037*7c478bd9Sstevel@tonic-gate 3038*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3039*7c478bd9Sstevel@tonic-gate assert(h->rh_fd_users > 0); 3040*7c478bd9Sstevel@tonic-gate if (--h->rh_fd_users == 0) { 3041*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&h->rh_cv); 3042*7c478bd9Sstevel@tonic-gate /* 3043*7c478bd9Sstevel@tonic-gate * check for a delayed close, now that there are no other 3044*7c478bd9Sstevel@tonic-gate * users. 3045*7c478bd9Sstevel@tonic-gate */ 3046*7c478bd9Sstevel@tonic-gate if (h->rh_doorfd_old != -1) { 3047*7c478bd9Sstevel@tonic-gate assert(h->rh_doorfd == -1); 3048*7c478bd9Sstevel@tonic-gate assert(fd == h->rh_doorfd_old); 3049*7c478bd9Sstevel@tonic-gate (void) close(h->rh_doorfd_old); 3050*7c478bd9Sstevel@tonic-gate h->rh_doorfd_old = -1; 3051*7c478bd9Sstevel@tonic-gate } 3052*7c478bd9Sstevel@tonic-gate } 3053*7c478bd9Sstevel@tonic-gate handle_unrefed(h); /* drops h->rh_lock */ 3054*7c478bd9Sstevel@tonic-gate 3055*7c478bd9Sstevel@tonic-gate if (r < 0) 3056*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3057*7c478bd9Sstevel@tonic-gate 3058*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_DONE) 3059*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 3060*7c478bd9Sstevel@tonic-gate 3061*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 3062*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3063*7c478bd9Sstevel@tonic-gate 3064*7c478bd9Sstevel@tonic-gate /* the following will be non-zero for delete notifications */ 3065*7c478bd9Sstevel@tonic-gate return (strlcpy(out, response.rpr_fmri, sz)); 3066*7c478bd9Sstevel@tonic-gate } 3067*7c478bd9Sstevel@tonic-gate 3068*7c478bd9Sstevel@tonic-gate static int 3069*7c478bd9Sstevel@tonic-gate _scf_snapshot_take(scf_instance_t *inst, const char *name, 3070*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, int flags) 3071*7c478bd9Sstevel@tonic-gate { 3072*7c478bd9Sstevel@tonic-gate scf_handle_t *h = inst->rd_d.rd_handle; 3073*7c478bd9Sstevel@tonic-gate 3074*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_take request; 3075*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 3076*7c478bd9Sstevel@tonic-gate 3077*7c478bd9Sstevel@tonic-gate int r; 3078*7c478bd9Sstevel@tonic-gate 3079*7c478bd9Sstevel@tonic-gate if (h != snap->rd_d.rd_handle) 3080*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 3081*7c478bd9Sstevel@tonic-gate 3082*7c478bd9Sstevel@tonic-gate if (strlcpy(request.rpr_name, (name != NULL)? name : "", 3083*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_name)) >= sizeof (request.rpr_name)) 3084*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3085*7c478bd9Sstevel@tonic-gate 3086*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3087*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_SNAPSHOT_TAKE; 3088*7c478bd9Sstevel@tonic-gate request.rpr_entityid_src = inst->rd_d.rd_entity; 3089*7c478bd9Sstevel@tonic-gate request.rpr_entityid_dest = snap->rd_d.rd_entity; 3090*7c478bd9Sstevel@tonic-gate request.rpr_flags = flags; 3091*7c478bd9Sstevel@tonic-gate 3092*7c478bd9Sstevel@tonic-gate datael_finish_reset(&inst->rd_d); 3093*7c478bd9Sstevel@tonic-gate datael_finish_reset(&snap->rd_d); 3094*7c478bd9Sstevel@tonic-gate 3095*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 3096*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 3097*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3098*7c478bd9Sstevel@tonic-gate 3099*7c478bd9Sstevel@tonic-gate if (r < 0) 3100*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3101*7c478bd9Sstevel@tonic-gate 3102*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 3103*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3104*7c478bd9Sstevel@tonic-gate 3105*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3106*7c478bd9Sstevel@tonic-gate } 3107*7c478bd9Sstevel@tonic-gate 3108*7c478bd9Sstevel@tonic-gate int 3109*7c478bd9Sstevel@tonic-gate _scf_snapshot_take_new_named(scf_instance_t *inst, 3110*7c478bd9Sstevel@tonic-gate const char *svcname, const char *instname, const char *snapname, 3111*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap) 3112*7c478bd9Sstevel@tonic-gate { 3113*7c478bd9Sstevel@tonic-gate scf_handle_t *h = inst->rd_d.rd_handle; 3114*7c478bd9Sstevel@tonic-gate 3115*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_take_named request; 3116*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 3117*7c478bd9Sstevel@tonic-gate 3118*7c478bd9Sstevel@tonic-gate int r; 3119*7c478bd9Sstevel@tonic-gate 3120*7c478bd9Sstevel@tonic-gate if (h != snap->rd_d.rd_handle) 3121*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 3122*7c478bd9Sstevel@tonic-gate 3123*7c478bd9Sstevel@tonic-gate if (strlcpy(request.rpr_svcname, svcname, 3124*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_svcname)) >= sizeof (request.rpr_svcname)) 3125*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3126*7c478bd9Sstevel@tonic-gate 3127*7c478bd9Sstevel@tonic-gate if (strlcpy(request.rpr_instname, instname, 3128*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_instname)) >= sizeof (request.rpr_instname)) 3129*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3130*7c478bd9Sstevel@tonic-gate 3131*7c478bd9Sstevel@tonic-gate if (strlcpy(request.rpr_name, snapname, 3132*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_name)) >= sizeof (request.rpr_name)) 3133*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3134*7c478bd9Sstevel@tonic-gate 3135*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3136*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_SNAPSHOT_TAKE_NAMED; 3137*7c478bd9Sstevel@tonic-gate request.rpr_entityid_src = inst->rd_d.rd_entity; 3138*7c478bd9Sstevel@tonic-gate request.rpr_entityid_dest = snap->rd_d.rd_entity; 3139*7c478bd9Sstevel@tonic-gate 3140*7c478bd9Sstevel@tonic-gate datael_finish_reset(&inst->rd_d); 3141*7c478bd9Sstevel@tonic-gate datael_finish_reset(&snap->rd_d); 3142*7c478bd9Sstevel@tonic-gate 3143*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 3144*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 3145*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3146*7c478bd9Sstevel@tonic-gate 3147*7c478bd9Sstevel@tonic-gate if (r < 0) 3148*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3149*7c478bd9Sstevel@tonic-gate 3150*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 3151*7c478bd9Sstevel@tonic-gate assert(response.rpr_response != 3152*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_FAIL_TYPE_MISMATCH); 3153*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3154*7c478bd9Sstevel@tonic-gate } 3155*7c478bd9Sstevel@tonic-gate 3156*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3157*7c478bd9Sstevel@tonic-gate } 3158*7c478bd9Sstevel@tonic-gate 3159*7c478bd9Sstevel@tonic-gate int 3160*7c478bd9Sstevel@tonic-gate _scf_snapshot_take_new(scf_instance_t *inst, const char *name, 3161*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap) 3162*7c478bd9Sstevel@tonic-gate { 3163*7c478bd9Sstevel@tonic-gate return (_scf_snapshot_take(inst, name, snap, REP_SNAPSHOT_NEW)); 3164*7c478bd9Sstevel@tonic-gate } 3165*7c478bd9Sstevel@tonic-gate 3166*7c478bd9Sstevel@tonic-gate int 3167*7c478bd9Sstevel@tonic-gate _scf_snapshot_take_attach(scf_instance_t *inst, scf_snapshot_t *snap) 3168*7c478bd9Sstevel@tonic-gate { 3169*7c478bd9Sstevel@tonic-gate return (_scf_snapshot_take(inst, NULL, snap, REP_SNAPSHOT_ATTACH)); 3170*7c478bd9Sstevel@tonic-gate } 3171*7c478bd9Sstevel@tonic-gate 3172*7c478bd9Sstevel@tonic-gate int 3173*7c478bd9Sstevel@tonic-gate _scf_snapshot_attach(scf_snapshot_t *src, scf_snapshot_t *dest) 3174*7c478bd9Sstevel@tonic-gate { 3175*7c478bd9Sstevel@tonic-gate scf_handle_t *h = dest->rd_d.rd_handle; 3176*7c478bd9Sstevel@tonic-gate 3177*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_attach request; 3178*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 3179*7c478bd9Sstevel@tonic-gate 3180*7c478bd9Sstevel@tonic-gate int r; 3181*7c478bd9Sstevel@tonic-gate 3182*7c478bd9Sstevel@tonic-gate if (h != src->rd_d.rd_handle) 3183*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 3184*7c478bd9Sstevel@tonic-gate 3185*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3186*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_SNAPSHOT_ATTACH; 3187*7c478bd9Sstevel@tonic-gate request.rpr_entityid_src = src->rd_d.rd_entity; 3188*7c478bd9Sstevel@tonic-gate request.rpr_entityid_dest = dest->rd_d.rd_entity; 3189*7c478bd9Sstevel@tonic-gate 3190*7c478bd9Sstevel@tonic-gate datael_finish_reset(&src->rd_d); 3191*7c478bd9Sstevel@tonic-gate datael_finish_reset(&dest->rd_d); 3192*7c478bd9Sstevel@tonic-gate 3193*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 3194*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 3195*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3196*7c478bd9Sstevel@tonic-gate 3197*7c478bd9Sstevel@tonic-gate if (r < 0) 3198*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3199*7c478bd9Sstevel@tonic-gate 3200*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 3201*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3202*7c478bd9Sstevel@tonic-gate 3203*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3204*7c478bd9Sstevel@tonic-gate } 3205*7c478bd9Sstevel@tonic-gate 3206*7c478bd9Sstevel@tonic-gate /* 3207*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, _INTERNAL 3208*7c478bd9Sstevel@tonic-gate * (bad server response or id in use), _NO_RESOURCES, or _NO_MEMORY. 3209*7c478bd9Sstevel@tonic-gate */ 3210*7c478bd9Sstevel@tonic-gate scf_property_t * 3211*7c478bd9Sstevel@tonic-gate scf_property_create(scf_handle_t *handle) 3212*7c478bd9Sstevel@tonic-gate { 3213*7c478bd9Sstevel@tonic-gate scf_property_t *ret; 3214*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 3215*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 3216*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->rd_d, handle, 3217*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTY) == -1) { 3218*7c478bd9Sstevel@tonic-gate uu_free(ret); 3219*7c478bd9Sstevel@tonic-gate return (NULL); 3220*7c478bd9Sstevel@tonic-gate } 3221*7c478bd9Sstevel@tonic-gate } else { 3222*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3223*7c478bd9Sstevel@tonic-gate } 3224*7c478bd9Sstevel@tonic-gate 3225*7c478bd9Sstevel@tonic-gate return (ret); 3226*7c478bd9Sstevel@tonic-gate } 3227*7c478bd9Sstevel@tonic-gate 3228*7c478bd9Sstevel@tonic-gate scf_handle_t * 3229*7c478bd9Sstevel@tonic-gate scf_property_handle(const scf_property_t *val) 3230*7c478bd9Sstevel@tonic-gate { 3231*7c478bd9Sstevel@tonic-gate return (datael_handle(&val->rd_d)); 3232*7c478bd9Sstevel@tonic-gate } 3233*7c478bd9Sstevel@tonic-gate 3234*7c478bd9Sstevel@tonic-gate void 3235*7c478bd9Sstevel@tonic-gate scf_property_destroy(scf_property_t *val) 3236*7c478bd9Sstevel@tonic-gate { 3237*7c478bd9Sstevel@tonic-gate if (val == NULL) 3238*7c478bd9Sstevel@tonic-gate return; 3239*7c478bd9Sstevel@tonic-gate 3240*7c478bd9Sstevel@tonic-gate datael_destroy(&val->rd_d); 3241*7c478bd9Sstevel@tonic-gate uu_free(val); 3242*7c478bd9Sstevel@tonic-gate } 3243*7c478bd9Sstevel@tonic-gate 3244*7c478bd9Sstevel@tonic-gate static int 3245*7c478bd9Sstevel@tonic-gate property_type_locked(const scf_property_t *prop, 3246*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t *out) 3247*7c478bd9Sstevel@tonic-gate { 3248*7c478bd9Sstevel@tonic-gate scf_handle_t *h = prop->rd_d.rd_handle; 3249*7c478bd9Sstevel@tonic-gate 3250*7c478bd9Sstevel@tonic-gate struct rep_protocol_property_request request; 3251*7c478bd9Sstevel@tonic-gate struct rep_protocol_integer_response response; 3252*7c478bd9Sstevel@tonic-gate 3253*7c478bd9Sstevel@tonic-gate int r; 3254*7c478bd9Sstevel@tonic-gate 3255*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 3256*7c478bd9Sstevel@tonic-gate 3257*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_PROPERTY_GET_TYPE; 3258*7c478bd9Sstevel@tonic-gate request.rpr_entityid = prop->rd_d.rd_entity; 3259*7c478bd9Sstevel@tonic-gate 3260*7c478bd9Sstevel@tonic-gate datael_finish_reset(&prop->rd_d); 3261*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 3262*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 3263*7c478bd9Sstevel@tonic-gate 3264*7c478bd9Sstevel@tonic-gate if (r < 0) 3265*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3266*7c478bd9Sstevel@tonic-gate 3267*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS || 3268*7c478bd9Sstevel@tonic-gate r < sizeof (response)) { 3269*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3270*7c478bd9Sstevel@tonic-gate } 3271*7c478bd9Sstevel@tonic-gate *out = response.rpr_value; 3272*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3273*7c478bd9Sstevel@tonic-gate } 3274*7c478bd9Sstevel@tonic-gate 3275*7c478bd9Sstevel@tonic-gate int 3276*7c478bd9Sstevel@tonic-gate scf_property_type(const scf_property_t *prop, scf_type_t *out) 3277*7c478bd9Sstevel@tonic-gate { 3278*7c478bd9Sstevel@tonic-gate scf_handle_t *h = prop->rd_d.rd_handle; 3279*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t out_raw; 3280*7c478bd9Sstevel@tonic-gate int ret; 3281*7c478bd9Sstevel@tonic-gate 3282*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3283*7c478bd9Sstevel@tonic-gate ret = property_type_locked(prop, &out_raw); 3284*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3285*7c478bd9Sstevel@tonic-gate 3286*7c478bd9Sstevel@tonic-gate if (ret == SCF_SUCCESS) 3287*7c478bd9Sstevel@tonic-gate *out = scf_protocol_type_to_type(out_raw); 3288*7c478bd9Sstevel@tonic-gate 3289*7c478bd9Sstevel@tonic-gate return (ret); 3290*7c478bd9Sstevel@tonic-gate } 3291*7c478bd9Sstevel@tonic-gate 3292*7c478bd9Sstevel@tonic-gate int 3293*7c478bd9Sstevel@tonic-gate scf_property_is_type(const scf_property_t *prop, scf_type_t base_arg) 3294*7c478bd9Sstevel@tonic-gate { 3295*7c478bd9Sstevel@tonic-gate scf_handle_t *h = prop->rd_d.rd_handle; 3296*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t base = scf_type_to_protocol_type(base_arg); 3297*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t type; 3298*7c478bd9Sstevel@tonic-gate int ret; 3299*7c478bd9Sstevel@tonic-gate 3300*7c478bd9Sstevel@tonic-gate if (base == REP_PROTOCOL_TYPE_INVALID) 3301*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3302*7c478bd9Sstevel@tonic-gate 3303*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3304*7c478bd9Sstevel@tonic-gate ret = property_type_locked(prop, &type); 3305*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3306*7c478bd9Sstevel@tonic-gate 3307*7c478bd9Sstevel@tonic-gate if (ret == SCF_SUCCESS) { 3308*7c478bd9Sstevel@tonic-gate if (!scf_is_compatible_type(base, type)) 3309*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_TYPE_MISMATCH)); 3310*7c478bd9Sstevel@tonic-gate } 3311*7c478bd9Sstevel@tonic-gate return (ret); 3312*7c478bd9Sstevel@tonic-gate } 3313*7c478bd9Sstevel@tonic-gate 3314*7c478bd9Sstevel@tonic-gate ssize_t 3315*7c478bd9Sstevel@tonic-gate scf_property_get_name(const scf_property_t *prop, char *out, size_t len) 3316*7c478bd9Sstevel@tonic-gate { 3317*7c478bd9Sstevel@tonic-gate return (datael_get_name(&prop->rd_d, out, len, RP_ENTITY_NAME_NAME)); 3318*7c478bd9Sstevel@tonic-gate } 3319*7c478bd9Sstevel@tonic-gate 3320*7c478bd9Sstevel@tonic-gate /* 3321*7c478bd9Sstevel@tonic-gate * transaction functions 3322*7c478bd9Sstevel@tonic-gate */ 3323*7c478bd9Sstevel@tonic-gate 3324*7c478bd9Sstevel@tonic-gate /* 3325*7c478bd9Sstevel@tonic-gate * Fails with _NO_MEMORY, _INVALID_ARGUMENT (handle is NULL), _HANDLE_DESTROYED, 3326*7c478bd9Sstevel@tonic-gate * _INTERNAL (bad server response or id in use), or _NO_RESOURCES. 3327*7c478bd9Sstevel@tonic-gate */ 3328*7c478bd9Sstevel@tonic-gate scf_transaction_t * 3329*7c478bd9Sstevel@tonic-gate scf_transaction_create(scf_handle_t *handle) 3330*7c478bd9Sstevel@tonic-gate { 3331*7c478bd9Sstevel@tonic-gate scf_transaction_t *ret; 3332*7c478bd9Sstevel@tonic-gate 3333*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (scf_transaction_t)); 3334*7c478bd9Sstevel@tonic-gate if (ret == NULL) { 3335*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3336*7c478bd9Sstevel@tonic-gate return (NULL); 3337*7c478bd9Sstevel@tonic-gate } 3338*7c478bd9Sstevel@tonic-gate if (datael_init(&ret->tran_pg.rd_d, handle, 3339*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTYGRP) == -1) { 3340*7c478bd9Sstevel@tonic-gate uu_free(ret); 3341*7c478bd9Sstevel@tonic-gate return (NULL); /* error already set */ 3342*7c478bd9Sstevel@tonic-gate } 3343*7c478bd9Sstevel@tonic-gate ret->tran_state = TRAN_STATE_NEW; 3344*7c478bd9Sstevel@tonic-gate ret->tran_props = uu_list_create(tran_entry_pool, ret, UU_LIST_SORTED); 3345*7c478bd9Sstevel@tonic-gate if (ret->tran_props == NULL) { 3346*7c478bd9Sstevel@tonic-gate datael_destroy(&ret->tran_pg.rd_d); 3347*7c478bd9Sstevel@tonic-gate uu_free(ret); 3348*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3349*7c478bd9Sstevel@tonic-gate return (NULL); 3350*7c478bd9Sstevel@tonic-gate } 3351*7c478bd9Sstevel@tonic-gate 3352*7c478bd9Sstevel@tonic-gate return (ret); 3353*7c478bd9Sstevel@tonic-gate } 3354*7c478bd9Sstevel@tonic-gate 3355*7c478bd9Sstevel@tonic-gate scf_handle_t * 3356*7c478bd9Sstevel@tonic-gate scf_transaction_handle(const scf_transaction_t *val) 3357*7c478bd9Sstevel@tonic-gate { 3358*7c478bd9Sstevel@tonic-gate return (handle_get(val->tran_pg.rd_d.rd_handle)); 3359*7c478bd9Sstevel@tonic-gate } 3360*7c478bd9Sstevel@tonic-gate 3361*7c478bd9Sstevel@tonic-gate int 3362*7c478bd9Sstevel@tonic-gate scf_transaction_start(scf_transaction_t *tran, scf_propertygroup_t *pg) 3363*7c478bd9Sstevel@tonic-gate { 3364*7c478bd9Sstevel@tonic-gate scf_handle_t *h = tran->tran_pg.rd_d.rd_handle; 3365*7c478bd9Sstevel@tonic-gate 3366*7c478bd9Sstevel@tonic-gate struct rep_protocol_transaction_start request; 3367*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 3368*7c478bd9Sstevel@tonic-gate int r; 3369*7c478bd9Sstevel@tonic-gate 3370*7c478bd9Sstevel@tonic-gate if (h != pg->rd_d.rd_handle) 3371*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 3372*7c478bd9Sstevel@tonic-gate 3373*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3374*7c478bd9Sstevel@tonic-gate if (tran->tran_state != TRAN_STATE_NEW) { 3375*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3376*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_IN_USE)); 3377*7c478bd9Sstevel@tonic-gate } 3378*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_PROPERTYGRP_TX_START; 3379*7c478bd9Sstevel@tonic-gate request.rpr_entityid_tx = tran->tran_pg.rd_d.rd_entity; 3380*7c478bd9Sstevel@tonic-gate request.rpr_entityid = pg->rd_d.rd_entity; 3381*7c478bd9Sstevel@tonic-gate 3382*7c478bd9Sstevel@tonic-gate datael_finish_reset(&tran->tran_pg.rd_d); 3383*7c478bd9Sstevel@tonic-gate datael_finish_reset(&pg->rd_d); 3384*7c478bd9Sstevel@tonic-gate 3385*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 3386*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 3387*7c478bd9Sstevel@tonic-gate 3388*7c478bd9Sstevel@tonic-gate if (r < 0) { 3389*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3390*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3391*7c478bd9Sstevel@tonic-gate } 3392*7c478bd9Sstevel@tonic-gate 3393*7c478bd9Sstevel@tonic-gate /* r < sizeof (response) cannot happen because sizeof (response) == 4 */ 3394*7c478bd9Sstevel@tonic-gate 3395*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS || 3396*7c478bd9Sstevel@tonic-gate r < sizeof (response)) { 3397*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3398*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3399*7c478bd9Sstevel@tonic-gate } 3400*7c478bd9Sstevel@tonic-gate 3401*7c478bd9Sstevel@tonic-gate tran->tran_state = TRAN_STATE_SETUP; 3402*7c478bd9Sstevel@tonic-gate tran->tran_invalid = 0; 3403*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3404*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3405*7c478bd9Sstevel@tonic-gate } 3406*7c478bd9Sstevel@tonic-gate 3407*7c478bd9Sstevel@tonic-gate static void 3408*7c478bd9Sstevel@tonic-gate entry_invalidate(scf_transaction_entry_t *cur, int and_destroy, 3409*7c478bd9Sstevel@tonic-gate int and_reset_value) 3410*7c478bd9Sstevel@tonic-gate { 3411*7c478bd9Sstevel@tonic-gate scf_value_t *v, *next; 3412*7c478bd9Sstevel@tonic-gate scf_transaction_t *tx; 3413*7c478bd9Sstevel@tonic-gate scf_handle_t *h = cur->entry_handle; 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 3416*7c478bd9Sstevel@tonic-gate 3417*7c478bd9Sstevel@tonic-gate if ((tx = cur->entry_tx) != NULL) { 3418*7c478bd9Sstevel@tonic-gate tx->tran_invalid = 1; 3419*7c478bd9Sstevel@tonic-gate uu_list_remove(tx->tran_props, cur); 3420*7c478bd9Sstevel@tonic-gate cur->entry_tx = NULL; 3421*7c478bd9Sstevel@tonic-gate } 3422*7c478bd9Sstevel@tonic-gate 3423*7c478bd9Sstevel@tonic-gate cur->entry_property = NULL; 3424*7c478bd9Sstevel@tonic-gate cur->entry_state = ENTRY_STATE_INVALID; 3425*7c478bd9Sstevel@tonic-gate cur->entry_action = REP_PROTOCOL_TX_ENTRY_INVALID; 3426*7c478bd9Sstevel@tonic-gate cur->entry_type = REP_PROTOCOL_TYPE_INVALID; 3427*7c478bd9Sstevel@tonic-gate 3428*7c478bd9Sstevel@tonic-gate for (v = cur->entry_head; v != NULL; v = next) { 3429*7c478bd9Sstevel@tonic-gate next = v->value_next; 3430*7c478bd9Sstevel@tonic-gate v->value_tx = NULL; 3431*7c478bd9Sstevel@tonic-gate v->value_next = NULL; 3432*7c478bd9Sstevel@tonic-gate if (and_destroy || and_reset_value) 3433*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, and_destroy); 3434*7c478bd9Sstevel@tonic-gate } 3435*7c478bd9Sstevel@tonic-gate cur->entry_head = NULL; 3436*7c478bd9Sstevel@tonic-gate } 3437*7c478bd9Sstevel@tonic-gate 3438*7c478bd9Sstevel@tonic-gate static void 3439*7c478bd9Sstevel@tonic-gate entry_destroy_locked(scf_transaction_entry_t *entry) 3440*7c478bd9Sstevel@tonic-gate { 3441*7c478bd9Sstevel@tonic-gate scf_handle_t *h = entry->entry_handle; 3442*7c478bd9Sstevel@tonic-gate 3443*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 3444*7c478bd9Sstevel@tonic-gate 3445*7c478bd9Sstevel@tonic-gate entry_invalidate(entry, 0, 0); 3446*7c478bd9Sstevel@tonic-gate 3447*7c478bd9Sstevel@tonic-gate entry->entry_handle = NULL; 3448*7c478bd9Sstevel@tonic-gate assert(h->rh_entries > 0); 3449*7c478bd9Sstevel@tonic-gate --h->rh_entries; 3450*7c478bd9Sstevel@tonic-gate --h->rh_extrefs; 3451*7c478bd9Sstevel@tonic-gate uu_list_node_fini(entry, &entry->entry_link, tran_entry_pool); 3452*7c478bd9Sstevel@tonic-gate uu_free(entry); 3453*7c478bd9Sstevel@tonic-gate } 3454*7c478bd9Sstevel@tonic-gate 3455*7c478bd9Sstevel@tonic-gate static int 3456*7c478bd9Sstevel@tonic-gate transaction_add(scf_transaction_t *tran, scf_transaction_entry_t *entry, 3457*7c478bd9Sstevel@tonic-gate enum rep_protocol_transaction_action action, 3458*7c478bd9Sstevel@tonic-gate const char *prop, rep_protocol_value_type_t type) 3459*7c478bd9Sstevel@tonic-gate { 3460*7c478bd9Sstevel@tonic-gate scf_handle_t *h = tran->tran_pg.rd_d.rd_handle; 3461*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *old; 3462*7c478bd9Sstevel@tonic-gate scf_property_t *prop_p; 3463*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t oldtype; 3464*7c478bd9Sstevel@tonic-gate scf_error_t error = SCF_ERROR_NONE; 3465*7c478bd9Sstevel@tonic-gate int ret; 3466*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 3467*7c478bd9Sstevel@tonic-gate 3468*7c478bd9Sstevel@tonic-gate if (h != entry->entry_handle) 3469*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 3470*7c478bd9Sstevel@tonic-gate 3471*7c478bd9Sstevel@tonic-gate if (action == REP_PROTOCOL_TX_ENTRY_DELETE) 3472*7c478bd9Sstevel@tonic-gate assert(type == REP_PROTOCOL_TYPE_INVALID); 3473*7c478bd9Sstevel@tonic-gate else if (type == REP_PROTOCOL_TYPE_INVALID) 3474*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3475*7c478bd9Sstevel@tonic-gate 3476*7c478bd9Sstevel@tonic-gate prop_p = HANDLE_HOLD_PROPERTY(h); 3477*7c478bd9Sstevel@tonic-gate 3478*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3479*7c478bd9Sstevel@tonic-gate if (tran->tran_state != TRAN_STATE_SETUP) { 3480*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_NOT_SET; 3481*7c478bd9Sstevel@tonic-gate goto error; 3482*7c478bd9Sstevel@tonic-gate } 3483*7c478bd9Sstevel@tonic-gate if (tran->tran_invalid) { 3484*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_NOT_SET; 3485*7c478bd9Sstevel@tonic-gate goto error; 3486*7c478bd9Sstevel@tonic-gate } 3487*7c478bd9Sstevel@tonic-gate 3488*7c478bd9Sstevel@tonic-gate if (entry->entry_state != ENTRY_STATE_INVALID) 3489*7c478bd9Sstevel@tonic-gate entry_invalidate(entry, 0, 0); 3490*7c478bd9Sstevel@tonic-gate 3491*7c478bd9Sstevel@tonic-gate old = uu_list_find(tran->tran_props, &prop, NULL, &idx); 3492*7c478bd9Sstevel@tonic-gate if (old != NULL) { 3493*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_IN_USE; 3494*7c478bd9Sstevel@tonic-gate goto error; 3495*7c478bd9Sstevel@tonic-gate } 3496*7c478bd9Sstevel@tonic-gate 3497*7c478bd9Sstevel@tonic-gate ret = datael_get_child_locked(&tran->tran_pg.rd_d, prop, 3498*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_PROPERTY, &prop_p->rd_d); 3499*7c478bd9Sstevel@tonic-gate if (ret == -1 && (error = scf_error()) != SCF_ERROR_NOT_FOUND) { 3500*7c478bd9Sstevel@tonic-gate goto error; 3501*7c478bd9Sstevel@tonic-gate } 3502*7c478bd9Sstevel@tonic-gate 3503*7c478bd9Sstevel@tonic-gate switch (action) { 3504*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TX_ENTRY_DELETE: 3505*7c478bd9Sstevel@tonic-gate if (ret == -1) { 3506*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_NOT_FOUND; 3507*7c478bd9Sstevel@tonic-gate goto error; 3508*7c478bd9Sstevel@tonic-gate } 3509*7c478bd9Sstevel@tonic-gate break; 3510*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TX_ENTRY_NEW: 3511*7c478bd9Sstevel@tonic-gate if (ret != -1) { 3512*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_EXISTS; 3513*7c478bd9Sstevel@tonic-gate goto error; 3514*7c478bd9Sstevel@tonic-gate } 3515*7c478bd9Sstevel@tonic-gate break; 3516*7c478bd9Sstevel@tonic-gate 3517*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TX_ENTRY_CLEAR: 3518*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TX_ENTRY_REPLACE: 3519*7c478bd9Sstevel@tonic-gate if (ret == -1) { 3520*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_NOT_FOUND; 3521*7c478bd9Sstevel@tonic-gate goto error; 3522*7c478bd9Sstevel@tonic-gate } 3523*7c478bd9Sstevel@tonic-gate if (action == REP_PROTOCOL_TX_ENTRY_CLEAR) { 3524*7c478bd9Sstevel@tonic-gate if (property_type_locked(prop_p, &oldtype) == -1) { 3525*7c478bd9Sstevel@tonic-gate error = scf_error(); 3526*7c478bd9Sstevel@tonic-gate goto error; 3527*7c478bd9Sstevel@tonic-gate } 3528*7c478bd9Sstevel@tonic-gate if (oldtype != type) { 3529*7c478bd9Sstevel@tonic-gate error = SCF_ERROR_TYPE_MISMATCH; 3530*7c478bd9Sstevel@tonic-gate goto error; 3531*7c478bd9Sstevel@tonic-gate } 3532*7c478bd9Sstevel@tonic-gate } 3533*7c478bd9Sstevel@tonic-gate break; 3534*7c478bd9Sstevel@tonic-gate default: 3535*7c478bd9Sstevel@tonic-gate assert(0); 3536*7c478bd9Sstevel@tonic-gate abort(); 3537*7c478bd9Sstevel@tonic-gate } 3538*7c478bd9Sstevel@tonic-gate 3539*7c478bd9Sstevel@tonic-gate (void) strlcpy(entry->entry_namebuf, prop, 3540*7c478bd9Sstevel@tonic-gate sizeof (entry->entry_namebuf)); 3541*7c478bd9Sstevel@tonic-gate entry->entry_property = entry->entry_namebuf; 3542*7c478bd9Sstevel@tonic-gate entry->entry_action = action; 3543*7c478bd9Sstevel@tonic-gate entry->entry_type = type; 3544*7c478bd9Sstevel@tonic-gate 3545*7c478bd9Sstevel@tonic-gate entry->entry_state = ENTRY_STATE_IN_TX_ACTION; 3546*7c478bd9Sstevel@tonic-gate entry->entry_tx = tran; 3547*7c478bd9Sstevel@tonic-gate uu_list_insert(tran->tran_props, entry, idx); 3548*7c478bd9Sstevel@tonic-gate 3549*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3550*7c478bd9Sstevel@tonic-gate 3551*7c478bd9Sstevel@tonic-gate HANDLE_RELE_PROPERTY(h); 3552*7c478bd9Sstevel@tonic-gate 3553*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3554*7c478bd9Sstevel@tonic-gate 3555*7c478bd9Sstevel@tonic-gate error: 3556*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3557*7c478bd9Sstevel@tonic-gate 3558*7c478bd9Sstevel@tonic-gate HANDLE_RELE_PROPERTY(h); 3559*7c478bd9Sstevel@tonic-gate 3560*7c478bd9Sstevel@tonic-gate return (scf_set_error(error)); 3561*7c478bd9Sstevel@tonic-gate } 3562*7c478bd9Sstevel@tonic-gate 3563*7c478bd9Sstevel@tonic-gate int 3564*7c478bd9Sstevel@tonic-gate scf_transaction_property_new(scf_transaction_t *tx, 3565*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *entry, const char *prop, scf_type_t type) 3566*7c478bd9Sstevel@tonic-gate { 3567*7c478bd9Sstevel@tonic-gate return (transaction_add(tx, entry, REP_PROTOCOL_TX_ENTRY_NEW, 3568*7c478bd9Sstevel@tonic-gate prop, scf_type_to_protocol_type(type))); 3569*7c478bd9Sstevel@tonic-gate } 3570*7c478bd9Sstevel@tonic-gate 3571*7c478bd9Sstevel@tonic-gate int 3572*7c478bd9Sstevel@tonic-gate scf_transaction_property_change(scf_transaction_t *tx, 3573*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *entry, const char *prop, scf_type_t type) 3574*7c478bd9Sstevel@tonic-gate { 3575*7c478bd9Sstevel@tonic-gate return (transaction_add(tx, entry, REP_PROTOCOL_TX_ENTRY_CLEAR, 3576*7c478bd9Sstevel@tonic-gate prop, scf_type_to_protocol_type(type))); 3577*7c478bd9Sstevel@tonic-gate } 3578*7c478bd9Sstevel@tonic-gate 3579*7c478bd9Sstevel@tonic-gate int 3580*7c478bd9Sstevel@tonic-gate scf_transaction_property_change_type(scf_transaction_t *tx, 3581*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *entry, const char *prop, scf_type_t type) 3582*7c478bd9Sstevel@tonic-gate { 3583*7c478bd9Sstevel@tonic-gate return (transaction_add(tx, entry, REP_PROTOCOL_TX_ENTRY_REPLACE, 3584*7c478bd9Sstevel@tonic-gate prop, scf_type_to_protocol_type(type))); 3585*7c478bd9Sstevel@tonic-gate } 3586*7c478bd9Sstevel@tonic-gate 3587*7c478bd9Sstevel@tonic-gate int 3588*7c478bd9Sstevel@tonic-gate scf_transaction_property_delete(scf_transaction_t *tx, 3589*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *entry, const char *prop) 3590*7c478bd9Sstevel@tonic-gate { 3591*7c478bd9Sstevel@tonic-gate return (transaction_add(tx, entry, REP_PROTOCOL_TX_ENTRY_DELETE, 3592*7c478bd9Sstevel@tonic-gate prop, REP_PROTOCOL_TYPE_INVALID)); 3593*7c478bd9Sstevel@tonic-gate } 3594*7c478bd9Sstevel@tonic-gate 3595*7c478bd9Sstevel@tonic-gate #define BAD_SIZE (-1UL) 3596*7c478bd9Sstevel@tonic-gate 3597*7c478bd9Sstevel@tonic-gate static size_t 3598*7c478bd9Sstevel@tonic-gate commit_value(caddr_t data, scf_value_t *val, rep_protocol_value_type_t t) 3599*7c478bd9Sstevel@tonic-gate { 3600*7c478bd9Sstevel@tonic-gate size_t len; 3601*7c478bd9Sstevel@tonic-gate 3602*7c478bd9Sstevel@tonic-gate assert(val->value_type == t); 3603*7c478bd9Sstevel@tonic-gate 3604*7c478bd9Sstevel@tonic-gate if (t == REP_PROTOCOL_TYPE_OPAQUE) { 3605*7c478bd9Sstevel@tonic-gate len = scf_opaque_encode(data, val->value_value, 3606*7c478bd9Sstevel@tonic-gate val->value_size); 3607*7c478bd9Sstevel@tonic-gate } else { 3608*7c478bd9Sstevel@tonic-gate if (data != NULL) 3609*7c478bd9Sstevel@tonic-gate len = strlcpy(data, val->value_value, 3610*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_VALUE_LEN); 3611*7c478bd9Sstevel@tonic-gate else 3612*7c478bd9Sstevel@tonic-gate len = strlen(val->value_value); 3613*7c478bd9Sstevel@tonic-gate if (len >= REP_PROTOCOL_VALUE_LEN) 3614*7c478bd9Sstevel@tonic-gate return (BAD_SIZE); 3615*7c478bd9Sstevel@tonic-gate } 3616*7c478bd9Sstevel@tonic-gate return (len + 1); /* count the '\0' */ 3617*7c478bd9Sstevel@tonic-gate } 3618*7c478bd9Sstevel@tonic-gate 3619*7c478bd9Sstevel@tonic-gate static size_t 3620*7c478bd9Sstevel@tonic-gate commit_process(scf_transaction_entry_t *cur, 3621*7c478bd9Sstevel@tonic-gate struct rep_protocol_transaction_cmd *out) 3622*7c478bd9Sstevel@tonic-gate { 3623*7c478bd9Sstevel@tonic-gate scf_value_t *child; 3624*7c478bd9Sstevel@tonic-gate size_t sz = 0; 3625*7c478bd9Sstevel@tonic-gate size_t len; 3626*7c478bd9Sstevel@tonic-gate caddr_t data = (caddr_t)out->rptc_data; 3627*7c478bd9Sstevel@tonic-gate caddr_t val_data; 3628*7c478bd9Sstevel@tonic-gate 3629*7c478bd9Sstevel@tonic-gate if (out != NULL) { 3630*7c478bd9Sstevel@tonic-gate len = strlcpy(data, cur->entry_property, REP_PROTOCOL_NAME_LEN); 3631*7c478bd9Sstevel@tonic-gate 3632*7c478bd9Sstevel@tonic-gate out->rptc_action = cur->entry_action; 3633*7c478bd9Sstevel@tonic-gate out->rptc_type = cur->entry_type; 3634*7c478bd9Sstevel@tonic-gate out->rptc_name_len = len + 1; 3635*7c478bd9Sstevel@tonic-gate } else { 3636*7c478bd9Sstevel@tonic-gate len = strlen(cur->entry_property); 3637*7c478bd9Sstevel@tonic-gate } 3638*7c478bd9Sstevel@tonic-gate 3639*7c478bd9Sstevel@tonic-gate if (len >= REP_PROTOCOL_NAME_LEN) 3640*7c478bd9Sstevel@tonic-gate return (BAD_SIZE); 3641*7c478bd9Sstevel@tonic-gate 3642*7c478bd9Sstevel@tonic-gate len = TX_SIZE(len + 1); 3643*7c478bd9Sstevel@tonic-gate 3644*7c478bd9Sstevel@tonic-gate sz += len; 3645*7c478bd9Sstevel@tonic-gate val_data = data + len; 3646*7c478bd9Sstevel@tonic-gate 3647*7c478bd9Sstevel@tonic-gate for (child = cur->entry_head; child != NULL; 3648*7c478bd9Sstevel@tonic-gate child = child->value_next) { 3649*7c478bd9Sstevel@tonic-gate assert(cur->entry_action != REP_PROTOCOL_TX_ENTRY_DELETE); 3650*7c478bd9Sstevel@tonic-gate if (out != NULL) { 3651*7c478bd9Sstevel@tonic-gate len = commit_value(val_data + sizeof (uint32_t), child, 3652*7c478bd9Sstevel@tonic-gate cur->entry_type); 3653*7c478bd9Sstevel@tonic-gate /* LINTED alignment */ 3654*7c478bd9Sstevel@tonic-gate *(uint32_t *)val_data = len; 3655*7c478bd9Sstevel@tonic-gate } else 3656*7c478bd9Sstevel@tonic-gate len = commit_value(NULL, child, cur->entry_type); 3657*7c478bd9Sstevel@tonic-gate 3658*7c478bd9Sstevel@tonic-gate if (len == BAD_SIZE) 3659*7c478bd9Sstevel@tonic-gate return (BAD_SIZE); 3660*7c478bd9Sstevel@tonic-gate 3661*7c478bd9Sstevel@tonic-gate len += sizeof (uint32_t); 3662*7c478bd9Sstevel@tonic-gate len = TX_SIZE(len); 3663*7c478bd9Sstevel@tonic-gate 3664*7c478bd9Sstevel@tonic-gate sz += len; 3665*7c478bd9Sstevel@tonic-gate val_data += len; 3666*7c478bd9Sstevel@tonic-gate } 3667*7c478bd9Sstevel@tonic-gate 3668*7c478bd9Sstevel@tonic-gate assert(val_data - data == sz); 3669*7c478bd9Sstevel@tonic-gate 3670*7c478bd9Sstevel@tonic-gate if (out != NULL) 3671*7c478bd9Sstevel@tonic-gate out->rptc_size = REP_PROTOCOL_TRANSACTION_CMD_SIZE(sz); 3672*7c478bd9Sstevel@tonic-gate 3673*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_TRANSACTION_CMD_SIZE(sz)); 3674*7c478bd9Sstevel@tonic-gate } 3675*7c478bd9Sstevel@tonic-gate 3676*7c478bd9Sstevel@tonic-gate int 3677*7c478bd9Sstevel@tonic-gate scf_transaction_commit(scf_transaction_t *tran) 3678*7c478bd9Sstevel@tonic-gate { 3679*7c478bd9Sstevel@tonic-gate scf_handle_t *h = tran->tran_pg.rd_d.rd_handle; 3680*7c478bd9Sstevel@tonic-gate 3681*7c478bd9Sstevel@tonic-gate struct rep_protocol_transaction_commit *request; 3682*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 3683*7c478bd9Sstevel@tonic-gate uintptr_t cmd; 3684*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *cur; 3685*7c478bd9Sstevel@tonic-gate size_t total, size; 3686*7c478bd9Sstevel@tonic-gate size_t request_size; 3687*7c478bd9Sstevel@tonic-gate size_t new_total; 3688*7c478bd9Sstevel@tonic-gate int r; 3689*7c478bd9Sstevel@tonic-gate 3690*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3691*7c478bd9Sstevel@tonic-gate if (tran->tran_state != TRAN_STATE_SETUP || 3692*7c478bd9Sstevel@tonic-gate tran->tran_invalid) { 3693*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3694*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3695*7c478bd9Sstevel@tonic-gate } 3696*7c478bd9Sstevel@tonic-gate 3697*7c478bd9Sstevel@tonic-gate total = 0; 3698*7c478bd9Sstevel@tonic-gate for (cur = uu_list_first(tran->tran_props); cur != NULL; 3699*7c478bd9Sstevel@tonic-gate cur = uu_list_next(tran->tran_props, cur)) { 3700*7c478bd9Sstevel@tonic-gate size = commit_process(cur, NULL); 3701*7c478bd9Sstevel@tonic-gate if (size == BAD_SIZE) { 3702*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3703*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 3704*7c478bd9Sstevel@tonic-gate } 3705*7c478bd9Sstevel@tonic-gate assert(TX_SIZE(size) == size); 3706*7c478bd9Sstevel@tonic-gate total += size; 3707*7c478bd9Sstevel@tonic-gate } 3708*7c478bd9Sstevel@tonic-gate 3709*7c478bd9Sstevel@tonic-gate request_size = REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(total); 3710*7c478bd9Sstevel@tonic-gate request = alloca(request_size); 3711*7c478bd9Sstevel@tonic-gate (void) memset(request, '\0', request_size); 3712*7c478bd9Sstevel@tonic-gate request->rpr_request = REP_PROTOCOL_PROPERTYGRP_TX_COMMIT; 3713*7c478bd9Sstevel@tonic-gate request->rpr_entityid = tran->tran_pg.rd_d.rd_entity; 3714*7c478bd9Sstevel@tonic-gate request->rpr_size = request_size; 3715*7c478bd9Sstevel@tonic-gate cmd = (uintptr_t)request->rpr_cmd; 3716*7c478bd9Sstevel@tonic-gate 3717*7c478bd9Sstevel@tonic-gate datael_finish_reset(&tran->tran_pg.rd_d); 3718*7c478bd9Sstevel@tonic-gate 3719*7c478bd9Sstevel@tonic-gate new_total = 0; 3720*7c478bd9Sstevel@tonic-gate for (cur = uu_list_first(tran->tran_props); cur != NULL; 3721*7c478bd9Sstevel@tonic-gate cur = uu_list_next(tran->tran_props, cur)) { 3722*7c478bd9Sstevel@tonic-gate size = commit_process(cur, (void *)cmd); 3723*7c478bd9Sstevel@tonic-gate if (size == BAD_SIZE) { 3724*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3725*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 3726*7c478bd9Sstevel@tonic-gate } 3727*7c478bd9Sstevel@tonic-gate cmd += size; 3728*7c478bd9Sstevel@tonic-gate new_total += size; 3729*7c478bd9Sstevel@tonic-gate } 3730*7c478bd9Sstevel@tonic-gate assert(new_total == total); 3731*7c478bd9Sstevel@tonic-gate 3732*7c478bd9Sstevel@tonic-gate r = make_door_call(h, request, request_size, 3733*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 3734*7c478bd9Sstevel@tonic-gate 3735*7c478bd9Sstevel@tonic-gate if (r < 0) { 3736*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3737*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 3738*7c478bd9Sstevel@tonic-gate } 3739*7c478bd9Sstevel@tonic-gate 3740*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS && 3741*7c478bd9Sstevel@tonic-gate response.rpr_response != REP_PROTOCOL_FAIL_NOT_LATEST) { 3742*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3743*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 3744*7c478bd9Sstevel@tonic-gate } 3745*7c478bd9Sstevel@tonic-gate 3746*7c478bd9Sstevel@tonic-gate tran->tran_state = TRAN_STATE_COMMITTED; 3747*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3748*7c478bd9Sstevel@tonic-gate return (response.rpr_response == REP_PROTOCOL_SUCCESS); 3749*7c478bd9Sstevel@tonic-gate } 3750*7c478bd9Sstevel@tonic-gate 3751*7c478bd9Sstevel@tonic-gate static void 3752*7c478bd9Sstevel@tonic-gate transaction_reset(scf_transaction_t *tran) 3753*7c478bd9Sstevel@tonic-gate { 3754*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&tran->tran_pg.rd_d.rd_handle->rh_lock)); 3755*7c478bd9Sstevel@tonic-gate 3756*7c478bd9Sstevel@tonic-gate tran->tran_state = TRAN_STATE_NEW; 3757*7c478bd9Sstevel@tonic-gate datael_reset_locked(&tran->tran_pg.rd_d); 3758*7c478bd9Sstevel@tonic-gate } 3759*7c478bd9Sstevel@tonic-gate 3760*7c478bd9Sstevel@tonic-gate static void 3761*7c478bd9Sstevel@tonic-gate scf_transaction_reset_impl(scf_transaction_t *tran, int and_destroy, 3762*7c478bd9Sstevel@tonic-gate int and_reset_value) 3763*7c478bd9Sstevel@tonic-gate { 3764*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *cur; 3765*7c478bd9Sstevel@tonic-gate void *cookie; 3766*7c478bd9Sstevel@tonic-gate 3767*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&tran->tran_pg.rd_d.rd_handle->rh_lock); 3768*7c478bd9Sstevel@tonic-gate cookie = NULL; 3769*7c478bd9Sstevel@tonic-gate while ((cur = uu_list_teardown(tran->tran_props, &cookie)) != NULL) { 3770*7c478bd9Sstevel@tonic-gate cur->entry_tx = NULL; 3771*7c478bd9Sstevel@tonic-gate 3772*7c478bd9Sstevel@tonic-gate assert(cur->entry_state == ENTRY_STATE_IN_TX_ACTION); 3773*7c478bd9Sstevel@tonic-gate cur->entry_state = ENTRY_STATE_INVALID; 3774*7c478bd9Sstevel@tonic-gate 3775*7c478bd9Sstevel@tonic-gate entry_invalidate(cur, and_destroy, and_reset_value); 3776*7c478bd9Sstevel@tonic-gate if (and_destroy) 3777*7c478bd9Sstevel@tonic-gate entry_destroy_locked(cur); 3778*7c478bd9Sstevel@tonic-gate } 3779*7c478bd9Sstevel@tonic-gate transaction_reset(tran); 3780*7c478bd9Sstevel@tonic-gate handle_unrefed(tran->tran_pg.rd_d.rd_handle); 3781*7c478bd9Sstevel@tonic-gate } 3782*7c478bd9Sstevel@tonic-gate 3783*7c478bd9Sstevel@tonic-gate void 3784*7c478bd9Sstevel@tonic-gate scf_transaction_reset(scf_transaction_t *tran) 3785*7c478bd9Sstevel@tonic-gate { 3786*7c478bd9Sstevel@tonic-gate scf_transaction_reset_impl(tran, 0, 0); 3787*7c478bd9Sstevel@tonic-gate } 3788*7c478bd9Sstevel@tonic-gate 3789*7c478bd9Sstevel@tonic-gate void 3790*7c478bd9Sstevel@tonic-gate scf_transaction_reset_all(scf_transaction_t *tran) 3791*7c478bd9Sstevel@tonic-gate { 3792*7c478bd9Sstevel@tonic-gate scf_transaction_reset_impl(tran, 0, 1); 3793*7c478bd9Sstevel@tonic-gate } 3794*7c478bd9Sstevel@tonic-gate 3795*7c478bd9Sstevel@tonic-gate void 3796*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(scf_transaction_t *val) 3797*7c478bd9Sstevel@tonic-gate { 3798*7c478bd9Sstevel@tonic-gate if (val == NULL) 3799*7c478bd9Sstevel@tonic-gate return; 3800*7c478bd9Sstevel@tonic-gate 3801*7c478bd9Sstevel@tonic-gate scf_transaction_reset(val); 3802*7c478bd9Sstevel@tonic-gate 3803*7c478bd9Sstevel@tonic-gate datael_destroy(&val->tran_pg.rd_d); 3804*7c478bd9Sstevel@tonic-gate 3805*7c478bd9Sstevel@tonic-gate uu_list_destroy(val->tran_props); 3806*7c478bd9Sstevel@tonic-gate uu_free(val); 3807*7c478bd9Sstevel@tonic-gate } 3808*7c478bd9Sstevel@tonic-gate 3809*7c478bd9Sstevel@tonic-gate void 3810*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(scf_transaction_t *tran) 3811*7c478bd9Sstevel@tonic-gate { 3812*7c478bd9Sstevel@tonic-gate scf_transaction_reset_impl(tran, 1, 0); 3813*7c478bd9Sstevel@tonic-gate } 3814*7c478bd9Sstevel@tonic-gate 3815*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t * 3816*7c478bd9Sstevel@tonic-gate scf_entry_create(scf_handle_t *h) 3817*7c478bd9Sstevel@tonic-gate { 3818*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ret; 3819*7c478bd9Sstevel@tonic-gate 3820*7c478bd9Sstevel@tonic-gate if (h == NULL) { 3821*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 3822*7c478bd9Sstevel@tonic-gate return (NULL); 3823*7c478bd9Sstevel@tonic-gate } 3824*7c478bd9Sstevel@tonic-gate 3825*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (scf_transaction_entry_t)); 3826*7c478bd9Sstevel@tonic-gate if (ret == NULL) { 3827*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3828*7c478bd9Sstevel@tonic-gate return (NULL); 3829*7c478bd9Sstevel@tonic-gate } 3830*7c478bd9Sstevel@tonic-gate ret->entry_action = REP_PROTOCOL_TX_ENTRY_INVALID; 3831*7c478bd9Sstevel@tonic-gate ret->entry_handle = h; 3832*7c478bd9Sstevel@tonic-gate 3833*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3834*7c478bd9Sstevel@tonic-gate if (h->rh_flags & HANDLE_DEAD) { 3835*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3836*7c478bd9Sstevel@tonic-gate uu_free(ret); 3837*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_HANDLE_DESTROYED); 3838*7c478bd9Sstevel@tonic-gate return (NULL); 3839*7c478bd9Sstevel@tonic-gate } 3840*7c478bd9Sstevel@tonic-gate h->rh_entries++; 3841*7c478bd9Sstevel@tonic-gate h->rh_extrefs++; 3842*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3843*7c478bd9Sstevel@tonic-gate 3844*7c478bd9Sstevel@tonic-gate uu_list_node_init(ret, &ret->entry_link, tran_entry_pool); 3845*7c478bd9Sstevel@tonic-gate 3846*7c478bd9Sstevel@tonic-gate return (ret); 3847*7c478bd9Sstevel@tonic-gate } 3848*7c478bd9Sstevel@tonic-gate 3849*7c478bd9Sstevel@tonic-gate scf_handle_t * 3850*7c478bd9Sstevel@tonic-gate scf_entry_handle(const scf_transaction_entry_t *val) 3851*7c478bd9Sstevel@tonic-gate { 3852*7c478bd9Sstevel@tonic-gate return (handle_get(val->entry_handle)); 3853*7c478bd9Sstevel@tonic-gate } 3854*7c478bd9Sstevel@tonic-gate 3855*7c478bd9Sstevel@tonic-gate void 3856*7c478bd9Sstevel@tonic-gate scf_entry_reset(scf_transaction_entry_t *entry) 3857*7c478bd9Sstevel@tonic-gate { 3858*7c478bd9Sstevel@tonic-gate scf_handle_t *h = entry->entry_handle; 3859*7c478bd9Sstevel@tonic-gate 3860*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3861*7c478bd9Sstevel@tonic-gate entry_invalidate(entry, 0, 0); 3862*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3863*7c478bd9Sstevel@tonic-gate } 3864*7c478bd9Sstevel@tonic-gate 3865*7c478bd9Sstevel@tonic-gate void 3866*7c478bd9Sstevel@tonic-gate scf_entry_destroy_children(scf_transaction_entry_t *entry) 3867*7c478bd9Sstevel@tonic-gate { 3868*7c478bd9Sstevel@tonic-gate scf_handle_t *h = entry->entry_handle; 3869*7c478bd9Sstevel@tonic-gate 3870*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3871*7c478bd9Sstevel@tonic-gate entry_invalidate(entry, 1, 0); 3872*7c478bd9Sstevel@tonic-gate handle_unrefed(h); /* drops h->rh_lock */ 3873*7c478bd9Sstevel@tonic-gate } 3874*7c478bd9Sstevel@tonic-gate 3875*7c478bd9Sstevel@tonic-gate void 3876*7c478bd9Sstevel@tonic-gate scf_entry_destroy(scf_transaction_entry_t *entry) 3877*7c478bd9Sstevel@tonic-gate { 3878*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 3879*7c478bd9Sstevel@tonic-gate 3880*7c478bd9Sstevel@tonic-gate if (entry == NULL) 3881*7c478bd9Sstevel@tonic-gate return; 3882*7c478bd9Sstevel@tonic-gate 3883*7c478bd9Sstevel@tonic-gate h = entry->entry_handle; 3884*7c478bd9Sstevel@tonic-gate 3885*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3886*7c478bd9Sstevel@tonic-gate entry_destroy_locked(entry); 3887*7c478bd9Sstevel@tonic-gate handle_unrefed(h); /* drops h->rh_lock */ 3888*7c478bd9Sstevel@tonic-gate } 3889*7c478bd9Sstevel@tonic-gate 3890*7c478bd9Sstevel@tonic-gate /* 3891*7c478bd9Sstevel@tonic-gate * Fails with 3892*7c478bd9Sstevel@tonic-gate * _HANDLE_MISMATCH 3893*7c478bd9Sstevel@tonic-gate * _NOT_SET - has not been added to a transaction 3894*7c478bd9Sstevel@tonic-gate * _INTERNAL - entry is corrupt 3895*7c478bd9Sstevel@tonic-gate * _INVALID_ARGUMENT - entry's transaction is not started or corrupt 3896*7c478bd9Sstevel@tonic-gate * entry is set to delete a property 3897*7c478bd9Sstevel@tonic-gate * v is reset or corrupt 3898*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - entry & v's types aren't compatible 3899*7c478bd9Sstevel@tonic-gate * _IN_USE - v has been added to another entry 3900*7c478bd9Sstevel@tonic-gate */ 3901*7c478bd9Sstevel@tonic-gate int 3902*7c478bd9Sstevel@tonic-gate scf_entry_add_value(scf_transaction_entry_t *entry, scf_value_t *v) 3903*7c478bd9Sstevel@tonic-gate { 3904*7c478bd9Sstevel@tonic-gate scf_handle_t *h = entry->entry_handle; 3905*7c478bd9Sstevel@tonic-gate 3906*7c478bd9Sstevel@tonic-gate if (h != v->value_handle) 3907*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 3908*7c478bd9Sstevel@tonic-gate 3909*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3910*7c478bd9Sstevel@tonic-gate 3911*7c478bd9Sstevel@tonic-gate if (entry->entry_state == ENTRY_STATE_INVALID) { 3912*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3913*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 3914*7c478bd9Sstevel@tonic-gate } 3915*7c478bd9Sstevel@tonic-gate assert(entry->entry_state == ENTRY_STATE_IN_TX_ACTION); 3916*7c478bd9Sstevel@tonic-gate 3917*7c478bd9Sstevel@tonic-gate if (entry->entry_tx->tran_state != TRAN_STATE_SETUP) { 3918*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3919*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3920*7c478bd9Sstevel@tonic-gate } 3921*7c478bd9Sstevel@tonic-gate 3922*7c478bd9Sstevel@tonic-gate if (entry->entry_action == REP_PROTOCOL_TX_ENTRY_DELETE) { 3923*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3924*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3925*7c478bd9Sstevel@tonic-gate } 3926*7c478bd9Sstevel@tonic-gate 3927*7c478bd9Sstevel@tonic-gate if (v->value_type == REP_PROTOCOL_TYPE_INVALID) { 3928*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3929*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 3930*7c478bd9Sstevel@tonic-gate } 3931*7c478bd9Sstevel@tonic-gate 3932*7c478bd9Sstevel@tonic-gate if (!scf_is_compatible_type(entry->entry_type, v->value_type)) { 3933*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3934*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_TYPE_MISMATCH)); 3935*7c478bd9Sstevel@tonic-gate } 3936*7c478bd9Sstevel@tonic-gate 3937*7c478bd9Sstevel@tonic-gate if (v->value_tx != NULL) { 3938*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3939*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_IN_USE)); 3940*7c478bd9Sstevel@tonic-gate } 3941*7c478bd9Sstevel@tonic-gate 3942*7c478bd9Sstevel@tonic-gate v->value_tx = entry; 3943*7c478bd9Sstevel@tonic-gate v->value_next = entry->entry_head; 3944*7c478bd9Sstevel@tonic-gate entry->entry_head = v; 3945*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3946*7c478bd9Sstevel@tonic-gate 3947*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 3948*7c478bd9Sstevel@tonic-gate } 3949*7c478bd9Sstevel@tonic-gate 3950*7c478bd9Sstevel@tonic-gate /* 3951*7c478bd9Sstevel@tonic-gate * value functions 3952*7c478bd9Sstevel@tonic-gate */ 3953*7c478bd9Sstevel@tonic-gate scf_value_t * 3954*7c478bd9Sstevel@tonic-gate scf_value_create(scf_handle_t *h) 3955*7c478bd9Sstevel@tonic-gate { 3956*7c478bd9Sstevel@tonic-gate scf_value_t *ret; 3957*7c478bd9Sstevel@tonic-gate 3958*7c478bd9Sstevel@tonic-gate if (h == NULL) { 3959*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 3960*7c478bd9Sstevel@tonic-gate return (NULL); 3961*7c478bd9Sstevel@tonic-gate } 3962*7c478bd9Sstevel@tonic-gate 3963*7c478bd9Sstevel@tonic-gate ret = uu_zalloc(sizeof (*ret)); 3964*7c478bd9Sstevel@tonic-gate if (ret != NULL) { 3965*7c478bd9Sstevel@tonic-gate ret->value_type = REP_PROTOCOL_TYPE_INVALID; 3966*7c478bd9Sstevel@tonic-gate ret->value_handle = h; 3967*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 3968*7c478bd9Sstevel@tonic-gate if (h->rh_flags & HANDLE_DEAD) { 3969*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3970*7c478bd9Sstevel@tonic-gate uu_free(ret); 3971*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 3972*7c478bd9Sstevel@tonic-gate return (NULL); 3973*7c478bd9Sstevel@tonic-gate } 3974*7c478bd9Sstevel@tonic-gate h->rh_values++; 3975*7c478bd9Sstevel@tonic-gate h->rh_extrefs++; 3976*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 3977*7c478bd9Sstevel@tonic-gate } else { 3978*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NO_MEMORY); 3979*7c478bd9Sstevel@tonic-gate } 3980*7c478bd9Sstevel@tonic-gate 3981*7c478bd9Sstevel@tonic-gate return (ret); 3982*7c478bd9Sstevel@tonic-gate } 3983*7c478bd9Sstevel@tonic-gate 3984*7c478bd9Sstevel@tonic-gate static void 3985*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(scf_value_t *val, int and_destroy) 3986*7c478bd9Sstevel@tonic-gate { 3987*7c478bd9Sstevel@tonic-gate scf_value_t **curp; 3988*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *te; 3989*7c478bd9Sstevel@tonic-gate 3990*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 3991*7c478bd9Sstevel@tonic-gate assert(MUTEX_HELD(&h->rh_lock)); 3992*7c478bd9Sstevel@tonic-gate if (val->value_tx != NULL) { 3993*7c478bd9Sstevel@tonic-gate te = val->value_tx; 3994*7c478bd9Sstevel@tonic-gate te->entry_tx->tran_invalid = 1; 3995*7c478bd9Sstevel@tonic-gate 3996*7c478bd9Sstevel@tonic-gate val->value_tx = NULL; 3997*7c478bd9Sstevel@tonic-gate 3998*7c478bd9Sstevel@tonic-gate for (curp = &te->entry_head; *curp != NULL; 3999*7c478bd9Sstevel@tonic-gate curp = &(*curp)->value_next) { 4000*7c478bd9Sstevel@tonic-gate if (*curp == val) { 4001*7c478bd9Sstevel@tonic-gate *curp = val->value_next; 4002*7c478bd9Sstevel@tonic-gate curp = NULL; 4003*7c478bd9Sstevel@tonic-gate break; 4004*7c478bd9Sstevel@tonic-gate } 4005*7c478bd9Sstevel@tonic-gate } 4006*7c478bd9Sstevel@tonic-gate assert(curp == NULL); 4007*7c478bd9Sstevel@tonic-gate } 4008*7c478bd9Sstevel@tonic-gate val->value_type = REP_PROTOCOL_TYPE_INVALID; 4009*7c478bd9Sstevel@tonic-gate 4010*7c478bd9Sstevel@tonic-gate if (and_destroy) { 4011*7c478bd9Sstevel@tonic-gate val->value_handle = NULL; 4012*7c478bd9Sstevel@tonic-gate assert(h->rh_values > 0); 4013*7c478bd9Sstevel@tonic-gate --h->rh_values; 4014*7c478bd9Sstevel@tonic-gate --h->rh_extrefs; 4015*7c478bd9Sstevel@tonic-gate uu_free(val); 4016*7c478bd9Sstevel@tonic-gate } 4017*7c478bd9Sstevel@tonic-gate } 4018*7c478bd9Sstevel@tonic-gate 4019*7c478bd9Sstevel@tonic-gate void 4020*7c478bd9Sstevel@tonic-gate scf_value_reset(scf_value_t *val) 4021*7c478bd9Sstevel@tonic-gate { 4022*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4023*7c478bd9Sstevel@tonic-gate 4024*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4025*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(val, 0); 4026*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4027*7c478bd9Sstevel@tonic-gate } 4028*7c478bd9Sstevel@tonic-gate 4029*7c478bd9Sstevel@tonic-gate scf_handle_t * 4030*7c478bd9Sstevel@tonic-gate scf_value_handle(const scf_value_t *val) 4031*7c478bd9Sstevel@tonic-gate { 4032*7c478bd9Sstevel@tonic-gate return (handle_get(val->value_handle)); 4033*7c478bd9Sstevel@tonic-gate } 4034*7c478bd9Sstevel@tonic-gate 4035*7c478bd9Sstevel@tonic-gate void 4036*7c478bd9Sstevel@tonic-gate scf_value_destroy(scf_value_t *val) 4037*7c478bd9Sstevel@tonic-gate { 4038*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 4039*7c478bd9Sstevel@tonic-gate 4040*7c478bd9Sstevel@tonic-gate if (val == NULL) 4041*7c478bd9Sstevel@tonic-gate return; 4042*7c478bd9Sstevel@tonic-gate 4043*7c478bd9Sstevel@tonic-gate h = val->value_handle; 4044*7c478bd9Sstevel@tonic-gate 4045*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4046*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(val, 1); 4047*7c478bd9Sstevel@tonic-gate handle_unrefed(h); /* drops h->rh_lock */ 4048*7c478bd9Sstevel@tonic-gate } 4049*7c478bd9Sstevel@tonic-gate 4050*7c478bd9Sstevel@tonic-gate scf_type_t 4051*7c478bd9Sstevel@tonic-gate scf_value_base_type(const scf_value_t *val) 4052*7c478bd9Sstevel@tonic-gate { 4053*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t t, cur; 4054*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4055*7c478bd9Sstevel@tonic-gate 4056*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4057*7c478bd9Sstevel@tonic-gate t = val->value_type; 4058*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4059*7c478bd9Sstevel@tonic-gate 4060*7c478bd9Sstevel@tonic-gate for (;;) { 4061*7c478bd9Sstevel@tonic-gate cur = scf_proto_underlying_type(t); 4062*7c478bd9Sstevel@tonic-gate if (cur == t) 4063*7c478bd9Sstevel@tonic-gate break; 4064*7c478bd9Sstevel@tonic-gate t = cur; 4065*7c478bd9Sstevel@tonic-gate } 4066*7c478bd9Sstevel@tonic-gate 4067*7c478bd9Sstevel@tonic-gate return (scf_protocol_type_to_type(t)); 4068*7c478bd9Sstevel@tonic-gate } 4069*7c478bd9Sstevel@tonic-gate 4070*7c478bd9Sstevel@tonic-gate scf_type_t 4071*7c478bd9Sstevel@tonic-gate scf_value_type(const scf_value_t *val) 4072*7c478bd9Sstevel@tonic-gate { 4073*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t t; 4074*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4075*7c478bd9Sstevel@tonic-gate 4076*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4077*7c478bd9Sstevel@tonic-gate t = val->value_type; 4078*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4079*7c478bd9Sstevel@tonic-gate 4080*7c478bd9Sstevel@tonic-gate return (scf_protocol_type_to_type(t)); 4081*7c478bd9Sstevel@tonic-gate } 4082*7c478bd9Sstevel@tonic-gate 4083*7c478bd9Sstevel@tonic-gate int 4084*7c478bd9Sstevel@tonic-gate scf_value_is_type(const scf_value_t *val, scf_type_t base_arg) 4085*7c478bd9Sstevel@tonic-gate { 4086*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t t; 4087*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t base = scf_type_to_protocol_type(base_arg); 4088*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4089*7c478bd9Sstevel@tonic-gate 4090*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4091*7c478bd9Sstevel@tonic-gate t = val->value_type; 4092*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4093*7c478bd9Sstevel@tonic-gate 4094*7c478bd9Sstevel@tonic-gate if (t == REP_PROTOCOL_TYPE_INVALID) 4095*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 4096*7c478bd9Sstevel@tonic-gate if (base == REP_PROTOCOL_TYPE_INVALID) 4097*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4098*7c478bd9Sstevel@tonic-gate if (!scf_is_compatible_type(base, t)) 4099*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_TYPE_MISMATCH)); 4100*7c478bd9Sstevel@tonic-gate 4101*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 4102*7c478bd9Sstevel@tonic-gate } 4103*7c478bd9Sstevel@tonic-gate 4104*7c478bd9Sstevel@tonic-gate /* 4105*7c478bd9Sstevel@tonic-gate * Fails with 4106*7c478bd9Sstevel@tonic-gate * _NOT_SET - val is reset 4107*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - val's type is not compatible with t 4108*7c478bd9Sstevel@tonic-gate */ 4109*7c478bd9Sstevel@tonic-gate static int 4110*7c478bd9Sstevel@tonic-gate scf_value_check_type(const scf_value_t *val, rep_protocol_value_type_t t) 4111*7c478bd9Sstevel@tonic-gate { 4112*7c478bd9Sstevel@tonic-gate if (val->value_type == REP_PROTOCOL_TYPE_INVALID) { 4113*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NOT_SET); 4114*7c478bd9Sstevel@tonic-gate return (0); 4115*7c478bd9Sstevel@tonic-gate } 4116*7c478bd9Sstevel@tonic-gate if (!scf_is_compatible_type(t, val->value_type)) { 4117*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_TYPE_MISMATCH); 4118*7c478bd9Sstevel@tonic-gate return (0); 4119*7c478bd9Sstevel@tonic-gate } 4120*7c478bd9Sstevel@tonic-gate return (1); 4121*7c478bd9Sstevel@tonic-gate } 4122*7c478bd9Sstevel@tonic-gate 4123*7c478bd9Sstevel@tonic-gate /* 4124*7c478bd9Sstevel@tonic-gate * Fails with 4125*7c478bd9Sstevel@tonic-gate * _NOT_SET - val is reset 4126*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - val is not _TYPE_BOOLEAN 4127*7c478bd9Sstevel@tonic-gate */ 4128*7c478bd9Sstevel@tonic-gate int 4129*7c478bd9Sstevel@tonic-gate scf_value_get_boolean(const scf_value_t *val, uint8_t *out) 4130*7c478bd9Sstevel@tonic-gate { 4131*7c478bd9Sstevel@tonic-gate char c; 4132*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4133*7c478bd9Sstevel@tonic-gate uint8_t o; 4134*7c478bd9Sstevel@tonic-gate 4135*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4136*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(val, REP_PROTOCOL_TYPE_BOOLEAN)) { 4137*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4138*7c478bd9Sstevel@tonic-gate return (-1); 4139*7c478bd9Sstevel@tonic-gate } 4140*7c478bd9Sstevel@tonic-gate 4141*7c478bd9Sstevel@tonic-gate c = val->value_value[0]; 4142*7c478bd9Sstevel@tonic-gate assert((c == '0' || c == '1') && val->value_value[1] == 0); 4143*7c478bd9Sstevel@tonic-gate 4144*7c478bd9Sstevel@tonic-gate o = (c != '0'); 4145*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4146*7c478bd9Sstevel@tonic-gate if (out != NULL) 4147*7c478bd9Sstevel@tonic-gate *out = o; 4148*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 4149*7c478bd9Sstevel@tonic-gate } 4150*7c478bd9Sstevel@tonic-gate 4151*7c478bd9Sstevel@tonic-gate int 4152*7c478bd9Sstevel@tonic-gate scf_value_get_count(const scf_value_t *val, uint64_t *out) 4153*7c478bd9Sstevel@tonic-gate { 4154*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4155*7c478bd9Sstevel@tonic-gate uint64_t o; 4156*7c478bd9Sstevel@tonic-gate 4157*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4158*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(val, REP_PROTOCOL_TYPE_COUNT)) { 4159*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4160*7c478bd9Sstevel@tonic-gate return (-1); 4161*7c478bd9Sstevel@tonic-gate } 4162*7c478bd9Sstevel@tonic-gate 4163*7c478bd9Sstevel@tonic-gate o = strtoull(val->value_value, NULL, 10); 4164*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4165*7c478bd9Sstevel@tonic-gate if (out != NULL) 4166*7c478bd9Sstevel@tonic-gate *out = o; 4167*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 4168*7c478bd9Sstevel@tonic-gate } 4169*7c478bd9Sstevel@tonic-gate 4170*7c478bd9Sstevel@tonic-gate int 4171*7c478bd9Sstevel@tonic-gate scf_value_get_integer(const scf_value_t *val, int64_t *out) 4172*7c478bd9Sstevel@tonic-gate { 4173*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4174*7c478bd9Sstevel@tonic-gate int64_t o; 4175*7c478bd9Sstevel@tonic-gate 4176*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4177*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(val, REP_PROTOCOL_TYPE_INTEGER)) { 4178*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4179*7c478bd9Sstevel@tonic-gate return (-1); 4180*7c478bd9Sstevel@tonic-gate } 4181*7c478bd9Sstevel@tonic-gate 4182*7c478bd9Sstevel@tonic-gate o = strtoll(val->value_value, NULL, 10); 4183*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4184*7c478bd9Sstevel@tonic-gate if (out != NULL) 4185*7c478bd9Sstevel@tonic-gate *out = o; 4186*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 4187*7c478bd9Sstevel@tonic-gate } 4188*7c478bd9Sstevel@tonic-gate 4189*7c478bd9Sstevel@tonic-gate int 4190*7c478bd9Sstevel@tonic-gate scf_value_get_time(const scf_value_t *val, int64_t *sec_out, int32_t *nsec_out) 4191*7c478bd9Sstevel@tonic-gate { 4192*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4193*7c478bd9Sstevel@tonic-gate char *p; 4194*7c478bd9Sstevel@tonic-gate int64_t os; 4195*7c478bd9Sstevel@tonic-gate int32_t ons; 4196*7c478bd9Sstevel@tonic-gate 4197*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4198*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(val, REP_PROTOCOL_TYPE_TIME)) { 4199*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4200*7c478bd9Sstevel@tonic-gate return (-1); 4201*7c478bd9Sstevel@tonic-gate } 4202*7c478bd9Sstevel@tonic-gate 4203*7c478bd9Sstevel@tonic-gate os = strtoll(val->value_value, &p, 10); 4204*7c478bd9Sstevel@tonic-gate if (*p == '.') 4205*7c478bd9Sstevel@tonic-gate ons = strtoul(p + 1, NULL, 10); 4206*7c478bd9Sstevel@tonic-gate else 4207*7c478bd9Sstevel@tonic-gate ons = 0; 4208*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4209*7c478bd9Sstevel@tonic-gate if (sec_out != NULL) 4210*7c478bd9Sstevel@tonic-gate *sec_out = os; 4211*7c478bd9Sstevel@tonic-gate if (nsec_out != NULL) 4212*7c478bd9Sstevel@tonic-gate *nsec_out = ons; 4213*7c478bd9Sstevel@tonic-gate 4214*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 4215*7c478bd9Sstevel@tonic-gate } 4216*7c478bd9Sstevel@tonic-gate 4217*7c478bd9Sstevel@tonic-gate /* 4218*7c478bd9Sstevel@tonic-gate * Fails with 4219*7c478bd9Sstevel@tonic-gate * _NOT_SET - val is reset 4220*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - val's type is not compatible with _TYPE_STRING. 4221*7c478bd9Sstevel@tonic-gate */ 4222*7c478bd9Sstevel@tonic-gate ssize_t 4223*7c478bd9Sstevel@tonic-gate scf_value_get_astring(const scf_value_t *val, char *out, size_t len) 4224*7c478bd9Sstevel@tonic-gate { 4225*7c478bd9Sstevel@tonic-gate ssize_t ret; 4226*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4227*7c478bd9Sstevel@tonic-gate 4228*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4229*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(val, REP_PROTOCOL_TYPE_STRING)) { 4230*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4231*7c478bd9Sstevel@tonic-gate return ((ssize_t)-1); 4232*7c478bd9Sstevel@tonic-gate } 4233*7c478bd9Sstevel@tonic-gate ret = (ssize_t)strlcpy(out, val->value_value, len); 4234*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4235*7c478bd9Sstevel@tonic-gate return (ret); 4236*7c478bd9Sstevel@tonic-gate } 4237*7c478bd9Sstevel@tonic-gate 4238*7c478bd9Sstevel@tonic-gate ssize_t 4239*7c478bd9Sstevel@tonic-gate scf_value_get_ustring(const scf_value_t *val, char *out, size_t len) 4240*7c478bd9Sstevel@tonic-gate { 4241*7c478bd9Sstevel@tonic-gate ssize_t ret; 4242*7c478bd9Sstevel@tonic-gate scf_handle_t *h = val->value_handle; 4243*7c478bd9Sstevel@tonic-gate 4244*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4245*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(val, REP_PROTOCOL_SUBTYPE_USTRING)) { 4246*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4247*7c478bd9Sstevel@tonic-gate return ((ssize_t)-1); 4248*7c478bd9Sstevel@tonic-gate } 4249*7c478bd9Sstevel@tonic-gate ret = (ssize_t)strlcpy(out, val->value_value, len); 4250*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4251*7c478bd9Sstevel@tonic-gate return (ret); 4252*7c478bd9Sstevel@tonic-gate } 4253*7c478bd9Sstevel@tonic-gate 4254*7c478bd9Sstevel@tonic-gate ssize_t 4255*7c478bd9Sstevel@tonic-gate scf_value_get_opaque(const scf_value_t *v, void *out, size_t len) 4256*7c478bd9Sstevel@tonic-gate { 4257*7c478bd9Sstevel@tonic-gate ssize_t ret; 4258*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4259*7c478bd9Sstevel@tonic-gate 4260*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4261*7c478bd9Sstevel@tonic-gate if (!scf_value_check_type(v, REP_PROTOCOL_TYPE_OPAQUE)) { 4262*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4263*7c478bd9Sstevel@tonic-gate return ((ssize_t)-1); 4264*7c478bd9Sstevel@tonic-gate } 4265*7c478bd9Sstevel@tonic-gate if (len > v->value_size) 4266*7c478bd9Sstevel@tonic-gate len = v->value_size; 4267*7c478bd9Sstevel@tonic-gate ret = len; 4268*7c478bd9Sstevel@tonic-gate 4269*7c478bd9Sstevel@tonic-gate (void) memcpy(out, v->value_value, len); 4270*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4271*7c478bd9Sstevel@tonic-gate return (ret); 4272*7c478bd9Sstevel@tonic-gate } 4273*7c478bd9Sstevel@tonic-gate 4274*7c478bd9Sstevel@tonic-gate void 4275*7c478bd9Sstevel@tonic-gate scf_value_set_boolean(scf_value_t *v, uint8_t new) 4276*7c478bd9Sstevel@tonic-gate { 4277*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4278*7c478bd9Sstevel@tonic-gate 4279*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4280*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4281*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_TYPE_BOOLEAN; 4282*7c478bd9Sstevel@tonic-gate (void) sprintf(v->value_value, "%d", (new != 0)); 4283*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4284*7c478bd9Sstevel@tonic-gate } 4285*7c478bd9Sstevel@tonic-gate 4286*7c478bd9Sstevel@tonic-gate void 4287*7c478bd9Sstevel@tonic-gate scf_value_set_count(scf_value_t *v, uint64_t new) 4288*7c478bd9Sstevel@tonic-gate { 4289*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4290*7c478bd9Sstevel@tonic-gate 4291*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4292*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4293*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_TYPE_COUNT; 4294*7c478bd9Sstevel@tonic-gate (void) sprintf(v->value_value, "%llu", (unsigned long long)new); 4295*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4296*7c478bd9Sstevel@tonic-gate } 4297*7c478bd9Sstevel@tonic-gate 4298*7c478bd9Sstevel@tonic-gate void 4299*7c478bd9Sstevel@tonic-gate scf_value_set_integer(scf_value_t *v, int64_t new) 4300*7c478bd9Sstevel@tonic-gate { 4301*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4302*7c478bd9Sstevel@tonic-gate 4303*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4304*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4305*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_TYPE_INTEGER; 4306*7c478bd9Sstevel@tonic-gate (void) sprintf(v->value_value, "%lld", (long long)new); 4307*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4308*7c478bd9Sstevel@tonic-gate } 4309*7c478bd9Sstevel@tonic-gate 4310*7c478bd9Sstevel@tonic-gate int 4311*7c478bd9Sstevel@tonic-gate scf_value_set_time(scf_value_t *v, int64_t new_sec, int32_t new_nsec) 4312*7c478bd9Sstevel@tonic-gate { 4313*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4314*7c478bd9Sstevel@tonic-gate 4315*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4316*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4317*7c478bd9Sstevel@tonic-gate if (new_nsec < 0 || new_nsec >= NANOSEC) { 4318*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4319*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4320*7c478bd9Sstevel@tonic-gate } 4321*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_TYPE_TIME; 4322*7c478bd9Sstevel@tonic-gate if (new_nsec == 0) 4323*7c478bd9Sstevel@tonic-gate (void) sprintf(v->value_value, "%lld", (long long)new_sec); 4324*7c478bd9Sstevel@tonic-gate else 4325*7c478bd9Sstevel@tonic-gate (void) sprintf(v->value_value, "%lld.%09u", (long long)new_sec, 4326*7c478bd9Sstevel@tonic-gate (unsigned)new_nsec); 4327*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4328*7c478bd9Sstevel@tonic-gate return (0); 4329*7c478bd9Sstevel@tonic-gate } 4330*7c478bd9Sstevel@tonic-gate 4331*7c478bd9Sstevel@tonic-gate int 4332*7c478bd9Sstevel@tonic-gate scf_value_set_astring(scf_value_t *v, const char *new) 4333*7c478bd9Sstevel@tonic-gate { 4334*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4335*7c478bd9Sstevel@tonic-gate 4336*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4337*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4338*7c478bd9Sstevel@tonic-gate if (!scf_validate_encoded_value(REP_PROTOCOL_TYPE_STRING, new)) { 4339*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4340*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4341*7c478bd9Sstevel@tonic-gate } 4342*7c478bd9Sstevel@tonic-gate if (strlcpy(v->value_value, new, sizeof (v->value_value)) >= 4343*7c478bd9Sstevel@tonic-gate sizeof (v->value_value)) { 4344*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4345*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4346*7c478bd9Sstevel@tonic-gate } 4347*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_TYPE_STRING; 4348*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4349*7c478bd9Sstevel@tonic-gate return (0); 4350*7c478bd9Sstevel@tonic-gate } 4351*7c478bd9Sstevel@tonic-gate 4352*7c478bd9Sstevel@tonic-gate int 4353*7c478bd9Sstevel@tonic-gate scf_value_set_ustring(scf_value_t *v, const char *new) 4354*7c478bd9Sstevel@tonic-gate { 4355*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4356*7c478bd9Sstevel@tonic-gate 4357*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4358*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4359*7c478bd9Sstevel@tonic-gate if (!scf_validate_encoded_value(REP_PROTOCOL_SUBTYPE_USTRING, new)) { 4360*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4361*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4362*7c478bd9Sstevel@tonic-gate } 4363*7c478bd9Sstevel@tonic-gate if (strlcpy(v->value_value, new, sizeof (v->value_value)) >= 4364*7c478bd9Sstevel@tonic-gate sizeof (v->value_value)) { 4365*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4366*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4367*7c478bd9Sstevel@tonic-gate } 4368*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_SUBTYPE_USTRING; 4369*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4370*7c478bd9Sstevel@tonic-gate return (0); 4371*7c478bd9Sstevel@tonic-gate } 4372*7c478bd9Sstevel@tonic-gate 4373*7c478bd9Sstevel@tonic-gate int 4374*7c478bd9Sstevel@tonic-gate scf_value_set_opaque(scf_value_t *v, const void *new, size_t len) 4375*7c478bd9Sstevel@tonic-gate { 4376*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4377*7c478bd9Sstevel@tonic-gate 4378*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4379*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4380*7c478bd9Sstevel@tonic-gate if (len > sizeof (v->value_value)) { 4381*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4382*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4383*7c478bd9Sstevel@tonic-gate } 4384*7c478bd9Sstevel@tonic-gate (void) memcpy(v->value_value, new, len); 4385*7c478bd9Sstevel@tonic-gate v->value_size = len; 4386*7c478bd9Sstevel@tonic-gate v->value_type = REP_PROTOCOL_TYPE_OPAQUE; 4387*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4388*7c478bd9Sstevel@tonic-gate return (0); 4389*7c478bd9Sstevel@tonic-gate } 4390*7c478bd9Sstevel@tonic-gate 4391*7c478bd9Sstevel@tonic-gate /* 4392*7c478bd9Sstevel@tonic-gate * Fails with 4393*7c478bd9Sstevel@tonic-gate * _NOT_SET - v_arg is reset 4394*7c478bd9Sstevel@tonic-gate * _INTERNAL - v_arg is corrupt 4395*7c478bd9Sstevel@tonic-gate * 4396*7c478bd9Sstevel@tonic-gate * If t is not _TYPE_INVALID, fails with 4397*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - v_arg's type is not compatible with t 4398*7c478bd9Sstevel@tonic-gate */ 4399*7c478bd9Sstevel@tonic-gate static ssize_t 4400*7c478bd9Sstevel@tonic-gate scf_value_get_as_string_common(const scf_value_t *v_arg, 4401*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t t, char *buf, size_t bufsz) 4402*7c478bd9Sstevel@tonic-gate { 4403*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v_arg->value_handle; 4404*7c478bd9Sstevel@tonic-gate scf_value_t v_s; 4405*7c478bd9Sstevel@tonic-gate scf_value_t *v = &v_s; 4406*7c478bd9Sstevel@tonic-gate ssize_t r; 4407*7c478bd9Sstevel@tonic-gate uint8_t b; 4408*7c478bd9Sstevel@tonic-gate 4409*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4410*7c478bd9Sstevel@tonic-gate if (t != REP_PROTOCOL_TYPE_INVALID && !scf_value_check_type(v_arg, t)) { 4411*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4412*7c478bd9Sstevel@tonic-gate return (-1); 4413*7c478bd9Sstevel@tonic-gate } 4414*7c478bd9Sstevel@tonic-gate 4415*7c478bd9Sstevel@tonic-gate v_s = *v_arg; /* copy locally so we can unlock */ 4416*7c478bd9Sstevel@tonic-gate h->rh_values++; /* keep the handle from going away */ 4417*7c478bd9Sstevel@tonic-gate h->rh_extrefs++; 4418*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4419*7c478bd9Sstevel@tonic-gate 4420*7c478bd9Sstevel@tonic-gate 4421*7c478bd9Sstevel@tonic-gate switch (REP_PROTOCOL_BASE_TYPE(v->value_type)) { 4422*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_BOOLEAN: 4423*7c478bd9Sstevel@tonic-gate r = scf_value_get_boolean(v, &b); 4424*7c478bd9Sstevel@tonic-gate assert(r == SCF_SUCCESS); 4425*7c478bd9Sstevel@tonic-gate 4426*7c478bd9Sstevel@tonic-gate r = strlcpy(buf, b ? "true" : "false", bufsz); 4427*7c478bd9Sstevel@tonic-gate break; 4428*7c478bd9Sstevel@tonic-gate 4429*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_COUNT: 4430*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_INTEGER: 4431*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_TIME: 4432*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_STRING: 4433*7c478bd9Sstevel@tonic-gate r = strlcpy(buf, v->value_value, bufsz); 4434*7c478bd9Sstevel@tonic-gate break; 4435*7c478bd9Sstevel@tonic-gate 4436*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_OPAQUE: 4437*7c478bd9Sstevel@tonic-gate /* 4438*7c478bd9Sstevel@tonic-gate * Note that we only write out full hex bytes -- if they're 4439*7c478bd9Sstevel@tonic-gate * short, and bufsz is even, we'll only fill (bufsz - 2) bytes 4440*7c478bd9Sstevel@tonic-gate * with data. 4441*7c478bd9Sstevel@tonic-gate */ 4442*7c478bd9Sstevel@tonic-gate if (bufsz > 0) 4443*7c478bd9Sstevel@tonic-gate (void) scf_opaque_encode(buf, v->value_value, 4444*7c478bd9Sstevel@tonic-gate MIN(v->value_size, (bufsz - 1)/2)); 4445*7c478bd9Sstevel@tonic-gate r = (v->value_size * 2); 4446*7c478bd9Sstevel@tonic-gate break; 4447*7c478bd9Sstevel@tonic-gate 4448*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_INVALID: 4449*7c478bd9Sstevel@tonic-gate r = scf_set_error(SCF_ERROR_NOT_SET); 4450*7c478bd9Sstevel@tonic-gate break; 4451*7c478bd9Sstevel@tonic-gate 4452*7c478bd9Sstevel@tonic-gate default: 4453*7c478bd9Sstevel@tonic-gate r = (scf_set_error(SCF_ERROR_INTERNAL)); 4454*7c478bd9Sstevel@tonic-gate break; 4455*7c478bd9Sstevel@tonic-gate } 4456*7c478bd9Sstevel@tonic-gate 4457*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4458*7c478bd9Sstevel@tonic-gate h->rh_values--; 4459*7c478bd9Sstevel@tonic-gate h->rh_extrefs--; 4460*7c478bd9Sstevel@tonic-gate handle_unrefed(h); 4461*7c478bd9Sstevel@tonic-gate 4462*7c478bd9Sstevel@tonic-gate return (r); 4463*7c478bd9Sstevel@tonic-gate } 4464*7c478bd9Sstevel@tonic-gate 4465*7c478bd9Sstevel@tonic-gate ssize_t 4466*7c478bd9Sstevel@tonic-gate scf_value_get_as_string(const scf_value_t *v, char *buf, size_t bufsz) 4467*7c478bd9Sstevel@tonic-gate { 4468*7c478bd9Sstevel@tonic-gate return (scf_value_get_as_string_common(v, REP_PROTOCOL_TYPE_INVALID, 4469*7c478bd9Sstevel@tonic-gate buf, bufsz)); 4470*7c478bd9Sstevel@tonic-gate } 4471*7c478bd9Sstevel@tonic-gate 4472*7c478bd9Sstevel@tonic-gate ssize_t 4473*7c478bd9Sstevel@tonic-gate scf_value_get_as_string_typed(const scf_value_t *v, scf_type_t type, 4474*7c478bd9Sstevel@tonic-gate char *buf, size_t bufsz) 4475*7c478bd9Sstevel@tonic-gate { 4476*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t ty = scf_type_to_protocol_type(type); 4477*7c478bd9Sstevel@tonic-gate if (ty == REP_PROTOCOL_TYPE_INVALID) 4478*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4479*7c478bd9Sstevel@tonic-gate 4480*7c478bd9Sstevel@tonic-gate return (scf_value_get_as_string_common(v, ty, buf, bufsz)); 4481*7c478bd9Sstevel@tonic-gate } 4482*7c478bd9Sstevel@tonic-gate 4483*7c478bd9Sstevel@tonic-gate int 4484*7c478bd9Sstevel@tonic-gate scf_value_set_from_string(scf_value_t *v, scf_type_t type, const char *str) 4485*7c478bd9Sstevel@tonic-gate { 4486*7c478bd9Sstevel@tonic-gate scf_handle_t *h = v->value_handle; 4487*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t ty; 4488*7c478bd9Sstevel@tonic-gate 4489*7c478bd9Sstevel@tonic-gate switch (type) { 4490*7c478bd9Sstevel@tonic-gate case SCF_TYPE_BOOLEAN: { 4491*7c478bd9Sstevel@tonic-gate uint8_t b; 4492*7c478bd9Sstevel@tonic-gate 4493*7c478bd9Sstevel@tonic-gate if (strcmp(str, "true") == 0 || strcmp(str, "t") == 0 || 4494*7c478bd9Sstevel@tonic-gate strcmp(str, "1") == 0) 4495*7c478bd9Sstevel@tonic-gate b = 1; 4496*7c478bd9Sstevel@tonic-gate else if (strcmp(str, "false") == 0 || 4497*7c478bd9Sstevel@tonic-gate strcmp(str, "f") == 0 || strcmp(str, "0") == 0) 4498*7c478bd9Sstevel@tonic-gate b = 0; 4499*7c478bd9Sstevel@tonic-gate else { 4500*7c478bd9Sstevel@tonic-gate goto bad; 4501*7c478bd9Sstevel@tonic-gate } 4502*7c478bd9Sstevel@tonic-gate 4503*7c478bd9Sstevel@tonic-gate scf_value_set_boolean(v, b); 4504*7c478bd9Sstevel@tonic-gate return (0); 4505*7c478bd9Sstevel@tonic-gate } 4506*7c478bd9Sstevel@tonic-gate 4507*7c478bd9Sstevel@tonic-gate case SCF_TYPE_COUNT: { 4508*7c478bd9Sstevel@tonic-gate uint64_t c; 4509*7c478bd9Sstevel@tonic-gate char *endp; 4510*7c478bd9Sstevel@tonic-gate 4511*7c478bd9Sstevel@tonic-gate errno = 0; 4512*7c478bd9Sstevel@tonic-gate c = strtoul(str, &endp, 0); 4513*7c478bd9Sstevel@tonic-gate 4514*7c478bd9Sstevel@tonic-gate if (errno != 0 || endp == str || *endp != '\0') 4515*7c478bd9Sstevel@tonic-gate goto bad; 4516*7c478bd9Sstevel@tonic-gate 4517*7c478bd9Sstevel@tonic-gate scf_value_set_count(v, c); 4518*7c478bd9Sstevel@tonic-gate return (0); 4519*7c478bd9Sstevel@tonic-gate } 4520*7c478bd9Sstevel@tonic-gate 4521*7c478bd9Sstevel@tonic-gate case SCF_TYPE_INTEGER: { 4522*7c478bd9Sstevel@tonic-gate int64_t i; 4523*7c478bd9Sstevel@tonic-gate char *endp; 4524*7c478bd9Sstevel@tonic-gate 4525*7c478bd9Sstevel@tonic-gate errno = 0; 4526*7c478bd9Sstevel@tonic-gate i = strtol(str, &endp, 0); 4527*7c478bd9Sstevel@tonic-gate 4528*7c478bd9Sstevel@tonic-gate if (errno != 0 || endp == str || *endp != '\0') 4529*7c478bd9Sstevel@tonic-gate goto bad; 4530*7c478bd9Sstevel@tonic-gate 4531*7c478bd9Sstevel@tonic-gate scf_value_set_integer(v, i); 4532*7c478bd9Sstevel@tonic-gate return (0); 4533*7c478bd9Sstevel@tonic-gate } 4534*7c478bd9Sstevel@tonic-gate 4535*7c478bd9Sstevel@tonic-gate case SCF_TYPE_TIME: { 4536*7c478bd9Sstevel@tonic-gate int64_t s; 4537*7c478bd9Sstevel@tonic-gate uint32_t ns = 0; 4538*7c478bd9Sstevel@tonic-gate char *endp, *ns_str; 4539*7c478bd9Sstevel@tonic-gate size_t len; 4540*7c478bd9Sstevel@tonic-gate 4541*7c478bd9Sstevel@tonic-gate errno = 0; 4542*7c478bd9Sstevel@tonic-gate s = strtoll(str, &endp, 10); 4543*7c478bd9Sstevel@tonic-gate if (errno != 0 || endp == str || 4544*7c478bd9Sstevel@tonic-gate (*endp != '\0' && *endp != '.')) 4545*7c478bd9Sstevel@tonic-gate goto bad; 4546*7c478bd9Sstevel@tonic-gate 4547*7c478bd9Sstevel@tonic-gate if (*endp == '.') { 4548*7c478bd9Sstevel@tonic-gate ns_str = endp + 1; 4549*7c478bd9Sstevel@tonic-gate len = strlen(ns_str); 4550*7c478bd9Sstevel@tonic-gate if (len == 0 || len > 9) 4551*7c478bd9Sstevel@tonic-gate goto bad; 4552*7c478bd9Sstevel@tonic-gate 4553*7c478bd9Sstevel@tonic-gate ns = strtoul(ns_str, &endp, 10); 4554*7c478bd9Sstevel@tonic-gate if (errno != 0 || endp == ns_str || *endp != '\0') 4555*7c478bd9Sstevel@tonic-gate goto bad; 4556*7c478bd9Sstevel@tonic-gate 4557*7c478bd9Sstevel@tonic-gate while (len++ < 9) 4558*7c478bd9Sstevel@tonic-gate ns *= 10; 4559*7c478bd9Sstevel@tonic-gate assert(ns < NANOSEC); 4560*7c478bd9Sstevel@tonic-gate } 4561*7c478bd9Sstevel@tonic-gate 4562*7c478bd9Sstevel@tonic-gate return (scf_value_set_time(v, s, ns)); 4563*7c478bd9Sstevel@tonic-gate } 4564*7c478bd9Sstevel@tonic-gate 4565*7c478bd9Sstevel@tonic-gate case SCF_TYPE_ASTRING: 4566*7c478bd9Sstevel@tonic-gate case SCF_TYPE_USTRING: 4567*7c478bd9Sstevel@tonic-gate case SCF_TYPE_OPAQUE: 4568*7c478bd9Sstevel@tonic-gate case SCF_TYPE_URI: 4569*7c478bd9Sstevel@tonic-gate case SCF_TYPE_FMRI: 4570*7c478bd9Sstevel@tonic-gate case SCF_TYPE_HOST: 4571*7c478bd9Sstevel@tonic-gate case SCF_TYPE_HOSTNAME: 4572*7c478bd9Sstevel@tonic-gate case SCF_TYPE_NET_ADDR_V4: 4573*7c478bd9Sstevel@tonic-gate case SCF_TYPE_NET_ADDR_V6: 4574*7c478bd9Sstevel@tonic-gate ty = scf_type_to_protocol_type(type); 4575*7c478bd9Sstevel@tonic-gate 4576*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4577*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4578*7c478bd9Sstevel@tonic-gate if (type == SCF_TYPE_OPAQUE) { 4579*7c478bd9Sstevel@tonic-gate v->value_size = scf_opaque_decode(v->value_value, 4580*7c478bd9Sstevel@tonic-gate str, sizeof (v->value_value)); 4581*7c478bd9Sstevel@tonic-gate if (!scf_validate_encoded_value(ty, str)) { 4582*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4583*7c478bd9Sstevel@tonic-gate goto bad; 4584*7c478bd9Sstevel@tonic-gate } 4585*7c478bd9Sstevel@tonic-gate } else { 4586*7c478bd9Sstevel@tonic-gate (void) strlcpy(v->value_value, str, 4587*7c478bd9Sstevel@tonic-gate sizeof (v->value_value)); 4588*7c478bd9Sstevel@tonic-gate if (!scf_validate_encoded_value(ty, v->value_value)) { 4589*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4590*7c478bd9Sstevel@tonic-gate goto bad; 4591*7c478bd9Sstevel@tonic-gate } 4592*7c478bd9Sstevel@tonic-gate } 4593*7c478bd9Sstevel@tonic-gate v->value_type = ty; 4594*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4595*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 4596*7c478bd9Sstevel@tonic-gate 4597*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_TYPE_INVALID: 4598*7c478bd9Sstevel@tonic-gate default: 4599*7c478bd9Sstevel@tonic-gate scf_value_reset(v); 4600*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_TYPE_MISMATCH)); 4601*7c478bd9Sstevel@tonic-gate } 4602*7c478bd9Sstevel@tonic-gate bad: 4603*7c478bd9Sstevel@tonic-gate scf_value_reset(v); 4604*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4605*7c478bd9Sstevel@tonic-gate } 4606*7c478bd9Sstevel@tonic-gate 4607*7c478bd9Sstevel@tonic-gate int 4608*7c478bd9Sstevel@tonic-gate scf_iter_property_values(scf_iter_t *iter, const scf_property_t *prop) 4609*7c478bd9Sstevel@tonic-gate { 4610*7c478bd9Sstevel@tonic-gate return (datael_setup_iter(iter, &prop->rd_d, 4611*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_ENTITY_VALUE, 0)); 4612*7c478bd9Sstevel@tonic-gate } 4613*7c478bd9Sstevel@tonic-gate 4614*7c478bd9Sstevel@tonic-gate int 4615*7c478bd9Sstevel@tonic-gate scf_iter_next_value(scf_iter_t *iter, scf_value_t *v) 4616*7c478bd9Sstevel@tonic-gate { 4617*7c478bd9Sstevel@tonic-gate scf_handle_t *h = iter->iter_handle; 4618*7c478bd9Sstevel@tonic-gate 4619*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_read_value request; 4620*7c478bd9Sstevel@tonic-gate struct rep_protocol_value_response response; 4621*7c478bd9Sstevel@tonic-gate 4622*7c478bd9Sstevel@tonic-gate int r; 4623*7c478bd9Sstevel@tonic-gate 4624*7c478bd9Sstevel@tonic-gate if (h != v->value_handle) 4625*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 4626*7c478bd9Sstevel@tonic-gate 4627*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4628*7c478bd9Sstevel@tonic-gate 4629*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4630*7c478bd9Sstevel@tonic-gate 4631*7c478bd9Sstevel@tonic-gate if (iter->iter_type == REP_PROTOCOL_ENTITY_NONE) { 4632*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4633*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_NOT_SET)); 4634*7c478bd9Sstevel@tonic-gate } 4635*7c478bd9Sstevel@tonic-gate 4636*7c478bd9Sstevel@tonic-gate if (iter->iter_type != REP_PROTOCOL_ENTITY_VALUE) { 4637*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4638*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4639*7c478bd9Sstevel@tonic-gate } 4640*7c478bd9Sstevel@tonic-gate 4641*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ITER_READ_VALUE; 4642*7c478bd9Sstevel@tonic-gate request.rpr_iterid = iter->iter_id; 4643*7c478bd9Sstevel@tonic-gate request.rpr_sequence = iter->iter_sequence; 4644*7c478bd9Sstevel@tonic-gate 4645*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 4646*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 4647*7c478bd9Sstevel@tonic-gate 4648*7c478bd9Sstevel@tonic-gate if (r < 0) { 4649*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4650*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 4651*7c478bd9Sstevel@tonic-gate } 4652*7c478bd9Sstevel@tonic-gate 4653*7c478bd9Sstevel@tonic-gate if (response.rpr_response == REP_PROTOCOL_DONE) { 4654*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4655*7c478bd9Sstevel@tonic-gate return (0); 4656*7c478bd9Sstevel@tonic-gate } 4657*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) { 4658*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4659*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 4660*7c478bd9Sstevel@tonic-gate } 4661*7c478bd9Sstevel@tonic-gate iter->iter_sequence++; 4662*7c478bd9Sstevel@tonic-gate 4663*7c478bd9Sstevel@tonic-gate v->value_type = response.rpr_type; 4664*7c478bd9Sstevel@tonic-gate 4665*7c478bd9Sstevel@tonic-gate assert(scf_validate_encoded_value(response.rpr_type, 4666*7c478bd9Sstevel@tonic-gate response.rpr_value)); 4667*7c478bd9Sstevel@tonic-gate 4668*7c478bd9Sstevel@tonic-gate if (v->value_type != REP_PROTOCOL_TYPE_OPAQUE) { 4669*7c478bd9Sstevel@tonic-gate (void) strlcpy(v->value_value, response.rpr_value, 4670*7c478bd9Sstevel@tonic-gate sizeof (v->value_value)); 4671*7c478bd9Sstevel@tonic-gate } else { 4672*7c478bd9Sstevel@tonic-gate v->value_size = scf_opaque_decode(v->value_value, 4673*7c478bd9Sstevel@tonic-gate response.rpr_value, sizeof (v->value_value)); 4674*7c478bd9Sstevel@tonic-gate } 4675*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4676*7c478bd9Sstevel@tonic-gate 4677*7c478bd9Sstevel@tonic-gate return (1); 4678*7c478bd9Sstevel@tonic-gate } 4679*7c478bd9Sstevel@tonic-gate 4680*7c478bd9Sstevel@tonic-gate int 4681*7c478bd9Sstevel@tonic-gate scf_property_get_value(const scf_property_t *prop, scf_value_t *v) 4682*7c478bd9Sstevel@tonic-gate { 4683*7c478bd9Sstevel@tonic-gate scf_handle_t *h = prop->rd_d.rd_handle; 4684*7c478bd9Sstevel@tonic-gate struct rep_protocol_property_request request; 4685*7c478bd9Sstevel@tonic-gate struct rep_protocol_value_response response; 4686*7c478bd9Sstevel@tonic-gate int r; 4687*7c478bd9Sstevel@tonic-gate 4688*7c478bd9Sstevel@tonic-gate if (h != v->value_handle) 4689*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 4690*7c478bd9Sstevel@tonic-gate 4691*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 4692*7c478bd9Sstevel@tonic-gate 4693*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_PROPERTY_GET_VALUE; 4694*7c478bd9Sstevel@tonic-gate request.rpr_entityid = prop->rd_d.rd_entity; 4695*7c478bd9Sstevel@tonic-gate 4696*7c478bd9Sstevel@tonic-gate scf_value_reset_locked(v, 0); 4697*7c478bd9Sstevel@tonic-gate datael_finish_reset(&prop->rd_d); 4698*7c478bd9Sstevel@tonic-gate 4699*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 4700*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 4701*7c478bd9Sstevel@tonic-gate 4702*7c478bd9Sstevel@tonic-gate if (r < 0) { 4703*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4704*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 4705*7c478bd9Sstevel@tonic-gate } 4706*7c478bd9Sstevel@tonic-gate 4707*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS && 4708*7c478bd9Sstevel@tonic-gate response.rpr_response != REP_PROTOCOL_FAIL_TRUNCATED) { 4709*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4710*7c478bd9Sstevel@tonic-gate assert(response.rpr_response != 4711*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_FAIL_TYPE_MISMATCH); 4712*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 4713*7c478bd9Sstevel@tonic-gate } 4714*7c478bd9Sstevel@tonic-gate 4715*7c478bd9Sstevel@tonic-gate v->value_type = response.rpr_type; 4716*7c478bd9Sstevel@tonic-gate if (v->value_type != REP_PROTOCOL_TYPE_OPAQUE) { 4717*7c478bd9Sstevel@tonic-gate (void) strlcpy(v->value_value, response.rpr_value, 4718*7c478bd9Sstevel@tonic-gate sizeof (v->value_value)); 4719*7c478bd9Sstevel@tonic-gate } else { 4720*7c478bd9Sstevel@tonic-gate v->value_size = scf_opaque_decode(v->value_value, 4721*7c478bd9Sstevel@tonic-gate response.rpr_value, sizeof (v->value_value)); 4722*7c478bd9Sstevel@tonic-gate } 4723*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 4724*7c478bd9Sstevel@tonic-gate return ((response.rpr_response == REP_PROTOCOL_SUCCESS)? 4725*7c478bd9Sstevel@tonic-gate SCF_SUCCESS : scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED)); 4726*7c478bd9Sstevel@tonic-gate } 4727*7c478bd9Sstevel@tonic-gate 4728*7c478bd9Sstevel@tonic-gate int 4729*7c478bd9Sstevel@tonic-gate scf_pg_get_parent_service(const scf_propertygroup_t *pg, scf_service_t *svc) 4730*7c478bd9Sstevel@tonic-gate { 4731*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&pg->rd_d, &svc->rd_d)); 4732*7c478bd9Sstevel@tonic-gate } 4733*7c478bd9Sstevel@tonic-gate 4734*7c478bd9Sstevel@tonic-gate int 4735*7c478bd9Sstevel@tonic-gate scf_pg_get_parent_instance(const scf_propertygroup_t *pg, scf_instance_t *inst) 4736*7c478bd9Sstevel@tonic-gate { 4737*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&pg->rd_d, &inst->rd_d)); 4738*7c478bd9Sstevel@tonic-gate } 4739*7c478bd9Sstevel@tonic-gate 4740*7c478bd9Sstevel@tonic-gate int 4741*7c478bd9Sstevel@tonic-gate scf_pg_get_parent_snaplevel(const scf_propertygroup_t *pg, 4742*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *level) 4743*7c478bd9Sstevel@tonic-gate { 4744*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&pg->rd_d, &level->rd_d)); 4745*7c478bd9Sstevel@tonic-gate } 4746*7c478bd9Sstevel@tonic-gate 4747*7c478bd9Sstevel@tonic-gate int 4748*7c478bd9Sstevel@tonic-gate scf_service_get_parent(const scf_service_t *svc, scf_scope_t *s) 4749*7c478bd9Sstevel@tonic-gate { 4750*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&svc->rd_d, &s->rd_d)); 4751*7c478bd9Sstevel@tonic-gate } 4752*7c478bd9Sstevel@tonic-gate 4753*7c478bd9Sstevel@tonic-gate int 4754*7c478bd9Sstevel@tonic-gate scf_instance_get_parent(const scf_instance_t *inst, scf_service_t *svc) 4755*7c478bd9Sstevel@tonic-gate { 4756*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&inst->rd_d, &svc->rd_d)); 4757*7c478bd9Sstevel@tonic-gate } 4758*7c478bd9Sstevel@tonic-gate 4759*7c478bd9Sstevel@tonic-gate int 4760*7c478bd9Sstevel@tonic-gate scf_snapshot_get_parent(const scf_snapshot_t *inst, scf_instance_t *svc) 4761*7c478bd9Sstevel@tonic-gate { 4762*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&inst->rd_d, &svc->rd_d)); 4763*7c478bd9Sstevel@tonic-gate } 4764*7c478bd9Sstevel@tonic-gate 4765*7c478bd9Sstevel@tonic-gate int 4766*7c478bd9Sstevel@tonic-gate scf_snaplevel_get_parent(const scf_snaplevel_t *inst, scf_snapshot_t *svc) 4767*7c478bd9Sstevel@tonic-gate { 4768*7c478bd9Sstevel@tonic-gate return (datael_get_parent(&inst->rd_d, &svc->rd_d)); 4769*7c478bd9Sstevel@tonic-gate } 4770*7c478bd9Sstevel@tonic-gate 4771*7c478bd9Sstevel@tonic-gate /* 4772*7c478bd9Sstevel@tonic-gate * FMRI functions 4773*7c478bd9Sstevel@tonic-gate * 4774*7c478bd9Sstevel@tonic-gate * Note: In the scf_parse_svc_fmri(), scf_parse_file_fmri() and 4775*7c478bd9Sstevel@tonic-gate * scf_parse_fmri(), fmri isn't const because that would require 4776*7c478bd9Sstevel@tonic-gate * allocating memory. Also, note that scope, at least, is not necessarily 4777*7c478bd9Sstevel@tonic-gate * in the passed in fmri. 4778*7c478bd9Sstevel@tonic-gate */ 4779*7c478bd9Sstevel@tonic-gate 4780*7c478bd9Sstevel@tonic-gate int 4781*7c478bd9Sstevel@tonic-gate scf_parse_svc_fmri(char *fmri, const char **scope, const char **service, 4782*7c478bd9Sstevel@tonic-gate const char **instance, const char **propertygroup, const char **property) 4783*7c478bd9Sstevel@tonic-gate { 4784*7c478bd9Sstevel@tonic-gate char *s, *e, *te, *tpg; 4785*7c478bd9Sstevel@tonic-gate char *my_s = NULL, *my_i = NULL, *my_pg = NULL, *my_p = NULL; 4786*7c478bd9Sstevel@tonic-gate 4787*7c478bd9Sstevel@tonic-gate if (scope != NULL) 4788*7c478bd9Sstevel@tonic-gate *scope = NULL; 4789*7c478bd9Sstevel@tonic-gate if (service != NULL) 4790*7c478bd9Sstevel@tonic-gate *service = NULL; 4791*7c478bd9Sstevel@tonic-gate if (instance != NULL) 4792*7c478bd9Sstevel@tonic-gate *instance = NULL; 4793*7c478bd9Sstevel@tonic-gate if (propertygroup != NULL) 4794*7c478bd9Sstevel@tonic-gate *propertygroup = NULL; 4795*7c478bd9Sstevel@tonic-gate if (property != NULL) 4796*7c478bd9Sstevel@tonic-gate *property = NULL; 4797*7c478bd9Sstevel@tonic-gate 4798*7c478bd9Sstevel@tonic-gate s = fmri; 4799*7c478bd9Sstevel@tonic-gate e = strchr(s, '\0'); 4800*7c478bd9Sstevel@tonic-gate 4801*7c478bd9Sstevel@tonic-gate if (strncmp(s, SCF_FMRI_SVC_PREFIX, 4802*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SVC_PREFIX) - 1) == 0) 4803*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_SVC_PREFIX) - 1; 4804*7c478bd9Sstevel@tonic-gate 4805*7c478bd9Sstevel@tonic-gate if (strncmp(s, SCF_FMRI_SCOPE_PREFIX, 4806*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SCOPE_PREFIX) - 1) == 0) { 4807*7c478bd9Sstevel@tonic-gate char *my_scope; 4808*7c478bd9Sstevel@tonic-gate 4809*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_SCOPE_PREFIX) - 1; 4810*7c478bd9Sstevel@tonic-gate te = strstr(s, SCF_FMRI_SERVICE_PREFIX); 4811*7c478bd9Sstevel@tonic-gate if (te == NULL) 4812*7c478bd9Sstevel@tonic-gate te = e; 4813*7c478bd9Sstevel@tonic-gate 4814*7c478bd9Sstevel@tonic-gate *te = 0; 4815*7c478bd9Sstevel@tonic-gate my_scope = s; 4816*7c478bd9Sstevel@tonic-gate 4817*7c478bd9Sstevel@tonic-gate s = te; 4818*7c478bd9Sstevel@tonic-gate if (s < e) 4819*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_SERVICE_PREFIX) - 1; 4820*7c478bd9Sstevel@tonic-gate 4821*7c478bd9Sstevel@tonic-gate /* If the scope ends with the suffix, remove it. */ 4822*7c478bd9Sstevel@tonic-gate te = strstr(my_scope, SCF_FMRI_SCOPE_SUFFIX); 4823*7c478bd9Sstevel@tonic-gate if (te != NULL && te[sizeof (SCF_FMRI_SCOPE_SUFFIX) - 1] == 0) 4824*7c478bd9Sstevel@tonic-gate *te = 0; 4825*7c478bd9Sstevel@tonic-gate 4826*7c478bd9Sstevel@tonic-gate /* Validate the scope. */ 4827*7c478bd9Sstevel@tonic-gate if (my_scope[0] == '\0') 4828*7c478bd9Sstevel@tonic-gate my_scope = SCF_FMRI_LOCAL_SCOPE; 4829*7c478bd9Sstevel@tonic-gate else if (uu_check_name(my_scope, 0) == -1) { 4830*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4831*7c478bd9Sstevel@tonic-gate } 4832*7c478bd9Sstevel@tonic-gate 4833*7c478bd9Sstevel@tonic-gate if (scope != NULL) 4834*7c478bd9Sstevel@tonic-gate *scope = my_scope; 4835*7c478bd9Sstevel@tonic-gate } else { 4836*7c478bd9Sstevel@tonic-gate if (scope != NULL) 4837*7c478bd9Sstevel@tonic-gate *scope = SCF_FMRI_LOCAL_SCOPE; 4838*7c478bd9Sstevel@tonic-gate } 4839*7c478bd9Sstevel@tonic-gate 4840*7c478bd9Sstevel@tonic-gate if (s[0] != 0) { 4841*7c478bd9Sstevel@tonic-gate if (strncmp(s, SCF_FMRI_SERVICE_PREFIX, 4842*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SERVICE_PREFIX) - 1) == 0) 4843*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_SERVICE_PREFIX) - 1; 4844*7c478bd9Sstevel@tonic-gate 4845*7c478bd9Sstevel@tonic-gate /* 4846*7c478bd9Sstevel@tonic-gate * Can't validate service here because it might not be null 4847*7c478bd9Sstevel@tonic-gate * terminated. 4848*7c478bd9Sstevel@tonic-gate */ 4849*7c478bd9Sstevel@tonic-gate my_s = s; 4850*7c478bd9Sstevel@tonic-gate } 4851*7c478bd9Sstevel@tonic-gate 4852*7c478bd9Sstevel@tonic-gate tpg = strstr(s, SCF_FMRI_PROPERTYGRP_PREFIX); 4853*7c478bd9Sstevel@tonic-gate te = strstr(s, SCF_FMRI_INSTANCE_PREFIX); 4854*7c478bd9Sstevel@tonic-gate if (te != NULL && (tpg == NULL || te < tpg)) { 4855*7c478bd9Sstevel@tonic-gate *te = 0; 4856*7c478bd9Sstevel@tonic-gate te += sizeof (SCF_FMRI_INSTANCE_PREFIX) - 1; 4857*7c478bd9Sstevel@tonic-gate 4858*7c478bd9Sstevel@tonic-gate /* Can't validate instance here either. */ 4859*7c478bd9Sstevel@tonic-gate my_i = s = te; 4860*7c478bd9Sstevel@tonic-gate 4861*7c478bd9Sstevel@tonic-gate te = strstr(s, SCF_FMRI_PROPERTYGRP_PREFIX); 4862*7c478bd9Sstevel@tonic-gate } else { 4863*7c478bd9Sstevel@tonic-gate te = tpg; 4864*7c478bd9Sstevel@tonic-gate } 4865*7c478bd9Sstevel@tonic-gate 4866*7c478bd9Sstevel@tonic-gate if (te != NULL) { 4867*7c478bd9Sstevel@tonic-gate *te = 0; 4868*7c478bd9Sstevel@tonic-gate te += sizeof (SCF_FMRI_PROPERTYGRP_PREFIX) - 1; 4869*7c478bd9Sstevel@tonic-gate 4870*7c478bd9Sstevel@tonic-gate my_pg = s = te; 4871*7c478bd9Sstevel@tonic-gate te = strstr(s, SCF_FMRI_PROPERTY_PREFIX); 4872*7c478bd9Sstevel@tonic-gate if (te != NULL) { 4873*7c478bd9Sstevel@tonic-gate *te = 0; 4874*7c478bd9Sstevel@tonic-gate te += sizeof (SCF_FMRI_PROPERTY_PREFIX) - 1; 4875*7c478bd9Sstevel@tonic-gate 4876*7c478bd9Sstevel@tonic-gate my_p = te; 4877*7c478bd9Sstevel@tonic-gate s = te; 4878*7c478bd9Sstevel@tonic-gate } 4879*7c478bd9Sstevel@tonic-gate } 4880*7c478bd9Sstevel@tonic-gate 4881*7c478bd9Sstevel@tonic-gate if (my_s != NULL) { 4882*7c478bd9Sstevel@tonic-gate if (uu_check_name(my_s, UU_NAME_DOMAIN | UU_NAME_PATH) == -1) 4883*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4884*7c478bd9Sstevel@tonic-gate 4885*7c478bd9Sstevel@tonic-gate if (service != NULL) 4886*7c478bd9Sstevel@tonic-gate *service = my_s; 4887*7c478bd9Sstevel@tonic-gate } 4888*7c478bd9Sstevel@tonic-gate 4889*7c478bd9Sstevel@tonic-gate if (my_i != NULL) { 4890*7c478bd9Sstevel@tonic-gate if (uu_check_name(my_i, UU_NAME_DOMAIN) == -1) 4891*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4892*7c478bd9Sstevel@tonic-gate 4893*7c478bd9Sstevel@tonic-gate if (instance != NULL) 4894*7c478bd9Sstevel@tonic-gate *instance = my_i; 4895*7c478bd9Sstevel@tonic-gate } 4896*7c478bd9Sstevel@tonic-gate 4897*7c478bd9Sstevel@tonic-gate if (my_pg != NULL) { 4898*7c478bd9Sstevel@tonic-gate if (uu_check_name(my_pg, UU_NAME_DOMAIN) == -1) 4899*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4900*7c478bd9Sstevel@tonic-gate 4901*7c478bd9Sstevel@tonic-gate if (propertygroup != NULL) 4902*7c478bd9Sstevel@tonic-gate *propertygroup = my_pg; 4903*7c478bd9Sstevel@tonic-gate } 4904*7c478bd9Sstevel@tonic-gate 4905*7c478bd9Sstevel@tonic-gate if (my_p != NULL) { 4906*7c478bd9Sstevel@tonic-gate if (uu_check_name(my_p, UU_NAME_DOMAIN) == -1) 4907*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4908*7c478bd9Sstevel@tonic-gate 4909*7c478bd9Sstevel@tonic-gate if (property != NULL) 4910*7c478bd9Sstevel@tonic-gate *property = my_p; 4911*7c478bd9Sstevel@tonic-gate } 4912*7c478bd9Sstevel@tonic-gate 4913*7c478bd9Sstevel@tonic-gate return (0); 4914*7c478bd9Sstevel@tonic-gate } 4915*7c478bd9Sstevel@tonic-gate 4916*7c478bd9Sstevel@tonic-gate int 4917*7c478bd9Sstevel@tonic-gate scf_parse_file_fmri(char *fmri, const char **scope, const char **path) 4918*7c478bd9Sstevel@tonic-gate { 4919*7c478bd9Sstevel@tonic-gate char *s, *e, *te; 4920*7c478bd9Sstevel@tonic-gate 4921*7c478bd9Sstevel@tonic-gate if (scope != NULL) 4922*7c478bd9Sstevel@tonic-gate *scope = NULL; 4923*7c478bd9Sstevel@tonic-gate 4924*7c478bd9Sstevel@tonic-gate s = fmri; 4925*7c478bd9Sstevel@tonic-gate e = strchr(s, '\0'); 4926*7c478bd9Sstevel@tonic-gate 4927*7c478bd9Sstevel@tonic-gate if (strncmp(s, SCF_FMRI_FILE_PREFIX, 4928*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_FILE_PREFIX) - 1) == 0) 4929*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_FILE_PREFIX) - 1; 4930*7c478bd9Sstevel@tonic-gate 4931*7c478bd9Sstevel@tonic-gate if (strncmp(s, SCF_FMRI_SCOPE_PREFIX, 4932*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SCOPE_PREFIX) - 1) == 0) { 4933*7c478bd9Sstevel@tonic-gate char *my_scope; 4934*7c478bd9Sstevel@tonic-gate 4935*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_SCOPE_PREFIX) - 1; 4936*7c478bd9Sstevel@tonic-gate te = strstr(s, SCF_FMRI_SERVICE_PREFIX); 4937*7c478bd9Sstevel@tonic-gate if (te == NULL) 4938*7c478bd9Sstevel@tonic-gate te = e; 4939*7c478bd9Sstevel@tonic-gate 4940*7c478bd9Sstevel@tonic-gate *te = 0; 4941*7c478bd9Sstevel@tonic-gate my_scope = s; 4942*7c478bd9Sstevel@tonic-gate 4943*7c478bd9Sstevel@tonic-gate s = te; 4944*7c478bd9Sstevel@tonic-gate 4945*7c478bd9Sstevel@tonic-gate /* Validate the scope. */ 4946*7c478bd9Sstevel@tonic-gate if (my_scope[0] != '\0' && 4947*7c478bd9Sstevel@tonic-gate strcmp(my_scope, SCF_FMRI_LOCAL_SCOPE) != 0) { 4948*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4949*7c478bd9Sstevel@tonic-gate } 4950*7c478bd9Sstevel@tonic-gate 4951*7c478bd9Sstevel@tonic-gate if (scope != NULL) 4952*7c478bd9Sstevel@tonic-gate *scope = my_scope; 4953*7c478bd9Sstevel@tonic-gate } else { 4954*7c478bd9Sstevel@tonic-gate /* 4955*7c478bd9Sstevel@tonic-gate * FMRI paths must be absolute 4956*7c478bd9Sstevel@tonic-gate */ 4957*7c478bd9Sstevel@tonic-gate if (s[0] != '/') 4958*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4959*7c478bd9Sstevel@tonic-gate } 4960*7c478bd9Sstevel@tonic-gate 4961*7c478bd9Sstevel@tonic-gate s += sizeof (SCF_FMRI_SERVICE_PREFIX) - 1; 4962*7c478bd9Sstevel@tonic-gate 4963*7c478bd9Sstevel@tonic-gate if (s >= e) 4964*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 4965*7c478bd9Sstevel@tonic-gate 4966*7c478bd9Sstevel@tonic-gate /* 4967*7c478bd9Sstevel@tonic-gate * If the user requests it, return the full path of the file. 4968*7c478bd9Sstevel@tonic-gate */ 4969*7c478bd9Sstevel@tonic-gate if (path != NULL) { 4970*7c478bd9Sstevel@tonic-gate assert(s > fmri); 4971*7c478bd9Sstevel@tonic-gate s[-1] = '/'; 4972*7c478bd9Sstevel@tonic-gate *path = s - 1; 4973*7c478bd9Sstevel@tonic-gate } 4974*7c478bd9Sstevel@tonic-gate 4975*7c478bd9Sstevel@tonic-gate return (0); 4976*7c478bd9Sstevel@tonic-gate } 4977*7c478bd9Sstevel@tonic-gate 4978*7c478bd9Sstevel@tonic-gate int 4979*7c478bd9Sstevel@tonic-gate scf_parse_fmri(char *fmri, int *type, const char **scope, const char **service, 4980*7c478bd9Sstevel@tonic-gate const char **instance, const char **propertygroup, const char **property) 4981*7c478bd9Sstevel@tonic-gate { 4982*7c478bd9Sstevel@tonic-gate if (strncmp(fmri, SCF_FMRI_SVC_PREFIX, 4983*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_SVC_PREFIX) - 1) == 0) { 4984*7c478bd9Sstevel@tonic-gate if (type) 4985*7c478bd9Sstevel@tonic-gate *type = SCF_FMRI_TYPE_SVC; 4986*7c478bd9Sstevel@tonic-gate return (scf_parse_svc_fmri(fmri, scope, service, instance, 4987*7c478bd9Sstevel@tonic-gate propertygroup, property)); 4988*7c478bd9Sstevel@tonic-gate } else if (strncmp(fmri, SCF_FMRI_FILE_PREFIX, 4989*7c478bd9Sstevel@tonic-gate sizeof (SCF_FMRI_FILE_PREFIX) - 1) == 0) { 4990*7c478bd9Sstevel@tonic-gate if (type) 4991*7c478bd9Sstevel@tonic-gate *type = SCF_FMRI_TYPE_FILE; 4992*7c478bd9Sstevel@tonic-gate return (scf_parse_file_fmri(fmri, scope, NULL)); 4993*7c478bd9Sstevel@tonic-gate } else { 4994*7c478bd9Sstevel@tonic-gate /* 4995*7c478bd9Sstevel@tonic-gate * Parse as a svc if the fmri type is not explicitly 4996*7c478bd9Sstevel@tonic-gate * specified. 4997*7c478bd9Sstevel@tonic-gate */ 4998*7c478bd9Sstevel@tonic-gate if (type) 4999*7c478bd9Sstevel@tonic-gate *type = SCF_FMRI_TYPE_SVC; 5000*7c478bd9Sstevel@tonic-gate return (scf_parse_svc_fmri(fmri, scope, service, instance, 5001*7c478bd9Sstevel@tonic-gate propertygroup, property)); 5002*7c478bd9Sstevel@tonic-gate } 5003*7c478bd9Sstevel@tonic-gate } 5004*7c478bd9Sstevel@tonic-gate 5005*7c478bd9Sstevel@tonic-gate /* 5006*7c478bd9Sstevel@tonic-gate * Fails with _INVALID_ARGUMENT. fmri and buf may be equal. 5007*7c478bd9Sstevel@tonic-gate */ 5008*7c478bd9Sstevel@tonic-gate ssize_t 5009*7c478bd9Sstevel@tonic-gate scf_canonify_fmri(const char *fmri, char *buf, size_t bufsz) 5010*7c478bd9Sstevel@tonic-gate { 5011*7c478bd9Sstevel@tonic-gate const char *scope, *service, *instance, *pg, *property; 5012*7c478bd9Sstevel@tonic-gate char local[6 * REP_PROTOCOL_NAME_LEN]; 5013*7c478bd9Sstevel@tonic-gate int r; 5014*7c478bd9Sstevel@tonic-gate size_t len; 5015*7c478bd9Sstevel@tonic-gate 5016*7c478bd9Sstevel@tonic-gate if (strlcpy(local, fmri, sizeof (local)) >= sizeof (local)) { 5017*7c478bd9Sstevel@tonic-gate /* Should this be CONSTRAINT_VIOLATED? */ 5018*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 5019*7c478bd9Sstevel@tonic-gate return (-1); 5020*7c478bd9Sstevel@tonic-gate } 5021*7c478bd9Sstevel@tonic-gate 5022*7c478bd9Sstevel@tonic-gate 5023*7c478bd9Sstevel@tonic-gate r = scf_parse_svc_fmri(local, &scope, &service, &instance, &pg, 5024*7c478bd9Sstevel@tonic-gate &property); 5025*7c478bd9Sstevel@tonic-gate if (r != 0) 5026*7c478bd9Sstevel@tonic-gate return (-1); 5027*7c478bd9Sstevel@tonic-gate 5028*7c478bd9Sstevel@tonic-gate len = strlcpy(buf, "svc:/", bufsz); 5029*7c478bd9Sstevel@tonic-gate 5030*7c478bd9Sstevel@tonic-gate if (scope != NULL && strcmp(scope, SCF_SCOPE_LOCAL) != 0) { 5031*7c478bd9Sstevel@tonic-gate len += strlcat(buf, "/", bufsz); 5032*7c478bd9Sstevel@tonic-gate len += strlcat(buf, scope, bufsz); 5033*7c478bd9Sstevel@tonic-gate } 5034*7c478bd9Sstevel@tonic-gate 5035*7c478bd9Sstevel@tonic-gate if (service) 5036*7c478bd9Sstevel@tonic-gate len += strlcat(buf, service, bufsz); 5037*7c478bd9Sstevel@tonic-gate 5038*7c478bd9Sstevel@tonic-gate if (instance) { 5039*7c478bd9Sstevel@tonic-gate len += strlcat(buf, ":", bufsz); 5040*7c478bd9Sstevel@tonic-gate len += strlcat(buf, instance, bufsz); 5041*7c478bd9Sstevel@tonic-gate } 5042*7c478bd9Sstevel@tonic-gate 5043*7c478bd9Sstevel@tonic-gate if (pg) { 5044*7c478bd9Sstevel@tonic-gate len += strlcat(buf, "/:properties/", bufsz); 5045*7c478bd9Sstevel@tonic-gate len += strlcat(buf, pg, bufsz); 5046*7c478bd9Sstevel@tonic-gate } 5047*7c478bd9Sstevel@tonic-gate 5048*7c478bd9Sstevel@tonic-gate if (property) { 5049*7c478bd9Sstevel@tonic-gate len += strlcat(buf, "/", bufsz); 5050*7c478bd9Sstevel@tonic-gate len += strlcat(buf, property, bufsz); 5051*7c478bd9Sstevel@tonic-gate } 5052*7c478bd9Sstevel@tonic-gate 5053*7c478bd9Sstevel@tonic-gate return (len); 5054*7c478bd9Sstevel@tonic-gate } 5055*7c478bd9Sstevel@tonic-gate 5056*7c478bd9Sstevel@tonic-gate int 5057*7c478bd9Sstevel@tonic-gate scf_handle_decode_fmri(scf_handle_t *h, const char *fmri, scf_scope_t *sc, 5058*7c478bd9Sstevel@tonic-gate scf_service_t *svc, scf_instance_t *inst, scf_propertygroup_t *pg, 5059*7c478bd9Sstevel@tonic-gate scf_property_t *prop, int flags) 5060*7c478bd9Sstevel@tonic-gate { 5061*7c478bd9Sstevel@tonic-gate const char *scope, *service, *instance, *propertygroup, *property; 5062*7c478bd9Sstevel@tonic-gate int last; 5063*7c478bd9Sstevel@tonic-gate char local[6 * REP_PROTOCOL_NAME_LEN]; 5064*7c478bd9Sstevel@tonic-gate int ret; 5065*7c478bd9Sstevel@tonic-gate const uint32_t holds = RH_HOLD_SCOPE | RH_HOLD_SERVICE | 5066*7c478bd9Sstevel@tonic-gate RH_HOLD_INSTANCE | RH_HOLD_PG | RH_HOLD_PROPERTY; 5067*7c478bd9Sstevel@tonic-gate 5068*7c478bd9Sstevel@tonic-gate /* 5069*7c478bd9Sstevel@tonic-gate * verify that all handles match 5070*7c478bd9Sstevel@tonic-gate */ 5071*7c478bd9Sstevel@tonic-gate if ((sc != NULL && h != sc->rd_d.rd_handle) || 5072*7c478bd9Sstevel@tonic-gate (svc != NULL && h != svc->rd_d.rd_handle) || 5073*7c478bd9Sstevel@tonic-gate (inst != NULL && h != inst->rd_d.rd_handle) || 5074*7c478bd9Sstevel@tonic-gate (pg != NULL && h != pg->rd_d.rd_handle) || 5075*7c478bd9Sstevel@tonic-gate (prop != NULL && h != prop->rd_d.rd_handle)) 5076*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 5077*7c478bd9Sstevel@tonic-gate 5078*7c478bd9Sstevel@tonic-gate if (strlcpy(local, fmri, sizeof (local)) >= sizeof (local)) { 5079*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_INVALID_ARGUMENT); 5080*7c478bd9Sstevel@tonic-gate goto reset_args; 5081*7c478bd9Sstevel@tonic-gate } 5082*7c478bd9Sstevel@tonic-gate 5083*7c478bd9Sstevel@tonic-gate /* 5084*7c478bd9Sstevel@tonic-gate * We can simply return from an error in parsing, because 5085*7c478bd9Sstevel@tonic-gate * scf_parse_fmri sets the error code correctly. 5086*7c478bd9Sstevel@tonic-gate */ 5087*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(local, &scope, &service, &instance, 5088*7c478bd9Sstevel@tonic-gate &propertygroup, &property) == -1) { 5089*7c478bd9Sstevel@tonic-gate ret = -1; 5090*7c478bd9Sstevel@tonic-gate goto reset_args; 5091*7c478bd9Sstevel@tonic-gate } 5092*7c478bd9Sstevel@tonic-gate 5093*7c478bd9Sstevel@tonic-gate /* 5094*7c478bd9Sstevel@tonic-gate * the FMRI looks valid at this point -- do constraint checks. 5095*7c478bd9Sstevel@tonic-gate */ 5096*7c478bd9Sstevel@tonic-gate 5097*7c478bd9Sstevel@tonic-gate if (instance != NULL && (flags & SCF_DECODE_FMRI_REQUIRE_NO_INSTANCE)) { 5098*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 5099*7c478bd9Sstevel@tonic-gate goto reset_args; 5100*7c478bd9Sstevel@tonic-gate } 5101*7c478bd9Sstevel@tonic-gate if (instance == NULL && (flags & SCF_DECODE_FMRI_REQUIRE_INSTANCE)) { 5102*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 5103*7c478bd9Sstevel@tonic-gate goto reset_args; 5104*7c478bd9Sstevel@tonic-gate } 5105*7c478bd9Sstevel@tonic-gate 5106*7c478bd9Sstevel@tonic-gate if (prop != NULL) 5107*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_PROPERTY; 5108*7c478bd9Sstevel@tonic-gate else if (pg != NULL) 5109*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_PROPERTYGRP; 5110*7c478bd9Sstevel@tonic-gate else if (inst != NULL) 5111*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_INSTANCE; 5112*7c478bd9Sstevel@tonic-gate else if (svc != NULL) 5113*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_SERVICE; 5114*7c478bd9Sstevel@tonic-gate else if (sc != NULL) 5115*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_SCOPE; 5116*7c478bd9Sstevel@tonic-gate else 5117*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_NONE; 5118*7c478bd9Sstevel@tonic-gate 5119*7c478bd9Sstevel@tonic-gate if (flags & SCF_DECODE_FMRI_EXACT) { 5120*7c478bd9Sstevel@tonic-gate int last_fmri; 5121*7c478bd9Sstevel@tonic-gate 5122*7c478bd9Sstevel@tonic-gate if (property != NULL) 5123*7c478bd9Sstevel@tonic-gate last_fmri = REP_PROTOCOL_ENTITY_PROPERTY; 5124*7c478bd9Sstevel@tonic-gate else if (propertygroup != NULL) 5125*7c478bd9Sstevel@tonic-gate last_fmri = REP_PROTOCOL_ENTITY_PROPERTYGRP; 5126*7c478bd9Sstevel@tonic-gate else if (instance != NULL) 5127*7c478bd9Sstevel@tonic-gate last_fmri = REP_PROTOCOL_ENTITY_INSTANCE; 5128*7c478bd9Sstevel@tonic-gate else if (service != NULL) 5129*7c478bd9Sstevel@tonic-gate last_fmri = REP_PROTOCOL_ENTITY_SERVICE; 5130*7c478bd9Sstevel@tonic-gate else if (scope != NULL) 5131*7c478bd9Sstevel@tonic-gate last_fmri = REP_PROTOCOL_ENTITY_SCOPE; 5132*7c478bd9Sstevel@tonic-gate else 5133*7c478bd9Sstevel@tonic-gate last_fmri = REP_PROTOCOL_ENTITY_NONE; 5134*7c478bd9Sstevel@tonic-gate 5135*7c478bd9Sstevel@tonic-gate if (last != last_fmri) { 5136*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_CONSTRAINT_VIOLATED); 5137*7c478bd9Sstevel@tonic-gate goto reset_args; 5138*7c478bd9Sstevel@tonic-gate } 5139*7c478bd9Sstevel@tonic-gate } 5140*7c478bd9Sstevel@tonic-gate 5141*7c478bd9Sstevel@tonic-gate if ((flags & SCF_DECODE_FMRI_TRUNCATE) && 5142*7c478bd9Sstevel@tonic-gate last == REP_PROTOCOL_ENTITY_NONE) { 5143*7c478bd9Sstevel@tonic-gate ret = 0; /* nothing to do */ 5144*7c478bd9Sstevel@tonic-gate goto reset_args; 5145*7c478bd9Sstevel@tonic-gate } 5146*7c478bd9Sstevel@tonic-gate 5147*7c478bd9Sstevel@tonic-gate if (!(flags & SCF_DECODE_FMRI_TRUNCATE)) 5148*7c478bd9Sstevel@tonic-gate last = REP_PROTOCOL_ENTITY_NONE; /* never stop */ 5149*7c478bd9Sstevel@tonic-gate 5150*7c478bd9Sstevel@tonic-gate /* 5151*7c478bd9Sstevel@tonic-gate * passed the constraint checks -- try to grab the thing itself. 5152*7c478bd9Sstevel@tonic-gate */ 5153*7c478bd9Sstevel@tonic-gate 5154*7c478bd9Sstevel@tonic-gate handle_hold_subhandles(h, holds); 5155*7c478bd9Sstevel@tonic-gate if (sc == NULL) 5156*7c478bd9Sstevel@tonic-gate sc = h->rh_scope; 5157*7c478bd9Sstevel@tonic-gate else 5158*7c478bd9Sstevel@tonic-gate datael_reset(&sc->rd_d); 5159*7c478bd9Sstevel@tonic-gate 5160*7c478bd9Sstevel@tonic-gate if (svc == NULL) 5161*7c478bd9Sstevel@tonic-gate svc = h->rh_service; 5162*7c478bd9Sstevel@tonic-gate else 5163*7c478bd9Sstevel@tonic-gate datael_reset(&svc->rd_d); 5164*7c478bd9Sstevel@tonic-gate 5165*7c478bd9Sstevel@tonic-gate if (inst == NULL) 5166*7c478bd9Sstevel@tonic-gate inst = h->rh_instance; 5167*7c478bd9Sstevel@tonic-gate else 5168*7c478bd9Sstevel@tonic-gate datael_reset(&inst->rd_d); 5169*7c478bd9Sstevel@tonic-gate 5170*7c478bd9Sstevel@tonic-gate if (pg == NULL) 5171*7c478bd9Sstevel@tonic-gate pg = h->rh_pg; 5172*7c478bd9Sstevel@tonic-gate else 5173*7c478bd9Sstevel@tonic-gate datael_reset(&pg->rd_d); 5174*7c478bd9Sstevel@tonic-gate 5175*7c478bd9Sstevel@tonic-gate if (prop == NULL) 5176*7c478bd9Sstevel@tonic-gate prop = h->rh_property; 5177*7c478bd9Sstevel@tonic-gate else 5178*7c478bd9Sstevel@tonic-gate datael_reset(&prop->rd_d); 5179*7c478bd9Sstevel@tonic-gate 5180*7c478bd9Sstevel@tonic-gate /* 5181*7c478bd9Sstevel@tonic-gate * We only support local scopes, but we check *after* getting 5182*7c478bd9Sstevel@tonic-gate * the local scope, so that any repository-related errors take 5183*7c478bd9Sstevel@tonic-gate * precedence. 5184*7c478bd9Sstevel@tonic-gate */ 5185*7c478bd9Sstevel@tonic-gate if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc) == -1) { 5186*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5187*7c478bd9Sstevel@tonic-gate ret = -1; 5188*7c478bd9Sstevel@tonic-gate goto reset_args; 5189*7c478bd9Sstevel@tonic-gate } 5190*7c478bd9Sstevel@tonic-gate 5191*7c478bd9Sstevel@tonic-gate if (scope != NULL && strcmp(scope, SCF_FMRI_LOCAL_SCOPE) != 0) { 5192*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5193*7c478bd9Sstevel@tonic-gate ret = scf_set_error(SCF_ERROR_NOT_FOUND); 5194*7c478bd9Sstevel@tonic-gate goto reset_args; 5195*7c478bd9Sstevel@tonic-gate } 5196*7c478bd9Sstevel@tonic-gate 5197*7c478bd9Sstevel@tonic-gate 5198*7c478bd9Sstevel@tonic-gate if (service == NULL || last == REP_PROTOCOL_ENTITY_SCOPE) { 5199*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5200*7c478bd9Sstevel@tonic-gate return (0); 5201*7c478bd9Sstevel@tonic-gate } 5202*7c478bd9Sstevel@tonic-gate 5203*7c478bd9Sstevel@tonic-gate if (scf_scope_get_service(sc, service, svc) == -1) { 5204*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5205*7c478bd9Sstevel@tonic-gate ret = -1; 5206*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_NOT_SET); 5207*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 5208*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NOT_FOUND); 5209*7c478bd9Sstevel@tonic-gate goto reset_args; 5210*7c478bd9Sstevel@tonic-gate } 5211*7c478bd9Sstevel@tonic-gate 5212*7c478bd9Sstevel@tonic-gate if (last == REP_PROTOCOL_ENTITY_SERVICE) { 5213*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5214*7c478bd9Sstevel@tonic-gate return (0); 5215*7c478bd9Sstevel@tonic-gate } 5216*7c478bd9Sstevel@tonic-gate 5217*7c478bd9Sstevel@tonic-gate if (instance == NULL) { 5218*7c478bd9Sstevel@tonic-gate if (propertygroup == NULL || 5219*7c478bd9Sstevel@tonic-gate last == REP_PROTOCOL_ENTITY_INSTANCE) { 5220*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5221*7c478bd9Sstevel@tonic-gate return (0); 5222*7c478bd9Sstevel@tonic-gate } 5223*7c478bd9Sstevel@tonic-gate 5224*7c478bd9Sstevel@tonic-gate if (scf_service_get_pg(svc, propertygroup, pg) == -1) { 5225*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5226*7c478bd9Sstevel@tonic-gate ret = -1; 5227*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_NOT_SET); 5228*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 5229*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NOT_FOUND); 5230*7c478bd9Sstevel@tonic-gate goto reset_args; 5231*7c478bd9Sstevel@tonic-gate } 5232*7c478bd9Sstevel@tonic-gate } else { 5233*7c478bd9Sstevel@tonic-gate if (scf_service_get_instance(svc, instance, inst) == -1) { 5234*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5235*7c478bd9Sstevel@tonic-gate ret = -1; 5236*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_NOT_SET); 5237*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 5238*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NOT_FOUND); 5239*7c478bd9Sstevel@tonic-gate goto reset_args; 5240*7c478bd9Sstevel@tonic-gate } 5241*7c478bd9Sstevel@tonic-gate 5242*7c478bd9Sstevel@tonic-gate if (propertygroup == NULL || 5243*7c478bd9Sstevel@tonic-gate last == REP_PROTOCOL_ENTITY_INSTANCE) { 5244*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5245*7c478bd9Sstevel@tonic-gate return (0); 5246*7c478bd9Sstevel@tonic-gate } 5247*7c478bd9Sstevel@tonic-gate 5248*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, propertygroup, pg) == -1) { 5249*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5250*7c478bd9Sstevel@tonic-gate ret = -1; 5251*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_NOT_SET); 5252*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 5253*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NOT_FOUND); 5254*7c478bd9Sstevel@tonic-gate goto reset_args; 5255*7c478bd9Sstevel@tonic-gate } 5256*7c478bd9Sstevel@tonic-gate } 5257*7c478bd9Sstevel@tonic-gate 5258*7c478bd9Sstevel@tonic-gate if (property == NULL || last == REP_PROTOCOL_ENTITY_PROPERTYGRP) { 5259*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5260*7c478bd9Sstevel@tonic-gate return (0); 5261*7c478bd9Sstevel@tonic-gate } 5262*7c478bd9Sstevel@tonic-gate 5263*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, property, prop) == -1) { 5264*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5265*7c478bd9Sstevel@tonic-gate ret = -1; 5266*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_NOT_SET); 5267*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 5268*7c478bd9Sstevel@tonic-gate (void) scf_set_error(SCF_ERROR_NOT_FOUND); 5269*7c478bd9Sstevel@tonic-gate goto reset_args; 5270*7c478bd9Sstevel@tonic-gate } 5271*7c478bd9Sstevel@tonic-gate 5272*7c478bd9Sstevel@tonic-gate handle_rele_subhandles(h, holds); 5273*7c478bd9Sstevel@tonic-gate return (0); 5274*7c478bd9Sstevel@tonic-gate 5275*7c478bd9Sstevel@tonic-gate reset_args: 5276*7c478bd9Sstevel@tonic-gate if (sc != NULL) 5277*7c478bd9Sstevel@tonic-gate datael_reset(&sc->rd_d); 5278*7c478bd9Sstevel@tonic-gate if (svc != NULL) 5279*7c478bd9Sstevel@tonic-gate datael_reset(&svc->rd_d); 5280*7c478bd9Sstevel@tonic-gate if (inst != NULL) 5281*7c478bd9Sstevel@tonic-gate datael_reset(&inst->rd_d); 5282*7c478bd9Sstevel@tonic-gate if (pg != NULL) 5283*7c478bd9Sstevel@tonic-gate datael_reset(&pg->rd_d); 5284*7c478bd9Sstevel@tonic-gate if (prop != NULL) 5285*7c478bd9Sstevel@tonic-gate datael_reset(&prop->rd_d); 5286*7c478bd9Sstevel@tonic-gate 5287*7c478bd9Sstevel@tonic-gate return (ret); 5288*7c478bd9Sstevel@tonic-gate } 5289*7c478bd9Sstevel@tonic-gate 5290*7c478bd9Sstevel@tonic-gate /* 5291*7c478bd9Sstevel@tonic-gate * Fails with _NOT_BOUND, _CONNECTION_BROKEN, _INTERNAL (server response too 5292*7c478bd9Sstevel@tonic-gate * big, bad entity id, request not applicable to entity, name too long for 5293*7c478bd9Sstevel@tonic-gate * buffer), _NOT_SET, or _DELETED. 5294*7c478bd9Sstevel@tonic-gate */ 5295*7c478bd9Sstevel@tonic-gate ssize_t 5296*7c478bd9Sstevel@tonic-gate scf_scope_to_fmri(const scf_scope_t *scope, char *out, size_t sz) 5297*7c478bd9Sstevel@tonic-gate { 5298*7c478bd9Sstevel@tonic-gate ssize_t r, len; 5299*7c478bd9Sstevel@tonic-gate 5300*7c478bd9Sstevel@tonic-gate char tmp[REP_PROTOCOL_NAME_LEN]; 5301*7c478bd9Sstevel@tonic-gate 5302*7c478bd9Sstevel@tonic-gate r = scf_scope_get_name(scope, tmp, sizeof (tmp)); 5303*7c478bd9Sstevel@tonic-gate 5304*7c478bd9Sstevel@tonic-gate if (r <= 0) 5305*7c478bd9Sstevel@tonic-gate return (r); 5306*7c478bd9Sstevel@tonic-gate 5307*7c478bd9Sstevel@tonic-gate len = strlcpy(out, SCF_FMRI_SVC_PREFIX, sz); 5308*7c478bd9Sstevel@tonic-gate if (strcmp(tmp, SCF_FMRI_LOCAL_SCOPE) != 0) { 5309*7c478bd9Sstevel@tonic-gate if (len >= sz) 5310*7c478bd9Sstevel@tonic-gate return (len + r + sizeof (SCF_FMRI_SCOPE_SUFFIX) - 1); 5311*7c478bd9Sstevel@tonic-gate 5312*7c478bd9Sstevel@tonic-gate len = strlcat(out, tmp, sz); 5313*7c478bd9Sstevel@tonic-gate if (len >= sz) 5314*7c478bd9Sstevel@tonic-gate return (len + sizeof (SCF_FMRI_SCOPE_SUFFIX) - 1); 5315*7c478bd9Sstevel@tonic-gate len = strlcat(out, 5316*7c478bd9Sstevel@tonic-gate SCF_FMRI_SCOPE_SUFFIX SCF_FMRI_SERVICE_PREFIX, sz); 5317*7c478bd9Sstevel@tonic-gate } 5318*7c478bd9Sstevel@tonic-gate 5319*7c478bd9Sstevel@tonic-gate return (len); 5320*7c478bd9Sstevel@tonic-gate } 5321*7c478bd9Sstevel@tonic-gate 5322*7c478bd9Sstevel@tonic-gate /* 5323*7c478bd9Sstevel@tonic-gate * Fails with _NOT_BOUND, _CONNECTION_BROKEN, _INTERNAL (server response too 5324*7c478bd9Sstevel@tonic-gate * big, bad element id, bad ids, bad types, scope has no parent, request not 5325*7c478bd9Sstevel@tonic-gate * applicable to entity, name too long), _NOT_SET, _DELETED, 5326*7c478bd9Sstevel@tonic-gate */ 5327*7c478bd9Sstevel@tonic-gate ssize_t 5328*7c478bd9Sstevel@tonic-gate scf_service_to_fmri(const scf_service_t *svc, char *out, size_t sz) 5329*7c478bd9Sstevel@tonic-gate { 5330*7c478bd9Sstevel@tonic-gate scf_handle_t *h = svc->rd_d.rd_handle; 5331*7c478bd9Sstevel@tonic-gate scf_scope_t *scope = HANDLE_HOLD_SCOPE(h); 5332*7c478bd9Sstevel@tonic-gate ssize_t r, len; 5333*7c478bd9Sstevel@tonic-gate 5334*7c478bd9Sstevel@tonic-gate char tmp[REP_PROTOCOL_NAME_LEN]; 5335*7c478bd9Sstevel@tonic-gate 5336*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&svc->rd_d, &scope->rd_d); 5337*7c478bd9Sstevel@tonic-gate if (r != SCF_SUCCESS) { 5338*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SCOPE(h); 5339*7c478bd9Sstevel@tonic-gate 5340*7c478bd9Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_HANDLE_MISMATCH); 5341*7c478bd9Sstevel@tonic-gate return (-1); 5342*7c478bd9Sstevel@tonic-gate } 5343*7c478bd9Sstevel@tonic-gate if (out != NULL && sz > 0) 5344*7c478bd9Sstevel@tonic-gate len = scf_scope_to_fmri(scope, out, sz); 5345*7c478bd9Sstevel@tonic-gate else 5346*7c478bd9Sstevel@tonic-gate len = scf_scope_to_fmri(scope, tmp, 2); 5347*7c478bd9Sstevel@tonic-gate 5348*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SCOPE(h); 5349*7c478bd9Sstevel@tonic-gate 5350*7c478bd9Sstevel@tonic-gate if (len < 0) 5351*7c478bd9Sstevel@tonic-gate return (-1); 5352*7c478bd9Sstevel@tonic-gate 5353*7c478bd9Sstevel@tonic-gate if (out == NULL || len >= sz) 5354*7c478bd9Sstevel@tonic-gate len += sizeof (SCF_FMRI_SERVICE_PREFIX) - 1; 5355*7c478bd9Sstevel@tonic-gate else 5356*7c478bd9Sstevel@tonic-gate len = strlcat(out, SCF_FMRI_SERVICE_PREFIX, sz); 5357*7c478bd9Sstevel@tonic-gate 5358*7c478bd9Sstevel@tonic-gate r = scf_service_get_name(svc, tmp, sizeof (tmp)); 5359*7c478bd9Sstevel@tonic-gate if (r < 0) 5360*7c478bd9Sstevel@tonic-gate return (r); 5361*7c478bd9Sstevel@tonic-gate 5362*7c478bd9Sstevel@tonic-gate if (out == NULL || len >= sz) 5363*7c478bd9Sstevel@tonic-gate len += r; 5364*7c478bd9Sstevel@tonic-gate else 5365*7c478bd9Sstevel@tonic-gate len = strlcat(out, tmp, sz); 5366*7c478bd9Sstevel@tonic-gate 5367*7c478bd9Sstevel@tonic-gate return (len); 5368*7c478bd9Sstevel@tonic-gate } 5369*7c478bd9Sstevel@tonic-gate 5370*7c478bd9Sstevel@tonic-gate ssize_t 5371*7c478bd9Sstevel@tonic-gate scf_instance_to_fmri(const scf_instance_t *inst, char *out, size_t sz) 5372*7c478bd9Sstevel@tonic-gate { 5373*7c478bd9Sstevel@tonic-gate scf_handle_t *h = inst->rd_d.rd_handle; 5374*7c478bd9Sstevel@tonic-gate scf_service_t *svc = HANDLE_HOLD_SERVICE(h); 5375*7c478bd9Sstevel@tonic-gate ssize_t r, len; 5376*7c478bd9Sstevel@tonic-gate 5377*7c478bd9Sstevel@tonic-gate char tmp[REP_PROTOCOL_NAME_LEN]; 5378*7c478bd9Sstevel@tonic-gate 5379*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&inst->rd_d, &svc->rd_d); 5380*7c478bd9Sstevel@tonic-gate if (r != SCF_SUCCESS) { 5381*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SERVICE(h); 5382*7c478bd9Sstevel@tonic-gate return (-1); 5383*7c478bd9Sstevel@tonic-gate } 5384*7c478bd9Sstevel@tonic-gate 5385*7c478bd9Sstevel@tonic-gate len = scf_service_to_fmri(svc, out, sz); 5386*7c478bd9Sstevel@tonic-gate 5387*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SERVICE(h); 5388*7c478bd9Sstevel@tonic-gate 5389*7c478bd9Sstevel@tonic-gate if (len < 0) 5390*7c478bd9Sstevel@tonic-gate return (len); 5391*7c478bd9Sstevel@tonic-gate 5392*7c478bd9Sstevel@tonic-gate if (len >= sz) 5393*7c478bd9Sstevel@tonic-gate len += sizeof (SCF_FMRI_INSTANCE_PREFIX) - 1; 5394*7c478bd9Sstevel@tonic-gate else 5395*7c478bd9Sstevel@tonic-gate len = strlcat(out, SCF_FMRI_INSTANCE_PREFIX, sz); 5396*7c478bd9Sstevel@tonic-gate 5397*7c478bd9Sstevel@tonic-gate r = scf_instance_get_name(inst, tmp, sizeof (tmp)); 5398*7c478bd9Sstevel@tonic-gate if (r < 0) 5399*7c478bd9Sstevel@tonic-gate return (r); 5400*7c478bd9Sstevel@tonic-gate 5401*7c478bd9Sstevel@tonic-gate if (len >= sz) 5402*7c478bd9Sstevel@tonic-gate len += r; 5403*7c478bd9Sstevel@tonic-gate else 5404*7c478bd9Sstevel@tonic-gate len = strlcat(out, tmp, sz); 5405*7c478bd9Sstevel@tonic-gate 5406*7c478bd9Sstevel@tonic-gate return (len); 5407*7c478bd9Sstevel@tonic-gate } 5408*7c478bd9Sstevel@tonic-gate 5409*7c478bd9Sstevel@tonic-gate ssize_t 5410*7c478bd9Sstevel@tonic-gate scf_pg_to_fmri(const scf_propertygroup_t *pg, char *out, size_t sz) 5411*7c478bd9Sstevel@tonic-gate { 5412*7c478bd9Sstevel@tonic-gate scf_handle_t *h = pg->rd_d.rd_handle; 5413*7c478bd9Sstevel@tonic-gate 5414*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_parent_type request; 5415*7c478bd9Sstevel@tonic-gate struct rep_protocol_integer_response response; 5416*7c478bd9Sstevel@tonic-gate 5417*7c478bd9Sstevel@tonic-gate char tmp[REP_PROTOCOL_NAME_LEN]; 5418*7c478bd9Sstevel@tonic-gate ssize_t len, r; 5419*7c478bd9Sstevel@tonic-gate 5420*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 5421*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_ENTITY_PARENT_TYPE; 5422*7c478bd9Sstevel@tonic-gate request.rpr_entityid = pg->rd_d.rd_entity; 5423*7c478bd9Sstevel@tonic-gate 5424*7c478bd9Sstevel@tonic-gate datael_finish_reset(&pg->rd_d); 5425*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 5426*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 5427*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 5428*7c478bd9Sstevel@tonic-gate 5429*7c478bd9Sstevel@tonic-gate if (r < 0) 5430*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 5431*7c478bd9Sstevel@tonic-gate 5432*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS || 5433*7c478bd9Sstevel@tonic-gate r < sizeof (response)) { 5434*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 5435*7c478bd9Sstevel@tonic-gate } 5436*7c478bd9Sstevel@tonic-gate 5437*7c478bd9Sstevel@tonic-gate switch (response.rpr_value) { 5438*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SERVICE: { 5439*7c478bd9Sstevel@tonic-gate scf_service_t *svc; 5440*7c478bd9Sstevel@tonic-gate 5441*7c478bd9Sstevel@tonic-gate svc = HANDLE_HOLD_SERVICE(h); 5442*7c478bd9Sstevel@tonic-gate 5443*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&pg->rd_d, &svc->rd_d); 5444*7c478bd9Sstevel@tonic-gate 5445*7c478bd9Sstevel@tonic-gate if (r == SCF_SUCCESS) 5446*7c478bd9Sstevel@tonic-gate len = scf_service_to_fmri(svc, out, sz); 5447*7c478bd9Sstevel@tonic-gate 5448*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SERVICE(h); 5449*7c478bd9Sstevel@tonic-gate break; 5450*7c478bd9Sstevel@tonic-gate } 5451*7c478bd9Sstevel@tonic-gate 5452*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_INSTANCE: { 5453*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 5454*7c478bd9Sstevel@tonic-gate 5455*7c478bd9Sstevel@tonic-gate inst = HANDLE_HOLD_INSTANCE(h); 5456*7c478bd9Sstevel@tonic-gate 5457*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&pg->rd_d, &inst->rd_d); 5458*7c478bd9Sstevel@tonic-gate 5459*7c478bd9Sstevel@tonic-gate if (r == SCF_SUCCESS) 5460*7c478bd9Sstevel@tonic-gate len = scf_instance_to_fmri(inst, out, sz); 5461*7c478bd9Sstevel@tonic-gate 5462*7c478bd9Sstevel@tonic-gate HANDLE_RELE_INSTANCE(h); 5463*7c478bd9Sstevel@tonic-gate break; 5464*7c478bd9Sstevel@tonic-gate } 5465*7c478bd9Sstevel@tonic-gate 5466*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPLEVEL: { 5467*7c478bd9Sstevel@tonic-gate scf_instance_t *inst = HANDLE_HOLD_INSTANCE(h); 5468*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap = HANDLE_HOLD_SNAPSHOT(h); 5469*7c478bd9Sstevel@tonic-gate scf_snaplevel_t *level = HANDLE_HOLD_SNAPLVL(h); 5470*7c478bd9Sstevel@tonic-gate 5471*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&pg->rd_d, &level->rd_d); 5472*7c478bd9Sstevel@tonic-gate 5473*7c478bd9Sstevel@tonic-gate if (r == SCF_SUCCESS) 5474*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&level->rd_d, &snap->rd_d); 5475*7c478bd9Sstevel@tonic-gate 5476*7c478bd9Sstevel@tonic-gate if (r == SCF_SUCCESS) 5477*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&snap->rd_d, &inst->rd_d); 5478*7c478bd9Sstevel@tonic-gate 5479*7c478bd9Sstevel@tonic-gate if (r == SCF_SUCCESS) 5480*7c478bd9Sstevel@tonic-gate len = scf_instance_to_fmri(inst, out, sz); 5481*7c478bd9Sstevel@tonic-gate 5482*7c478bd9Sstevel@tonic-gate HANDLE_RELE_INSTANCE(h); 5483*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SNAPSHOT(h); 5484*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SNAPLVL(h); 5485*7c478bd9Sstevel@tonic-gate break; 5486*7c478bd9Sstevel@tonic-gate } 5487*7c478bd9Sstevel@tonic-gate 5488*7c478bd9Sstevel@tonic-gate default: 5489*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INTERNAL)); 5490*7c478bd9Sstevel@tonic-gate } 5491*7c478bd9Sstevel@tonic-gate 5492*7c478bd9Sstevel@tonic-gate if (r != SCF_SUCCESS) 5493*7c478bd9Sstevel@tonic-gate return (r); 5494*7c478bd9Sstevel@tonic-gate 5495*7c478bd9Sstevel@tonic-gate if (len >= sz) 5496*7c478bd9Sstevel@tonic-gate len += sizeof (SCF_FMRI_PROPERTYGRP_PREFIX) - 1; 5497*7c478bd9Sstevel@tonic-gate else 5498*7c478bd9Sstevel@tonic-gate len = strlcat(out, SCF_FMRI_PROPERTYGRP_PREFIX, sz); 5499*7c478bd9Sstevel@tonic-gate 5500*7c478bd9Sstevel@tonic-gate r = scf_pg_get_name(pg, tmp, sizeof (tmp)); 5501*7c478bd9Sstevel@tonic-gate 5502*7c478bd9Sstevel@tonic-gate if (r < 0) 5503*7c478bd9Sstevel@tonic-gate return (r); 5504*7c478bd9Sstevel@tonic-gate 5505*7c478bd9Sstevel@tonic-gate if (len >= sz) 5506*7c478bd9Sstevel@tonic-gate len += r; 5507*7c478bd9Sstevel@tonic-gate else 5508*7c478bd9Sstevel@tonic-gate len = strlcat(out, tmp, sz); 5509*7c478bd9Sstevel@tonic-gate 5510*7c478bd9Sstevel@tonic-gate return (len); 5511*7c478bd9Sstevel@tonic-gate } 5512*7c478bd9Sstevel@tonic-gate 5513*7c478bd9Sstevel@tonic-gate ssize_t 5514*7c478bd9Sstevel@tonic-gate scf_property_to_fmri(const scf_property_t *prop, char *out, size_t sz) 5515*7c478bd9Sstevel@tonic-gate { 5516*7c478bd9Sstevel@tonic-gate scf_handle_t *h = prop->rd_d.rd_handle; 5517*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = HANDLE_HOLD_PG(h); 5518*7c478bd9Sstevel@tonic-gate 5519*7c478bd9Sstevel@tonic-gate char tmp[REP_PROTOCOL_NAME_LEN]; 5520*7c478bd9Sstevel@tonic-gate ssize_t len; 5521*7c478bd9Sstevel@tonic-gate int r; 5522*7c478bd9Sstevel@tonic-gate 5523*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&prop->rd_d, &pg->rd_d); 5524*7c478bd9Sstevel@tonic-gate if (r != SCF_SUCCESS) { 5525*7c478bd9Sstevel@tonic-gate HANDLE_RELE_PG(h); 5526*7c478bd9Sstevel@tonic-gate return (-1); 5527*7c478bd9Sstevel@tonic-gate } 5528*7c478bd9Sstevel@tonic-gate 5529*7c478bd9Sstevel@tonic-gate len = scf_pg_to_fmri(pg, out, sz); 5530*7c478bd9Sstevel@tonic-gate 5531*7c478bd9Sstevel@tonic-gate HANDLE_RELE_PG(h); 5532*7c478bd9Sstevel@tonic-gate 5533*7c478bd9Sstevel@tonic-gate if (len >= sz) 5534*7c478bd9Sstevel@tonic-gate len += sizeof (SCF_FMRI_PROPERTY_PREFIX) - 1; 5535*7c478bd9Sstevel@tonic-gate else 5536*7c478bd9Sstevel@tonic-gate len = strlcat(out, SCF_FMRI_PROPERTY_PREFIX, sz); 5537*7c478bd9Sstevel@tonic-gate 5538*7c478bd9Sstevel@tonic-gate r = scf_property_get_name(prop, tmp, sizeof (tmp)); 5539*7c478bd9Sstevel@tonic-gate 5540*7c478bd9Sstevel@tonic-gate if (r < 0) 5541*7c478bd9Sstevel@tonic-gate return (r); 5542*7c478bd9Sstevel@tonic-gate 5543*7c478bd9Sstevel@tonic-gate if (len >= sz) 5544*7c478bd9Sstevel@tonic-gate len += r; 5545*7c478bd9Sstevel@tonic-gate else 5546*7c478bd9Sstevel@tonic-gate len = strlcat(out, tmp, sz); 5547*7c478bd9Sstevel@tonic-gate 5548*7c478bd9Sstevel@tonic-gate return (len); 5549*7c478bd9Sstevel@tonic-gate } 5550*7c478bd9Sstevel@tonic-gate 5551*7c478bd9Sstevel@tonic-gate int 5552*7c478bd9Sstevel@tonic-gate scf_pg_get_underlying_pg(const scf_propertygroup_t *pg, 5553*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *out) 5554*7c478bd9Sstevel@tonic-gate { 5555*7c478bd9Sstevel@tonic-gate scf_handle_t *h = pg->rd_d.rd_handle; 5556*7c478bd9Sstevel@tonic-gate scf_service_t *svc; 5557*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 5558*7c478bd9Sstevel@tonic-gate 5559*7c478bd9Sstevel@tonic-gate char me[REP_PROTOCOL_NAME_LEN]; 5560*7c478bd9Sstevel@tonic-gate int r; 5561*7c478bd9Sstevel@tonic-gate 5562*7c478bd9Sstevel@tonic-gate if (h != out->rd_d.rd_handle) 5563*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_HANDLE_MISMATCH)); 5564*7c478bd9Sstevel@tonic-gate 5565*7c478bd9Sstevel@tonic-gate r = scf_pg_get_name(pg, me, sizeof (me)); 5566*7c478bd9Sstevel@tonic-gate 5567*7c478bd9Sstevel@tonic-gate if (r < 0) 5568*7c478bd9Sstevel@tonic-gate return (r); 5569*7c478bd9Sstevel@tonic-gate 5570*7c478bd9Sstevel@tonic-gate svc = HANDLE_HOLD_SERVICE(h); 5571*7c478bd9Sstevel@tonic-gate inst = HANDLE_HOLD_INSTANCE(h); 5572*7c478bd9Sstevel@tonic-gate 5573*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&pg->rd_d, &inst->rd_d); 5574*7c478bd9Sstevel@tonic-gate 5575*7c478bd9Sstevel@tonic-gate if (r == SCF_SUCCESS) { 5576*7c478bd9Sstevel@tonic-gate r = datael_get_parent(&inst->rd_d, &svc->rd_d); 5577*7c478bd9Sstevel@tonic-gate if (r != SCF_SUCCESS) { 5578*7c478bd9Sstevel@tonic-gate goto out; 5579*7c478bd9Sstevel@tonic-gate } 5580*7c478bd9Sstevel@tonic-gate r = scf_service_get_pg(svc, me, out); 5581*7c478bd9Sstevel@tonic-gate } else { 5582*7c478bd9Sstevel@tonic-gate r = scf_set_error(SCF_ERROR_NOT_FOUND); 5583*7c478bd9Sstevel@tonic-gate } 5584*7c478bd9Sstevel@tonic-gate 5585*7c478bd9Sstevel@tonic-gate out: 5586*7c478bd9Sstevel@tonic-gate HANDLE_RELE_SERVICE(h); 5587*7c478bd9Sstevel@tonic-gate HANDLE_RELE_INSTANCE(h); 5588*7c478bd9Sstevel@tonic-gate return (r); 5589*7c478bd9Sstevel@tonic-gate } 5590*7c478bd9Sstevel@tonic-gate 5591*7c478bd9Sstevel@tonic-gate #define LEGACY_SCHEME "lrc:" 5592*7c478bd9Sstevel@tonic-gate #define LEGACY_UNKNOWN "unknown" 5593*7c478bd9Sstevel@tonic-gate 5594*7c478bd9Sstevel@tonic-gate /* 5595*7c478bd9Sstevel@tonic-gate * Implementation of scf_walk_fmri() 5596*7c478bd9Sstevel@tonic-gate * 5597*7c478bd9Sstevel@tonic-gate * This is a little tricky due to the many-to-many relationship between patterns 5598*7c478bd9Sstevel@tonic-gate * and matches. We need to be able to satisfy the following requirements: 5599*7c478bd9Sstevel@tonic-gate * 5600*7c478bd9Sstevel@tonic-gate * 1) Detect patterns which match more than one FMRI, and be able to 5601*7c478bd9Sstevel@tonic-gate * report which FMRIs have been matched. 5602*7c478bd9Sstevel@tonic-gate * 2) Detect patterns which have not matched any FMRIs 5603*7c478bd9Sstevel@tonic-gate * 3) Visit each matching FMRI exactly once across all patterns 5604*7c478bd9Sstevel@tonic-gate * 4) Ignore FMRIs which have only been matched due to multiply-matching 5605*7c478bd9Sstevel@tonic-gate * patterns. 5606*7c478bd9Sstevel@tonic-gate * 5607*7c478bd9Sstevel@tonic-gate * We maintain an array of scf_pattern_t structures, one for each argument, and 5608*7c478bd9Sstevel@tonic-gate * maintain a linked list of scf_match_t structures for each one. We first 5609*7c478bd9Sstevel@tonic-gate * qualify each pattern's type: 5610*7c478bd9Sstevel@tonic-gate * 5611*7c478bd9Sstevel@tonic-gate * PATTERN_INVALID The argument is invalid (too long). 5612*7c478bd9Sstevel@tonic-gate * 5613*7c478bd9Sstevel@tonic-gate * PATTERN_EXACT The pattern is a complete FMRI. The list of 5614*7c478bd9Sstevel@tonic-gate * matches contains only a single entry. 5615*7c478bd9Sstevel@tonic-gate * 5616*7c478bd9Sstevel@tonic-gate * PATTERN_GLOB The pattern will be matched against all 5617*7c478bd9Sstevel@tonic-gate * FMRIs via fnmatch() in the second phase. 5618*7c478bd9Sstevel@tonic-gate * Matches will be added to the pattern's list 5619*7c478bd9Sstevel@tonic-gate * as they are found. 5620*7c478bd9Sstevel@tonic-gate * 5621*7c478bd9Sstevel@tonic-gate * PATTERN_PARTIAL Everything else. We will assume that this is 5622*7c478bd9Sstevel@tonic-gate * an abbreviated FMRI, and match according to 5623*7c478bd9Sstevel@tonic-gate * our abbreviated FMRI rules. Matches will be 5624*7c478bd9Sstevel@tonic-gate * added to the pattern's list as they are found. 5625*7c478bd9Sstevel@tonic-gate * 5626*7c478bd9Sstevel@tonic-gate * The first pass searches for arguments that are complete FMRIs. These are 5627*7c478bd9Sstevel@tonic-gate * classified as EXACT patterns and do not necessitate searching the entire 5628*7c478bd9Sstevel@tonic-gate * tree. 5629*7c478bd9Sstevel@tonic-gate * 5630*7c478bd9Sstevel@tonic-gate * Once this is done, if we have any GLOB or PARTIAL patterns (or if no 5631*7c478bd9Sstevel@tonic-gate * arguments were given), we iterate over all services and instances in the 5632*7c478bd9Sstevel@tonic-gate * repository, looking for matches. 5633*7c478bd9Sstevel@tonic-gate * 5634*7c478bd9Sstevel@tonic-gate * When a match is found, we add the match to the pattern's list. We also enter 5635*7c478bd9Sstevel@tonic-gate * the match into a hash table, resulting in something like this: 5636*7c478bd9Sstevel@tonic-gate * 5637*7c478bd9Sstevel@tonic-gate * scf_pattern_t scf_match_t 5638*7c478bd9Sstevel@tonic-gate * +---------------+ +-------+ +-------+ 5639*7c478bd9Sstevel@tonic-gate * | pattern 'foo' |----->| match |---->| match | 5640*7c478bd9Sstevel@tonic-gate * +---------------+ +-------+ +-------+ 5641*7c478bd9Sstevel@tonic-gate * | | 5642*7c478bd9Sstevel@tonic-gate * scf_match_key_t | | 5643*7c478bd9Sstevel@tonic-gate * +--------------+ | | 5644*7c478bd9Sstevel@tonic-gate * | FMRI bar/foo |<----+ | 5645*7c478bd9Sstevel@tonic-gate * +--------------+ | 5646*7c478bd9Sstevel@tonic-gate * | FMRI baz/foo |<------------------+ 5647*7c478bd9Sstevel@tonic-gate * +--------------+ 5648*7c478bd9Sstevel@tonic-gate * 5649*7c478bd9Sstevel@tonic-gate * Once we have all of this set up, we do one pass to report patterns matching 5650*7c478bd9Sstevel@tonic-gate * multiple FMRIs (if SCF_WALK_MULTIPLE is not set) and patterns for which no 5651*7c478bd9Sstevel@tonic-gate * match was found. 5652*7c478bd9Sstevel@tonic-gate * 5653*7c478bd9Sstevel@tonic-gate * Finally, we walk through all valid patterns, and for each match, if we 5654*7c478bd9Sstevel@tonic-gate * haven't already seen the match (as recorded in the hash table), then we 5655*7c478bd9Sstevel@tonic-gate * execute the callback. 5656*7c478bd9Sstevel@tonic-gate */ 5657*7c478bd9Sstevel@tonic-gate 5658*7c478bd9Sstevel@tonic-gate struct scf_matchkey; 5659*7c478bd9Sstevel@tonic-gate struct scf_match; 5660*7c478bd9Sstevel@tonic-gate 5661*7c478bd9Sstevel@tonic-gate /* 5662*7c478bd9Sstevel@tonic-gate * scf_pattern_t 5663*7c478bd9Sstevel@tonic-gate */ 5664*7c478bd9Sstevel@tonic-gate typedef struct scf_pattern { 5665*7c478bd9Sstevel@tonic-gate enum { 5666*7c478bd9Sstevel@tonic-gate PATTERN_INVALID, /* Uninitialized state */ 5667*7c478bd9Sstevel@tonic-gate PATTERN_EXACT, 5668*7c478bd9Sstevel@tonic-gate PATTERN_GLOB, 5669*7c478bd9Sstevel@tonic-gate PATTERN_PARTIAL 5670*7c478bd9Sstevel@tonic-gate } sp_type; 5671*7c478bd9Sstevel@tonic-gate char *sp_arg; /* Original argument */ 5672*7c478bd9Sstevel@tonic-gate struct scf_match *sp_matches; /* List of matches */ 5673*7c478bd9Sstevel@tonic-gate int sp_matchcount; /* # of matches */ 5674*7c478bd9Sstevel@tonic-gate } scf_pattern_t; 5675*7c478bd9Sstevel@tonic-gate 5676*7c478bd9Sstevel@tonic-gate /* 5677*7c478bd9Sstevel@tonic-gate * scf_matchkey_t 5678*7c478bd9Sstevel@tonic-gate */ 5679*7c478bd9Sstevel@tonic-gate typedef struct scf_matchkey { 5680*7c478bd9Sstevel@tonic-gate char *sk_fmri; /* Matching FMRI */ 5681*7c478bd9Sstevel@tonic-gate char *sk_legacy; /* Legacy name */ 5682*7c478bd9Sstevel@tonic-gate int sk_seen; /* If we've been seen */ 5683*7c478bd9Sstevel@tonic-gate struct scf_matchkey *sk_next; /* Next in hash chain */ 5684*7c478bd9Sstevel@tonic-gate } scf_matchkey_t; 5685*7c478bd9Sstevel@tonic-gate 5686*7c478bd9Sstevel@tonic-gate /* 5687*7c478bd9Sstevel@tonic-gate * scf_match_t 5688*7c478bd9Sstevel@tonic-gate */ 5689*7c478bd9Sstevel@tonic-gate typedef struct scf_match { 5690*7c478bd9Sstevel@tonic-gate scf_matchkey_t *sm_key; 5691*7c478bd9Sstevel@tonic-gate struct scf_match *sm_next; 5692*7c478bd9Sstevel@tonic-gate } scf_match_t; 5693*7c478bd9Sstevel@tonic-gate 5694*7c478bd9Sstevel@tonic-gate #define WALK_HTABLE_SIZE 123 5695*7c478bd9Sstevel@tonic-gate 5696*7c478bd9Sstevel@tonic-gate /* 5697*7c478bd9Sstevel@tonic-gate * scf_get_key() 5698*7c478bd9Sstevel@tonic-gate * 5699*7c478bd9Sstevel@tonic-gate * Given an FMRI and a hash table, returns the scf_matchkey_t corresponding to 5700*7c478bd9Sstevel@tonic-gate * this FMRI. If the FMRI does not exist, it is added to the hash table. If a 5701*7c478bd9Sstevel@tonic-gate * new entry cannot be allocated due to lack of memory, NULL is returned. 5702*7c478bd9Sstevel@tonic-gate */ 5703*7c478bd9Sstevel@tonic-gate static scf_matchkey_t * 5704*7c478bd9Sstevel@tonic-gate scf_get_key(scf_matchkey_t **htable, const char *fmri, const char *legacy) 5705*7c478bd9Sstevel@tonic-gate { 5706*7c478bd9Sstevel@tonic-gate uint_t h = 0, g; 5707*7c478bd9Sstevel@tonic-gate const char *p, *k; 5708*7c478bd9Sstevel@tonic-gate scf_matchkey_t *key; 5709*7c478bd9Sstevel@tonic-gate 5710*7c478bd9Sstevel@tonic-gate k = strstr(fmri, ":/"); 5711*7c478bd9Sstevel@tonic-gate assert(k != NULL); 5712*7c478bd9Sstevel@tonic-gate k += 2; 5713*7c478bd9Sstevel@tonic-gate 5714*7c478bd9Sstevel@tonic-gate /* 5715*7c478bd9Sstevel@tonic-gate * Generic hash function from uts/common/os/modhash.c. 5716*7c478bd9Sstevel@tonic-gate */ 5717*7c478bd9Sstevel@tonic-gate for (p = k; *p != '\0'; ++p) { 5718*7c478bd9Sstevel@tonic-gate h = (h << 4) + *p; 5719*7c478bd9Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) { 5720*7c478bd9Sstevel@tonic-gate h ^= (g >> 24); 5721*7c478bd9Sstevel@tonic-gate h ^= g; 5722*7c478bd9Sstevel@tonic-gate } 5723*7c478bd9Sstevel@tonic-gate } 5724*7c478bd9Sstevel@tonic-gate 5725*7c478bd9Sstevel@tonic-gate h %= WALK_HTABLE_SIZE; 5726*7c478bd9Sstevel@tonic-gate 5727*7c478bd9Sstevel@tonic-gate /* 5728*7c478bd9Sstevel@tonic-gate * Search for an existing key 5729*7c478bd9Sstevel@tonic-gate */ 5730*7c478bd9Sstevel@tonic-gate for (key = htable[h]; key != NULL; key = key->sk_next) { 5731*7c478bd9Sstevel@tonic-gate if (strcmp(key->sk_fmri, fmri) == 0) 5732*7c478bd9Sstevel@tonic-gate return (key); 5733*7c478bd9Sstevel@tonic-gate } 5734*7c478bd9Sstevel@tonic-gate 5735*7c478bd9Sstevel@tonic-gate if ((key = calloc(sizeof (scf_matchkey_t), 1)) == NULL) 5736*7c478bd9Sstevel@tonic-gate return (NULL); 5737*7c478bd9Sstevel@tonic-gate 5738*7c478bd9Sstevel@tonic-gate /* 5739*7c478bd9Sstevel@tonic-gate * Add new key to hash table. 5740*7c478bd9Sstevel@tonic-gate */ 5741*7c478bd9Sstevel@tonic-gate if ((key->sk_fmri = strdup(fmri)) == NULL) { 5742*7c478bd9Sstevel@tonic-gate free(key); 5743*7c478bd9Sstevel@tonic-gate return (NULL); 5744*7c478bd9Sstevel@tonic-gate } 5745*7c478bd9Sstevel@tonic-gate 5746*7c478bd9Sstevel@tonic-gate if (legacy == NULL) { 5747*7c478bd9Sstevel@tonic-gate key->sk_legacy = NULL; 5748*7c478bd9Sstevel@tonic-gate } else if ((key->sk_legacy = strdup(legacy)) == NULL) { 5749*7c478bd9Sstevel@tonic-gate free(key->sk_fmri); 5750*7c478bd9Sstevel@tonic-gate free(key); 5751*7c478bd9Sstevel@tonic-gate return (NULL); 5752*7c478bd9Sstevel@tonic-gate } 5753*7c478bd9Sstevel@tonic-gate 5754*7c478bd9Sstevel@tonic-gate key->sk_next = htable[h]; 5755*7c478bd9Sstevel@tonic-gate htable[h] = key; 5756*7c478bd9Sstevel@tonic-gate 5757*7c478bd9Sstevel@tonic-gate return (key); 5758*7c478bd9Sstevel@tonic-gate } 5759*7c478bd9Sstevel@tonic-gate 5760*7c478bd9Sstevel@tonic-gate /* 5761*7c478bd9Sstevel@tonic-gate * Given an FMRI, insert it into the pattern's list appropriately. 5762*7c478bd9Sstevel@tonic-gate * svc_explicit indicates whether matching services should take 5763*7c478bd9Sstevel@tonic-gate * precedence over matching instances. 5764*7c478bd9Sstevel@tonic-gate */ 5765*7c478bd9Sstevel@tonic-gate static scf_error_t 5766*7c478bd9Sstevel@tonic-gate scf_add_match(scf_matchkey_t **htable, const char *fmri, const char *legacy, 5767*7c478bd9Sstevel@tonic-gate scf_pattern_t *pattern, int svc_explicit) 5768*7c478bd9Sstevel@tonic-gate { 5769*7c478bd9Sstevel@tonic-gate scf_match_t *match; 5770*7c478bd9Sstevel@tonic-gate 5771*7c478bd9Sstevel@tonic-gate /* 5772*7c478bd9Sstevel@tonic-gate * If svc_explicit is set, enforce the constaint that matching 5773*7c478bd9Sstevel@tonic-gate * instances take precedence over matching services. Otherwise, 5774*7c478bd9Sstevel@tonic-gate * matching services take precedence over matching instances. 5775*7c478bd9Sstevel@tonic-gate */ 5776*7c478bd9Sstevel@tonic-gate if (svc_explicit) { 5777*7c478bd9Sstevel@tonic-gate scf_match_t *next, *prev; 5778*7c478bd9Sstevel@tonic-gate /* 5779*7c478bd9Sstevel@tonic-gate * If we match an instance, check to see if we must remove 5780*7c478bd9Sstevel@tonic-gate * any matching services (for SCF_WALK_EXPLICIT). 5781*7c478bd9Sstevel@tonic-gate */ 5782*7c478bd9Sstevel@tonic-gate for (prev = match = pattern->sp_matches; match != NULL; 5783*7c478bd9Sstevel@tonic-gate match = next) { 5784*7c478bd9Sstevel@tonic-gate size_t len = strlen(match->sm_key->sk_fmri); 5785*7c478bd9Sstevel@tonic-gate next = match->sm_next; 5786*7c478bd9Sstevel@tonic-gate if (strncmp(match->sm_key->sk_fmri, fmri, len) == 0 && 5787*7c478bd9Sstevel@tonic-gate fmri[len] == ':') { 5788*7c478bd9Sstevel@tonic-gate if (prev == match) 5789*7c478bd9Sstevel@tonic-gate pattern->sp_matches = match->sm_next; 5790*7c478bd9Sstevel@tonic-gate else 5791*7c478bd9Sstevel@tonic-gate prev->sm_next = match->sm_next; 5792*7c478bd9Sstevel@tonic-gate pattern->sp_matchcount--; 5793*7c478bd9Sstevel@tonic-gate free(match); 5794*7c478bd9Sstevel@tonic-gate } else 5795*7c478bd9Sstevel@tonic-gate prev = match; 5796*7c478bd9Sstevel@tonic-gate } 5797*7c478bd9Sstevel@tonic-gate } else { 5798*7c478bd9Sstevel@tonic-gate /* 5799*7c478bd9Sstevel@tonic-gate * If we've matched a service don't add any instances (for 5800*7c478bd9Sstevel@tonic-gate * SCF_WALK_SERVICE). 5801*7c478bd9Sstevel@tonic-gate */ 5802*7c478bd9Sstevel@tonic-gate for (match = pattern->sp_matches; match != NULL; 5803*7c478bd9Sstevel@tonic-gate match = match->sm_next) { 5804*7c478bd9Sstevel@tonic-gate size_t len = strlen(match->sm_key->sk_fmri); 5805*7c478bd9Sstevel@tonic-gate if (strncmp(match->sm_key->sk_fmri, fmri, len) == 0 && 5806*7c478bd9Sstevel@tonic-gate fmri[len] == ':') 5807*7c478bd9Sstevel@tonic-gate return (0); 5808*7c478bd9Sstevel@tonic-gate } 5809*7c478bd9Sstevel@tonic-gate } 5810*7c478bd9Sstevel@tonic-gate 5811*7c478bd9Sstevel@tonic-gate if ((match = malloc(sizeof (scf_match_t))) == NULL) 5812*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_NO_MEMORY); 5813*7c478bd9Sstevel@tonic-gate 5814*7c478bd9Sstevel@tonic-gate if ((match->sm_key = scf_get_key(htable, fmri, legacy)) == NULL) { 5815*7c478bd9Sstevel@tonic-gate free(match); 5816*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_NO_MEMORY); 5817*7c478bd9Sstevel@tonic-gate } 5818*7c478bd9Sstevel@tonic-gate 5819*7c478bd9Sstevel@tonic-gate match->sm_next = pattern->sp_matches; 5820*7c478bd9Sstevel@tonic-gate pattern->sp_matches = match; 5821*7c478bd9Sstevel@tonic-gate pattern->sp_matchcount++; 5822*7c478bd9Sstevel@tonic-gate 5823*7c478bd9Sstevel@tonic-gate return (0); 5824*7c478bd9Sstevel@tonic-gate } 5825*7c478bd9Sstevel@tonic-gate 5826*7c478bd9Sstevel@tonic-gate /* 5827*7c478bd9Sstevel@tonic-gate * Returns 1 if the fmri matches the given pattern, 0 otherwise. 5828*7c478bd9Sstevel@tonic-gate */ 5829*7c478bd9Sstevel@tonic-gate static int 5830*7c478bd9Sstevel@tonic-gate scf_cmp_pattern(char *fmri, scf_pattern_t *pattern) 5831*7c478bd9Sstevel@tonic-gate { 5832*7c478bd9Sstevel@tonic-gate char *tmp; 5833*7c478bd9Sstevel@tonic-gate 5834*7c478bd9Sstevel@tonic-gate if (pattern->sp_type == PATTERN_GLOB) { 5835*7c478bd9Sstevel@tonic-gate if (fnmatch(pattern->sp_arg, fmri, 0) == 0) 5836*7c478bd9Sstevel@tonic-gate return (1); 5837*7c478bd9Sstevel@tonic-gate } else if (pattern->sp_type == PATTERN_PARTIAL && 5838*7c478bd9Sstevel@tonic-gate (tmp = strstr(fmri, pattern->sp_arg)) != NULL) { 5839*7c478bd9Sstevel@tonic-gate /* 5840*7c478bd9Sstevel@tonic-gate * We only allow partial matches anchored on the end of 5841*7c478bd9Sstevel@tonic-gate * a service or instance, and beginning on an element 5842*7c478bd9Sstevel@tonic-gate * boundary. 5843*7c478bd9Sstevel@tonic-gate */ 5844*7c478bd9Sstevel@tonic-gate if (tmp != fmri && tmp[-1] != '/' && tmp[-1] != ':' && 5845*7c478bd9Sstevel@tonic-gate tmp[0] != ':') 5846*7c478bd9Sstevel@tonic-gate return (0); 5847*7c478bd9Sstevel@tonic-gate tmp += strlen(pattern->sp_arg); 5848*7c478bd9Sstevel@tonic-gate if (tmp != fmri + strlen(fmri) && tmp[0] != ':' && 5849*7c478bd9Sstevel@tonic-gate tmp[-1] != ':') 5850*7c478bd9Sstevel@tonic-gate return (0); 5851*7c478bd9Sstevel@tonic-gate 5852*7c478bd9Sstevel@tonic-gate /* 5853*7c478bd9Sstevel@tonic-gate * If the user has supplied a short pattern that matches 5854*7c478bd9Sstevel@tonic-gate * 'svc:/' or 'lrc:/', ignore it. 5855*7c478bd9Sstevel@tonic-gate */ 5856*7c478bd9Sstevel@tonic-gate if (tmp <= fmri + 4) 5857*7c478bd9Sstevel@tonic-gate return (0); 5858*7c478bd9Sstevel@tonic-gate 5859*7c478bd9Sstevel@tonic-gate return (1); 5860*7c478bd9Sstevel@tonic-gate } 5861*7c478bd9Sstevel@tonic-gate 5862*7c478bd9Sstevel@tonic-gate return (0); 5863*7c478bd9Sstevel@tonic-gate } 5864*7c478bd9Sstevel@tonic-gate 5865*7c478bd9Sstevel@tonic-gate /* 5866*7c478bd9Sstevel@tonic-gate * Attempts to match the given FMRI against a set of patterns, keeping track of 5867*7c478bd9Sstevel@tonic-gate * the results. 5868*7c478bd9Sstevel@tonic-gate */ 5869*7c478bd9Sstevel@tonic-gate static scf_error_t 5870*7c478bd9Sstevel@tonic-gate scf_pattern_match(scf_matchkey_t **htable, char *fmri, const char *legacy, 5871*7c478bd9Sstevel@tonic-gate int npattern, scf_pattern_t *pattern, int svc_explicit) 5872*7c478bd9Sstevel@tonic-gate { 5873*7c478bd9Sstevel@tonic-gate int i; 5874*7c478bd9Sstevel@tonic-gate int ret = 0; 5875*7c478bd9Sstevel@tonic-gate 5876*7c478bd9Sstevel@tonic-gate for (i = 0; i < npattern; i++) { 5877*7c478bd9Sstevel@tonic-gate if (scf_cmp_pattern(fmri, &pattern[i]) && 5878*7c478bd9Sstevel@tonic-gate (ret = scf_add_match(htable, fmri, 5879*7c478bd9Sstevel@tonic-gate legacy, &pattern[i], svc_explicit)) != 0) 5880*7c478bd9Sstevel@tonic-gate return (ret); 5881*7c478bd9Sstevel@tonic-gate } 5882*7c478bd9Sstevel@tonic-gate 5883*7c478bd9Sstevel@tonic-gate return (0); 5884*7c478bd9Sstevel@tonic-gate } 5885*7c478bd9Sstevel@tonic-gate 5886*7c478bd9Sstevel@tonic-gate scf_error_t 5887*7c478bd9Sstevel@tonic-gate scf_walk_fmri(scf_handle_t *h, int argc, char **argv, int flags, 5888*7c478bd9Sstevel@tonic-gate scf_walk_callback callback, void *data, int *err, 5889*7c478bd9Sstevel@tonic-gate void (*errfunc)(const char *, ...)) 5890*7c478bd9Sstevel@tonic-gate { 5891*7c478bd9Sstevel@tonic-gate scf_pattern_t *pattern = NULL; 5892*7c478bd9Sstevel@tonic-gate int i; 5893*7c478bd9Sstevel@tonic-gate char *fmri = NULL; 5894*7c478bd9Sstevel@tonic-gate ssize_t max_fmri_length; 5895*7c478bd9Sstevel@tonic-gate scf_service_t *svc = NULL; 5896*7c478bd9Sstevel@tonic-gate scf_instance_t *inst = NULL; 5897*7c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL, *sciter = NULL, *siter = NULL; 5898*7c478bd9Sstevel@tonic-gate scf_scope_t *scope = NULL; 5899*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 5900*7c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 5901*7c478bd9Sstevel@tonic-gate scf_value_t *value = NULL; 5902*7c478bd9Sstevel@tonic-gate int ret = 0; 5903*7c478bd9Sstevel@tonic-gate scf_matchkey_t **htable = NULL; 5904*7c478bd9Sstevel@tonic-gate int pattern_search = 0; 5905*7c478bd9Sstevel@tonic-gate ssize_t max_name_length; 5906*7c478bd9Sstevel@tonic-gate char *pgname = NULL; 5907*7c478bd9Sstevel@tonic-gate scf_walkinfo_t info; 5908*7c478bd9Sstevel@tonic-gate 5909*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 5910*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_EXPLICIT) 5911*7c478bd9Sstevel@tonic-gate assert(flags & SCF_WALK_SERVICE); 5912*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_NOINSTANCE) 5913*7c478bd9Sstevel@tonic-gate assert(flags & SCF_WALK_SERVICE); 5914*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_PROPERTY) 5915*7c478bd9Sstevel@tonic-gate assert(!(flags & SCF_WALK_LEGACY)); 5916*7c478bd9Sstevel@tonic-gate #endif 5917*7c478bd9Sstevel@tonic-gate 5918*7c478bd9Sstevel@tonic-gate /* 5919*7c478bd9Sstevel@tonic-gate * Setup initial variables 5920*7c478bd9Sstevel@tonic-gate */ 5921*7c478bd9Sstevel@tonic-gate if ((max_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH)) == -1 || 5922*7c478bd9Sstevel@tonic-gate (max_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH)) == -1) 5923*7c478bd9Sstevel@tonic-gate return (SCF_ERROR_INTERNAL); 5924*7c478bd9Sstevel@tonic-gate 5925*7c478bd9Sstevel@tonic-gate if ((fmri = malloc(max_fmri_length + 1)) == NULL || 5926*7c478bd9Sstevel@tonic-gate (pgname = malloc(max_name_length + 1)) == NULL) { 5927*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 5928*7c478bd9Sstevel@tonic-gate goto error; 5929*7c478bd9Sstevel@tonic-gate } 5930*7c478bd9Sstevel@tonic-gate 5931*7c478bd9Sstevel@tonic-gate if (argc == 0) { 5932*7c478bd9Sstevel@tonic-gate pattern = NULL; 5933*7c478bd9Sstevel@tonic-gate } else if ((pattern = calloc(argc, sizeof (scf_pattern_t))) 5934*7c478bd9Sstevel@tonic-gate == NULL) { 5935*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 5936*7c478bd9Sstevel@tonic-gate goto error; 5937*7c478bd9Sstevel@tonic-gate } 5938*7c478bd9Sstevel@tonic-gate 5939*7c478bd9Sstevel@tonic-gate if ((htable = calloc(WALK_HTABLE_SIZE, sizeof (void *))) == NULL) { 5940*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 5941*7c478bd9Sstevel@tonic-gate goto error; 5942*7c478bd9Sstevel@tonic-gate } 5943*7c478bd9Sstevel@tonic-gate 5944*7c478bd9Sstevel@tonic-gate if ((inst = scf_instance_create(h)) == NULL || 5945*7c478bd9Sstevel@tonic-gate (svc = scf_service_create(h)) == NULL || 5946*7c478bd9Sstevel@tonic-gate (iter = scf_iter_create(h)) == NULL || 5947*7c478bd9Sstevel@tonic-gate (sciter = scf_iter_create(h)) == NULL || 5948*7c478bd9Sstevel@tonic-gate (siter = scf_iter_create(h)) == NULL || 5949*7c478bd9Sstevel@tonic-gate (scope = scf_scope_create(h)) == NULL || 5950*7c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 5951*7c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 5952*7c478bd9Sstevel@tonic-gate (value = scf_value_create(h)) == NULL) { 5953*7c478bd9Sstevel@tonic-gate ret = scf_error(); 5954*7c478bd9Sstevel@tonic-gate goto error; 5955*7c478bd9Sstevel@tonic-gate } 5956*7c478bd9Sstevel@tonic-gate 5957*7c478bd9Sstevel@tonic-gate /* 5958*7c478bd9Sstevel@tonic-gate * For each fmri given, we first check to see if it's a full service, 5959*7c478bd9Sstevel@tonic-gate * instance, property group, or property FMRI. This avoids having to do 5960*7c478bd9Sstevel@tonic-gate * the (rather expensive) walk of all instances. Any element which does 5961*7c478bd9Sstevel@tonic-gate * not match a full fmri is identified as a globbed pattern or a partial 5962*7c478bd9Sstevel@tonic-gate * fmri and stored in a private array when walking instances. 5963*7c478bd9Sstevel@tonic-gate */ 5964*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 5965*7c478bd9Sstevel@tonic-gate const char *scope_name, *svc_name, *inst_name, *pg_name; 5966*7c478bd9Sstevel@tonic-gate const char *prop_name; 5967*7c478bd9Sstevel@tonic-gate 5968*7c478bd9Sstevel@tonic-gate if (strlen(argv[i]) > max_fmri_length) { 5969*7c478bd9Sstevel@tonic-gate errfunc(scf_get_msg(SCF_MSG_ARGTOOLONG), argv[i]); 5970*7c478bd9Sstevel@tonic-gate if (err != NULL) 5971*7c478bd9Sstevel@tonic-gate *err = UU_EXIT_FATAL; 5972*7c478bd9Sstevel@tonic-gate continue; 5973*7c478bd9Sstevel@tonic-gate } 5974*7c478bd9Sstevel@tonic-gate 5975*7c478bd9Sstevel@tonic-gate (void) strcpy(fmri, argv[i]); 5976*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(fmri, &scope_name, &svc_name, &inst_name, 5977*7c478bd9Sstevel@tonic-gate &pg_name, &prop_name) != SCF_SUCCESS) 5978*7c478bd9Sstevel@tonic-gate goto badfmri; 5979*7c478bd9Sstevel@tonic-gate 5980*7c478bd9Sstevel@tonic-gate /* 5981*7c478bd9Sstevel@tonic-gate * If the user has specified SCF_WALK_PROPERTY, allow property 5982*7c478bd9Sstevel@tonic-gate * groups and properties. 5983*7c478bd9Sstevel@tonic-gate */ 5984*7c478bd9Sstevel@tonic-gate if (pg_name != NULL || prop_name != NULL) { 5985*7c478bd9Sstevel@tonic-gate if (!(flags & SCF_WALK_PROPERTY)) 5986*7c478bd9Sstevel@tonic-gate goto badfmri; 5987*7c478bd9Sstevel@tonic-gate 5988*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, argv[i], NULL, NULL, 5989*7c478bd9Sstevel@tonic-gate NULL, pg, prop, 0) != 0) 5990*7c478bd9Sstevel@tonic-gate goto badfmri; 5991*7c478bd9Sstevel@tonic-gate 5992*7c478bd9Sstevel@tonic-gate if (scf_pg_get_name(pg, NULL, 0) < 0 && 5993*7c478bd9Sstevel@tonic-gate scf_property_get_name(prop, NULL, 0) < 0) 5994*7c478bd9Sstevel@tonic-gate goto badfmri; 5995*7c478bd9Sstevel@tonic-gate 5996*7c478bd9Sstevel@tonic-gate if (scf_canonify_fmri(argv[i], fmri, max_fmri_length) 5997*7c478bd9Sstevel@tonic-gate <= 0) { 5998*7c478bd9Sstevel@tonic-gate /* 5999*7c478bd9Sstevel@tonic-gate * scf_parse_fmri() should have caught this. 6000*7c478bd9Sstevel@tonic-gate */ 6001*7c478bd9Sstevel@tonic-gate abort(); 6002*7c478bd9Sstevel@tonic-gate } 6003*7c478bd9Sstevel@tonic-gate 6004*7c478bd9Sstevel@tonic-gate if ((ret = scf_add_match(htable, fmri, NULL, 6005*7c478bd9Sstevel@tonic-gate &pattern[i], flags & SCF_WALK_EXPLICIT)) != 0) 6006*7c478bd9Sstevel@tonic-gate goto error; 6007*7c478bd9Sstevel@tonic-gate 6008*7c478bd9Sstevel@tonic-gate if ((pattern[i].sp_arg = strdup(argv[i])) == NULL) { 6009*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 6010*7c478bd9Sstevel@tonic-gate goto error; 6011*7c478bd9Sstevel@tonic-gate } 6012*7c478bd9Sstevel@tonic-gate pattern[i].sp_type = PATTERN_EXACT; 6013*7c478bd9Sstevel@tonic-gate } 6014*7c478bd9Sstevel@tonic-gate 6015*7c478bd9Sstevel@tonic-gate /* 6016*7c478bd9Sstevel@tonic-gate * We need at least a service name 6017*7c478bd9Sstevel@tonic-gate */ 6018*7c478bd9Sstevel@tonic-gate if (scope_name == NULL || svc_name == NULL) 6019*7c478bd9Sstevel@tonic-gate goto badfmri; 6020*7c478bd9Sstevel@tonic-gate 6021*7c478bd9Sstevel@tonic-gate /* 6022*7c478bd9Sstevel@tonic-gate * If we have a fully qualified instance, add it to our list of 6023*7c478bd9Sstevel@tonic-gate * fmris to watch. 6024*7c478bd9Sstevel@tonic-gate */ 6025*7c478bd9Sstevel@tonic-gate if (inst_name != NULL) { 6026*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_NOINSTANCE) 6027*7c478bd9Sstevel@tonic-gate goto badfmri; 6028*7c478bd9Sstevel@tonic-gate 6029*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, argv[i], NULL, NULL, 6030*7c478bd9Sstevel@tonic-gate inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 6031*7c478bd9Sstevel@tonic-gate goto badfmri; 6032*7c478bd9Sstevel@tonic-gate 6033*7c478bd9Sstevel@tonic-gate if (scf_canonify_fmri(argv[i], fmri, max_fmri_length) 6034*7c478bd9Sstevel@tonic-gate <= 0) 6035*7c478bd9Sstevel@tonic-gate goto badfmri; 6036*7c478bd9Sstevel@tonic-gate 6037*7c478bd9Sstevel@tonic-gate if ((ret = scf_add_match(htable, fmri, NULL, 6038*7c478bd9Sstevel@tonic-gate &pattern[i], flags & SCF_WALK_EXPLICIT)) != 0) 6039*7c478bd9Sstevel@tonic-gate goto error; 6040*7c478bd9Sstevel@tonic-gate 6041*7c478bd9Sstevel@tonic-gate if ((pattern[i].sp_arg = strdup(argv[i])) == NULL) { 6042*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 6043*7c478bd9Sstevel@tonic-gate goto error; 6044*7c478bd9Sstevel@tonic-gate } 6045*7c478bd9Sstevel@tonic-gate pattern[i].sp_type = PATTERN_EXACT; 6046*7c478bd9Sstevel@tonic-gate 6047*7c478bd9Sstevel@tonic-gate continue; 6048*7c478bd9Sstevel@tonic-gate } 6049*7c478bd9Sstevel@tonic-gate 6050*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, argv[i], NULL, svc, 6051*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 6052*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) 6053*7c478bd9Sstevel@tonic-gate goto badfmri; 6054*7c478bd9Sstevel@tonic-gate 6055*7c478bd9Sstevel@tonic-gate /* 6056*7c478bd9Sstevel@tonic-gate * If the user allows for bare services, then simply 6057*7c478bd9Sstevel@tonic-gate * pass this service on. 6058*7c478bd9Sstevel@tonic-gate */ 6059*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_SERVICE) { 6060*7c478bd9Sstevel@tonic-gate if (scf_service_to_fmri(svc, fmri, 6061*7c478bd9Sstevel@tonic-gate max_fmri_length + 1) <= 0) { 6062*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6063*7c478bd9Sstevel@tonic-gate goto error; 6064*7c478bd9Sstevel@tonic-gate } 6065*7c478bd9Sstevel@tonic-gate 6066*7c478bd9Sstevel@tonic-gate if ((ret = scf_add_match(htable, fmri, NULL, 6067*7c478bd9Sstevel@tonic-gate &pattern[i], flags & SCF_WALK_EXPLICIT)) != 0) 6068*7c478bd9Sstevel@tonic-gate goto error; 6069*7c478bd9Sstevel@tonic-gate 6070*7c478bd9Sstevel@tonic-gate if ((pattern[i].sp_arg = strdup(argv[i])) 6071*7c478bd9Sstevel@tonic-gate == NULL) { 6072*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 6073*7c478bd9Sstevel@tonic-gate goto error; 6074*7c478bd9Sstevel@tonic-gate } 6075*7c478bd9Sstevel@tonic-gate pattern[i].sp_type = PATTERN_EXACT; 6076*7c478bd9Sstevel@tonic-gate continue; 6077*7c478bd9Sstevel@tonic-gate } 6078*7c478bd9Sstevel@tonic-gate 6079*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_NOINSTANCE) 6080*7c478bd9Sstevel@tonic-gate goto badfmri; 6081*7c478bd9Sstevel@tonic-gate 6082*7c478bd9Sstevel@tonic-gate /* 6083*7c478bd9Sstevel@tonic-gate * Otherwise, iterate over all instances in the service. 6084*7c478bd9Sstevel@tonic-gate */ 6085*7c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iter, svc) != 6086*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 6087*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6088*7c478bd9Sstevel@tonic-gate goto error; 6089*7c478bd9Sstevel@tonic-gate } 6090*7c478bd9Sstevel@tonic-gate 6091*7c478bd9Sstevel@tonic-gate for (;;) { 6092*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_instance(iter, inst); 6093*7c478bd9Sstevel@tonic-gate if (ret == 0) 6094*7c478bd9Sstevel@tonic-gate break; 6095*7c478bd9Sstevel@tonic-gate if (ret != 1) { 6096*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6097*7c478bd9Sstevel@tonic-gate goto error; 6098*7c478bd9Sstevel@tonic-gate } 6099*7c478bd9Sstevel@tonic-gate 6100*7c478bd9Sstevel@tonic-gate if (scf_instance_to_fmri(inst, fmri, 6101*7c478bd9Sstevel@tonic-gate max_fmri_length + 1) == -1) 6102*7c478bd9Sstevel@tonic-gate goto badfmri; 6103*7c478bd9Sstevel@tonic-gate 6104*7c478bd9Sstevel@tonic-gate if ((ret = scf_add_match(htable, fmri, NULL, 6105*7c478bd9Sstevel@tonic-gate &pattern[i], flags & SCF_WALK_EXPLICIT)) != 0) 6106*7c478bd9Sstevel@tonic-gate goto error; 6107*7c478bd9Sstevel@tonic-gate } 6108*7c478bd9Sstevel@tonic-gate 6109*7c478bd9Sstevel@tonic-gate if ((pattern[i].sp_arg = strdup(argv[i])) == NULL) { 6110*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 6111*7c478bd9Sstevel@tonic-gate goto error; 6112*7c478bd9Sstevel@tonic-gate } 6113*7c478bd9Sstevel@tonic-gate pattern[i].sp_type = PATTERN_EXACT; 6114*7c478bd9Sstevel@tonic-gate 6115*7c478bd9Sstevel@tonic-gate continue; 6116*7c478bd9Sstevel@tonic-gate 6117*7c478bd9Sstevel@tonic-gate badfmri: 6118*7c478bd9Sstevel@tonic-gate 6119*7c478bd9Sstevel@tonic-gate /* 6120*7c478bd9Sstevel@tonic-gate * If we got here because of a fatal error, bail out 6121*7c478bd9Sstevel@tonic-gate * immediately. 6122*7c478bd9Sstevel@tonic-gate */ 6123*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) { 6124*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6125*7c478bd9Sstevel@tonic-gate goto error; 6126*7c478bd9Sstevel@tonic-gate } 6127*7c478bd9Sstevel@tonic-gate 6128*7c478bd9Sstevel@tonic-gate /* 6129*7c478bd9Sstevel@tonic-gate * At this point we failed to interpret the argument as a 6130*7c478bd9Sstevel@tonic-gate * complete fmri, so mark it as a partial or globbed FMRI for 6131*7c478bd9Sstevel@tonic-gate * later processing. 6132*7c478bd9Sstevel@tonic-gate */ 6133*7c478bd9Sstevel@tonic-gate if (strpbrk(argv[i], "*?[") != NULL) { 6134*7c478bd9Sstevel@tonic-gate /* 6135*7c478bd9Sstevel@tonic-gate * Prepend svc:/ to patterns which don't begin with * or 6136*7c478bd9Sstevel@tonic-gate * svc: or lrc:. 6137*7c478bd9Sstevel@tonic-gate */ 6138*7c478bd9Sstevel@tonic-gate pattern[i].sp_type = PATTERN_GLOB; 6139*7c478bd9Sstevel@tonic-gate if (argv[i][0] == '*' || 6140*7c478bd9Sstevel@tonic-gate (strlen(argv[i]) >= 4 && argv[i][3] == ':')) 6141*7c478bd9Sstevel@tonic-gate pattern[i].sp_arg = strdup(argv[i]); 6142*7c478bd9Sstevel@tonic-gate else { 6143*7c478bd9Sstevel@tonic-gate pattern[i].sp_arg = malloc(strlen(argv[i]) + 6); 6144*7c478bd9Sstevel@tonic-gate if (pattern[i].sp_arg != NULL) 6145*7c478bd9Sstevel@tonic-gate (void) snprintf(pattern[i].sp_arg, 6146*7c478bd9Sstevel@tonic-gate strlen(argv[i]) + 6, "svc:/%s", 6147*7c478bd9Sstevel@tonic-gate argv[i]); 6148*7c478bd9Sstevel@tonic-gate } 6149*7c478bd9Sstevel@tonic-gate } else { 6150*7c478bd9Sstevel@tonic-gate pattern[i].sp_type = PATTERN_PARTIAL; 6151*7c478bd9Sstevel@tonic-gate pattern[i].sp_arg = strdup(argv[i]); 6152*7c478bd9Sstevel@tonic-gate } 6153*7c478bd9Sstevel@tonic-gate pattern_search = 1; 6154*7c478bd9Sstevel@tonic-gate if (pattern[i].sp_arg == NULL) { 6155*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 6156*7c478bd9Sstevel@tonic-gate goto error; 6157*7c478bd9Sstevel@tonic-gate } 6158*7c478bd9Sstevel@tonic-gate } 6159*7c478bd9Sstevel@tonic-gate 6160*7c478bd9Sstevel@tonic-gate if (pattern_search || argc == 0) { 6161*7c478bd9Sstevel@tonic-gate /* 6162*7c478bd9Sstevel@tonic-gate * We have a set of patterns to search for. Iterate over all 6163*7c478bd9Sstevel@tonic-gate * instances and legacy services searching for matches. 6164*7c478bd9Sstevel@tonic-gate */ 6165*7c478bd9Sstevel@tonic-gate if (scf_handle_get_local_scope(h, scope) != 0) { 6166*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6167*7c478bd9Sstevel@tonic-gate goto error; 6168*7c478bd9Sstevel@tonic-gate } 6169*7c478bd9Sstevel@tonic-gate 6170*7c478bd9Sstevel@tonic-gate if (scf_iter_scope_services(sciter, scope) != 0) { 6171*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6172*7c478bd9Sstevel@tonic-gate goto error; 6173*7c478bd9Sstevel@tonic-gate } 6174*7c478bd9Sstevel@tonic-gate 6175*7c478bd9Sstevel@tonic-gate for (;;) { 6176*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_service(sciter, svc); 6177*7c478bd9Sstevel@tonic-gate if (ret == 0) 6178*7c478bd9Sstevel@tonic-gate break; 6179*7c478bd9Sstevel@tonic-gate if (ret != 1) { 6180*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6181*7c478bd9Sstevel@tonic-gate goto error; 6182*7c478bd9Sstevel@tonic-gate } 6183*7c478bd9Sstevel@tonic-gate 6184*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_SERVICE) { 6185*7c478bd9Sstevel@tonic-gate /* 6186*7c478bd9Sstevel@tonic-gate * If the user is requesting bare services, try 6187*7c478bd9Sstevel@tonic-gate * to match the service first. 6188*7c478bd9Sstevel@tonic-gate */ 6189*7c478bd9Sstevel@tonic-gate if (scf_service_to_fmri(svc, fmri, 6190*7c478bd9Sstevel@tonic-gate max_fmri_length + 1) < 0) { 6191*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6192*7c478bd9Sstevel@tonic-gate goto error; 6193*7c478bd9Sstevel@tonic-gate } 6194*7c478bd9Sstevel@tonic-gate 6195*7c478bd9Sstevel@tonic-gate if (argc == 0) { 6196*7c478bd9Sstevel@tonic-gate info.fmri = fmri; 6197*7c478bd9Sstevel@tonic-gate info.scope = scope; 6198*7c478bd9Sstevel@tonic-gate info.svc = svc; 6199*7c478bd9Sstevel@tonic-gate info.inst = NULL; 6200*7c478bd9Sstevel@tonic-gate info.pg = NULL; 6201*7c478bd9Sstevel@tonic-gate info.prop = NULL; 6202*7c478bd9Sstevel@tonic-gate if ((ret = callback(data, &info)) != 0) 6203*7c478bd9Sstevel@tonic-gate goto error; 6204*7c478bd9Sstevel@tonic-gate continue; 6205*7c478bd9Sstevel@tonic-gate } else if ((ret = scf_pattern_match(htable, 6206*7c478bd9Sstevel@tonic-gate fmri, NULL, argc, pattern, 6207*7c478bd9Sstevel@tonic-gate flags & SCF_WALK_EXPLICIT)) != 0) { 6208*7c478bd9Sstevel@tonic-gate goto error; 6209*7c478bd9Sstevel@tonic-gate } 6210*7c478bd9Sstevel@tonic-gate } 6211*7c478bd9Sstevel@tonic-gate 6212*7c478bd9Sstevel@tonic-gate if (flags & SCF_WALK_NOINSTANCE) 6213*7c478bd9Sstevel@tonic-gate continue; 6214*7c478bd9Sstevel@tonic-gate 6215*7c478bd9Sstevel@tonic-gate /* 6216*7c478bd9Sstevel@tonic-gate * Iterate over all instances in the service. 6217*7c478bd9Sstevel@tonic-gate */ 6218*7c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(siter, svc) != 0) { 6219*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) { 6220*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6221*7c478bd9Sstevel@tonic-gate goto error; 6222*7c478bd9Sstevel@tonic-gate } 6223*7c478bd9Sstevel@tonic-gate continue; 6224*7c478bd9Sstevel@tonic-gate } 6225*7c478bd9Sstevel@tonic-gate 6226*7c478bd9Sstevel@tonic-gate for (;;) { 6227*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_instance(siter, inst); 6228*7c478bd9Sstevel@tonic-gate if (ret == 0) 6229*7c478bd9Sstevel@tonic-gate break; 6230*7c478bd9Sstevel@tonic-gate if (ret != 1) { 6231*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) { 6232*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6233*7c478bd9Sstevel@tonic-gate goto error; 6234*7c478bd9Sstevel@tonic-gate } 6235*7c478bd9Sstevel@tonic-gate break; 6236*7c478bd9Sstevel@tonic-gate } 6237*7c478bd9Sstevel@tonic-gate 6238*7c478bd9Sstevel@tonic-gate if (scf_instance_to_fmri(inst, fmri, 6239*7c478bd9Sstevel@tonic-gate max_fmri_length + 1) < 0) { 6240*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6241*7c478bd9Sstevel@tonic-gate goto error; 6242*7c478bd9Sstevel@tonic-gate } 6243*7c478bd9Sstevel@tonic-gate 6244*7c478bd9Sstevel@tonic-gate /* 6245*7c478bd9Sstevel@tonic-gate * Without arguments, execute the callback 6246*7c478bd9Sstevel@tonic-gate * immediately. 6247*7c478bd9Sstevel@tonic-gate */ 6248*7c478bd9Sstevel@tonic-gate if (argc == 0) { 6249*7c478bd9Sstevel@tonic-gate info.fmri = fmri; 6250*7c478bd9Sstevel@tonic-gate info.scope = scope; 6251*7c478bd9Sstevel@tonic-gate info.svc = svc; 6252*7c478bd9Sstevel@tonic-gate info.inst = inst; 6253*7c478bd9Sstevel@tonic-gate info.pg = NULL; 6254*7c478bd9Sstevel@tonic-gate info.prop = NULL; 6255*7c478bd9Sstevel@tonic-gate if ((ret = callback(data, &info)) != 0) 6256*7c478bd9Sstevel@tonic-gate goto error; 6257*7c478bd9Sstevel@tonic-gate } else if ((ret = scf_pattern_match(htable, 6258*7c478bd9Sstevel@tonic-gate fmri, NULL, argc, pattern, 6259*7c478bd9Sstevel@tonic-gate flags & SCF_WALK_EXPLICIT)) != 0) { 6260*7c478bd9Sstevel@tonic-gate goto error; 6261*7c478bd9Sstevel@tonic-gate } 6262*7c478bd9Sstevel@tonic-gate } 6263*7c478bd9Sstevel@tonic-gate } 6264*7c478bd9Sstevel@tonic-gate 6265*7c478bd9Sstevel@tonic-gate /* 6266*7c478bd9Sstevel@tonic-gate * Search legacy services 6267*7c478bd9Sstevel@tonic-gate */ 6268*7c478bd9Sstevel@tonic-gate if ((flags & SCF_WALK_LEGACY)) { 6269*7c478bd9Sstevel@tonic-gate if (scf_scope_get_service(scope, SCF_LEGACY_SERVICE, 6270*7c478bd9Sstevel@tonic-gate svc) != 0) { 6271*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) { 6272*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6273*7c478bd9Sstevel@tonic-gate goto error; 6274*7c478bd9Sstevel@tonic-gate } 6275*7c478bd9Sstevel@tonic-gate 6276*7c478bd9Sstevel@tonic-gate goto nolegacy; 6277*7c478bd9Sstevel@tonic-gate } 6278*7c478bd9Sstevel@tonic-gate 6279*7c478bd9Sstevel@tonic-gate if (scf_iter_service_pgs_typed(iter, svc, 6280*7c478bd9Sstevel@tonic-gate SCF_GROUP_FRAMEWORK) != SCF_SUCCESS) { 6281*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6282*7c478bd9Sstevel@tonic-gate goto error; 6283*7c478bd9Sstevel@tonic-gate } 6284*7c478bd9Sstevel@tonic-gate 6285*7c478bd9Sstevel@tonic-gate (void) strcpy(fmri, LEGACY_SCHEME); 6286*7c478bd9Sstevel@tonic-gate 6287*7c478bd9Sstevel@tonic-gate for (;;) { 6288*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_pg(iter, pg); 6289*7c478bd9Sstevel@tonic-gate if (ret == -1) { 6290*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6291*7c478bd9Sstevel@tonic-gate goto error; 6292*7c478bd9Sstevel@tonic-gate } 6293*7c478bd9Sstevel@tonic-gate if (ret == 0) 6294*7c478bd9Sstevel@tonic-gate break; 6295*7c478bd9Sstevel@tonic-gate 6296*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, 6297*7c478bd9Sstevel@tonic-gate SCF_LEGACY_PROPERTY_NAME, prop) == -1) { 6298*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6299*7c478bd9Sstevel@tonic-gate if (ret == SCF_ERROR_DELETED || 6300*7c478bd9Sstevel@tonic-gate ret == SCF_ERROR_NOT_FOUND) { 6301*7c478bd9Sstevel@tonic-gate ret = 0; 6302*7c478bd9Sstevel@tonic-gate continue; 6303*7c478bd9Sstevel@tonic-gate } 6304*7c478bd9Sstevel@tonic-gate goto error; 6305*7c478bd9Sstevel@tonic-gate } 6306*7c478bd9Sstevel@tonic-gate 6307*7c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_ASTRING) 6308*7c478bd9Sstevel@tonic-gate != SCF_SUCCESS) { 6309*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 6310*7c478bd9Sstevel@tonic-gate continue; 6311*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6312*7c478bd9Sstevel@tonic-gate goto error; 6313*7c478bd9Sstevel@tonic-gate } 6314*7c478bd9Sstevel@tonic-gate 6315*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, value) != 6316*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) 6317*7c478bd9Sstevel@tonic-gate continue; 6318*7c478bd9Sstevel@tonic-gate 6319*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(value, 6320*7c478bd9Sstevel@tonic-gate fmri + sizeof (LEGACY_SCHEME) - 1, 6321*7c478bd9Sstevel@tonic-gate max_fmri_length + 2 - 6322*7c478bd9Sstevel@tonic-gate sizeof (LEGACY_SCHEME)) <= 0) 6323*7c478bd9Sstevel@tonic-gate continue; 6324*7c478bd9Sstevel@tonic-gate 6325*7c478bd9Sstevel@tonic-gate if (scf_pg_get_name(pg, pgname, 6326*7c478bd9Sstevel@tonic-gate max_name_length + 1) <= 0) { 6327*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_DELETED) 6328*7c478bd9Sstevel@tonic-gate continue; 6329*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6330*7c478bd9Sstevel@tonic-gate goto error; 6331*7c478bd9Sstevel@tonic-gate } 6332*7c478bd9Sstevel@tonic-gate 6333*7c478bd9Sstevel@tonic-gate if (argc == 0) { 6334*7c478bd9Sstevel@tonic-gate info.fmri = fmri; 6335*7c478bd9Sstevel@tonic-gate info.scope = scope; 6336*7c478bd9Sstevel@tonic-gate info.svc = NULL; 6337*7c478bd9Sstevel@tonic-gate info.inst = NULL; 6338*7c478bd9Sstevel@tonic-gate info.pg = pg; 6339*7c478bd9Sstevel@tonic-gate info.prop = NULL; 6340*7c478bd9Sstevel@tonic-gate if ((ret = callback(data, &info)) != 0) 6341*7c478bd9Sstevel@tonic-gate goto error; 6342*7c478bd9Sstevel@tonic-gate } else if ((ret = scf_pattern_match(htable, 6343*7c478bd9Sstevel@tonic-gate fmri, pgname, argc, pattern, 6344*7c478bd9Sstevel@tonic-gate flags & SCF_WALK_EXPLICIT)) != 0) 6345*7c478bd9Sstevel@tonic-gate goto error; 6346*7c478bd9Sstevel@tonic-gate } 6347*7c478bd9Sstevel@tonic-gate 6348*7c478bd9Sstevel@tonic-gate } 6349*7c478bd9Sstevel@tonic-gate } 6350*7c478bd9Sstevel@tonic-gate nolegacy: 6351*7c478bd9Sstevel@tonic-gate ret = 0; 6352*7c478bd9Sstevel@tonic-gate 6353*7c478bd9Sstevel@tonic-gate if (argc == 0) 6354*7c478bd9Sstevel@tonic-gate goto error; 6355*7c478bd9Sstevel@tonic-gate 6356*7c478bd9Sstevel@tonic-gate /* 6357*7c478bd9Sstevel@tonic-gate * Check all patterns, and see if we have that any that didn't match 6358*7c478bd9Sstevel@tonic-gate * or any that matched multiple instances. For svcprop, add up the 6359*7c478bd9Sstevel@tonic-gate * total number of matching keys. 6360*7c478bd9Sstevel@tonic-gate */ 6361*7c478bd9Sstevel@tonic-gate info.count = 0; 6362*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 6363*7c478bd9Sstevel@tonic-gate scf_match_t *match; 6364*7c478bd9Sstevel@tonic-gate 6365*7c478bd9Sstevel@tonic-gate if (pattern[i].sp_type == PATTERN_INVALID) 6366*7c478bd9Sstevel@tonic-gate continue; 6367*7c478bd9Sstevel@tonic-gate if (pattern[i].sp_matchcount == 0) { 6368*7c478bd9Sstevel@tonic-gate scf_msg_t msgid; 6369*7c478bd9Sstevel@tonic-gate /* 6370*7c478bd9Sstevel@tonic-gate * Provide a useful error message based on the argument 6371*7c478bd9Sstevel@tonic-gate * and the type of entity requested. 6372*7c478bd9Sstevel@tonic-gate */ 6373*7c478bd9Sstevel@tonic-gate if (!(flags & SCF_WALK_LEGACY) && 6374*7c478bd9Sstevel@tonic-gate strncmp(pattern[i].sp_arg, "lrc:/", 5) == 0) 6375*7c478bd9Sstevel@tonic-gate msgid = SCF_MSG_PATTERN_LEGACY; 6376*7c478bd9Sstevel@tonic-gate else if (flags & SCF_WALK_PROPERTY) 6377*7c478bd9Sstevel@tonic-gate msgid = SCF_MSG_PATTERN_NOENTITY; 6378*7c478bd9Sstevel@tonic-gate else if (flags & SCF_WALK_NOINSTANCE) 6379*7c478bd9Sstevel@tonic-gate msgid = SCF_MSG_PATTERN_NOSERVICE; 6380*7c478bd9Sstevel@tonic-gate else if (flags & SCF_WALK_SERVICE) 6381*7c478bd9Sstevel@tonic-gate msgid = SCF_MSG_PATTERN_NOINSTSVC; 6382*7c478bd9Sstevel@tonic-gate else 6383*7c478bd9Sstevel@tonic-gate msgid = SCF_MSG_PATTERN_NOINSTANCE; 6384*7c478bd9Sstevel@tonic-gate 6385*7c478bd9Sstevel@tonic-gate errfunc(scf_get_msg(msgid), pattern[i].sp_arg); 6386*7c478bd9Sstevel@tonic-gate if (err) 6387*7c478bd9Sstevel@tonic-gate *err = UU_EXIT_FATAL; 6388*7c478bd9Sstevel@tonic-gate } else if (!(flags & SCF_WALK_MULTIPLE) && 6389*7c478bd9Sstevel@tonic-gate pattern[i].sp_matchcount > 1) { 6390*7c478bd9Sstevel@tonic-gate size_t len, off; 6391*7c478bd9Sstevel@tonic-gate char *msg; 6392*7c478bd9Sstevel@tonic-gate 6393*7c478bd9Sstevel@tonic-gate /* 6394*7c478bd9Sstevel@tonic-gate * Construct a message with all possible FMRIs before 6395*7c478bd9Sstevel@tonic-gate * passing off to error handling function. 6396*7c478bd9Sstevel@tonic-gate * 6397*7c478bd9Sstevel@tonic-gate * Note that strlen(scf_get_msg(...)) includes the 6398*7c478bd9Sstevel@tonic-gate * length of '%s', which accounts for the terminating 6399*7c478bd9Sstevel@tonic-gate * null byte. 6400*7c478bd9Sstevel@tonic-gate */ 6401*7c478bd9Sstevel@tonic-gate len = strlen(scf_get_msg(SCF_MSG_PATTERN_MULTIMATCH)) + 6402*7c478bd9Sstevel@tonic-gate strlen(pattern[i].sp_arg); 6403*7c478bd9Sstevel@tonic-gate for (match = pattern[i].sp_matches; match != NULL; 6404*7c478bd9Sstevel@tonic-gate match = match->sm_next) { 6405*7c478bd9Sstevel@tonic-gate len += strlen(match->sm_key->sk_fmri) + 2; 6406*7c478bd9Sstevel@tonic-gate } 6407*7c478bd9Sstevel@tonic-gate if ((msg = malloc(len)) == NULL) { 6408*7c478bd9Sstevel@tonic-gate ret = SCF_ERROR_NO_MEMORY; 6409*7c478bd9Sstevel@tonic-gate goto error; 6410*7c478bd9Sstevel@tonic-gate } 6411*7c478bd9Sstevel@tonic-gate 6412*7c478bd9Sstevel@tonic-gate /* LINTED - format argument */ 6413*7c478bd9Sstevel@tonic-gate (void) snprintf(msg, len, 6414*7c478bd9Sstevel@tonic-gate scf_get_msg(SCF_MSG_PATTERN_MULTIMATCH), 6415*7c478bd9Sstevel@tonic-gate pattern[i].sp_arg); 6416*7c478bd9Sstevel@tonic-gate off = strlen(msg); 6417*7c478bd9Sstevel@tonic-gate for (match = pattern[i].sp_matches; match != NULL; 6418*7c478bd9Sstevel@tonic-gate match = match->sm_next) { 6419*7c478bd9Sstevel@tonic-gate off += snprintf(msg + off, len - off, "\t%s\n", 6420*7c478bd9Sstevel@tonic-gate match->sm_key->sk_fmri); 6421*7c478bd9Sstevel@tonic-gate } 6422*7c478bd9Sstevel@tonic-gate 6423*7c478bd9Sstevel@tonic-gate errfunc(msg); 6424*7c478bd9Sstevel@tonic-gate if (err != NULL) 6425*7c478bd9Sstevel@tonic-gate *err = UU_EXIT_FATAL; 6426*7c478bd9Sstevel@tonic-gate 6427*7c478bd9Sstevel@tonic-gate free(msg); 6428*7c478bd9Sstevel@tonic-gate } else { 6429*7c478bd9Sstevel@tonic-gate for (match = pattern[i].sp_matches; match != NULL; 6430*7c478bd9Sstevel@tonic-gate match = match->sm_next) { 6431*7c478bd9Sstevel@tonic-gate if (!match->sm_key->sk_seen) 6432*7c478bd9Sstevel@tonic-gate info.count++; 6433*7c478bd9Sstevel@tonic-gate match->sm_key->sk_seen = 1; 6434*7c478bd9Sstevel@tonic-gate } 6435*7c478bd9Sstevel@tonic-gate } 6436*7c478bd9Sstevel@tonic-gate } 6437*7c478bd9Sstevel@tonic-gate 6438*7c478bd9Sstevel@tonic-gate /* 6439*7c478bd9Sstevel@tonic-gate * Clear 'sk_seen' for all keys. 6440*7c478bd9Sstevel@tonic-gate */ 6441*7c478bd9Sstevel@tonic-gate for (i = 0; i < WALK_HTABLE_SIZE; i++) { 6442*7c478bd9Sstevel@tonic-gate scf_matchkey_t *key; 6443*7c478bd9Sstevel@tonic-gate for (key = htable[i]; key != NULL; key = key->sk_next) 6444*7c478bd9Sstevel@tonic-gate key->sk_seen = 0; 6445*7c478bd9Sstevel@tonic-gate } 6446*7c478bd9Sstevel@tonic-gate 6447*7c478bd9Sstevel@tonic-gate /* 6448*7c478bd9Sstevel@tonic-gate * Iterate over all the FMRIs in our hash table and execute the 6449*7c478bd9Sstevel@tonic-gate * callback. 6450*7c478bd9Sstevel@tonic-gate */ 6451*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 6452*7c478bd9Sstevel@tonic-gate scf_match_t *match; 6453*7c478bd9Sstevel@tonic-gate scf_matchkey_t *key; 6454*7c478bd9Sstevel@tonic-gate 6455*7c478bd9Sstevel@tonic-gate /* 6456*7c478bd9Sstevel@tonic-gate * Ignore patterns which didn't match anything or matched too 6457*7c478bd9Sstevel@tonic-gate * many FMRIs. 6458*7c478bd9Sstevel@tonic-gate */ 6459*7c478bd9Sstevel@tonic-gate if (pattern[i].sp_matchcount == 0 || 6460*7c478bd9Sstevel@tonic-gate (!(flags & SCF_WALK_MULTIPLE) && 6461*7c478bd9Sstevel@tonic-gate pattern[i].sp_matchcount > 1)) 6462*7c478bd9Sstevel@tonic-gate continue; 6463*7c478bd9Sstevel@tonic-gate 6464*7c478bd9Sstevel@tonic-gate for (match = pattern[i].sp_matches; match != NULL; 6465*7c478bd9Sstevel@tonic-gate match = match->sm_next) { 6466*7c478bd9Sstevel@tonic-gate 6467*7c478bd9Sstevel@tonic-gate key = match->sm_key; 6468*7c478bd9Sstevel@tonic-gate if (key->sk_seen) 6469*7c478bd9Sstevel@tonic-gate continue; 6470*7c478bd9Sstevel@tonic-gate 6471*7c478bd9Sstevel@tonic-gate key->sk_seen = 1; 6472*7c478bd9Sstevel@tonic-gate 6473*7c478bd9Sstevel@tonic-gate if (key->sk_legacy != NULL) { 6474*7c478bd9Sstevel@tonic-gate if (scf_scope_get_service(scope, 6475*7c478bd9Sstevel@tonic-gate "smf/legacy_run", svc) != 0) { 6476*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6477*7c478bd9Sstevel@tonic-gate goto error; 6478*7c478bd9Sstevel@tonic-gate } 6479*7c478bd9Sstevel@tonic-gate 6480*7c478bd9Sstevel@tonic-gate if (scf_service_get_pg(svc, key->sk_legacy, 6481*7c478bd9Sstevel@tonic-gate pg) != 0) 6482*7c478bd9Sstevel@tonic-gate continue; 6483*7c478bd9Sstevel@tonic-gate 6484*7c478bd9Sstevel@tonic-gate info.fmri = key->sk_fmri; 6485*7c478bd9Sstevel@tonic-gate info.scope = scope; 6486*7c478bd9Sstevel@tonic-gate info.svc = NULL; 6487*7c478bd9Sstevel@tonic-gate info.inst = NULL; 6488*7c478bd9Sstevel@tonic-gate info.pg = pg; 6489*7c478bd9Sstevel@tonic-gate info.prop = NULL; 6490*7c478bd9Sstevel@tonic-gate if ((ret = callback(data, &info)) != 0) 6491*7c478bd9Sstevel@tonic-gate goto error; 6492*7c478bd9Sstevel@tonic-gate } else { 6493*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, key->sk_fmri, 6494*7c478bd9Sstevel@tonic-gate scope, svc, inst, pg, prop, 0) != 6495*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) 6496*7c478bd9Sstevel@tonic-gate continue; 6497*7c478bd9Sstevel@tonic-gate 6498*7c478bd9Sstevel@tonic-gate info.fmri = key->sk_fmri; 6499*7c478bd9Sstevel@tonic-gate info.scope = scope; 6500*7c478bd9Sstevel@tonic-gate info.svc = svc; 6501*7c478bd9Sstevel@tonic-gate if (scf_instance_get_name(inst, NULL, 0) < 0) { 6502*7c478bd9Sstevel@tonic-gate if (scf_error() == 6503*7c478bd9Sstevel@tonic-gate SCF_ERROR_CONNECTION_BROKEN) { 6504*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6505*7c478bd9Sstevel@tonic-gate goto error; 6506*7c478bd9Sstevel@tonic-gate } 6507*7c478bd9Sstevel@tonic-gate info.inst = NULL; 6508*7c478bd9Sstevel@tonic-gate } else { 6509*7c478bd9Sstevel@tonic-gate info.inst = inst; 6510*7c478bd9Sstevel@tonic-gate } 6511*7c478bd9Sstevel@tonic-gate if (scf_pg_get_name(pg, NULL, 0) < 0) { 6512*7c478bd9Sstevel@tonic-gate if (scf_error() == 6513*7c478bd9Sstevel@tonic-gate SCF_ERROR_CONNECTION_BROKEN) { 6514*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6515*7c478bd9Sstevel@tonic-gate goto error; 6516*7c478bd9Sstevel@tonic-gate } 6517*7c478bd9Sstevel@tonic-gate info.pg = NULL; 6518*7c478bd9Sstevel@tonic-gate } else { 6519*7c478bd9Sstevel@tonic-gate info.pg = pg; 6520*7c478bd9Sstevel@tonic-gate } 6521*7c478bd9Sstevel@tonic-gate if (scf_property_get_name(prop, NULL, 0) < 0) { 6522*7c478bd9Sstevel@tonic-gate if (scf_error() == 6523*7c478bd9Sstevel@tonic-gate SCF_ERROR_CONNECTION_BROKEN) { 6524*7c478bd9Sstevel@tonic-gate ret = scf_error(); 6525*7c478bd9Sstevel@tonic-gate goto error; 6526*7c478bd9Sstevel@tonic-gate } 6527*7c478bd9Sstevel@tonic-gate info.prop = NULL; 6528*7c478bd9Sstevel@tonic-gate } else { 6529*7c478bd9Sstevel@tonic-gate info.prop = prop; 6530*7c478bd9Sstevel@tonic-gate } 6531*7c478bd9Sstevel@tonic-gate 6532*7c478bd9Sstevel@tonic-gate if ((ret = callback(data, &info)) != 0) 6533*7c478bd9Sstevel@tonic-gate goto error; 6534*7c478bd9Sstevel@tonic-gate } 6535*7c478bd9Sstevel@tonic-gate } 6536*7c478bd9Sstevel@tonic-gate } 6537*7c478bd9Sstevel@tonic-gate 6538*7c478bd9Sstevel@tonic-gate error: 6539*7c478bd9Sstevel@tonic-gate if (htable) { 6540*7c478bd9Sstevel@tonic-gate scf_matchkey_t *key, *next; 6541*7c478bd9Sstevel@tonic-gate 6542*7c478bd9Sstevel@tonic-gate for (i = 0; i < WALK_HTABLE_SIZE; i++) { 6543*7c478bd9Sstevel@tonic-gate 6544*7c478bd9Sstevel@tonic-gate for (key = htable[i]; key != NULL; 6545*7c478bd9Sstevel@tonic-gate key = next) { 6546*7c478bd9Sstevel@tonic-gate 6547*7c478bd9Sstevel@tonic-gate next = key->sk_next; 6548*7c478bd9Sstevel@tonic-gate 6549*7c478bd9Sstevel@tonic-gate if (key->sk_fmri != NULL) 6550*7c478bd9Sstevel@tonic-gate free(key->sk_fmri); 6551*7c478bd9Sstevel@tonic-gate if (key->sk_legacy != NULL) 6552*7c478bd9Sstevel@tonic-gate free(key->sk_legacy); 6553*7c478bd9Sstevel@tonic-gate free(key); 6554*7c478bd9Sstevel@tonic-gate } 6555*7c478bd9Sstevel@tonic-gate } 6556*7c478bd9Sstevel@tonic-gate free(htable); 6557*7c478bd9Sstevel@tonic-gate } 6558*7c478bd9Sstevel@tonic-gate if (pattern != NULL) { 6559*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 6560*7c478bd9Sstevel@tonic-gate scf_match_t *match, *next; 6561*7c478bd9Sstevel@tonic-gate 6562*7c478bd9Sstevel@tonic-gate if (pattern[i].sp_arg != NULL) 6563*7c478bd9Sstevel@tonic-gate free(pattern[i].sp_arg); 6564*7c478bd9Sstevel@tonic-gate 6565*7c478bd9Sstevel@tonic-gate for (match = pattern[i].sp_matches; match != NULL; 6566*7c478bd9Sstevel@tonic-gate match = next) { 6567*7c478bd9Sstevel@tonic-gate 6568*7c478bd9Sstevel@tonic-gate next = match->sm_next; 6569*7c478bd9Sstevel@tonic-gate 6570*7c478bd9Sstevel@tonic-gate free(match); 6571*7c478bd9Sstevel@tonic-gate } 6572*7c478bd9Sstevel@tonic-gate } 6573*7c478bd9Sstevel@tonic-gate free(pattern); 6574*7c478bd9Sstevel@tonic-gate } 6575*7c478bd9Sstevel@tonic-gate 6576*7c478bd9Sstevel@tonic-gate free(fmri); 6577*7c478bd9Sstevel@tonic-gate free(pgname); 6578*7c478bd9Sstevel@tonic-gate 6579*7c478bd9Sstevel@tonic-gate scf_value_destroy(value); 6580*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 6581*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 6582*7c478bd9Sstevel@tonic-gate scf_scope_destroy(scope); 6583*7c478bd9Sstevel@tonic-gate scf_iter_destroy(siter); 6584*7c478bd9Sstevel@tonic-gate scf_iter_destroy(sciter); 6585*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 6586*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 6587*7c478bd9Sstevel@tonic-gate scf_service_destroy(svc); 6588*7c478bd9Sstevel@tonic-gate 6589*7c478bd9Sstevel@tonic-gate return (ret); 6590*7c478bd9Sstevel@tonic-gate } 6591*7c478bd9Sstevel@tonic-gate 6592*7c478bd9Sstevel@tonic-gate /* 6593*7c478bd9Sstevel@tonic-gate * _scf_request_backup: a simple wrapper routine 6594*7c478bd9Sstevel@tonic-gate */ 6595*7c478bd9Sstevel@tonic-gate int 6596*7c478bd9Sstevel@tonic-gate _scf_request_backup(scf_handle_t *h, const char *name) 6597*7c478bd9Sstevel@tonic-gate { 6598*7c478bd9Sstevel@tonic-gate struct rep_protocol_backup_request request; 6599*7c478bd9Sstevel@tonic-gate struct rep_protocol_response response; 6600*7c478bd9Sstevel@tonic-gate 6601*7c478bd9Sstevel@tonic-gate int r; 6602*7c478bd9Sstevel@tonic-gate 6603*7c478bd9Sstevel@tonic-gate if (strlcpy(request.rpr_name, name, sizeof (request.rpr_name)) >= 6604*7c478bd9Sstevel@tonic-gate sizeof (request.rpr_name)) 6605*7c478bd9Sstevel@tonic-gate return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT)); 6606*7c478bd9Sstevel@tonic-gate 6607*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&h->rh_lock); 6608*7c478bd9Sstevel@tonic-gate request.rpr_request = REP_PROTOCOL_BACKUP; 6609*7c478bd9Sstevel@tonic-gate request.rpr_changeid = handle_alloc_changeid(h); 6610*7c478bd9Sstevel@tonic-gate 6611*7c478bd9Sstevel@tonic-gate r = make_door_call(h, &request, sizeof (request), 6612*7c478bd9Sstevel@tonic-gate &response, sizeof (response)); 6613*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&h->rh_lock); 6614*7c478bd9Sstevel@tonic-gate 6615*7c478bd9Sstevel@tonic-gate if (r < 0) { 6616*7c478bd9Sstevel@tonic-gate DOOR_ERRORS_BLOCK(r); 6617*7c478bd9Sstevel@tonic-gate } 6618*7c478bd9Sstevel@tonic-gate 6619*7c478bd9Sstevel@tonic-gate if (response.rpr_response != REP_PROTOCOL_SUCCESS) 6620*7c478bd9Sstevel@tonic-gate return (scf_set_error(proto_error(response.rpr_response))); 6621*7c478bd9Sstevel@tonic-gate return (SCF_SUCCESS); 6622*7c478bd9Sstevel@tonic-gate } 6623