Mercurial > illumos > illumos-gate
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); + } } }