6185db853e024a486ff8837e6784dd290d866112dougm * CDDL HEADER START
6185db853e024a486ff8837e6784dd290d866112dougm * The contents of this file are subject to the terms of the
6185db853e024a486ff8837e6784dd290d866112dougm * Common Development and Distribution License (the "License").
6185db853e024a486ff8837e6784dd290d866112dougm * You may not use this file except in compliance with the License.
6185db853e024a486ff8837e6784dd290d866112dougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6185db853e024a486ff8837e6784dd290d866112dougm * See the License for the specific language governing permissions
6185db853e024a486ff8837e6784dd290d866112dougm * and limitations under the License.
6185db853e024a486ff8837e6784dd290d866112dougm * When distributing Covered Code, include this CDDL HEADER in each
6185db853e024a486ff8837e6784dd290d866112dougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6185db853e024a486ff8837e6784dd290d866112dougm * If applicable, add the following below this CDDL HEADER, with the
6185db853e024a486ff8837e6784dd290d866112dougm * fields enclosed by brackets "[]" replaced with your own identifying
6185db853e024a486ff8837e6784dd290d866112dougm * information: Portions Copyright [yyyy] [name of copyright owner]
6185db853e024a486ff8837e6784dd290d866112dougm * CDDL HEADER END
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
5cb0d67909d9970a3e7adbea9422ca3fc88000bfMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
09c9e6dc9b69d10b771bb87e01040ec320a0bfd3Chris Williamson * Copyright (c) 2016 by Delphix. All rights reserved.
6185db853e024a486ff8837e6784dd290d866112dougm * core library for common functions across all config store types
6185db853e024a486ff8837e6784dd290d866112dougm * and file systems to be exported. This includes legacy dfstab/sharetab
6185db853e024a486ff8837e6784dd290d866112dougm * parsing. Need to eliminate XML where possible.
6185db853e024a486ff8837e6784dd290d866112dougm "# Do not modify this file directly.\n",
6185db853e024a486ff8837e6784dd290d866112dougm "# Use the sharemgr(1m) command for all share management\n",
6185db853e024a486ff8837e6784dd290d866112dougm "# This file is reconstructed and only maintained for backward\n",
6185db853e024a486ff8837e6784dd290d866112dougm "# compatibility. Configuration lines could be lost.\n",
6185db853e024a486ff8837e6784dd290d866112dougm#define STRNCAT(x, y, z) (xmlChar *)strncat((char *)x, (char *)y, z)
6185db853e024a486ff8837e6784dd290d866112dougm/* will be much smaller, but this handles bad syntax in the file */
6185db853e024a486ff8837e6784dd290d866112dougm/* used internally only */
549ec3fff108310966327d1dc9004551b63210b7dougmstatic void parse_dfstab(sa_handle_t, char *, xmlNodePtr);
8d7e41661dc4633488e93b13363137523ce59977jose borregoextern char *_sa_get_token(char *);
6185db853e024a486ff8837e6784dd290d866112dougm/* prototypes */
549ec3fff108310966327d1dc9004551b63210b7dougmvoid getlegacyconfig(sa_handle_t, char *, xmlNodePtr *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern sa_share_t _sa_add_share(sa_group_t, char *, int, int *, uint64_t);
549ec3fff108310966327d1dc9004551b63210b7dougmextern sa_group_t _sa_create_group(sa_handle_impl_t, char *);
6185db853e024a486ff8837e6784dd290d866112dougmextern int set_node_share(void *, char *, char *);
6185db853e024a486ff8837e6784dd290d866112dougmextern void set_node_attr(void *, char *, char *);
a99982a76d4cc12b1e9021e88531cf425d1e7369dougm * sablocksigs(*sigs)
a99982a76d4cc12b1e9021e88531cf425d1e7369dougm * block important signals for a critical region. Arg is a pointer to
a99982a76d4cc12b1e9021e88531cf425d1e7369dougm * a sigset_t that is used later for the unblock.
a99982a76d4cc12b1e9021e88531cf425d1e7369dougm * saunblocksigs(*sigs)
a99982a76d4cc12b1e9021e88531cf425d1e7369dougm * unblock previously blocked signals from the sigs arg.
6185db853e024a486ff8837e6784dd290d866112dougm * alloc_sharelist()
6185db853e024a486ff8837e6784dd290d866112dougm * allocator function to return an zfs_sharelist_t
6185db853e024a486ff8837e6784dd290d866112dougm item = (xfs_sharelist_t *)malloc(sizeof (xfs_sharelist_t));
6185db853e024a486ff8837e6784dd290d866112dougm * fix_notice(list)
6185db853e024a486ff8837e6784dd290d866112dougm * Look at the beginning of the current /etc/dfs/dfstab file and add
6185db853e024a486ff8837e6784dd290d866112dougm * the do not modify notice if it doesn't exist.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* zero length dfstab */
6185db853e024a486ff8837e6784dd290d866112dougm if (list->path == NULL && list->description != NULL &&
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm for (prev = NULL, i = 0; i < DFSTAB_NOTICE_LINES; i++) {
6185db853e024a486ff8837e6784dd290d866112dougm * getdfstab(dfs)
6185db853e024a486ff8837e6784dd290d866112dougm * Returns an zfs_sharelist_t list of lines from the dfstab file
6185db853e024a486ff8837e6784dd290d866112dougm * pointed to by the FILE pointer dfs. Each entry is parsed and the
6185db853e024a486ff8837e6784dd290d866112dougm * original line is also preserved. Used in parsing and updating the
6185db853e024a486ff8837e6784dd290d866112dougm * dfstab file.
6185db853e024a486ff8837e6784dd290d866112dougm char buff[_POSIX_ARG_MAX]; /* reasonable size given syntax of share */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* if no path, then comment */
8d7e41661dc4633488e93b13363137523ce59977jose borrego (void) _sa_get_token(NULL); /* reset to new pointers */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm switch (c) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* resource and/or groupname */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* NFS is the default if none defined */
6185db853e024a486ff8837e6784dd290d866112dougm * finddfsentry(list, path)
7d968cb8b4b6274092771b93e94bf88d1ee31c6cdougm * Look for path in the zfs_sharelist_t list and return the entry if it
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm if (item->path != NULL && strcmp(item->path, path) == 0)
6185db853e024a486ff8837e6784dd290d866112dougm * remdfsentry(list, path, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * Remove the specified path (with protocol) from the list. This will
6185db853e024a486ff8837e6784dd290d866112dougm * remove it from dfstab when the file is rewritten.
6185db853e024a486ff8837e6784dd290d866112dougmremdfsentry(xfs_sharelist_t *list, char *path, char *proto)
6185db853e024a486ff8837e6784dd290d866112dougm for (item = prev = list; item != NULL; item = item->next) {
6185db853e024a486ff8837e6784dd290d866112dougm /* skip comment entry but don't lose it */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* if proto is NULL, remove all protocols */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm if (proto == NULL || (strcmp(item->path, path) == 0 &&
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm (item->fstype != NULL && strcmp(item->fstype, proto) == 0)))
6185db853e024a486ff8837e6784dd290d866112dougm * remdfsline(list, line)
6185db853e024a486ff8837e6784dd290d866112dougm * Remove the line specified from the list.
6185db853e024a486ff8837e6784dd290d866112dougm for (item = prev = list; item != NULL; item = item->next) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* skip comment entry but don't lose it */
6185db853e024a486ff8837e6784dd290d866112dougm * adddfsentry(list, share, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * Add an entry to the dfstab list for share (relative to proto). This
6185db853e024a486ff8837e6784dd290d866112dougm * is used to update dfstab for legacy purposes.
6185db853e024a486ff8837e6784dd290d866112dougmadddfsentry(xfs_sharelist_t *list, sa_share_t share, char *proto)
fe1c642d06e14b412cd83ae2179303186ab08972Bill Krier if (groupname != NULL && strcmp(groupname, "default") == 0) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm item->resource = sa_get_share_attr(share, "resource");
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm item->options = sa_proto_legacy_format(proto, share, 1);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm if (item->options != NULL && strlen(item->options) == 0) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* do nothing */;
6185db853e024a486ff8837e6784dd290d866112dougm * outdfstab(dfstab, list)
6185db853e024a486ff8837e6784dd290d866112dougm * Output the list to dfstab making sure the file is truncated.
6185db853e024a486ff8837e6784dd290d866112dougm * Comments and errors are preserved.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "share %s%s%s%s%s%s%s %s%s%s%s%s\n",
6185db853e024a486ff8837e6784dd290d866112dougm * open_dfstab(file)
6185db853e024a486ff8837e6784dd290d866112dougm * Open the specified dfstab file. If the owner/group/perms are wrong,
6185db853e024a486ff8837e6784dd290d866112dougm * fix them.
6185db853e024a486ff8837e6784dd290d866112dougm * sa_comment_line(line, err)
6185db853e024a486ff8837e6784dd290d866112dougm * Add a comment to the dfstab file with err as a prefix to the
6185db853e024a486ff8837e6784dd290d866112dougm * original line.
f345c0beb4c8f75cb54c2e070498e56febd468acdougm * don't ignore the return since the list could have
f345c0beb4c8f75cb54c2e070498e56febd468acdougm * gone to NULL if the file only had one line in it.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sa_delete_legacy(share, protocol)
6185db853e024a486ff8837e6784dd290d866112dougm * Delete the specified share from the legacy config file.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Protect against shares that don't have paths. This is not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * really an error at this point.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * may want to only do the dfstab if
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * this call returns NOT IMPLEMENTED
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * but it shouldn't hurt.
6185db853e024a486ff8837e6784dd290d866112dougm * sa_update_legacy(share, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * There is an assumption that dfstab will be the most common form of
6185db853e024a486ff8837e6784dd290d866112dougm * legacy configuration file for shares, but not the only one. Because
6185db853e024a486ff8837e6784dd290d866112dougm * of that, dfstab handling is done in the main code with calls to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * this function and protocol specific calls to deal with formatting
6185db853e024a486ff8837e6784dd290d866112dougm * options into dfstab/share compatible syntax. Since not everything
6185db853e024a486ff8837e6784dd290d866112dougm * will be dfstab, there is a provision for calling a protocol
6185db853e024a486ff8837e6784dd290d866112dougm * specific plugin interface that allows the protocol plugin to do its
6185db853e024a486ff8837e6784dd290d866112dougm * own legacy files and skip the dfstab update.
6185db853e024a486ff8837e6784dd290d866112dougm /* do the dfstab format */
6185db853e024a486ff8837e6784dd290d866112dougm * only update if the share is not transient -- no share type
6185db853e024a486ff8837e6784dd290d866112dougm * set or the type is not "transient".
6185db853e024a486ff8837e6784dd290d866112dougm if (persist == NULL || strcmp(persist, "transient") != 0) {
6185db853e024a486ff8837e6784dd290d866112dougm * sa_is_security(optname, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * Check to see if optname is a security (named optionset) specific
6185db853e024a486ff8837e6784dd290d866112dougm * property for the specified protocol.
6185db853e024a486ff8837e6784dd290d866112dougm * add_syntax_comment(root, line, err, todfstab)
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Add a comment to the document indicating a syntax error. If
6185db853e024a486ff8837e6784dd290d866112dougm * todfstab is set, write it back to the dfstab file as well.
6185db853e024a486ff8837e6784dd290d866112dougmadd_syntax_comment(xmlNodePtr root, char *line, char *err, int todfstab)
6185db853e024a486ff8837e6784dd290d866112dougm node = xmlNewChild(root, NULL, (xmlChar *)"error", (xmlChar *)line);
7a9d7716b53eb5c2c08bf4f0fdf4369571dbde4dthurlow (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)err);
6185db853e024a486ff8837e6784dd290d866112dougm * sa_is_share(object)
5cb0d67909d9970a3e7adbea9422ca3fc88000bfMarcel Telka * returns true if the object is of type "share".
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm if (strcmp((char *)((xmlNodePtr)object)->name, "share") == 0)
6185db853e024a486ff8837e6784dd290d866112dougm return (1);
6185db853e024a486ff8837e6784dd290d866112dougm return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sa_is_resource(object)
5cb0d67909d9970a3e7adbea9422ca3fc88000bfMarcel Telka * returns true if the object is of type "resource".
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strcmp((char *)((xmlNodePtr)object)->name, "resource") == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
6185db853e024a486ff8837e6784dd290d866112dougm * _sa_remove_property(property)
6185db853e024a486ff8837e6784dd290d866112dougm * remove a property only from the document.
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * _sa_create_dummy_share()
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * Create a share entry suitable for parsing but not tied to any real
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * config tree. Need to have a parent as well as the node to parse
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * on. Free using _sa_free_dummy_share(share);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm child_node = xmlNewChild(parent_node, NULL, (xmlChar *)"share",
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Use a "zfs" tag since that will make sure nothing
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * really attempts to put values into the
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * repository. Also ZFS is currently the only user of
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * this interface.
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * _sa_free_dummy_share(share)
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * Free the dummy share and its parent. It is an error to try and
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * free something that isn't a dummy.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Real shares always have a path but a dummy doesn't */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * If there is a parent, do the free on that since
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * xmlFreeNode is a recursive function and free's an
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * child nodes.
6185db853e024a486ff8837e6784dd290d866112dougm * sa_parse_legacy_options(group, options, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * In order to support legacy configurations, we allow the protocol
6185db853e024a486ff8837e6784dd290d866112dougm * specific plugin to parse legacy syntax options (like those in
6185db853e024a486ff8837e6784dd290d866112dougm * /etc/dfs/dfstab). This adds a new optionset to the group (or
6185db853e024a486ff8837e6784dd290d866112dougm * Once the optionset has been created, we then get the derived
6185db853e024a486ff8837e6784dd290d866112dougm * optionset of the parent (options from the optionset of the parent
6185db853e024a486ff8837e6784dd290d866112dougm * and any parent it might have) and remove those from the created
6185db853e024a486ff8837e6784dd290d866112dougm * optionset. This avoids duplication of options.
6185db853e024a486ff8837e6784dd290d866112dougmsa_parse_legacy_options(sa_group_t group, char *options, char *proto)
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * If "group" is NULL, this is just a parse without saving
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * anything in either SMF or ZFS. Create a dummy group to
6733190958bbcc0bd6d1d601e7ae0a6994dafb45dougm * handle this case.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Since this is a dummy parse, cleanup and quit here */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * If in a group, remove the inherited options and security
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Find parent options to remove from child */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm optionset = sa_get_derived_optionset(parent, proto, 1);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Remove the property
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * child. While we
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * removed it, we
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * don't need to reset
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * as we do below
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * since we always
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * search from the
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * beginning.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * All properties removed so remove the
6185db853e024a486ff8837e6784dd290d866112dougm * optionset if it is on a share
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Need to remove security here. If there are no
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * security options on the local group/share, don't
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * bother since those are the only ones that would be
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * affected.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm localoptions = sa_get_all_security_types(group, proto, 0);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * prop's value only changes outside this loop
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Need to get the next prop
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * now since we could break
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * the list during removal.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* remove Duplicates from this level */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * remove the property
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * from the child
6185db853e024a486ff8837e6784dd290d866112dougm * dfs_free_list(list)
6185db853e024a486ff8837e6784dd290d866112dougm * Free the data in each list entry of the list as well as freeing the
6185db853e024a486ff8837e6784dd290d866112dougm * entries themselves. We need to avoid memory leaks and don't want to
6185db853e024a486ff8837e6784dd290d866112dougm * dereference any NULL members.
6185db853e024a486ff8837e6784dd290d866112dougm * parse_dfstab(dfstab, root)
6185db853e024a486ff8837e6784dd290d866112dougm * Open and read the existing dfstab, parsing each line and adding it
6185db853e024a486ff8837e6784dd290d866112dougm * to the internal configuration. Make sure syntax errors, etc are
6185db853e024a486ff8837e6784dd290d866112dougm * preserved as comments.
549ec3fff108310966327d1dc9004551b63210b7dougmparse_dfstab(sa_handle_t handle, char *dfstab, xmlNodePtr root)
6185db853e024a486ff8837e6784dd290d866112dougm /* read the dfstab format file and fill in the doc tree */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Comment line that we will likely skip.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * If the line has the syntax:
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * # error: string: string
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * It should be preserved until manually deleted.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "No share specified in dfstab: "
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "line %d: %s\n"),
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "Unknown group used in dfstab: line %d: %s\n"),
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Shouldn't happen unless an SMF error */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* This is an OK add for legacy */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "Error in dfstab: line %d: %s\n"),
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "Attempt to change configuration in "
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm "dfstab: line %d: %s\n"),
546405c3c5a146c88705b0b02a469d1bd57f2b53dougm * It is the same group but could have changed
546405c3c5a146c88705b0b02a469d1bd57f2b53dougm * options. Make sure we include the group's
546405c3c5a146c88705b0b02a469d1bd57f2b53dougm * properties so we don't end up moving them to
546405c3c5a146c88705b0b02a469d1bd57f2b53dougm * the share inadvertantly. The last arg being
546405c3c5a146c88705b0b02a469d1bd57f2b53dougm * true says to get the inherited properties as well
546405c3c5a146c88705b0b02a469d1bd57f2b53dougm * as the local properties.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm oldprops = sa_proto_legacy_format(list->fstype, share,
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* possibly different values */
6185db853e024a486ff8837e6784dd290d866112dougm * legacy_removes(group, file)
6185db853e024a486ff8837e6784dd290d866112dougm * Find any shares that are "missing" from the legacy file. These
6185db853e024a486ff8837e6784dd290d866112dougm * should be removed from the configuration since they are likely from
6185db853e024a486ff8837e6784dd290d866112dougm * a legacy app or the admin modified the dfstab file directly. We
6185db853e024a486ff8837e6784dd290d866112dougm * have to support this even if it is not the recommended way to do
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* now see if the share is in the dfstab file */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* The share was removed this way */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Start over since the list was broken
6185db853e024a486ff8837e6784dd290d866112dougm * getlegacyconfig(path, root)
6185db853e024a486ff8837e6784dd290d866112dougm * Parse dfstab and build the legacy configuration. This only gets
6185db853e024a486ff8837e6784dd290d866112dougm * called when a change was detected.
549ec3fff108310966327d1dc9004551b63210b7dougmgetlegacyconfig(sa_handle_t handle, char *path, xmlNodePtr *root)
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Walk the default shares and find anything
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * missing. we do this first to make sure it
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * is cleaned up since there may be legacy
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * code add/del via dfstab and we need to
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * cleanup SMF.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Parse the dfstab and add anything new */
1cea05af420c1992d793dc442f4e30c7269fc107dougm * get_share_list(&err)
1cea05af420c1992d793dc442f4e30c7269fc107dougm * Get a linked list of all the shares on the system from
1cea05af420c1992d793dc442f4e30c7269fc107dougm * /etc/dfs/sharetab. This is partially copied from libfsmgt which we
1cea05af420c1992d793dc442f4e30c7269fc107dougm * can't use due to package dependencies.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Link into the list here so we don't leak
1cea05af420c1992d793dc442f4e30c7269fc107dougm * memory on a failure from strdup().
8d7e41661dc4633488e93b13363137523ce59977jose borrego if (newp->path == NULL || newp->resource == NULL ||
8d7e41661dc4633488e93b13363137523ce59977jose borrego newp->fstype == NULL || newp->options == NULL ||
1cea05af420c1992d793dc442f4e30c7269fc107dougm * Caller must free the mount list
1cea05af420c1992d793dc442f4e30c7269fc107dougm * Out of memory so cleanup and leave.
549ec3fff108310966327d1dc9004551b63210b7dougm * parse_sharetab(handle)
1cea05af420c1992d793dc442f4e30c7269fc107dougm * Read the /etc/dfs/sharetab file and see which entries don't exist
1cea05af420c1992d793dc442f4e30c7269fc107dougm * in the repository. These shares are marked transient. We also need
1cea05af420c1992d793dc442f4e30c7269fc107dougm * to see if they are ZFS shares since ZFS bypasses the SMF
1cea05af420c1992d793dc442f4e30c7269fc107dougm * repository.
6185db853e024a486ff8837e6784dd290d866112dougm for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * If this is a legacy share, mark as shared so we
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * only update sharetab appropriately. We also keep
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * the sharetab options in order to display for legacy
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * share with no arguments.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * This share is transient so needs to be
6185db853e024a486ff8837e6784dd290d866112dougm * added. Initially, this will be under
6185db853e024a486ff8837e6784dd290d866112dougm * default(legacy) unless it is a ZFS
6185db853e024a486ff8837e6784dd290d866112dougm * share. If zfs, we need a zfs group.
6185db853e024a486ff8837e6784dd290d866112dougm (groupname = strchr(tmplist->resource, '@')) != NULL) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* There is a defined group */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * While this case shouldn't
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * occur very often, it does
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * occur out of a "zfs set
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * sharenfs=off" when the
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * dataset is also set to
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * canmount=off. A warning
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * will then cause the zfs
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * command to abort. Since we
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * add it to the default list,
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * everything works properly
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * anyway and the library
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * doesn't need to give a
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Get the transient shares from the sharetab (or other) file. since
6185db853e024a486ff8837e6784dd290d866112dougm * these are transient, they only appear in the working file and not
6185db853e024a486ff8837e6784dd290d866112dougm * in a repository.
549ec3fff108310966327d1dc9004551b63210b7dougmgettransients(sa_handle_impl_t ihandle, xmlNodePtr *root)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < numproto; i++)
6185db853e024a486ff8837e6784dd290d866112dougm * sa_has_prop(optionset, prop)
6185db853e024a486ff8837e6784dd290d866112dougm * Is the specified property a member of the optionset?
6185db853e024a486ff8837e6784dd290d866112dougmsa_has_prop(sa_optionset_t optionset, sa_property_t prop)
6185db853e024a486ff8837e6784dd290d866112dougm * Update legacy files
6185db853e024a486ff8837e6784dd290d866112dougm * Provides functions to add/remove/modify individual entries
6185db853e024a486ff8837e6784dd290d866112dougm * in dfstab and sharetab
6185db853e024a486ff8837e6784dd290d866112dougm * no longer used -- this is a placeholder in case we need to
6185db853e024a486ff8837e6784dd290d866112dougm * add it back later.
687915e946710e354e302fa654bf53bf38b57cc6dougm * sa_valid_property(handle, object, proto, property)
6185db853e024a486ff8837e6784dd290d866112dougm * check to see if the specified property is valid relative to the
6185db853e024a486ff8837e6784dd290d866112dougm * specified protocol. The protocol plugin is called to do the work.
687915e946710e354e302fa654bf53bf38b57cc6dougmsa_valid_property(sa_handle_t handle, void *object, char *proto,
687915e946710e354e302fa654bf53bf38b57cc6dougm ret = sa_proto_valid_prop(handle, proto, property, object);
6185db853e024a486ff8837e6784dd290d866112dougm * sa_fstype(path)
6185db853e024a486ff8837e6784dd290d866112dougm * Given path, return the string representing the path's file system
6185db853e024a486ff8837e6784dd290d866112dougm * type. This is used to discover ZFS shares.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * If we have a valid path at this point ret, return the fstype.
6185db853e024a486ff8837e6784dd290d866112dougm * sa_get_derived_optionset(object, proto, hier)
6185db853e024a486ff8837e6784dd290d866112dougm * Work backward to the top of the share object tree and start
6185db853e024a486ff8837e6784dd290d866112dougm * copying protocol specific optionsets into a newly created
6185db853e024a486ff8837e6784dd290d866112dougm * optionset that doesn't have a parent (it will be freed
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * later). This provides for the property inheritance model. That
6185db853e024a486ff8837e6784dd290d866112dougm * is, properties closer to the share take precedence over group
6185db853e024a486ff8837e6784dd290d866112dougm * level. This also provides for groups of groups in the future.
6185db853e024a486ff8837e6784dd290d866112dougmsa_get_derived_optionset(void *object, char *proto, int hier)
6185db853e024a486ff8837e6784dd290d866112dougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm newoptionset = sa_get_derived_optionset((void *)group, proto,
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Dont' do anything if memory wasn't allocated */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Found the top so working back down the stack */
6185db853e024a486ff8837e6784dd290d866112dougm optionset = sa_get_optionset((sa_optionset_t)object, proto);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* add optionset to the newoptionset */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Replace the value with the new value */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Only set if value is non NULL, old value ok
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * if it is NULL.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* an entirely new property */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* While it shouldn't be linked, it doesn't hurt */
6185db853e024a486ff8837e6784dd290d866112dougm * sa_get_all_security_types(object, proto, hier)
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Find all the security types set for this object. This is
6185db853e024a486ff8837e6784dd290d866112dougm * preliminary to getting a derived security set. The return value is an
6185db853e024a486ff8837e6784dd290d866112dougm * optionset containg properties which are the sectype values found by
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * walking up the XML document structure. The returned optionset
6185db853e024a486ff8837e6784dd290d866112dougm * is a derived optionset.
6185db853e024a486ff8837e6784dd290d866112dougm * If hier is 0, only look at object. If non-zero, walk up the tree.
6185db853e024a486ff8837e6784dd290d866112dougmsa_get_all_security_types(void *object, char *proto, int hier)
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL)
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm options = sa_get_all_security_types((void *)group, proto, hier);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Hit the top so collect the security types working back. */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm for (security = sa_get_security((sa_group_t)object, NULL, NULL);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Have a security type, check to see if
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * already present in optionset and add if it
6185db853e024a486ff8837e6784dd290d866112dougm * sa_get_derived_security(object, sectype, proto, hier)
6185db853e024a486ff8837e6784dd290d866112dougm * Get the derived security(named optionset) for the object given the
6185db853e024a486ff8837e6784dd290d866112dougm * sectype and proto. If hier is non-zero, walk up the tree to get all
6185db853e024a486ff8837e6784dd290d866112dougm * properties defined for this object, otherwise just those on the
6185db853e024a486ff8837e6784dd290d866112dougmsa_get_derived_security(void *object, char *sectype, char *proto, int hier)
6185db853e024a486ff8837e6784dd290d866112dougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm sa_set_security_attr(newsecurity, "sectype", sectype);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Don't do anything if memory wasn't allocated */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Found the top so working back down the stack. */
6185db853e024a486ff8837e6784dd290d866112dougm security = sa_get_security((sa_security_t)object, sectype, proto);
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* add security to the newsecurity */
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* Replace the value with the new value */
97df5ac96dbf15a7624a8e07b7dd686404d988c0dougm * Only set if value is non NULL, old
97df5ac96dbf15a7624a8e07b7dd686404d988c0dougm * value ok if it is NULL. The value
97df5ac96dbf15a7624a8e07b7dd686404d988c0dougm * must be associated with the "value"
97df5ac96dbf15a7624a8e07b7dd686404d988c0dougm * tag within XML.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm /* An entirely new property */
6185db853e024a486ff8837e6784dd290d866112dougm /* while it shouldn't be linked, it doesn't hurt */
6185db853e024a486ff8837e6784dd290d866112dougm * sharetab utility functions
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * Makes use of the original sharetab.c from fs.d/nfs/lib
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * sa_fillshare(share, proto, sh)
6185db853e024a486ff8837e6784dd290d866112dougm * Fill the struct share with values obtained from the share object.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarkssa_fillshare(sa_share_t share, char *proto, struct share *sh)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We only want to deal with the path level shares for the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sharetab file. If a resource, get the parent.
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * since the groupname is either "default" or the
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * group is a ZFS group, we don't want to keep
25a68471b9ababbc21cfdbbb2866014f34f419ecdougm * groupname. We do want it if it is any other type of
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get correct default prop string. NFS uses "rw", others use
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * sa_emptyshare(sh)
6185db853e024a486ff8837e6784dd290d866112dougm * Free the strings in the non-NULL members of sh.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * sa_update_sharetab_ts(handle)
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * Update the internal timestamp of when sharetab was last
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * changed. This needs to be public for ZFS to get at it.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm sa_handle_impl_t implhandle = (sa_handle_impl_t)handle;
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm if (implhandle != NULL && stat(SA_LEGACY_SHARETAB, &st) == 0)
6185db853e024a486ff8837e6784dd290d866112dougm * sa_update_sharetab(share, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * Update the sharetab file with info from the specified share.
6185db853e024a486ff8837e6784dd290d866112dougm * This could be an update or add.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * Fill in share structure and send it to the kernel.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * We need the timestamp of the sharetab file right
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * after the update was done. This lets us detect a
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * change that made by a different process.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * sa_delete_sharetab(handle, path, proto)
6185db853e024a486ff8837e6784dd290d866112dougm * remove the specified share from sharetab.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougmsa_delete_sharetab(sa_handle_t handle, char *path, char *proto)
a237e38e9161f0acd6451439d4a7dd597e66291dth * Both the path and the proto are
a237e38e9161f0acd6451439d4a7dd597e66291dth * keys into the sharetab.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm if (handle != NULL && stat(SA_LEGACY_SHARETAB, &st) == 0)
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * sa_needs_refresh(handle)
09c9e6dc9b69d10b771bb87e01040ec320a0bfd3Chris Williamson * Returns B_TRUE if the internal cache needs to be refreshed due to a
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * change by another process. B_FALSE returned otherwise.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm sa_handle_impl_t implhandle = (sa_handle_impl_t)handle;
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * If sharetab has changed, then there was an external
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * change. Check sharetab first since it is updated by ZFS as
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * well as sharemgr. This is where external ZFS changes are
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * If sharetab wasn't changed, check whether there were any
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * SMF transactions that modified the config but didn't
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm * initiate a share. This is less common but does happen.
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm prop = scf_simple_prop_get(implhandle->scfhandle->handle,
5b6e0c463149a26dd0aeb4c1f70611c97161ff32dougm "lastupdate");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sa_fix_resource_name(path)
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * Convert invalid characters in a resource name (SMB share name)
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * to underscores ('_'). The list of invalid characters includes
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * control characters and the following:
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * " / \ [ ] : | < > + ; , ? * =
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * The caller must pass a valid path. Leading and trailing slashes
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * are stripped from the path before converting invalid characters.
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * Resource names are restricted to SA_MAX_RESOURCE_NAME characters.
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * Strip leading and trailing /'s.
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego while ((--q, *q == '/'))
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego if (*p == '\0') {
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * Stride over path components until the remaining
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * path is no longer than SA_MAX_RESOURCE_NAME.
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego while ((q != NULL) && (strlen(q) > SA_MAX_RESOURCE_NAME)) {
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * If the path is still longer than SA_MAX_RESOURCE_NAME,
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego * take the trailing SA_MAX_RESOURCE_NAME characters.
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego if ((len = strlen(p)) > SA_MAX_RESOURCE_NAME) {
89dc44ce9705974a8bc4a39f1e878a0491a5be61jose borrego p = strchr(p, '\0') - (SA_MAX_RESOURCE_NAME - 1);