summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
authorSean Wilcox <Sean.Wilcox@Sun.COM>2009-09-07 10:46:52 -0700
committerSean Wilcox <Sean.Wilcox@Sun.COM>2009-09-07 10:46:52 -0700
commit23294c7da48c2eb5222bccedbefb1e06cf5c4df3 (patch)
tree4459e74ddb1749d95bc583a78419b66c5bdc285c /usr/src/cmd
parent7b3411b6ce9d5ba373d2e36a6c8db48b2dfb74b7 (diff)
downloadillumos-joyent-23294c7da48c2eb5222bccedbefb1e06cf5c4df3.tar.gz
6859248 manifest removal should automatically cause repository cleanup
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/svc/common/manifest_hash.c34
-rw-r--r--usr/src/cmd/svc/common/manifest_hash.h6
-rw-r--r--usr/src/cmd/svc/milestone/manifest-import48
-rw-r--r--usr/src/cmd/svc/prophist/prophist.c10
-rw-r--r--usr/src/cmd/svc/shell/Makefile3
-rw-r--r--usr/src/cmd/svc/shell/manifest_cleanup.ksh474
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_engine.c4
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_libscf.c145
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_xml.c37
9 files changed, 725 insertions, 36 deletions
diff --git a/usr/src/cmd/svc/common/manifest_hash.c b/usr/src/cmd/svc/common/manifest_hash.c
index 547f791df9..d833a53325 100644
--- a/usr/src/cmd/svc/common/manifest_hash.c
+++ b/usr/src/cmd/svc/common/manifest_hash.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -189,16 +189,18 @@ out:
}
int
-mhash_store_entry(scf_handle_t *hndl, const char *name, uchar_t *hash,
- char **errstr)
+mhash_store_entry(scf_handle_t *hndl, const char *name, const char *fname,
+ uchar_t *hash, char **errstr)
{
scf_scope_t *scope = NULL;
scf_service_t *svc = NULL;
scf_propertygroup_t *pg = NULL;
scf_property_t *prop = NULL;
scf_value_t *val = NULL;
+ scf_value_t *fval = NULL;
scf_transaction_t *tx = NULL;
scf_transaction_entry_t *e = NULL;
+ scf_transaction_entry_t *fe = NULL;
int ret, result = 0;
int i;
@@ -312,7 +314,9 @@ mhash_store_entry(scf_handle_t *hndl, const char *name, uchar_t *hash,
}
if ((e = scf_entry_create(hndl)) == NULL ||
- (val = scf_value_create(hndl)) == NULL) {
+ (val = scf_value_create(hndl)) == NULL ||
+ (fe = scf_entry_create(hndl)) == NULL ||
+ (fval = scf_value_create(hndl)) == NULL) {
if (errstr != NULL)
*errstr = gettext("Could not store file hash: "
"permission denied.\n");
@@ -322,6 +326,8 @@ mhash_store_entry(scf_handle_t *hndl, const char *name, uchar_t *hash,
ret = scf_value_set_opaque(val, hash, MHASH_SIZE);
assert(ret == SCF_SUCCESS);
+ ret = scf_value_set_astring(fval, fname);
+ assert(ret == SCF_SUCCESS);
tx = scf_transaction_create(hndl);
if (tx == NULL) {
@@ -372,6 +378,20 @@ mhash_store_entry(scf_handle_t *hndl, const char *name, uchar_t *hash,
ret = scf_entry_add_value(e, val);
assert(ret == SCF_SUCCESS);
+ if (scf_transaction_property_new(tx, fe, MFILE_PROP,
+ SCF_TYPE_ASTRING) != SCF_SUCCESS &&
+ scf_transaction_property_change_type(tx, fe, MFILE_PROP,
+ SCF_TYPE_ASTRING) != SCF_SUCCESS) {
+ if (errstr != NULL)
+ *errstr = gettext("Could not modify file "
+ "entry");
+ result = -1;
+ goto out;
+ }
+
+ ret = scf_entry_add_value(fe, fval);
+ assert(ret == SCF_SUCCESS);
+
ret = scf_transaction_commit(tx);
if (ret == 0)
@@ -394,9 +414,11 @@ mhash_store_entry(scf_handle_t *hndl, const char *name, uchar_t *hash,
scf_transaction_destroy(tx);
(void) scf_entry_destroy(e);
+ (void) scf_entry_destroy(fe);
out:
(void) scf_value_destroy(val);
+ (void) scf_value_destroy(fval);
scf_property_destroy(prop);
scf_pg_destroy(pg);
scf_service_destroy(svc);
@@ -609,7 +631,7 @@ mhash_test_file(scf_handle_t *hndl, const char *file, uint_t is_profile,
* we then update the database with the complete
* new hash so we can be a bit quicker next time.
*/
- (void) mhash_store_entry(hndl, pname, hash, NULL);
+ (void) mhash_store_entry(hndl, pname, file, hash, NULL);
uu_free(pname);
return (MHASH_RECONCILED);
}
@@ -633,7 +655,7 @@ mhash_test_file(scf_handle_t *hndl, const char *file, uint_t is_profile,
* Update the new entry so we don't have to go through
* all this trouble next time.
*/
- (void) mhash_store_entry(hndl, pname, hash, NULL);
+ (void) mhash_store_entry(hndl, pname, file, hash, NULL);
uu_free(pname);
return (MHASH_RECONCILED);
}
diff --git a/usr/src/cmd/svc/common/manifest_hash.h b/usr/src/cmd/svc/common/manifest_hash.h
index ec718b9c76..1a43137e44 100644
--- a/usr/src/cmd/svc/common/manifest_hash.h
+++ b/usr/src/cmd/svc/common/manifest_hash.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,6 +41,7 @@ extern "C" {
#define MHASH_PG_TYPE "framework"
#define MHASH_PG_FLAGS 0
#define MHASH_PROP "md5sum"
+#define MFILE_PROP "manifestfile"
#define MHASH_FORMAT_V1 "%llx%x%llx%lx"
#define MHASH_FORMAT_V2 "%x%x%llx%lx"
@@ -51,7 +52,8 @@ extern "C" {
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_store_entry(scf_handle_t *, const char *, const char *, uchar_t *,
+ char **);
int mhash_test_file(scf_handle_t *, const char *, uint_t, char **, uchar_t *);
#ifdef __cplusplus
diff --git a/usr/src/cmd/svc/milestone/manifest-import b/usr/src/cmd/svc/milestone/manifest-import
index 0b3586d0ae..113b308b99 100644
--- a/usr/src/cmd/svc/milestone/manifest-import
+++ b/usr/src/cmd/svc/milestone/manifest-import
@@ -1,4 +1,4 @@
-#!/sbin/sh
+#!/bin/ksh
#
# CDDL HEADER START
#
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -29,6 +29,7 @@
[ -f /lib/svc/share/smf_include.sh ] || exit 1
. /lib/svc/share/smf_include.sh
+. /lib/svc/share/manifest_cleanup.ksh
activity=false
@@ -41,14 +42,14 @@ while getopts n opt; do
esac
done
-svccfg_apply () {
+function svccfg_apply {
$X /usr/sbin/svccfg apply $1
if [ $? -ne 0 ]; then
echo "WARNING: svccfg apply $1 failed" | tee /dev/msglog
fi
}
-svccfg_import () {
+function svccfg_import {
$X /usr/sbin/svccfg import $1 2>>/tmp/manifest_import.$$
if [ $? -ne 0 ]; then
echo > /dev/msglog
@@ -56,7 +57,7 @@ svccfg_import () {
fi
}
-prophist_upgrade () {
+function prophist_upgrade {
#
# A property has changed in the manifest that we wish to propagate into
# the repository during manifest import. We don't want to pollute
@@ -73,7 +74,7 @@ prophist_upgrade () {
[ $? = 0 ] && instance_refresh $fmri
}
-prophist_override () {
+function prophist_override {
#
# A property has changed in the manifest that we wish to propagate
# into the repository during manifest import.
@@ -87,7 +88,7 @@ prophist_override () {
[ $? = 0 ] && instance_refresh $fmri
}
-prophist_delete_svc_pg () {
+function prophist_delete_svc_pg {
#
# Certain property groups have migrated from the service level to the
# instance level. We don't care if they are at both, as the instance
@@ -108,7 +109,7 @@ prophist_delete_svc_pg () {
fi
}
-prophist_delete_dependency () {
+function prophist_delete_dependency {
#
# Some services have stale dependencies that need to be removed.
# This is done by removing the dependency property group.
@@ -125,7 +126,7 @@ prophist_delete_dependency () {
fi
}
-prophist_delete_pg () {
+function prophist_delete_pg {
# Delete obsolete property groups from old manifests. Instances
# should be refreshed for changes to take effect.
fmri=$1
@@ -135,7 +136,7 @@ prophist_delete_pg () {
/lib/svc/bin/prophist delete -e $fmri -g $pg
}
-prophist_addprop () {
+function prophist_addprop {
#
# If a property doesn't exist, create it. Instances should be
# refreshed for changes to take effect.
@@ -161,7 +162,7 @@ prophist_addprop () {
/usr/sbin/svccfg -s $fmri setprop $pg/$prop = $*
}
-prophist_addmeth () {
+function prophist_addmeth {
#
# If a method doesn't exist, create it. Instances should be refreshed
# for changes to take effect.
@@ -188,7 +189,7 @@ prophist_addmeth () {
END
}
-prophist_adddep () {
+function prophist_adddep {
#
# If a dependency doesn't exist, create it. Instances should be
# refreshed for changes to take effect.
@@ -218,7 +219,7 @@ prophist_adddep () {
END
}
-prophist_adddpt () {
+function prophist_adddpt {
#
# If a dependent doesn't exist, create it. Instances should be
# refresh for changes to take effect.
@@ -242,26 +243,26 @@ prophist_adddpt () {
prophist_adddep $target $name service $group $ro $fmri
}
-instance_refresh () {
+function instance_refresh {
echo $1 >> /etc/svc/volatile/refreshes
}
-refresh_instances () {
+function refresh_instances {
[ -r /etc/svc/volatile/refreshes ] && {
sort -u /etc/svc/volatile/refreshes | xargs -l svcadm refresh
}
}
-instance_clear () {
+function instance_clear {
echo $1 >> /etc/svc/volatile/clears
}
-clear_conditionally () {
+function clear_conditionally {
[ "`/usr/bin/svcprop -p restarter/state $1`" = "maintenance" ] && \
/usr/sbin/svcadm clear $1
}
-clear_instances () {
+function clear_instances {
[ -r /etc/svc/volatile/clears ] && {
for inst in `/usr/bin/sort -u /etc/svc/volatile/clears`; do
clear_conditionally $inst
@@ -269,7 +270,7 @@ clear_instances () {
}
}
-prepare_last_import () {
+function prepare_last_import {
# Preserve the five hashes for the profiles: generic (two
# cases), platform (uname -i, uname -m outputs), and site.
@@ -458,6 +459,7 @@ if [ -n "$nonsite_manifests" -o -n "$site_manifests" ]; then
rm -f /tmp/manifest_import.$$
set -- $manifests
+ cleanup=""
backup=`echo "$#/$#" | sed 's/.//g'`
fwidth=`echo "$#\c" | wc -c`
@@ -471,13 +473,19 @@ if [ -n "$nonsite_manifests" -o -n "$site_manifests" ]; then
doswitch=$?
i=1; n=$#
+ svcprop smf/manifest > /etc/svc/volatile/smf_manifest_svcprop 2>&1
while [ $# -gt 0 ]; do
printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog
+ grep $1 /etc/svc/volatile/smf_manifest_svcprop > /dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ cleanup="$cleanup $1"
+ fi
svccfg_import $1
i=`expr $i + 1`
shift
echo "$backup\c" > /dev/msglog
done
+ rm -f /etc/svc/volatile/smf_manifest_svcprop
#
# If switch back fails, exit with the fatal error code.
@@ -578,4 +586,6 @@ if $activity; then
svcadm _smf_backup "manifest_import" || true
fi
+manifest_cleanup $activity $cleanup
+
exit 0
diff --git a/usr/src/cmd/svc/prophist/prophist.c b/usr/src/cmd/svc/prophist/prophist.c
index 0f42c906ec..8f1aedb1a5 100644
--- a/usr/src/cmd/svc/prophist/prophist.c
+++ b/usr/src/cmd/svc/prophist/prophist.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* prophist - property history utility
*
@@ -193,15 +191,15 @@ hash(char *arg)
uu_die(gettext("mhash_test_file() failed"));
default:
uu_die(gettext("unknown return value (%d) from "
- "mhash_test_file()"), ret);
+ "mhash_test_file()"), ret);
}
- if (mhash_store_entry(hndl, pname, hash, &errstr)) {
+ if (mhash_store_entry(hndl, pname, arg, hash, &errstr)) {
if (errstr)
uu_die(errstr);
else
uu_die(gettext("Unknown error from "
- "mhash_store_entry()\n"));
+ "mhash_store_entry()\n"));
}
return (3);
diff --git a/usr/src/cmd/svc/shell/Makefile b/usr/src/cmd/svc/shell/Makefile
index 3367b317be..fc9bc37da3 100644
--- a/usr/src/cmd/svc/shell/Makefile
+++ b/usr/src/cmd/svc/shell/Makefile
@@ -31,7 +31,8 @@ SRCS = \
net_include.sh \
routing_include.sh \
sendmail_include.sh \
- smf_include.sh
+ smf_include.sh \
+ manifest_cleanup.ksh
SCRIPTS = $(SRCS:%=$(ROOT)/lib/svc/share/%)
diff --git a/usr/src/cmd/svc/shell/manifest_cleanup.ksh b/usr/src/cmd/svc/shell/manifest_cleanup.ksh
new file mode 100644
index 0000000000..8c29e9fabb
--- /dev/null
+++ b/usr/src/cmd/svc/shell/manifest_cleanup.ksh
@@ -0,0 +1,474 @@
+#!/bin/ksh
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+[ -f /lib/svc/share/smf_include.sh ] || exit 1
+
+. /lib/svc/share/smf_include.sh
+
+SVCADM=/usr/sbin/svcadm
+SVCCFG=/usr/sbin/svccfg
+SVCPROP=/bin/svcprop
+SVCS=/usr/bin/svcs
+MFSTPG=manifestfiles
+MFSTSCAN=/lib/svc/bin/mfstscan
+MCLEANUPFILE=/etc/svc/volatile/mcleanup.$$
+IGNORELIST="system/install-discovery smf/manifest"
+UPLIST=0
+
+#
+# Create a list of service to manifest pairs for the upgrade
+# process to determine what files are associated with a service
+#
+function create_list {
+ for cl_mfile in `find /var/svc/manifest -name "*.xml"`
+ do
+ for cl_invent in `svccfg inventory $cl_mfile`
+ do
+ cl_invent=${cl_invent#svc:/*}
+
+ cl_instance=${cl_invent#*:}
+ cl_instance=${cl_instance##*/*}
+ [ $cl_instance ] && continue
+
+ cl_invent=${cl_invent%:*}
+ cl_invent=`echo $cl_invent | sed -e 's/[-\/\,]/_/g'`
+
+
+ eval $cl_invent=\"\$$cl_invent $cl_mfile\"
+ # XXX - remove this line at some point "
+ # I clears up the above escaped quote throwing
+ # off my color scheme in vim.
+ done
+ done
+ UPLIST=1
+}
+
+#
+# Inventory the instances listed with a manifest file
+#
+function get_instances {
+ gi_mfile=$1
+
+ lst=""
+ for gi_invent in `svccfg inventory $gi_mfile`
+ do
+ gi_tmp=${gi_invent#svc:/*}
+ gi_tmp=${gi_tmp#*:}
+ gi_tmp=${gi_tmp##*/*}
+
+ [ $gi_tmp ] && lst="$lst $gi_invent"
+ done
+
+ echo $lst
+}
+
+function pid_timeout {
+ pt_pid=$1
+
+ pt_cnt=0
+ while [ `ps -p $pt_pid -o pid | grep -v PID` -a $pt_cnt -lt 30 ]
+ do
+ sleep 1
+ cnt=`expr $pt_cnt + 1`
+ done
+ if [ $pt_cnt -eq 30 -a "`ps -p $pt_pid -o pid | grep -v PID`" ]; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+#
+# Process a service to ensure that it's manifests exist
+# and are in sync with the service.
+#
+function process_service {
+ ps_service=$1
+
+ #
+ # Throw away unsupported services, if there is a false listing
+ # for manifestfiles support
+ #
+ $SVCPROP -p $MFSTPG/support $ps_service 2>/dev/null | grep false > /dev/null
+ [ $? -eq 0 ] && return
+
+ #
+ # Create the list of instances for this service.
+ #
+ $SVCPROP -p $MFSTPG $ps_service > $MCLEANUPFILE
+ set -A ps_mfiles `grep astring $MCLEANUPFILE | awk '{print $3}'`
+
+ #
+ # Check to see if the manifest files associated with the service are
+ # missing, or if the manifest file has changed, either caught here
+ # or by the caller.
+ #
+ ps_x=`$MFSTSCAN ${ps_mfiles[@]} 2>&1`
+ if [ $? -eq 0 ]; then
+ if [ "$force" != "true" -a ! "$ps_x" ]; then
+ ps_ret=0
+ for ps_f in ${ps_mfiles[@]}
+ do
+ echo "$force" | grep -v $ps_f > /dev/null 2>&1
+ ps_ret=`expr $ps_ret + $?`
+ done
+ [ $ps_ret -eq 0 ] && return
+ fi
+ fi
+
+ ps_refresh=0
+ ps_mfiles_tmp=""
+ ps_mfiles_cnt=${#ps_mfiles[@]}
+ ps_instances=`$SVCS -H -oFMRI $ps_service 2>/dev/null`
+
+ #
+ # For each manifest file that is listed by the service
+ # check for its existance. If it exists, then check that
+ # the instances of the service are supported by at least
+ # one of the manifest files listed.
+ #
+ for mf in ${ps_mfiles[@]}
+ do
+ if [ ! -f $mf ]; then
+ ps_mfiles_tmp="$ps_mfiles_tmp $mf"
+ continue
+ fi
+
+ [ ${mf%/var/svc/manifest*} ] && continue
+
+ inst=`get_instances $mf`
+
+ set -A ps_inst_list
+ for i in $inst
+ do
+ ps_inst_tmp=""
+ for j in $ps_instances
+ do
+ if [ "$i" == "$j" ]; then
+ set -A ps_inst_list ${ps_inst_list[*]} $j
+ continue
+ else
+ ps_inst_tmp="$ps_inst_tmp $j"
+ fi
+ done
+ #
+ # If there are any instances not accounted for add
+ # them to the list to be cleaned up.
+ #
+ ps_instances=$ps_inst_tmp
+ done
+ done
+ #
+ # If there are any manifest files set them to the list
+ # to be cleaned up.
+ #
+ set -A ps_mfiles $ps_mfiles_tmp
+
+ #
+ # For each manifest file that was not found remove it from
+ # the service's list of manifest files.
+ #
+ for mf in ${ps_mfiles[@]}
+ do
+ #
+ # Need to remove the file from the smf/manifest
+ # list.
+ #
+ ps_refresh=1
+ mf_nw=`echo "$needwork" | grep -v $mf`
+ needwork="$mf_nw"
+ mf_srch=`echo $mf | sed -e 's/\./\\\./g'`
+ mf_pg=`grep "$mf_srch" $MCLEANUPFILE | awk '{print $1}'`
+ [ $ps_mfiles_cnt -ne ${#ps_mfiles[@]} ] && \
+ $SVCCFG -s $ps_service delprop $mf_pg > /dev/null 2>&1
+ mf_pg=`echo $mf_pg | awk -F'/' '{print $2}'`
+ $SVCCFG -s smf/manifest delpg $mf_pg > /dev/null 2>&1
+ done
+
+ #
+ # If all the manifest files that were listed in the service have now
+ # been removed, delete the service.
+ #
+ if [ $ps_mfiles_cnt -eq ${#ps_mfiles[@]} ]; then
+ #
+ # Disable each of the instances for the service
+ # then delete the service.
+ #
+ # If the restarter is not startd then the service
+ # will not be online at this point and we need
+ # to not wait on the disable.
+ #
+ # Set the delete opt to -f if the disable is not
+ # synchronous.
+ #
+ $SVCPROP -q -p general/restarter $ps_service
+ if [ $? -ne 0 ]; then
+ DISOPT="-s"
+ DELOP=""
+ else
+ DISOPT=""
+ DELOP="-f"
+ fi
+
+ for i in `$SVCS -H -oFMRI $ps_service`
+ do
+ $SVCADM disable $DISOPT $i &
+ CPID=$!
+
+ pid_timeout $CPID
+ if [ $? -ne 0 ]; then
+ DELOPT="-f"
+ kill $CPID
+ fi
+ done
+
+ echo "$SVCCFG delete $ps_service"
+ $SVCCFG delete $DELOPT $ps_service
+ return
+ fi
+
+ #
+ # Need to only cleanup instances that are no longer supported
+ # by the manifest files associated with the service.
+ #
+ for i in $ps_instances
+ do
+ #
+ # Ignore any instances that are hand created
+ #
+ ps_refresh=1
+ $SVCCFG -s $i selectsnap last-import > /dev/null 2>&1
+ [ $? -ne 0 ] && continue
+
+ #
+ # If the restarter is not startd then the service
+ # will not be online at this point and we need
+ # to not wait on the disable.
+ #
+ $SVCPROP -q -p general/restarter $ps_service
+ if [ $? -ne 0 ]; then
+ DELOP=""
+ $SVCADM disable -s $i &
+ CPID=$!
+
+ pid_timeout $CPID
+ if [ $? -ne 0 ]; then
+ DELOPT="-f"
+ kill $CPID
+ fi
+ else
+ DELOP="-f"
+ $SVCADM disable $i
+ fi
+
+ echo "$SVCCFG delete $i"
+ $SVCCFG delete $DELOP $i
+ done
+
+ #
+ # If instances of the services were removed, refresh the
+ # additional instances, or cleanup any leftover services.
+ #
+ if [ $ps_refresh -ne 0 ]; then
+ if [ ${#ps_inst_list[@]} -gt 0 ]; then
+ for i in ${ps_inst_list[@]}
+ do
+ $SVCCFG -s $i refresh
+ done
+ else
+ ps_support=0
+ for ps_mfile in `awk '{print $3}' $MCLEANUPFILE`
+ do
+ $SVCCFG inventory $ps_mfile | grep $ps_service > /dev/null 2>&1
+ [ $? -eq 0 ] && ps_supprt=1
+ done
+ [ $ps_support -eq 0 ] && $SVCCFG delete $ps_service
+ fi
+ fi
+}
+
+#
+# Upgrade a service to have the manifest files associated with
+# listed in the manifestfiles property group.
+#
+# If the first argument is FALSE, then check to see if the service
+# has any previous import indications. If so then delete the
+# service, otherwise set the service as a non-supported service
+# for the automated manifest deletion process.
+#
+function add_manifest {
+ am_service=$1
+ shift
+
+ $SVCCFG -s $am_service addpg $MFSTPG framework
+
+ if [ "$1" == "FALSE" ]; then
+ am_lisnap=1
+ am_inst=`svcs -H -oFMRI $am_service 2>/dev/null`
+ if [ $? -eq 0 ]; then
+ for i in $am_inst
+ do
+ $SVCCFG -s $i selectsnap last-import > /dev/null 2>&1
+ [ $? -eq 0 ] && am_lisnap=0
+ done
+ fi
+
+ if [ $am_lisnap -eq 0 ]; then
+ $SVCCFG delete -f $am_service
+ else
+ $SVCCFG -s $am_service setprop $MFSTPG/support = boolean: 0
+ fi
+ else
+ for am_mfile in $@
+ do
+ CF=${am_mfile#/*}
+ CF=`echo $CF | sed -e 's/[-\/\,\.]/_/g'`
+ $SVCCFG -s $am_service setprop $MFSTPG/$CF = astring: $am_mfile
+ done
+ fi
+}
+
+#
+# upgrade the entries in the smf/manifest table to have
+# a pointer to the actual manifest file.
+#
+function upgrade_smfmanifest {
+ us_unfnd=""
+
+ for us_E in `$SVCPROP smf/manifest | grep md5sum | grep var_svc_manifest | awk '{print $1}' | awk -F'/' '{print $1}'`
+ do
+ $SVCPROP -q -p $us_E/manifestfile smf/manifest
+ [ $? -eq 0 ] && continue
+
+ us_S=`echo $us_E | sed -e 's/_xml/.xml/'`
+ us_S=`echo $us_S | sed -e 's/var_svc_manifest_/var\/svc\/manifest\//'`
+
+ us_R=""
+ while [ ! -f $us_S -a ! "$us_R" ]
+ do
+ us_S=`echo $us_S | sed -e 's/_/\//'`
+ us_R=${us_S##*_*}
+ done
+
+ us_S="/$us_S"
+ if [ -f $us_S ]; then
+ us_R=`$MFSTSCAN $us_S`
+ [ ! "$R" ] && \
+ $SVCCFG -s smf/manifest setprop ${us_E}/manifestfile = astring: $us_S
+ else
+ us_unfnd="$us_unfnd $us_E"
+ fi
+ done
+
+ echo "$us_unfnd"
+}
+
+function manifest_cleanup {
+ #
+ # If manifest-import had activity then need to make checks to override
+ # a mfstscan that returns no modifications. This is because the hash
+ # table will already have been updated by the manifest-import run,
+ # therefor manifest-cleanup will not see those changes in the mfstscan
+ # call.
+ #
+ # activity indicates changes and overrides the needwork check.
+ # force can be a list of files that will only be processed
+ # or force can be set to true, so that all files are checked
+ # regardless.
+ #
+ arg1=$1
+ activity=${arg1:-true}
+ [ "$1" ] && shift
+ argrest=$@
+ force=${argrest:-false}
+
+ #
+ # Check the smf/manifest table to see if it needs upgrading
+ #
+ md5c=`$SVCPROP smf/manifest | grep var_svc_manifest | grep -c md5sum`
+ mfc=`$SVCPROP smf/manifest | grep var_svc_manifest | grep -cw manifestfile`
+ if [ $md5c -ne $mfc ]; then
+ unfnd_upgrade=`upgrade_smfmanifest`
+ if [ "$force" == false ]; then
+ activity="true"
+ force="true"
+ fi
+ fi
+
+ smfmfiles=`svcprop smf/manifest | grep manifestfile | grep astring | awk '{print $3}'`
+ needwork=`/lib/svc/bin/mfstscan $smfmfiles 2>&1 1>/dev/null`
+ if [ ! "$needwork" ]; then
+ [ "$activity" == false ] && return
+
+ [ "$activity" == true -a "$force" == false ] && return
+ fi
+
+ #
+ # Walk the list of services...
+ #
+ export SVCCFG_CHECKHASH=1
+ for service in `$SVCCFG list`
+ do
+ svcprop -q -p $MFSTPG $service
+ if [ $? -ne 0 ]; then
+ if [[ $IGNORELIST == $ps_service ]]; then
+ echo "add_manifest $service FALSE"
+ add_manifest $service FALSE
+ fi
+
+ [ $UPLIST -eq 0 ] && create_list
+
+ CS=`echo $service | sed -e 's/[-\/\,]/_/g'`
+
+ eval manifestlist=\$$CS
+ if [ -n "$manifestlist" ]; then
+ echo "add_manifest $service $manifestlist"
+ add_manifest $service $manifestlist
+ else
+ echo "add_manifest $service FALSE"
+ add_manifest $service FALSE
+ fi
+ else
+ process_service $service
+ fi
+ done
+
+ rm -f $MCLEANUPFILE
+ unset SVCCFG_CHECKHASH
+
+ #
+ # Check to make sure all work was processed and
+ # that all the files were removed correctly from
+ # the smf/manifest table.
+ #
+ leftover=`echo "$needwork" | grep "cannot stat" | awk '{print $4}'`
+ for f in $leftover $unfnd_upgrade
+ do
+ f_srch=`echo $f | sed -e 's/\./\\\./g; s/:$//'`
+ f_entry=`$SVCPROP smf/manifest | grep "$f_srch" | awk -F'/' '{print $1}'`
+ [ "$f_entry" ] && $SVCCFG -s smf/manifest delpg $f_entry
+ done
+}
diff --git a/usr/src/cmd/svc/svccfg/svccfg_engine.c b/usr/src/cmd/svc/svccfg/svccfg_engine.c
index 660582fe07..365f2c9ac5 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_engine.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_engine.c
@@ -622,7 +622,7 @@ engine_import(uu_list_t *args)
if (pname) {
char *errstr;
- if (mhash_store_entry(g_hndl, pname, hash, &errstr)) {
+ if (mhash_store_entry(g_hndl, pname, file, hash, &errstr)) {
if (errstr)
semerr(errstr);
else
@@ -671,7 +671,7 @@ engine_apply(const char *file, int apply_changes)
if (pname) {
char *errstr;
- if (mhash_store_entry(g_hndl, pname, hash, &errstr))
+ if (mhash_store_entry(g_hndl, pname, file, hash, &errstr))
semerr(errstr);
free(pname);
diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
index d7dc1311de..76b8ed2e87 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
@@ -48,6 +48,8 @@
#include <libxml/tree.h>
+#include <sys/param.h>
+
#include "svccfg.h"
#include "manifest_hash.h"
@@ -3288,6 +3290,145 @@ commit:
}
/*
+ * Used to add the manifests to the list of currently supported manifests.
+ * We could modify the existing manifest list removing entries if the files
+ * don't exist.
+ *
+ * Get the old list and the new file name
+ * If the new file name is in the list return
+ * If not then add the file to the list.
+ * As we process the list check to see if the files in the old list exist
+ * if not then remove the file from the list.
+ * Commit the list of manifest file names.
+ *
+ */
+static int
+upgrade_manifestfiles(const entity_t *ient, const scf_snaplevel_t *running,
+ void *ent)
+{
+ scf_propertygroup_t *ud_run_mfsts_pg = NULL;
+ scf_property_t *ud_run_prop = NULL;
+ scf_iter_t *ud_prop_iter;
+ scf_value_t *fname_value;
+ pgroup_t *mfst_pgroup;
+ property_t *mfst_prop;
+ property_t *old_prop;
+ char *pname = malloc(MAXPATHLEN);
+ char *fval;
+ char *old_pname;
+ char *old_fval;
+ int mfst_seen;
+ int r;
+
+ const int issvc = (ient->sc_etype == SVCCFG_SERVICE_OBJECT);
+
+ /*
+ * This should always be the service base on the code
+ * path, and the fact that the manifests pg is a service
+ * level property group only.
+ */
+ ud_run_mfsts_pg = scf_pg_create(g_hndl);
+ ud_run_prop = scf_property_create(g_hndl);
+ ud_prop_iter = scf_iter_create(g_hndl);
+ fname_value = scf_value_create(g_hndl);
+
+ /* Fetch the running version of the "manifests" property group */
+ if (running != NULL)
+ r = scf_snaplevel_get_pg(running, SCF_PG_MANIFESTFILES,
+ ud_run_mfsts_pg);
+ else
+ r = entity_get_pg(ent, issvc, SCF_PG_MANIFESTFILES,
+ ud_run_mfsts_pg);
+
+ if (r != 0) {
+ 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_NOT_SET:
+ case SCF_ERROR_INVALID_ARGUMENT:
+ case SCF_ERROR_HANDLE_MISMATCH:
+ case SCF_ERROR_NOT_BOUND:
+ default:
+ bad_error(running ? "scf_snaplevel_get_pg" :
+ "entity_get_pg", scf_error());
+ }
+ }
+
+ /* Fetch the new manifests property group */
+ for (mfst_pgroup = uu_list_first(ient->sc_pgroups);
+ mfst_pgroup != NULL;
+ mfst_pgroup = uu_list_next(ient->sc_pgroups, mfst_pgroup)) {
+ if (strcmp(mfst_pgroup->sc_pgroup_name,
+ SCF_PG_MANIFESTFILES) == 0)
+ break;
+ }
+
+ if (scf_iter_pg_properties(ud_prop_iter, ud_run_mfsts_pg) !=
+ SCF_SUCCESS)
+ return (-1);
+
+ while ((r = scf_iter_next_property(ud_prop_iter, ud_run_prop)) == 1) {
+ mfst_seen = 0;
+ if (scf_property_get_name(ud_run_prop, pname, MAXPATHLEN) < 0)
+ continue;
+
+ for (mfst_prop = uu_list_first(mfst_pgroup->sc_pgroup_props);
+ mfst_prop != NULL;
+ mfst_prop = uu_list_next(mfst_pgroup->sc_pgroup_props,
+ mfst_prop)) {
+ if (strcmp(mfst_prop->sc_property_name, pname) == 0) {
+ mfst_seen = 1;
+ }
+ }
+
+ /*
+ * If the manifest is not seen then add it to the new mfst
+ * property list to get proccessed into the repo.
+ */
+ if (mfst_seen == 0) {
+ fval = malloc(MAXPATHLEN);
+
+ /*
+ * If we cannot get the value then there is no
+ * reasont to attempt to attach the value to
+ * the property group
+ */
+ if (fval != NULL &&
+ prop_get_val(ud_run_prop, fname_value) == 0 &&
+ scf_value_get_astring(fname_value, fval,
+ MAXPATHLEN) != -1) {
+ /*
+ * First check to see if the manifest is there
+ * if not then there is no need to add it.
+ */
+ if (access(fval, F_OK) == -1) {
+ free(fval);
+ continue;
+ }
+ old_pname = safe_strdup(pname);
+ old_fval = safe_strdup(fval);
+ old_prop = internal_property_create(old_pname,
+ SCF_TYPE_ASTRING, 1, old_fval);
+
+ /*
+ * Already checked to see if the property exists
+ * in the group, and it does not.
+ */
+ (void) internal_attach_property(mfst_pgroup,
+ old_prop);
+ }
+ }
+ }
+
+ return (r);
+}
+
+/*
* prop is taken to be a property in the "dependents" property group of snpl,
* which is taken to be the snaplevel of a last-import snapshot corresponding
* to ient. If prop is a valid dependents property, upgrade the dependent it
@@ -4698,6 +4839,10 @@ process_old_pg(const scf_propertygroup_t *lipg, entity_t *ient, void *ent,
if (strcmp(imp_str, "dependents") == 0)
return (upgrade_dependents(lipg, imp_snpl, ient, running, ent));
+ if (strcmp(imp_str, SCF_PG_MANIFESTFILES) == 0)
+ if ((r = upgrade_manifestfiles(ient, running, ent)) != 0)
+ return (r);
+
if (mpg == NULL || mpg->sc_pgroup_delete) {
/* property group was deleted from manifest */
if (entity_get_pg(ent, issvc, imp_str, imp_pg2) != 0) {
diff --git a/usr/src/cmd/svc/svccfg/svccfg_xml.c b/usr/src/cmd/svc/svccfg/svccfg_xml.c
index 0947068b8f..dd9236bc08 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_xml.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_xml.c
@@ -50,6 +50,9 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <sys/param.h>
+#include "manifest_hash.h"
+
#include "svccfg.h"
/*
@@ -2948,6 +2951,8 @@ lxml_get_single_instance(entity_t *entity, xmlNodePtr si)
static int
lxml_get_service(bundle_t *bundle, xmlNodePtr svc, svccfg_op_t op)
{
+ pgroup_t *pg;
+ property_t *p;
entity_t *s;
xmlNodePtr cursor;
xmlChar *type;
@@ -2969,6 +2974,36 @@ lxml_get_service(bundle_t *bundle, xmlNodePtr svc, svccfg_op_t op)
xmlFree(type);
/*
+ * Now that the service is created create the manifest
+ * property group and add the property value of the service.
+ */
+ if (svc->doc->name != NULL &&
+ bundle->sc_bundle_type == SVCCFG_MANIFEST) {
+ char *buf, *base, *fname;
+
+ pg = internal_pgroup_create_strict(s, SCF_PG_MANIFESTFILES,
+ SCF_GROUP_FRAMEWORK);
+
+ if (pg == NULL) {
+ uu_die(gettext("Property group for prop_pattern, "
+ "\"%s\", already exists in %s\n"),
+ SCF_PG_MANIFESTFILES, s->sc_name);
+ }
+ buf = mhash_filename_to_propname(svc->doc->name, B_FALSE);
+ /*
+ * Must remove the PKG_INSTALL_ROOT, point to the correct
+ * directory after install
+ */
+ base = getenv("PKG_INSTALL_ROOT");
+ fname = safe_strdup(svc->doc->name +
+ ((base != NULL) ? strlen(base) : 0));
+
+ p = internal_property_create(buf, SCF_TYPE_ASTRING, 1, fname);
+
+ (void) internal_attach_property(pg, p);
+ }
+
+ /*
* Walk its child elements, as appropriate.
*/
for (cursor = svc->xmlChildrenNode; cursor != NULL;
@@ -3166,6 +3201,8 @@ lxml_get_bundle_file(bundle_t *bundle, const char *filename, svccfg_op_t op)
return (-1);
}
+ document->name = strdup(filename);
+
/*
* Verify that this is a document type we understand.
*/