changeset 4327:4ca5d5f63ada

6556719 sharemgr: sa_zfs_init() dumps core on failure 6558300 _zfs_init_libshare() performs insufficient error checking 6559698 sharemgr: sa_init() leaks SMF property
author dougm
date Fri, 25 May 2007 09:30:08 -0700
parents 3c27e4b80d13
children fe6ac87d8e60
files usr/src/lib/libshare/common/libshare.c usr/src/lib/libshare/common/libshare_zfs.c usr/src/lib/libzfs/common/libzfs_mount.c
diffstat 3 files changed, 1574 insertions(+), 1382 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libshare/common/libshare.c	Fri May 25 09:07:46 2007 -0700
+++ b/usr/src/lib/libshare/common/libshare.c	Fri May 25 09:30:08 2007 -0700
@@ -55,6 +55,7 @@
 					(tm.tv_nsec & 0xffffffff))
 
 #define	DFS_LOCK_FILE	"/etc/dfs/fstypes"
+#define	SA_STRSIZE	256	/* max string size for names */
 
 /*
  * internal data structures
@@ -74,7 +75,7 @@
 extern int sa_zfs_set_sharenfs(sa_group_t, char *, int);
 extern void update_legacy_config(sa_handle_t);
 extern int issubdir(char *, char *);
-extern void sa_zfs_init(sa_handle_impl_t);
+extern int sa_zfs_init(sa_handle_impl_t);
 extern void sa_zfs_fini(sa_handle_impl_t);
 extern void sablocksigs(sigset_t *);
 extern void saunblocksigs(sigset_t *);
@@ -93,6 +94,11 @@
 	sa_handle_impl_t	handle;
 };
 
+/* definitions used in a couple of property functions */
+#define	SA_PROP_OP_REMOVE	1
+#define	SA_PROP_OP_ADD		2
+#define	SA_PROP_OP_UPDATE	3
+
 static struct doc2handle *sa_global_handles = NULL;
 
 /* helper functions */
@@ -111,81 +117,81 @@
 
 	switch (err) {
 	case SA_OK:
-	    ret = dgettext(TEXT_DOMAIN, "ok");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "ok");
+		break;
 	case SA_NO_SUCH_PATH:
-	    ret = dgettext(TEXT_DOMAIN, "path doesn't exist");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "path doesn't exist");
+		break;
 	case SA_NO_MEMORY:
-	    ret = dgettext(TEXT_DOMAIN, "no memory");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "no memory");
+		break;
 	case SA_DUPLICATE_NAME:
-	    ret = dgettext(TEXT_DOMAIN, "name in use");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "name in use");
+		break;
 	case SA_BAD_PATH:
-	    ret = dgettext(TEXT_DOMAIN, "bad path");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "bad path");
+		break;
 	case SA_NO_SUCH_GROUP:
-	    ret = dgettext(TEXT_DOMAIN, "no such group");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "no such group");
+		break;
 	case SA_CONFIG_ERR:
-	    ret = dgettext(TEXT_DOMAIN, "configuration error");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "configuration error");
+		break;
 	case SA_SYSTEM_ERR:
-	    ret = dgettext(TEXT_DOMAIN, "system error");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "system error");
+		break;
 	case SA_SYNTAX_ERR:
-	    ret = dgettext(TEXT_DOMAIN, "syntax error");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "syntax error");
+		break;
 	case SA_NO_PERMISSION:
-	    ret = dgettext(TEXT_DOMAIN, "no permission");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "no permission");
+		break;
 	case SA_BUSY:
-	    ret = dgettext(TEXT_DOMAIN, "busy");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "busy");
+		break;
 	case SA_NO_SUCH_PROP:
-	    ret = dgettext(TEXT_DOMAIN, "no such property");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "no such property");
+		break;
 	case SA_INVALID_NAME:
-	    ret = dgettext(TEXT_DOMAIN, "invalid name");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "invalid name");
+		break;
 	case SA_INVALID_PROTOCOL:
-	    ret = dgettext(TEXT_DOMAIN, "invalid protocol");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "invalid protocol");
+		break;
 	case SA_NOT_ALLOWED:
-	    ret = dgettext(TEXT_DOMAIN, "operation not allowed");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "operation not allowed");
+		break;
 	case SA_BAD_VALUE:
-	    ret = dgettext(TEXT_DOMAIN, "bad property value");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "bad property value");
+		break;
 	case SA_INVALID_SECURITY:
-	    ret = dgettext(TEXT_DOMAIN, "invalid security type");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "invalid security type");
+		break;
 	case SA_NO_SUCH_SECURITY:
-	    ret = dgettext(TEXT_DOMAIN, "security type not found");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "security type not found");
+		break;
 	case SA_VALUE_CONFLICT:
-	    ret = dgettext(TEXT_DOMAIN, "property value conflict");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "property value conflict");
+		break;
 	case SA_NOT_IMPLEMENTED:
-	    ret = dgettext(TEXT_DOMAIN, "not implemented");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "not implemented");
+		break;
 	case SA_INVALID_PATH:
-	    ret = dgettext(TEXT_DOMAIN, "invalid path");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "invalid path");
+		break;
 	case SA_NOT_SUPPORTED:
-	    ret = dgettext(TEXT_DOMAIN, "operation not supported");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "operation not supported");
+		break;
 	case SA_PROP_SHARE_ONLY:
-	    ret = dgettext(TEXT_DOMAIN, "property not valid for group");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "property not valid for group");
+		break;
 	case SA_NOT_SHARED:
-	    ret = dgettext(TEXT_DOMAIN, "not shared");
-	    break;
+		ret = dgettext(TEXT_DOMAIN, "not shared");
+		break;
 	default:
-	    (void) snprintf(errstr, sizeof (errstr),
-				dgettext(TEXT_DOMAIN, "unknown %d"), err);
-	    ret = errstr;
+		(void) snprintf(errstr, sizeof (errstr),
+		    dgettext(TEXT_DOMAIN, "unknown %d"), err);
+		ret = errstr;
 	}
 	return (ret);
 }
@@ -204,12 +210,12 @@
 
 	(void) mutex_lock(&sa_global_lock);
 	for (item = sa_global_handles; item != NULL; item = item->next) {
-	    if (item->root == root)
-		break;
+		if (item->root == root)
+			break;
 	}
 	(void) mutex_unlock(&sa_global_lock);
 	if (item != NULL)
-	    return (item->handle);
+		return (item->handle);
 	return (NULL);
 }
 
@@ -221,13 +227,13 @@
 
 	item = (struct doc2handle *)calloc(sizeof (struct doc2handle), 1);
 	if (item != NULL) {
-	    item->root = root;
-	    item->handle = handle;
-	    (void) mutex_lock(&sa_global_lock);
-	    item->next = sa_global_handles;
-	    sa_global_handles = item;
-	    (void) mutex_unlock(&sa_global_lock);
-	    ret = SA_OK;
+		item->root = root;
+		item->handle = handle;
+		(void) mutex_lock(&sa_global_lock);
+		item->next = sa_global_handles;
+		sa_global_handles = item;
+		(void) mutex_unlock(&sa_global_lock);
+		ret = SA_OK;
 	}
 	return (ret);
 }
@@ -246,19 +252,18 @@
 
 	(void) mutex_lock(&sa_global_lock);
 	for (prev = NULL, item = sa_global_handles; item != NULL;
-		item = item->next) {
-	    if (item->root == root) {
-		if (prev == NULL) {
-		    /* first in the list */
-		    sa_global_handles = sa_global_handles->next;
-		} else {
-		    prev->next = item->next;
+	    item = item->next) {
+		if (item->root == root) {
+			/* first in the list */
+			if (prev == NULL)
+				sa_global_handles = sa_global_handles->next;
+			else
+				prev->next = item->next;
+			/* Item is out of the list so free the list structure */
+			free(item);
+			break;
 		}
-		/* Item is out of the list so free the list structure */
-		free(item);
-		break;
-	    }
-	    prev = item;
+		prev = item;
 	}
 	(void) mutex_unlock(&sa_global_lock);
 }
@@ -276,12 +281,12 @@
 	sa_handle_t handle;
 
 	while (node != NULL) {
-	    if (strcmp((char *)(node->name), "sharecfg") == 0) {
-		/* have the root so get the handle */
-		handle = (sa_handle_t)get_handle_for_root(node);
-		return (handle);
-	    }
-	    node = node->parent;
+		if (strcmp((char *)(node->name), "sharecfg") == 0) {
+			/* have the root so get the handle */
+			handle = (sa_handle_t)get_handle_for_root(node);
+			return (handle);
+		}
+		node = node->parent;
 	}
 	return (NULL);
 }
@@ -304,46 +309,49 @@
 	/* Have to have a handle or else we weren't initialized. */
 	handle = get_handle_for_root(root);
 	if (handle == NULL)
-	    return;
+		return;
 
 	for (node = root->xmlChildrenNode; node != NULL;
-		node = node->next) {
-	    if (xmlStrcmp(node->name, (xmlChar *)"legacy") == 0) {
-		/* a possible legacy node for this path */
-		lpath = xmlGetProp(node, (xmlChar *)"path");
-		if (lpath != NULL && xmlStrcmp(lpath, (xmlChar *)path) == 0) {
-		    xmlFree(lpath);
-		    break;
+	    node = node->next) {
+		if (xmlStrcmp(node->name, (xmlChar *)"legacy") == 0) {
+			/* a possible legacy node for this path */
+			lpath = xmlGetProp(node, (xmlChar *)"path");
+			if (lpath != NULL &&
+			    xmlStrcmp(lpath, (xmlChar *)path) == 0) {
+				xmlFree(lpath);
+				break;
+			}
+			if (lpath != NULL)
+				xmlFree(lpath);
 		}
-		if (lpath != NULL)
-		    xmlFree(lpath);
-	    }
 	}
 	if (node == NULL) {
-	    /* need to create the first legacy timestamp node */
-	    node = xmlNewChild(root, NULL, (xmlChar *)"legacy", NULL);
+		/* need to create the first legacy timestamp node */
+		node = xmlNewChild(root, NULL, (xmlChar *)"legacy", NULL);
 	}
 	if (node != NULL) {
-	    char tstring[32];
-	    int ret;
+		char tstring[32];
+		int ret;
 
-	    (void) snprintf(tstring, sizeof (tstring), "%lld", tval);
-	    xmlSetProp(node, (xmlChar *)"timestamp", (xmlChar *)tstring);
-	    xmlSetProp(node, (xmlChar *)"path", (xmlChar *)path);
-	    /* now commit to SMF */
-	    ret = sa_get_instance(handle->scfhandle, "default");
-	    if (ret == SA_OK) {
-		ret = sa_start_transaction(handle->scfhandle, "operation");
+		(void) snprintf(tstring, sizeof (tstring), "%lld", tval);
+		xmlSetProp(node, (xmlChar *)"timestamp", (xmlChar *)tstring);
+		xmlSetProp(node, (xmlChar *)"path", (xmlChar *)path);
+		/* now commit to SMF */
+		ret = sa_get_instance(handle->scfhandle, "default");
 		if (ret == SA_OK) {
-		    ret = sa_set_property(handle->scfhandle, "legacy-timestamp",
-					    tstring);
-		    if (ret == SA_OK) {
-			(void) sa_end_transaction(handle->scfhandle);
-		    } else {
-			sa_abort_transaction(handle->scfhandle);
-		    }
+			ret = sa_start_transaction(handle->scfhandle,
+			    "operation");
+			if (ret == SA_OK) {
+				ret = sa_set_property(handle->scfhandle,
+				    "legacy-timestamp", tstring);
+				if (ret == SA_OK) {
+					(void) sa_end_transaction(
+					    handle->scfhandle);
+				} else {
+					sa_abort_transaction(handle->scfhandle);
+				}
+			}
 		}
-	    }
 	}
 }
 
@@ -360,9 +368,9 @@
 
 	shared = sa_get_share_attr(share, "shared");
 	if (shared != NULL) {
-	    if (strcmp(shared, "true") == 0)
-		result = 1;
-	    sa_free_attr_string(shared);
+		if (strcmp(shared, "true") == 0)
+			result = 1;
+		sa_free_attr_string(shared);
 	}
 	return (result);
 }
@@ -395,10 +403,10 @@
 		 * could be considered incorrect.  We may tighten this
 		 * up in the future.
 		 */
-	    if (strictness == SA_CHECK_NORMAL && !is_shared(share))
-		continue;
+		if (strictness == SA_CHECK_NORMAL && !is_shared(share))
+			continue;
 
-	    path = sa_get_share_attr(share, "path");
+		path = sa_get_share_attr(share, "path");
 		/*
 		 * If path is NULL, then a share is in the process of
 		 * construction or someone has modified the property
@@ -407,18 +415,18 @@
 		 * implementation and does the difficult part of
 		 * checking subdirectories.
 		 */
-	    if (path == NULL)
-		continue;
-	    if (newpath != NULL &&
-		(strcmp(path, newpath) == 0 || issubdir(newpath, path) ||
-		issubdir(path, newpath))) {
+		if (path == NULL)
+			continue;
+		if (newpath != NULL &&
+		    (strcmp(path, newpath) == 0 || issubdir(newpath, path) ||
+		    issubdir(path, newpath))) {
+			sa_free_attr_string(path);
+			path = NULL;
+			issub = SA_INVALID_PATH;
+			break;
+		}
 		sa_free_attr_string(path);
 		path = NULL;
-		issub = SA_INVALID_PATH;
-		break;
-	    }
-	    sa_free_attr_string(path);
-	    path = NULL;
 	}
 	return (issub);
 }
@@ -442,20 +450,20 @@
 	char *path = NULL;
 
 	for (issub = 0, group = sa_get_group(handle, NULL);
-		group != NULL && !issub;
-		group = sa_get_next_group(group)) {
-	    if (sa_group_is_zfs(group)) {
-		sa_group_t subgroup;
-		for (subgroup = sa_get_sub_group(group);
-		    subgroup != NULL && !issub;
-		    subgroup = sa_get_next_group(subgroup))
-		    issub = checksubdirgroup(subgroup, newpath, strictness);
-	    } else {
-		issub = checksubdirgroup(group, newpath, strictness);
-	    }
+	    group != NULL && !issub; group = sa_get_next_group(group)) {
+		if (sa_group_is_zfs(group)) {
+			sa_group_t subgroup;
+			for (subgroup = sa_get_sub_group(group);
+			    subgroup != NULL && !issub;
+			    subgroup = sa_get_next_group(subgroup))
+				issub = checksubdirgroup(subgroup, newpath,
+				    strictness);
+		} else {
+			issub = checksubdirgroup(group, newpath, strictness);
+		}
 	}
 	if (path != NULL)
-	    sa_free_attr_string(path);
+		sa_free_attr_string(path);
 	return (issub);
 }
 
@@ -473,36 +481,36 @@
 	sa_share_t share;
 	char *fstype;
 
-	if (*path != '/') {
-	    return (SA_BAD_PATH);
-	}
+	if (*path != '/')
+		return (SA_BAD_PATH);
+
 	if (stat(path, &st) < 0) {
-	    error = SA_NO_SUCH_PATH;
+		error = SA_NO_SUCH_PATH;
 	} else {
-	    share = sa_find_share(handle, path);
-	    if (share != NULL) {
-		error = SA_DUPLICATE_NAME;
-	    }
-	    if (error == SA_OK) {
-		/*
-		 * check for special case with file system that might
-		 * have restrictions.  For now, ZFS is the only case
-		 * since it has its own idea of how to configure
-		 * shares. We do this before subdir checking since
-		 * things like ZFS will do that for us. This should
-		 * also be done via plugin interface.
-		 */
-		fstype = sa_fstype(path);
-		if (fstype != NULL && strcmp(fstype, "zfs") == 0) {
-		    if (sa_zfs_is_shared(handle, path))
-			error = SA_INVALID_NAME;
+		share = sa_find_share(handle, path);
+		if (share != NULL)
+			error = SA_DUPLICATE_NAME;
+
+		if (error == SA_OK) {
+			/*
+			 * check for special case with file system
+			 * that might have restrictions.  For now, ZFS
+			 * is the only case since it has its own idea
+			 * of how to configure shares. We do this
+			 * before subdir checking since things like
+			 * ZFS will do that for us. This should also
+			 * be done via plugin interface.
+			 */
+			fstype = sa_fstype(path);
+			if (fstype != NULL && strcmp(fstype, "zfs") == 0) {
+				if (sa_zfs_is_shared(handle, path))
+					error = SA_INVALID_NAME;
+			}
+			if (fstype != NULL)
+				sa_free_fstype(fstype);
 		}
-		if (fstype != NULL)
-		    sa_free_fstype(fstype);
-	    }
-	    if (error == SA_OK) {
-		error = checksubdir(handle, path, strictness);
-	    }
+		if (error == SA_OK)
+			error = checksubdir(handle, path, strictness);
 	}
 	return (error);
 }
