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