summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Jung <Philippe.Jung@Sun.COM>2008-09-03 00:00:40 -0700
committerPhilippe Jung <Philippe.Jung@Sun.COM>2008-09-03 00:00:40 -0700
commit70cbfe41f2338b77c15f79c6625eca6e70c412f3 (patch)
tree7dd8cf514b3381d51819a68779f3a64e48cebc97
parent28a27262607274108141b82c5960bbaa1b3a9aae (diff)
downloadillumos-joyent-70cbfe41f2338b77c15f79c6625eca6e70c412f3.tar.gz
6438829 SMF svcs are not removed when performing a pkgrm in an alternate root
-rw-r--r--usr/src/cmd/svc/common/manifest_hash.c28
-rw-r--r--usr/src/cmd/svc/common/manifest_hash.h5
-rw-r--r--usr/src/cmd/svc/mfstscan/mfstscan.c6
-rw-r--r--usr/src/cmd/svc/milestone/manifest-import22
-rw-r--r--usr/src/cmd/svc/startd/Makefile5
-rw-r--r--usr/src/cmd/svc/startd/deathrow.c257
-rw-r--r--usr/src/cmd/svc/startd/graph.c89
-rw-r--r--usr/src/cmd/svc/startd/libscf.c84
-rw-r--r--usr/src/cmd/svc/startd/startd.h9
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg.h2
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg.l2
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg.y24
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_engine.c2
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_help.c5
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_libscf.c36
-rw-r--r--usr/src/lib/libscf/inc/libscf.h10
-rw-r--r--usr/src/lib/libscf/inc/libscf_priv.h4
-rw-r--r--usr/src/pkgdefs/common_files/i.manifest70
-rw-r--r--usr/src/pkgdefs/common_files/r.manifest56
19 files changed, 657 insertions, 59 deletions
diff --git a/usr/src/cmd/svc/common/manifest_hash.c b/usr/src/cmd/svc/common/manifest_hash.c
index 7c27c5f491..547f791df9 100644
--- a/usr/src/cmd/svc/common/manifest_hash.c
+++ b/usr/src/cmd/svc/common/manifest_hash.c
@@ -19,11 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/stat.h>
#include <sys/types.h>
@@ -48,18 +47,27 @@
/*
* Translate a file name to property name. Return an allocated string or NULL
- * if realpath() fails.
+ * if realpath() fails. If deathrow is true, realpath() is skipped. This
+ * allows to return the property name even if the file doesn't exist.
*/
char *
-mhash_filename_to_propname(const char *in)
+mhash_filename_to_propname(const char *in, boolean_t deathrow)
{
char *out, *cp, *base;
size_t len, piece_len;
out = uu_zalloc(PATH_MAX + 1);
- if (realpath(in, out) == NULL) {
- uu_free(out);
- return (NULL);
+ if (deathrow) {
+ /* used only for service deathrow handling */
+ if (strlcpy(out, in, PATH_MAX + 1) >= (PATH_MAX + 1)) {
+ uu_free(out);
+ return (NULL);
+ }
+ } else {
+ if (realpath(in, out) == NULL) {
+ uu_free(out);
+ return (NULL);
+ }
}
base = getenv("PKG_INSTALL_ROOT");
@@ -517,7 +525,7 @@ mhash_test_file(scf_handle_t *hndl, const char *file, uint_t is_profile,
return (MHASH_NEWFILE);
}
- pname = mhash_filename_to_propname(file);
+ pname = mhash_filename_to_propname(file, B_FALSE);
if (pname == NULL)
return (MHASH_FAILURE);
@@ -538,9 +546,9 @@ mhash_test_file(scf_handle_t *hndl, const char *file, uint_t is_profile,
return (MHASH_NEWFILE);
}
- do
+ do {
ret = stat64(file, &st);
- while (ret < 0 && errno == EINTR);
+ } while (ret < 0 && errno == EINTR);
if (ret < 0) {
uu_free(pname);
return (MHASH_FAILURE);
diff --git a/usr/src/cmd/svc/common/manifest_hash.h b/usr/src/cmd/svc/common/manifest_hash.h
index e641fbdcd1..ec718b9c76 100644
--- a/usr/src/cmd/svc/common/manifest_hash.h
+++ b/usr/src/cmd/svc/common/manifest_hash.h
@@ -19,14 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _MANIFEST_HASH_H
#define _MANIFEST_HASH_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <libscf.h>
@@ -50,7 +49,7 @@ extern "C" {
#define MHASH_RECONCILED (1)
#define MHASH_FAILURE (-1)
-char *mhash_filename_to_propname(const char *);
+char *mhash_filename_to_propname(const char *, boolean_t);
int mhash_retrieve_entry(scf_handle_t *, const char *, uchar_t *);
int mhash_store_entry(scf_handle_t *, const char *, uchar_t *, char **);
int mhash_test_file(scf_handle_t *, const char *, uint_t, char **, uchar_t *);
diff --git a/usr/src/cmd/svc/mfstscan/mfstscan.c b/usr/src/cmd/svc/mfstscan/mfstscan.c
index 1bb1cbe2a0..62aa465b7d 100644
--- a/usr/src/cmd/svc/mfstscan/mfstscan.c
+++ b/usr/src/cmd/svc/mfstscan/mfstscan.c
@@ -19,11 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
@@ -113,7 +112,8 @@ main(int argc, char *argv[])
for (i = optind; i < argc; i++) {
if (tflag) {
- char *pname = mhash_filename_to_propname(argv[i]);
+ char *pname = mhash_filename_to_propname(argv[i],
+ B_FALSE);
if (pname != NULL)
(void) puts(pname);
diff --git a/usr/src/cmd/svc/milestone/manifest-import b/usr/src/cmd/svc/milestone/manifest-import
index 07f6ba0328..0b3586d0ae 100644
--- a/usr/src/cmd/svc/milestone/manifest-import
+++ b/usr/src/cmd/svc/milestone/manifest-import
@@ -23,9 +23,8 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-# 0. Initialization.
+# 0a Initialization.
[ -f /lib/svc/share/smf_include.sh ] || exit 1
@@ -338,10 +337,27 @@ prepare_last_import () {
}
}
+#
+# 0b Cleanup deathrow
+#
+deathrow=/etc/svc/deathrow
+if [ -s $deathrow ];then
+ #
+ # svc.startd has unconfigured the services found in deathrow,
+ # clean them now.
+ #
+ while read fmri mfst pkgname; do
+ # Delete services and instances from the deathrow file.
+ /usr/sbin/svccfg delete -f $fmri >/dev/null 2>&1
+ # Remove deathrow manifest hash.
+ /usr/sbin/svccfg delhash -d $mfst >/dev/null 2>&1
+ done < $deathrow
+ /usr/bin/mv $deathrow $deathrow.old
+fi
SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH
#
-# 0. Clean up repository
+# 0c Clean up repository
#
if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null |
/usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null
diff --git a/usr/src/cmd/svc/startd/Makefile b/usr/src/cmd/svc/startd/Makefile
index 0aacf0e373..f5b20e6e81 100644
--- a/usr/src/cmd/svc/startd/Makefile
+++ b/usr/src/cmd/svc/startd/Makefile
@@ -19,15 +19,14 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-#
PROG = svc.startd
OBJS = \
contract.o \
+ deathrow.o \
dict.o \
env.o \
expand.o \
diff --git a/usr/src/cmd/svc/startd/deathrow.c b/usr/src/cmd/svc/startd/deathrow.c
new file mode 100644
index 0000000000..e4e0ab2977
--- /dev/null
+++ b/usr/src/cmd/svc/startd/deathrow.c
@@ -0,0 +1,257 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/param.h>
+#include "startd.h"
+
+/*
+ * The service deathrow mechanism addresses the problem of removing services
+ * from a non accessible SMF repository. In this case, we can't simply use the
+ * "SVCCFG_REPOSITORY=$ROOT/etc/svc/repository.db svccfg delete service_fmri"
+ * command as the alternate repository format is not committed and could be
+ * incompatible with the local SMF commands version.
+ *
+ * The idea is to manage a file (/etc/svc/deathrow) on the alternate root
+ * directory that lists the FMRIs that need to disappear from the repository
+ * when the system that uses this root directory boots up.
+ * r.manifest and i.manifest update the file /etc/svc/deathrow in the alternate
+ * root case.
+ *
+ * When svc.startd daemon launches, it first reads the /etc/svc/deathrow file
+ * and for all FMRIs listed in this file, the service is not configured and
+ * dependencies on it are forced satisfied (during svc.startd init time only).
+ *
+ * Than manifest-import service will actually, as first task, delete the
+ * unconfigured services found in the /etc/svc/deathrow file and the
+ * manifest hash entry from the repository.
+ *
+ */
+
+#define SVC_DEATHROW_FILE "/etc/svc/deathrow"
+
+/*
+ * These data structures are unprotected because they
+ * are modified by a single thread, at startup time.
+ * After initialization, these data structures are
+ * used only in read mode, thus requiring no protection.
+ */
+
+/* list of deathrow fmris, created from the file SVC_DEATHROW_FILE */
+typedef struct deathrow {
+ char *fmri;
+ uu_list_node_t deathrow_link;
+} deathrow_t;
+
+static uu_list_pool_t *deathrow_pool;
+static uu_list_t *deathrow_list;
+
+static boolean_t deathrow_handling_status = B_FALSE;
+
+static deathrow_t *fmri_in_deathrow_internal(const char *);
+static void deathrow_add(const char *);
+
+static void
+deathrow_handling_start()
+{
+ assert(deathrow_handling_status == B_FALSE);
+ deathrow_handling_status = B_TRUE;
+}
+
+static void
+deathrow_handling_stop()
+{
+ assert(deathrow_handling_status == B_TRUE);
+ deathrow_handling_status = B_FALSE;
+}
+
+void
+deathrow_init()
+{
+ FILE *file;
+ char *line;
+ char *fmri;
+ char *manifest;
+ char *pkgname;
+ size_t line_size, sz;
+ unsigned int line_parsed = 0;
+
+ log_framework(LOG_DEBUG, "Deathrow init\n");
+
+ while ((file = fopen(SVC_DEATHROW_FILE, "r")) == NULL) {
+ if (errno == EINTR) {
+ continue;
+ }
+ if (errno != ENOENT) {
+ log_framework(LOG_ERR,
+ "Deathrow not processed. "
+ "Error opening file (%s): %s\n",
+ SVC_DEATHROW_FILE, strerror(errno));
+ }
+ return;
+ }
+
+ deathrow_pool = uu_list_pool_create("deathrow",
+ sizeof (deathrow_t), offsetof(deathrow_t, deathrow_link),
+ NULL, UU_LIST_POOL_DEBUG);
+ if (deathrow_pool == NULL) {
+ uu_die("deathrow_init couldn't create deathrow_pool");
+ }
+
+ deathrow_list = uu_list_create(deathrow_pool, deathrow_list, 0);
+ if (deathrow_list == NULL) {
+ uu_die("deathrow_init couldn't create deathrow_list");
+ }
+
+ /*
+ * A deathrow file line looks like:
+ * <fmri>< ><manifest path>< ><package name><\n>
+ * (field separator is a space character)
+ */
+ line_size = max_scf_fmri_size + 3 + MAXPATHLEN + MAXNAMELEN;
+ line = (char *)startd_alloc(line_size);
+ *line = '\0';
+
+ while (fgets(line, line_size, file) != NULL) {
+ line_parsed++;
+ fmri = NULL;
+ manifest = NULL;
+ pkgname = NULL;
+ sz = strlen(line);
+ if (sz > 0) {
+ /* remove linefeed */
+ if (line[sz - 1] == '\n') {
+ line[sz - 1] = '\0';
+ }
+ manifest = strchr(line, ' ');
+ if (manifest != NULL) {
+ fmri = line;
+ *manifest = '\0';
+ manifest++;
+ pkgname = strchr(manifest, ' ');
+ if (pkgname != NULL) {
+ *pkgname = '\0';
+ pkgname++;
+ }
+ }
+ }
+ if (fmri != NULL && strlen(fmri) > 0 &&
+ strlen(fmri) < max_scf_fmri_size &&
+ manifest != NULL && strlen(manifest) > 0 &&
+ pkgname != NULL && strlen(pkgname) > 0) {
+ log_framework(LOG_DEBUG,
+ "Deathrow parser <%s><%s><%s>\n",
+ fmri, manifest, pkgname);
+ if (fmri_in_deathrow_internal(fmri) == NULL) {
+ /* fmri is not in list, add fmri */
+ deathrow_add(fmri);
+ }
+ } else {
+ log_framework(LOG_ERR,
+ "Deathrow error processing file (%s). "
+ "Skipping line %u.\n",
+ SVC_DEATHROW_FILE, line_parsed);
+ }
+ *line = '\0';
+ }
+ startd_free(line, line_size);
+ (void) fclose(file);
+
+ if (uu_list_first(deathrow_list) != NULL) {
+ deathrow_handling_start();
+ }
+}
+
+void
+deathrow_fini()
+{
+ deathrow_t *d;
+ void *cookie = NULL;
+
+ if (deathrow_handling_status == B_FALSE) {
+ log_framework(LOG_DEBUG, "Deathrow fini\n");
+ return;
+ }
+ deathrow_handling_stop();
+
+ while ((d = uu_list_teardown(deathrow_list, &cookie)) != NULL) {
+ startd_free(d->fmri, strlen(d->fmri) + 1);
+ startd_free(d, sizeof (deathrow_t));
+ }
+
+ uu_list_destroy(deathrow_list);
+ uu_list_pool_destroy(deathrow_pool);
+ deathrow_pool = NULL;
+ deathrow_list = NULL;
+ log_framework(LOG_DEBUG, "Deathrow fini\n");
+}
+
+static void
+deathrow_add(const char *fmri)
+{
+ deathrow_t *d;
+
+ assert(fmri != NULL);
+
+ d = startd_alloc(sizeof (deathrow_t));
+ d->fmri = startd_alloc(strlen(fmri) + 1);
+ (void) strcpy(d->fmri, fmri);
+ uu_list_node_init(d, &d->deathrow_link, deathrow_pool);
+ (void) uu_list_insert_after(deathrow_list, NULL, d);
+
+ log_framework(LOG_DEBUG, "Deathrow added <%s>\n", d->fmri);
+}
+
+static deathrow_t *
+fmri_in_deathrow_internal(const char *fmri)
+{
+ deathrow_t *d;
+
+ assert(fmri != NULL);
+ assert(deathrow_pool != NULL);
+ assert(deathrow_list != NULL);
+
+ for ((d = uu_list_first(deathrow_list)); d != NULL;
+ d = uu_list_next(deathrow_list, d)) {
+ if (strcmp(fmri, d->fmri) == 0) {
+ return (d);
+ }
+ }
+ return (NULL);
+}
+
+boolean_t
+is_fmri_in_deathrow(const char *fmri)
+{
+ if (deathrow_handling_status == B_FALSE) {
+ return (B_FALSE);
+ }
+ return ((fmri_in_deathrow_internal(fmri) != NULL) ? B_TRUE : B_FALSE);
+}
diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c
index 57b04d33ae..e45faeb7dd 100644
--- a/usr/src/cmd/svc/startd/graph.c
+++ b/usr/src/cmd/svc/startd/graph.c
@@ -1504,8 +1504,16 @@ dependency_satisfied(graph_vertex_t *v, boolean_t satbility)
{
switch (v->gv_type) {
case GVT_INST:
- if ((v->gv_flags & GV_CONFIGURED) == 0)
+ if ((v->gv_flags & GV_CONFIGURED) == 0) {
+ if (v->gv_flags & GV_DEATHROW) {
+ /*
+ * A dependency on an instance with GV_DEATHROW
+ * flag is always considered as satisfied.
+ */
+ return (1);
+ }
return (-1);
+ }
switch (v->gv_state) {
case RESTARTER_STATE_ONLINE:
@@ -2869,6 +2877,7 @@ configure_vertex(graph_vertex_t *v, scf_instance_t *inst)
int enabled, enabled_ovr;
int err;
int *path;
+ int deathrow;
restarter_fmri[0] = '\0';
@@ -2880,11 +2889,86 @@ configure_vertex(graph_vertex_t *v, scf_instance_t *inst)
assert(should_be_in_subgraph(v) ==
((v->gv_flags & GV_INSUBGRAPH) != 0));
- log_framework(LOG_DEBUG, "Graph adding %s.\n", v->gv_name);
+ /*
+ * If the instance fmri is in the deathrow list then set the
+ * GV_DEATHROW flag on the vertex and create and set to true the
+ * SCF_PROPERTY_DEATHROW boolean property in the non-persistent
+ * repository for this instance fmri.
+ */
+ if ((v->gv_flags & GV_DEATHROW) ||
+ (is_fmri_in_deathrow(v->gv_name) == B_TRUE)) {
+ if ((v->gv_flags & GV_DEATHROW) == 0) {
+ /*
+ * Set flag GV_DEATHROW, create and set to true
+ * the SCF_PROPERTY_DEATHROW property in the
+ * non-persistent repository for this instance fmri.
+ */
+ v->gv_flags |= GV_DEATHROW;
+
+ switch (err = libscf_set_deathrow(inst, 1)) {
+ case 0:
+ break;
+
+ case ECONNABORTED:
+ case ECANCELED:
+ startd_free(restarter_fmri, max_scf_value_size);
+ return (err);
+
+ case EROFS:
+ log_error(LOG_WARNING, "Could not set %s/%s "
+ "for deathrow %s: %s.\n",
+ SCF_PG_DEATHROW, SCF_PROPERTY_DEATHROW,
+ v->gv_name, strerror(err));
+ break;
+
+ case EPERM:
+ uu_die("Permission denied.\n");
+ /* NOTREACHED */
+
+ default:
+ bad_error("libscf_set_deathrow", err);
+ }
+ log_framework(LOG_DEBUG, "Deathrow, graph set %s.\n",
+ v->gv_name);
+ }
+ startd_free(restarter_fmri, max_scf_value_size);
+ return (0);
+ }
h = scf_instance_handle(inst);
/*
+ * Using a temporary deathrow boolean property, set through
+ * libscf_set_deathrow(), only for fmris on deathrow, is necessary
+ * because deathrow_fini() may already have been called, and in case
+ * of a refresh, GV_DEATHROW may need to be set again.
+ * libscf_get_deathrow() sets deathrow to 1 only if this instance
+ * has a temporary boolean property named 'deathrow' valued true
+ * in a property group 'deathrow', -1 or 0 in all other cases.
+ */
+ err = libscf_get_deathrow(h, inst, &deathrow);
+ switch (err) {
+ case 0:
+ break;
+
+ case ECONNABORTED:
+ case ECANCELED:
+ startd_free(restarter_fmri, max_scf_value_size);
+ return (err);
+
+ default:
+ bad_error("libscf_get_deathrow", err);
+ }
+
+ if (deathrow == 1) {
+ v->gv_flags |= GV_DEATHROW;
+ startd_free(restarter_fmri, max_scf_value_size);
+ return (0);
+ }
+
+ log_framework(LOG_DEBUG, "Graph adding %s.\n", v->gv_name);
+
+ /*
* If the instance does not have a restarter property group,
* initialize its state to uninitialized/none, in case the restarter
* is not enabled.
@@ -4296,6 +4380,7 @@ dgraph_remove_instance(const char *fmri, scf_handle_t *h)
graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART);
v->gv_flags &= ~GV_CONFIGURED;
+ v->gv_flags &= ~GV_DEATHROW;
graph_walk_dependents(v, propagate_start, NULL);
propagate_satbility(v);
diff --git a/usr/src/cmd/svc/startd/libscf.c b/usr/src/cmd/svc/startd/libscf.c
index 741d17cfe6..4584babf95 100644
--- a/usr/src/cmd/svc/startd/libscf.c
+++ b/usr/src/cmd/svc/startd/libscf.c
@@ -24,7 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/contract/process.h>
#include <assert.h>
@@ -931,6 +930,72 @@ libscf_lookup_instance(const char *fmri, scf_instance_t *inst)
}
/*
+ * int libscf_get_deathrow()
+ * Read deathrow for inst. Returns 0, ECONNABORTED if the connection to the
+ * repository is broken, ECANCELED if inst is deleted, or ENOENT if inst
+ * has no deathrow property group.
+ *
+ * If deathrow/deathrow was missing or invalid, *deathrow will be -1 and a
+ * debug message is logged.
+ */
+int
+libscf_get_deathrow(scf_handle_t *h, scf_instance_t *inst, int *deathrow)
+{
+ scf_propertygroup_t *pg;
+ int r;
+ uint8_t deathrow_8;
+
+ pg = safe_scf_pg_create(h);
+
+ if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_DEATHROW, pg) !=
+ 0) {
+ switch (scf_error()) {
+ case SCF_ERROR_CONNECTION_BROKEN:
+ default:
+ scf_pg_destroy(pg);
+ return (ECONNABORTED);
+
+ case SCF_ERROR_DELETED:
+ scf_pg_destroy(pg);
+ return (ECANCELED);
+
+ case SCF_ERROR_NOT_FOUND:
+ *deathrow = -1;
+ break;
+
+ case SCF_ERROR_HANDLE_MISMATCH:
+ case SCF_ERROR_INVALID_ARGUMENT:
+ case SCF_ERROR_NOT_SET:
+ bad_error("libscf_get_deathrow", scf_error());
+ }
+ } else {
+ switch (r = get_boolean(pg,
+ SCF_PROPERTY_DEATHROW, &deathrow_8)) {
+ case 0:
+ *deathrow = deathrow_8;
+ break;
+
+ case ECONNABORTED:
+ case ECANCELED:
+ scf_pg_destroy(pg);
+ return (r);
+
+ case ENOENT:
+ case EINVAL:
+ *deathrow = -1;
+ break;
+
+ default:
+ bad_error("get_boolean", r);
+ }
+ }
+
+ scf_pg_destroy(pg);
+
+ return (0);
+}
+
+/*
* void libscf_get_basic_instance_data()
* Read enabled, enabled_ovr, and restarter_fmri (into an allocated
* buffer) for inst. Returns 0, ECONNABORTED if the connection to the
@@ -1498,6 +1563,19 @@ libscf_set_enable_ovr(scf_instance_t *inst, int enable)
}
/*
+ * Returns 0 on success, ECONNABORTED if the repository connection is broken,
+ * ECANCELED if inst is deleted, EROFS if the backend is readonly, or EPERM if
+ * permission was denied.
+ */
+int
+libscf_set_deathrow(scf_instance_t *inst, int deathrow)
+{
+ return (libscf_inst_set_boolean_prop(inst, SCF_PG_DEATHROW,
+ SCF_PG_DEATHROW_TYPE, SCF_PG_DEATHROW_FLAGS,
+ SCF_PROPERTY_DEATHROW, deathrow));
+}
+
+/*
* Returns
* 0 - success
* ECONNABORTED - repository connection broken
@@ -2776,6 +2854,8 @@ libscf_populate_graph(scf_handle_t *h)
svc_iter = safe_scf_iter_create(h);
inst_iter = safe_scf_iter_create(h);
+ deathrow_init();
+
if ((ret = scf_handle_get_local_scope(h, scope)) !=
SCF_SUCCESS)
uu_die("retrieving local scope failed: %d\n", ret);
@@ -2803,6 +2883,8 @@ libscf_populate_graph(scf_handle_t *h)
}
}
+ deathrow_fini();
+
scf_iter_destroy(inst_iter);
scf_iter_destroy(svc_iter);
scf_instance_destroy(inst);
diff --git a/usr/src/cmd/svc/startd/startd.h b/usr/src/cmd/svc/startd/startd.h
index 99b88c7699..7040a4a52d 100644
--- a/usr/src/cmd/svc/startd/startd.h
+++ b/usr/src/cmd/svc/startd/startd.h
@@ -26,7 +26,6 @@
#ifndef _STARTD_H
#define _STARTD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/time.h>
#include <librestart.h>
@@ -287,6 +286,7 @@ typedef enum {
#define GV_ENABLED 0x02 /* Service should be online */
#define GV_ENBLD_NOOVR 0x04 /* GV_ENABLED, ignoring override */
#define GV_INSUBGRAPH 0x08 /* Current milestone depends on service */
+#define GV_DEATHROW 0x10 /* Service is on deathrow */
/* ID must come first to support search */
typedef struct graph_vertex {
@@ -619,6 +619,7 @@ int libscf_inst_set_count_prop(scf_instance_t *, const char *,
const char *pgtype, uint32_t, const char *, uint64_t);
/* libscf.c - used by graph.c */
+int libscf_get_deathrow(scf_handle_t *, scf_instance_t *, int *);
int libscf_get_basic_instance_data(scf_handle_t *, scf_instance_t *,
const char *, int *, int *, char **);
int libscf_inst_get_or_add_pg(scf_instance_t *, const char *, const char *,
@@ -630,6 +631,7 @@ gv_type_t depgroup_read_scheme(scf_handle_t *, scf_propertygroup_t *);
depgroup_type_t depgroup_read_grouping(scf_handle_t *, scf_propertygroup_t *);
restarter_error_t depgroup_read_restart(scf_handle_t *, scf_propertygroup_t *);
int libscf_set_enable_ovr(scf_instance_t *, int);
+int libscf_set_deathrow(scf_instance_t *, int);
int libscf_inst_delete_prop(scf_instance_t *, const char *, const char *);
int libscf_delete_enable_ovr(scf_instance_t *);
int libscf_get_milestone(scf_instance_t *, scf_property_t *, scf_value_t *,
@@ -756,6 +758,11 @@ void wait_ignore_by_fmri(const char *);
/* proc.c */
ctid_t proc_get_ctid();
+/* deathrow.c */
+extern void deathrow_init();
+extern void deathrow_fini();
+extern boolean_t is_fmri_in_deathrow(const char *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/svc/svccfg/svccfg.h b/usr/src/cmd/svc/svccfg/svccfg.h
index 971f4175f2..e63c24c111 100644
--- a/usr/src/cmd/svc/svccfg/svccfg.h
+++ b/usr/src/cmd/svc/svccfg/svccfg.h
@@ -27,7 +27,6 @@
#ifndef _CMD_SVCCFG_H
#define _CMD_SVCCFG_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
@@ -337,6 +336,7 @@ void lscf_add(const char *);
void lscf_listpg(const char *);
void lscf_addpg(const char *, const char *, const char *);
void lscf_delpg(char *);
+void lscf_delhash(char *, int);
void lscf_listprop(const char *);
void lscf_addprop(char *, const char *, const uu_list_t *);
void lscf_delprop(char *);
diff --git a/usr/src/cmd/svc/svccfg/svccfg.l b/usr/src/cmd/svc/svccfg/svccfg.l
index 9ecff499e4..4bf42e18b3 100644
--- a/usr/src/cmd/svc/svccfg/svccfg.l
+++ b/usr/src/cmd/svc/svccfg/svccfg.l
@@ -25,7 +25,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#pragma error_messages(off, E_BLOCK_DECL_UNUSED)
#pragma error_messages(off, E_EQUALITY_NOT_ASSIGNMENT)
@@ -100,6 +99,7 @@ extern int yyerror(const char *);
<INITIAL>listpg { BEGIN WORD; return (SCC_LISTPG); }
<INITIAL>addpg { BEGIN WORD; return (SCC_ADDPG); }
<INITIAL>delpg { BEGIN WORD; return (SCC_DELPG); }
+<INITIAL>delhash { BEGIN WORD; return (SCC_DELHASH); }
<INITIAL>listprop { BEGIN WORD; return (SCC_LISTPROP); }
<INITIAL>setprop { BEGIN WORD; return (SCC_SETPROP); }
<INITIAL>delprop { BEGIN WORD; return (SCC_DELPROP); }
diff --git a/usr/src/cmd/svc/svccfg/svccfg.y b/usr/src/cmd/svc/svccfg/svccfg.y
index 53c92b49c7..2cc0b04ab7 100644
--- a/usr/src/cmd/svc/svccfg/svccfg.y
+++ b/usr/src/cmd/svc/svccfg/svccfg.y
@@ -25,7 +25,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <libintl.h>
@@ -46,7 +45,7 @@ uu_list_pool_t *string_pool;
%token SCC_VALIDATE SCC_IMPORT SCC_EXPORT SCC_ARCHIVE SCC_APPLY SCC_EXTRACT
%token SCC_REPOSITORY SCC_INVENTORY SCC_SET SCC_END SCC_HELP SCC_RESTORE
%token SCC_LIST SCC_ADD SCC_DELETE SCC_SELECT SCC_UNSELECT
-%token SCC_LISTPG SCC_ADDPG SCC_DELPG
+%token SCC_LISTPG SCC_ADDPG SCC_DELPG SCC_DELHASH
%token SCC_LISTPROP SCC_SETPROP SCC_DELPROP SCC_EDITPROP
%token SCC_ADDPROPVALUE SCC_DELPROPVALUE SCC_SETENV SCC_UNSETENV
%token SCC_LISTSNAP SCC_SELECTSNAP SCC_REVERT SCC_REFRESH
@@ -92,6 +91,7 @@ command : terminator
| listpg_cmd
| addpg_cmd
| delpg_cmd
+ | delhash_cmd
| listprop_cmd
| setprop_cmd
| delprop_cmd
@@ -346,6 +346,25 @@ delpg_cmd : SCC_DELPG SCV_WORD terminator
{ lscf_delpg($2); free($2); }
| SCC_DELPG error terminator { synerr(SCC_DELPG); return(0); }
+delhash_cmd : SCC_DELHASH SCV_WORD terminator
+ {
+ lscf_delhash($2, 0); free($2);
+ }
+ | SCC_DELHASH SCV_WORD SCV_WORD terminator
+ {
+ if (strcmp($2, "-d") == 0) {
+ lscf_delhash($3, 1);
+ free($2);
+ free($3);
+ } else {
+ synerr(SCC_DELHASH);
+ free($2);
+ free($3);
+ return(0);
+ }
+ }
+ | SCC_DELHASH error terminator { synerr(SCC_DELHASH); return(0); }
+
listprop_cmd : SCC_LISTPROP opt_word terminator
{ lscf_listprop($2); free($2); }
| SCC_LISTPROP error terminator { synerr(SCC_LISTPROP); return(0); }
@@ -527,6 +546,7 @@ command_token : SCC_VALIDATE { $$ = SCC_VALIDATE; }
| SCC_LISTPG { $$ = SCC_LISTPG; }
| SCC_ADDPG { $$ = SCC_ADDPG; }
| SCC_DELPG { $$ = SCC_DELPG; }
+ | SCC_DELHASH { $$ = SCC_DELHASH; }
| SCC_LISTPROP { $$ = SCC_LISTPROP; }
| SCC_SETPROP { $$ = SCC_SETPROP; }
| SCC_DELPROP { $$ = SCC_DELPROP; }
diff --git a/usr/src/cmd/svc/svccfg/svccfg_engine.c b/usr/src/cmd/svc/svccfg/svccfg_engine.c
index 105c166778..e610814274 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_engine.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_engine.c
@@ -24,7 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* svccfg(1) interpreter and command execution engine.
@@ -216,6 +215,7 @@ static struct cmd_info {
{ "listpg", CS_SVC | CS_INST | CS_SNAP, NULL },
{ "addpg", CS_SVC | CS_INST, NULL },
{ "delpg", CS_SVC | CS_INST, NULL },
+ { "delhash", CS_GLOBAL, complete_single_xml_file_arg },
{ "listprop", CS_SVC | CS_INST | CS_SNAP, NULL },
{ "setprop", CS_SVC | CS_INST, NULL },
{ "delprop", CS_SVC | CS_INST, NULL },
diff --git a/usr/src/cmd/svc/svccfg/svccfg_help.c b/usr/src/cmd/svc/svccfg/svccfg_help.c
index a9b8713fb8..0a03767614 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_help.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_help.c
@@ -24,7 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include "svccfg.h"
#include "svccfg_grammar.h"
@@ -80,6 +79,10 @@ struct help_message help_messages[] = {
{ SCC_DELPG, "delpg name\n\n"
"Delete the named property group from the currently selected entity."
},
+ { SCC_DELHASH, "delhash [-d] manifest\n\n"
+"Delete the named manifest hash entry (from smf/manifest).\n"
+"With -d, manifest file doesn't need to exist."
+ },
{ SCC_LISTPROP, "listprop [glob_pattern]\n\n"
"List property groups and properties of the currently selected entity."
},
diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
index c152e2cd10..9c133a37c4 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
@@ -24,7 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <alloca.h>
#include <assert.h>
@@ -48,6 +47,7 @@
#include <libxml/tree.h>
#include "svccfg.h"
+#include "manifest_hash.h"
/* The colon namespaces in each entity (each followed by a newline). */
#define COLON_NAMESPACES ":properties\n"
@@ -11022,6 +11022,40 @@ lscf_delpg(char *name)
lscf_delprop(name);
}
+/*
+ * scf_delhash() is used to remove the property group related to the
+ * hash entry for a specific manifest in the repository. pgname will be
+ * constructed from the location of the manifest file. If deathrow isn't 0,
+ * manifest file doesn't need to exist (manifest string will be used as
+ * an absolute path).
+ */
+void
+lscf_delhash(char *manifest, int deathrow)
+{
+ char *pgname;
+
+ if (cur_snap != NULL ||
+ cur_inst != NULL || cur_svc != NULL) {
+ warn(gettext("error, an entity is selected\n"));
+ return;
+ }
+
+ /* select smf/manifest */
+ lscf_select("smf/manifest");
+ /*
+ * Translate the manifest file name to property name. In the deathrow
+ * case, the manifest file does not need to exist.
+ */
+ pgname = mhash_filename_to_propname(manifest,
+ deathrow ? B_TRUE : B_FALSE);
+ if (pgname == NULL) {
+ warn(gettext("cannot resolve pathname for %s\n"), manifest);
+ return;
+ }
+ /* delete the hash property name */
+ lscf_delpg(pgname);
+}
+
void
lscf_listprop(const char *pattern)
{
diff --git a/usr/src/lib/libscf/inc/libscf.h b/usr/src/lib/libscf/inc/libscf.h
index 5bb5a19869..3bdd12f7b9 100644
--- a/usr/src/lib/libscf/inc/libscf.h
+++ b/usr/src/lib/libscf/inc/libscf.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _LIBSCF_H
#define _LIBSCF_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <stddef.h>
#include <sys/types.h>
@@ -178,6 +176,7 @@ typedef enum scf_error {
#define SCF_PG_OPTIONS_OVR ((const char *)"options_ovr")
#define SCF_PG_STARTD ((const char *)"startd")
#define SCF_PG_STARTD_PRIVATE ((const char *)"svc-startd-private")
+#define SCF_PG_DEATHROW ((const char *)"deathrow")
/*
* Template property group names and prefix
@@ -198,6 +197,7 @@ typedef enum scf_error {
#define SCF_PROPERTY_DEGRADE_IMMEDIATE ((const char *)"degrade_immediate")
#define SCF_PROPERTY_DURATION ((const char *)"duration")
#define SCF_PROPERTY_ENABLED ((const char *)"enabled")
+#define SCF_PROPERTY_DEATHROW ((const char *)"deathrow")
#define SCF_PROPERTY_ENTITY_STABILITY ((const char *)"entity_stability")
#define SCF_PROPERTY_ENTITIES ((const char *)"entities")
#define SCF_PROPERTY_EXEC ((const char *)"exec")
diff --git a/usr/src/lib/libscf/inc/libscf_priv.h b/usr/src/lib/libscf/inc/libscf_priv.h
index 5c44c9b757..ab4ad553c5 100644
--- a/usr/src/lib/libscf/inc/libscf_priv.h
+++ b/usr/src/lib/libscf/inc/libscf_priv.h
@@ -26,7 +26,6 @@
#ifndef _LIBSCF_PRIV_H
#define _LIBSCF_PRIV_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <libscf.h>
#include <unistd.h>
@@ -48,6 +47,9 @@ extern "C" {
#define SCF_PG_GENERAL_OVR_TYPE SCF_GROUP_FRAMEWORK
#define SCF_PG_GENERAL_OVR_FLAGS SCF_PG_FLAG_NONPERSISTENT
+#define SCF_PG_DEATHROW_TYPE SCF_GROUP_FRAMEWORK
+#define SCF_PG_DEATHROW_FLAGS SCF_PG_FLAG_NONPERSISTENT
+
#define SCF_PG_OPTIONS_TYPE SCF_GROUP_FRAMEWORK
#define SCF_PG_OPTIONS_FLAGS 0
diff --git a/usr/src/pkgdefs/common_files/i.manifest b/usr/src/pkgdefs/common_files/i.manifest
index 72ebfddd04..07c4b8ca78 100644
--- a/usr/src/pkgdefs/common_files/i.manifest
+++ b/usr/src/pkgdefs/common_files/i.manifest
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -21,17 +20,58 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-#
# i.manifest - smf(5) service manifest install class action script
#
repfile=$PKG_INSTALL_ROOT/etc/svc/repository.db
export repfile
+SVCCFG=/usr/sbin/svccfg
+AWK=/usr/bin/awk
+RM=/usr/bin/rm
+CP=/usr/bin/cp
+MV=/usr/bin/mv
+CHMOD=/usr/bin/chmod
+CHOWN=/usr/bin/chown
+
+#
+# Helper function. Handle services deathrow file.
+# Arguments: $1:manifest file.
+#
+svc_deathrow()
+{
+ TEMP=/tmp/svc_deathrow.$$
+ DEATHROW_FILE=${PKG_INSTALL_ROOT}/etc/svc/deathrow
+ #
+ # Services deathrow file handling, file format:
+ # <fmri>< ><manifest file>< ><package name>
+ # (field separator is a space character)
+ #
+ if [ -s ${DEATHROW_FILE} ]; then
+ #
+ # Manifest file could be from another Solaris version, bypass
+ # the service bundle and validation (we only need the fmris
+ # list). Calling svccfg inventory with SVCCFG_NOVALIDATE=1 is
+ # safe because there is no access to the alternate repository.
+ #
+ ENTITIES=`SVCCFG_NOVALIDATE=1 $SVCCFG inventory $1`
+ for fmri in $ENTITIES; do
+ #
+ # If fmri matches one in deathrow file, remove the
+ # line from the file.
+ #
+ >${TEMP}
+ $AWK "(\$1==\"$fmri\") \
+ {next}; {print}" ${DEATHROW_FILE} >>${TEMP} && \
+ $MV ${TEMP} ${DEATHROW_FILE}
+ $RM -f ${TEMP}
+ done
+ fi
+}
+
#
# If the repository does not yet exist, create it from the appropriate seed. If
# for some reason the seeds do not exist, svccfg(1M) will create the repository
@@ -41,15 +81,13 @@ if [ ! -f $repfile ]; then
if [ -n "$SUNW_PKG_INSTALL_ZONENAME" -a \
"$SUNW_PKG_INSTALL_ZONENAME" != "global" ]; then
[ -f $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db ] && \
- /usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db \
- $repfile
+ $CP $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db $repfile
else
[ -f $PKG_INSTALL_ROOT/lib/svc/seed/global.db ] && \
- /usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/global.db \
- $repfile
+ $CP $PKG_INSTALL_ROOT/lib/svc/seed/global.db $repfile
fi
- /usr/bin/chmod 0600 $repfile
- /usr/bin/chown root:sys $repfile
+ $CHMOD 0600 $repfile
+ $CHOWN root:sys $repfile
fi
if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then
@@ -59,17 +97,19 @@ if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then
# cannot consistently handle dependent placement. Defer to next boot.
#
while read src dst; do
- /usr/bin/cp -p $src $dst
+ $CP -p $src $dst
+ # deathrow handling
+ svc_deathrow $dst
done
else
#
# Local package install.
#
while read src dst; do
- /usr/bin/cp -p $src $dst
+ $CP -p $src $dst
[ "$PKG_INSTALL_ROOT" = "" -o "$PKG_INSTALL_ROOT" = "/" ] && \
- SVCCFG_CHECKHASH=1 /usr/sbin/svccfg import $dst
+ SVCCFG_CHECKHASH=1 $SVCCFG import $dst
done
fi
diff --git a/usr/src/pkgdefs/common_files/r.manifest b/usr/src/pkgdefs/common_files/r.manifest
index cf6a0dc956..879016a302 100644
--- a/usr/src/pkgdefs/common_files/r.manifest
+++ b/usr/src/pkgdefs/common_files/r.manifest
@@ -31,10 +31,56 @@ MFSTSCAN=/lib/svc/bin/mfstscan
SVCCFG=/usr/sbin/svccfg
SVCPROP=/usr/bin/svcprop
SVCADM=/usr/sbin/svcadm
+AWK=/usr/bin/awk
+CP=/usr/bin/cp
+RM=/usr/bin/rm
# number of seconds to wait before killing processes
STOP_DELAY=60
+#
+# Helper function. Delete the manifest hash value.
+# Arguments: $1: manifest file.
+#
+svc_delhash()
+{
+ $SVCCFG delhash $1 >/dev/null 2>&1
+ if [ "$?" != "0" ];then
+ # this Solaris release doesn't have delhash command
+ pg_name=`$MFSTSCAN -t $1`
+ if $SVCPROP -q -p $pg_name smf/manifest; then
+ $SVCCFG -s smf/manifest delpg $pg_name
+ fi
+ fi
+}
+
+#
+# Helper function. Handle services deathrow file.
+# Arguments: $1:manifest file, $2:package name.
+#
+svc_deathrow()
+{
+ DEATHROW_FILE=${PKG_INSTALL_ROOT}/etc/svc/deathrow
+ # remove alternate root from manifest path
+ manifest=`echo "${PKG_INSTALL_ROOT} $1" | $AWK \
+ '{ print substr($2, length($1)+1); }'`
+ #
+ # Services deathrow file handling, file format:
+ # <fmri>< ><manifest file>< ><package name>
+ # (field separator is a space character)
+ #
+ # Manifest file could be from another Solaris version, bypass the
+ # the service bundle and validation (we only need the fmris list).
+ # Calling svccfg inventory with SVCCFG_NOVALIDATE=1 is safe because
+ # there is no access to the alternate repository.
+ #
+ ENTITIES=`SVCCFG_NOVALIDATE=1 $SVCCFG inventory $1`
+ for fmri in $ENTITIES; do
+ # add to services deathrow file
+ echo ${fmri} ${manifest} $2 >> ${DEATHROW_FILE}
+ done
+}
+
wait_disable() {
svcinst=$1
wait_time=$2
@@ -128,13 +174,13 @@ while read mfst; do
#
# Delete the manifest hash value.
#
- pg_name=`$MFSTSCAN -t $mfst`
- if $SVCPROP -q -p $pg_name smf/manifest; then
- $SVCCFG -s smf/manifest delpg $pg_name
- fi
+ svc_delhash $mfst
+ else
+ # deathrow handling
+ svc_deathrow $mfst $PKGINST
fi
- /usr/bin/rm $mfst
+ $RM -f $mfst
done
exit 0