@@ -518,9 +526,9 @@
 
 	type = sa_get_group_attr(group, "type");
 	if (type != NULL && strcmp(type, "transient") == 0)
-	    persist = 0;
+		persist = 0;
 	if (type != NULL)
-	    sa_free_attr_string(type);
+		sa_free_attr_string(type);
 	return (persist);
 }
 
@@ -541,18 +549,18 @@
 	ssize_t len;
 
 	if (name != NULL && isalpha(*name)) {
-	    char c;
-	    len = strlen(name);
-	    if (len < (scf_max_name_len - sizeof ("group:"))) {
-		for (c = *name++; c != '\0' && ret != 0; c = *name++) {
-		    if (!isalnum(c) && c != '-' && c != '_')
+		char c;
+		len = strlen(name);
+		if (len < (scf_max_name_len - sizeof ("group:"))) {
+			for (c = *name++; c != '\0' && ret != 0; c = *name++) {
+				if (!isalnum(c) && c != '-' && c != '_')
+					ret = 0;
+			}
+		} else {
 			ret = 0;
 		}
-	    } else {
+	} else {
 		ret = 0;
-	    }
-	} else {
-	    ret = 0;
 	}
 	return (ret);
 }
@@ -569,15 +577,14 @@
 	xmlNodePtr parent;
 	xmlChar *zfs;
 
-	if (strcmp((char *)((xmlNodePtr)group)->name, "share") == 0) {
-	    parent = (xmlNodePtr)sa_get_parent_group(group);
-	} else {
-	    parent = (xmlNodePtr)group;
-	}
+	if (strcmp((char *)((xmlNodePtr)group)->name, "share") == 0)
+		parent = (xmlNodePtr)sa_get_parent_group(group);
+	else
+		parent = (xmlNodePtr)group;
 	zfs = xmlGetProp(parent, (xmlChar *)"zfs");
 	if (zfs != NULL) {
-	    xmlFree(zfs);
-	    ret = 1;
+		xmlFree(zfs);
+		ret = 1;
 	}
 	return (ret);
 }
@@ -600,13 +607,13 @@
 	char *proto;
 
 	if (id == NULL)
-	    id = "optionset";
+		id = "optionset";
 
 	proto = sa_get_optionset_attr(optionset, "type");
 	len = snprintf(oname, len, "%s_%s", id, proto ? proto : "default");
 
 	if (proto != NULL)
-	    sa_free_attr_string(proto);
+		sa_free_attr_string(proto);
 	return (len);
 }
 
@@ -630,21 +637,41 @@
 	char *sectype;
 
 	if (id == NULL)
-	    id = "optionset";
+		id = "optionset";
 
 	proto = sa_get_security_attr(security, "type");
 	sectype = sa_get_security_attr(security, "sectype");
-	len = snprintf(oname, len, "%s_%s_%s", id,
-			    proto ? proto : "default",
-			    sectype ? sectype : "default");
+	len = snprintf(oname, len, "%s_%s_%s", id, proto ? proto : "default",
+	    sectype ? sectype : "default");
 	if (proto != NULL)
-	    sa_free_attr_string(proto);
+		sa_free_attr_string(proto);
 	if (sectype != NULL)
-	    sa_free_attr_string(sectype);
+		sa_free_attr_string(sectype);
 	return (len);
 }
 
 /*
+ * verifydefgroupopts(handle)
+ *
+ * Make sure a "default" group exists and has default protocols enabled.
+ */
+static void
+verifydefgroupopts(sa_handle_t handle)
+{
+	sa_group_t defgrp;
+	sa_optionset_t opt;
+	defgrp = sa_get_group(handle, "default");
+	if (defgrp != NULL) {
+		opt = sa_get_optionset(defgrp, NULL);
+		/*
+		 * NFS is the default for default group
+		 */
+		if (opt == NULL)
+			opt = sa_create_optionset(defgrp, "nfs");
+	}
+}
+
+/*
  * sa_init(init_service)
  *	Initialize the API
  *	find all the shared objects
@@ -652,6 +679,10 @@
  *	read in the current configuration
  */
 
+#define	GETPROP(prop)	scf_simple_prop_next_astring(prop)
+#define	CHECKTSTAMP(st, tval)	stat(SA_LEGACY_DFSTAB, &st) >= 0 && \
+	tval != TSTAMP(st.st_ctim)
+
 sa_handle_t
 sa_init(int init_service)
 {
@@ -668,144 +699,153 @@
 	handle = calloc(sizeof (struct sa_handle_impl), 1);
 
 	if (handle != NULL) {
-	    /* get protocol specific structures */
-	    (void) proto_plugin_init();
-	    if (init_service & SA_INIT_SHARE_API) {
-		/*
-		 * initialize access into libzfs. We use this when
-		 * collecting info about ZFS datasets and shares.
-		 */
-		sa_zfs_init(handle);
-		/*
-		 * since we want to use SMF, initialize an svc handle
-		 * and find out what is there.
-		 */
-		handle->scfhandle = sa_scf_init(handle);
-		if (handle->scfhandle != NULL) {
+		/* get protocol specific structures */
+		(void) proto_plugin_init();
+		if (init_service & SA_INIT_SHARE_API) {
 			/*
-			 * Need to lock the extraction of the
-			 * configuration if the dfstab file has
-			 * changed. Lock everything now and release if
-			 * not needed.  Use a file that isn't being
-			 * manipulated by other parts of the system in
-			 * order to not interfere with locking. Using
-			 * dfstab doesn't work.
+			 * initialize access into libzfs. We use this
+			 * when collecting info about ZFS datasets and
+			 * shares.
 			 */
-		    sablocksigs(&old);
-		    lockfd = open(DFS_LOCK_FILE, O_RDWR);
-		    if (lockfd >= 0) {
-			extern int errno;
-			errno = 0;
-			(void) lockf(lockfd, F_LOCK, 0);
+			if (sa_zfs_init(handle) == B_FALSE) {
+				free(handle);
+				(void) proto_plugin_fini();
+				return (NULL);
+			}
 			/*
-			 * Check whether we are going to need to merge
-			 * any dfstab changes. This is done by
-			 * comparing the value of legacy-timestamp
-			 * with the current st_ctim of the file. If
-			 * they are different, an update is needed and
-			 * the file must remain locked until the merge
-			 * is done in order to prevent multiple
-			 * startups from changing the SMF repository
-			 * at the same time.  The first to get the
-			 * lock will make any changes before the
-			 * others can read the repository.
+			 * since we want to use SMF, initialize an svc handle
+			 * and find out what is there.
 			 */
-			prop = scf_simple_prop_get(handle->scfhandle->handle,
-						(const char *)
-						    SA_SVC_FMRI_BASE ":default",
-						"operation",
-						"legacy-timestamp");
-			if (prop != NULL) {
-			    char *i64;
-			    i64 = scf_simple_prop_next_astring(prop);
-			    if (i64 != NULL) {
-				tval = strtoull(i64, NULL, 0);
-			    }
-			    if (stat(SA_LEGACY_DFSTAB, &st) >= 0 &&
-				tval != TSTAMP(st.st_ctim)) {
-				updatelegacy = B_TRUE;
-			    }
-			} else {
-			    /* We haven't set the timestamp before so do it. */
-			    updatelegacy = B_TRUE;
-			}
-		    }
-		    if (updatelegacy == B_FALSE) {
-			/* Don't need the lock anymore */
-			(void) lockf(lockfd, F_ULOCK, 0);
-			(void) close(lockfd);
-		    }
+			handle->scfhandle = sa_scf_init(handle);
+			if (handle->scfhandle != NULL) {
+				/*
+				 * Need to lock the extraction of the
+				 * configuration if the dfstab file has
+				 * changed. Lock everything now and release if
+				 * not needed.  Use a file that isn't being
+				 * manipulated by other parts of the system in
+				 * order to not interfere with locking. Using
+				 * dfstab doesn't work.
+				 */
+				sablocksigs(&old);
+				lockfd = open(DFS_LOCK_FILE, O_RDWR);
+				if (lockfd >= 0) {
+					extern int errno;
+					errno = 0;
+					(void) lockf(lockfd, F_LOCK, 0);
+					/*
+					 * Check whether we are going to need
+					 * to merge any dfstab changes. This
+					 * is done by comparing the value of
+					 * legacy-timestamp with the current
+					 * st_ctim of the file. If they are
+					 * different, an update is needed and
+					 * the file must remain locked until
+					 * the merge is done in order to
+					 * prevent multiple startups from
+					 * changing the SMF repository at the
+					 * same time.  The first to get the
+					 * lock will make any changes before
+					 * the others can read the repository.
+					 */
+					prop = scf_simple_prop_get
+					    (handle->scfhandle->handle,
+					    (const char *)SA_SVC_FMRI_BASE
+					    ":default", "operation",
+					    "legacy-timestamp");
+					if (prop != NULL) {
+						char *i64;
+						i64 = GETPROP(prop);
+						if (i64 != NULL)
+							tval = strtoull(i64,
+							    NULL, 0);
+						if (CHECKTSTAMP(st, tval))
+							updatelegacy = B_TRUE;
+						scf_simple_prop_free(prop);
+					} else {
+						/*
+						 * We haven't set the
+						 * timestamp before so do it.
+						 */
+						updatelegacy = B_TRUE;
+					}
+				}
+				if (updatelegacy == B_FALSE) {
+					/* Don't need the lock anymore */
+					(void) lockf(lockfd, F_ULOCK, 0);
+					(void) close(lockfd);
+				}
 
-		/*
-		 * It is essential that the document tree and
-		 * the internal list of roots to handles be
-		 * setup before anything that might try to
-		 * create a new object is called. The document
-		 * tree is the combination of handle->doc and
-		 * handle->tree. This allows searches,
-		 * etc. when all you have is an object in the
-		 * tree.
-		 */
-		    handle->doc = xmlNewDoc((xmlChar *)"1.0");
-		    handle->tree = xmlNewNode(NULL, (xmlChar *)"sharecfg");
-		    if (handle->doc != NULL && handle->tree != NULL) {
-			xmlDocSetRootElement(handle->doc, handle->tree);
-			err = add_handle_for_root(handle->tree, handle);
-			if (err == SA_OK)
-			    err = sa_get_config(handle->scfhandle,
+				/*
+				 * It is essential that the document tree and
+				 * the internal list of roots to handles be
+				 * setup before anything that might try to
+				 * create a new object is called. The document
+				 * tree is the combination of handle->doc and
+				 * handle->tree. This allows searches,
+				 * etc. when all you have is an object in the
+				 * tree.
+				 */
+				handle->doc = xmlNewDoc((xmlChar *)"1.0");
+				handle->tree = xmlNewNode(NULL,
+				    (xmlChar *)"sharecfg");
+				if (handle->doc != NULL &&
+				    handle->tree != NULL) {
+					xmlDocSetRootElement(handle->doc,
+					    handle->tree);
+					err = add_handle_for_root(handle->tree,
+					    handle);
+					if (err == SA_OK)
+						err = sa_get_config(
+						    handle->scfhandle,
 						    handle->tree, handle);
-		    } else {
-			if (handle->doc != NULL)
-			    xmlFreeDoc(handle->doc);
-			if (handle->tree != NULL)
-			    xmlFreeNode(handle->tree);
-			err = SA_NO_MEMORY;
-		    }
+				} else {
+					if (handle->doc != NULL)
+						xmlFreeDoc(handle->doc);
+					if (handle->tree != NULL)
+						xmlFreeNode(handle->tree);
+					err = SA_NO_MEMORY;
+				}
 
-		    saunblocksigs(&old);
+				saunblocksigs(&old);
 
-		    if (err != SA_OK) {
-			/*
-			 * If we couldn't add the tree handle
-			 * to the list, then things are going
-			 * to fail badly. Might as well undo
-			 * everything now and fail the
-			 * sa_init().
-			 */
-			sa_fini(handle);
-			return (NULL);
-		    }
+				if (err != SA_OK) {
+					/*
+					 * If we couldn't add the tree handle
+					 * to the list, then things are going
+					 * to fail badly. Might as well undo
+					 * everything now and fail the
+					 * sa_init().
+					 */
+					sa_fini(handle);
+					return (NULL);
+				}
 
-		    if (tval == 0) {
-			/* first time so make sure default is setup */
-			sa_group_t defgrp;
-			sa_optionset_t opt;
-			defgrp = sa_get_group(handle, "default");
-			if (defgrp != NULL) {
-			    opt = sa_get_optionset(defgrp, NULL);
-			    if (opt == NULL)
-				/* NFS is the default for default */
-				opt = sa_create_optionset(defgrp, "nfs");
-			}
-		    }
+				if (tval == 0) {
+					/*
+					 * first time so make sure
+					 * default is setup
+					 */
+					verifydefgroupopts(handle);
+				}
 
-		    if (updatelegacy == B_TRUE) {
-			sablocksigs(&old);
-			getlegacyconfig((sa_handle_t)handle,
-					    SA_LEGACY_DFSTAB, &handle->tree);
-			if (stat(SA_LEGACY_DFSTAB, &st) >= 0)
-			    set_legacy_timestamp(handle->tree,
-						SA_LEGACY_DFSTAB,
-						TSTAMP(st.st_ctim));
-			saunblocksigs(&old);
-			/* Safe to unlock now to allow others to run */
-			(void) lockf(lockfd, F_ULOCK, 0);
-			(void) close(lockfd);
-		    }
-		    legacy |= sa_get_zfs_shares(handle, "zfs");
-		    legacy |= gettransients(handle, &handle->tree);
+			if (updatelegacy == B_TRUE) {
+				sablocksigs(&old);
+				getlegacyconfig((sa_handle_t)handle,
+				    SA_LEGACY_DFSTAB, &handle->tree);
+				if (stat(SA_LEGACY_DFSTAB, &st) >= 0)
+					set_legacy_timestamp(handle->tree,
+					    SA_LEGACY_DFSTAB,
+					    TSTAMP(st.st_ctim));
+				saunblocksigs(&old);
+				/* Safe to unlock now to allow others to run */
+				(void) lockf(lockfd, F_ULOCK, 0);
+				(void) close(lockfd);
+			}
+			legacy |= sa_get_zfs_shares(handle, "zfs");
+			legacy |= gettransients(handle, &handle->tree);
 		}
-	    }
+		}
 	}
 	return ((sa_handle_t)handle);
 }
@@ -842,7 +882,7 @@
 		 * plugins that were loaded.
 		 */
 		if (sa_global_handles == NULL)
-		    (void) proto_plugin_fini();
+			(void) proto_plugin_fini();
 
 	}
 }
@@ -863,23 +903,24 @@
 	int numproto = -1;
 
 	if (protocols != NULL) {
-	    struct sa_proto_plugin *plug;
-	    for (numproto = 0, plug = sap_proto_list; plug != NULL;
-		plug = plug->plugin_next) {
-		numproto++;
-	    }
+		struct sa_proto_plugin *plug;
+		for (numproto = 0, plug = sap_proto_list; plug != NULL;
+		    plug = plug->plugin_next) {
+			numproto++;
+		}
 
-	    *protocols = calloc(numproto + 1,  sizeof (char *));
-	    if (*protocols != NULL) {
-		int ret = 0;
-		for (plug = sap_proto_list; plug != NULL;
-		    plug = plug->plugin_next) {
-		    /* faking for now */
-		    (*protocols)[ret++] = plug->plugin_ops->sa_protocol;
+		*protocols = calloc(numproto + 1,  sizeof (char *));
+		if (*protocols != NULL) {
+			int ret = 0;
+			for (plug = sap_proto_list; plug != NULL;
+			    plug = plug->plugin_next) {
+				/* faking for now */
+				(*protocols)[ret++] =
+				    plug->plugin_ops->sa_protocol;
+			}
+		} else {
+			numproto = -1;
 		}
-	    } else {
-		numproto = -1;
-	    }
 	}
 	return (numproto);
 }
@@ -899,23 +940,21 @@
 
 	for (node = node->xmlChildrenNode; node != NULL;
 	    node = node->next) {
-	    if (xmlStrcmp(node->name, (xmlChar *)"group") == 0) {
-		/* if no groupname, return the first found */
-		if (group == NULL)
-		    break;
-		name = xmlGetProp(node, (xmlChar *)"name");
-		if (name != NULL &&
-		    xmlStrcmp(name, group) == 0) {
-		    break;
+		if (xmlStrcmp(node->name, (xmlChar *)"group") == 0) {
+			/* if no groupname, return the first found */
+			if (group == NULL)
+				break;
+			name = xmlGetProp(node, (xmlChar *)"name");
+			if (name != NULL && xmlStrcmp(name, group) == 0)
+				break;
+			if (name != NULL) {
+				xmlFree(name);
+				name = NULL;
+			}
 		}
-		if (name != NULL) {
-		    xmlFree(name);
-		    name = NULL;
-		}
-	    }
 	}
 	if (name != NULL)
-	    xmlFree(name);
+		xmlFree(name);
 	return (node);
 }
 
