diff options
Diffstat (limited to 'lib/libshare/libshare.c')
-rw-r--r-- | lib/libshare/libshare.c | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/lib/libshare/libshare.c b/lib/libshare/libshare.c new file mode 100644 index 000000000000..d32a282a36e3 --- /dev/null +++ b/lib/libshare/libshare.c @@ -0,0 +1,366 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 Gunnar Beutner + * Copyright (c) 2018, 2020 by Delphix. All rights reserved. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <strings.h> +#include <libintl.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <libzfs.h> +#include <libshare.h> +#include "libzfs_impl.h" +#include "libshare_impl.h" +#include "nfs.h" +#include "smb.h" + +static sa_share_impl_t alloc_share(const char *zfsname, const char *path); +static void free_share(sa_share_impl_t share); + +static int fstypes_count; +static sa_fstype_t *fstypes; + +sa_fstype_t * +register_fstype(const char *name, const sa_share_ops_t *ops) +{ + sa_fstype_t *fstype; + + fstype = calloc(1, sizeof (sa_fstype_t)); + + if (fstype == NULL) + return (NULL); + + fstype->name = name; + fstype->ops = ops; + fstype->fsinfo_index = fstypes_count; + + fstypes_count++; + + fstype->next = fstypes; + fstypes = fstype; + + return (fstype); +} + +__attribute__((constructor)) static void +libshare_init(void) +{ + libshare_nfs_init(); + libshare_smb_init(); +} + +int +sa_enable_share(const char *zfsname, const char *mountpoint, + const char *shareopts, char *protocol) +{ + int rc, ret = SA_OK; + boolean_t found_protocol = B_FALSE; + sa_fstype_t *fstype; + + sa_share_impl_t impl_share = alloc_share(zfsname, mountpoint); + if (impl_share == NULL) + return (SA_NO_MEMORY); + + fstype = fstypes; + while (fstype != NULL) { + if (strcmp(fstype->name, protocol) == 0) { + + rc = fstype->ops->update_shareopts(impl_share, + shareopts); + if (rc != SA_OK) + break; + + rc = fstype->ops->enable_share(impl_share); + if (rc != SA_OK) + ret = rc; + + found_protocol = B_TRUE; + } + + fstype = fstype->next; + } + free_share(impl_share); + + return (found_protocol ? ret : SA_INVALID_PROTOCOL); +} + +int +sa_disable_share(const char *mountpoint, char *protocol) +{ + int rc, ret = SA_OK; + boolean_t found_protocol = B_FALSE; + sa_fstype_t *fstype; + + sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); + if (impl_share == NULL) + return (SA_NO_MEMORY); + + fstype = fstypes; + while (fstype != NULL) { + if (strcmp(fstype->name, protocol) == 0) { + + rc = fstype->ops->disable_share(impl_share); + if (rc != SA_OK) + ret = rc; + + found_protocol = B_TRUE; + } + + fstype = fstype->next; + } + free_share(impl_share); + + return (found_protocol ? ret : SA_INVALID_PROTOCOL); +} + +boolean_t +sa_is_shared(const char *mountpoint, char *protocol) +{ + sa_fstype_t *fstype; + boolean_t ret = B_FALSE; + + /* guid value is not used */ + sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); + if (impl_share == NULL) + return (B_FALSE); + + fstype = fstypes; + while (fstype != NULL) { + if (strcmp(fstype->name, protocol) == 0) { + ret = fstype->ops->is_shared(impl_share); + } + fstype = fstype->next; + } + free_share(impl_share); + return (ret); +} + +void +sa_commit_shares(const char *protocol) +{ + sa_fstype_t *fstype = fstypes; + while (fstype != NULL) { + if (strcmp(fstype->name, protocol) == 0) + fstype->ops->commit_shares(); + fstype = fstype->next; + } +} + +/* + * sa_errorstr(err) + * + * convert an error value to an error string + */ +char * +sa_errorstr(int err) +{ + static char errstr[32]; + char *ret = NULL; + + switch (err) { + case SA_OK: + ret = dgettext(TEXT_DOMAIN, "ok"); + break; + case SA_NO_SUCH_PATH: + ret = dgettext(TEXT_DOMAIN, "path doesn't exist"); + break; + case SA_NO_MEMORY: + ret = dgettext(TEXT_DOMAIN, "no memory"); + break; + case SA_DUPLICATE_NAME: + ret = dgettext(TEXT_DOMAIN, "name in use"); + break; + case SA_BAD_PATH: + ret = dgettext(TEXT_DOMAIN, "bad path"); + break; + case SA_NO_SUCH_GROUP: + ret = dgettext(TEXT_DOMAIN, "no such group"); + break; + case SA_CONFIG_ERR: + ret = dgettext(TEXT_DOMAIN, "configuration error"); + break; + case SA_SYSTEM_ERR: + ret = dgettext(TEXT_DOMAIN, "system error"); + break; + case SA_SYNTAX_ERR: + ret = dgettext(TEXT_DOMAIN, "syntax error"); + break; + case SA_NO_PERMISSION: + ret = dgettext(TEXT_DOMAIN, "no permission"); + break; + case SA_BUSY: + ret = dgettext(TEXT_DOMAIN, "busy"); + break; + case SA_NO_SUCH_PROP: + ret = dgettext(TEXT_DOMAIN, "no such property"); + break; + case SA_INVALID_NAME: + ret = dgettext(TEXT_DOMAIN, "invalid name"); + break; + case SA_INVALID_PROTOCOL: + ret = dgettext(TEXT_DOMAIN, "invalid protocol"); + break; + case SA_NOT_ALLOWED: + ret = dgettext(TEXT_DOMAIN, "operation not allowed"); + break; + case SA_BAD_VALUE: + ret = dgettext(TEXT_DOMAIN, "bad property value"); + break; + case SA_INVALID_SECURITY: + ret = dgettext(TEXT_DOMAIN, "invalid security type"); + break; + case SA_NO_SUCH_SECURITY: + ret = dgettext(TEXT_DOMAIN, "security type not found"); + break; + case SA_VALUE_CONFLICT: + ret = dgettext(TEXT_DOMAIN, "property value conflict"); + break; + case SA_NOT_IMPLEMENTED: + ret = dgettext(TEXT_DOMAIN, "not implemented"); + break; + case SA_INVALID_PATH: + ret = dgettext(TEXT_DOMAIN, "invalid path"); + break; + case SA_NOT_SUPPORTED: + ret = dgettext(TEXT_DOMAIN, "operation not supported"); + break; + case SA_PROP_SHARE_ONLY: + ret = dgettext(TEXT_DOMAIN, "property not valid for group"); + break; + case SA_NOT_SHARED: + ret = dgettext(TEXT_DOMAIN, "not shared"); + break; + case SA_NO_SUCH_RESOURCE: + ret = dgettext(TEXT_DOMAIN, "no such resource"); + break; + case SA_RESOURCE_REQUIRED: + ret = dgettext(TEXT_DOMAIN, "resource name required"); + break; + case SA_MULTIPLE_ERROR: + ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols"); + break; + case SA_PATH_IS_SUBDIR: + ret = dgettext(TEXT_DOMAIN, "path is a subpath of share"); + break; + case SA_PATH_IS_PARENTDIR: + ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); + break; + case SA_NO_SECTION: + ret = dgettext(TEXT_DOMAIN, "protocol requires a section"); + break; + case SA_NO_PROPERTIES: + ret = dgettext(TEXT_DOMAIN, "properties not found"); + break; + case SA_NO_SUCH_SECTION: + ret = dgettext(TEXT_DOMAIN, "section not found"); + break; + case SA_PASSWORD_ENC: + ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted"); + break; + case SA_SHARE_EXISTS: + ret = dgettext(TEXT_DOMAIN, "path or file is already shared"); + break; + default: + (void) snprintf(errstr, sizeof (errstr), + dgettext(TEXT_DOMAIN, "unknown %d"), err); + ret = errstr; + } + return (ret); +} + +int +sa_validate_shareopts(char *options, char *proto) +{ + sa_fstype_t *fstype; + + fstype = fstypes; + while (fstype != NULL) { + if (strcmp(fstype->name, proto) != 0) { + fstype = fstype->next; + continue; + } + + return (fstype->ops->validate_shareopts(options)); + } + + return (SA_INVALID_PROTOCOL); +} + +static sa_share_impl_t +alloc_share(const char *zfsname, const char *mountpoint) +{ + sa_share_impl_t impl_share; + + impl_share = calloc(1, sizeof (struct sa_share_impl)); + + if (impl_share == NULL) + return (NULL); + + if (mountpoint != NULL && + ((impl_share->sa_mountpoint = strdup(mountpoint)) == NULL)) { + free(impl_share); + return (NULL); + } + + if (zfsname != NULL && + ((impl_share->sa_zfsname = strdup(zfsname)) == NULL)) { + free(impl_share->sa_mountpoint); + free(impl_share); + return (NULL); + } + + impl_share->sa_fsinfo = calloc(fstypes_count, + sizeof (sa_share_fsinfo_t)); + if (impl_share->sa_fsinfo == NULL) { + free(impl_share->sa_mountpoint); + free(impl_share->sa_zfsname); + free(impl_share); + return (NULL); + } + + return (impl_share); +} + +static void +free_share(sa_share_impl_t impl_share) +{ + sa_fstype_t *fstype; + + fstype = fstypes; + while (fstype != NULL) { + fstype->ops->clear_shareopts(impl_share); + fstype = fstype->next; + } + + free(impl_share->sa_mountpoint); + free(impl_share->sa_zfsname); + free(impl_share->sa_fsinfo); + free(impl_share); +} |