summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorSean Wilcox <Sean.Wilcox@Sun.COM>2009-01-08 15:26:25 -0700
committerSean Wilcox <Sean.Wilcox@Sun.COM>2009-01-08 15:26:25 -0700
commit67b54fb64138aa0cc33ebb72f670b0956d2ba53d (patch)
treefd63c445ec9c46745e342959f2877adaeb1395f2 /usr
parented9c9f974daf230167107f22b896206a90ae2390 (diff)
downloadillumos-joyent-67b54fb64138aa0cc33ebb72f670b0956d2ba53d.tar.gz
6790135 WOS images go into maintenance mode post-6765907
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_libscf.c412
1 files changed, 267 insertions, 145 deletions
diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
index 2440306534..b31f76314e 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1384,6 +1384,93 @@ out:
}
/*
+ * Create or update a snapshot of inst. snap is a required scratch object.
+ *
+ * Returns
+ * 0 - success
+ * ECONNABORTED - repository connection broken
+ * EPERM - permission denied
+ * ENOSPC - configd is out of resources
+ * ECANCELED - inst was deleted
+ * -1 - unknown libscf error (message printed)
+ */
+static int
+take_snap(scf_instance_t *inst, const char *name, scf_snapshot_t *snap)
+{
+again:
+ if (scf_instance_get_snapshot(inst, name, snap) == 0) {
+ if (_scf_snapshot_take_attach(inst, snap) != 0) {
+ switch (scf_error()) {
+ case SCF_ERROR_CONNECTION_BROKEN:
+ case SCF_ERROR_PERMISSION_DENIED:
+ case SCF_ERROR_NO_RESOURCES:
+ return (scferror2errno(scf_error()));
+
+ case SCF_ERROR_NOT_SET:
+ case SCF_ERROR_INVALID_ARGUMENT:
+ default:
+ bad_error("_scf_snapshot_take_attach",
+ scf_error());
+ }
+ }
+ } else {
+ switch (scf_error()) {
+ case SCF_ERROR_NOT_FOUND:
+ break;
+
+ case SCF_ERROR_DELETED:
+ case SCF_ERROR_CONNECTION_BROKEN:
+ return (scferror2errno(scf_error()));
+
+ case SCF_ERROR_HANDLE_MISMATCH:
+ case SCF_ERROR_NOT_BOUND:
+ case SCF_ERROR_INVALID_ARGUMENT:
+ case SCF_ERROR_NOT_SET:
+ default:
+ bad_error("scf_instance_get_snapshot", scf_error());
+ }
+
+ if (_scf_snapshot_take_new(inst, name, snap) != 0) {
+ switch (scf_error()) {
+ case SCF_ERROR_EXISTS:
+ goto again;
+
+ case SCF_ERROR_CONNECTION_BROKEN:
+ case SCF_ERROR_NO_RESOURCES:
+ case SCF_ERROR_PERMISSION_DENIED:
+ return (scferror2errno(scf_error()));
+
+ default:
+ scfwarn();
+ return (-1);
+
+ case SCF_ERROR_NOT_SET:
+ case SCF_ERROR_INTERNAL:
+ case SCF_ERROR_INVALID_ARGUMENT:
+ case SCF_ERROR_HANDLE_MISMATCH:
+ bad_error("_scf_snapshot_take_new",
+ scf_error());
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+refresh_running_snapshot(void *entity) {
+ scf_snapshot_t *snap;
+ int r;
+
+ if ((snap = scf_snapshot_create(g_hndl)) == NULL)
+ scfdie();
+ r = take_snap(entity, snap_running, snap);
+ scf_snapshot_destroy(snap);
+
+ return (r);
+}
+
+/*
* Refresh entity. If isservice is zero, take entity to be an scf_instance_t *.
* Otherwise take entity to be an scf_service_t * and refresh all of its child
* instances. fmri is used for messages. inst, iter, and name_buf are used
@@ -1393,6 +1480,7 @@ out:
* ECANCELED - entity was deleted
* EACCES - backend denied access
* EPERM - permission denied
+ * ENOSPC - repository server out of resources
* -1 - _smf_refresh_instance_i() failed. scf_error() should be set.
*/
static int
@@ -1403,21 +1491,41 @@ refresh_entity(int isservice, void *entity, const char *fmri,
int r;
if (!isservice) {
- if (_smf_refresh_instance_i(entity) == 0) {
- if (g_verbose)
- warn(gettext("Refreshed %s.\n"), fmri);
- return (0);
- }
+ if (est->sc_repo_filename == NULL) {
+ if (_smf_refresh_instance_i(entity) == 0) {
+ if (g_verbose)
+ warn(gettext("Refreshed %s.\n"), fmri);
+ return (0);
+ }
- switch (scf_error()) {
- case SCF_ERROR_BACKEND_ACCESS:
- return (EACCES);
+ switch (scf_error()) {
+ case SCF_ERROR_BACKEND_ACCESS:
+ return (EACCES);
- case SCF_ERROR_PERMISSION_DENIED:
- return (EPERM);
+ case SCF_ERROR_PERMISSION_DENIED:
+ return (EPERM);
- default:
- return (-1);
+ default:
+ return (-1);
+ }
+ } else {
+ r = refresh_running_snapshot(entity);
+ switch (r) {
+ case 0:
+ break;
+
+ case ECONNABORTED:
+ case ECANCELED:
+ case EPERM:
+ case ENOSPC:
+ break;
+
+ default:
+ bad_error("refresh_running_snapshot",
+ scf_error());
+ }
+
+ return (r);
}
}
@@ -1459,6 +1567,26 @@ refresh_entity(int isservice, void *entity, const char *fmri,
}
}
+ if (est->sc_repo_filename != NULL) {
+ r = refresh_running_snapshot(inst);
+ switch (r) {
+ case 0:
+ continue;
+
+ case ECONNABORTED:
+ case ECANCELED:
+ case EPERM:
+ case ENOSPC:
+ break;
+ default:
+ bad_error("refresh_running_snapshot",
+ scf_error());
+ }
+
+ return (r);
+
+ }
+
if (_smf_refresh_instance_i(inst) == 0) {
if (g_verbose) {
if (scf_instance_get_name(inst, name_buf,
@@ -1487,91 +1615,99 @@ refresh_entity(int isservice, void *entity, const char *fmri,
return (0);
}
-static int
-stash_scferror_err(scf_callback_t *cbp, scf_error_t err)
+static void
+private_refresh(void)
{
- cbp->sc_err = scferror2errno(err);
- return (UU_WALK_ERROR);
-}
+ scf_instance_t *pinst = NULL;
+ scf_iter_t *piter = NULL;
+ ssize_t fmrilen;
+ size_t bufsz;
+ char *fmribuf;
+ void *ent;
+ int issvc;
+ int r;
-static int
-stash_scferror(scf_callback_t *cbp)
-{
- return (stash_scferror_err(cbp, scf_error()));
-}
+ if (est->sc_repo_filename == NULL)
+ return;
-/*
- * Create or update a snapshot of inst. snap is a required scratch object.
- *
- * Returns
- * 0 - success
- * ECONNABORTED - repository connection broken
- * EPERM - permission denied
- * ENOSPC - configd is out of resources
- * ECANCELED - inst was deleted
- * -1 - unknown libscf error (message printed)
- */
-static int
-take_snap(scf_instance_t *inst, const char *name, scf_snapshot_t *snap)
-{
-again:
- if (scf_instance_get_snapshot(inst, name, snap) == 0) {
- if (_scf_snapshot_take_attach(inst, snap) != 0) {
- switch (scf_error()) {
- case SCF_ERROR_CONNECTION_BROKEN:
- case SCF_ERROR_PERMISSION_DENIED:
- case SCF_ERROR_NO_RESOURCES:
- return (scferror2errno(scf_error()));
+ assert(cur_svc != NULL);
- case SCF_ERROR_NOT_SET:
- case SCF_ERROR_INVALID_ARGUMENT:
- default:
- bad_error("_scf_snapshot_take_attach",
- scf_error());
- }
- }
+ bufsz = max_scf_fmri_len + 1;
+ fmribuf = safe_malloc(bufsz);
+ if (cur_inst) {
+ issvc = 0;
+ ent = cur_inst;
+ fmrilen = scf_instance_to_fmri(ent, fmribuf, bufsz);
} else {
- switch (scf_error()) {
- case SCF_ERROR_NOT_FOUND:
- break;
+ issvc = 1;
+ ent = cur_svc;
+ fmrilen = scf_service_to_fmri(ent, fmribuf, bufsz);
+ if ((pinst = scf_instance_create(g_hndl)) == NULL)
+ scfdie();
- case SCF_ERROR_DELETED:
- case SCF_ERROR_CONNECTION_BROKEN:
- return (scferror2errno(scf_error()));
+ if ((piter = scf_iter_create(g_hndl)) == NULL)
+ scfdie();
+ }
+ if (fmrilen < 0) {
+ free(fmribuf);
+ if (scf_error() != SCF_ERROR_DELETED)
+ scfdie();
- case SCF_ERROR_HANDLE_MISMATCH:
- case SCF_ERROR_NOT_BOUND:
- case SCF_ERROR_INVALID_ARGUMENT:
- case SCF_ERROR_NOT_SET:
- default:
- bad_error("scf_instance_get_snapshot", scf_error());
- }
+ warn(emsg_deleted);
+ return;
+ }
+ assert(fmrilen < bufsz);
- if (_scf_snapshot_take_new(inst, name, snap) != 0) {
- switch (scf_error()) {
- case SCF_ERROR_EXISTS:
- goto again;
+ r = refresh_entity(issvc, ent, fmribuf, pinst, piter, NULL);
+ switch (r) {
+ case 0:
+ break;
- case SCF_ERROR_CONNECTION_BROKEN:
- case SCF_ERROR_NO_RESOURCES:
- case SCF_ERROR_PERMISSION_DENIED:
- return (scferror2errno(scf_error()));
+ case ECONNABORTED:
+ warn(gettext("Could not refresh %s "
+ "(repository connection broken).\n"), fmribuf);
+ break;
- default:
- scfwarn();
- return (-1);
+ case ECANCELED:
+ warn(emsg_deleted);
+ break;
- case SCF_ERROR_NOT_SET:
- case SCF_ERROR_INTERNAL:
- case SCF_ERROR_INVALID_ARGUMENT:
- case SCF_ERROR_HANDLE_MISMATCH:
- bad_error("_scf_snapshot_take_new",
- scf_error());
- }
- }
+ case EPERM:
+ warn(gettext("Could not refresh %s "
+ "(permission denied).\n"), fmribuf);
+ break;
+
+ case ENOSPC:
+ warn(gettext("Could not refresh %s "
+ "(repository server out of resources).\n"),
+ fmribuf);
+ break;
+
+ case EACCES:
+ default:
+ bad_error("refresh_entity", scf_error());
}
- return (0);
+ if (issvc) {
+ scf_instance_destroy(pinst);
+ scf_iter_destroy(piter);
+ }
+
+ free(fmribuf);
+}
+
+
+static int
+stash_scferror_err(scf_callback_t *cbp, scf_error_t err)
+{
+ cbp->sc_err = scferror2errno(err);
+ return (UU_WALK_ERROR);
+}
+
+static int
+stash_scferror(scf_callback_t *cbp)
+{
+ return (stash_scferror_err(cbp, scf_error()));
}
/*
@@ -6782,6 +6918,18 @@ imp_refresh_fmri(const char *fmri, const char *name, const char *d_fmri)
"(permission denied).\n"), fmri, name, d_fmri);
return (r);
+ case ENOSPC:
+ if (name == NULL)
+ warn(gettext("Could not refresh %s "
+ "(repository server out of resources).\n"),
+ fmri);
+ else
+ warn(gettext("Could not refresh %s "
+ "(dependent \"%s\" of %s) "
+ "(repository server out of resources).\n"),
+ fmri, name, d_fmri);
+ return (r);
+
case -1:
scfwarn();
return (r);
@@ -11914,6 +12062,8 @@ lscf_addpg(const char *name, const char *type, const char *flags)
}
scf_pg_destroy(pg);
+
+ private_refresh();
}
void
@@ -12173,6 +12323,9 @@ lscf_setprop(const char *pgname, const char *type, const char *value,
}
ret = 0;
+
+ private_refresh();
+
goto cleanup;
fail:
@@ -12256,6 +12409,8 @@ lscf_delprop(char *pgn)
scfdie();
semerr(emsg_permission_denied);
+ } else {
+ private_refresh();
}
scf_pg_destroy(pg);
@@ -12300,6 +12455,8 @@ lscf_delprop(char *pgn)
scfdie();
semerr(emsg_permission_denied);
+ } else {
+ private_refresh();
}
scf_transaction_destroy(tx);
@@ -12851,6 +13008,8 @@ lscf_setpropvalue(const char *pgname, const char *type,
result = 0;
+ private_refresh();
+
out:
scf_transaction_destroy(tx);
scf_entry_destroy(e);
@@ -13670,7 +13829,6 @@ lscf_refresh(void)
size_t bufsz;
char *fmribuf;
int r;
- scf_snapshot_t *snap;
lscf_prep_hndl();
@@ -13693,70 +13851,34 @@ lscf_refresh(void)
}
assert(fmrilen < bufsz);
- /*
- * If the repository is the active one, a refresh of the instance is
- * requested. For alternate repositories, the refresh command simply
- * takes a new 'running' snapshot, so the refresh method is not run.
- */
- if (est->sc_repo_filename == NULL) {
- r = refresh_entity(0, cur_inst, fmribuf, NULL, NULL, NULL);
-
- switch (r) {
- case 0:
- break;
-
- case ECONNABORTED:
- warn(gettext("Could not refresh %s "
- "(repository connection broken).\n"), fmribuf);
- break;
-
- case ECANCELED:
- warn(emsg_deleted);
- break;
-
- case EPERM:
- warn(gettext("Could not refresh %s "
- "(permission denied).\n"), fmribuf);
- break;
-
- case EACCES:
- default:
- bad_error("refresh_entity", scf_error());
- }
-
- } else {
- if ((snap = scf_snapshot_create(g_hndl)) == NULL)
- scfdie();
- r = take_snap(cur_inst, snap_running, snap);
- scf_snapshot_destroy(snap);
-
- switch (r) {
- case 0:
- break;
+ r = refresh_entity(0, cur_inst, fmribuf, NULL, NULL, NULL);
+ switch (r) {
+ case 0:
+ break;
- case ECONNABORTED:
- warn(gettext("Could not refresh %s "
- "(repository connection broken).\n"), fmribuf);
- break;
+ case ECONNABORTED:
+ warn(gettext("Could not refresh %s "
+ "(repository connection broken).\n"), fmribuf);
+ break;
- case ECANCELED:
- warn(emsg_deleted);
- break;
+ case ECANCELED:
+ warn(emsg_deleted);
+ break;
- case EPERM:
- warn(gettext("Could not refresh %s "
- "(permission denied).\n"), fmribuf);
- break;
+ case EPERM:
+ warn(gettext("Could not refresh %s "
+ "(permission denied).\n"), fmribuf);
+ break;
- case ENOSPC:
- warn(gettext("Could not refresh %s "
- "(repository server out of resources).\n"),
- fmribuf);
- break;
+ case ENOSPC:
+ warn(gettext("Could not refresh %s "
+ "(repository server out of resources).\n"),
+ fmribuf);
+ break;
- default:
- bad_error("take_snap", scf_error());
- }
+ case EACCES:
+ default:
+ bad_error("refresh_entity", scf_error());
}
free(fmribuf);