@@ -933,22 +972,21 @@
 	sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle;
 
 	if (impl_handle != NULL && impl_handle->tree != NULL) {
-	    if (groupname != NULL) {
-		group = strdup(groupname);
-		subgroup = strchr(group, '/');
-		if (subgroup != NULL)
-		    *subgroup++ = '\0';
-	    }
-	    node = find_group_by_name(impl_handle->tree, (xmlChar *)group);
-	    /* if a subgroup, find it before returning */
-	    if (subgroup != NULL && node != NULL) {
-		node = find_group_by_name(node, (xmlChar *)subgroup);
-	    }
+		if (groupname != NULL) {
+			group = strdup(groupname);
+			subgroup = strchr(group, '/');
+			if (subgroup != NULL)
+				*subgroup++ = '\0';
+		}
+		node = find_group_by_name(impl_handle->tree, (xmlChar *)group);
+		/* if a subgroup, find it before returning */
+		if (subgroup != NULL && node != NULL)
+			node = find_group_by_name(node, (xmlChar *)subgroup);
 	}
 	if (node != NULL && (char *)group != NULL)
-	    (void) sa_get_instance(impl_handle->scfhandle, (char *)group);
+		(void) sa_get_instance(impl_handle->scfhandle, (char *)group);
 	if (group != NULL)
-	    free(group);
+		free(group);
 	return ((sa_group_t)(node));
 }
 
@@ -962,11 +1000,11 @@
 {
 	xmlNodePtr ngroup = NULL;
 	if (group != NULL) {
-	    for (ngroup = ((xmlNodePtr)group)->next; ngroup != NULL;
+		for (ngroup = ((xmlNodePtr)group)->next; ngroup != NULL;
 		    ngroup = ngroup->next) {
-		if (xmlStrcmp(ngroup->name, (xmlChar *)"group") == 0)
-		    break;
-	    }
+			if (xmlStrcmp(ngroup->name, (xmlChar *)"group") == 0)
+				break;
+		}
 	}
 	return ((sa_group_t)ngroup);
 }
@@ -988,23 +1026,25 @@
 	 * services.
 	 */
 	if (group != NULL) {
-	    for (node = ((xmlNodePtr)group)->children; node != NULL;
+		for (node = ((xmlNodePtr)group)->children; node != NULL;
 		    node = node->next) {
-		if (xmlStrcmp(node->name, (xmlChar *)"share") == 0) {
-			if (sharepath == NULL) {
-				break;
-			} else {
-				/* is it the correct share? */
-			    path = xmlGetProp(node, (xmlChar *)"path");
-			    if (path != NULL &&
-				xmlStrcmp(path, (xmlChar *)sharepath) == 0) {
-				xmlFree(path);
-				break;
-			    }
-			    xmlFree(path);
+			if (xmlStrcmp(node->name, (xmlChar *)"share") == 0) {
+				if (sharepath == NULL) {
+					break;
+				} else {
+					/* is it the correct share? */
+					path = xmlGetProp(node,
+					    (xmlChar *)"path");
+					if (path != NULL &&
+					    xmlStrcmp(path,
+					    (xmlChar *)sharepath) == 0) {
+						xmlFree(path);
+						break;
+					}
+					xmlFree(path);
+				}
 			}
 		}
-	    }
 	}
 	return ((sa_share_t)node);
 }
@@ -1022,12 +1062,12 @@
 	xmlNodePtr node = NULL;
 
 	if (share != NULL) {
-	    for (node = ((xmlNodePtr)share)->next; node != NULL;
+		for (node = ((xmlNodePtr)share)->next; node != NULL;
 		    node = node->next) {
-		if (xmlStrcmp(node->name, (xmlChar *)"share") == 0) {
-			break;
+			if (xmlStrcmp(node->name, (xmlChar *)"share") == 0) {
+				break;
+			}
 		}
-	    }
 	}
 	return ((sa_share_t)node);
 }
@@ -1045,8 +1085,8 @@
 	xmlNodePtr child;
 	for (child = node->xmlChildrenNode; child != NULL;
 	    child = child->next)
-	    if (xmlStrcmp(child->name, type) == 0)
-		return (child);
+		if (xmlStrcmp(child->name, type) == 0)
+			return (child);
 	return ((xmlNodePtr)NULL);
 }
 
@@ -1065,13 +1105,13 @@
 
 	for (share = sa_get_share(group, NULL); share != NULL;
 	    share = sa_get_next_share(share)) {
-	    path = sa_get_share_attr(share, "path");
-	    if (path != NULL && strcmp(path, sharepath) == 0) {
-		sa_free_attr_string(path);
-		break;
-	    }
-	    if (path != NULL)
-		sa_free_attr_string(path);
+		path = sa_get_share_attr(share, "path");
+		if (path != NULL && strcmp(path, sharepath) == 0) {
+			sa_free_attr_string(path);
+			break;
+		}
+		if (path != NULL)
+			sa_free_attr_string(path);
 	}
 	return (share);
 }
@@ -1088,7 +1128,7 @@
 sa_get_sub_group(sa_group_t group)
 {
 	return ((sa_group_t)_sa_get_child_node((xmlNodePtr)group,
-					    (xmlChar *)"group"));
+	    (xmlChar *)"group"));
 }
 
 /*
@@ -1108,20 +1148,22 @@
 	int done = 0;
 
 	for (group = sa_get_group(handle, NULL); group != NULL && !done;
-		group = sa_get_next_group(group)) {
-	    if (is_zfs_group(group)) {
-		for (zgroup = (sa_group_t)_sa_get_child_node((xmlNodePtr)group,
-							(xmlChar *)"group");
-		    zgroup != NULL; zgroup = sa_get_next_group(zgroup)) {
-		    share = find_share(zgroup, sharepath);
-		    if (share != NULL)
+	    group = sa_get_next_group(group)) {
+		if (is_zfs_group(group)) {
+			for (zgroup =
+			    (sa_group_t)_sa_get_child_node((xmlNodePtr)group,
+			    (xmlChar *)"group");
+			    zgroup != NULL;
+			    zgroup = sa_get_next_group(zgroup)) {
+				share = find_share(zgroup, sharepath);
+				if (share != NULL)
+					break;
+			}
+		} else {
+			share = find_share(group, sharepath);
+		}
+		if (share != NULL)
 			break;
-		}
-	    } else {
-		share = find_share(group, sharepath);
-	    }
-	    if (share != NULL)
-		break;
 	}
 	return (share);
 }
@@ -1164,49 +1206,53 @@
 
 	err  = SA_OK; /* assume success */
 
-	node = xmlNewChild((xmlNodePtr)group, NULL,
-				(xmlChar *)"share", NULL);
+	node = xmlNewChild((xmlNodePtr)group, NULL, (xmlChar *)"share", NULL);
 	if (node != NULL) {
-	    xmlSetProp(node, (xmlChar *)"path", (xmlChar *)sharepath);
-	    xmlSetProp(node, (xmlChar *)"type", persist ?
-			(xmlChar *)"persist" : (xmlChar *)"transient");
-	    if (persist != SA_SHARE_TRANSIENT) {
-		/*
-		 * persistent shares come in two flavors: SMF and
-		 * ZFS. Sort this one out based on target group and
-		 * path type. Currently, only NFS is supported in the
-		 * ZFS group and it is always on.
-		 */
-		if (sa_group_is_zfs(group) && sa_path_is_zfs(sharepath)) {
-		    err = sa_zfs_set_sharenfs(group, sharepath, 1);
-		} else {
-		    sa_handle_impl_t impl_handle;
-		    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-		    if (impl_handle != NULL)
-			err = sa_commit_share(impl_handle->scfhandle, group,
-						(sa_share_t)node);
-		    else
-			err = SA_SYSTEM_ERR;
+		xmlSetProp(node, (xmlChar *)"path", (xmlChar *)sharepath);
+		xmlSetProp(node, (xmlChar *)"type",
+		    persist ? (xmlChar *)"persist" : (xmlChar *)"transient");
+		if (persist != SA_SHARE_TRANSIENT) {
+			/*
+			 * persistent shares come in two flavors: SMF and
+			 * ZFS. Sort this one out based on target group and
+			 * path type. Currently, only NFS is supported in the
+			 * ZFS group and it is always on.
+			 */
+			if (sa_group_is_zfs(group) &&
+			    sa_path_is_zfs(sharepath)) {
+				err = sa_zfs_set_sharenfs(group, sharepath, 1);
+			} else {
+				sa_handle_impl_t impl_handle;
+				impl_handle =
+				    (sa_handle_impl_t)sa_find_group_handle(
+				    group);
+				if (impl_handle != NULL) {
+					err = sa_commit_share(
+					    impl_handle->scfhandle, group,
+					    (sa_share_t)node);
+				} else {
+					err = SA_SYSTEM_ERR;
+				}
+			}
 		}
-	    }
-	    if (err == SA_NO_PERMISSION && persist & SA_SHARE_PARSER) {
-		/* called by the dfstab parser so could be a show */
-		err = SA_OK;
-	    }
-	    if (err != SA_OK) {
-		/*
-		 * we couldn't commit to the repository so undo
-		 * our internal state to reflect reality.
-		 */
-		xmlUnlinkNode(node);
-		xmlFreeNode(node);
-		node = NULL;
-	    }
+		if (err == SA_NO_PERMISSION && persist & SA_SHARE_PARSER) {
+			/* called by the dfstab parser so could be a show */
+			err = SA_OK;
+		}
+		if (err != SA_OK) {
+			/*
+			 * we couldn't commit to the repository so undo
+			 * our internal state to reflect reality.
+			 */
+			xmlUnlinkNode(node);
+			xmlFreeNode(node);
+			node = NULL;
+		}
 	} else {
-	    err = SA_NO_MEMORY;
+		err = SA_NO_MEMORY;
 	}
 	if (error != NULL)
-	    *error = err;
+		*error = err;
 	return (node);
 }
 
@@ -1238,17 +1284,16 @@
 	 * it as an override.
 	 */
 	if (persist & SA_SHARE_PARSER || persist == SA_SHARE_PERMANENT)
-	    strictness = SA_CHECK_STRICT;
+		strictness = SA_CHECK_STRICT;
 
 	handle = sa_find_group_handle(group);
 
 	if ((dup = sa_find_share(handle, sharepath)) == NULL &&
-		(*error = sa_check_path(group, sharepath, strictness)) ==
-			SA_OK) {
-	    node = _sa_add_share(group, sharepath, persist, error);
+	    (*error = sa_check_path(group, sharepath, strictness)) == SA_OK) {
+		node = _sa_add_share(group, sharepath, persist, error);
 	}
 	if (dup != NULL)
-	    *error = SA_DUPLICATE_NAME;
+		*error = SA_DUPLICATE_NAME;
 
 	return ((sa_share_t)node);
 }
@@ -1267,22 +1312,26 @@
 
 	sharepath = sa_get_share_attr(share, "path");
 	if (stat(sharepath, &st) < 0) {
-	    err = SA_NO_SUCH_PATH;
+		err = SA_NO_SUCH_PATH;
 	} else {
-	    /* tell the server about the share */
-	    if (protocol != NULL) {
-		/* lookup protocol specific handler */
-		err = sa_proto_share(protocol, share);
-		if (err == SA_OK)
-		    (void) sa_set_share_attr(share, "shared", "true");
-	    } else {
-		/* tell all protocols */
-		err = sa_proto_share("nfs", share); /* only NFS for now */
-		(void) sa_set_share_attr(share, "shared", "true");
-	    }
+		/* tell the server about the share */
+		if (protocol != NULL) {
+			/* lookup protocol specific handler */
+			err = sa_proto_share(protocol, share);
+			if (err == SA_OK)
+				(void) sa_set_share_attr(share, "shared",
+				    "true");
+		} else {
+			/*
+			 * Tell all protocols.  Only NFS for now but
+			 * SMB is coming.
+			 */
+			err = sa_proto_share("nfs", share);
+			(void) sa_set_share_attr(share, "shared", "true");
+		}
 	}
 	if (sharepath != NULL)
-	    sa_free_attr_string(sharepath);
+		sa_free_attr_string(sharepath);
 	return (err);
 }
 
@@ -1302,17 +1351,17 @@
 	shared = sa_get_share_attr(share, "shared");
 
 	if (protocol != NULL) {
-	    ret = sa_proto_unshare(protocol, path);
+		ret = sa_proto_unshare(protocol, path);
 	} else {
-	    /* need to do all protocols */
-	    ret = sa_proto_unshare("nfs", path);
+		/* need to do all protocols */
+		ret = sa_proto_unshare("nfs", path);
 	}
 	if (ret == SA_OK)
 		(void) sa_set_share_attr(share, "shared", NULL);
 	if (path != NULL)
-	    sa_free_attr_string(path);
+		sa_free_attr_string(path);
 	if (shared != NULL)
-	    sa_free_attr_string(shared);
+		sa_free_attr_string(shared);
 	return (ret);
 }
 
@@ -1338,9 +1387,9 @@
 	zfs = sa_get_group_attr(group, "zfs");
 	groupname = sa_get_group_attr(group, "name");
 	if (type != NULL && strcmp(type, "persist") != 0)
-	    transient = 1;
+		transient = 1;
 	if (type != NULL)
-	    sa_free_attr_string(type);
+		sa_free_attr_string(type);
 
 	/* remove the node from its group then free the memory */
 
@@ -1349,30 +1398,35 @@
 	 */
 	/* only do SMF action if permanent */
 	if (!transient || zfs != NULL) {
-	    /* remove from legacy dfstab as well as possible SMF */
-	    ret = sa_delete_legacy(share);
-	    if (ret == SA_OK) {
-		if (!sa_group_is_zfs(group)) {
-		    sa_handle_impl_t impl_handle;
-		    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-		    if (impl_handle != NULL)
-			ret = sa_delete_share(impl_handle->scfhandle,
-						group, share);
-		    else
-			ret = SA_SYSTEM_ERR;
-		} else {
-		    char *sharepath = sa_get_share_attr(share, "path");
-		    if (sharepath != NULL) {
-			ret = sa_zfs_set_sharenfs(group, sharepath, 0);
-			sa_free_attr_string(sharepath);
-		    }
+		/* remove from legacy dfstab as well as possible SMF */
+		ret = sa_delete_legacy(share);
+		if (ret == SA_OK) {
+			if (!sa_group_is_zfs(group)) {
+				sa_handle_impl_t impl_handle;
+				impl_handle = (sa_handle_impl_t)
+				    sa_find_group_handle(group);
+				if (impl_handle != NULL) {
+					ret = sa_delete_share(
+					    impl_handle->scfhandle, group,
+					    share);
+				} else {
+					ret = SA_SYSTEM_ERR;
+				}
+			} else {
+				char *sharepath = sa_get_share_attr(share,
+				    "path");
+				if (sharepath != NULL) {
+					ret = sa_zfs_set_sharenfs(group,
+					    sharepath, 0);
+					sa_free_attr_string(sharepath);
+				}
+			}
 		}
-	    }
 	}
 	if (groupname != NULL)
-	    sa_free_attr_string(groupname);
+		sa_free_attr_string(groupname);
 	if (zfs != NULL)
-	    sa_free_attr_string(zfs);
+		sa_free_attr_string(zfs);
 
 	xmlUnlinkNode((xmlNodePtr)share);
 	xmlFreeNode((xmlNodePtr)share);
@@ -1396,25 +1450,30 @@
 
 	oldgroup = sa_get_parent_group(share);
 	if (oldgroup != group) {
-	    sa_handle_impl_t impl_handle;
-	    xmlUnlinkNode((xmlNodePtr)share);
-	    /* now that the share isn't in its old group, add to the new one */
-	    xmlAddChild((xmlNodePtr)group, (xmlNodePtr)share);
-	    /* need to deal with SMF */
-	    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-	    if (impl_handle != NULL) {
+		sa_handle_impl_t impl_handle;
+		xmlUnlinkNode((xmlNodePtr)share);
 		/*
-		 * need to remove from old group first and then add to
-		 * new group. Ideally, we would do the other order but
-		 * need to avoid having the share in two groups at the
-		 * same time.
+		 * now that the share isn't in its old group, add to
+		 * the new one
 		 */
-		ret = sa_delete_share(impl_handle->scfhandle, oldgroup, share);
-		if (ret == SA_OK)
-		    ret = sa_commit_share(impl_handle->scfhandle, group, share);
-	    } else {
-		ret = SA_SYSTEM_ERR;
-	    }
+		xmlAddChild((xmlNodePtr)group, (xmlNodePtr)share);
+		/* need to deal with SMF */
+		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
+		if (impl_handle != NULL) {
+			/*
+			 * need to remove from old group first and then add to
+			 * new group. Ideally, we would do the other order but
+			 * need to avoid having the share in two groups at the
+			 * same time.
+			 */
+			ret = sa_delete_share(impl_handle->scfhandle, oldgroup,
+			    share);
+			if (ret == SA_OK)
+				ret = sa_commit_share(impl_handle->scfhandle,
+				    group, share);
+		} else {
+			ret = SA_SYSTEM_ERR;
+		}
 	}
 	return (ret);
 }
