1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/contract/process.h> 30*0Sstevel@tonic-gate #include <assert.h> 31*0Sstevel@tonic-gate #include <errno.h> 32*0Sstevel@tonic-gate #include <libscf.h> 33*0Sstevel@tonic-gate #include <libscf_priv.h> 34*0Sstevel@tonic-gate #include <poll.h> 35*0Sstevel@tonic-gate #include <stdlib.h> 36*0Sstevel@tonic-gate #include <string.h> 37*0Sstevel@tonic-gate #include <unistd.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #include "startd.h" 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #define SMF_SNAPSHOT_RUNNING "running" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate char * 44*0Sstevel@tonic-gate inst_fmri_to_svc_fmri(const char *fmri) 45*0Sstevel@tonic-gate { 46*0Sstevel@tonic-gate char *buf, *sfmri; 47*0Sstevel@tonic-gate const char *scope, *svc; 48*0Sstevel@tonic-gate int r; 49*0Sstevel@tonic-gate boolean_t local; 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate buf = startd_alloc(max_scf_fmri_size); 52*0Sstevel@tonic-gate sfmri = startd_alloc(max_scf_fmri_size); 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate (void) strcpy(buf, fmri); 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate r = scf_parse_svc_fmri(buf, &scope, &svc, NULL, NULL, NULL); 57*0Sstevel@tonic-gate assert(r == 0); 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate local = strcmp(scope, SCF_SCOPE_LOCAL) == 0; 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate (void) snprintf(sfmri, max_scf_fmri_size, "svc:%s%s/%s", 62*0Sstevel@tonic-gate local ? "" : "//", local ? "" : scope, svc); 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate startd_free(buf, max_scf_fmri_size); 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate return (sfmri); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * Wrapper for the scf_*_create() functions. On SCF_ERROR_NO_MEMORY and 71*0Sstevel@tonic-gate * SCF_ERROR_NO_RESOURCES, retries or dies. So this can only fail with 72*0Sstevel@tonic-gate * SCF_ERROR_INVALID_ARGUMENT, if h is NULL. 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate void * 75*0Sstevel@tonic-gate libscf_object_create(void *f(scf_handle_t *), scf_handle_t *h) 76*0Sstevel@tonic-gate { 77*0Sstevel@tonic-gate void *o; 78*0Sstevel@tonic-gate uint_t try, msecs; 79*0Sstevel@tonic-gate scf_error_t err; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate o = f(h); 82*0Sstevel@tonic-gate if (o != NULL) 83*0Sstevel@tonic-gate return (o); 84*0Sstevel@tonic-gate err = scf_error(); 85*0Sstevel@tonic-gate if (err != SCF_ERROR_NO_MEMORY && err != SCF_ERROR_NO_RESOURCES) 86*0Sstevel@tonic-gate return (NULL); 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate msecs = ALLOC_DELAY; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate for (try = 0; try < ALLOC_RETRY; ++try) { 91*0Sstevel@tonic-gate (void) poll(NULL, 0, msecs); 92*0Sstevel@tonic-gate msecs *= ALLOC_DELAY_MULT; 93*0Sstevel@tonic-gate o = f(h); 94*0Sstevel@tonic-gate if (o != NULL) 95*0Sstevel@tonic-gate return (o); 96*0Sstevel@tonic-gate err = scf_error(); 97*0Sstevel@tonic-gate if (err != SCF_ERROR_NO_MEMORY && err != SCF_ERROR_NO_RESOURCES) 98*0Sstevel@tonic-gate return (NULL); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate uu_die("Insufficient memory.\n"); 102*0Sstevel@tonic-gate /* NOTREACHED */ 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate scf_snapshot_t * 106*0Sstevel@tonic-gate libscf_get_running_snapshot(scf_instance_t *inst) 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate scf_handle_t *h; 109*0Sstevel@tonic-gate scf_snapshot_t *snap; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate h = scf_instance_handle(inst); 112*0Sstevel@tonic-gate if (h == NULL) 113*0Sstevel@tonic-gate return (NULL); 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate snap = scf_snapshot_create(h); 116*0Sstevel@tonic-gate if (snap == NULL) 117*0Sstevel@tonic-gate return (NULL); 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, SMF_SNAPSHOT_RUNNING, snap) == 0) 120*0Sstevel@tonic-gate return (snap); 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 123*0Sstevel@tonic-gate return (NULL); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * Make sure a service has a "running" snapshot. If it doesn't, make one from 128*0Sstevel@tonic-gate * the editing configuration. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate scf_snapshot_t * 131*0Sstevel@tonic-gate libscf_get_or_make_running_snapshot(scf_instance_t *inst, const char *fmri, 132*0Sstevel@tonic-gate boolean_t retake) 133*0Sstevel@tonic-gate { 134*0Sstevel@tonic-gate scf_handle_t *h; 135*0Sstevel@tonic-gate scf_snapshot_t *snap; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate h = scf_instance_handle(inst); 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate snap = scf_snapshot_create(h); 140*0Sstevel@tonic-gate if (snap == NULL) 141*0Sstevel@tonic-gate goto err; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, SMF_SNAPSHOT_RUNNING, snap) == 0) 144*0Sstevel@tonic-gate return (snap); 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate switch (scf_error()) { 147*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 148*0Sstevel@tonic-gate break; 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 151*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 152*0Sstevel@tonic-gate return (NULL); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate default: 155*0Sstevel@tonic-gate err: 156*0Sstevel@tonic-gate log_error(LOG_NOTICE, 157*0Sstevel@tonic-gate "Could not check for running snapshot of %s (%s).\n", fmri, 158*0Sstevel@tonic-gate scf_strerror(scf_error())); 159*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 160*0Sstevel@tonic-gate return (NULL); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate if (_scf_snapshot_take_new(inst, SMF_SNAPSHOT_RUNNING, snap) == 0) { 164*0Sstevel@tonic-gate log_framework(LOG_DEBUG, "Took running snapshot for %s.\n", 165*0Sstevel@tonic-gate fmri); 166*0Sstevel@tonic-gate } else { 167*0Sstevel@tonic-gate if (retake && scf_error() == SCF_ERROR_BACKEND_READONLY) 168*0Sstevel@tonic-gate restarter_mark_pending_snapshot(fmri, 169*0Sstevel@tonic-gate RINST_RETAKE_RUNNING); 170*0Sstevel@tonic-gate else 171*0Sstevel@tonic-gate log_error(LOG_DEBUG, 172*0Sstevel@tonic-gate "Could not create running snapshot for %s " 173*0Sstevel@tonic-gate "(%s).\n", fmri, scf_strerror(scf_error())); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 176*0Sstevel@tonic-gate snap = NULL; 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate return (snap); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * When a service comes up, point the "start" snapshot at the "running" 184*0Sstevel@tonic-gate * snapshot. Returns 0 on success, ENOTSUP if fmri designates something other 185*0Sstevel@tonic-gate * than an instance, ECONNABORTED, ENOENT if the instance does not exist, or 186*0Sstevel@tonic-gate * EACCES. 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate int 189*0Sstevel@tonic-gate libscf_snapshots_poststart(scf_handle_t *h, const char *fmri, boolean_t retake) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate scf_instance_t *inst = NULL; 192*0Sstevel@tonic-gate scf_snapshot_t *running, *start = NULL; 193*0Sstevel@tonic-gate int ret = 0, r; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate r = libscf_fmri_get_instance(h, fmri, &inst); 196*0Sstevel@tonic-gate switch (r) { 197*0Sstevel@tonic-gate case 0: 198*0Sstevel@tonic-gate break; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate case ENOTSUP: 201*0Sstevel@tonic-gate case ECONNABORTED: 202*0Sstevel@tonic-gate case ENOENT: 203*0Sstevel@tonic-gate return (r); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate case EINVAL: 206*0Sstevel@tonic-gate default: 207*0Sstevel@tonic-gate assert(0); 208*0Sstevel@tonic-gate abort(); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate start = safe_scf_snapshot_create(h); 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate again: 214*0Sstevel@tonic-gate running = libscf_get_or_make_running_snapshot(inst, fmri, retake); 215*0Sstevel@tonic-gate if (running == NULL) { 216*0Sstevel@tonic-gate ret = 0; 217*0Sstevel@tonic-gate goto out; 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate lookup: 221*0Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "start", start) != 0) { 222*0Sstevel@tonic-gate switch (scf_error()) { 223*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 224*0Sstevel@tonic-gate default: 225*0Sstevel@tonic-gate ret = ECONNABORTED; 226*0Sstevel@tonic-gate goto out; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 229*0Sstevel@tonic-gate if (_scf_snapshot_take_new(inst, "start", start) != 0) { 230*0Sstevel@tonic-gate switch (scf_error()) { 231*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 232*0Sstevel@tonic-gate default: 233*0Sstevel@tonic-gate ret = ECONNABORTED; 234*0Sstevel@tonic-gate goto out; 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 237*0Sstevel@tonic-gate ret = ENOENT; 238*0Sstevel@tonic-gate goto out; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate case SCF_ERROR_EXISTS: 241*0Sstevel@tonic-gate goto lookup; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 244*0Sstevel@tonic-gate uu_die("Repository server out of " 245*0Sstevel@tonic-gate "resources.\n"); 246*0Sstevel@tonic-gate /* NOTREACHED */ 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 249*0Sstevel@tonic-gate goto readonly; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 252*0Sstevel@tonic-gate uu_die("Insufficient privileges.\n"); 253*0Sstevel@tonic-gate /* NOTREACHED */ 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 256*0Sstevel@tonic-gate ret = EACCES; 257*0Sstevel@tonic-gate goto out; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 260*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 261*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 262*0Sstevel@tonic-gate bad_error("_scf_snapshot_take_new", 263*0Sstevel@tonic-gate scf_error()); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate break; 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 269*0Sstevel@tonic-gate ret = ENOENT; 270*0Sstevel@tonic-gate goto out; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 273*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 274*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 275*0Sstevel@tonic-gate bad_error("scf_instance_get_snapshot", scf_error()); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate if (_scf_snapshot_attach(running, start) == 0) { 280*0Sstevel@tonic-gate log_framework(LOG_DEBUG, "Updated \"start\" snapshot for %s.\n", 281*0Sstevel@tonic-gate fmri); 282*0Sstevel@tonic-gate } else { 283*0Sstevel@tonic-gate switch (scf_error()) { 284*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 285*0Sstevel@tonic-gate default: 286*0Sstevel@tonic-gate ret = ECONNABORTED; 287*0Sstevel@tonic-gate goto out; 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 290*0Sstevel@tonic-gate scf_snapshot_destroy(running); 291*0Sstevel@tonic-gate goto again; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 294*0Sstevel@tonic-gate uu_die("Repository server out of resources.\n"); 295*0Sstevel@tonic-gate /* NOTREACHED */ 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 298*0Sstevel@tonic-gate uu_die("Insufficient privileges.\n"); 299*0Sstevel@tonic-gate /* NOTREACHED */ 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 302*0Sstevel@tonic-gate ret = EACCES; 303*0Sstevel@tonic-gate goto out; 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 306*0Sstevel@tonic-gate readonly: 307*0Sstevel@tonic-gate if (retake) 308*0Sstevel@tonic-gate restarter_mark_pending_snapshot(fmri, 309*0Sstevel@tonic-gate RINST_RETAKE_START); 310*0Sstevel@tonic-gate break; 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 313*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 314*0Sstevel@tonic-gate bad_error("_scf_snapshot_attach", scf_error()); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate out: 319*0Sstevel@tonic-gate scf_snapshot_destroy(start); 320*0Sstevel@tonic-gate scf_snapshot_destroy(running); 321*0Sstevel@tonic-gate scf_instance_destroy(inst); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate return (ret); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * Before a refresh, update the "running" snapshot from the editing 328*0Sstevel@tonic-gate * configuration. 329*0Sstevel@tonic-gate * 330*0Sstevel@tonic-gate * Returns 0 on success and -1 on failure. 331*0Sstevel@tonic-gate */ 332*0Sstevel@tonic-gate int 333*0Sstevel@tonic-gate libscf_snapshots_refresh(scf_instance_t *inst, const char *fmri) 334*0Sstevel@tonic-gate { 335*0Sstevel@tonic-gate scf_handle_t *h; 336*0Sstevel@tonic-gate scf_snapshot_t *snap; 337*0Sstevel@tonic-gate boolean_t err = 1; 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate h = scf_instance_handle(inst); 340*0Sstevel@tonic-gate if (h == NULL) 341*0Sstevel@tonic-gate goto out; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate snap = scf_snapshot_create(h); 344*0Sstevel@tonic-gate if (snap == NULL) 345*0Sstevel@tonic-gate goto out; 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, SMF_SNAPSHOT_RUNNING, snap) == 0) { 348*0Sstevel@tonic-gate if (_scf_snapshot_take_attach(inst, snap) == 0) 349*0Sstevel@tonic-gate err = 0; 350*0Sstevel@tonic-gate } else { 351*0Sstevel@tonic-gate switch (scf_error()) { 352*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 353*0Sstevel@tonic-gate err = 0; 354*0Sstevel@tonic-gate goto out; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 357*0Sstevel@tonic-gate break; 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 360*0Sstevel@tonic-gate assert(0); 361*0Sstevel@tonic-gate abort(); 362*0Sstevel@tonic-gate /* NOTREACHED */ 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate default: 365*0Sstevel@tonic-gate goto out; 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate log_error(LOG_DEBUG, 369*0Sstevel@tonic-gate "Service %s has no %s snapshot; creating one.\n", fmri, 370*0Sstevel@tonic-gate SMF_SNAPSHOT_RUNNING); 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if (_scf_snapshot_take_new(inst, SMF_SNAPSHOT_RUNNING, 373*0Sstevel@tonic-gate snap) == 0) 374*0Sstevel@tonic-gate err = 0; 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate out: 378*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate if (!err) 381*0Sstevel@tonic-gate return (0); 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate log_error(LOG_WARNING, 384*0Sstevel@tonic-gate "Could not update \"running\" snapshot for refresh of %s.\n", fmri); 385*0Sstevel@tonic-gate return (-1); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate /* 389*0Sstevel@tonic-gate * int libscf_read_single_astring() 390*0Sstevel@tonic-gate * Reads a single astring value of the requested property into the 391*0Sstevel@tonic-gate * pre-allocated buffer (conventionally of size max_scf_value_size). 392*0Sstevel@tonic-gate * Multiple values constitute an error. 393*0Sstevel@tonic-gate * 394*0Sstevel@tonic-gate * Returns 0 on success or LIBSCF_PROPERTY_ABSENT or LIBSCF_PROPERTY_ERROR. 395*0Sstevel@tonic-gate */ 396*0Sstevel@tonic-gate static int 397*0Sstevel@tonic-gate libscf_read_single_astring(scf_handle_t *h, scf_property_t *prop, char **ret) 398*0Sstevel@tonic-gate { 399*0Sstevel@tonic-gate scf_value_t *val = safe_scf_value_create(h); 400*0Sstevel@tonic-gate int r = 0; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if (scf_property_get_value(prop, val) == -1) { 403*0Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 404*0Sstevel@tonic-gate r = LIBSCF_PROPERTY_ABSENT; 405*0Sstevel@tonic-gate else 406*0Sstevel@tonic-gate r = LIBSCF_PROPERTY_ERROR; 407*0Sstevel@tonic-gate goto read_single_astring_fail; 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate if (scf_value_get_astring(val, *ret, max_scf_value_size) <= 0) { 411*0Sstevel@tonic-gate r = LIBSCF_PROPERTY_ERROR; 412*0Sstevel@tonic-gate goto read_single_astring_fail; 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate read_single_astring_fail: 416*0Sstevel@tonic-gate scf_value_destroy(val); 417*0Sstevel@tonic-gate return (r); 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate static int 421*0Sstevel@tonic-gate libscf_read_state(const scf_propertygroup_t *pg, const char *prop_name, 422*0Sstevel@tonic-gate restarter_instance_state_t *state) 423*0Sstevel@tonic-gate { 424*0Sstevel@tonic-gate scf_handle_t *h; 425*0Sstevel@tonic-gate scf_property_t *prop; 426*0Sstevel@tonic-gate char *char_state = startd_alloc(max_scf_value_size); 427*0Sstevel@tonic-gate int ret = 0; 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate h = scf_pg_handle(pg); 430*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate if (scf_pg_get_property(pg, prop_name, prop) == -1) { 433*0Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 434*0Sstevel@tonic-gate ret = LIBSCF_PROPERTY_ABSENT; 435*0Sstevel@tonic-gate else 436*0Sstevel@tonic-gate ret = LIBSCF_PROPERTY_ERROR; 437*0Sstevel@tonic-gate } else { 438*0Sstevel@tonic-gate ret = libscf_read_single_astring(h, prop, &char_state); 439*0Sstevel@tonic-gate if (ret != 0) { 440*0Sstevel@tonic-gate if (ret != LIBSCF_PROPERTY_ABSENT) 441*0Sstevel@tonic-gate ret = LIBSCF_PROPERTY_ERROR; 442*0Sstevel@tonic-gate } else { 443*0Sstevel@tonic-gate *state = restarter_string_to_state(char_state); 444*0Sstevel@tonic-gate ret = 0; 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate } 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate startd_free(char_state, max_scf_value_size); 449*0Sstevel@tonic-gate scf_property_destroy(prop); 450*0Sstevel@tonic-gate return (ret); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* 454*0Sstevel@tonic-gate * int libscf_read_states(const scf_propertygroup_t *, 455*0Sstevel@tonic-gate * restarter_instance_state_t *, restarter_instance_state_t *) 456*0Sstevel@tonic-gate * 457*0Sstevel@tonic-gate * Set the current state and next_state values for the given service instance. 458*0Sstevel@tonic-gate * Returns 0 on success, or a libscf error code on failure. 459*0Sstevel@tonic-gate */ 460*0Sstevel@tonic-gate int 461*0Sstevel@tonic-gate libscf_read_states(const scf_propertygroup_t *pg, 462*0Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state) 463*0Sstevel@tonic-gate { 464*0Sstevel@tonic-gate int state_ret, next_state_ret, ret; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate state_ret = libscf_read_state(pg, SCF_PROPERTY_STATE, state); 467*0Sstevel@tonic-gate next_state_ret = libscf_read_state(pg, SCF_PROPERTY_NEXT_STATE, 468*0Sstevel@tonic-gate next_state); 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate if (state_ret == LIBSCF_PROPERTY_ERROR || 471*0Sstevel@tonic-gate next_state_ret == LIBSCF_PROPERTY_ERROR) { 472*0Sstevel@tonic-gate ret = LIBSCF_PROPERTY_ERROR; 473*0Sstevel@tonic-gate } else if (state_ret == 0 && next_state_ret == 0) { 474*0Sstevel@tonic-gate ret = 0; 475*0Sstevel@tonic-gate } else if (state_ret == LIBSCF_PROPERTY_ABSENT && 476*0Sstevel@tonic-gate next_state_ret == LIBSCF_PROPERTY_ABSENT) { 477*0Sstevel@tonic-gate *state = RESTARTER_STATE_UNINIT; 478*0Sstevel@tonic-gate *next_state = RESTARTER_STATE_NONE; 479*0Sstevel@tonic-gate ret = 0; 480*0Sstevel@tonic-gate } else if (state_ret == LIBSCF_PROPERTY_ABSENT || 481*0Sstevel@tonic-gate next_state_ret == LIBSCF_PROPERTY_ABSENT) { 482*0Sstevel@tonic-gate log_framework(LOG_DEBUG, 483*0Sstevel@tonic-gate "Only one repository state exists, setting " 484*0Sstevel@tonic-gate "restarter states to MAINTENANCE and NONE\n"); 485*0Sstevel@tonic-gate *state = RESTARTER_STATE_MAINT; 486*0Sstevel@tonic-gate *next_state = RESTARTER_STATE_NONE; 487*0Sstevel@tonic-gate ret = 0; 488*0Sstevel@tonic-gate } else { 489*0Sstevel@tonic-gate ret = LIBSCF_PROPERTY_ERROR; 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate read_states_out: 493*0Sstevel@tonic-gate return (ret); 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate /* 497*0Sstevel@tonic-gate * depgroup_empty() 498*0Sstevel@tonic-gate * 499*0Sstevel@tonic-gate * Returns 0 if not empty. 500*0Sstevel@tonic-gate * Returns 1 if empty. 501*0Sstevel@tonic-gate * Returns -1 on error (check scf_error()). 502*0Sstevel@tonic-gate */ 503*0Sstevel@tonic-gate int 504*0Sstevel@tonic-gate depgroup_empty(scf_handle_t *h, scf_propertygroup_t *pg) 505*0Sstevel@tonic-gate { 506*0Sstevel@tonic-gate int empty = 1; 507*0Sstevel@tonic-gate scf_iter_t *iter; 508*0Sstevel@tonic-gate scf_property_t *prop; 509*0Sstevel@tonic-gate int ret; 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate iter = safe_scf_iter_create(h); 512*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate iter = safe_scf_iter_create(h); 515*0Sstevel@tonic-gate if (scf_iter_pg_properties(iter, pg) != SCF_SUCCESS) 516*0Sstevel@tonic-gate return (-1); 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate ret = scf_iter_next_property(iter, prop); 519*0Sstevel@tonic-gate if (ret < 0) 520*0Sstevel@tonic-gate return (-1); 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate if (ret == 1) 523*0Sstevel@tonic-gate empty = 0; 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate scf_property_destroy(prop); 526*0Sstevel@tonic-gate scf_iter_destroy(iter); 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate return (empty); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate gv_type_t 532*0Sstevel@tonic-gate depgroup_read_scheme(scf_handle_t *h, scf_propertygroup_t *pg) 533*0Sstevel@tonic-gate { 534*0Sstevel@tonic-gate scf_property_t *prop; 535*0Sstevel@tonic-gate char *scheme = startd_alloc(max_scf_value_size); 536*0Sstevel@tonic-gate gv_type_t ret; 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_TYPE, prop) == -1 || 541*0Sstevel@tonic-gate libscf_read_single_astring(h, prop, &scheme) != 0) { 542*0Sstevel@tonic-gate scf_property_destroy(prop); 543*0Sstevel@tonic-gate startd_free(scheme, max_scf_value_size); 544*0Sstevel@tonic-gate return (GVT_UNSUPPORTED); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate if (strcmp(scheme, "service") == 0) 548*0Sstevel@tonic-gate ret = GVT_INST; 549*0Sstevel@tonic-gate else if (strcmp(scheme, "path") == 0) 550*0Sstevel@tonic-gate ret = GVT_FILE; 551*0Sstevel@tonic-gate else 552*0Sstevel@tonic-gate ret = GVT_UNSUPPORTED; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate startd_free(scheme, max_scf_value_size); 555*0Sstevel@tonic-gate scf_property_destroy(prop); 556*0Sstevel@tonic-gate return (ret); 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate depgroup_type_t 560*0Sstevel@tonic-gate depgroup_read_grouping(scf_handle_t *h, scf_propertygroup_t *pg) 561*0Sstevel@tonic-gate { 562*0Sstevel@tonic-gate char *grouping = startd_alloc(max_scf_value_size); 563*0Sstevel@tonic-gate depgroup_type_t ret; 564*0Sstevel@tonic-gate scf_property_t *prop = safe_scf_property_create(h); 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_GROUPING, prop) == -1 || 567*0Sstevel@tonic-gate libscf_read_single_astring(h, prop, &grouping) != 0) { 568*0Sstevel@tonic-gate scf_property_destroy(prop); 569*0Sstevel@tonic-gate startd_free(grouping, max_scf_value_size); 570*0Sstevel@tonic-gate return (DEPGRP_UNSUPPORTED); 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate if (strcmp(grouping, SCF_DEP_REQUIRE_ANY) == 0) 574*0Sstevel@tonic-gate ret = DEPGRP_REQUIRE_ANY; 575*0Sstevel@tonic-gate else if (strcmp(grouping, SCF_DEP_REQUIRE_ALL) == 0) 576*0Sstevel@tonic-gate ret = DEPGRP_REQUIRE_ALL; 577*0Sstevel@tonic-gate else if (strcmp(grouping, SCF_DEP_OPTIONAL_ALL) == 0) 578*0Sstevel@tonic-gate ret = DEPGRP_OPTIONAL_ALL; 579*0Sstevel@tonic-gate else if (strcmp(grouping, SCF_DEP_EXCLUDE_ALL) == 0) 580*0Sstevel@tonic-gate ret = DEPGRP_EXCLUDE_ALL; 581*0Sstevel@tonic-gate else { 582*0Sstevel@tonic-gate ret = DEPGRP_UNSUPPORTED; 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate startd_free(grouping, max_scf_value_size); 585*0Sstevel@tonic-gate scf_property_destroy(prop); 586*0Sstevel@tonic-gate return (ret); 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate restarter_error_t 590*0Sstevel@tonic-gate depgroup_read_restart(scf_handle_t *h, scf_propertygroup_t *pg) 591*0Sstevel@tonic-gate { 592*0Sstevel@tonic-gate scf_property_t *prop = safe_scf_property_create(h); 593*0Sstevel@tonic-gate char *restart_on = startd_alloc(max_scf_value_size); 594*0Sstevel@tonic-gate restarter_error_t ret; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_RESTART_ON, prop) == -1 || 597*0Sstevel@tonic-gate libscf_read_single_astring(h, prop, &restart_on) != 0) { 598*0Sstevel@tonic-gate startd_free(restart_on, max_scf_value_size); 599*0Sstevel@tonic-gate scf_property_destroy(prop); 600*0Sstevel@tonic-gate return (RERR_UNSUPPORTED); 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate if (strcmp(restart_on, SCF_DEP_RESET_ON_ERROR) == 0) 604*0Sstevel@tonic-gate ret = RERR_FAULT; 605*0Sstevel@tonic-gate else if (strcmp(restart_on, SCF_DEP_RESET_ON_RESTART) == 0) 606*0Sstevel@tonic-gate ret = RERR_RESTART; 607*0Sstevel@tonic-gate else if (strcmp(restart_on, SCF_DEP_RESET_ON_REFRESH) == 0) 608*0Sstevel@tonic-gate ret = RERR_REFRESH; 609*0Sstevel@tonic-gate else if (strcmp(restart_on, SCF_DEP_RESET_ON_NONE) == 0) 610*0Sstevel@tonic-gate ret = RERR_NONE; 611*0Sstevel@tonic-gate else 612*0Sstevel@tonic-gate ret = RERR_UNSUPPORTED; 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate startd_free(restart_on, max_scf_value_size); 615*0Sstevel@tonic-gate scf_property_destroy(prop); 616*0Sstevel@tonic-gate return (ret); 617*0Sstevel@tonic-gate } 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate /* 620*0Sstevel@tonic-gate * int get_boolean() 621*0Sstevel@tonic-gate * Fetches the value of a boolean property of the given property group. 622*0Sstevel@tonic-gate * Returns 623*0Sstevel@tonic-gate * 0 - success 624*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 625*0Sstevel@tonic-gate * ECANCELED - pg was deleted 626*0Sstevel@tonic-gate * ENOENT - the property doesn't exist or has no values 627*0Sstevel@tonic-gate * EINVAL - the property has the wrong type 628*0Sstevel@tonic-gate * the property is not single-valued 629*0Sstevel@tonic-gate */ 630*0Sstevel@tonic-gate static int 631*0Sstevel@tonic-gate get_boolean(scf_propertygroup_t *pg, const char *propname, uint8_t *valuep) 632*0Sstevel@tonic-gate { 633*0Sstevel@tonic-gate scf_handle_t *h; 634*0Sstevel@tonic-gate scf_property_t *prop; 635*0Sstevel@tonic-gate scf_value_t *val; 636*0Sstevel@tonic-gate int ret = 0, r; 637*0Sstevel@tonic-gate scf_type_t type; 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate h = scf_pg_handle(pg); 640*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 641*0Sstevel@tonic-gate val = safe_scf_value_create(h); 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) != 0) { 644*0Sstevel@tonic-gate switch (scf_error()) { 645*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 646*0Sstevel@tonic-gate default: 647*0Sstevel@tonic-gate ret = ECONNABORTED; 648*0Sstevel@tonic-gate goto out; 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 651*0Sstevel@tonic-gate ret = ECANCELED; 652*0Sstevel@tonic-gate goto out; 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 655*0Sstevel@tonic-gate ret = ENOENT; 656*0Sstevel@tonic-gate goto out; 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 659*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 660*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 661*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 662*0Sstevel@tonic-gate } 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0) { 666*0Sstevel@tonic-gate switch (scf_error()) { 667*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 668*0Sstevel@tonic-gate default: 669*0Sstevel@tonic-gate ret = ECONNABORTED; 670*0Sstevel@tonic-gate goto out; 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 673*0Sstevel@tonic-gate ret = ENOENT; 674*0Sstevel@tonic-gate goto out; 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 677*0Sstevel@tonic-gate bad_error("scf_property_type", scf_error()); 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate } 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate if (type != SCF_TYPE_BOOLEAN) { 682*0Sstevel@tonic-gate ret = EINVAL; 683*0Sstevel@tonic-gate goto out; 684*0Sstevel@tonic-gate } 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate if (scf_property_get_value(prop, val) != 0) { 687*0Sstevel@tonic-gate switch (scf_error()) { 688*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 689*0Sstevel@tonic-gate default: 690*0Sstevel@tonic-gate ret = ECONNABORTED; 691*0Sstevel@tonic-gate goto out; 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 694*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 695*0Sstevel@tonic-gate ret = ENOENT; 696*0Sstevel@tonic-gate goto out; 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 699*0Sstevel@tonic-gate ret = EINVAL; 700*0Sstevel@tonic-gate goto out; 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 703*0Sstevel@tonic-gate bad_error("scf_property_get_value", scf_error()); 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate r = scf_value_get_boolean(val, valuep); 708*0Sstevel@tonic-gate assert(r == 0); 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate out: 711*0Sstevel@tonic-gate scf_value_destroy(val); 712*0Sstevel@tonic-gate scf_property_destroy(prop); 713*0Sstevel@tonic-gate return (ret); 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* 717*0Sstevel@tonic-gate * int get_count() 718*0Sstevel@tonic-gate * Fetches the value of a count property of the given property group. 719*0Sstevel@tonic-gate * Returns 720*0Sstevel@tonic-gate * 0 - success 721*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 722*0Sstevel@tonic-gate * unknown libscf error 723*0Sstevel@tonic-gate * ECANCELED - pg was deleted 724*0Sstevel@tonic-gate * ENOENT - the property doesn't exist or has no values 725*0Sstevel@tonic-gate * EINVAL - the property has the wrong type 726*0Sstevel@tonic-gate * the property is not single-valued 727*0Sstevel@tonic-gate */ 728*0Sstevel@tonic-gate static int 729*0Sstevel@tonic-gate get_count(scf_propertygroup_t *pg, const char *propname, uint64_t *valuep) 730*0Sstevel@tonic-gate { 731*0Sstevel@tonic-gate scf_handle_t *h; 732*0Sstevel@tonic-gate scf_property_t *prop; 733*0Sstevel@tonic-gate scf_value_t *val; 734*0Sstevel@tonic-gate int ret = 0, r; 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate h = scf_pg_handle(pg); 737*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 738*0Sstevel@tonic-gate val = safe_scf_value_create(h); 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) != 0) { 741*0Sstevel@tonic-gate switch (scf_error()) { 742*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 743*0Sstevel@tonic-gate default: 744*0Sstevel@tonic-gate ret = ECONNABORTED; 745*0Sstevel@tonic-gate goto out; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 748*0Sstevel@tonic-gate ret = ECANCELED; 749*0Sstevel@tonic-gate goto out; 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 752*0Sstevel@tonic-gate ret = ENOENT; 753*0Sstevel@tonic-gate goto out; 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 756*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 757*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 758*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0) { 763*0Sstevel@tonic-gate switch (scf_error()) { 764*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 765*0Sstevel@tonic-gate default: 766*0Sstevel@tonic-gate ret = ECONNABORTED; 767*0Sstevel@tonic-gate goto out; 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 770*0Sstevel@tonic-gate ret = EINVAL; 771*0Sstevel@tonic-gate goto out; 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 774*0Sstevel@tonic-gate ret = ECANCELED; 775*0Sstevel@tonic-gate goto out; 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 778*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 779*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 780*0Sstevel@tonic-gate bad_error("scf_property_is_type", scf_error()); 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate } 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate if (scf_property_get_value(prop, val) != 0) { 785*0Sstevel@tonic-gate switch (scf_error()) { 786*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 787*0Sstevel@tonic-gate default: 788*0Sstevel@tonic-gate ret = ECONNABORTED; 789*0Sstevel@tonic-gate goto out; 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 792*0Sstevel@tonic-gate ret = ECANCELED; 793*0Sstevel@tonic-gate goto out; 794*0Sstevel@tonic-gate 795*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 796*0Sstevel@tonic-gate ret = ENOENT; 797*0Sstevel@tonic-gate goto out; 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 800*0Sstevel@tonic-gate ret = EINVAL; 801*0Sstevel@tonic-gate goto out; 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 804*0Sstevel@tonic-gate bad_error("scf_property_get_value", scf_error()); 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate r = scf_value_get_count(val, valuep); 809*0Sstevel@tonic-gate assert(r == 0); 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate out: 812*0Sstevel@tonic-gate scf_value_destroy(val); 813*0Sstevel@tonic-gate scf_property_destroy(prop); 814*0Sstevel@tonic-gate return (ret); 815*0Sstevel@tonic-gate } 816*0Sstevel@tonic-gate 817*0Sstevel@tonic-gate 818*0Sstevel@tonic-gate static void 819*0Sstevel@tonic-gate get_restarter(scf_handle_t *h, scf_propertygroup_t *pg, char **restarter) 820*0Sstevel@tonic-gate { 821*0Sstevel@tonic-gate scf_property_t *prop = safe_scf_property_create(h); 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_RESTARTER, prop) == -1 || 824*0Sstevel@tonic-gate libscf_read_single_astring(h, prop, restarter) != 0) 825*0Sstevel@tonic-gate *restarter[0] = '\0'; 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate scf_property_destroy(prop); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate /* 831*0Sstevel@tonic-gate * int libscf_instance_get_fmri(scf_instance_t *, char **) 832*0Sstevel@tonic-gate * Give a valid SCF instance, return its FMRI. Returns 0 on success, 833*0Sstevel@tonic-gate * ECONNABORTED, or ECANCELED if inst is deleted. 834*0Sstevel@tonic-gate */ 835*0Sstevel@tonic-gate int 836*0Sstevel@tonic-gate libscf_instance_get_fmri(scf_instance_t *inst, char **retp) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate char *inst_fmri = startd_alloc(max_scf_fmri_size); 839*0Sstevel@tonic-gate 840*0Sstevel@tonic-gate inst_fmri[0] = 0; 841*0Sstevel@tonic-gate if (scf_instance_to_fmri(inst, inst_fmri, max_scf_fmri_size) <= 0) { 842*0Sstevel@tonic-gate startd_free(inst_fmri, max_scf_fmri_size); 843*0Sstevel@tonic-gate switch (scf_error()) { 844*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 845*0Sstevel@tonic-gate default: 846*0Sstevel@tonic-gate return (ECONNABORTED); 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 849*0Sstevel@tonic-gate return (ECANCELED); 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 852*0Sstevel@tonic-gate assert(0); 853*0Sstevel@tonic-gate abort(); 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate *retp = inst_fmri; 858*0Sstevel@tonic-gate return (0); 859*0Sstevel@tonic-gate } 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate /* 862*0Sstevel@tonic-gate * int libscf_fmri_get_instance(scf_handle_t *, const char *, 863*0Sstevel@tonic-gate * scf_instance_t **) 864*0Sstevel@tonic-gate * Given a valid SCF handle and an FMRI, return the SCF instance that matches 865*0Sstevel@tonic-gate * exactly. The instance must be released using scf_instance_destroy(). 866*0Sstevel@tonic-gate * Returns 0 on success, EINVAL if the FMRI is invalid, ENOTSUP if the FMRI 867*0Sstevel@tonic-gate * is valid but designates something other than an instance, ECONNABORTED if 868*0Sstevel@tonic-gate * the repository connection is broken, or ENOENT if the instance does not 869*0Sstevel@tonic-gate * exist. 870*0Sstevel@tonic-gate */ 871*0Sstevel@tonic-gate int 872*0Sstevel@tonic-gate libscf_fmri_get_instance(scf_handle_t *h, const char *fmri, 873*0Sstevel@tonic-gate scf_instance_t **instp) 874*0Sstevel@tonic-gate { 875*0Sstevel@tonic-gate scf_instance_t *inst; 876*0Sstevel@tonic-gate int r; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate inst = safe_scf_instance_create(h); 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate r = libscf_lookup_instance(fmri, inst); 881*0Sstevel@tonic-gate 882*0Sstevel@tonic-gate if (r == 0) 883*0Sstevel@tonic-gate *instp = inst; 884*0Sstevel@tonic-gate else 885*0Sstevel@tonic-gate scf_instance_destroy(inst); 886*0Sstevel@tonic-gate 887*0Sstevel@tonic-gate return (r); 888*0Sstevel@tonic-gate } 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gate int 891*0Sstevel@tonic-gate libscf_lookup_instance(const char *fmri, scf_instance_t *inst) 892*0Sstevel@tonic-gate { 893*0Sstevel@tonic-gate if (scf_handle_decode_fmri(scf_instance_handle(inst), fmri, NULL, NULL, 894*0Sstevel@tonic-gate inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) { 895*0Sstevel@tonic-gate switch (scf_error()) { 896*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 897*0Sstevel@tonic-gate return (EINVAL); 898*0Sstevel@tonic-gate 899*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 900*0Sstevel@tonic-gate return (ENOTSUP); 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 903*0Sstevel@tonic-gate return (ECONNABORTED); 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 906*0Sstevel@tonic-gate return (ENOENT); 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 909*0Sstevel@tonic-gate default: 910*0Sstevel@tonic-gate bad_error("scf_handle_decode_fmri", scf_error()); 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate } 913*0Sstevel@tonic-gate 914*0Sstevel@tonic-gate return (0); 915*0Sstevel@tonic-gate } 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate /* 918*0Sstevel@tonic-gate * void libscf_get_basic_instance_data() 919*0Sstevel@tonic-gate * Read enabled, enabled_ovr, and restarter_fmri (into an allocated 920*0Sstevel@tonic-gate * buffer) for inst. Returns 0, ECONNABORTED if the connection to the 921*0Sstevel@tonic-gate * repository is broken, ECANCELED if inst is deleted, or ENOENT if inst 922*0Sstevel@tonic-gate * has no general property group. 923*0Sstevel@tonic-gate * 924*0Sstevel@tonic-gate * On success, restarter_fmri may be NULL. If general/enabled was missing 925*0Sstevel@tonic-gate * or invalid, *enabledp will be -1 and a debug message is logged. 926*0Sstevel@tonic-gate */ 927*0Sstevel@tonic-gate int 928*0Sstevel@tonic-gate libscf_get_basic_instance_data(scf_handle_t *h, scf_instance_t *inst, 929*0Sstevel@tonic-gate const char *fmri, int *enabledp, int *enabled_ovrp, char **restarter_fmri) 930*0Sstevel@tonic-gate { 931*0Sstevel@tonic-gate scf_propertygroup_t *pg; 932*0Sstevel@tonic-gate int r; 933*0Sstevel@tonic-gate uint8_t enabled_8; 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate if (enabled_ovrp == NULL) 938*0Sstevel@tonic-gate goto enabled; 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_GENERAL_OVR, pg) != 941*0Sstevel@tonic-gate 0) { 942*0Sstevel@tonic-gate switch (scf_error()) { 943*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 944*0Sstevel@tonic-gate default: 945*0Sstevel@tonic-gate scf_pg_destroy(pg); 946*0Sstevel@tonic-gate return (ECONNABORTED); 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 949*0Sstevel@tonic-gate scf_pg_destroy(pg); 950*0Sstevel@tonic-gate return (ECANCELED); 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 953*0Sstevel@tonic-gate *enabled_ovrp = -1; 954*0Sstevel@tonic-gate break; 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 957*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 958*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 959*0Sstevel@tonic-gate bad_error("scf_instance_get_pg_composed", scf_error()); 960*0Sstevel@tonic-gate } 961*0Sstevel@tonic-gate } else { 962*0Sstevel@tonic-gate switch (r = get_boolean(pg, SCF_PROPERTY_ENABLED, &enabled_8)) { 963*0Sstevel@tonic-gate case 0: 964*0Sstevel@tonic-gate *enabled_ovrp = enabled_8; 965*0Sstevel@tonic-gate break; 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate case ECONNABORTED: 968*0Sstevel@tonic-gate case ECANCELED: 969*0Sstevel@tonic-gate scf_pg_destroy(pg); 970*0Sstevel@tonic-gate return (r); 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate case ENOENT: 973*0Sstevel@tonic-gate case EINVAL: 974*0Sstevel@tonic-gate *enabled_ovrp = -1; 975*0Sstevel@tonic-gate break; 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate default: 978*0Sstevel@tonic-gate bad_error("get_boolean", r); 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate } 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate enabled: 983*0Sstevel@tonic-gate /* 984*0Sstevel@tonic-gate * Since general/restarter can be at the service level, we must do 985*0Sstevel@tonic-gate * a composed lookup. These properties are immediate, though, so we 986*0Sstevel@tonic-gate * must use the "editing" snapshot. Technically enabled shouldn't be 987*0Sstevel@tonic-gate * at the service level, but looking it up composed, too, doesn't 988*0Sstevel@tonic-gate * hurt. 989*0Sstevel@tonic-gate */ 990*0Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_GENERAL, pg) != 0) { 991*0Sstevel@tonic-gate scf_pg_destroy(pg); 992*0Sstevel@tonic-gate switch (scf_error()) { 993*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 994*0Sstevel@tonic-gate default: 995*0Sstevel@tonic-gate return (ECONNABORTED); 996*0Sstevel@tonic-gate 997*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 998*0Sstevel@tonic-gate return (ECANCELED); 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1001*0Sstevel@tonic-gate return (ENOENT); 1002*0Sstevel@tonic-gate 1003*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1004*0Sstevel@tonic-gate bad_error("scf_instance_get_pg_composed", scf_error()); 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate } 1007*0Sstevel@tonic-gate 1008*0Sstevel@tonic-gate switch (r = get_boolean(pg, SCF_PROPERTY_ENABLED, &enabled_8)) { 1009*0Sstevel@tonic-gate case 0: 1010*0Sstevel@tonic-gate *enabledp = enabled_8; 1011*0Sstevel@tonic-gate break; 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate case ECONNABORTED: 1014*0Sstevel@tonic-gate case ECANCELED: 1015*0Sstevel@tonic-gate scf_pg_destroy(pg); 1016*0Sstevel@tonic-gate return (r); 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate case ENOENT: 1019*0Sstevel@tonic-gate /* 1020*0Sstevel@tonic-gate * DEBUG because this happens when svccfg import creates 1021*0Sstevel@tonic-gate * a temporary service. 1022*0Sstevel@tonic-gate */ 1023*0Sstevel@tonic-gate log_framework(LOG_DEBUG, 1024*0Sstevel@tonic-gate "general/enabled property of %s is missing.\n", fmri); 1025*0Sstevel@tonic-gate *enabledp = -1; 1026*0Sstevel@tonic-gate break; 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate case EINVAL: 1029*0Sstevel@tonic-gate log_framework(LOG_ERR, 1030*0Sstevel@tonic-gate "general/enabled property of %s is invalid.\n", fmri); 1031*0Sstevel@tonic-gate *enabledp = -1; 1032*0Sstevel@tonic-gate break; 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate default: 1035*0Sstevel@tonic-gate bad_error("get_boolean", r); 1036*0Sstevel@tonic-gate } 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate if (restarter_fmri != NULL) 1039*0Sstevel@tonic-gate get_restarter(h, pg, restarter_fmri); 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate scf_pg_destroy(pg); 1042*0Sstevel@tonic-gate 1043*0Sstevel@tonic-gate return (0); 1044*0Sstevel@tonic-gate } 1045*0Sstevel@tonic-gate 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate /* 1048*0Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is 1049*0Sstevel@tonic-gate * added. 1050*0Sstevel@tonic-gate * 1051*0Sstevel@tonic-gate * Fails with 1052*0Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error 1053*0Sstevel@tonic-gate * ECANCELED - inst is deleted 1054*0Sstevel@tonic-gate * EPERM - permission is denied 1055*0Sstevel@tonic-gate * EACCES - backend denied access 1056*0Sstevel@tonic-gate * EROFS - backend readonly 1057*0Sstevel@tonic-gate */ 1058*0Sstevel@tonic-gate int 1059*0Sstevel@tonic-gate libscf_inst_get_or_add_pg(scf_instance_t *inst, const char *name, 1060*0Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 1061*0Sstevel@tonic-gate { 1062*0Sstevel@tonic-gate uint32_t f; 1063*0Sstevel@tonic-gate 1064*0Sstevel@tonic-gate again: 1065*0Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0) { 1066*0Sstevel@tonic-gate if (scf_pg_get_flags(pg, &f) != 0) { 1067*0Sstevel@tonic-gate switch (scf_error()) { 1068*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1069*0Sstevel@tonic-gate default: 1070*0Sstevel@tonic-gate return (ECONNABORTED); 1071*0Sstevel@tonic-gate 1072*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1073*0Sstevel@tonic-gate goto add; 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1076*0Sstevel@tonic-gate bad_error("scf_pg_get_flags", scf_error()); 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate if (f == flags) 1081*0Sstevel@tonic-gate return (0); 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate if (scf_pg_delete(pg) != 0) { 1084*0Sstevel@tonic-gate switch (scf_error()) { 1085*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1086*0Sstevel@tonic-gate default: 1087*0Sstevel@tonic-gate return (ECONNABORTED); 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1090*0Sstevel@tonic-gate break; 1091*0Sstevel@tonic-gate 1092*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1093*0Sstevel@tonic-gate return (EPERM); 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1096*0Sstevel@tonic-gate return (EACCES); 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1099*0Sstevel@tonic-gate return (EROFS); 1100*0Sstevel@tonic-gate 1101*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1102*0Sstevel@tonic-gate bad_error("scf_pg_delete", scf_error()); 1103*0Sstevel@tonic-gate } 1104*0Sstevel@tonic-gate } 1105*0Sstevel@tonic-gate } else { 1106*0Sstevel@tonic-gate switch (scf_error()) { 1107*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1108*0Sstevel@tonic-gate default: 1109*0Sstevel@tonic-gate return (ECONNABORTED); 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1112*0Sstevel@tonic-gate return (ECANCELED); 1113*0Sstevel@tonic-gate 1114*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1115*0Sstevel@tonic-gate break; 1116*0Sstevel@tonic-gate 1117*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1118*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1119*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1120*0Sstevel@tonic-gate bad_error("scf_instance_get_pg", scf_error()); 1121*0Sstevel@tonic-gate } 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate 1124*0Sstevel@tonic-gate add: 1125*0Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0) 1126*0Sstevel@tonic-gate return (0); 1127*0Sstevel@tonic-gate 1128*0Sstevel@tonic-gate switch (scf_error()) { 1129*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1130*0Sstevel@tonic-gate default: 1131*0Sstevel@tonic-gate return (ECONNABORTED); 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1134*0Sstevel@tonic-gate return (ECANCELED); 1135*0Sstevel@tonic-gate 1136*0Sstevel@tonic-gate case SCF_ERROR_EXISTS: 1137*0Sstevel@tonic-gate goto again; 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1140*0Sstevel@tonic-gate return (EPERM); 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1143*0Sstevel@tonic-gate return (EACCES); 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1146*0Sstevel@tonic-gate return (EROFS); 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1149*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1150*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1151*0Sstevel@tonic-gate bad_error("scf_instance_add_pg", scf_error()); 1152*0Sstevel@tonic-gate /* NOTREACHED */ 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate /* 1157*0Sstevel@tonic-gate * Returns 1158*0Sstevel@tonic-gate * 0 - success 1159*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 1160*0Sstevel@tonic-gate * - unknown libscf error 1161*0Sstevel@tonic-gate * ECANCELED 1162*0Sstevel@tonic-gate */ 1163*0Sstevel@tonic-gate static scf_error_t 1164*0Sstevel@tonic-gate transaction_add_set(scf_transaction_t *tx, scf_transaction_entry_t *ent, 1165*0Sstevel@tonic-gate const char *pname, scf_type_t ty) 1166*0Sstevel@tonic-gate { 1167*0Sstevel@tonic-gate for (;;) { 1168*0Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname, 1169*0Sstevel@tonic-gate ty) == 0) 1170*0Sstevel@tonic-gate return (0); 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate switch (scf_error()) { 1173*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1174*0Sstevel@tonic-gate default: 1175*0Sstevel@tonic-gate return (ECONNABORTED); 1176*0Sstevel@tonic-gate 1177*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1178*0Sstevel@tonic-gate return (ECANCELED); 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1181*0Sstevel@tonic-gate break; 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1184*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1185*0Sstevel@tonic-gate case SCF_ERROR_IN_USE: 1186*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1187*0Sstevel@tonic-gate bad_error("scf_transaction_property_change_type", 1188*0Sstevel@tonic-gate scf_error()); 1189*0Sstevel@tonic-gate } 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0) 1192*0Sstevel@tonic-gate return (0); 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate switch (scf_error()) { 1195*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1196*0Sstevel@tonic-gate default: 1197*0Sstevel@tonic-gate return (ECONNABORTED); 1198*0Sstevel@tonic-gate 1199*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1200*0Sstevel@tonic-gate return (ECANCELED); 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate case SCF_ERROR_EXISTS: 1203*0Sstevel@tonic-gate break; 1204*0Sstevel@tonic-gate 1205*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1206*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1207*0Sstevel@tonic-gate case SCF_ERROR_IN_USE: 1208*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1209*0Sstevel@tonic-gate bad_error("scf_transaction_property_new", scf_error()); 1210*0Sstevel@tonic-gate /* NOTREACHED */ 1211*0Sstevel@tonic-gate } 1212*0Sstevel@tonic-gate } 1213*0Sstevel@tonic-gate } 1214*0Sstevel@tonic-gate 1215*0Sstevel@tonic-gate /* 1216*0Sstevel@tonic-gate * Returns 1217*0Sstevel@tonic-gate * 0 - success 1218*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 1219*0Sstevel@tonic-gate * - unknown libscf error 1220*0Sstevel@tonic-gate * ECANCELED - pg was deleted 1221*0Sstevel@tonic-gate * EPERM 1222*0Sstevel@tonic-gate * EACCES 1223*0Sstevel@tonic-gate * EROFS 1224*0Sstevel@tonic-gate */ 1225*0Sstevel@tonic-gate static int 1226*0Sstevel@tonic-gate pg_set_prop_value(scf_propertygroup_t *pg, const char *pname, scf_value_t *v) 1227*0Sstevel@tonic-gate { 1228*0Sstevel@tonic-gate scf_handle_t *h; 1229*0Sstevel@tonic-gate scf_transaction_t *tx; 1230*0Sstevel@tonic-gate scf_transaction_entry_t *e; 1231*0Sstevel@tonic-gate scf_type_t ty; 1232*0Sstevel@tonic-gate scf_error_t scfe; 1233*0Sstevel@tonic-gate int ret, r; 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate h = scf_pg_handle(pg); 1236*0Sstevel@tonic-gate tx = safe_scf_transaction_create(h); 1237*0Sstevel@tonic-gate e = safe_scf_entry_create(h); 1238*0Sstevel@tonic-gate 1239*0Sstevel@tonic-gate ty = scf_value_type(v); 1240*0Sstevel@tonic-gate assert(ty != SCF_TYPE_INVALID); 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate for (;;) { 1243*0Sstevel@tonic-gate if (scf_transaction_start(tx, pg) != 0) { 1244*0Sstevel@tonic-gate switch (scf_error()) { 1245*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1246*0Sstevel@tonic-gate default: 1247*0Sstevel@tonic-gate ret = ECONNABORTED; 1248*0Sstevel@tonic-gate goto out; 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1251*0Sstevel@tonic-gate ret = ECANCELED; 1252*0Sstevel@tonic-gate goto out; 1253*0Sstevel@tonic-gate 1254*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1255*0Sstevel@tonic-gate ret = EPERM; 1256*0Sstevel@tonic-gate goto out; 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1259*0Sstevel@tonic-gate ret = EACCES; 1260*0Sstevel@tonic-gate goto out; 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1263*0Sstevel@tonic-gate ret = EROFS; 1264*0Sstevel@tonic-gate goto out; 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1267*0Sstevel@tonic-gate bad_error("scf_transaction_start", ret); 1268*0Sstevel@tonic-gate } 1269*0Sstevel@tonic-gate } 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate ret = transaction_add_set(tx, e, pname, ty); 1272*0Sstevel@tonic-gate switch (ret) { 1273*0Sstevel@tonic-gate case 0: 1274*0Sstevel@tonic-gate break; 1275*0Sstevel@tonic-gate 1276*0Sstevel@tonic-gate case ECONNABORTED: 1277*0Sstevel@tonic-gate case ECANCELED: 1278*0Sstevel@tonic-gate goto out; 1279*0Sstevel@tonic-gate 1280*0Sstevel@tonic-gate default: 1281*0Sstevel@tonic-gate bad_error("transaction_add_set", ret); 1282*0Sstevel@tonic-gate } 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate r = scf_entry_add_value(e, v); 1285*0Sstevel@tonic-gate assert(r == 0); 1286*0Sstevel@tonic-gate 1287*0Sstevel@tonic-gate r = scf_transaction_commit(tx); 1288*0Sstevel@tonic-gate if (r == 1) 1289*0Sstevel@tonic-gate break; 1290*0Sstevel@tonic-gate if (r != 0) { 1291*0Sstevel@tonic-gate scfe = scf_error(); 1292*0Sstevel@tonic-gate scf_transaction_reset(tx); 1293*0Sstevel@tonic-gate switch (scfe) { 1294*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1295*0Sstevel@tonic-gate default: 1296*0Sstevel@tonic-gate ret = ECONNABORTED; 1297*0Sstevel@tonic-gate goto out; 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1300*0Sstevel@tonic-gate ret = ECANCELED; 1301*0Sstevel@tonic-gate goto out; 1302*0Sstevel@tonic-gate 1303*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1304*0Sstevel@tonic-gate ret = EPERM; 1305*0Sstevel@tonic-gate goto out; 1306*0Sstevel@tonic-gate 1307*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1308*0Sstevel@tonic-gate ret = EACCES; 1309*0Sstevel@tonic-gate goto out; 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1312*0Sstevel@tonic-gate ret = EROFS; 1313*0Sstevel@tonic-gate goto out; 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1316*0Sstevel@tonic-gate bad_error("scf_transaction_commit", scfe); 1317*0Sstevel@tonic-gate } 1318*0Sstevel@tonic-gate } 1319*0Sstevel@tonic-gate 1320*0Sstevel@tonic-gate scf_transaction_reset(tx); 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 1323*0Sstevel@tonic-gate switch (scf_error()) { 1324*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1325*0Sstevel@tonic-gate default: 1326*0Sstevel@tonic-gate ret = ECONNABORTED; 1327*0Sstevel@tonic-gate goto out; 1328*0Sstevel@tonic-gate 1329*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1330*0Sstevel@tonic-gate ret = ECANCELED; 1331*0Sstevel@tonic-gate goto out; 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1334*0Sstevel@tonic-gate bad_error("scf_pg_update", scf_error()); 1335*0Sstevel@tonic-gate } 1336*0Sstevel@tonic-gate } 1337*0Sstevel@tonic-gate } 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate ret = 0; 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate out: 1342*0Sstevel@tonic-gate scf_transaction_destroy(tx); 1343*0Sstevel@tonic-gate scf_entry_destroy(e); 1344*0Sstevel@tonic-gate return (ret); 1345*0Sstevel@tonic-gate } 1346*0Sstevel@tonic-gate 1347*0Sstevel@tonic-gate /* 1348*0Sstevel@tonic-gate * Returns 1349*0Sstevel@tonic-gate * 0 - success 1350*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 1351*0Sstevel@tonic-gate * - unknown libscf error 1352*0Sstevel@tonic-gate * ECANCELED - inst was deleted 1353*0Sstevel@tonic-gate * EPERM 1354*0Sstevel@tonic-gate * EACCES 1355*0Sstevel@tonic-gate * EROFS 1356*0Sstevel@tonic-gate */ 1357*0Sstevel@tonic-gate int 1358*0Sstevel@tonic-gate libscf_inst_set_boolean_prop(scf_instance_t *inst, const char *pgname, 1359*0Sstevel@tonic-gate const char *pgtype, uint32_t pgflags, const char *pname, int val) 1360*0Sstevel@tonic-gate { 1361*0Sstevel@tonic-gate scf_handle_t *h; 1362*0Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 1363*0Sstevel@tonic-gate scf_value_t *v; 1364*0Sstevel@tonic-gate int ret = 0; 1365*0Sstevel@tonic-gate 1366*0Sstevel@tonic-gate h = scf_instance_handle(inst); 1367*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 1368*0Sstevel@tonic-gate v = safe_scf_value_create(h); 1369*0Sstevel@tonic-gate 1370*0Sstevel@tonic-gate ret = libscf_inst_get_or_add_pg(inst, pgname, pgtype, pgflags, pg); 1371*0Sstevel@tonic-gate switch (ret) { 1372*0Sstevel@tonic-gate case 0: 1373*0Sstevel@tonic-gate break; 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate case ECONNABORTED: 1376*0Sstevel@tonic-gate case ECANCELED: 1377*0Sstevel@tonic-gate case EPERM: 1378*0Sstevel@tonic-gate case EACCES: 1379*0Sstevel@tonic-gate case EROFS: 1380*0Sstevel@tonic-gate goto out; 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate default: 1383*0Sstevel@tonic-gate bad_error("libscf_inst_get_or_add_pg", ret); 1384*0Sstevel@tonic-gate } 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate scf_value_set_boolean(v, val); 1387*0Sstevel@tonic-gate 1388*0Sstevel@tonic-gate ret = pg_set_prop_value(pg, pname, v); 1389*0Sstevel@tonic-gate switch (ret) { 1390*0Sstevel@tonic-gate case 0: 1391*0Sstevel@tonic-gate case ECONNABORTED: 1392*0Sstevel@tonic-gate case ECANCELED: 1393*0Sstevel@tonic-gate case EPERM: 1394*0Sstevel@tonic-gate case EACCES: 1395*0Sstevel@tonic-gate case EROFS: 1396*0Sstevel@tonic-gate break; 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gate default: 1399*0Sstevel@tonic-gate bad_error("pg_set_prop_value", ret); 1400*0Sstevel@tonic-gate } 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate out: 1403*0Sstevel@tonic-gate scf_pg_destroy(pg); 1404*0Sstevel@tonic-gate scf_value_destroy(v); 1405*0Sstevel@tonic-gate return (ret); 1406*0Sstevel@tonic-gate } 1407*0Sstevel@tonic-gate 1408*0Sstevel@tonic-gate /* 1409*0Sstevel@tonic-gate * Returns 1410*0Sstevel@tonic-gate * 0 - success 1411*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 1412*0Sstevel@tonic-gate * - unknown libscf error 1413*0Sstevel@tonic-gate * ECANCELED - inst was deleted 1414*0Sstevel@tonic-gate * EPERM 1415*0Sstevel@tonic-gate * EACCES 1416*0Sstevel@tonic-gate * EROFS 1417*0Sstevel@tonic-gate */ 1418*0Sstevel@tonic-gate int 1419*0Sstevel@tonic-gate libscf_inst_set_count_prop(scf_instance_t *inst, const char *pgname, 1420*0Sstevel@tonic-gate const char *pgtype, uint32_t pgflags, const char *pname, uint64_t count) 1421*0Sstevel@tonic-gate { 1422*0Sstevel@tonic-gate scf_handle_t *h; 1423*0Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 1424*0Sstevel@tonic-gate scf_value_t *v; 1425*0Sstevel@tonic-gate int ret = 0; 1426*0Sstevel@tonic-gate 1427*0Sstevel@tonic-gate h = scf_instance_handle(inst); 1428*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 1429*0Sstevel@tonic-gate v = safe_scf_value_create(h); 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate ret = libscf_inst_get_or_add_pg(inst, pgname, pgtype, pgflags, pg); 1432*0Sstevel@tonic-gate switch (ret) { 1433*0Sstevel@tonic-gate case 0: 1434*0Sstevel@tonic-gate break; 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate case ECONNABORTED: 1437*0Sstevel@tonic-gate case ECANCELED: 1438*0Sstevel@tonic-gate case EPERM: 1439*0Sstevel@tonic-gate case EACCES: 1440*0Sstevel@tonic-gate case EROFS: 1441*0Sstevel@tonic-gate goto out; 1442*0Sstevel@tonic-gate 1443*0Sstevel@tonic-gate default: 1444*0Sstevel@tonic-gate bad_error("libscf_inst_get_or_add_pg", ret); 1445*0Sstevel@tonic-gate } 1446*0Sstevel@tonic-gate 1447*0Sstevel@tonic-gate scf_value_set_count(v, count); 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate ret = pg_set_prop_value(pg, pname, v); 1450*0Sstevel@tonic-gate switch (ret) { 1451*0Sstevel@tonic-gate case 0: 1452*0Sstevel@tonic-gate case ECONNABORTED: 1453*0Sstevel@tonic-gate case ECANCELED: 1454*0Sstevel@tonic-gate case EPERM: 1455*0Sstevel@tonic-gate case EACCES: 1456*0Sstevel@tonic-gate case EROFS: 1457*0Sstevel@tonic-gate break; 1458*0Sstevel@tonic-gate 1459*0Sstevel@tonic-gate default: 1460*0Sstevel@tonic-gate bad_error("pg_set_prop_value", ret); 1461*0Sstevel@tonic-gate } 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate out: 1464*0Sstevel@tonic-gate scf_pg_destroy(pg); 1465*0Sstevel@tonic-gate scf_value_destroy(v); 1466*0Sstevel@tonic-gate return (ret); 1467*0Sstevel@tonic-gate } 1468*0Sstevel@tonic-gate 1469*0Sstevel@tonic-gate /* 1470*0Sstevel@tonic-gate * Returns 0 on success, ECONNABORTED if the repository connection is broken, 1471*0Sstevel@tonic-gate * ECANCELED if inst is deleted, EROFS if the backend is readonly, or EPERM if 1472*0Sstevel@tonic-gate * permission was denied. 1473*0Sstevel@tonic-gate */ 1474*0Sstevel@tonic-gate int 1475*0Sstevel@tonic-gate libscf_set_enable_ovr(scf_instance_t *inst, int enable) 1476*0Sstevel@tonic-gate { 1477*0Sstevel@tonic-gate return (libscf_inst_set_boolean_prop(inst, SCF_PG_GENERAL_OVR, 1478*0Sstevel@tonic-gate SCF_PG_GENERAL_OVR_TYPE, SCF_PG_GENERAL_OVR_FLAGS, 1479*0Sstevel@tonic-gate SCF_PROPERTY_ENABLED, enable)); 1480*0Sstevel@tonic-gate } 1481*0Sstevel@tonic-gate 1482*0Sstevel@tonic-gate /* 1483*0Sstevel@tonic-gate * Returns 1484*0Sstevel@tonic-gate * 0 - success 1485*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 1486*0Sstevel@tonic-gate * ECANCELED - inst was deleted 1487*0Sstevel@tonic-gate * EPERM 1488*0Sstevel@tonic-gate * EACCES 1489*0Sstevel@tonic-gate * EROFS 1490*0Sstevel@tonic-gate */ 1491*0Sstevel@tonic-gate int 1492*0Sstevel@tonic-gate libscf_inst_delete_prop(scf_instance_t *inst, const char *pgname, 1493*0Sstevel@tonic-gate const char *pname) 1494*0Sstevel@tonic-gate { 1495*0Sstevel@tonic-gate scf_handle_t *h; 1496*0Sstevel@tonic-gate scf_propertygroup_t *pg; 1497*0Sstevel@tonic-gate scf_transaction_t *tx; 1498*0Sstevel@tonic-gate scf_transaction_entry_t *e; 1499*0Sstevel@tonic-gate scf_error_t serr; 1500*0Sstevel@tonic-gate int ret = 0, r; 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate h = scf_instance_handle(inst); 1503*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 1504*0Sstevel@tonic-gate 1505*0Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) != 0) { 1506*0Sstevel@tonic-gate scf_pg_destroy(pg); 1507*0Sstevel@tonic-gate switch (scf_error()) { 1508*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1509*0Sstevel@tonic-gate default: 1510*0Sstevel@tonic-gate return (ECONNABORTED); 1511*0Sstevel@tonic-gate 1512*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1513*0Sstevel@tonic-gate return (ECANCELED); 1514*0Sstevel@tonic-gate 1515*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1516*0Sstevel@tonic-gate return (0); 1517*0Sstevel@tonic-gate 1518*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1519*0Sstevel@tonic-gate bad_error("scf_instance_get_pg", scf_error()); 1520*0Sstevel@tonic-gate } 1521*0Sstevel@tonic-gate } 1522*0Sstevel@tonic-gate 1523*0Sstevel@tonic-gate tx = safe_scf_transaction_create(h); 1524*0Sstevel@tonic-gate e = safe_scf_entry_create(h); 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate for (;;) { 1527*0Sstevel@tonic-gate if (scf_transaction_start(tx, pg) != 0) { 1528*0Sstevel@tonic-gate switch (scf_error()) { 1529*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1530*0Sstevel@tonic-gate default: 1531*0Sstevel@tonic-gate ret = ECONNABORTED; 1532*0Sstevel@tonic-gate goto out; 1533*0Sstevel@tonic-gate 1534*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1535*0Sstevel@tonic-gate ret = 0; 1536*0Sstevel@tonic-gate goto out; 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1539*0Sstevel@tonic-gate ret = EPERM; 1540*0Sstevel@tonic-gate goto out; 1541*0Sstevel@tonic-gate 1542*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1543*0Sstevel@tonic-gate ret = EACCES; 1544*0Sstevel@tonic-gate goto out; 1545*0Sstevel@tonic-gate 1546*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1547*0Sstevel@tonic-gate ret = EROFS; 1548*0Sstevel@tonic-gate goto out; 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1551*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1552*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1553*0Sstevel@tonic-gate bad_error("scf_transaction_start", scf_error()); 1554*0Sstevel@tonic-gate } 1555*0Sstevel@tonic-gate } 1556*0Sstevel@tonic-gate 1557*0Sstevel@tonic-gate if (scf_transaction_property_delete(tx, e, pname) != 0) { 1558*0Sstevel@tonic-gate switch (scf_error()) { 1559*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1560*0Sstevel@tonic-gate default: 1561*0Sstevel@tonic-gate ret = ECONNABORTED; 1562*0Sstevel@tonic-gate goto out; 1563*0Sstevel@tonic-gate 1564*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1565*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1566*0Sstevel@tonic-gate ret = 0; 1567*0Sstevel@tonic-gate goto out; 1568*0Sstevel@tonic-gate 1569*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1570*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1571*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 1572*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1573*0Sstevel@tonic-gate bad_error("scf_transaction_property_delete", 1574*0Sstevel@tonic-gate scf_error()); 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate } 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gate r = scf_transaction_commit(tx); 1579*0Sstevel@tonic-gate if (r == 1) 1580*0Sstevel@tonic-gate break; 1581*0Sstevel@tonic-gate if (r != 0) { 1582*0Sstevel@tonic-gate serr = scf_error(); 1583*0Sstevel@tonic-gate scf_transaction_reset(tx); 1584*0Sstevel@tonic-gate switch (serr) { 1585*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1586*0Sstevel@tonic-gate default: 1587*0Sstevel@tonic-gate ret = ECONNABORTED; 1588*0Sstevel@tonic-gate goto out; 1589*0Sstevel@tonic-gate 1590*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1591*0Sstevel@tonic-gate ret = 0; 1592*0Sstevel@tonic-gate goto out; 1593*0Sstevel@tonic-gate 1594*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1595*0Sstevel@tonic-gate ret = EPERM; 1596*0Sstevel@tonic-gate goto out; 1597*0Sstevel@tonic-gate 1598*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1599*0Sstevel@tonic-gate ret = EACCES; 1600*0Sstevel@tonic-gate goto out; 1601*0Sstevel@tonic-gate 1602*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1603*0Sstevel@tonic-gate ret = EROFS; 1604*0Sstevel@tonic-gate goto out; 1605*0Sstevel@tonic-gate 1606*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1607*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1608*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 1609*0Sstevel@tonic-gate bad_error("scf_transaction_commit", serr); 1610*0Sstevel@tonic-gate } 1611*0Sstevel@tonic-gate } 1612*0Sstevel@tonic-gate 1613*0Sstevel@tonic-gate scf_transaction_reset(tx); 1614*0Sstevel@tonic-gate 1615*0Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 1616*0Sstevel@tonic-gate switch (scf_error()) { 1617*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1618*0Sstevel@tonic-gate default: 1619*0Sstevel@tonic-gate ret = ECONNABORTED; 1620*0Sstevel@tonic-gate goto out; 1621*0Sstevel@tonic-gate 1622*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1623*0Sstevel@tonic-gate ret = 0; 1624*0Sstevel@tonic-gate goto out; 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1627*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 1628*0Sstevel@tonic-gate bad_error("scf_pg_update", scf_error()); 1629*0Sstevel@tonic-gate } 1630*0Sstevel@tonic-gate } 1631*0Sstevel@tonic-gate } 1632*0Sstevel@tonic-gate 1633*0Sstevel@tonic-gate out: 1634*0Sstevel@tonic-gate scf_transaction_destroy(tx); 1635*0Sstevel@tonic-gate (void) scf_entry_destroy(e); 1636*0Sstevel@tonic-gate scf_pg_destroy(pg); 1637*0Sstevel@tonic-gate return (ret); 1638*0Sstevel@tonic-gate } 1639*0Sstevel@tonic-gate 1640*0Sstevel@tonic-gate /* 1641*0Sstevel@tonic-gate * Returns 0, ECONNABORTED, ECANCELED, or EPERM. 1642*0Sstevel@tonic-gate */ 1643*0Sstevel@tonic-gate int 1644*0Sstevel@tonic-gate libscf_delete_enable_ovr(scf_instance_t *inst) 1645*0Sstevel@tonic-gate { 1646*0Sstevel@tonic-gate return (libscf_inst_delete_prop(inst, SCF_PG_GENERAL_OVR, 1647*0Sstevel@tonic-gate SCF_PROPERTY_ENABLED)); 1648*0Sstevel@tonic-gate } 1649*0Sstevel@tonic-gate 1650*0Sstevel@tonic-gate /* 1651*0Sstevel@tonic-gate * Fails with 1652*0Sstevel@tonic-gate * ECONNABORTED - repository connection was broken 1653*0Sstevel@tonic-gate * ECANCELED - pg was deleted 1654*0Sstevel@tonic-gate * ENOENT - pg has no milestone property 1655*0Sstevel@tonic-gate * EINVAL - the milestone property is misconfigured 1656*0Sstevel@tonic-gate */ 1657*0Sstevel@tonic-gate static int 1658*0Sstevel@tonic-gate pg_get_milestone(scf_propertygroup_t *pg, scf_property_t *prop, 1659*0Sstevel@tonic-gate scf_value_t *val, char *buf, size_t buf_sz) 1660*0Sstevel@tonic-gate { 1661*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_MILESTONE, prop) != 0) { 1662*0Sstevel@tonic-gate switch (scf_error()) { 1663*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1664*0Sstevel@tonic-gate default: 1665*0Sstevel@tonic-gate return (ECONNABORTED); 1666*0Sstevel@tonic-gate 1667*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1668*0Sstevel@tonic-gate return (ECANCELED); 1669*0Sstevel@tonic-gate 1670*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1671*0Sstevel@tonic-gate return (ENOENT); 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1674*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1675*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1676*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 1677*0Sstevel@tonic-gate } 1678*0Sstevel@tonic-gate } 1679*0Sstevel@tonic-gate 1680*0Sstevel@tonic-gate if (scf_property_get_value(prop, val) != 0) { 1681*0Sstevel@tonic-gate switch (scf_error()) { 1682*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1683*0Sstevel@tonic-gate default: 1684*0Sstevel@tonic-gate return (ECONNABORTED); 1685*0Sstevel@tonic-gate 1686*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1687*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 1688*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1689*0Sstevel@tonic-gate return (EINVAL); 1690*0Sstevel@tonic-gate 1691*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1692*0Sstevel@tonic-gate bad_error("scf_property_get_value", scf_error()); 1693*0Sstevel@tonic-gate } 1694*0Sstevel@tonic-gate } 1695*0Sstevel@tonic-gate 1696*0Sstevel@tonic-gate if (scf_value_get_astring(val, buf, buf_sz) < 0) { 1697*0Sstevel@tonic-gate switch (scf_error()) { 1698*0Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 1699*0Sstevel@tonic-gate return (EINVAL); 1700*0Sstevel@tonic-gate 1701*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1702*0Sstevel@tonic-gate default: 1703*0Sstevel@tonic-gate bad_error("scf_value_get_astring", scf_error()); 1704*0Sstevel@tonic-gate } 1705*0Sstevel@tonic-gate } 1706*0Sstevel@tonic-gate 1707*0Sstevel@tonic-gate return (0); 1708*0Sstevel@tonic-gate } 1709*0Sstevel@tonic-gate 1710*0Sstevel@tonic-gate /* 1711*0Sstevel@tonic-gate * Fails with 1712*0Sstevel@tonic-gate * ECONNABORTED - repository connection was broken 1713*0Sstevel@tonic-gate * ECANCELED - inst was deleted 1714*0Sstevel@tonic-gate * ENOENT - inst has no milestone property 1715*0Sstevel@tonic-gate * EINVAL - the milestone property is misconfigured 1716*0Sstevel@tonic-gate */ 1717*0Sstevel@tonic-gate int 1718*0Sstevel@tonic-gate libscf_get_milestone(scf_instance_t *inst, scf_property_t *prop, 1719*0Sstevel@tonic-gate scf_value_t *val, char *buf, size_t buf_sz) 1720*0Sstevel@tonic-gate { 1721*0Sstevel@tonic-gate scf_propertygroup_t *pg; 1722*0Sstevel@tonic-gate int r; 1723*0Sstevel@tonic-gate 1724*0Sstevel@tonic-gate pg = safe_scf_pg_create(scf_instance_handle(inst)); 1725*0Sstevel@tonic-gate 1726*0Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_OPTIONS_OVR, pg) == 0) { 1727*0Sstevel@tonic-gate switch (r = pg_get_milestone(pg, prop, val, buf, buf_sz)) { 1728*0Sstevel@tonic-gate case 0: 1729*0Sstevel@tonic-gate case ECONNABORTED: 1730*0Sstevel@tonic-gate case EINVAL: 1731*0Sstevel@tonic-gate goto out; 1732*0Sstevel@tonic-gate 1733*0Sstevel@tonic-gate case ECANCELED: 1734*0Sstevel@tonic-gate case ENOENT: 1735*0Sstevel@tonic-gate break; 1736*0Sstevel@tonic-gate 1737*0Sstevel@tonic-gate default: 1738*0Sstevel@tonic-gate bad_error("pg_get_milestone", r); 1739*0Sstevel@tonic-gate } 1740*0Sstevel@tonic-gate } else { 1741*0Sstevel@tonic-gate switch (scf_error()) { 1742*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1743*0Sstevel@tonic-gate default: 1744*0Sstevel@tonic-gate r = ECONNABORTED; 1745*0Sstevel@tonic-gate goto out; 1746*0Sstevel@tonic-gate 1747*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1748*0Sstevel@tonic-gate r = ECANCELED; 1749*0Sstevel@tonic-gate goto out; 1750*0Sstevel@tonic-gate 1751*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1752*0Sstevel@tonic-gate break; 1753*0Sstevel@tonic-gate 1754*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1755*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1756*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1757*0Sstevel@tonic-gate bad_error("scf_instance_get_pg", scf_error()); 1758*0Sstevel@tonic-gate } 1759*0Sstevel@tonic-gate } 1760*0Sstevel@tonic-gate 1761*0Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_OPTIONS, pg) == 0) { 1762*0Sstevel@tonic-gate r = pg_get_milestone(pg, prop, val, buf, buf_sz); 1763*0Sstevel@tonic-gate } else { 1764*0Sstevel@tonic-gate switch (scf_error()) { 1765*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1766*0Sstevel@tonic-gate default: 1767*0Sstevel@tonic-gate r = ECONNABORTED; 1768*0Sstevel@tonic-gate goto out; 1769*0Sstevel@tonic-gate 1770*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1771*0Sstevel@tonic-gate r = ECANCELED; 1772*0Sstevel@tonic-gate goto out; 1773*0Sstevel@tonic-gate 1774*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1775*0Sstevel@tonic-gate r = ENOENT; 1776*0Sstevel@tonic-gate break; 1777*0Sstevel@tonic-gate 1778*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1779*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1780*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1781*0Sstevel@tonic-gate bad_error("scf_instance_get_pg", scf_error()); 1782*0Sstevel@tonic-gate } 1783*0Sstevel@tonic-gate } 1784*0Sstevel@tonic-gate 1785*0Sstevel@tonic-gate out: 1786*0Sstevel@tonic-gate scf_pg_destroy(pg); 1787*0Sstevel@tonic-gate 1788*0Sstevel@tonic-gate return (r); 1789*0Sstevel@tonic-gate } 1790*0Sstevel@tonic-gate 1791*0Sstevel@tonic-gate /* 1792*0Sstevel@tonic-gate * Get the runlevel character from the runlevel property of the given property 1793*0Sstevel@tonic-gate * group. Fails with 1794*0Sstevel@tonic-gate * ECONNABORTED - repository connection was broken 1795*0Sstevel@tonic-gate * ECANCELED - prop's property group was deleted 1796*0Sstevel@tonic-gate * ENOENT - the property has no values 1797*0Sstevel@tonic-gate * EINVAL - the property has more than one value 1798*0Sstevel@tonic-gate * the property is of the wrong type 1799*0Sstevel@tonic-gate * the property value is malformed 1800*0Sstevel@tonic-gate */ 1801*0Sstevel@tonic-gate int 1802*0Sstevel@tonic-gate libscf_extract_runlevel(scf_property_t *prop, char *rlp) 1803*0Sstevel@tonic-gate { 1804*0Sstevel@tonic-gate scf_value_t *val; 1805*0Sstevel@tonic-gate char buf[2]; 1806*0Sstevel@tonic-gate 1807*0Sstevel@tonic-gate val = safe_scf_value_create(scf_property_handle(prop)); 1808*0Sstevel@tonic-gate 1809*0Sstevel@tonic-gate if (scf_property_get_value(prop, val) != 0) { 1810*0Sstevel@tonic-gate switch (scf_error()) { 1811*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1812*0Sstevel@tonic-gate return (ECONNABORTED); 1813*0Sstevel@tonic-gate 1814*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1815*0Sstevel@tonic-gate return (ENOENT); 1816*0Sstevel@tonic-gate 1817*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1818*0Sstevel@tonic-gate return (ECANCELED); 1819*0Sstevel@tonic-gate 1820*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 1821*0Sstevel@tonic-gate return (EINVAL); 1822*0Sstevel@tonic-gate 1823*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1824*0Sstevel@tonic-gate return (ENOENT); 1825*0Sstevel@tonic-gate 1826*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1827*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 1828*0Sstevel@tonic-gate default: 1829*0Sstevel@tonic-gate bad_error("scf_property_get_value", scf_error()); 1830*0Sstevel@tonic-gate } 1831*0Sstevel@tonic-gate } 1832*0Sstevel@tonic-gate 1833*0Sstevel@tonic-gate if (scf_value_get_astring(val, buf, sizeof (buf)) < 0) { 1834*0Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH) 1835*0Sstevel@tonic-gate bad_error("scf_value_get_astring", scf_error()); 1836*0Sstevel@tonic-gate 1837*0Sstevel@tonic-gate return (EINVAL); 1838*0Sstevel@tonic-gate } 1839*0Sstevel@tonic-gate 1840*0Sstevel@tonic-gate if (buf[0] == '\0' || buf[1] != '\0') 1841*0Sstevel@tonic-gate return (EINVAL); 1842*0Sstevel@tonic-gate 1843*0Sstevel@tonic-gate *rlp = buf[0]; 1844*0Sstevel@tonic-gate 1845*0Sstevel@tonic-gate return (0); 1846*0Sstevel@tonic-gate } 1847*0Sstevel@tonic-gate 1848*0Sstevel@tonic-gate /* 1849*0Sstevel@tonic-gate * Delete the "runlevel" property from the given property group. Also set the 1850*0Sstevel@tonic-gate * "milestone" property to the given string. Fails with ECONNABORTED, 1851*0Sstevel@tonic-gate * ECANCELED, EPERM, EACCES, or EROFS. 1852*0Sstevel@tonic-gate */ 1853*0Sstevel@tonic-gate int 1854*0Sstevel@tonic-gate libscf_clear_runlevel(scf_propertygroup_t *pg, const char *milestone) 1855*0Sstevel@tonic-gate { 1856*0Sstevel@tonic-gate scf_handle_t *h; 1857*0Sstevel@tonic-gate scf_transaction_t *tx; 1858*0Sstevel@tonic-gate scf_transaction_entry_t *e_rl, *e_ms; 1859*0Sstevel@tonic-gate scf_value_t *val; 1860*0Sstevel@tonic-gate scf_error_t serr; 1861*0Sstevel@tonic-gate boolean_t isempty = B_TRUE; 1862*0Sstevel@tonic-gate int ret = 0, r; 1863*0Sstevel@tonic-gate 1864*0Sstevel@tonic-gate h = scf_pg_handle(pg); 1865*0Sstevel@tonic-gate tx = safe_scf_transaction_create(h); 1866*0Sstevel@tonic-gate e_rl = safe_scf_entry_create(h); 1867*0Sstevel@tonic-gate e_ms = safe_scf_entry_create(h); 1868*0Sstevel@tonic-gate val = safe_scf_value_create(h); 1869*0Sstevel@tonic-gate 1870*0Sstevel@tonic-gate if (milestone) { 1871*0Sstevel@tonic-gate r = scf_value_set_astring(val, milestone); 1872*0Sstevel@tonic-gate assert(r == 0); 1873*0Sstevel@tonic-gate } 1874*0Sstevel@tonic-gate 1875*0Sstevel@tonic-gate for (;;) { 1876*0Sstevel@tonic-gate if (scf_transaction_start(tx, pg) != 0) { 1877*0Sstevel@tonic-gate switch (scf_error()) { 1878*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1879*0Sstevel@tonic-gate default: 1880*0Sstevel@tonic-gate ret = ECONNABORTED; 1881*0Sstevel@tonic-gate goto out; 1882*0Sstevel@tonic-gate 1883*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1884*0Sstevel@tonic-gate ret = ECANCELED; 1885*0Sstevel@tonic-gate goto out; 1886*0Sstevel@tonic-gate 1887*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1888*0Sstevel@tonic-gate ret = EPERM; 1889*0Sstevel@tonic-gate goto out; 1890*0Sstevel@tonic-gate 1891*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1892*0Sstevel@tonic-gate ret = EACCES; 1893*0Sstevel@tonic-gate goto out; 1894*0Sstevel@tonic-gate 1895*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1896*0Sstevel@tonic-gate ret = EROFS; 1897*0Sstevel@tonic-gate goto out; 1898*0Sstevel@tonic-gate 1899*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1900*0Sstevel@tonic-gate bad_error("scf_transaction_start", scf_error()); 1901*0Sstevel@tonic-gate } 1902*0Sstevel@tonic-gate } 1903*0Sstevel@tonic-gate 1904*0Sstevel@tonic-gate if (scf_transaction_property_delete(tx, e_rl, 1905*0Sstevel@tonic-gate "runlevel") == 0) { 1906*0Sstevel@tonic-gate isempty = B_FALSE; 1907*0Sstevel@tonic-gate } else { 1908*0Sstevel@tonic-gate switch (scf_error()) { 1909*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1910*0Sstevel@tonic-gate default: 1911*0Sstevel@tonic-gate ret = ECONNABORTED; 1912*0Sstevel@tonic-gate goto out; 1913*0Sstevel@tonic-gate 1914*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 1915*0Sstevel@tonic-gate ret = ECANCELED; 1916*0Sstevel@tonic-gate goto out; 1917*0Sstevel@tonic-gate 1918*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1919*0Sstevel@tonic-gate break; 1920*0Sstevel@tonic-gate 1921*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1922*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 1923*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1924*0Sstevel@tonic-gate bad_error("scf_transaction_property_delete", 1925*0Sstevel@tonic-gate scf_error()); 1926*0Sstevel@tonic-gate } 1927*0Sstevel@tonic-gate } 1928*0Sstevel@tonic-gate 1929*0Sstevel@tonic-gate if (milestone) { 1930*0Sstevel@tonic-gate ret = transaction_add_set(tx, e_ms, 1931*0Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_TYPE_ASTRING); 1932*0Sstevel@tonic-gate switch (ret) { 1933*0Sstevel@tonic-gate case 0: 1934*0Sstevel@tonic-gate break; 1935*0Sstevel@tonic-gate 1936*0Sstevel@tonic-gate case ECONNABORTED: 1937*0Sstevel@tonic-gate case ECANCELED: 1938*0Sstevel@tonic-gate goto out; 1939*0Sstevel@tonic-gate 1940*0Sstevel@tonic-gate default: 1941*0Sstevel@tonic-gate bad_error("transaction_add_set", ret); 1942*0Sstevel@tonic-gate } 1943*0Sstevel@tonic-gate 1944*0Sstevel@tonic-gate isempty = B_FALSE; 1945*0Sstevel@tonic-gate 1946*0Sstevel@tonic-gate r = scf_entry_add_value(e_ms, val); 1947*0Sstevel@tonic-gate assert(r == 0); 1948*0Sstevel@tonic-gate } 1949*0Sstevel@tonic-gate 1950*0Sstevel@tonic-gate if (isempty) 1951*0Sstevel@tonic-gate goto out; 1952*0Sstevel@tonic-gate 1953*0Sstevel@tonic-gate r = scf_transaction_commit(tx); 1954*0Sstevel@tonic-gate if (r == 1) 1955*0Sstevel@tonic-gate break; 1956*0Sstevel@tonic-gate if (r != 0) { 1957*0Sstevel@tonic-gate serr = scf_error(); 1958*0Sstevel@tonic-gate scf_transaction_reset(tx); 1959*0Sstevel@tonic-gate switch (serr) { 1960*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1961*0Sstevel@tonic-gate ret = ECONNABORTED; 1962*0Sstevel@tonic-gate goto out; 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1965*0Sstevel@tonic-gate ret = EPERM; 1966*0Sstevel@tonic-gate goto out; 1967*0Sstevel@tonic-gate 1968*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1969*0Sstevel@tonic-gate ret = EACCES; 1970*0Sstevel@tonic-gate goto out; 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1973*0Sstevel@tonic-gate ret = EROFS; 1974*0Sstevel@tonic-gate goto out; 1975*0Sstevel@tonic-gate 1976*0Sstevel@tonic-gate default: 1977*0Sstevel@tonic-gate bad_error("scf_transaction_commit", serr); 1978*0Sstevel@tonic-gate } 1979*0Sstevel@tonic-gate } 1980*0Sstevel@tonic-gate 1981*0Sstevel@tonic-gate scf_transaction_reset(tx); 1982*0Sstevel@tonic-gate 1983*0Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 1984*0Sstevel@tonic-gate switch (scf_error()) { 1985*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1986*0Sstevel@tonic-gate ret = ECONNABORTED; 1987*0Sstevel@tonic-gate goto out; 1988*0Sstevel@tonic-gate 1989*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1990*0Sstevel@tonic-gate ret = ECANCELED; 1991*0Sstevel@tonic-gate goto out; 1992*0Sstevel@tonic-gate 1993*0Sstevel@tonic-gate default: 1994*0Sstevel@tonic-gate assert(0); 1995*0Sstevel@tonic-gate abort(); 1996*0Sstevel@tonic-gate } 1997*0Sstevel@tonic-gate } 1998*0Sstevel@tonic-gate } 1999*0Sstevel@tonic-gate 2000*0Sstevel@tonic-gate out: 2001*0Sstevel@tonic-gate scf_transaction_destroy(tx); 2002*0Sstevel@tonic-gate scf_entry_destroy(e_rl); 2003*0Sstevel@tonic-gate scf_entry_destroy(e_ms); 2004*0Sstevel@tonic-gate scf_value_destroy(val); 2005*0Sstevel@tonic-gate return (ret); 2006*0Sstevel@tonic-gate } 2007*0Sstevel@tonic-gate 2008*0Sstevel@tonic-gate /* 2009*0Sstevel@tonic-gate * int libscf_get_template_values(scf_instance_t *, scf_snapshot_t *, 2010*0Sstevel@tonic-gate * char **) 2011*0Sstevel@tonic-gate * 2012*0Sstevel@tonic-gate * Return template values for inst in *common_name suitable for use in 2013*0Sstevel@tonic-gate * restarter_inst_t->ri_common_name. Called by restarter_insert_inst(). 2014*0Sstevel@tonic-gate * 2015*0Sstevel@tonic-gate * Returns 0 on success, ECANCELED if the instance is deleted, ECHILD if 2016*0Sstevel@tonic-gate * a value fetch failed for a property, ENOENT if the instance has no 2017*0Sstevel@tonic-gate * tm_common_name property group or the property group is deleted, and 2018*0Sstevel@tonic-gate * ECONNABORTED if the repository connection is broken. 2019*0Sstevel@tonic-gate */ 2020*0Sstevel@tonic-gate int 2021*0Sstevel@tonic-gate libscf_get_template_values(scf_instance_t *inst, scf_snapshot_t *snap, 2022*0Sstevel@tonic-gate char **common_name, char **c_common_name) 2023*0Sstevel@tonic-gate { 2024*0Sstevel@tonic-gate scf_handle_t *h; 2025*0Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 2026*0Sstevel@tonic-gate scf_property_t *prop = NULL; 2027*0Sstevel@tonic-gate int ret = 0, r; 2028*0Sstevel@tonic-gate char *cname = startd_alloc(max_scf_value_size); 2029*0Sstevel@tonic-gate char *c_cname = startd_alloc(max_scf_value_size); 2030*0Sstevel@tonic-gate 2031*0Sstevel@tonic-gate h = scf_instance_handle(inst); 2032*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2033*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate /* 2036*0Sstevel@tonic-gate * The tm_common_name property group, as with all template property 2037*0Sstevel@tonic-gate * groups, is optional. 2038*0Sstevel@tonic-gate */ 2039*0Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_TM_COMMON_NAME, pg) 2040*0Sstevel@tonic-gate == -1) { 2041*0Sstevel@tonic-gate switch (scf_error()) { 2042*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2043*0Sstevel@tonic-gate ret = ECANCELED; 2044*0Sstevel@tonic-gate goto template_values_out; 2045*0Sstevel@tonic-gate 2046*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2047*0Sstevel@tonic-gate goto template_values_out; 2048*0Sstevel@tonic-gate 2049*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2050*0Sstevel@tonic-gate default: 2051*0Sstevel@tonic-gate ret = ECONNABORTED; 2052*0Sstevel@tonic-gate goto template_values_out; 2053*0Sstevel@tonic-gate 2054*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2055*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2056*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2057*0Sstevel@tonic-gate bad_error("scf_instance_get_pg_composed", scf_error()); 2058*0Sstevel@tonic-gate } 2059*0Sstevel@tonic-gate } 2060*0Sstevel@tonic-gate 2061*0Sstevel@tonic-gate /* 2062*0Sstevel@tonic-gate * The name we wish uses the current locale name as the property name. 2063*0Sstevel@tonic-gate */ 2064*0Sstevel@tonic-gate if (st->st_locale != NULL) { 2065*0Sstevel@tonic-gate if (scf_pg_get_property(pg, st->st_locale, prop) == -1) { 2066*0Sstevel@tonic-gate startd_free(cname, max_scf_value_size); 2067*0Sstevel@tonic-gate 2068*0Sstevel@tonic-gate switch (scf_error()) { 2069*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2070*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2071*0Sstevel@tonic-gate break; 2072*0Sstevel@tonic-gate 2073*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2074*0Sstevel@tonic-gate default: 2075*0Sstevel@tonic-gate ret = ECONNABORTED; 2076*0Sstevel@tonic-gate goto template_values_out; 2077*0Sstevel@tonic-gate 2078*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2079*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2080*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2081*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 2082*0Sstevel@tonic-gate } 2083*0Sstevel@tonic-gate } else { 2084*0Sstevel@tonic-gate if ((r = libscf_read_single_astring(h, prop, &cname)) != 2085*0Sstevel@tonic-gate 0) { 2086*0Sstevel@tonic-gate if (r != LIBSCF_PROPERTY_ABSENT) 2087*0Sstevel@tonic-gate ret = ECHILD; 2088*0Sstevel@tonic-gate startd_free(cname, max_scf_value_size); 2089*0Sstevel@tonic-gate goto template_values_out; 2090*0Sstevel@tonic-gate } 2091*0Sstevel@tonic-gate 2092*0Sstevel@tonic-gate *common_name = cname; 2093*0Sstevel@tonic-gate } 2094*0Sstevel@tonic-gate } 2095*0Sstevel@tonic-gate 2096*0Sstevel@tonic-gate /* 2097*0Sstevel@tonic-gate * Also pull out the C locale name, as a fallback for the case where 2098*0Sstevel@tonic-gate * service offers no localized name. 2099*0Sstevel@tonic-gate */ 2100*0Sstevel@tonic-gate if (scf_pg_get_property(pg, "C", prop) == -1) { 2101*0Sstevel@tonic-gate startd_free(c_cname, max_scf_value_size); 2102*0Sstevel@tonic-gate 2103*0Sstevel@tonic-gate switch (scf_error()) { 2104*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2105*0Sstevel@tonic-gate ret = ENOENT; 2106*0Sstevel@tonic-gate goto template_values_out; 2107*0Sstevel@tonic-gate 2108*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2109*0Sstevel@tonic-gate break; 2110*0Sstevel@tonic-gate 2111*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2112*0Sstevel@tonic-gate default: 2113*0Sstevel@tonic-gate ret = ECONNABORTED; 2114*0Sstevel@tonic-gate goto template_values_out; 2115*0Sstevel@tonic-gate 2116*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2117*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2118*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2119*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 2120*0Sstevel@tonic-gate } 2121*0Sstevel@tonic-gate } else { 2122*0Sstevel@tonic-gate if ((r = libscf_read_single_astring(h, prop, &c_cname)) != 0) { 2123*0Sstevel@tonic-gate if (r != LIBSCF_PROPERTY_ABSENT) 2124*0Sstevel@tonic-gate ret = ECHILD; 2125*0Sstevel@tonic-gate goto template_values_out; 2126*0Sstevel@tonic-gate } 2127*0Sstevel@tonic-gate 2128*0Sstevel@tonic-gate *c_common_name = c_cname; 2129*0Sstevel@tonic-gate } 2130*0Sstevel@tonic-gate 2131*0Sstevel@tonic-gate 2132*0Sstevel@tonic-gate template_values_out: 2133*0Sstevel@tonic-gate scf_property_destroy(prop); 2134*0Sstevel@tonic-gate scf_pg_destroy(pg); 2135*0Sstevel@tonic-gate 2136*0Sstevel@tonic-gate return (ret); 2137*0Sstevel@tonic-gate } 2138*0Sstevel@tonic-gate 2139*0Sstevel@tonic-gate /* 2140*0Sstevel@tonic-gate * int libscf_get_startd_properties(scf_handle_t *, scf_instance_t *, 2141*0Sstevel@tonic-gate * scf_snapshot_t *, uint_t *, char **) 2142*0Sstevel@tonic-gate * 2143*0Sstevel@tonic-gate * Return startd settings for inst in *flags suitable for use in 2144*0Sstevel@tonic-gate * restarter_inst_t->ri_flags. Called by restarter_insert_inst(). 2145*0Sstevel@tonic-gate * 2146*0Sstevel@tonic-gate * Returns 0 on success, ECANCELED if the instance is deleted, ECHILD if 2147*0Sstevel@tonic-gate * a value fetch failed for a property, ENOENT if the instance has no 2148*0Sstevel@tonic-gate * general property group or the property group is deleted, and 2149*0Sstevel@tonic-gate * ECONNABORTED if the repository connection is broken. 2150*0Sstevel@tonic-gate */ 2151*0Sstevel@tonic-gate int 2152*0Sstevel@tonic-gate libscf_get_startd_properties(scf_instance_t *inst, 2153*0Sstevel@tonic-gate scf_snapshot_t *snap, uint_t *flags, char **prefixp) 2154*0Sstevel@tonic-gate { 2155*0Sstevel@tonic-gate scf_handle_t *h; 2156*0Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 2157*0Sstevel@tonic-gate scf_property_t *prop = NULL; 2158*0Sstevel@tonic-gate int style = RINST_CONTRACT; 2159*0Sstevel@tonic-gate char *style_str = startd_alloc(max_scf_value_size); 2160*0Sstevel@tonic-gate int ret = 0, r; 2161*0Sstevel@tonic-gate 2162*0Sstevel@tonic-gate h = scf_instance_handle(inst); 2163*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2164*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 2165*0Sstevel@tonic-gate 2166*0Sstevel@tonic-gate /* 2167*0Sstevel@tonic-gate * The startd property group is optional. 2168*0Sstevel@tonic-gate */ 2169*0Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_STARTD, pg) == -1) { 2170*0Sstevel@tonic-gate switch (scf_error()) { 2171*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2172*0Sstevel@tonic-gate ret = ECANCELED; 2173*0Sstevel@tonic-gate goto instance_flags_out; 2174*0Sstevel@tonic-gate 2175*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2176*0Sstevel@tonic-gate ret = ENOENT; 2177*0Sstevel@tonic-gate goto instance_flags_out; 2178*0Sstevel@tonic-gate 2179*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2180*0Sstevel@tonic-gate default: 2181*0Sstevel@tonic-gate ret = ECONNABORTED; 2182*0Sstevel@tonic-gate goto instance_flags_out; 2183*0Sstevel@tonic-gate 2184*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2185*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2186*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2187*0Sstevel@tonic-gate bad_error("scf_instance_get_pg_composed", scf_error()); 2188*0Sstevel@tonic-gate } 2189*0Sstevel@tonic-gate } 2190*0Sstevel@tonic-gate 2191*0Sstevel@tonic-gate /* 2192*0Sstevel@tonic-gate * 1. Duration property. 2193*0Sstevel@tonic-gate */ 2194*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_DURATION, prop) == -1) { 2195*0Sstevel@tonic-gate switch (scf_error()) { 2196*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2197*0Sstevel@tonic-gate ret = ENOENT; 2198*0Sstevel@tonic-gate goto instance_flags_out; 2199*0Sstevel@tonic-gate 2200*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2201*0Sstevel@tonic-gate break; 2202*0Sstevel@tonic-gate 2203*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2204*0Sstevel@tonic-gate default: 2205*0Sstevel@tonic-gate ret = ECONNABORTED; 2206*0Sstevel@tonic-gate goto instance_flags_out; 2207*0Sstevel@tonic-gate 2208*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2209*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2210*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2211*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 2212*0Sstevel@tonic-gate } 2213*0Sstevel@tonic-gate } else { 2214*0Sstevel@tonic-gate errno = 0; 2215*0Sstevel@tonic-gate if ((r = libscf_read_single_astring(h, prop, &style_str)) 2216*0Sstevel@tonic-gate != 0) { 2217*0Sstevel@tonic-gate if (r != LIBSCF_PROPERTY_ABSENT) 2218*0Sstevel@tonic-gate ret = ECHILD; 2219*0Sstevel@tonic-gate goto instance_flags_out; 2220*0Sstevel@tonic-gate } 2221*0Sstevel@tonic-gate 2222*0Sstevel@tonic-gate if (strcmp(style_str, "child") == 0) 2223*0Sstevel@tonic-gate style = RINST_WAIT; 2224*0Sstevel@tonic-gate else if (strcmp(style_str, "transient") == 0) 2225*0Sstevel@tonic-gate style = RINST_TRANSIENT; 2226*0Sstevel@tonic-gate } 2227*0Sstevel@tonic-gate 2228*0Sstevel@tonic-gate /* 2229*0Sstevel@tonic-gate * 2. utmpx prefix property. 2230*0Sstevel@tonic-gate */ 2231*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_UTMPX_PREFIX, prop) == 0) { 2232*0Sstevel@tonic-gate errno = 0; 2233*0Sstevel@tonic-gate if ((r = libscf_read_single_astring(h, prop, prefixp)) != 0) { 2234*0Sstevel@tonic-gate if (r != LIBSCF_PROPERTY_ABSENT) 2235*0Sstevel@tonic-gate ret = ECHILD; 2236*0Sstevel@tonic-gate goto instance_flags_out; 2237*0Sstevel@tonic-gate } 2238*0Sstevel@tonic-gate } else { 2239*0Sstevel@tonic-gate switch (scf_error()) { 2240*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2241*0Sstevel@tonic-gate ret = ENOENT; 2242*0Sstevel@tonic-gate goto instance_flags_out; 2243*0Sstevel@tonic-gate 2244*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2245*0Sstevel@tonic-gate goto instance_flags_out; 2246*0Sstevel@tonic-gate 2247*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2248*0Sstevel@tonic-gate default: 2249*0Sstevel@tonic-gate ret = ECONNABORTED; 2250*0Sstevel@tonic-gate goto instance_flags_out; 2251*0Sstevel@tonic-gate 2252*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2253*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2254*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2255*0Sstevel@tonic-gate bad_error("scf_pg_get_property", scf_error()); 2256*0Sstevel@tonic-gate } 2257*0Sstevel@tonic-gate } 2258*0Sstevel@tonic-gate 2259*0Sstevel@tonic-gate instance_flags_out: 2260*0Sstevel@tonic-gate startd_free(style_str, max_scf_value_size); 2261*0Sstevel@tonic-gate *flags = (*flags & ~RINST_STYLE_MASK) | style; 2262*0Sstevel@tonic-gate 2263*0Sstevel@tonic-gate scf_property_destroy(prop); 2264*0Sstevel@tonic-gate scf_pg_destroy(pg); 2265*0Sstevel@tonic-gate 2266*0Sstevel@tonic-gate return (ret); 2267*0Sstevel@tonic-gate } 2268*0Sstevel@tonic-gate 2269*0Sstevel@tonic-gate /* 2270*0Sstevel@tonic-gate * int libscf_read_method_ids(scf_handle_t *, scf_instance_t *, ctid_t *, 2271*0Sstevel@tonic-gate * ctid_t *, pid_t *) 2272*0Sstevel@tonic-gate * 2273*0Sstevel@tonic-gate * Sets given id_t variables to primary and transient contract IDs and start 2274*0Sstevel@tonic-gate * PID. Returns 0, ECONNABORTED, and ECANCELED. 2275*0Sstevel@tonic-gate */ 2276*0Sstevel@tonic-gate int 2277*0Sstevel@tonic-gate libscf_read_method_ids(scf_handle_t *h, scf_instance_t *inst, const char *fmri, 2278*0Sstevel@tonic-gate ctid_t *primary, ctid_t *transient, pid_t *start_pid) 2279*0Sstevel@tonic-gate { 2280*0Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 2281*0Sstevel@tonic-gate scf_property_t *prop = NULL; 2282*0Sstevel@tonic-gate scf_value_t *val = NULL; 2283*0Sstevel@tonic-gate uint64_t p, t; 2284*0Sstevel@tonic-gate int ret = 0; 2285*0Sstevel@tonic-gate 2286*0Sstevel@tonic-gate *primary = 0; 2287*0Sstevel@tonic-gate *transient = 0; 2288*0Sstevel@tonic-gate *start_pid = -1; 2289*0Sstevel@tonic-gate 2290*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2291*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 2292*0Sstevel@tonic-gate val = safe_scf_value_create(h); 2293*0Sstevel@tonic-gate 2294*0Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, pg) == -1) { 2295*0Sstevel@tonic-gate switch (scf_error()) { 2296*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2297*0Sstevel@tonic-gate default: 2298*0Sstevel@tonic-gate ret = ECONNABORTED; 2299*0Sstevel@tonic-gate goto read_id_err; 2300*0Sstevel@tonic-gate 2301*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2302*0Sstevel@tonic-gate ret = ECANCELED; 2303*0Sstevel@tonic-gate goto read_id_err; 2304*0Sstevel@tonic-gate 2305*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2306*0Sstevel@tonic-gate goto read_id_err; 2307*0Sstevel@tonic-gate 2308*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2309*0Sstevel@tonic-gate bad_error("scf_instance_get_pg", scf_error()); 2310*0Sstevel@tonic-gate } 2311*0Sstevel@tonic-gate } 2312*0Sstevel@tonic-gate 2313*0Sstevel@tonic-gate ret = get_count(pg, SCF_PROPERTY_CONTRACT, &p); 2314*0Sstevel@tonic-gate switch (ret) { 2315*0Sstevel@tonic-gate case 0: 2316*0Sstevel@tonic-gate break; 2317*0Sstevel@tonic-gate 2318*0Sstevel@tonic-gate case EINVAL: 2319*0Sstevel@tonic-gate log_error(LOG_NOTICE, 2320*0Sstevel@tonic-gate "%s: Ignoring %s/%s: multivalued or not of type count\n", 2321*0Sstevel@tonic-gate fmri, SCF_PG_RESTARTER, SCF_PROPERTY_CONTRACT); 2322*0Sstevel@tonic-gate /* FALLTHROUGH */ 2323*0Sstevel@tonic-gate case ENOENT: 2324*0Sstevel@tonic-gate ret = 0; 2325*0Sstevel@tonic-gate goto read_trans; 2326*0Sstevel@tonic-gate 2327*0Sstevel@tonic-gate case ECONNABORTED: 2328*0Sstevel@tonic-gate case ECANCELED: 2329*0Sstevel@tonic-gate goto read_id_err; 2330*0Sstevel@tonic-gate 2331*0Sstevel@tonic-gate default: 2332*0Sstevel@tonic-gate bad_error("get_count", ret); 2333*0Sstevel@tonic-gate } 2334*0Sstevel@tonic-gate 2335*0Sstevel@tonic-gate *primary = p; 2336*0Sstevel@tonic-gate 2337*0Sstevel@tonic-gate read_trans: 2338*0Sstevel@tonic-gate ret = get_count(pg, SCF_PROPERTY_TRANSIENT_CONTRACT, &t); 2339*0Sstevel@tonic-gate switch (ret) { 2340*0Sstevel@tonic-gate case 0: 2341*0Sstevel@tonic-gate break; 2342*0Sstevel@tonic-gate 2343*0Sstevel@tonic-gate case EINVAL: 2344*0Sstevel@tonic-gate log_error(LOG_NOTICE, 2345*0Sstevel@tonic-gate "%s: Ignoring %s/%s: multivalued or not of type count\n", 2346*0Sstevel@tonic-gate fmri, SCF_PG_RESTARTER, SCF_PROPERTY_TRANSIENT_CONTRACT); 2347*0Sstevel@tonic-gate /* FALLTHROUGH */ 2348*0Sstevel@tonic-gate 2349*0Sstevel@tonic-gate case ENOENT: 2350*0Sstevel@tonic-gate ret = 0; 2351*0Sstevel@tonic-gate goto read_pid_only; 2352*0Sstevel@tonic-gate 2353*0Sstevel@tonic-gate case ECONNABORTED: 2354*0Sstevel@tonic-gate case ECANCELED: 2355*0Sstevel@tonic-gate goto read_id_err; 2356*0Sstevel@tonic-gate 2357*0Sstevel@tonic-gate default: 2358*0Sstevel@tonic-gate bad_error("get_count", ret); 2359*0Sstevel@tonic-gate } 2360*0Sstevel@tonic-gate 2361*0Sstevel@tonic-gate *transient = t; 2362*0Sstevel@tonic-gate 2363*0Sstevel@tonic-gate read_pid_only: 2364*0Sstevel@tonic-gate ret = get_count(pg, SCF_PROPERTY_START_PID, &p); 2365*0Sstevel@tonic-gate switch (ret) { 2366*0Sstevel@tonic-gate case 0: 2367*0Sstevel@tonic-gate break; 2368*0Sstevel@tonic-gate 2369*0Sstevel@tonic-gate case EINVAL: 2370*0Sstevel@tonic-gate log_error(LOG_NOTICE, 2371*0Sstevel@tonic-gate "%s: Ignoring %s/%s: multivalued or not of type count\n", 2372*0Sstevel@tonic-gate fmri, SCF_PG_RESTARTER, SCF_PROPERTY_START_PID); 2373*0Sstevel@tonic-gate /* FALLTHROUGH */ 2374*0Sstevel@tonic-gate case ENOENT: 2375*0Sstevel@tonic-gate ret = 0; 2376*0Sstevel@tonic-gate goto read_id_err; 2377*0Sstevel@tonic-gate 2378*0Sstevel@tonic-gate case ECONNABORTED: 2379*0Sstevel@tonic-gate case ECANCELED: 2380*0Sstevel@tonic-gate goto read_id_err; 2381*0Sstevel@tonic-gate 2382*0Sstevel@tonic-gate default: 2383*0Sstevel@tonic-gate bad_error("get_count", ret); 2384*0Sstevel@tonic-gate } 2385*0Sstevel@tonic-gate 2386*0Sstevel@tonic-gate *start_pid = p; 2387*0Sstevel@tonic-gate 2388*0Sstevel@tonic-gate read_id_err: 2389*0Sstevel@tonic-gate scf_value_destroy(val); 2390*0Sstevel@tonic-gate scf_property_destroy(prop); 2391*0Sstevel@tonic-gate scf_pg_destroy(pg); 2392*0Sstevel@tonic-gate return (ret); 2393*0Sstevel@tonic-gate } 2394*0Sstevel@tonic-gate 2395*0Sstevel@tonic-gate /* 2396*0Sstevel@tonic-gate * Returns with 2397*0Sstevel@tonic-gate * 0 - success 2398*0Sstevel@tonic-gate * ECONNABORTED - repository connection broken 2399*0Sstevel@tonic-gate * - unknown libscf error 2400*0Sstevel@tonic-gate * ECANCELED - s_inst was deleted 2401*0Sstevel@tonic-gate * EPERM 2402*0Sstevel@tonic-gate * EACCES 2403*0Sstevel@tonic-gate * EROFS 2404*0Sstevel@tonic-gate */ 2405*0Sstevel@tonic-gate int 2406*0Sstevel@tonic-gate libscf_write_start_pid(scf_instance_t *s_inst, pid_t pid) 2407*0Sstevel@tonic-gate { 2408*0Sstevel@tonic-gate scf_handle_t *h; 2409*0Sstevel@tonic-gate scf_transaction_entry_t *t_pid; 2410*0Sstevel@tonic-gate scf_value_t *v_pid; 2411*0Sstevel@tonic-gate scf_propertygroup_t *pg; 2412*0Sstevel@tonic-gate int ret = 0; 2413*0Sstevel@tonic-gate 2414*0Sstevel@tonic-gate h = scf_instance_handle(s_inst); 2415*0Sstevel@tonic-gate 2416*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2417*0Sstevel@tonic-gate t_pid = safe_scf_entry_create(h); 2418*0Sstevel@tonic-gate v_pid = safe_scf_value_create(h); 2419*0Sstevel@tonic-gate 2420*0Sstevel@tonic-gate get_pg: 2421*0Sstevel@tonic-gate ret = libscf_inst_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 2422*0Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 2423*0Sstevel@tonic-gate switch (ret) { 2424*0Sstevel@tonic-gate case 0: 2425*0Sstevel@tonic-gate break; 2426*0Sstevel@tonic-gate 2427*0Sstevel@tonic-gate case ECONNABORTED: 2428*0Sstevel@tonic-gate case ECANCELED: 2429*0Sstevel@tonic-gate case EPERM: 2430*0Sstevel@tonic-gate case EACCES: 2431*0Sstevel@tonic-gate case EROFS: 2432*0Sstevel@tonic-gate goto write_start_err; 2433*0Sstevel@tonic-gate 2434*0Sstevel@tonic-gate default: 2435*0Sstevel@tonic-gate bad_error("libscf_inst_get_or_add_pg", ret); 2436*0Sstevel@tonic-gate } 2437*0Sstevel@tonic-gate 2438*0Sstevel@tonic-gate scf_value_set_count(v_pid, pid); 2439*0Sstevel@tonic-gate 2440*0Sstevel@tonic-gate ret = pg_set_prop_value(pg, SCF_PROPERTY_START_PID, v_pid); 2441*0Sstevel@tonic-gate switch (ret) { 2442*0Sstevel@tonic-gate case 0: 2443*0Sstevel@tonic-gate case ECONNABORTED: 2444*0Sstevel@tonic-gate case EPERM: 2445*0Sstevel@tonic-gate case EACCES: 2446*0Sstevel@tonic-gate case EROFS: 2447*0Sstevel@tonic-gate break; 2448*0Sstevel@tonic-gate 2449*0Sstevel@tonic-gate case ECANCELED: 2450*0Sstevel@tonic-gate goto get_pg; 2451*0Sstevel@tonic-gate 2452*0Sstevel@tonic-gate default: 2453*0Sstevel@tonic-gate bad_error("pg_set_prop_value", ret); 2454*0Sstevel@tonic-gate } 2455*0Sstevel@tonic-gate 2456*0Sstevel@tonic-gate write_start_err: 2457*0Sstevel@tonic-gate scf_entry_destroy(t_pid); 2458*0Sstevel@tonic-gate scf_value_destroy(v_pid); 2459*0Sstevel@tonic-gate scf_pg_destroy(pg); 2460*0Sstevel@tonic-gate 2461*0Sstevel@tonic-gate return (ret); 2462*0Sstevel@tonic-gate } 2463*0Sstevel@tonic-gate 2464*0Sstevel@tonic-gate /* 2465*0Sstevel@tonic-gate * Add a property indicating the instance log file. If the dir is 2466*0Sstevel@tonic-gate * equal to LOG_PREFIX_EARLY, then the property restarter/alt_logfile 2467*0Sstevel@tonic-gate * of the instance is used; otherwise, restarter/logfile is used. 2468*0Sstevel@tonic-gate * 2469*0Sstevel@tonic-gate * Returns 2470*0Sstevel@tonic-gate * 0 - success 2471*0Sstevel@tonic-gate * ECONNABORTED 2472*0Sstevel@tonic-gate * ECANCELED 2473*0Sstevel@tonic-gate * EPERM 2474*0Sstevel@tonic-gate * EACCES 2475*0Sstevel@tonic-gate * EROFS 2476*0Sstevel@tonic-gate * EAGAIN 2477*0Sstevel@tonic-gate */ 2478*0Sstevel@tonic-gate int 2479*0Sstevel@tonic-gate libscf_note_method_log(scf_instance_t *inst, const char *dir, const char *file) 2480*0Sstevel@tonic-gate { 2481*0Sstevel@tonic-gate scf_handle_t *h; 2482*0Sstevel@tonic-gate scf_value_t *v; 2483*0Sstevel@tonic-gate scf_propertygroup_t *pg; 2484*0Sstevel@tonic-gate int ret = 0; 2485*0Sstevel@tonic-gate char *logname; 2486*0Sstevel@tonic-gate const char *propname; 2487*0Sstevel@tonic-gate 2488*0Sstevel@tonic-gate h = scf_instance_handle(inst); 2489*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2490*0Sstevel@tonic-gate v = safe_scf_value_create(h); 2491*0Sstevel@tonic-gate 2492*0Sstevel@tonic-gate logname = uu_msprintf("%s%s", dir, file); 2493*0Sstevel@tonic-gate 2494*0Sstevel@tonic-gate if (logname == NULL) { 2495*0Sstevel@tonic-gate ret = errno; 2496*0Sstevel@tonic-gate goto out; 2497*0Sstevel@tonic-gate } 2498*0Sstevel@tonic-gate 2499*0Sstevel@tonic-gate ret = libscf_inst_get_or_add_pg(inst, SCF_PG_RESTARTER, 2500*0Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 2501*0Sstevel@tonic-gate switch (ret) { 2502*0Sstevel@tonic-gate case 0: 2503*0Sstevel@tonic-gate break; 2504*0Sstevel@tonic-gate 2505*0Sstevel@tonic-gate case ECONNABORTED: 2506*0Sstevel@tonic-gate case ECANCELED: 2507*0Sstevel@tonic-gate case EPERM: 2508*0Sstevel@tonic-gate case EACCES: 2509*0Sstevel@tonic-gate case EROFS: 2510*0Sstevel@tonic-gate goto out; 2511*0Sstevel@tonic-gate 2512*0Sstevel@tonic-gate default: 2513*0Sstevel@tonic-gate bad_error("libscf_inst_get_or_add_pg", ret); 2514*0Sstevel@tonic-gate } 2515*0Sstevel@tonic-gate 2516*0Sstevel@tonic-gate (void) scf_value_set_astring(v, logname); 2517*0Sstevel@tonic-gate 2518*0Sstevel@tonic-gate if (strcmp(LOG_PREFIX_EARLY, dir) == 0) 2519*0Sstevel@tonic-gate propname = SCF_PROPERTY_ALT_LOGFILE; 2520*0Sstevel@tonic-gate else 2521*0Sstevel@tonic-gate propname = SCF_PROPERTY_LOGFILE; 2522*0Sstevel@tonic-gate 2523*0Sstevel@tonic-gate ret = pg_set_prop_value(pg, propname, v); 2524*0Sstevel@tonic-gate switch (ret) { 2525*0Sstevel@tonic-gate case 0: 2526*0Sstevel@tonic-gate case ECONNABORTED: 2527*0Sstevel@tonic-gate case ECANCELED: 2528*0Sstevel@tonic-gate case EPERM: 2529*0Sstevel@tonic-gate case EACCES: 2530*0Sstevel@tonic-gate case EROFS: 2531*0Sstevel@tonic-gate break; 2532*0Sstevel@tonic-gate 2533*0Sstevel@tonic-gate default: 2534*0Sstevel@tonic-gate bad_error("pg_set_prop_value", ret); 2535*0Sstevel@tonic-gate } 2536*0Sstevel@tonic-gate 2537*0Sstevel@tonic-gate out: 2538*0Sstevel@tonic-gate scf_pg_destroy(pg); 2539*0Sstevel@tonic-gate scf_value_destroy(v); 2540*0Sstevel@tonic-gate uu_free(logname); 2541*0Sstevel@tonic-gate return (ret); 2542*0Sstevel@tonic-gate } 2543*0Sstevel@tonic-gate 2544*0Sstevel@tonic-gate /* 2545*0Sstevel@tonic-gate * Returns 2546*0Sstevel@tonic-gate * 0 - success 2547*0Sstevel@tonic-gate * ENAMETOOLONG - name is too long 2548*0Sstevel@tonic-gate * ECONNABORTED 2549*0Sstevel@tonic-gate * ECANCELED 2550*0Sstevel@tonic-gate * EPERM 2551*0Sstevel@tonic-gate * EACCES 2552*0Sstevel@tonic-gate * EROFS 2553*0Sstevel@tonic-gate */ 2554*0Sstevel@tonic-gate int 2555*0Sstevel@tonic-gate libscf_write_method_status(scf_instance_t *s_inst, const char *name, 2556*0Sstevel@tonic-gate int status) 2557*0Sstevel@tonic-gate { 2558*0Sstevel@tonic-gate scf_handle_t *h; 2559*0Sstevel@tonic-gate scf_transaction_t *tx; 2560*0Sstevel@tonic-gate scf_transaction_entry_t *e_time, *e_stat; 2561*0Sstevel@tonic-gate scf_value_t *v_time, *v_stat; 2562*0Sstevel@tonic-gate scf_propertygroup_t *pg; 2563*0Sstevel@tonic-gate int ret = 0, r; 2564*0Sstevel@tonic-gate char pname[30]; 2565*0Sstevel@tonic-gate struct timeval tv; 2566*0Sstevel@tonic-gate scf_error_t scfe; 2567*0Sstevel@tonic-gate 2568*0Sstevel@tonic-gate if (strlen(name) + sizeof ("_method_waitstatus") > sizeof (pname)) 2569*0Sstevel@tonic-gate return (ENAMETOOLONG); 2570*0Sstevel@tonic-gate 2571*0Sstevel@tonic-gate h = scf_instance_handle(s_inst); 2572*0Sstevel@tonic-gate 2573*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2574*0Sstevel@tonic-gate tx = safe_scf_transaction_create(h); 2575*0Sstevel@tonic-gate e_time = safe_scf_entry_create(h); 2576*0Sstevel@tonic-gate v_time = safe_scf_value_create(h); 2577*0Sstevel@tonic-gate e_stat = safe_scf_entry_create(h); 2578*0Sstevel@tonic-gate v_stat = safe_scf_value_create(h); 2579*0Sstevel@tonic-gate 2580*0Sstevel@tonic-gate get_pg: 2581*0Sstevel@tonic-gate ret = libscf_inst_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 2582*0Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 2583*0Sstevel@tonic-gate switch (ret) { 2584*0Sstevel@tonic-gate case 0: 2585*0Sstevel@tonic-gate break; 2586*0Sstevel@tonic-gate 2587*0Sstevel@tonic-gate case ECONNABORTED: 2588*0Sstevel@tonic-gate case ECANCELED: 2589*0Sstevel@tonic-gate case EPERM: 2590*0Sstevel@tonic-gate case EACCES: 2591*0Sstevel@tonic-gate case EROFS: 2592*0Sstevel@tonic-gate goto out; 2593*0Sstevel@tonic-gate 2594*0Sstevel@tonic-gate default: 2595*0Sstevel@tonic-gate bad_error("libscf_inst_get_or_add_pg", ret); 2596*0Sstevel@tonic-gate } 2597*0Sstevel@tonic-gate 2598*0Sstevel@tonic-gate (void) gettimeofday(&tv, NULL); 2599*0Sstevel@tonic-gate 2600*0Sstevel@tonic-gate r = scf_value_set_time(v_time, tv.tv_sec, tv.tv_usec * 1000); 2601*0Sstevel@tonic-gate assert(r == 0); 2602*0Sstevel@tonic-gate 2603*0Sstevel@tonic-gate scf_value_set_integer(v_stat, status); 2604*0Sstevel@tonic-gate 2605*0Sstevel@tonic-gate for (;;) { 2606*0Sstevel@tonic-gate if (scf_transaction_start(tx, pg) != 0) { 2607*0Sstevel@tonic-gate switch (scf_error()) { 2608*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2609*0Sstevel@tonic-gate default: 2610*0Sstevel@tonic-gate ret = ECONNABORTED; 2611*0Sstevel@tonic-gate goto out; 2612*0Sstevel@tonic-gate 2613*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2614*0Sstevel@tonic-gate ret = ECANCELED; 2615*0Sstevel@tonic-gate goto out; 2616*0Sstevel@tonic-gate 2617*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 2618*0Sstevel@tonic-gate ret = EPERM; 2619*0Sstevel@tonic-gate goto out; 2620*0Sstevel@tonic-gate 2621*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 2622*0Sstevel@tonic-gate ret = EACCES; 2623*0Sstevel@tonic-gate goto out; 2624*0Sstevel@tonic-gate 2625*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 2626*0Sstevel@tonic-gate ret = EROFS; 2627*0Sstevel@tonic-gate goto out; 2628*0Sstevel@tonic-gate 2629*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2630*0Sstevel@tonic-gate bad_error("scf_transaction_start", ret); 2631*0Sstevel@tonic-gate } 2632*0Sstevel@tonic-gate } 2633*0Sstevel@tonic-gate 2634*0Sstevel@tonic-gate (void) snprintf(pname, sizeof (pname), "%s_method_timestamp", 2635*0Sstevel@tonic-gate name); 2636*0Sstevel@tonic-gate ret = transaction_add_set(tx, e_time, pname, SCF_TYPE_TIME); 2637*0Sstevel@tonic-gate switch (ret) { 2638*0Sstevel@tonic-gate case 0: 2639*0Sstevel@tonic-gate break; 2640*0Sstevel@tonic-gate 2641*0Sstevel@tonic-gate case ECONNABORTED: 2642*0Sstevel@tonic-gate case ECANCELED: 2643*0Sstevel@tonic-gate goto out; 2644*0Sstevel@tonic-gate 2645*0Sstevel@tonic-gate default: 2646*0Sstevel@tonic-gate bad_error("transaction_add_set", ret); 2647*0Sstevel@tonic-gate } 2648*0Sstevel@tonic-gate 2649*0Sstevel@tonic-gate r = scf_entry_add_value(e_time, v_time); 2650*0Sstevel@tonic-gate assert(r == 0); 2651*0Sstevel@tonic-gate 2652*0Sstevel@tonic-gate (void) snprintf(pname, sizeof (pname), "%s_method_waitstatus", 2653*0Sstevel@tonic-gate name); 2654*0Sstevel@tonic-gate ret = transaction_add_set(tx, e_stat, pname, SCF_TYPE_INTEGER); 2655*0Sstevel@tonic-gate switch (ret) { 2656*0Sstevel@tonic-gate case 0: 2657*0Sstevel@tonic-gate break; 2658*0Sstevel@tonic-gate 2659*0Sstevel@tonic-gate case ECONNABORTED: 2660*0Sstevel@tonic-gate case ECANCELED: 2661*0Sstevel@tonic-gate goto out; 2662*0Sstevel@tonic-gate 2663*0Sstevel@tonic-gate default: 2664*0Sstevel@tonic-gate bad_error("transaction_add_set", ret); 2665*0Sstevel@tonic-gate } 2666*0Sstevel@tonic-gate 2667*0Sstevel@tonic-gate r = scf_entry_add_value(e_stat, v_stat); 2668*0Sstevel@tonic-gate if (r != 0) 2669*0Sstevel@tonic-gate bad_error("scf_entry_add_value", scf_error()); 2670*0Sstevel@tonic-gate 2671*0Sstevel@tonic-gate r = scf_transaction_commit(tx); 2672*0Sstevel@tonic-gate if (r == 1) 2673*0Sstevel@tonic-gate break; 2674*0Sstevel@tonic-gate if (r != 0) { 2675*0Sstevel@tonic-gate scfe = scf_error(); 2676*0Sstevel@tonic-gate scf_transaction_reset_all(tx); 2677*0Sstevel@tonic-gate switch (scfe) { 2678*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2679*0Sstevel@tonic-gate default: 2680*0Sstevel@tonic-gate ret = ECONNABORTED; 2681*0Sstevel@tonic-gate goto out; 2682*0Sstevel@tonic-gate 2683*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2684*0Sstevel@tonic-gate ret = ECANCELED; 2685*0Sstevel@tonic-gate goto out; 2686*0Sstevel@tonic-gate 2687*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 2688*0Sstevel@tonic-gate ret = EPERM; 2689*0Sstevel@tonic-gate goto out; 2690*0Sstevel@tonic-gate 2691*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 2692*0Sstevel@tonic-gate ret = EACCES; 2693*0Sstevel@tonic-gate goto out; 2694*0Sstevel@tonic-gate 2695*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 2696*0Sstevel@tonic-gate ret = EROFS; 2697*0Sstevel@tonic-gate goto out; 2698*0Sstevel@tonic-gate 2699*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2700*0Sstevel@tonic-gate bad_error("scf_transaction_commit", scfe); 2701*0Sstevel@tonic-gate } 2702*0Sstevel@tonic-gate } 2703*0Sstevel@tonic-gate 2704*0Sstevel@tonic-gate scf_transaction_reset_all(tx); 2705*0Sstevel@tonic-gate 2706*0Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 2707*0Sstevel@tonic-gate switch (scf_error()) { 2708*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2709*0Sstevel@tonic-gate default: 2710*0Sstevel@tonic-gate ret = ECONNABORTED; 2711*0Sstevel@tonic-gate goto out; 2712*0Sstevel@tonic-gate 2713*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2714*0Sstevel@tonic-gate ret = ECANCELED; 2715*0Sstevel@tonic-gate goto out; 2716*0Sstevel@tonic-gate 2717*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2718*0Sstevel@tonic-gate bad_error("scf_pg_update", scf_error()); 2719*0Sstevel@tonic-gate } 2720*0Sstevel@tonic-gate } 2721*0Sstevel@tonic-gate } 2722*0Sstevel@tonic-gate 2723*0Sstevel@tonic-gate out: 2724*0Sstevel@tonic-gate scf_transaction_destroy(tx); 2725*0Sstevel@tonic-gate scf_entry_destroy(e_time); 2726*0Sstevel@tonic-gate scf_value_destroy(v_time); 2727*0Sstevel@tonic-gate scf_entry_destroy(e_stat); 2728*0Sstevel@tonic-gate scf_value_destroy(v_stat); 2729*0Sstevel@tonic-gate scf_pg_destroy(pg); 2730*0Sstevel@tonic-gate 2731*0Sstevel@tonic-gate return (ret); 2732*0Sstevel@tonic-gate } 2733*0Sstevel@tonic-gate 2734*0Sstevel@tonic-gate /* 2735*0Sstevel@tonic-gate * Call dgraph_add_instance() for each instance in the repository. 2736*0Sstevel@tonic-gate */ 2737*0Sstevel@tonic-gate void 2738*0Sstevel@tonic-gate libscf_populate_graph(scf_handle_t *h) 2739*0Sstevel@tonic-gate { 2740*0Sstevel@tonic-gate scf_scope_t *scope; 2741*0Sstevel@tonic-gate scf_service_t *svc; 2742*0Sstevel@tonic-gate scf_instance_t *inst; 2743*0Sstevel@tonic-gate scf_iter_t *svc_iter; 2744*0Sstevel@tonic-gate scf_iter_t *inst_iter; 2745*0Sstevel@tonic-gate int ret; 2746*0Sstevel@tonic-gate 2747*0Sstevel@tonic-gate scope = safe_scf_scope_create(h); 2748*0Sstevel@tonic-gate svc = safe_scf_service_create(h); 2749*0Sstevel@tonic-gate inst = safe_scf_instance_create(h); 2750*0Sstevel@tonic-gate svc_iter = safe_scf_iter_create(h); 2751*0Sstevel@tonic-gate inst_iter = safe_scf_iter_create(h); 2752*0Sstevel@tonic-gate 2753*0Sstevel@tonic-gate if ((ret = scf_handle_get_local_scope(h, scope)) != 2754*0Sstevel@tonic-gate SCF_SUCCESS) 2755*0Sstevel@tonic-gate uu_die("retrieving local scope failed: %d\n", ret); 2756*0Sstevel@tonic-gate 2757*0Sstevel@tonic-gate if (scf_iter_scope_services(svc_iter, scope) == -1) 2758*0Sstevel@tonic-gate uu_die("walking local scope's services failed\n"); 2759*0Sstevel@tonic-gate 2760*0Sstevel@tonic-gate while (scf_iter_next_service(svc_iter, svc) > 0) { 2761*0Sstevel@tonic-gate if (scf_iter_service_instances(inst_iter, svc) == -1) 2762*0Sstevel@tonic-gate uu_die("unable to walk service's instances"); 2763*0Sstevel@tonic-gate 2764*0Sstevel@tonic-gate while (scf_iter_next_instance(inst_iter, inst) > 0) { 2765*0Sstevel@tonic-gate char *fmri; 2766*0Sstevel@tonic-gate 2767*0Sstevel@tonic-gate if (libscf_instance_get_fmri(inst, &fmri) == 0) { 2768*0Sstevel@tonic-gate int err; 2769*0Sstevel@tonic-gate 2770*0Sstevel@tonic-gate err = dgraph_add_instance(fmri, inst, B_TRUE); 2771*0Sstevel@tonic-gate if (err != 0 && err != EEXIST) 2772*0Sstevel@tonic-gate log_error(LOG_WARNING, 2773*0Sstevel@tonic-gate "Failed to add %s (%s).\n", fmri, 2774*0Sstevel@tonic-gate strerror(err)); 2775*0Sstevel@tonic-gate startd_free(fmri, max_scf_fmri_size); 2776*0Sstevel@tonic-gate } 2777*0Sstevel@tonic-gate } 2778*0Sstevel@tonic-gate } 2779*0Sstevel@tonic-gate 2780*0Sstevel@tonic-gate scf_iter_destroy(inst_iter); 2781*0Sstevel@tonic-gate scf_iter_destroy(svc_iter); 2782*0Sstevel@tonic-gate scf_instance_destroy(inst); 2783*0Sstevel@tonic-gate scf_service_destroy(svc); 2784*0Sstevel@tonic-gate scf_scope_destroy(scope); 2785*0Sstevel@tonic-gate } 2786*0Sstevel@tonic-gate 2787*0Sstevel@tonic-gate /* 2788*0Sstevel@tonic-gate * Monitors get handled differently since there can be multiple of them. 2789*0Sstevel@tonic-gate * 2790*0Sstevel@tonic-gate * Returns exec string on success. If method not defined, returns 2791*0Sstevel@tonic-gate * LIBSCF_PGROUP_ABSENT; if exec property missing, returns 2792*0Sstevel@tonic-gate * LIBSCF_PROPERTY_ABSENT. Returns LIBSCF_PROPERTY_ERROR on other failures. 2793*0Sstevel@tonic-gate */ 2794*0Sstevel@tonic-gate char * 2795*0Sstevel@tonic-gate libscf_get_method(scf_handle_t *h, int type, restarter_inst_t *inst, 2796*0Sstevel@tonic-gate scf_snapshot_t *snap, method_restart_t *restart_on, uint_t *cte_mask, 2797*0Sstevel@tonic-gate uint8_t *need_sessionp, uint64_t *timeout, uint8_t *timeout_retry) 2798*0Sstevel@tonic-gate { 2799*0Sstevel@tonic-gate scf_instance_t *scf_inst = NULL; 2800*0Sstevel@tonic-gate scf_propertygroup_t *pg = NULL, *pg_startd = NULL; 2801*0Sstevel@tonic-gate scf_property_t *prop = NULL; 2802*0Sstevel@tonic-gate const char *name; 2803*0Sstevel@tonic-gate char *method = startd_alloc(max_scf_value_size); 2804*0Sstevel@tonic-gate char *ig = startd_alloc(max_scf_value_size); 2805*0Sstevel@tonic-gate char *restart = startd_alloc(max_scf_value_size); 2806*0Sstevel@tonic-gate char *ret; 2807*0Sstevel@tonic-gate int error = 0, r; 2808*0Sstevel@tonic-gate 2809*0Sstevel@tonic-gate scf_inst = safe_scf_instance_create(h); 2810*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 2811*0Sstevel@tonic-gate pg_startd = safe_scf_pg_create(h); 2812*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 2813*0Sstevel@tonic-gate 2814*0Sstevel@tonic-gate ret = NULL; 2815*0Sstevel@tonic-gate 2816*0Sstevel@tonic-gate *restart_on = METHOD_RESTART_UNKNOWN; 2817*0Sstevel@tonic-gate 2818*0Sstevel@tonic-gate switch (type) { 2819*0Sstevel@tonic-gate case METHOD_START: 2820*0Sstevel@tonic-gate name = "start"; 2821*0Sstevel@tonic-gate break; 2822*0Sstevel@tonic-gate case METHOD_STOP: 2823*0Sstevel@tonic-gate name = "stop"; 2824*0Sstevel@tonic-gate break; 2825*0Sstevel@tonic-gate case METHOD_REFRESH: 2826*0Sstevel@tonic-gate name = "refresh"; 2827*0Sstevel@tonic-gate break; 2828*0Sstevel@tonic-gate default: 2829*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2830*0Sstevel@tonic-gate goto get_method_cleanup; 2831*0Sstevel@tonic-gate } 2832*0Sstevel@tonic-gate 2833*0Sstevel@tonic-gate if (scf_handle_decode_fmri(h, inst->ri_i.i_fmri, NULL, NULL, scf_inst, 2834*0Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 2835*0Sstevel@tonic-gate log_error(LOG_WARNING, 2836*0Sstevel@tonic-gate "%s: get_method decode instance FMRI failed: %s\n", 2837*0Sstevel@tonic-gate inst->ri_i.i_fmri, scf_strerror(scf_error())); 2838*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2839*0Sstevel@tonic-gate goto get_method_cleanup; 2840*0Sstevel@tonic-gate } 2841*0Sstevel@tonic-gate 2842*0Sstevel@tonic-gate if (scf_instance_get_pg_composed(scf_inst, snap, name, pg) == -1) { 2843*0Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 2844*0Sstevel@tonic-gate error = LIBSCF_PGROUP_ABSENT; 2845*0Sstevel@tonic-gate else 2846*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2847*0Sstevel@tonic-gate goto get_method_cleanup; 2848*0Sstevel@tonic-gate } 2849*0Sstevel@tonic-gate 2850*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_EXEC, prop) == -1) { 2851*0Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 2852*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ABSENT; 2853*0Sstevel@tonic-gate else 2854*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2855*0Sstevel@tonic-gate goto get_method_cleanup; 2856*0Sstevel@tonic-gate } 2857*0Sstevel@tonic-gate 2858*0Sstevel@tonic-gate error = libscf_read_single_astring(h, prop, &method); 2859*0Sstevel@tonic-gate if (error != 0) { 2860*0Sstevel@tonic-gate log_error(LOG_WARNING, 2861*0Sstevel@tonic-gate "%s: get_method failed: can't get a single astring " 2862*0Sstevel@tonic-gate "from %s/%s\n", inst->ri_i.i_fmri, name, SCF_PROPERTY_EXEC); 2863*0Sstevel@tonic-gate goto get_method_cleanup; 2864*0Sstevel@tonic-gate } 2865*0Sstevel@tonic-gate 2866*0Sstevel@tonic-gate error = expand_method_tokens(method, scf_inst, snap, type, &ret); 2867*0Sstevel@tonic-gate if (error != 0) { 2868*0Sstevel@tonic-gate log_instance(inst, B_TRUE, "Could not expand method tokens " 2869*0Sstevel@tonic-gate "in \"%s\": %s", method, ret); 2870*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2871*0Sstevel@tonic-gate goto get_method_cleanup; 2872*0Sstevel@tonic-gate } 2873*0Sstevel@tonic-gate 2874*0Sstevel@tonic-gate r = get_count(pg, SCF_PROPERTY_TIMEOUT, timeout); 2875*0Sstevel@tonic-gate switch (r) { 2876*0Sstevel@tonic-gate case 0: 2877*0Sstevel@tonic-gate break; 2878*0Sstevel@tonic-gate 2879*0Sstevel@tonic-gate case ECONNABORTED: 2880*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2881*0Sstevel@tonic-gate goto get_method_cleanup; 2882*0Sstevel@tonic-gate 2883*0Sstevel@tonic-gate case EINVAL: 2884*0Sstevel@tonic-gate log_instance(inst, B_TRUE, "%s/%s is multi-valued or not of " 2885*0Sstevel@tonic-gate "type count. Using infinite timeout.", name, 2886*0Sstevel@tonic-gate SCF_PROPERTY_TIMEOUT); 2887*0Sstevel@tonic-gate /* FALLTHROUGH */ 2888*0Sstevel@tonic-gate case ECANCELED: 2889*0Sstevel@tonic-gate case ENOENT: 2890*0Sstevel@tonic-gate *timeout = METHOD_TIMEOUT_INFINITE; 2891*0Sstevel@tonic-gate break; 2892*0Sstevel@tonic-gate 2893*0Sstevel@tonic-gate default: 2894*0Sstevel@tonic-gate bad_error("get_count", r); 2895*0Sstevel@tonic-gate } 2896*0Sstevel@tonic-gate 2897*0Sstevel@tonic-gate /* Both 0 and -1 (ugh) are considered infinite timeouts. */ 2898*0Sstevel@tonic-gate if (*timeout == -1 || *timeout == 0) 2899*0Sstevel@tonic-gate *timeout = METHOD_TIMEOUT_INFINITE; 2900*0Sstevel@tonic-gate 2901*0Sstevel@tonic-gate if (scf_instance_get_pg_composed(scf_inst, snap, SCF_PG_STARTD, 2902*0Sstevel@tonic-gate pg_startd) == -1) { 2903*0Sstevel@tonic-gate switch (scf_error()) { 2904*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2905*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 2906*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2907*0Sstevel@tonic-gate goto get_method_cleanup; 2908*0Sstevel@tonic-gate 2909*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2910*0Sstevel@tonic-gate *cte_mask = 0; 2911*0Sstevel@tonic-gate break; 2912*0Sstevel@tonic-gate 2913*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2914*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2915*0Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 2916*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2917*0Sstevel@tonic-gate bad_error("scf_instance_get_pg_composed", scf_error()); 2918*0Sstevel@tonic-gate } 2919*0Sstevel@tonic-gate } else { 2920*0Sstevel@tonic-gate if (scf_pg_get_property(pg_startd, SCF_PROPERTY_IGNORE, 2921*0Sstevel@tonic-gate prop) == -1) { 2922*0Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 2923*0Sstevel@tonic-gate *cte_mask = 0; 2924*0Sstevel@tonic-gate else { 2925*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2926*0Sstevel@tonic-gate goto get_method_cleanup; 2927*0Sstevel@tonic-gate } 2928*0Sstevel@tonic-gate } else { 2929*0Sstevel@tonic-gate error = libscf_read_single_astring(h, prop, &ig); 2930*0Sstevel@tonic-gate if (error != 0) { 2931*0Sstevel@tonic-gate log_error(LOG_WARNING, 2932*0Sstevel@tonic-gate "%s: get_method failed: can't get a single " 2933*0Sstevel@tonic-gate "astring from %s/%s\n", inst->ri_i.i_fmri, 2934*0Sstevel@tonic-gate name, SCF_PROPERTY_IGNORE); 2935*0Sstevel@tonic-gate goto get_method_cleanup; 2936*0Sstevel@tonic-gate } 2937*0Sstevel@tonic-gate 2938*0Sstevel@tonic-gate if (strcmp(ig, "core") == 0) 2939*0Sstevel@tonic-gate *cte_mask = CT_PR_EV_CORE; 2940*0Sstevel@tonic-gate else if (strcmp(ig, "signal") == 0) 2941*0Sstevel@tonic-gate *cte_mask = CT_PR_EV_SIGNAL; 2942*0Sstevel@tonic-gate else if (strcmp(ig, "core,signal") == 0 || 2943*0Sstevel@tonic-gate strcmp(ig, "signal,core") == 0) 2944*0Sstevel@tonic-gate *cte_mask = CT_PR_EV_CORE | CT_PR_EV_SIGNAL; 2945*0Sstevel@tonic-gate else 2946*0Sstevel@tonic-gate *cte_mask = 0; 2947*0Sstevel@tonic-gate } 2948*0Sstevel@tonic-gate 2949*0Sstevel@tonic-gate r = get_boolean(pg_startd, SCF_PROPERTY_NEED_SESSION, 2950*0Sstevel@tonic-gate need_sessionp); 2951*0Sstevel@tonic-gate switch (r) { 2952*0Sstevel@tonic-gate case 0: 2953*0Sstevel@tonic-gate break; 2954*0Sstevel@tonic-gate 2955*0Sstevel@tonic-gate case ECONNABORTED: 2956*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2957*0Sstevel@tonic-gate goto get_method_cleanup; 2958*0Sstevel@tonic-gate 2959*0Sstevel@tonic-gate case ECANCELED: 2960*0Sstevel@tonic-gate case ENOENT: 2961*0Sstevel@tonic-gate case EINVAL: 2962*0Sstevel@tonic-gate *need_sessionp = 0; 2963*0Sstevel@tonic-gate break; 2964*0Sstevel@tonic-gate 2965*0Sstevel@tonic-gate default: 2966*0Sstevel@tonic-gate bad_error("get_boolean", r); 2967*0Sstevel@tonic-gate } 2968*0Sstevel@tonic-gate 2969*0Sstevel@tonic-gate /* 2970*0Sstevel@tonic-gate * Determine whether service has overriden retry after 2971*0Sstevel@tonic-gate * method timeout. Default to retry if no value is 2972*0Sstevel@tonic-gate * specified. 2973*0Sstevel@tonic-gate */ 2974*0Sstevel@tonic-gate r = get_boolean(pg_startd, SCF_PROPERTY_TIMEOUT_RETRY, 2975*0Sstevel@tonic-gate timeout_retry); 2976*0Sstevel@tonic-gate switch (r) { 2977*0Sstevel@tonic-gate case 0: 2978*0Sstevel@tonic-gate break; 2979*0Sstevel@tonic-gate 2980*0Sstevel@tonic-gate case ECONNABORTED: 2981*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 2982*0Sstevel@tonic-gate goto get_method_cleanup; 2983*0Sstevel@tonic-gate 2984*0Sstevel@tonic-gate case ECANCELED: 2985*0Sstevel@tonic-gate case ENOENT: 2986*0Sstevel@tonic-gate case EINVAL: 2987*0Sstevel@tonic-gate *timeout_retry = 1; 2988*0Sstevel@tonic-gate break; 2989*0Sstevel@tonic-gate 2990*0Sstevel@tonic-gate default: 2991*0Sstevel@tonic-gate bad_error("get_boolean", r); 2992*0Sstevel@tonic-gate } 2993*0Sstevel@tonic-gate } 2994*0Sstevel@tonic-gate 2995*0Sstevel@tonic-gate if (type != METHOD_START) 2996*0Sstevel@tonic-gate goto get_method_cleanup; 2997*0Sstevel@tonic-gate 2998*0Sstevel@tonic-gate /* Only start methods need to honor the restart_on property. */ 2999*0Sstevel@tonic-gate 3000*0Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_RESTART_ON, prop) == -1) { 3001*0Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 3002*0Sstevel@tonic-gate *restart_on = METHOD_RESTART_ALL; 3003*0Sstevel@tonic-gate else 3004*0Sstevel@tonic-gate error = LIBSCF_PROPERTY_ERROR; 3005*0Sstevel@tonic-gate goto get_method_cleanup; 3006*0Sstevel@tonic-gate } 3007*0Sstevel@tonic-gate 3008*0Sstevel@tonic-gate error = libscf_read_single_astring(h, prop, &restart); 3009*0Sstevel@tonic-gate if (error != 0) { 3010*0Sstevel@tonic-gate log_error(LOG_WARNING, 3011*0Sstevel@tonic-gate "%s: get_method failed: can't get a single astring " 3012*0Sstevel@tonic-gate "from %s/%s\n", inst->ri_i.i_fmri, name, 3013*0Sstevel@tonic-gate SCF_PROPERTY_RESTART_ON); 3014*0Sstevel@tonic-gate goto get_method_cleanup; 3015*0Sstevel@tonic-gate } 3016*0Sstevel@tonic-gate 3017*0Sstevel@tonic-gate if (strcmp(restart, "all") == 0) 3018*0Sstevel@tonic-gate *restart_on = METHOD_RESTART_ALL; 3019*0Sstevel@tonic-gate else if (strcmp(restart, "external_fault") == 0) 3020*0Sstevel@tonic-gate *restart_on = METHOD_RESTART_EXTERNAL_FAULT; 3021*0Sstevel@tonic-gate else if (strcmp(restart, "any_fault") == 0) 3022*0Sstevel@tonic-gate *restart_on = METHOD_RESTART_ANY_FAULT; 3023*0Sstevel@tonic-gate 3024*0Sstevel@tonic-gate get_method_cleanup: 3025*0Sstevel@tonic-gate startd_free(ig, max_scf_value_size); 3026*0Sstevel@tonic-gate startd_free(method, max_scf_value_size); 3027*0Sstevel@tonic-gate startd_free(restart, max_scf_value_size); 3028*0Sstevel@tonic-gate 3029*0Sstevel@tonic-gate scf_instance_destroy(scf_inst); 3030*0Sstevel@tonic-gate scf_pg_destroy(pg); 3031*0Sstevel@tonic-gate scf_pg_destroy(pg_startd); 3032*0Sstevel@tonic-gate scf_property_destroy(prop); 3033*0Sstevel@tonic-gate 3034*0Sstevel@tonic-gate if (error != 0 && ret != NULL) { 3035*0Sstevel@tonic-gate free(ret); 3036*0Sstevel@tonic-gate ret = NULL; 3037*0Sstevel@tonic-gate } 3038*0Sstevel@tonic-gate 3039*0Sstevel@tonic-gate errno = error; 3040*0Sstevel@tonic-gate return (ret); 3041*0Sstevel@tonic-gate } 3042*0Sstevel@tonic-gate 3043*0Sstevel@tonic-gate /* 3044*0Sstevel@tonic-gate * Returns 1 if we've reached the fault threshold 3045*0Sstevel@tonic-gate */ 3046*0Sstevel@tonic-gate int 3047*0Sstevel@tonic-gate update_fault_count(restarter_inst_t *inst, int type) 3048*0Sstevel@tonic-gate { 3049*0Sstevel@tonic-gate assert(type == FAULT_COUNT_INCR || type == FAULT_COUNT_RESET); 3050*0Sstevel@tonic-gate 3051*0Sstevel@tonic-gate if (type == FAULT_COUNT_INCR) { 3052*0Sstevel@tonic-gate inst->ri_i.i_fault_count++; 3053*0Sstevel@tonic-gate log_framework(LOG_INFO, "%s: Increasing fault count to %d\n", 3054*0Sstevel@tonic-gate inst->ri_i.i_fmri, inst->ri_i.i_fault_count); 3055*0Sstevel@tonic-gate } 3056*0Sstevel@tonic-gate if (type == FAULT_COUNT_RESET) 3057*0Sstevel@tonic-gate inst->ri_i.i_fault_count = 0; 3058*0Sstevel@tonic-gate 3059*0Sstevel@tonic-gate if (inst->ri_i.i_fault_count >= FAULT_THRESHOLD) 3060*0Sstevel@tonic-gate return (1); 3061*0Sstevel@tonic-gate 3062*0Sstevel@tonic-gate return (0); 3063*0Sstevel@tonic-gate } 3064*0Sstevel@tonic-gate 3065*0Sstevel@tonic-gate /* 3066*0Sstevel@tonic-gate * int libscf_unset_action() 3067*0Sstevel@tonic-gate * Delete any pending timestamps for the specified action which is 3068*0Sstevel@tonic-gate * older than the supplied ts. 3069*0Sstevel@tonic-gate * 3070*0Sstevel@tonic-gate * Returns 0 on success, ECONNABORTED, EACCES, or EPERM on failure. 3071*0Sstevel@tonic-gate */ 3072*0Sstevel@tonic-gate int 3073*0Sstevel@tonic-gate libscf_unset_action(scf_handle_t *h, scf_propertygroup_t *pg, 3074*0Sstevel@tonic-gate admin_action_t a, hrtime_t ts) 3075*0Sstevel@tonic-gate { 3076*0Sstevel@tonic-gate scf_transaction_t *t; 3077*0Sstevel@tonic-gate scf_transaction_entry_t *e; 3078*0Sstevel@tonic-gate scf_property_t *prop; 3079*0Sstevel@tonic-gate scf_value_t *val; 3080*0Sstevel@tonic-gate hrtime_t rep_ts; 3081*0Sstevel@tonic-gate int ret = 0, r; 3082*0Sstevel@tonic-gate 3083*0Sstevel@tonic-gate t = safe_scf_transaction_create(h); 3084*0Sstevel@tonic-gate e = safe_scf_entry_create(h); 3085*0Sstevel@tonic-gate prop = safe_scf_property_create(h); 3086*0Sstevel@tonic-gate val = safe_scf_value_create(h); 3087*0Sstevel@tonic-gate 3088*0Sstevel@tonic-gate for (;;) { 3089*0Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 3090*0Sstevel@tonic-gate switch (scf_error()) { 3091*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3092*0Sstevel@tonic-gate default: 3093*0Sstevel@tonic-gate ret = ECONNABORTED; 3094*0Sstevel@tonic-gate goto unset_action_cleanup; 3095*0Sstevel@tonic-gate 3096*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3097*0Sstevel@tonic-gate goto unset_action_cleanup; 3098*0Sstevel@tonic-gate 3099*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3100*0Sstevel@tonic-gate assert(0); 3101*0Sstevel@tonic-gate abort(); 3102*0Sstevel@tonic-gate } 3103*0Sstevel@tonic-gate } 3104*0Sstevel@tonic-gate 3105*0Sstevel@tonic-gate if (scf_transaction_start(t, pg) == -1) { 3106*0Sstevel@tonic-gate switch (scf_error()) { 3107*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3108*0Sstevel@tonic-gate default: 3109*0Sstevel@tonic-gate ret = ECONNABORTED; 3110*0Sstevel@tonic-gate goto unset_action_cleanup; 3111*0Sstevel@tonic-gate 3112*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3113*0Sstevel@tonic-gate goto unset_action_cleanup; 3114*0Sstevel@tonic-gate 3115*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 3116*0Sstevel@tonic-gate ret = EPERM; 3117*0Sstevel@tonic-gate goto unset_action_cleanup; 3118*0Sstevel@tonic-gate 3119*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 3120*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 3121*0Sstevel@tonic-gate ret = EACCES; 3122*0Sstevel@tonic-gate goto unset_action_cleanup; 3123*0Sstevel@tonic-gate 3124*0Sstevel@tonic-gate case SCF_ERROR_IN_USE: 3125*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3126*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3127*0Sstevel@tonic-gate assert(0); 3128*0Sstevel@tonic-gate abort(); 3129*0Sstevel@tonic-gate } 3130*0Sstevel@tonic-gate } 3131*0Sstevel@tonic-gate 3132*0Sstevel@tonic-gate /* Return failure only if the property hasn't been deleted. */ 3133*0Sstevel@tonic-gate if (scf_pg_get_property(pg, admin_actions[a], prop) == -1) { 3134*0Sstevel@tonic-gate switch (scf_error()) { 3135*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3136*0Sstevel@tonic-gate default: 3137*0Sstevel@tonic-gate ret = ECONNABORTED; 3138*0Sstevel@tonic-gate goto unset_action_cleanup; 3139*0Sstevel@tonic-gate 3140*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3141*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 3142*0Sstevel@tonic-gate goto unset_action_cleanup; 3143*0Sstevel@tonic-gate 3144*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3145*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3146*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3147*0Sstevel@tonic-gate assert(0); 3148*0Sstevel@tonic-gate abort(); 3149*0Sstevel@tonic-gate } 3150*0Sstevel@tonic-gate } 3151*0Sstevel@tonic-gate 3152*0Sstevel@tonic-gate if (scf_property_get_value(prop, val) == -1) { 3153*0Sstevel@tonic-gate switch (scf_error()) { 3154*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3155*0Sstevel@tonic-gate default: 3156*0Sstevel@tonic-gate ret = ECONNABORTED; 3157*0Sstevel@tonic-gate goto unset_action_cleanup; 3158*0Sstevel@tonic-gate 3159*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3160*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 3161*0Sstevel@tonic-gate goto unset_action_cleanup; 3162*0Sstevel@tonic-gate 3163*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 3164*0Sstevel@tonic-gate /* 3165*0Sstevel@tonic-gate * More than one value was associated with 3166*0Sstevel@tonic-gate * this property -- this is incorrect. Take 3167*0Sstevel@tonic-gate * the opportunity to clean up and clear the 3168*0Sstevel@tonic-gate * entire property. 3169*0Sstevel@tonic-gate */ 3170*0Sstevel@tonic-gate rep_ts = ts; 3171*0Sstevel@tonic-gate break; 3172*0Sstevel@tonic-gate 3173*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3174*0Sstevel@tonic-gate assert(0); 3175*0Sstevel@tonic-gate abort(); 3176*0Sstevel@tonic-gate } 3177*0Sstevel@tonic-gate } else if (scf_value_get_integer(val, &rep_ts) == -1) { 3178*0Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_TYPE_MISMATCH); 3179*0Sstevel@tonic-gate rep_ts = 0; 3180*0Sstevel@tonic-gate } 3181*0Sstevel@tonic-gate 3182*0Sstevel@tonic-gate /* Repository ts is more current. Don't clear the action. */ 3183*0Sstevel@tonic-gate if (rep_ts > ts) 3184*0Sstevel@tonic-gate goto unset_action_cleanup; 3185*0Sstevel@tonic-gate 3186*0Sstevel@tonic-gate r = scf_transaction_property_change_type(t, e, 3187*0Sstevel@tonic-gate admin_actions[a], SCF_TYPE_INTEGER); 3188*0Sstevel@tonic-gate assert(r == 0); 3189*0Sstevel@tonic-gate 3190*0Sstevel@tonic-gate r = scf_transaction_commit(t); 3191*0Sstevel@tonic-gate if (r == 1) 3192*0Sstevel@tonic-gate break; 3193*0Sstevel@tonic-gate 3194*0Sstevel@tonic-gate if (r != 0) { 3195*0Sstevel@tonic-gate switch (scf_error()) { 3196*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3197*0Sstevel@tonic-gate default: 3198*0Sstevel@tonic-gate ret = ECONNABORTED; 3199*0Sstevel@tonic-gate goto unset_action_cleanup; 3200*0Sstevel@tonic-gate 3201*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3202*0Sstevel@tonic-gate break; 3203*0Sstevel@tonic-gate 3204*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 3205*0Sstevel@tonic-gate ret = EPERM; 3206*0Sstevel@tonic-gate goto unset_action_cleanup; 3207*0Sstevel@tonic-gate 3208*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 3209*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 3210*0Sstevel@tonic-gate ret = EACCES; 3211*0Sstevel@tonic-gate goto unset_action_cleanup; 3212*0Sstevel@tonic-gate 3213*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3214*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3215*0Sstevel@tonic-gate assert(0); 3216*0Sstevel@tonic-gate abort(); 3217*0Sstevel@tonic-gate } 3218*0Sstevel@tonic-gate } 3219*0Sstevel@tonic-gate 3220*0Sstevel@tonic-gate scf_transaction_reset(t); 3221*0Sstevel@tonic-gate } 3222*0Sstevel@tonic-gate 3223*0Sstevel@tonic-gate unset_action_cleanup: 3224*0Sstevel@tonic-gate scf_transaction_destroy(t); 3225*0Sstevel@tonic-gate scf_entry_destroy(e); 3226*0Sstevel@tonic-gate scf_property_destroy(prop); 3227*0Sstevel@tonic-gate scf_value_destroy(val); 3228*0Sstevel@tonic-gate 3229*0Sstevel@tonic-gate return (ret); 3230*0Sstevel@tonic-gate } 3231*0Sstevel@tonic-gate 3232*0Sstevel@tonic-gate /* 3233*0Sstevel@tonic-gate * Decorates & binds hndl. hndl must be unbound. Returns 3234*0Sstevel@tonic-gate * 0 - success 3235*0Sstevel@tonic-gate * -1 - repository server is not running 3236*0Sstevel@tonic-gate * -1 - repository server is out of resources 3237*0Sstevel@tonic-gate */ 3238*0Sstevel@tonic-gate static int 3239*0Sstevel@tonic-gate handle_decorate_and_bind(scf_handle_t *hndl) 3240*0Sstevel@tonic-gate { 3241*0Sstevel@tonic-gate scf_value_t *door_dec_value; 3242*0Sstevel@tonic-gate 3243*0Sstevel@tonic-gate door_dec_value = safe_scf_value_create(hndl); 3244*0Sstevel@tonic-gate 3245*0Sstevel@tonic-gate /* 3246*0Sstevel@tonic-gate * Decorate if alternate door path set. 3247*0Sstevel@tonic-gate */ 3248*0Sstevel@tonic-gate if (st->st_door_path) { 3249*0Sstevel@tonic-gate if (scf_value_set_astring(door_dec_value, st->st_door_path) != 3250*0Sstevel@tonic-gate 0) 3251*0Sstevel@tonic-gate uu_die("$STARTD_ALT_DOOR is too long.\n"); 3252*0Sstevel@tonic-gate 3253*0Sstevel@tonic-gate if (scf_handle_decorate(hndl, "door_path", door_dec_value) != 0) 3254*0Sstevel@tonic-gate bad_error("scf_handle_decorate", scf_error()); 3255*0Sstevel@tonic-gate } 3256*0Sstevel@tonic-gate 3257*0Sstevel@tonic-gate scf_value_destroy(door_dec_value); 3258*0Sstevel@tonic-gate 3259*0Sstevel@tonic-gate if (scf_handle_bind(hndl) == 0) 3260*0Sstevel@tonic-gate return (0); 3261*0Sstevel@tonic-gate 3262*0Sstevel@tonic-gate switch (scf_error()) { 3263*0Sstevel@tonic-gate case SCF_ERROR_NO_SERVER: 3264*0Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 3265*0Sstevel@tonic-gate return (-1); 3266*0Sstevel@tonic-gate 3267*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3268*0Sstevel@tonic-gate case SCF_ERROR_IN_USE: 3269*0Sstevel@tonic-gate default: 3270*0Sstevel@tonic-gate bad_error("scf_handle_bind", scf_error()); 3271*0Sstevel@tonic-gate /* NOTREACHED */ 3272*0Sstevel@tonic-gate } 3273*0Sstevel@tonic-gate } 3274*0Sstevel@tonic-gate 3275*0Sstevel@tonic-gate scf_handle_t * 3276*0Sstevel@tonic-gate libscf_handle_create_bound(scf_version_t v) 3277*0Sstevel@tonic-gate { 3278*0Sstevel@tonic-gate scf_handle_t *hndl = scf_handle_create(v); 3279*0Sstevel@tonic-gate 3280*0Sstevel@tonic-gate if (hndl == NULL) 3281*0Sstevel@tonic-gate return (hndl); 3282*0Sstevel@tonic-gate 3283*0Sstevel@tonic-gate if (handle_decorate_and_bind(hndl) == 0) 3284*0Sstevel@tonic-gate return (hndl); 3285*0Sstevel@tonic-gate 3286*0Sstevel@tonic-gate scf_handle_destroy(hndl); 3287*0Sstevel@tonic-gate return (NULL); 3288*0Sstevel@tonic-gate } 3289*0Sstevel@tonic-gate 3290*0Sstevel@tonic-gate void 3291*0Sstevel@tonic-gate libscf_handle_rebind(scf_handle_t *h) 3292*0Sstevel@tonic-gate { 3293*0Sstevel@tonic-gate (void) scf_handle_unbind(h); 3294*0Sstevel@tonic-gate 3295*0Sstevel@tonic-gate MUTEX_LOCK(&st->st_configd_live_lock); 3296*0Sstevel@tonic-gate 3297*0Sstevel@tonic-gate /* 3298*0Sstevel@tonic-gate * Try to rebind the handle before sleeping in case the server isn't 3299*0Sstevel@tonic-gate * really dead. 3300*0Sstevel@tonic-gate */ 3301*0Sstevel@tonic-gate while (handle_decorate_and_bind(h) != 0) 3302*0Sstevel@tonic-gate (void) pthread_cond_wait(&st->st_configd_live_cv, 3303*0Sstevel@tonic-gate &st->st_configd_live_lock); 3304*0Sstevel@tonic-gate 3305*0Sstevel@tonic-gate MUTEX_UNLOCK(&st->st_configd_live_lock); 3306*0Sstevel@tonic-gate } 3307*0Sstevel@tonic-gate 3308*0Sstevel@tonic-gate /* 3309*0Sstevel@tonic-gate * Create a handle and try to bind it until it succeeds. Always returns 3310*0Sstevel@tonic-gate * a bound handle. 3311*0Sstevel@tonic-gate */ 3312*0Sstevel@tonic-gate scf_handle_t * 3313*0Sstevel@tonic-gate libscf_handle_create_bound_loop() 3314*0Sstevel@tonic-gate { 3315*0Sstevel@tonic-gate scf_handle_t *h; 3316*0Sstevel@tonic-gate 3317*0Sstevel@tonic-gate while ((h = scf_handle_create(SCF_VERSION)) == NULL) { 3318*0Sstevel@tonic-gate /* This should have been caught earlier. */ 3319*0Sstevel@tonic-gate assert(scf_error() != SCF_ERROR_VERSION_MISMATCH); 3320*0Sstevel@tonic-gate (void) sleep(2); 3321*0Sstevel@tonic-gate } 3322*0Sstevel@tonic-gate 3323*0Sstevel@tonic-gate if (handle_decorate_and_bind(h) != 0) 3324*0Sstevel@tonic-gate libscf_handle_rebind(h); 3325*0Sstevel@tonic-gate 3326*0Sstevel@tonic-gate return (h); 3327*0Sstevel@tonic-gate } 3328*0Sstevel@tonic-gate 3329*0Sstevel@tonic-gate /* 3330*0Sstevel@tonic-gate * Call cb for each dependency property group of inst. cb is invoked with 3331*0Sstevel@tonic-gate * a pointer to the scf_propertygroup_t and arg. If the repository connection 3332*0Sstevel@tonic-gate * is broken, returns ECONNABORTED. If inst is deleted, returns ECANCELED. 3333*0Sstevel@tonic-gate * If cb returns non-zero, the walk is stopped and EINTR is returned. 3334*0Sstevel@tonic-gate * Otherwise returns 0. 3335*0Sstevel@tonic-gate */ 3336*0Sstevel@tonic-gate int 3337*0Sstevel@tonic-gate walk_dependency_pgs(scf_instance_t *inst, callback_t cb, void *arg) 3338*0Sstevel@tonic-gate { 3339*0Sstevel@tonic-gate scf_handle_t *h; 3340*0Sstevel@tonic-gate scf_snapshot_t *snap; 3341*0Sstevel@tonic-gate scf_iter_t *iter; 3342*0Sstevel@tonic-gate scf_propertygroup_t *pg; 3343*0Sstevel@tonic-gate int r; 3344*0Sstevel@tonic-gate 3345*0Sstevel@tonic-gate h = scf_instance_handle(inst); 3346*0Sstevel@tonic-gate 3347*0Sstevel@tonic-gate iter = safe_scf_iter_create(h); 3348*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 3349*0Sstevel@tonic-gate 3350*0Sstevel@tonic-gate snap = libscf_get_running_snapshot(inst); 3351*0Sstevel@tonic-gate 3352*0Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(iter, inst, snap, 3353*0Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) != 0) { 3354*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 3355*0Sstevel@tonic-gate scf_pg_destroy(pg); 3356*0Sstevel@tonic-gate scf_iter_destroy(iter); 3357*0Sstevel@tonic-gate switch (scf_error()) { 3358*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3359*0Sstevel@tonic-gate default: 3360*0Sstevel@tonic-gate return (ECONNABORTED); 3361*0Sstevel@tonic-gate 3362*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3363*0Sstevel@tonic-gate return (ECANCELED); 3364*0Sstevel@tonic-gate 3365*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3366*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3367*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3368*0Sstevel@tonic-gate assert(0); 3369*0Sstevel@tonic-gate abort(); 3370*0Sstevel@tonic-gate } 3371*0Sstevel@tonic-gate } 3372*0Sstevel@tonic-gate 3373*0Sstevel@tonic-gate for (;;) { 3374*0Sstevel@tonic-gate r = scf_iter_next_pg(iter, pg); 3375*0Sstevel@tonic-gate if (r == 0) 3376*0Sstevel@tonic-gate break; 3377*0Sstevel@tonic-gate if (r == -1) { 3378*0Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_CONNECTION_BROKEN); 3379*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 3380*0Sstevel@tonic-gate scf_pg_destroy(pg); 3381*0Sstevel@tonic-gate scf_iter_destroy(iter); 3382*0Sstevel@tonic-gate return (ECONNABORTED); 3383*0Sstevel@tonic-gate } 3384*0Sstevel@tonic-gate 3385*0Sstevel@tonic-gate r = cb(pg, arg); 3386*0Sstevel@tonic-gate 3387*0Sstevel@tonic-gate if (r != 0) 3388*0Sstevel@tonic-gate break; 3389*0Sstevel@tonic-gate } 3390*0Sstevel@tonic-gate 3391*0Sstevel@tonic-gate scf_snapshot_destroy(snap); 3392*0Sstevel@tonic-gate scf_pg_destroy(pg); 3393*0Sstevel@tonic-gate scf_iter_destroy(iter); 3394*0Sstevel@tonic-gate 3395*0Sstevel@tonic-gate return (r == 0 ? 0 : EINTR); 3396*0Sstevel@tonic-gate } 3397*0Sstevel@tonic-gate 3398*0Sstevel@tonic-gate /* 3399*0Sstevel@tonic-gate * Call cb for each of the string values of prop. cb is invoked with 3400*0Sstevel@tonic-gate * a pointer to the string and arg. If the connection to the repository is 3401*0Sstevel@tonic-gate * broken, ECONNABORTED is returned. If the property is deleted, ECANCELED is 3402*0Sstevel@tonic-gate * returned. If the property does not have astring type, EINVAL is returned. 3403*0Sstevel@tonic-gate * If cb returns non-zero, the walk is stopped and EINTR is returned. 3404*0Sstevel@tonic-gate * Otherwise 0 is returned. 3405*0Sstevel@tonic-gate */ 3406*0Sstevel@tonic-gate int 3407*0Sstevel@tonic-gate walk_property_astrings(scf_property_t *prop, callback_t cb, void *arg) 3408*0Sstevel@tonic-gate { 3409*0Sstevel@tonic-gate scf_handle_t *h; 3410*0Sstevel@tonic-gate scf_value_t *val; 3411*0Sstevel@tonic-gate scf_iter_t *iter; 3412*0Sstevel@tonic-gate char *buf; 3413*0Sstevel@tonic-gate int r; 3414*0Sstevel@tonic-gate ssize_t sz; 3415*0Sstevel@tonic-gate 3416*0Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_ASTRING) != 0) { 3417*0Sstevel@tonic-gate switch (scf_error()) { 3418*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3419*0Sstevel@tonic-gate default: 3420*0Sstevel@tonic-gate return (ECONNABORTED); 3421*0Sstevel@tonic-gate 3422*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3423*0Sstevel@tonic-gate return (ECANCELED); 3424*0Sstevel@tonic-gate 3425*0Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 3426*0Sstevel@tonic-gate return (EINVAL); 3427*0Sstevel@tonic-gate 3428*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3429*0Sstevel@tonic-gate assert(0); 3430*0Sstevel@tonic-gate abort(); 3431*0Sstevel@tonic-gate } 3432*0Sstevel@tonic-gate } 3433*0Sstevel@tonic-gate 3434*0Sstevel@tonic-gate h = scf_property_handle(prop); 3435*0Sstevel@tonic-gate 3436*0Sstevel@tonic-gate val = safe_scf_value_create(h); 3437*0Sstevel@tonic-gate iter = safe_scf_iter_create(h); 3438*0Sstevel@tonic-gate 3439*0Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 3440*0Sstevel@tonic-gate scf_iter_destroy(iter); 3441*0Sstevel@tonic-gate scf_value_destroy(val); 3442*0Sstevel@tonic-gate switch (scf_error()) { 3443*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3444*0Sstevel@tonic-gate default: 3445*0Sstevel@tonic-gate return (ECONNABORTED); 3446*0Sstevel@tonic-gate 3447*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3448*0Sstevel@tonic-gate return (ECANCELED); 3449*0Sstevel@tonic-gate 3450*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3451*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3452*0Sstevel@tonic-gate assert(0); 3453*0Sstevel@tonic-gate abort(); 3454*0Sstevel@tonic-gate } 3455*0Sstevel@tonic-gate } 3456*0Sstevel@tonic-gate 3457*0Sstevel@tonic-gate buf = startd_alloc(max_scf_value_size); 3458*0Sstevel@tonic-gate 3459*0Sstevel@tonic-gate for (;;) { 3460*0Sstevel@tonic-gate r = scf_iter_next_value(iter, val); 3461*0Sstevel@tonic-gate if (r < 0) { 3462*0Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_CONNECTION_BROKEN); 3463*0Sstevel@tonic-gate startd_free(buf, max_scf_value_size); 3464*0Sstevel@tonic-gate scf_iter_destroy(iter); 3465*0Sstevel@tonic-gate scf_value_destroy(val); 3466*0Sstevel@tonic-gate return (ECONNABORTED); 3467*0Sstevel@tonic-gate } 3468*0Sstevel@tonic-gate if (r == 0) 3469*0Sstevel@tonic-gate break; 3470*0Sstevel@tonic-gate 3471*0Sstevel@tonic-gate sz = scf_value_get_astring(val, buf, max_scf_value_size); 3472*0Sstevel@tonic-gate assert(sz >= 0); 3473*0Sstevel@tonic-gate 3474*0Sstevel@tonic-gate r = cb(buf, arg); 3475*0Sstevel@tonic-gate 3476*0Sstevel@tonic-gate if (r != 0) 3477*0Sstevel@tonic-gate break; 3478*0Sstevel@tonic-gate } 3479*0Sstevel@tonic-gate 3480*0Sstevel@tonic-gate startd_free(buf, max_scf_value_size); 3481*0Sstevel@tonic-gate scf_value_destroy(val); 3482*0Sstevel@tonic-gate scf_iter_destroy(iter); 3483*0Sstevel@tonic-gate 3484*0Sstevel@tonic-gate return (r == 0 ? 0 : EINTR); 3485*0Sstevel@tonic-gate } 3486*0Sstevel@tonic-gate 3487*0Sstevel@tonic-gate /* 3488*0Sstevel@tonic-gate * Returns 0 or ECONNABORTED. 3489*0Sstevel@tonic-gate */ 3490*0Sstevel@tonic-gate int 3491*0Sstevel@tonic-gate libscf_create_self(scf_handle_t *h) 3492*0Sstevel@tonic-gate { 3493*0Sstevel@tonic-gate scf_scope_t *scope; 3494*0Sstevel@tonic-gate scf_service_t *svc; 3495*0Sstevel@tonic-gate scf_instance_t *inst; 3496*0Sstevel@tonic-gate instance_data_t idata; 3497*0Sstevel@tonic-gate int ret = 0, r; 3498*0Sstevel@tonic-gate ctid_t ctid; 3499*0Sstevel@tonic-gate uint64_t uint64; 3500*0Sstevel@tonic-gate uint_t count = 0, msecs = ALLOC_DELAY; 3501*0Sstevel@tonic-gate 3502*0Sstevel@tonic-gate const char * const startd_svc = "system/svc/restarter"; 3503*0Sstevel@tonic-gate const char * const startd_inst = "default"; 3504*0Sstevel@tonic-gate 3505*0Sstevel@tonic-gate /* If SCF_SERVICE_STARTD changes, our strings must change, too. */ 3506*0Sstevel@tonic-gate assert(strcmp(SCF_SERVICE_STARTD, 3507*0Sstevel@tonic-gate "svc:/system/svc/restarter:default") == 0); 3508*0Sstevel@tonic-gate 3509*0Sstevel@tonic-gate scope = safe_scf_scope_create(h); 3510*0Sstevel@tonic-gate svc = safe_scf_service_create(h); 3511*0Sstevel@tonic-gate inst = safe_scf_instance_create(h); 3512*0Sstevel@tonic-gate 3513*0Sstevel@tonic-gate if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, scope) != 0) { 3514*0Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_CONNECTION_BROKEN); 3515*0Sstevel@tonic-gate ret = ECONNABORTED; 3516*0Sstevel@tonic-gate goto out; 3517*0Sstevel@tonic-gate } 3518*0Sstevel@tonic-gate 3519*0Sstevel@tonic-gate get_svc: 3520*0Sstevel@tonic-gate if (scf_scope_get_service(scope, startd_svc, svc) != 0) { 3521*0Sstevel@tonic-gate switch (scf_error()) { 3522*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3523*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3524*0Sstevel@tonic-gate default: 3525*0Sstevel@tonic-gate ret = ECONNABORTED; 3526*0Sstevel@tonic-gate goto out; 3527*0Sstevel@tonic-gate 3528*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 3529*0Sstevel@tonic-gate break; 3530*0Sstevel@tonic-gate 3531*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3532*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3533*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3534*0Sstevel@tonic-gate bad_error("scf_scope_get_service", scf_error()); 3535*0Sstevel@tonic-gate } 3536*0Sstevel@tonic-gate 3537*0Sstevel@tonic-gate add_svc: 3538*0Sstevel@tonic-gate if (scf_scope_add_service(scope, startd_svc, svc) != 0) { 3539*0Sstevel@tonic-gate switch (scf_error()) { 3540*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3541*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3542*0Sstevel@tonic-gate default: 3543*0Sstevel@tonic-gate ret = ECONNABORTED; 3544*0Sstevel@tonic-gate goto out; 3545*0Sstevel@tonic-gate 3546*0Sstevel@tonic-gate case SCF_ERROR_EXISTS: 3547*0Sstevel@tonic-gate goto get_svc; 3548*0Sstevel@tonic-gate 3549*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 3550*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 3551*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 3552*0Sstevel@tonic-gate uu_warn("Could not create %s: %s\n", 3553*0Sstevel@tonic-gate SCF_SERVICE_STARTD, 3554*0Sstevel@tonic-gate scf_strerror(scf_error())); 3555*0Sstevel@tonic-gate goto out; 3556*0Sstevel@tonic-gate 3557*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3558*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3559*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3560*0Sstevel@tonic-gate bad_error("scf_scope_add_service", scf_error()); 3561*0Sstevel@tonic-gate } 3562*0Sstevel@tonic-gate } 3563*0Sstevel@tonic-gate } 3564*0Sstevel@tonic-gate 3565*0Sstevel@tonic-gate if (scf_service_get_instance(svc, startd_inst, NULL) == 0) 3566*0Sstevel@tonic-gate goto out; 3567*0Sstevel@tonic-gate 3568*0Sstevel@tonic-gate switch (scf_error()) { 3569*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3570*0Sstevel@tonic-gate default: 3571*0Sstevel@tonic-gate ret = ECONNABORTED; 3572*0Sstevel@tonic-gate goto out; 3573*0Sstevel@tonic-gate 3574*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 3575*0Sstevel@tonic-gate break; 3576*0Sstevel@tonic-gate 3577*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3578*0Sstevel@tonic-gate goto add_svc; 3579*0Sstevel@tonic-gate 3580*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3581*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3582*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3583*0Sstevel@tonic-gate bad_error("scf_service_get_instance", scf_error()); 3584*0Sstevel@tonic-gate } 3585*0Sstevel@tonic-gate 3586*0Sstevel@tonic-gate add_inst: 3587*0Sstevel@tonic-gate if (scf_service_add_instance(svc, startd_inst, inst) != 0) { 3588*0Sstevel@tonic-gate switch (scf_error()) { 3589*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3590*0Sstevel@tonic-gate default: 3591*0Sstevel@tonic-gate ret = ECONNABORTED; 3592*0Sstevel@tonic-gate goto out; 3593*0Sstevel@tonic-gate 3594*0Sstevel@tonic-gate case SCF_ERROR_EXISTS: 3595*0Sstevel@tonic-gate break; 3596*0Sstevel@tonic-gate 3597*0Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 3598*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 3599*0Sstevel@tonic-gate uu_die("Could not create %s: %s\n", SCF_SERVICE_STARTD, 3600*0Sstevel@tonic-gate scf_strerror(scf_error())); 3601*0Sstevel@tonic-gate /* NOTREACHED */ 3602*0Sstevel@tonic-gate 3603*0Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 3604*0Sstevel@tonic-gate log_error(LOG_NOTICE, 3605*0Sstevel@tonic-gate "Could not create %s: backend readonly.\n", 3606*0Sstevel@tonic-gate SCF_SERVICE_STARTD); 3607*0Sstevel@tonic-gate goto out; 3608*0Sstevel@tonic-gate 3609*0Sstevel@tonic-gate case SCF_ERROR_DELETED: 3610*0Sstevel@tonic-gate goto add_svc; 3611*0Sstevel@tonic-gate 3612*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3613*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3614*0Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 3615*0Sstevel@tonic-gate bad_error("scf_service_add_instance", scf_error()); 3616*0Sstevel@tonic-gate } 3617*0Sstevel@tonic-gate } 3618*0Sstevel@tonic-gate 3619*0Sstevel@tonic-gate /* Set start time. */ 3620*0Sstevel@tonic-gate idata.i_fmri = SCF_SERVICE_STARTD; 3621*0Sstevel@tonic-gate idata.i_state = RESTARTER_STATE_NONE; 3622*0Sstevel@tonic-gate idata.i_next_state = RESTARTER_STATE_NONE; 3623*0Sstevel@tonic-gate set_state: 3624*0Sstevel@tonic-gate switch (r = _restarter_commit_states(h, &idata, RESTARTER_STATE_ONLINE, 3625*0Sstevel@tonic-gate RESTARTER_STATE_NONE, NULL)) { 3626*0Sstevel@tonic-gate case 0: 3627*0Sstevel@tonic-gate break; 3628*0Sstevel@tonic-gate 3629*0Sstevel@tonic-gate case ENOMEM: 3630*0Sstevel@tonic-gate ++count; 3631*0Sstevel@tonic-gate if (count < ALLOC_RETRY) { 3632*0Sstevel@tonic-gate (void) poll(NULL, 0, msecs); 3633*0Sstevel@tonic-gate msecs *= ALLOC_DELAY_MULT; 3634*0Sstevel@tonic-gate goto set_state; 3635*0Sstevel@tonic-gate } 3636*0Sstevel@tonic-gate 3637*0Sstevel@tonic-gate uu_die("Insufficient memory.\n"); 3638*0Sstevel@tonic-gate /* NOTREACHED */ 3639*0Sstevel@tonic-gate 3640*0Sstevel@tonic-gate case ECONNABORTED: 3641*0Sstevel@tonic-gate ret = ECONNABORTED; 3642*0Sstevel@tonic-gate goto out; 3643*0Sstevel@tonic-gate 3644*0Sstevel@tonic-gate case ENOENT: 3645*0Sstevel@tonic-gate goto add_inst; 3646*0Sstevel@tonic-gate 3647*0Sstevel@tonic-gate case EPERM: 3648*0Sstevel@tonic-gate case EACCES: 3649*0Sstevel@tonic-gate case EROFS: 3650*0Sstevel@tonic-gate uu_warn("Could not timestamp %s: %s\n", idata.i_fmri, 3651*0Sstevel@tonic-gate strerror(r)); 3652*0Sstevel@tonic-gate break; 3653*0Sstevel@tonic-gate 3654*0Sstevel@tonic-gate case EINVAL: 3655*0Sstevel@tonic-gate default: 3656*0Sstevel@tonic-gate bad_error("_restarter_commit_states", r); 3657*0Sstevel@tonic-gate } 3658*0Sstevel@tonic-gate 3659*0Sstevel@tonic-gate /* Set general/enabled. */ 3660*0Sstevel@tonic-gate ret = libscf_inst_set_boolean_prop(inst, SCF_PG_GENERAL, 3661*0Sstevel@tonic-gate SCF_PG_GENERAL_TYPE, SCF_PG_GENERAL_FLAGS, SCF_PROPERTY_ENABLED, 1); 3662*0Sstevel@tonic-gate switch (ret) { 3663*0Sstevel@tonic-gate case 0: 3664*0Sstevel@tonic-gate case ECONNABORTED: 3665*0Sstevel@tonic-gate case EPERM: 3666*0Sstevel@tonic-gate case EACCES: 3667*0Sstevel@tonic-gate case EROFS: 3668*0Sstevel@tonic-gate break; 3669*0Sstevel@tonic-gate 3670*0Sstevel@tonic-gate case ECANCELED: 3671*0Sstevel@tonic-gate goto add_inst; 3672*0Sstevel@tonic-gate 3673*0Sstevel@tonic-gate default: 3674*0Sstevel@tonic-gate bad_error("libscf_inst_set_boolean_prop", ret); 3675*0Sstevel@tonic-gate } 3676*0Sstevel@tonic-gate 3677*0Sstevel@tonic-gate ret = libscf_write_start_pid(inst, getpid()); 3678*0Sstevel@tonic-gate switch (ret) { 3679*0Sstevel@tonic-gate case 0: 3680*0Sstevel@tonic-gate case ECONNABORTED: 3681*0Sstevel@tonic-gate case EPERM: 3682*0Sstevel@tonic-gate case EACCES: 3683*0Sstevel@tonic-gate case EROFS: 3684*0Sstevel@tonic-gate break; 3685*0Sstevel@tonic-gate 3686*0Sstevel@tonic-gate case ECANCELED: 3687*0Sstevel@tonic-gate goto add_inst; 3688*0Sstevel@tonic-gate 3689*0Sstevel@tonic-gate default: 3690*0Sstevel@tonic-gate bad_error("libscf_write_start_pid", ret); 3691*0Sstevel@tonic-gate } 3692*0Sstevel@tonic-gate 3693*0Sstevel@tonic-gate ctid = proc_get_ctid(); 3694*0Sstevel@tonic-gate if (ctid > 0) { 3695*0Sstevel@tonic-gate 3696*0Sstevel@tonic-gate uint64 = (uint64_t)ctid; 3697*0Sstevel@tonic-gate ret = libscf_inst_set_count_prop(inst, 3698*0Sstevel@tonic-gate SCF_PG_RESTARTER, SCF_PG_RESTARTER_TYPE, 3699*0Sstevel@tonic-gate SCF_PG_RESTARTER_FLAGS, SCF_PROPERTY_CONTRACT, uint64); 3700*0Sstevel@tonic-gate 3701*0Sstevel@tonic-gate switch (ret) { 3702*0Sstevel@tonic-gate case 0: 3703*0Sstevel@tonic-gate case ECONNABORTED: 3704*0Sstevel@tonic-gate case EPERM: 3705*0Sstevel@tonic-gate case EACCES: 3706*0Sstevel@tonic-gate case EROFS: 3707*0Sstevel@tonic-gate break; 3708*0Sstevel@tonic-gate 3709*0Sstevel@tonic-gate case ECANCELED: 3710*0Sstevel@tonic-gate goto add_inst; 3711*0Sstevel@tonic-gate 3712*0Sstevel@tonic-gate default: 3713*0Sstevel@tonic-gate bad_error("libscf_inst_set_count_prop", ret); 3714*0Sstevel@tonic-gate } 3715*0Sstevel@tonic-gate } 3716*0Sstevel@tonic-gate 3717*0Sstevel@tonic-gate ret = libscf_note_method_log(inst, LOG_PREFIX_EARLY, 3718*0Sstevel@tonic-gate STARTD_DEFAULT_LOG); 3719*0Sstevel@tonic-gate if (ret == 0) { 3720*0Sstevel@tonic-gate ret = libscf_note_method_log(inst, LOG_PREFIX_NORMAL, 3721*0Sstevel@tonic-gate STARTD_DEFAULT_LOG); 3722*0Sstevel@tonic-gate } 3723*0Sstevel@tonic-gate 3724*0Sstevel@tonic-gate switch (ret) { 3725*0Sstevel@tonic-gate case ECONNABORTED: 3726*0Sstevel@tonic-gate case EPERM: 3727*0Sstevel@tonic-gate case EACCES: 3728*0Sstevel@tonic-gate case EROFS: 3729*0Sstevel@tonic-gate case EAGAIN: 3730*0Sstevel@tonic-gate break; 3731*0Sstevel@tonic-gate 3732*0Sstevel@tonic-gate case ECANCELED: 3733*0Sstevel@tonic-gate goto add_inst; 3734*0Sstevel@tonic-gate 3735*0Sstevel@tonic-gate default: 3736*0Sstevel@tonic-gate bad_error("libscf_note_method_log", ret); 3737*0Sstevel@tonic-gate } 3738*0Sstevel@tonic-gate 3739*0Sstevel@tonic-gate out: 3740*0Sstevel@tonic-gate scf_instance_destroy(inst); 3741*0Sstevel@tonic-gate scf_service_destroy(svc); 3742*0Sstevel@tonic-gate scf_scope_destroy(scope); 3743*0Sstevel@tonic-gate return (ret); 3744*0Sstevel@tonic-gate } 3745*0Sstevel@tonic-gate 3746*0Sstevel@tonic-gate /* 3747*0Sstevel@tonic-gate * Returns 3748*0Sstevel@tonic-gate * 0 - success 3749*0Sstevel@tonic-gate * ENOENT - SCF_SERVICE_STARTD does not exist in repository 3750*0Sstevel@tonic-gate * EPERM 3751*0Sstevel@tonic-gate * EACCES 3752*0Sstevel@tonic-gate * EROFS 3753*0Sstevel@tonic-gate */ 3754*0Sstevel@tonic-gate int 3755*0Sstevel@tonic-gate libscf_set_reconfig(int set) 3756*0Sstevel@tonic-gate { 3757*0Sstevel@tonic-gate scf_handle_t *h; 3758*0Sstevel@tonic-gate scf_instance_t *inst; 3759*0Sstevel@tonic-gate scf_propertygroup_t *pg; 3760*0Sstevel@tonic-gate int ret = 0; 3761*0Sstevel@tonic-gate 3762*0Sstevel@tonic-gate h = libscf_handle_create_bound_loop(); 3763*0Sstevel@tonic-gate inst = safe_scf_instance_create(h); 3764*0Sstevel@tonic-gate pg = safe_scf_pg_create(h); 3765*0Sstevel@tonic-gate 3766*0Sstevel@tonic-gate again: 3767*0Sstevel@tonic-gate if (scf_handle_decode_fmri(h, SCF_SERVICE_STARTD, NULL, NULL, 3768*0Sstevel@tonic-gate inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 3769*0Sstevel@tonic-gate switch (scf_error()) { 3770*0Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3771*0Sstevel@tonic-gate default: 3772*0Sstevel@tonic-gate libscf_handle_rebind(h); 3773*0Sstevel@tonic-gate goto again; 3774*0Sstevel@tonic-gate 3775*0Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 3776*0Sstevel@tonic-gate ret = ENOENT; 3777*0Sstevel@tonic-gate goto reconfig_out; 3778*0Sstevel@tonic-gate 3779*0Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 3780*0Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 3781*0Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 3782*0Sstevel@tonic-gate bad_error("scf_handle_decode_fmri", scf_error()); 3783*0Sstevel@tonic-gate } 3784*0Sstevel@tonic-gate } 3785*0Sstevel@tonic-gate 3786*0Sstevel@tonic-gate ret = libscf_inst_set_boolean_prop(inst, "system", SCF_GROUP_FRAMEWORK, 3787*0Sstevel@tonic-gate SCF_PG_FLAG_NONPERSISTENT, "reconfigure", set); 3788*0Sstevel@tonic-gate switch (ret) { 3789*0Sstevel@tonic-gate case 0: 3790*0Sstevel@tonic-gate case EPERM: 3791*0Sstevel@tonic-gate case EACCES: 3792*0Sstevel@tonic-gate case EROFS: 3793*0Sstevel@tonic-gate break; 3794*0Sstevel@tonic-gate 3795*0Sstevel@tonic-gate case ECONNABORTED: 3796*0Sstevel@tonic-gate libscf_handle_rebind(h); 3797*0Sstevel@tonic-gate goto again; 3798*0Sstevel@tonic-gate 3799*0Sstevel@tonic-gate case ECANCELED: 3800*0Sstevel@tonic-gate ret = ENOENT; 3801*0Sstevel@tonic-gate break; 3802*0Sstevel@tonic-gate 3803*0Sstevel@tonic-gate default: 3804*0Sstevel@tonic-gate bad_error("libscf_inst_set_boolean_prop", ret); 3805*0Sstevel@tonic-gate } 3806*0Sstevel@tonic-gate 3807*0Sstevel@tonic-gate reconfig_out: 3808*0Sstevel@tonic-gate scf_pg_destroy(pg); 3809*0Sstevel@tonic-gate scf_instance_destroy(inst); 3810*0Sstevel@tonic-gate scf_handle_destroy(h); 3811*0Sstevel@tonic-gate return (ret); 3812*0Sstevel@tonic-gate } 3813*0Sstevel@tonic-gate 3814*0Sstevel@tonic-gate /* 3815*0Sstevel@tonic-gate * Set inst->ri_m_inst to the scf instance for inst. If it has been deleted, 3816*0Sstevel@tonic-gate * set inst->ri_mi_deleted to true. If the repository connection is broken, it 3817*0Sstevel@tonic-gate * is rebound with libscf_handle_rebound(). 3818*0Sstevel@tonic-gate */ 3819*0Sstevel@tonic-gate void 3820*0Sstevel@tonic-gate libscf_reget_instance(restarter_inst_t *inst) 3821*0Sstevel@tonic-gate { 3822*0Sstevel@tonic-gate scf_handle_t *h; 3823*0Sstevel@tonic-gate int r; 3824*0Sstevel@tonic-gate 3825*0Sstevel@tonic-gate h = scf_instance_handle(inst->ri_m_inst); 3826*0Sstevel@tonic-gate 3827*0Sstevel@tonic-gate again: 3828*0Sstevel@tonic-gate r = libscf_lookup_instance(inst->ri_i.i_fmri, inst->ri_m_inst); 3829*0Sstevel@tonic-gate switch (r) { 3830*0Sstevel@tonic-gate case 0: 3831*0Sstevel@tonic-gate case ENOENT: 3832*0Sstevel@tonic-gate inst->ri_mi_deleted = (r == ENOENT); 3833*0Sstevel@tonic-gate return; 3834*0Sstevel@tonic-gate 3835*0Sstevel@tonic-gate case ECONNABORTED: 3836*0Sstevel@tonic-gate libscf_handle_rebind(h); 3837*0Sstevel@tonic-gate goto again; 3838*0Sstevel@tonic-gate 3839*0Sstevel@tonic-gate case EINVAL: 3840*0Sstevel@tonic-gate case ENOTSUP: 3841*0Sstevel@tonic-gate default: 3842*0Sstevel@tonic-gate bad_error("libscf_lookup_instance", r); 3843*0Sstevel@tonic-gate } 3844*0Sstevel@tonic-gate } 3845