6670426 lsvcrun barfs on rc scripts which remove themselves
authorVladimir Marek <Vladimir.Marek@Sun.COM>
Tue, 01 Jun 2010 16:51:51 +0200
changeset 12718 5d58bbec4ff6
parent 12717 1cb0b42b763e
child 12719 bd9fb35d09c2
6670426 lsvcrun barfs on rc scripts which remove themselves
usr/src/cmd/svc/lsvcrun/lsvcrun.c
--- a/usr/src/cmd/svc/lsvcrun/lsvcrun.c	Mon Jun 28 14:29:09 2010 -0700
+++ b/usr/src/cmd/svc/lsvcrun/lsvcrun.c	Tue Jun 01 16:51:51 2010 +0200
@@ -19,12 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * lsvcrun - run an rc?.d script, modifying appropriate data in the
  * repository to reflect legacy behavior.
@@ -38,6 +35,9 @@
  * inode, the inode of the script; and suffix, the suffix of the
  * script name, e.g. 'foo'.
  *
+ * In order to support rc scripts which delete themselves upon invocation we
+ * collect inode before running the script.
+ *
  * When we run a K script, we try to identify and remove the
  * property group by means of examining the inode and script
  * suffix.  The inode check means more than one script with the
@@ -501,9 +501,9 @@
 	char *svc_strbuf;
 	int err = 0;
 
-	do
+	do {
 		fd = open64(CTFS_ROOT "/process/template", O_RDWR);
-	while (fd < 0 && errno == EINTR);
+	} while (fd < 0 && errno == EINTR);
 	if (fd < 0) {
 		uu_warn(gettext("Can not create contract"));
 		return (-1);
@@ -700,14 +700,13 @@
 }
 
 static void
-set_legacy_service(scf_propertygroup_t *pg, const char *script)
+set_legacy_service(scf_propertygroup_t *pg, const char *script, ino_t inode)
 {
 	scf_handle_t *h;
 	const char *func;
 	char *suffix;
 	scf_transaction_t *tx;
 	struct timeval tstamp;
-	struct stat st;
 	ctid_t ctid;
 	char *svc_name = NULL;
 	int ret;
@@ -721,12 +720,6 @@
 	ret = gettimeofday(&tstamp, NULL);
 	assert(ret == 0);
 
-	if (stat(script, &st) != 0) {
-		uu_warn(gettext("Couldn't stat %s (%s).\n"), script,
-		    strerror(errno));
-		goto err;
-	}
-
 	if (errno = contract_latest(&ctid)) {
 		uu_warn(gettext("Could not get contract"));
 		goto err;
@@ -758,7 +751,7 @@
 		goto err;
 
 	if (add_new_property(h, tx, SCF_LEGACY_PROPERTY_INODE,
-	    SCF_TYPE_COUNT, (void *)st.st_ino) != 0)
+	    SCF_TYPE_COUNT, (void *)inode) != 0)
 		goto err;
 
 	if ((suffix = script_suffix(script)) != NULL) {
@@ -814,6 +807,7 @@
 	int pipefds[2];
 	char c;
 	int exitstatus;
+	struct stat st;
 
 	scf_propertygroup_t *pg;
 	boolean_t pg_ok;
@@ -893,6 +887,12 @@
 		    script);
 	(void) fflush(stdout);
 
+	if (stat(script, &st) != 0) {
+		uu_warn(gettext("Couldn't stat %s (%s).\n"), script,
+		    strerror(errno));
+		st.st_ino = (ino_t)0;
+	}
+
 	pid = fork();
 	if (pid < 0) {
 		uu_warn(gettext("Could not fork"));
@@ -975,7 +975,7 @@
 
 	if (pg != NULL) {
 		if (start_flag)
-			set_legacy_service(pg, script);
+			set_legacy_service(pg, script, st.st_ino);
 		else
 			cleanup_pg(pg);
 		scf_pg_destroy(pg);