@@ -1431,15 +1490,15 @@
 {
 	xmlNodePtr node = NULL;
 	if (share != NULL) {
-	    node = ((xmlNodePtr)share)->parent;
+		node = ((xmlNodePtr)share)->parent;
 		/*
 		 * make sure parent is a group and not sharecfg since
 		 * we may be cheating and passing in a group.
 		 * Eventually, groups of groups might come into being.
 		 */
-	    if (node == NULL ||
-		xmlStrcmp(node->name, (xmlChar *)"sharecfg") == 0)
-		node = NULL;
+		if (node == NULL ||
+		    xmlStrcmp(node->name, (xmlChar *)"sharecfg") == 0)
+			node = NULL;
 	}
 	return ((sa_group_t)node);
 }
@@ -1457,12 +1516,14 @@
 	xmlNodePtr node = NULL;
 
 	if (sa_valid_group_name(groupname)) {
-	    node = xmlNewChild(impl_handle->tree, NULL,
-				(xmlChar *)"group", NULL);
-	    if (node != NULL) {
-		xmlSetProp(node, (xmlChar *)"name", (xmlChar *)groupname);
-		xmlSetProp(node, (xmlChar *)"state", (xmlChar *)"enabled");
-	    }
+		node = xmlNewChild(impl_handle->tree, NULL, (xmlChar *)"group",
+		    NULL);
+		if (node != NULL) {
+			xmlSetProp(node, (xmlChar *)"name",
+			    (xmlChar *)groupname);
+			xmlSetProp(node, (xmlChar *)"state",
+			    (xmlChar *)"enabled");
+		}
 	}
 	return ((sa_group_t)node);
 }
@@ -1479,8 +1540,7 @@
 {
 	xmlNodePtr node = NULL;
 
-	node = xmlNewChild((xmlNodePtr)group, NULL,
-				(xmlChar *)"group", NULL);
+	node = xmlNewChild((xmlNodePtr)group, NULL, (xmlChar *)"group", NULL);
 	if (node != NULL) {
 		xmlSetProp(node, (xmlChar *)"name", (xmlChar *)groupname);
 		xmlSetProp(node, (xmlChar *)"state", (xmlChar *)"enabled");
@@ -1504,84 +1564,99 @@
 	xmlNodePtr node = NULL;
 	sa_group_t group;
 	int ret;
-	char rbacstr[256];
+	char rbacstr[SA_STRSIZE];
 	sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle;
 
 	ret = SA_OK;
 
 	if (impl_handle == NULL || impl_handle->scfhandle == NULL) {
-	    ret = SA_SYSTEM_ERR;
-	    goto err;
+		ret = SA_SYSTEM_ERR;
+		goto err;
 	}
 
 	group = sa_get_group(handle, groupname);
 	if (group != NULL) {
-	    ret = SA_DUPLICATE_NAME;
+		ret = SA_DUPLICATE_NAME;
 	} else {
-	    if (sa_valid_group_name(groupname)) {
-		node = xmlNewChild(impl_handle->tree, NULL,
-				    (xmlChar *)"group", NULL);
-		if (node != NULL) {
-		    xmlSetProp(node, (xmlChar *)"name", (xmlChar *)groupname);
-		    /* default to the group being enabled */
-		    xmlSetProp(node, (xmlChar *)"state", (xmlChar *)"enabled");
-		    ret = sa_create_instance(impl_handle->scfhandle, groupname);
-		    if (ret == SA_OK) {
-			ret = sa_start_transaction(impl_handle->scfhandle,
-							"operation");
-		    }
-		    if (ret == SA_OK) {
-			ret = sa_set_property(impl_handle->scfhandle,
-						"state", "enabled");
-			if (ret == SA_OK) {
-			    ret = sa_end_transaction(impl_handle->scfhandle);
-			} else {
-			    sa_abort_transaction(impl_handle->scfhandle);
-			}
-		    }
-		    if (ret == SA_OK) {
-			/* initialize the RBAC strings */
-			ret = sa_start_transaction(impl_handle->scfhandle,
-							"general");
-			if (ret == SA_OK) {
-			    (void) snprintf(rbacstr, sizeof (rbacstr), "%s.%s",
-					SA_RBAC_MANAGE, groupname);
-			    ret = sa_set_property(impl_handle->scfhandle,
+		if (sa_valid_group_name(groupname)) {
+			node = xmlNewChild(impl_handle->tree, NULL,
+			    (xmlChar *)"group", NULL);
+			if (node != NULL) {
+				xmlSetProp(node, (xmlChar *)"name",
+				    (xmlChar *)groupname);
+				/* default to the group being enabled */
+				xmlSetProp(node, (xmlChar *)"state",
+				    (xmlChar *)"enabled");
+				ret = sa_create_instance(impl_handle->scfhandle,
+				    groupname);
+				if (ret == SA_OK) {
+					ret = sa_start_transaction(
+					    impl_handle->scfhandle,
+					    "operation");
+				}
+				if (ret == SA_OK) {
+					ret = sa_set_property(
+					    impl_handle->scfhandle,
+					    "state", "enabled");
+					if (ret == SA_OK) {
+						ret = sa_end_transaction(
+						    impl_handle->scfhandle);
+					} else {
+						sa_abort_transaction(
+						    impl_handle->scfhandle);
+					}
+				}
+				if (ret == SA_OK) {
+					/* initialize the RBAC strings */
+					ret = sa_start_transaction(
+					    impl_handle->scfhandle,
+					    "general");
+					if (ret == SA_OK) {
+						(void) snprintf(rbacstr,
+						    sizeof (rbacstr), "%s.%s",
+						    SA_RBAC_MANAGE, groupname);
+						ret = sa_set_property(
+						    impl_handle->scfhandle,
 						    "action_authorization",
 						    rbacstr);
-			}
-			if (ret == SA_OK) {
-			    (void) snprintf(rbacstr, sizeof (rbacstr), "%s.%s",
-					SA_RBAC_VALUE, groupname);
-			    ret = sa_set_property(impl_handle->scfhandle,
+					}
+					if (ret == SA_OK) {
+						(void) snprintf(rbacstr,
+						    sizeof (rbacstr), "%s.%s",
+						    SA_RBAC_VALUE, groupname);
+						ret = sa_set_property(
+						    impl_handle->scfhandle,
 						    "value_authorization",
 						    rbacstr);
-			}
-			if (ret == SA_OK) {
-			    ret = sa_end_transaction(impl_handle->scfhandle);
+					}
+					if (ret == SA_OK) {
+						ret = sa_end_transaction(
+						    impl_handle->scfhandle);
+					} else {
+						sa_abort_transaction(
+						    impl_handle->scfhandle);
+					}
+				}
+				if (ret != SA_OK) {
+					/*
+					 * Couldn't commit the group
+					 * so we need to undo
+					 * internally.
+					 */
+					xmlUnlinkNode(node);
+					xmlFreeNode(node);
+					node = NULL;
+				}
 			} else {
-			    sa_abort_transaction(impl_handle->scfhandle);
+				ret = SA_NO_MEMORY;
 			}
-		    }
-		    if (ret != SA_OK) {
-			/*
-			 * Couldn't commit the group so we need to
-			 * undo internally.
-			 */
-			xmlUnlinkNode(node);
-			xmlFreeNode(node);
-			node = NULL;
-		    }
 		} else {
-		    ret = SA_NO_MEMORY;
+			ret = SA_INVALID_NAME;
 		}
-	    } else {
-		ret = SA_INVALID_NAME;
-	    }
 	}
 err:
 	if (error != NULL)
-	    *error = ret;
+		*error = ret;
 	return ((sa_group_t)node);
 }
 
@@ -1601,15 +1676,15 @@
 
 	impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
 	if (impl_handle != NULL) {
-	    name = sa_get_group_attr(group, "name");
-	    if (name != NULL) {
-		ret = sa_delete_instance(impl_handle->scfhandle, name);
-		sa_free_attr_string(name);
-	    }
-	    xmlUnlinkNode((xmlNodePtr)group); /* make sure unlinked */
-	    xmlFreeNode((xmlNodePtr)group);   /* now it is gone */
+		name = sa_get_group_attr(group, "name");
+		if (name != NULL) {
+			ret = sa_delete_instance(impl_handle->scfhandle, name);
+			sa_free_attr_string(name);
+		}
+		xmlUnlinkNode((xmlNodePtr)group); /* make sure unlinked */
+		xmlFreeNode((xmlNodePtr)group);   /* now it is gone */
 	} else {
-	    ret = SA_SYSTEM_ERR;
+		ret = SA_SYSTEM_ERR;
 	}
 	return (ret);
 }
@@ -1647,9 +1722,8 @@
 	xmlNodePtr node = (xmlNodePtr)nodehdl;
 	xmlChar *name = NULL;
 
-	if (node != NULL) {
+	if (node != NULL)
 		name = xmlGetProp(node, (xmlChar *)tag);
-	}
 	return ((char *)name);
 }
 
@@ -1666,11 +1740,10 @@
 {
 	xmlNodePtr node = (xmlNodePtr)nodehdl;
 	if (node != NULL && tag != NULL) {
-		if (value != NULL) {
+		if (value != NULL)
 			xmlSetProp(node, (xmlChar *)tag, (xmlChar *)value);
-		} else {
+		else
 			xmlUnsetProp(node, (xmlChar *)tag);
-		}
 	}
 }
 
@@ -1705,24 +1778,27 @@
 
 	impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
 	if (impl_handle != NULL) {
-	    groupname = sa_get_group_attr(group, "name");
-	    ret = sa_get_instance(impl_handle->scfhandle, groupname);
-	    if (ret == SA_OK) {
-		set_node_attr((void *)group, tag, value);
-		ret = sa_start_transaction(impl_handle->scfhandle, "operation");
+		groupname = sa_get_group_attr(group, "name");
+		ret = sa_get_instance(impl_handle->scfhandle, groupname);
 		if (ret == SA_OK) {
-		    ret = sa_set_property(impl_handle->scfhandle, tag, value);
-		    if (ret == SA_OK)
-			(void) sa_end_transaction(impl_handle->scfhandle);
-		    else {
-			sa_abort_transaction(impl_handle->scfhandle);
-		    }
+			set_node_attr((void *)group, tag, value);
+			ret = sa_start_transaction(impl_handle->scfhandle,
+			    "operation");
+			if (ret == SA_OK) {
+				ret = sa_set_property(impl_handle->scfhandle,
+				    tag, value);
+				if (ret == SA_OK)
+					(void) sa_end_transaction(
+					    impl_handle->scfhandle);
+				else
+					sa_abort_transaction(
+					    impl_handle->scfhandle);
+			}
 		}
-	    }
-	    if (groupname != NULL)
-		sa_free_attr_string(groupname);
+		if (groupname != NULL)
+			sa_free_attr_string(groupname);
 	} else {
-	    ret = SA_SYSTEM_ERR;
+		ret = SA_SYSTEM_ERR;
 	}
 	return (ret);
 }
@@ -1757,18 +1833,18 @@
 	char *name = NULL;
 
 	if (resource != NULL) {
-	    for (share = sa_get_share(group, NULL); share != NULL;
-		share = sa_get_next_share(share)) {
-		name = sa_get_share_attr(share, "resource");
-		if (name != NULL) {
-		    if (strcmp(name, resource) == 0)
-			break;
-		    sa_free_attr_string(name);
-		    name = NULL;
+		for (share = sa_get_share(group, NULL); share != NULL;
+		    share = sa_get_next_share(share)) {
+			name = sa_get_share_attr(share, "resource");
+			if (name != NULL) {
+				if (strcmp(name, resource) == 0)
+					break;
+				sa_free_attr_string(name);
+				name = NULL;
+			}
 		}
-	    }
-	    if (name != NULL)
-		sa_free_attr_string(name);
+		if (name != NULL)
+			sa_free_attr_string(name);
 	}
 	return ((sa_share_t)share);
 }
@@ -1784,8 +1860,8 @@
 _sa_set_share_description(sa_share_t share, char *content)
 {
 	xmlNodePtr node;
-	node = xmlNewChild((xmlNodePtr)share,
-			    NULL, (xmlChar *)"description", NULL);
+	node = xmlNewChild((xmlNodePtr)share, NULL, (xmlChar *)"description",
+	    NULL);
 	xmlNodeSetContent(node, (xmlChar *)content);
 	return (node);
 }
@@ -1816,28 +1892,32 @@
 	 */
 
 	if (strcmp(tag, "resource") == 0) {
-	    resource = sa_get_resource(group, value);
-	    if (resource != share && resource != NULL)
-		ret = SA_DUPLICATE_NAME;
+		resource = sa_get_resource(group, value);
+		if (resource != share && resource != NULL)
+			ret = SA_DUPLICATE_NAME;
 	}
 	if (ret == SA_OK) {
-	    set_node_attr((void *)share, tag, value);
-	    if (group != NULL) {
-		char *type;
-		/* we can probably optimize this some */
-		type = sa_get_share_attr(share, "type");
-		if (type == NULL || strcmp(type, "transient") != 0) {
-		    sa_handle_impl_t impl_handle;
-		    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-		    if (impl_handle != NULL)
-			ret = sa_commit_share(impl_handle->scfhandle,
-						group, share);
-		    else
-			ret = SA_SYSTEM_ERR;
+		set_node_attr((void *)share, tag, value);
+		if (group != NULL) {
+			char *type;
+			/* we can probably optimize this some */
+			type = sa_get_share_attr(share, "type");
+			if (type == NULL || strcmp(type, "transient") != 0) {
+				sa_handle_impl_t impl_handle;
+				impl_handle =
+				    (sa_handle_impl_t)sa_find_group_handle(
+				    group);
+				if (impl_handle != NULL) {
+					ret = sa_commit_share(
+					    impl_handle->scfhandle, group,
+					    share);
+				} else {
+					ret = SA_SYSTEM_ERR;
+				}
+			}
+			if (type != NULL)
+				sa_free_attr_string(type);
 		}
-		if (type != NULL)
-		    sa_free_attr_string(type);
-	    }
 	}
 	return (ret);
 }
@@ -1909,25 +1989,25 @@
 	xmlChar *value = NULL;
 
 	for (node = ((xmlNodePtr)group)->children; node != NULL;
-		node = node->next) {
+	    node = node->next) {
 		if (xmlStrcmp(node->name, (xmlChar *)"optionset") == 0) {
-		    value = xmlGetProp(node, (xmlChar *)"type");
-		    if (proto != NULL) {
-			if (value != NULL &&
-			    xmlStrcmp(value, (xmlChar *)proto) == 0) {
-			    break;
+			value = xmlGetProp(node, (xmlChar *)"type");
+			if (proto != NULL) {
+				if (value != NULL &&
+				    xmlStrcmp(value, (xmlChar *)proto) == 0) {
+					break;
+				}
+				if (value != NULL) {
+					xmlFree(value);
+					value = NULL;
+				}
+			} else {
+				break;
 			}
-			if (value != NULL) {
-			    xmlFree(value);
-			    value = NULL;
-			}
-		    } else {
-			break;
-		    }
 		}
 	}
 	if (value != NULL)
-	    xmlFree(value);
+		xmlFree(value);
 	return ((sa_optionset_t)node);
 }
 
@@ -1943,7 +2023,7 @@
 	xmlNodePtr node;
 
 	for (node = ((xmlNodePtr)optionset)->next; node != NULL;
-		node = node->next) {
+	    node = node->next) {
 		if (xmlStrcmp(node->name, (xmlChar *)"optionset") == 0) {
 			break;
 		}
@@ -1967,41 +2047,41 @@
 	xmlChar *value = NULL;
 
 	for (node = ((xmlNodePtr)group)->children; node != NULL;
-		node = node->next) {
-	    if (xmlStrcmp(node->name, (xmlChar *)"security") == 0) {
-		if (proto != NULL) {
-		    value = xmlGetProp(node, (xmlChar *)"type");
-		    if (value == NULL ||
-			(value != NULL &&
-			xmlStrcmp(value, (xmlChar *)proto) != 0)) {
-			/* it doesn't match so continue */
-			xmlFree(value);
-			value = NULL;
-			continue;
-		    }
+	    node = node->next) {
+		if (xmlStrcmp(node->name, (xmlChar *)"security") == 0) {
+			if (proto != NULL) {
+				value = xmlGetProp(node, (xmlChar *)"type");
+				if (value == NULL ||
+				    (value != NULL &&
+				    xmlStrcmp(value, (xmlChar *)proto) != 0)) {
+					/* it doesn't match so continue */
+					xmlFree(value);
+					value = NULL;
+					continue;
+				}
+			}
+			if (value != NULL) {
+				xmlFree(value);
+				value = NULL;
+			}
+			/* potential match */
+			if (sectype != NULL) {
+				value = xmlGetProp(node, (xmlChar *)"sectype");
+				if (value != NULL &&
+				    xmlStrcmp(value, (xmlChar *)sectype) == 0) {
+					break;
+				}
+			} else {
+				break;
+			}
 		}
 		if (value != NULL) {
-		    xmlFree(value);
-		    value = NULL;
+			xmlFree(value);
+			value = NULL;
 		}
-		/* potential match */
-		if (sectype != NULL) {
-		    value = xmlGetProp(node, (xmlChar *)"sectype");
-		    if (value != NULL &&
-			xmlStrcmp(value, (xmlChar *)sectype) == 0) {
-			break;
-		    }
-		} else {
-		    break;
-		}
-	    }
-	    if (value != NULL) {
-		xmlFree(value);
-		value = NULL;
-	    }
 	}
 	if (value != NULL)
-	    xmlFree(value);
+		xmlFree(value);
 	return ((sa_security_t)node);
 }
 
@@ -2017,7 +2097,7 @@
 	xmlNodePtr node;
 
 	for (node = ((xmlNodePtr)security)->next; node != NULL;
-		node = node->next) {
+	    node = node->next) {
 		if (xmlStrcmp(node->name, (xmlChar *)"security") == 0) {
 			break;
 		}
@@ -2039,28 +2119,32 @@
 	xmlChar *value = NULL;
 
 	if (optionset == NULL)
-	    return (NULL);
+		return (NULL);
 
 	for (node = node->children; node != NULL;
-		node = node->next) {
-	    if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
-		if (prop == NULL)
-		    break;
-		value = xmlGetProp(node, (xmlChar *)"type");
-		if (value != NULL && xmlStrcmp(value, (xmlChar *)prop) == 0) {
-		    break;
+	    node = node->next) {
+		if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
+			if (prop == NULL)
+				break;
+			value = xmlGetProp(node, (xmlChar *)"type");
+			if (value != NULL &&
+			    xmlStrcmp(value, (xmlChar *)prop) == 0) {
+				break;
+			}
+			if (value != NULL) {
+				xmlFree(value);
+				value = NULL;
+			}
 		}
-		if (value != NULL) {
-		    xmlFree(value);
-		    value = NULL;
-		}
-	    }
 	}
 	if (value != NULL)
 		xmlFree(value);
 	if (node != NULL && xmlStrcmp(node->name, (xmlChar *)"option") != 0) {
-	    /* avoid a non option node -- it is possible to be a text node */
-	    node = NULL;
+		/*
+		 * avoid a non option node -- it is possible to be a
+		 * text node
+		 */
+		node = NULL;
 	}
 	return ((sa_property_t)node);
 }
@@ -2078,7 +2162,7 @@
 	xmlNodePtr node;
 
 	for (node = ((xmlNodePtr)property)->next; node != NULL;
-		node = node->next) {
+	    node = node->next) {
 		if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
 			break;
 		}
@@ -2100,7 +2184,7 @@
 	int ret = SA_OK;
 
 	for (node = ((xmlNodePtr)share)->children; node != NULL;
-		node = node->next) {
+	    node = node->next) {
 		if (xmlStrcmp(node->name, (xmlChar *)"description") == 0) {
 			break;
 		}
@@ -2109,7 +2193,7 @@
 	/* no existing description but want to add */
 	if (node == NULL && content != NULL) {
 		/* add a description */
-	    node = _sa_set_share_description(share, content);
+		node = _sa_set_share_description(share, content);
 	} else if (node != NULL && content != NULL) {
 		/* update a description */
 		xmlNodeSetContent(node, (xmlChar *)content);
@@ -2119,12 +2203,14 @@
 		xmlFreeNode(node);
 	}
 	if (group != NULL && is_persistent((sa_group_t)share)) {
-	    sa_handle_impl_t impl_handle;
-	    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-	    if (impl_handle != NULL)
-		ret = sa_commit_share(impl_handle->scfhandle, group, share);
-	    else
-		ret = SA_SYSTEM_ERR;
+		sa_handle_impl_t impl_handle;
+		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
+		if (impl_handle != NULL) {
+			ret = sa_commit_share(impl_handle->scfhandle, group,
+			    share);
+		} else {
+			ret = SA_SYSTEM_ERR;
+		}
 	}
 	return (ret);
 }
@@ -2140,10 +2226,10 @@
 {
 	int c;
 	for (c = *str; c != '\0'; c = *++str) {
-	    if (c == '\t' || c == '\n')
-		*str = ' ';
-	    else if (c == '"')
-		*str = '\'';
+		if (c == '\t' || c == '\n')
+			*str = ' ';
+		else if (c == '"')
+			*str = '\'';
 	}
 }
 
@@ -2161,14 +2247,14 @@
 	xmlNodePtr node;
 
 	for (node = ((xmlNodePtr)share)->children; node != NULL;
-		node = node->next) {
-	    if (xmlStrcmp(node->name, (xmlChar *)"description") == 0) {
-		break;
-	    }
+	    node = node->next) {
+		if (xmlStrcmp(node->name, (xmlChar *)"description") == 0) {
+			break;
+		}
 	}
 	if (node != NULL) {
-	    description = xmlNodeGetContent((xmlNodePtr)share);
-	    fixproblemchars((char *)description);
+		description = xmlNodeGetContent((xmlNodePtr)share);
+		fixproblemchars((char *)description);
 	}
 	return ((char *)description);
 }
@@ -2201,47 +2287,48 @@
 	optionset = sa_get_optionset(group, proto);
 	if (optionset != NULL) {
 		/* can't have a duplicate protocol */
-	    optionset = NULL;
+		optionset = NULL;
 	} else {
-	    optionset = (sa_optionset_t)xmlNewChild((xmlNodePtr)group,
-						    NULL,
-						    (xmlChar *)"optionset",
-						    NULL);
+		optionset = (sa_optionset_t)xmlNewChild((xmlNodePtr)group,
+		    NULL, (xmlChar *)"optionset", NULL);
 		/*
 		 * only put to repository if on a group and we were
 		 * able to create an optionset.
 		 */
-	    if (optionset != NULL) {
-		char oname[256];
-		char *groupname;
-		char *id = NULL;
+		if (optionset != NULL) {
+			char oname[SA_STRSIZE];
+			char *groupname;
+			char *id = NULL;
+
+			if (sa_is_share(group))
+				parent = sa_get_parent_group((sa_share_t)group);
+
+			sa_set_optionset_attr(optionset, "type", proto);
 
-		if (sa_is_share(group))
-		    parent = sa_get_parent_group((sa_share_t)group);
-
-		sa_set_optionset_attr(optionset, "type", proto);
-
-		if (sa_is_share(group)) {
-			id = sa_get_share_attr((sa_share_t)group, "id");
+			if (sa_is_share(group)) {
+				id = sa_get_share_attr((sa_share_t)group, "id");
+			}
+			(void) sa_optionset_name(optionset, oname,
+			    sizeof (oname), id);
+			groupname = sa_get_group_attr(parent, "name");
+			if (groupname != NULL && is_persistent(group)) {
+				sa_handle_impl_t impl_handle;
+				impl_handle = (sa_handle_impl_t)
+				    sa_find_group_handle(group);
+				assert(impl_handle != NULL);
+				if (impl_handle != NULL) {
+					(void) sa_get_instance(
+					    impl_handle->scfhandle,
+					    groupname);
+					(void) sa_create_pgroup(
+					    impl_handle->scfhandle, oname);
+				}
+			}
+			if (groupname != NULL)
+				sa_free_attr_string(groupname);
+			if (id != NULL)
+				sa_free_attr_string(id);
 		}
-		(void) sa_optionset_name(optionset, oname,
-					sizeof (oname), id);
-		groupname = sa_get_group_attr(parent, "name");
-		if (groupname != NULL && is_persistent(group)) {
-		    sa_handle_impl_t impl_handle;
-		    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-		    assert(impl_handle != NULL);
-		    if (impl_handle != NULL) {
-			(void) sa_get_instance(impl_handle->scfhandle,
-						groupname);
-			(void) sa_create_pgroup(impl_handle->scfhandle, oname);
-		    }
-		}
-		if (groupname != NULL)
-		    sa_free_attr_string(groupname);
-		if (id != NULL)
-		    sa_free_attr_string(id);
-	    }
 	}
 	return (optionset);
 }
@@ -2258,9 +2345,8 @@
 {
 	xmlNodePtr node = NULL;
 
-	if (property != NULL) {
-	    node = ((xmlNodePtr)property)->parent;
-	}
+	if (property != NULL)
+		node = ((xmlNodePtr)property)->parent;
 	return ((sa_optionset_t)node);
 }
 
@@ -2276,9 +2362,8 @@
 {
 	xmlNodePtr node = NULL;
 
-	if (optionset != NULL) {
-	    node = ((xmlNodePtr)optionset)->parent;
-	}
+	if (optionset != NULL)
+		node = ((xmlNodePtr)optionset)->parent;
 	return ((sa_group_t)node);
 }
 
@@ -2300,7 +2385,7 @@
 
 	attr = sa_get_share_attr(share, "changed");
 	if (attr != NULL) {
-	    sa_free_attr_string(attr);
+		sa_free_attr_string(attr);
 		result = 1;
 	}
 	set_node_attr((void *)share, "changed", NULL);
@@ -2338,28 +2423,30 @@
 
 	group = sa_get_optionset_parent(optionset);
 	if (group != NULL && (sa_is_share(group) || is_zfs_group(group))) {
-	    /* only update ZFS if on a share */
-	    parent = sa_get_parent_group(group);
-	    zfs++;
-	    if (parent != NULL && is_zfs_group(parent)) {
-		needsupdate = zfs_needs_update(group);
-	    } else {
-		zfs = 0;
-	    }
+		/* only update ZFS if on a share */
+		parent = sa_get_parent_group(group);
+		zfs++;
+		if (parent != NULL && is_zfs_group(parent))
+			needsupdate = zfs_needs_update(group);
+		else
+			zfs = 0;
 	}
 	if (zfs) {
-	    if (!clear && needsupdate)
-		ret = sa_zfs_update((sa_share_t)group);
+		if (!clear && needsupdate)
+			ret = sa_zfs_update((sa_share_t)group);
 	} else {
-	    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-	    if (impl_handle != NULL) {
-		if (clear)
-		    (void) sa_abort_transaction(impl_handle->scfhandle);
-		else
-		    ret = sa_end_transaction(impl_handle->scfhandle);
-	    } else {
-		ret = SA_SYSTEM_ERR;
-	    }
+		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
+		if (impl_handle != NULL) {
+			if (clear) {
+				(void) sa_abort_transaction(
+				    impl_handle->scfhandle);
+			} else {
+				ret = sa_end_transaction(
+				    impl_handle->scfhandle);
+			}
+		} else {
+			ret = SA_SYSTEM_ERR;
+		}
 	}
 	return (ret);
 }
@@ -2374,7 +2461,7 @@
 int
 sa_destroy_optionset(sa_optionset_t optionset)
 {
-	char name[256];
+	char name[SA_STRSIZE];
 	int len;
 	int ret;
 	char *id = NULL;
@@ -2384,25 +2471,26 @@
 	/* now delete the prop group */
 	group = sa_get_optionset_parent(optionset);
 	if (group != NULL && sa_is_share(group)) {
-	    ispersist = is_persistent(group);
-	    id = sa_get_share_attr((sa_share_t)group, "id");
+		ispersist = is_persistent(group);
+		id = sa_get_share_attr((sa_share_t)group, "id");
 	}
 	if (ispersist) {
-	    sa_handle_impl_t impl_handle;
-	    len = sa_optionset_name(optionset, name, sizeof (name), id);
-	    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-	    if (impl_handle != NULL) {
-		if (len > 0) {
-		    ret = sa_delete_pgroup(impl_handle->scfhandle, name);
+		sa_handle_impl_t impl_handle;
+		len = sa_optionset_name(optionset, name, sizeof (name), id);
+		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
+		if (impl_handle != NULL) {
+			if (len > 0) {
+				ret = sa_delete_pgroup(impl_handle->scfhandle,
+				    name);
+			}
+		} else {
+			ret = SA_SYSTEM_ERR;
 		}
-	    } else {
-		ret = SA_SYSTEM_ERR;
-	    }
 	}
 	xmlUnlinkNode((xmlNodePtr)optionset);
 	xmlFreeNode((xmlNodePtr)optionset);
 	if (id != NULL)
-	    sa_free_attr_string(id);
+		sa_free_attr_string(id);
 	return (ret);
 }
 
@@ -2433,12 +2521,12 @@
 	char *groupname = NULL;
 
 	if (group != NULL && sa_is_share(group)) {
-	    id = sa_get_share_attr((sa_share_t)group, "id");
-	    parent = sa_get_parent_group(group);
-	    if (parent != NULL)
-		groupname = sa_get_group_attr(parent, "name");
+		id = sa_get_share_attr((sa_share_t)group, "id");
+		parent = sa_get_parent_group(group);
+		if (parent != NULL)
+			groupname = sa_get_group_attr(parent, "name");
 	} else if (group != NULL) {
-	    groupname = sa_get_group_attr(group, "name");
+		groupname = sa_get_group_attr(group, "name");
 	}
 
 	security = sa_get_security(group, sectype, proto);
@@ -2447,31 +2535,30 @@
 		security = NULL;
 	} else {
 		security = (sa_security_t)xmlNewChild((xmlNodePtr)group,
-							NULL,
-							(xmlChar *)"security",
-							NULL);
+		    NULL, (xmlChar *)"security", NULL);
 		if (security != NULL) {
-			char oname[256];
+			char oname[SA_STRSIZE];
 			sa_set_security_attr(security, "type", proto);
 
 			sa_set_security_attr(security, "sectype", sectype);
 			(void) sa_security_name(security, oname,
-						sizeof (oname), id);
+			    sizeof (oname), id);
 			if (groupname != NULL && is_persistent(group)) {
-			    sa_handle_impl_t impl_handle;
-			    impl_handle =
-				(sa_handle_impl_t)sa_find_group_handle(group);
-			    if (impl_handle != NULL) {
-				(void) sa_get_instance(impl_handle->scfhandle,
-							groupname);
-				(void) sa_create_pgroup(impl_handle->scfhandle,
-							oname);
-			    }
+				sa_handle_impl_t impl_handle;
+				impl_handle =
+				    (sa_handle_impl_t)sa_find_group_handle(
+				    group);
+				if (impl_handle != NULL) {
+					(void) sa_get_instance(
+					    impl_handle->scfhandle, groupname);
+					(void) sa_create_pgroup(
+					    impl_handle->scfhandle, oname);
+				}
 			}
 		}
 	}
 	if (groupname != NULL)
-	    sa_free_attr_string(groupname);
+		sa_free_attr_string(groupname);
 	return (security);
 }
 
@@ -2485,7 +2572,7 @@
 int
 sa_destroy_security(sa_security_t security)
 {
-	char name[256];
+	char name[SA_STRSIZE];
 	int len;
 	int ret = SA_OK;
 	char *id = NULL;
@@ -2496,32 +2583,33 @@
 	group = sa_get_optionset_parent(security);
 
 	if (group != NULL)
-	    iszfs = sa_group_is_zfs(group);
+		iszfs = sa_group_is_zfs(group);
 
 	if (group != NULL && !iszfs) {
-	    if (sa_is_share(group))
-		ispersist = is_persistent(group);
-	    id = sa_get_share_attr((sa_share_t)group, "id");
+		if (sa_is_share(group))
+			ispersist = is_persistent(group);
+		id = sa_get_share_attr((sa_share_t)group, "id");
 	}
 	if (ispersist) {
-	    len = sa_security_name(security, name, sizeof (name), id);
-	    if (!iszfs && len > 0) {
-		sa_handle_impl_t impl_handle;
-		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-		if (impl_handle != NULL) {
-		    ret = sa_delete_pgroup(impl_handle->scfhandle, name);
-		} else {
-		    ret = SA_SYSTEM_ERR;
+		len = sa_security_name(security, name, sizeof (name), id);
+		if (!iszfs && len > 0) {
+			sa_handle_impl_t impl_handle;
+			impl_handle =
+			    (sa_handle_impl_t)sa_find_group_handle(group);
+			if (impl_handle != NULL) {
+				ret = sa_delete_pgroup(impl_handle->scfhandle,
+				    name);
+			} else {
+				ret = SA_SYSTEM_ERR;
+			}
 		}
-	    }
 	}
 	xmlUnlinkNode((xmlNodePtr)security);
 	xmlFreeNode((xmlNodePtr)security);
-	if (iszfs) {
-	    ret = sa_zfs_update(group);
-	}
+	if (iszfs)
+		ret = sa_zfs_update(group);
 	if (id != NULL)
-	    sa_free_attr_string(id);
+		sa_free_attr_string(id);
 	return (ret);
 }
 
@@ -2562,6 +2650,40 @@
 	return (strcmp((char *)((xmlNodePtr)node)->name, type) == 0);
 }
 
+
+/*
+ * add_or_update()
+ *
+ * Add or update a property. Pulled out of sa_set_prop_by_prop for
+ * readability.
+ */
+static int
+add_or_update(scfutilhandle_t *scf_handle, int type, scf_value_t *value,
+    scf_transaction_entry_t *entry, char *name, char *valstr)
+{
+	int ret = SA_SYSTEM_ERR;
+
+	if (value != NULL) {
+		if (type == SA_PROP_OP_ADD)
+			ret = scf_transaction_property_new(scf_handle->trans,
+			    entry, name, SCF_TYPE_ASTRING);
+		else
+			ret = scf_transaction_property_change(scf_handle->trans,
+			    entry, name, SCF_TYPE_ASTRING);
+		if (ret == 0) {
+			ret = scf_value_set_astring(value, valstr);
+			if (ret == 0)
+				ret = scf_entry_add_value(entry, value);
+			if (ret == 0)
+				return (ret);
+			scf_value_destroy(value);
+		} else {
+			scf_entry_destroy(entry);
+		}
+	}
+	return (SA_SYSTEM_ERR);
+}
+
 /*
  * sa_set_prop_by_prop(optionset, group, prop, type)
  *
@@ -2571,9 +2693,6 @@
  * marked as needing an update)
  */
 
-#define	SA_PROP_OP_REMOVE	1
-#define	SA_PROP_OP_ADD		2
-#define	SA_PROP_OP_UPDATE	3
 static int
 sa_set_prop_by_prop(sa_optionset_t optionset, sa_group_t group,
 			sa_property_t prop, int type)
@@ -2596,12 +2715,11 @@
 		 * if the group/share is not persistent we don't need
 		 * to do anything here
 		 */
-	    return (SA_OK);
+		return (SA_OK);
 	}
 	impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-	if (impl_handle == NULL || impl_handle->scfhandle == NULL) {
-	    return (SA_SYSTEM_ERR);
-	}
+	if (impl_handle == NULL || impl_handle->scfhandle == NULL)
+		return (SA_SYSTEM_ERR);
 	scf_handle = impl_handle->scfhandle;
 	name = sa_get_property_attr(prop, "type");
 	valstr = sa_get_property_attr(prop, "value");
@@ -2609,97 +2727,78 @@
 	opttype = is_nodetype((void *)optionset, "optionset");
 
 	if (valstr != NULL && entry != NULL) {
-	    if (sa_is_share(group)) {
-		isshare = 1;
-		parent = sa_get_parent_group(group);
-		if (parent != NULL) {
-		    iszfs = is_zfs_group(parent);
+		if (sa_is_share(group)) {
+			isshare = 1;
+			parent = sa_get_parent_group(group);
+			if (parent != NULL)
+				iszfs = is_zfs_group(parent);
+		} else {
+			iszfs = is_zfs_group(group);
 		}
-	    } else {
-		iszfs = is_zfs_group(group);
-	    }
-	    if (!iszfs) {
-		    if (scf_handle->trans == NULL) {
-			char oname[256];
-			char *groupname = NULL;
-			if (isshare) {
-			    if (parent != NULL) {
-				groupname = sa_get_group_attr(parent, "name");
-			    }
-			    id = sa_get_share_attr((sa_share_t)group, "id");
-			} else {
-			    groupname = sa_get_group_attr(group, "name");
-			}
-			if (groupname != NULL) {
-			    ret = sa_get_instance(scf_handle, groupname);
-			    sa_free_attr_string(groupname);
+		if (!iszfs) {
+			if (scf_handle->trans == NULL) {
+				char oname[SA_STRSIZE];
+				char *groupname = NULL;
+				if (isshare) {
+					if (parent != NULL) {
+						groupname =
+						    sa_get_group_attr(parent,
+						    "name");
+					}
+					id =
+					    sa_get_share_attr((sa_share_t)group,
+					    "id");
+				} else {
+					groupname = sa_get_group_attr(group,
+					    "name");
+				}
+				if (groupname != NULL) {
+					ret = sa_get_instance(scf_handle,
+					    groupname);
+					sa_free_attr_string(groupname);
+				}
+				if (opttype)
+					(void) sa_optionset_name(optionset,
+					    oname, sizeof (oname), id);
+				else
+					(void) sa_security_name(optionset,
+					    oname, sizeof (oname), id);
+				ret = sa_start_transaction(scf_handle, oname);
 			}
-			if (opttype)
-			    (void) sa_optionset_name(optionset, oname,
-							sizeof (oname), id);
-			else
-			    (void) sa_security_name(optionset, oname,
-							sizeof (oname), id);
-			ret = sa_start_transaction(scf_handle, oname);
-		    }
-		    if (ret == SA_OK) {
-			switch (type) {
-			case SA_PROP_OP_REMOVE:
-			    ret = scf_transaction_property_delete(
-							scf_handle->trans,
-							entry, name);
-			    break;
-			case SA_PROP_OP_ADD:
-			case SA_PROP_OP_UPDATE:
-			    value = scf_value_create(scf_handle->handle);
-			    if (value != NULL) {
-				if (type == SA_PROP_OP_ADD)
-				    ret = scf_transaction_property_new(
-							scf_handle->trans,
-							entry,
-							name,
-							SCF_TYPE_ASTRING);
-				else
-				    ret = scf_transaction_property_change(
-							scf_handle->trans,
-							entry,
-							name,
-							SCF_TYPE_ASTRING);
-				if (ret == 0) {
-				    ret = scf_value_set_astring(value, valstr);
-				    if (ret == 0)
-					ret = scf_entry_add_value(entry, value);
-				    if (ret != 0) {
-					scf_value_destroy(value);
-					ret = SA_SYSTEM_ERR;
-				    }
-				} else {
-				    scf_entry_destroy(entry);
-				    ret = SA_SYSTEM_ERR;
+			if (ret == SA_OK) {
+				switch (type) {
+				case SA_PROP_OP_REMOVE:
+					ret = scf_transaction_property_delete(
+					    scf_handle->trans, entry, name);
+					break;
+				case SA_PROP_OP_ADD:
+				case SA_PROP_OP_UPDATE:
+					value = scf_value_create(
+					    scf_handle->handle);
+					ret = add_or_update(scf_handle, type,
+					    value, entry, name, valstr);
+					break;
 				}
-				break;
-			    }
 			}
-		    }
-	    } else {
-		/*
-		 * ZFS update. The calling function would have updated
-		 * the internal XML structure. Just need to flag it as
-		 * changed for ZFS.
-		 */
-		zfs_set_update((sa_share_t)group);
-	    }
+		} else {
+			/*
+			 * ZFS update. The calling function would have updated
+			 * the internal XML structure. Just need to flag it as
+			 * changed for ZFS.
+			 */
+			zfs_set_update((sa_share_t)group);
+		}
 	}
 
 	if (name != NULL)
-	    sa_free_attr_string(name);
+		sa_free_attr_string(name);
 	if (valstr != NULL)
-	    sa_free_attr_string(valstr);
+		sa_free_attr_string(valstr);
 	else if (entry != NULL)
-	    scf_entry_destroy(entry);
+		scf_entry_destroy(entry);
 
 	if (ret == -1)
-	    ret = SA_SYSTEM_ERR;
+		ret = SA_SYSTEM_ERR;
 
 	return (ret);
 }
@@ -2740,87 +2839,105 @@
 
 	proto = sa_get_optionset_attr(object, "type");
 	if (property != NULL) {
-	    if ((ret = sa_valid_property(object, proto, property)) == SA_OK) {
-		property = (sa_property_t)xmlAddChild((xmlNodePtr)object,
-							(xmlNodePtr)property);
-	    } else {
-		if (proto != NULL)
-		    sa_free_attr_string(proto);
-		return (ret);
-	    }
+		if ((ret = sa_valid_property(object, proto, property)) ==
+		    SA_OK) {
+			property = (sa_property_t)xmlAddChild(
+			    (xmlNodePtr)object, (xmlNodePtr)property);
+		} else {
+			if (proto != NULL)
+				sa_free_attr_string(proto);
+			return (ret);
+		}
 	}
 
 	if (proto != NULL)
-	    sa_free_attr_string(proto);
+		sa_free_attr_string(proto);
 
 	parent = sa_get_parent_group(object);
 	if (!is_persistent(parent)) {
-	    return (ret);
+		return (ret);
 	}
 
 	if (sa_is_share(parent))
-	    group = sa_get_parent_group(parent);
+		group = sa_get_parent_group(parent);
 	else
-	    group = parent;
+		group = parent;
 
-	if (property == NULL)
-	    ret = SA_NO_MEMORY;
-	else {
-	    char oname[256];
+	if (property == NULL) {
+		ret = SA_NO_MEMORY;
+	} else {
+		char oname[SA_STRSIZE];
 
-	    if (!is_zfs_group(group)) {
-		char *id = NULL;
-		sa_handle_impl_t impl_handle;
-		scfutilhandle_t  *scf_handle;
+		if (!is_zfs_group(group)) {
+			char *id = NULL;
+			sa_handle_impl_t impl_handle;
+			scfutilhandle_t  *scf_handle;
 
-		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-		if (impl_handle == NULL || impl_handle->scfhandle == NULL)
-		    ret = SA_SYSTEM_ERR;
-		if (ret == SA_OK) {
-		    scf_handle = impl_handle->scfhandle;
-		    if (sa_is_share((sa_group_t)parent)) {
-			id = sa_get_share_attr((sa_share_t)parent, "id");
-		    }
-		    if (scf_handle->trans == NULL) {
-			if (is_nodetype(object, "optionset"))
-			    (void) sa_optionset_name((sa_optionset_t)object,
-					    oname, sizeof (oname), id);
-			else
-			    (void) sa_security_name((sa_optionset_t)object,
-					    oname, sizeof (oname), id);
-			ret = sa_start_transaction(scf_handle, oname);
-		    }
-		    if (ret == SA_OK) {
-			char *name;
-			char *value;
-			name = sa_get_property_attr(property, "type");
-			value = sa_get_property_attr(property, "value");
-			if (name != NULL && value != NULL) {
-			    if (scf_handle->scf_state == SCH_STATE_INIT)
-				ret = sa_set_property(scf_handle, name, value);
-			} else
-			    ret = SA_CONFIG_ERR;
-			if (name != NULL)
-			    sa_free_attr_string(name);
-			if (value != NULL)
-			    sa_free_attr_string(value);
-		    }
-		    if (id != NULL)
-			sa_free_attr_string(id);
+			impl_handle = (sa_handle_impl_t)sa_find_group_handle(
+			    group);
+			if (impl_handle == NULL ||
+			    impl_handle->scfhandle == NULL)
+				ret = SA_SYSTEM_ERR;
+			if (ret == SA_OK) {
+				scf_handle = impl_handle->scfhandle;
+				if (sa_is_share((sa_group_t)parent)) {
+					id = sa_get_share_attr(
+					    (sa_share_t)parent, "id");
+				}
+				if (scf_handle->trans == NULL) {
+					if (is_nodetype(object, "optionset")) {
+						(void) sa_optionset_name(
+						    (sa_optionset_t)object,
+						    oname, sizeof (oname), id);
+					} else {
+						(void) sa_security_name(
+						    (sa_optionset_t)object,
+						    oname, sizeof (oname), id);
+					}
+					ret = sa_start_transaction(scf_handle,
+					    oname);
+				}
+				if (ret == SA_OK) {
+					char *name;
+					char *value;
+					name = sa_get_property_attr(property,
+					    "type");
+					value = sa_get_property_attr(property,
+					    "value");
+					if (name != NULL && value != NULL) {
+						if (scf_handle->scf_state ==
+						    SCH_STATE_INIT) {
+							ret = sa_set_property(
+							    scf_handle, name,
+							    value);
+						}
+					} else {
+						ret = SA_CONFIG_ERR;
+					}
+					if (name != NULL)
+						sa_free_attr_string(
+						    name);
+					if (value != NULL)
+						sa_free_attr_string(value);
+				}
+				if (id != NULL)
+					sa_free_attr_string(id);
+			}
+		} else {
+			/*
+			 * ZFS is a special case. We do want
+			 * to allow editing property/security
+			 * lists since we can have a better
+			 * syntax and we also want to keep
+			 * things consistent when possible.
+			 *
+			 * Right now, we defer until the
+			 * sa_commit_properties so we can get
+			 * them all at once. We do need to
+			 * mark the share as "changed"
+			 */
+			zfs_set_update((sa_share_t)parent);
 		}
-	    } else {
-		/*
-		 * ZFS is a special case. We do want to allow editing
-		 * property/security lists since we can have a better
-		 * syntax and we also want to keep things consistent
-		 * when possible.
-		 *
-		 * Right now, we defer until the sa_commit_properties
-		 * so we can get them all at once. We do need to mark
-		 * the share as "changed"
-		 */
-		zfs_set_update((sa_share_t)parent);
-	    }
 	}
 	return (ret);
 }
@@ -2842,16 +2959,16 @@
 		sa_group_t group;
 		optionset = sa_get_property_parent(property);
 		if (optionset != NULL) {
-		    group = sa_get_optionset_parent(optionset);
-		    if (group != NULL) {
-			ret = sa_set_prop_by_prop(optionset, group, property,
-					    SA_PROP_OP_REMOVE);
-		    }
+			group = sa_get_optionset_parent(optionset);
+			if (group != NULL) {
+				ret = sa_set_prop_by_prop(optionset, group,
+				    property, SA_PROP_OP_REMOVE);
+			}
 		}
 		xmlUnlinkNode((xmlNodePtr)property);
 		xmlFreeNode((xmlNodePtr)property);
 	} else {
-	    ret = SA_NO_SUCH_PROP;
+		ret = SA_NO_SUCH_PROP;
 	}
 	return (ret);
 }
@@ -2875,13 +2992,13 @@
 		set_node_attr((void *)property, "value", value);
 		optionset = sa_get_property_parent(property);
 		if (optionset != NULL) {
-		    group = sa_get_optionset_parent(optionset);
-		    if (group != NULL) {
-			ret = sa_set_prop_by_prop(optionset, group, property,
-					    SA_PROP_OP_UPDATE);
-		    }
+			group = sa_get_optionset_parent(optionset);
+			if (group != NULL) {
+				ret = sa_set_prop_by_prop(optionset, group,
+				    property, SA_PROP_OP_UPDATE);
+			}
 		} else {
-		    ret = SA_NO_SUCH_PROP;
+			ret = SA_NO_SUCH_PROP;
 		}
 	}
 	return (ret);
@@ -2901,26 +3018,29 @@
 	xmlChar *value = NULL;
 
 	for (node = node->children; node != NULL;
-		node = node->next) {
-	    if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
-		if (prop == NULL)
-		    break;
-		value = xmlGetProp(node, (xmlChar *)"type");
-		if (value != NULL &&
-		    xmlStrcasecmp(value, (xmlChar *)prop) == 0) {
-		    break;
+	    node = node->next) {
+		if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
+			if (prop == NULL)
+				break;
+			value = xmlGetProp(node, (xmlChar *)"type");
+			if (value != NULL &&
+			    xmlStrcasecmp(value, (xmlChar *)prop) == 0) {
+				break;
+			}
+			if (value != NULL) {
+				xmlFree(value);
+				value = NULL;
+			}
 		}
-		if (value != NULL) {
-		    xmlFree(value);
-		    value = NULL;
-		}
-	    }
 	}
 	if (value != NULL)
 		xmlFree(value);
 	if (node != NULL && xmlStrcmp(node->name, (xmlChar *)"option") != 0) {
-	    /* avoid a non option node -- it is possible to be a text node */
-	    node = NULL;
+		/*
+		 * avoid a non option node -- it is possible to be a
+		 * text node
+		 */
+		node = NULL;
 	}
 	return ((sa_property_t)node);
 }
@@ -2937,7 +3057,7 @@
 	xmlNodePtr node;
 
 	for (node = ((xmlNodePtr)prop)->next; node != NULL;
-		node = node->next) {
+	    node = node->next) {
 		if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
 			break;
 		}
@@ -2961,12 +3081,12 @@
 
 	propset = ((xmlNodePtr)prop)->parent;
 	if (propset != NULL) {
-	    proto = sa_get_optionset_attr(propset, "type");
-	    if (proto != NULL) {
-		set_node_attr((xmlNodePtr)prop, "value", value);
-		ret = sa_proto_set_property(proto, prop);
-		sa_free_attr_string(proto);
-	    }
+		proto = sa_get_optionset_attr(propset, "type");
+		if (proto != NULL) {
+			set_node_attr((xmlNodePtr)prop, "value", value);
+			ret = sa_proto_set_property(proto, prop);
+			sa_free_attr_string(proto);
+		}
 	}
 	return (ret);
 }
@@ -2985,7 +3105,7 @@
 	/* should check for legitimacy */
 	node = xmlAddChild((xmlNodePtr)propset, (xmlNodePtr)prop);
 	if (node != NULL)
-	    return (SA_OK);
+		return (SA_OK);
 	return (SA_NO_MEMORY);
 }
 
@@ -2999,9 +3119,9 @@
 sa_create_protocol_properties(char *proto)
 {
 	xmlNodePtr node;
+
 	node = xmlNewNode(NULL, (xmlChar *)"propertyset");
-	if (node != NULL) {
-	    xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
-	}
+	if (node != NULL)
+		xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
 	return (node);
 }
--- a/usr/src/lib/libshare/common/libshare_zfs.c	Fri May 25 09:07:46 2007 -0700
+++ b/usr/src/lib/libshare/common/libshare_zfs.c	Fri May 25 09:30:08 2007 -0700
@@ -58,11 +58,15 @@
  * mounts.
  */
 
-void
+int
 sa_zfs_init(sa_handle_impl_t impl_handle)
 {
 	impl_handle->zfs_libhandle = libzfs_init();
-	libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE);
+	if (impl_handle->zfs_libhandle != NULL) {
+		libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE);
+		return (B_TRUE);
+	}
+	return (B_FALSE);
 }
 
 /*
@@ -76,17 +80,17 @@
 sa_zfs_fini(sa_handle_impl_t impl_handle)
 {
 	if (impl_handle->zfs_libhandle != NULL) {
-	    libzfs_fini(impl_handle->zfs_libhandle);
-	    impl_handle->zfs_libhandle = NULL;
-	    if (impl_handle->zfs_list != NULL) {
-		/*
-		 * contents of zfs_list were already freed by the call to
-		 * libzfs_fini().
-		 */
-		free(impl_handle->zfs_list);
-		impl_handle->zfs_list = NULL;
-		impl_handle->zfs_list_count = 0;
-	    }
+		libzfs_fini(impl_handle->zfs_libhandle);
+		impl_handle->zfs_libhandle = NULL;
+		if (impl_handle->zfs_list != NULL) {
+			/*
+			 * contents of zfs_list were already freed by
+			 * the call to libzfs_fini().
+			 */
+			free(impl_handle->zfs_list);
+			impl_handle->zfs_list = NULL;
+			impl_handle->zfs_list_count = 0;
+		}
 	}
 }
 
@@ -121,7 +125,7 @@
 
 		handles = calloc(1, cbp->cb_alloc * sizeof (void *));
 		if (handles == NULL) {
-		    return (0);
+			return (0);
 		}
 
 		if (cbp->cb_handles) {
@@ -154,13 +158,13 @@
 	get_all_cbdata_t cb = { 0 };
 
 	if (impl_handle->zfs_list != NULL) {
-	    *fslist = impl_handle->zfs_list;
-	    *count = impl_handle->zfs_list_count;
-	    return;
+		*fslist = impl_handle->zfs_list;
+		*count = impl_handle->zfs_list_count;
+		return;
 	}
 
 	(void) zfs_iter_root(impl_handle->zfs_libhandle,
-				get_one_filesystem, &cb);
+	    get_one_filesystem, &cb);
 
 	impl_handle->zfs_list = *fslist = cb.cb_handles;
 	impl_handle->zfs_list_count = *count = cb.cb_used;
@@ -209,39 +213,39 @@
 	get_all_filesystems(impl_handle, &zlist, &count);
 	qsort(zlist, count, sizeof (void *), mountpoint_compare);
 	for (i = 0; i < count; i++) {
-	    /* must have a mountpoint */
-	    if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT, mountpoint,
-		sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
-		/* no mountpoint */
-		continue;
-	    }
+		/* must have a mountpoint */
+		if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT, mountpoint,
+		    sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
+			/* no mountpoint */
+			continue;
+		}
 
-	    /* mountpoint must be a path */
-	    if (strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) == 0 ||
-		strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0)
-		continue;
+		/* mountpoint must be a path */
+		if (strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) == 0 ||
+		    strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0)
+			continue;
 
-	    /* canmount must be set */
-	    canmount[0] = '\0';
-	    if (!zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount,
+		/* canmount must be set */
+		canmount[0] = '\0';
+		if (!zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount,
 		    sizeof (canmount), NULL, NULL, 0, B_FALSE) != 0 ||
-		strcmp(canmount, "off") == 0)
-		continue;
+		    strcmp(canmount, "off") == 0)
+			continue;
 
-	/*
-	 * have a mountable handle but want to skip those marked none
-	 * and legacy
-	 */
-	    if (strcmp(mountpoint, path) == 0) {
-		dataset = (char *)zfs_get_name(zlist[i]);
-		break;
-	    }
+		/*
+		 * have a mountable handle but want to skip those marked none
+		 * and legacy
+		 */
+		if (strcmp(mountpoint, path) == 0) {
+			dataset = (char *)zfs_get_name(zlist[i]);
+			break;
+		}
 
 	}
 
-	if (dataset != NULL) {
-	    dataset = strdup(dataset);
-	}
+	if (dataset != NULL)
+		dataset = strdup(dataset);
+
 	return (dataset);
 }
 
@@ -260,18 +264,18 @@
 
 	libhandle = libzfs_init();
 	if (libhandle != NULL) {
-	    handle = zfs_open(libhandle, dataset, ZFS_TYPE_FILESYSTEM);
-	    if (handle != NULL) {
-		if (zfs_prop_get(handle, property, shareopts,
-				sizeof (shareopts), NULL, NULL, 0,
-				B_FALSE) == 0) {
-		    zfs_close(handle);
-		    libzfs_fini(libhandle);
-		    return (strdup(shareopts));
+		handle = zfs_open(libhandle, dataset, ZFS_TYPE_FILESYSTEM);
+		if (handle != NULL) {
+			if (zfs_prop_get(handle, property, shareopts,
+			    sizeof (shareopts), NULL, NULL, 0,
+			    B_FALSE) == 0) {
+				zfs_close(handle);
+				libzfs_fini(libhandle);
+				return (strdup(shareopts));
+			}
+			zfs_close(handle);
 		}
-		zfs_close(handle);
-	    }
-	    libzfs_fini(libhandle);
+		libzfs_fini(libhandle);
 	}
 	return (NULL);
 }
@@ -294,20 +298,22 @@
 
 	dataset = get_zfs_dataset((sa_handle_t)sahandle, path);
 	if (dataset != NULL) {
-	    libhandle = libzfs_init();
-	    if (libhandle != NULL) {
-		handle = zfs_open(libhandle, dataset, ZFS_TYPE_FILESYSTEM);
-		if (handle != NULL) {
-		    if (zfs_prop_get(handle, ZFS_PROP_SHARENFS, shareopts,
-					sizeof (shareopts), NULL, NULL, 0,
-					B_FALSE) == 0 &&
-			strcmp(shareopts, "off") != 0)
-			ret = 1; /* it is shared */
-		    zfs_close(handle);
+		libhandle = libzfs_init();
+		if (libhandle != NULL) {
+			handle = zfs_open(libhandle, dataset,
+			    ZFS_TYPE_FILESYSTEM);
+			if (handle != NULL) {
+				if (zfs_prop_get(handle, ZFS_PROP_SHARENFS,
+				    shareopts, sizeof (shareopts), NULL, NULL,
+				    0, B_FALSE) == 0 &&
+				    strcmp(shareopts, "off") != 0) {
+					ret = 1; /* it is shared */
+				}
+				zfs_close(handle);
+			}
+			libzfs_fini(libhandle);
 		}
-		libzfs_fini(libhandle);
-	    }
-	    free(dataset);
+		free(dataset);
 	}
 	return (ret);
 }
@@ -338,31 +344,32 @@
 	 */
 	group = sa_get_group(handle, groupname);
 	if (group == NULL) {
-	    group = sa_create_group(handle, groupname, &ret);
+		group = sa_create_group(handle, groupname, &ret);
 
-	    /* make sure this is flagged as a ZFS group */
-	    if (group != NULL)
-		ret = sa_set_group_attr(group, "zfs", "true");
+		/* make sure this is flagged as a ZFS group */
+		if (group != NULL)
+			ret = sa_set_group_attr(group, "zfs", "true");
 	}
 	if (group != NULL) {
-	    if (proto != NULL) {
-		optionset = sa_get_optionset(group, proto);
-		if (optionset == NULL) {
-		    optionset = sa_create_optionset(group, proto);
-		} else {
-		    char **protolist;
-		    int numprotos, i;
-		    numprotos = sa_get_protocols(&protolist);
-		    for (i = 0; i < numprotos; i++) {
-			optionset = sa_create_optionset(group, protolist[i]);
-		    }
-		    if (protolist != NULL)
-			free(protolist);
+		if (proto != NULL) {
+			optionset = sa_get_optionset(group, proto);
+			if (optionset == NULL) {
+				optionset = sa_create_optionset(group, proto);
+			} else {
+				char **protolist;
+				int numprotos, i;
+				numprotos = sa_get_protocols(&protolist);
+				for (i = 0; i < numprotos; i++) {
+					optionset = sa_create_optionset(group,
+					    protolist[i]);
+				}
+				if (protolist != NULL)
+					free(protolist);
+			}
 		}
-	    }
 	}
 	if (err != NULL)
-	    *err = ret;
+		*err = ret;
 	return (group);
 }
 
@@ -391,41 +398,152 @@
 	zfs = sa_get_group(handle, "zfs");
 	*err = SA_OK;
 	if (zfs != NULL) {
-	    for (group = sa_get_sub_group(zfs); group != NULL;
-		group = sa_get_next_group(group)) {
-		name = sa_get_group_attr(group, "name");
-		if (name != NULL && strcmp(name, groupname) == 0) {
-		    /* have the group so break out of here */
-		    sa_free_attr_string(name);
-		    break;
+		for (group = sa_get_sub_group(zfs); group != NULL;
+		    group = sa_get_next_group(group)) {
+			name = sa_get_group_attr(group, "name");
+			if (name != NULL && strcmp(name, groupname) == 0) {
+				/* have the group so break out of here */
+				sa_free_attr_string(name);
+				break;
+			}
+			if (name != NULL)
+				sa_free_attr_string(name);
 		}
-		if (name != NULL)
-		    sa_free_attr_string(name);
-	    }
 
-	    if (group == NULL) {
-		/* need to create the sub-group since it doesn't exist */
-		group = _sa_create_zfs_group(zfs, groupname);
-		if (group != NULL) {
-		    set_node_attr(group, "zfs", "true");
+		if (group == NULL) {
+			/*
+			 * need to create the sub-group since it doesn't exist
+			 */
+			group = _sa_create_zfs_group(zfs, groupname);
+			if (group != NULL)
+				set_node_attr(group, "zfs", "true");
+			if (strcmp(optstring, "on") == 0)
+				optstring = "rw";
+			if (group != NULL) {
+				options = strdup(optstring);
+				if (options != NULL) {
+					*err = sa_parse_legacy_options(group,
+					    options, "nfs");
+					free(options);
+				} else {
+					*err = SA_NO_MEMORY;
+				}
+			}
 		}
-		if (strcmp(optstring, "on") == 0)
-		    optstring = "rw";
-		if (group != NULL) {
-		    options = strdup(optstring);
-		    if (options != NULL) {
-			*err = sa_parse_legacy_options(group, options, "nfs");
-			free(options);
-		    } else {
-			*err = SA_NO_MEMORY;
-		    }
-		}
-	    }
 	}
 	return (group);
 }
 
 /*
+ * zfs_inherited(handle, source, sourcestr)
+ *
+ * handle case of inherited sharenfs. Pulled out of sa_get_zfs_shares
+ * for readability.
+ */
+static int
+zfs_inherited(sa_handle_t handle, sa_share_t share, char *sourcestr,
+    char *shareopts, char *mountpoint)
+{
+	int doshopt = 0;
+	int err = SA_OK;
+	sa_group_t group;
+
+	/*
+	 * Need to find the "real" parent sub-group. It may not be
+	 * mounted, but it was identified in the "sourcestr"
+	 * variable. The real parent not mounted can occur if
+	 * "canmount=off and sharenfs=on".
+	 */
+	group = find_or_create_zfs_subgroup(handle, sourcestr, shareopts,
+	    &doshopt);
+	if (group != NULL) {
+		share = _sa_add_share(group, mountpoint, SA_SHARE_TRANSIENT,
+		    &err);
+		/*
+		 * some options may only be on shares. If the opt
+		 * string contains one of those, we put it just on the
+		 * share.
+		 */
+		if (share != NULL && doshopt == SA_PROP_SHARE_ONLY) {
+			char *options;
+			options = strdup(shareopts);
+			if (options != NULL) {
+				err = sa_parse_legacy_options(share, options,
+				    "nfs");
+				free(options);
+			}
+		}
+	} else {
+		err = SA_NO_MEMORY;
+	}
+	return (err);
+}
+
+/*
+ * zfs_notinherited()
+ *
+ * handle case where this is the top of a sub-group in ZFS. Pulled out
+ * of sa_get_zfs_shares for readability.
+ */
+static int
+zfs_notinherited(sa_group_t group, char *mountpoint, char *shareopts)
+{
+	int err = SA_OK;
+	sa_share_t share;
+
+	set_node_attr(group, "zfs", "true");
+	share = _sa_add_share(group, mountpoint, SA_SHARE_TRANSIENT, &err);
+	if (err == SA_OK) {
+		if (strcmp(shareopts, "on") != 0) {
+			char *options;
+			options = strdup(shareopts);
+			if (options != NULL) {
+				err = sa_parse_legacy_options(group, options,
+				    "nfs");
+				free(options);
+			}
+			if (err == SA_PROP_SHARE_ONLY) {
+				/*
+				 * Same as above, some properties may
+				 * only be on shares, but due to the
+				 * ZFS sub-groups being artificial, we
+				 * sometimes get this and have to deal
+				 * with it. We do it by attempting to
+				 * put it on the share.
+				 */
+				options = strdup(shareopts);
+				if (options != NULL)
+					err = sa_parse_legacy_options(share,
+					    options, "nfs");
+				if (options != NULL)
+					free(options);
+			}
+			/* unmark the share's changed state */
+			set_node_attr(share, "changed", NULL);
+		}
+	}
+	return (err);
+}
+
+/*
+ * zfs_grp_error(err)
+ *
+ * Print group create error, but only once. If err is 0 do the
+ * print else don't.
+ */
+
+static void
+zfs_grp_error(int err)
+{
+	if (err == 0) {
+		/* only print error once */
+		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+		    "Cannot create ZFS subgroup during initialization:"
+		    " %s\n"), sa_errorstr(SA_SYSTEM_ERR));
+	}
+}
+
+/*
  * sa_get_zfs_shares(handle, groupname)
  *
  * Walk the mnttab for all zfs mounts and determine which are
@@ -449,7 +567,6 @@
 	zfs_source_t source;
 	char sourcestr[ZFS_MAXPROPLEN];
 	char mountpoint[ZFS_MAXPROPLEN];
-	char *options;
 	size_t count = 0, i;
 	libzfs_handle_t *zfs_libhandle;
 
@@ -458,7 +575,7 @@
 	 */
 	zfs_libhandle = ((sa_handle_impl_t)handle)->zfs_libhandle;
 	if (zfs_libhandle == NULL)
-	    return (SA_SYSTEM_ERR);
+		return (SA_SYSTEM_ERR);
 
 	zfsgroup = find_or_create_group(handle, groupname, "nfs", &err);
 	if (zfsgroup != NULL) {
@@ -466,154 +583,90 @@
 		 * need to walk the mounted ZFS pools and datasets to
 		 * find shares that are possible.
 		 */
-	    get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count);
-	    qsort(zlist, count, sizeof (void *), mountpoint_compare);
-
-	    group = zfsgroup;
-	    for (i = 0; i < count; i++) {
-		char *dataset;
-
-		source = ZFS_SRC_ALL;
-		if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT, mountpoint,
-					sizeof (mountpoint), NULL, NULL, 0,
-					B_FALSE) != 0) {
-		    /* no mountpoint */
-		    continue;
-		}
+		get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count);
+		qsort(zlist, count, sizeof (void *), mountpoint_compare);
 
-		/*
-		 * zfs_get_name value must not be freed. It is just a
-		 * pointer to a value in the handle.
-		 */
-		if ((dataset = (char *)zfs_get_name(zlist[i])) == NULL)
-		    continue;
-
-		/*
-		 * only deal with "mounted" file systems since
-		 * unmounted file systems can't actually be shared.
-		 */
-
-		if (!zfs_is_mounted(zlist[i], NULL))
-		    continue;
+		group = zfsgroup;
+		for (i = 0; i < count; i++) {
+			char *dataset;
 
-		if (zfs_prop_get(zlist[i], ZFS_PROP_SHARENFS, shareopts,
-					sizeof (shareopts), &source, sourcestr,
-					ZFS_MAXPROPLEN,
-					B_FALSE) == 0 &&
-			strcmp(shareopts, "off") != 0) {
-		    /* it is shared so add to list */
-		    share = sa_find_share(handle, mountpoint);
-		    err = SA_OK;
-		    if (share != NULL) {
+			source = ZFS_SRC_ALL;
+			if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT,
+			    mountpoint, sizeof (mountpoint), NULL, NULL, 0,
+			    B_FALSE) != 0) {
+				/* no mountpoint */
+				continue;
+			}
+
 			/*
-			 * A zfs file system had been shared
-			 * through traditional methods
-			 * (share/dfstab or added to a non-zfs
-			 * group.  Now it has been added to a
-			 * ZFS group via the zfs
-			 * command. Remove from previous
-			 * config and setup with current
-			 * options.
+			 * zfs_get_name value must not be freed. It is just a
+			 * pointer to a value in the handle.
 			 */
-			err = sa_remove_share(share);
-			share = NULL;
-		    }
-		    if (err == SA_OK) {
-			if (source & ZFS_SRC_INHERITED) {
-			    int doshopt = 0;
+			if ((dataset = (char *)zfs_get_name(zlist[i])) == NULL)
+				continue;
+
 			/*
-			 * Need to find the "real" parent
-			 * sub-group. It may not be mounted, but it
-			 * was identified in the "sourcestr"
-			 * variable. The real parent not mounted can
-			 * occur if "canmount=off and sharenfs=on".
+			 * only deal with "mounted" file systems since
+			 * unmounted file systems can't actually be shared.
 			 */
-			    group = find_or_create_zfs_subgroup(handle,
-							sourcestr,
-							shareopts, &doshopt);
-			    if (group != NULL) {
-				share = _sa_add_share(group, mountpoint,
-							SA_SHARE_TRANSIENT,
-							&err);
-				/*
-				 * some options may only be on
-				 * shares. If the opt string
-				 * contains one of those, we
-				 * put it just on the share.
-				 */
-				if (share != NULL &&
-				    doshopt == SA_PROP_SHARE_ONLY) {
-				    options = strdup(shareopts);
-				    if (options != NULL) {
-					err = sa_parse_legacy_options(share,
-								options, "nfs");
-					free(options);
-				    }
+
+			if (!zfs_is_mounted(zlist[i], NULL))
+				continue;
+
+			if (zfs_prop_get(zlist[i], ZFS_PROP_SHARENFS, shareopts,
+			    sizeof (shareopts), &source, sourcestr,
+			    ZFS_MAXPROPLEN, B_FALSE) == 0 &&
+			    strcmp(shareopts, "off") != 0) {
+				/* it is shared so add to list */
+				share = sa_find_share(handle, mountpoint);
+				err = SA_OK;
+				if (share != NULL) {
+					/*
+					 * A zfs file system had been shared
+					 * through traditional methods
+					 * (share/dfstab or added to a non-zfs
+					 * group.  Now it has been added to a
+					 * ZFS group via the zfs
+					 * command. Remove from previous
+					 * config and setup with current
+					 * options.
+					 */
+					err = sa_remove_share(share);
+					share = NULL;
 				}
-			    } else {
-				err = SA_NO_MEMORY;
-			    }
-			} else {
-			    group = _sa_create_zfs_group(zfsgroup, dataset);
-			    if (group == NULL) {
-				static int err = 0;
-				/*
-				 * there is a problem, but we can't do
-				 * anything about it at this point so
-				 * we issue a warning an move on.
-				 */
-				if (err == 0) {
-				    /* only print error once */
-				    (void) fprintf(stderr,
-					dgettext(TEXT_DOMAIN,
-						"Cannot create ZFS subgroup "
-						"during initialization:"
-						" %s\n"),
-					sa_errorstr(SA_SYSTEM_ERR));
-				    err = 1;
+				if (err == SA_OK) {
+					if (source & ZFS_SRC_INHERITED) {
+						err = zfs_inherited(handle,
+						    share, sourcestr,
+						    shareopts, mountpoint);
+					} else {
+						group = _sa_create_zfs_group(
+						    zfsgroup, dataset);
+						if (group == NULL) {
+							static int err = 0;
+							/*
+							 * there is a problem,
+							 * but we can't do
+							 * anything about it
+							 * at this point so we
+							 * issue a warning an
+							 * move on.
+							 */
+							zfs_grp_error(err);
+							err = 1;
+							continue;
+						}
+						set_node_attr(group, "zfs",
+						    "true");
+						share = _sa_add_share(group,
+						    mountpoint,
+						    SA_SHARE_TRANSIENT, &err);
+						err = zfs_notinherited(group,
+						    mountpoint, shareopts);
+					}
 				}
-				continue;
-			    }
-			    set_node_attr(group, "zfs", "true");
-			    share = _sa_add_share(group, mountpoint,
-						SA_SHARE_TRANSIENT, &err);
-			    if (err == SA_OK) {
-				if (strcmp(shareopts, "on") != 0) {
-				    options = strdup(shareopts);
-				    if (options != NULL) {
-					err = sa_parse_legacy_options(group,
-									options,
-									"nfs");
-					free(options);
-				    }
-				    if (err == SA_PROP_SHARE_ONLY) {
-					/*
-					 * Same as above, some
-					 * properties may only be on
-					 * shares, but due to the ZFS
-					 * sub-groups being
-					 * artificial, we sometimes
-					 * get this and have to deal
-					 * with it. We do it by
-					 * attempting to put it on the
-					 * share.
-					 */
-					options = strdup(shareopts);
-					if (options != NULL)
-					    err = sa_parse_legacy_options(
-									share,
-									options,
-									"nfs");
-					    free(options);
-					}
-				    /* unmark the share's changed state */
-				    set_node_attr(share, "changed", NULL);
-				}
-			    }
 			}
-		    }
 		}
-	    }
 	}
 	/*
 	 * Don't need to free the "zlist" variable since it is only a
@@ -641,43 +694,42 @@
 
 	command = malloc(ZFS_MAXPROPLEN * 2);
 	if (command != NULL) {
-	    char *opts = NULL;
-	    char *dataset = NULL;
-	    FILE *pfile;
-	    sa_handle_impl_t impl_handle;
-	    /* for now, NFS is always available for "zfs" */
-	    if (on) {
-		opts = sa_proto_legacy_format("nfs", group, 1);
-		if (opts != NULL && strlen(opts) == 0) {
-		    free(opts);
-		    opts = strdup("on");
+		char *opts = NULL;
+		char *dataset = NULL;
+		FILE *pfile;
+		sa_handle_impl_t impl_handle;
+		/* for now, NFS is always available for "zfs" */
+		if (on) {
+			opts = sa_proto_legacy_format("nfs", group, 1);
+			if (opts != NULL && strlen(opts) == 0) {
+				free(opts);
+				opts = strdup("on");
+			}
 		}
-	    }
 
-	    impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
-	    assert(impl_handle != NULL);
-	    if (impl_handle != NULL)
-		dataset = get_zfs_dataset(impl_handle, path);
-	    else
-		ret = SA_SYSTEM_ERR;
+		impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
+		assert(impl_handle != NULL);
+		if (impl_handle != NULL)
+			dataset = get_zfs_dataset(impl_handle, path);
+		else
+			ret = SA_SYSTEM_ERR;
 
-	    if (dataset != NULL) {
-		(void) snprintf(command, ZFS_MAXPROPLEN * 2,
-				"%s set sharenfs=\"%s\" %s", COMMAND,
-				opts != NULL ? opts : "off",
-				dataset);
-		pfile = popen(command, "r");
-		if (pfile != NULL) {
-		    ret = pclose(pfile);
-		    if (ret != 0)
-			ret = SA_SYSTEM_ERR;
+		if (dataset != NULL) {
+			(void) snprintf(command, ZFS_MAXPROPLEN * 2,
+			    "%s set sharenfs=\"%s\" %s", COMMAND,
+			    opts != NULL ? opts : "off", dataset);
+			pfile = popen(command, "r");
+			if (pfile != NULL) {
+				ret = pclose(pfile);
+				if (ret != 0)
+					ret = SA_SYSTEM_ERR;
+			}
 		}
-	    }
-	    if (opts != NULL)
-		free(opts);
-	    if (dataset != NULL)
-		free(dataset);
-	    free(command);
+		if (opts != NULL)
+			free(opts);
+		if (dataset != NULL)
+			free(dataset);
+		free(command);
 	}
 	return (ret);
 }
@@ -700,88 +752,97 @@
 	FILE *pfile;
 
 	if (sa_is_share(group))
-	    parent = sa_get_parent_group(group);
+		parent = sa_get_parent_group(group);
 	else
-	    parent = group;
+		parent = group;
 
 	if (parent != NULL) {
-	    command = malloc(ZFS_MAXPROPLEN * 2);
-	    if (command == NULL)
-		return (SA_NO_MEMORY);
+		command = malloc(ZFS_MAXPROPLEN * 2);
+		if (command == NULL)
+			return (SA_NO_MEMORY);
+
+		*command = '\0';
+		for (protopt = sa_get_optionset(parent, NULL); protopt != NULL;
+		    protopt = sa_get_next_optionset(protopt)) {
 
-	    *command = '\0';
-	    for (protopt = sa_get_optionset(parent, NULL); protopt != NULL;
-		protopt = sa_get_next_optionset(protopt)) {
+			char *proto = sa_get_optionset_attr(protopt, "type");
+			char *path;
+			char *dataset = NULL;
+			char *zfsopts = NULL;
 
-		char *proto = sa_get_optionset_attr(protopt, "type");
-		char *path;
-		char *dataset = NULL;
-		char *zfsopts = NULL;
+			if (sa_is_share(group)) {
+				path = sa_get_share_attr((sa_share_t)group,
+				    "path");
+				if (path != NULL) {
+					sa_handle_impl_t impl_handle;
 
-		if (sa_is_share(group)) {
-		    path = sa_get_share_attr((sa_share_t)group, "path");
-		    if (path != NULL) {
-			sa_handle_impl_t impl_handle;
-
-			impl_handle = sa_find_group_handle(group);
-			if (impl_handle != NULL)
-			    dataset = get_zfs_dataset(impl_handle, path);
-			else
-			    ret = SA_SYSTEM_ERR;
+					impl_handle = sa_find_group_handle(
+					    group);
+					if (impl_handle != NULL)
+						dataset = get_zfs_dataset(
+						    impl_handle, path);
+					else
+						ret = SA_SYSTEM_ERR;
 
-			sa_free_attr_string(path);
-		    }
-		} else {
-		    dataset = sa_get_group_attr(group, "name");
-		}
-		/* update only when there is an optstring found */
-		doupdate = 0;
-		if (proto != NULL && dataset != NULL) {
-		    optstring = sa_proto_legacy_format(proto, group, 1);
-		    zfsopts = get_zfs_property(dataset, ZFS_PROP_SHARENFS);
+					sa_free_attr_string(path);
+				}
+			} else {
+				dataset = sa_get_group_attr(group, "name");
+			}
+			/* update only when there is an optstring found */
+			doupdate = 0;
+			if (proto != NULL && dataset != NULL) {
+				optstring = sa_proto_legacy_format(proto,
+				    group, 1);
+				zfsopts = get_zfs_property(dataset,
+				    ZFS_PROP_SHARENFS);
 
-		    if (optstring != NULL && zfsopts != NULL) {
-			if (strcmp(optstring, zfsopts) != 0)
-			    doupdate++;
-		    }
+				if (optstring != NULL && zfsopts != NULL) {
+					if (strcmp(optstring, zfsopts) != 0)
+						doupdate++;
+				}
 
-		    if (doupdate) {
-			if (optstring != NULL && strlen(optstring) > 0) {
-			    (void) snprintf(command, ZFS_MAXPROPLEN * 2,
-					    "%s set sharenfs=%s %s", COMMAND,
-					    optstring, dataset);
-			} else {
-			    (void) snprintf(command, ZFS_MAXPROPLEN * 2,
-					    "%s set sharenfs=on %s", COMMAND,
-					    dataset);
+				if (doupdate) {
+					if (optstring != NULL &&
+					    strlen(optstring) > 0) {
+						(void) snprintf(command,
+						    ZFS_MAXPROPLEN * 2,
+						    "%s set sharenfs=%s %s"
+						    COMMAND,
+						    optstring, dataset);
+					} else {
+						(void) snprintf(command,
+						    ZFS_MAXPROPLEN * 2,
+						    "%s set sharenfs=on %s",
+						    COMMAND,
+						    dataset);
+					}
+					pfile = popen(command, "r");
+					if (pfile != NULL)
+						ret = pclose(pfile);
+					switch (ret) {
+					default:
+					case 1:
+						ret = SA_SYSTEM_ERR;
+						break;
+					case 2:
+						ret = SA_SYNTAX_ERR;
+						break;
+					case 0:
+						break;
+					}
+				}
+				if (optstring != NULL)
+					free(optstring);
+				if (zfsopts != NULL)
+					free(zfsopts);
 			}
-			pfile = popen(command, "r");
-			if (pfile != NULL)
-			    ret = pclose(pfile);
-			switch (ret) {
-			default:
-			case 1:
-			    ret = SA_SYSTEM_ERR;
-			    break;
-			case 2:
-			    ret = SA_SYNTAX_ERR;
-			    break;
-			case 0:
-			    break;
-			}
-		    }
-		    if (optstring != NULL) {
-			free(optstring);
-		    }
-		    if (zfsopts != NULL)
-			free(zfsopts);
+			if (proto != NULL)
+				sa_free_attr_string(proto);
+			if (dataset != NULL)
+				free(dataset);
 		}
-		if (proto != NULL)
-		    sa_free_attr_string(proto);
-		if (dataset != NULL)
-		    free(dataset);
-	    }
-	    free(command);
+		free(command);
 	}
 	return (ret);
 }
@@ -800,8 +861,8 @@
 
 	zfs = sa_get_group_attr(group, "zfs");
 	if (zfs != NULL) {
-	    ret = 1;
-	    sa_free_attr_string(zfs);
+		ret = 1;
+		sa_free_attr_string(zfs);
 	}
 	return (ret);
 }
@@ -819,10 +880,9 @@
 	int ret = 0;
 
 	fstype = sa_fstype(path);
-	if (fstype != NULL && strcmp(fstype, "zfs") == 0) {
-	    ret = 1;
-	}
+	if (fstype != NULL && strcmp(fstype, "zfs") == 0)
+		ret = 1;
 	if (fstype != NULL)
-	    sa_free_fstype(fstype);
+		sa_free_fstype(fstype);
 	return (ret);
 }
--- a/usr/src/lib/libzfs/common/libzfs_mount.c	Fri May 25 09:07:46 2007 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c	Fri May 25 09:30:08 2007 -0700
@@ -475,6 +475,18 @@
 		_sa_errorstr = (char *(*)(int))dlsym(libshare, "sa_errorstr");
 		_sa_parse_legacy_options = (int (*)(sa_group_t, char *, char *))
 		    dlsym(libshare, "sa_parse_legacy_options");
+		if (_sa_init == NULL || _sa_fini == NULL ||
+		    _sa_find_share == NULL || _sa_enable_share == NULL ||
+		    _sa_disable_share == NULL || _sa_errorstr == NULL ||
+		    _sa_parse_legacy_options == NULL) {
+			_sa_init = NULL;
+			_sa_fini = NULL;
+			_sa_disable_share = NULL;
+			_sa_enable_share = NULL;
+			_sa_errorstr = NULL;
+			_sa_parse_legacy_options = NULL;
+			(void) dlclose(libshare);
+		}
 	}
 }