diff options
Diffstat (limited to 'lib/libshare')
-rw-r--r-- | lib/libshare/Makefile.am | 27 | ||||
-rw-r--r-- | lib/libshare/libshare.c | 204 | ||||
-rw-r--r-- | lib/libshare/libshare_impl.h | 48 | ||||
-rw-r--r-- | lib/libshare/nfs.c | 318 | ||||
-rw-r--r-- | lib/libshare/nfs.h | 38 | ||||
-rw-r--r-- | lib/libshare/os/freebsd/nfs.c | 244 | ||||
-rw-r--r-- | lib/libshare/os/freebsd/smb.c | 87 | ||||
-rw-r--r-- | lib/libshare/os/linux/nfs.c | 587 | ||||
-rw-r--r-- | lib/libshare/os/linux/smb.c | 407 | ||||
-rw-r--r-- | lib/libshare/smb.h | 46 |
10 files changed, 0 insertions, 2006 deletions
diff --git a/lib/libshare/Makefile.am b/lib/libshare/Makefile.am deleted file mode 100644 index 48d8cb832428..000000000000 --- a/lib/libshare/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -libshare_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS) -libshare_la_CFLAGS += -fvisibility=hidden - -libshare_la_CPPFLAGS = $(AM_CPPFLAGS) -libshare_la_CPPFLAGS += -I$(srcdir)/%D% - -noinst_LTLIBRARIES += libshare.la -CPPCHECKTARGETS += libshare.la - -libshare_la_SOURCES = \ - %D%/libshare_impl.h \ - %D%/libshare.c \ - %D%/nfs.c \ - %D%/nfs.h \ - %D%/smb.h - -if BUILD_LINUX -libshare_la_SOURCES += \ - %D%/os/linux/nfs.c \ - %D%/os/linux/smb.c -endif - -if BUILD_FREEBSD -libshare_la_SOURCES += \ - %D%/os/freebsd/nfs.c \ - %D%/os/freebsd/smb.c -endif diff --git a/lib/libshare/libshare.c b/lib/libshare/libshare.c deleted file mode 100644 index 3695207e6fe7..000000000000 --- a/lib/libshare/libshare.c +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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, 2022 by Delphix. All rights reserved. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <errno.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 "libshare_impl.h" - -#define init_share(zfsname, path, shareopts) \ - { \ - .sa_zfsname = zfsname, \ - .sa_mountpoint = path, \ - .sa_shareopts = shareopts, \ - } - -#define VALIDATE_PROTOCOL(proto, ...) \ - if ((proto) < 0 || (proto) >= SA_PROTOCOL_COUNT) \ - return __VA_ARGS__ - -const char *const sa_protocol_names[SA_PROTOCOL_COUNT] = { - [SA_PROTOCOL_NFS] = "nfs", - [SA_PROTOCOL_SMB] = "smb", -}; - -static const sa_fstype_t *fstypes[SA_PROTOCOL_COUNT] = - {&libshare_nfs_type, &libshare_smb_type}; - -int -sa_enable_share(const char *zfsname, const char *mountpoint, - const char *shareopts, enum sa_protocol protocol) -{ - VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL); - - const struct sa_share_impl args = - init_share(zfsname, mountpoint, shareopts); - return (fstypes[protocol]->enable_share(&args)); -} - -int -sa_disable_share(const char *mountpoint, enum sa_protocol protocol) -{ - VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL); - - const struct sa_share_impl args = init_share(NULL, mountpoint, NULL); - return (fstypes[protocol]->disable_share(&args)); -} - -boolean_t -sa_is_shared(const char *mountpoint, enum sa_protocol protocol) -{ - VALIDATE_PROTOCOL(protocol, B_FALSE); - - const struct sa_share_impl args = init_share(NULL, mountpoint, NULL); - return (fstypes[protocol]->is_shared(&args)); -} - -void -sa_commit_shares(enum sa_protocol protocol) -{ - /* CSTYLED */ - VALIDATE_PROTOCOL(protocol, ); - - fstypes[protocol]->commit_shares(); -} - -void -sa_truncate_shares(enum sa_protocol protocol) -{ - /* CSTYLED */ - VALIDATE_PROTOCOL(protocol, ); - - if (fstypes[protocol]->truncate_shares != NULL) - fstypes[protocol]->truncate_shares(); -} - -int -sa_validate_shareopts(const char *options, enum sa_protocol protocol) -{ - VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL); - - return (fstypes[protocol]->validate_shareopts(options)); -} - -/* - * sa_errorstr(err) - * - * convert an error value to an error string - */ -const char * -sa_errorstr(int err) -{ - static char errstr[32]; - - switch (err) { - case SA_OK: - return (dgettext(TEXT_DOMAIN, "ok")); - case SA_NO_SUCH_PATH: - return (dgettext(TEXT_DOMAIN, "path doesn't exist")); - case SA_NO_MEMORY: - return (dgettext(TEXT_DOMAIN, "no memory")); - case SA_DUPLICATE_NAME: - return (dgettext(TEXT_DOMAIN, "name in use")); - case SA_BAD_PATH: - return (dgettext(TEXT_DOMAIN, "bad path")); - case SA_NO_SUCH_GROUP: - return (dgettext(TEXT_DOMAIN, "no such group")); - case SA_CONFIG_ERR: - return (dgettext(TEXT_DOMAIN, "configuration error")); - case SA_SYSTEM_ERR: - return (dgettext(TEXT_DOMAIN, "system error")); - case SA_SYNTAX_ERR: - return (dgettext(TEXT_DOMAIN, "syntax error")); - case SA_NO_PERMISSION: - return (dgettext(TEXT_DOMAIN, "no permission")); - case SA_BUSY: - return (dgettext(TEXT_DOMAIN, "busy")); - case SA_NO_SUCH_PROP: - return (dgettext(TEXT_DOMAIN, "no such property")); - case SA_INVALID_NAME: - return (dgettext(TEXT_DOMAIN, "invalid name")); - case SA_INVALID_PROTOCOL: - return (dgettext(TEXT_DOMAIN, "invalid protocol")); - case SA_NOT_ALLOWED: - return (dgettext(TEXT_DOMAIN, "operation not allowed")); - case SA_BAD_VALUE: - return (dgettext(TEXT_DOMAIN, "bad property value")); - case SA_INVALID_SECURITY: - return (dgettext(TEXT_DOMAIN, "invalid security type")); - case SA_NO_SUCH_SECURITY: - return (dgettext(TEXT_DOMAIN, "security type not found")); - case SA_VALUE_CONFLICT: - return (dgettext(TEXT_DOMAIN, "property value conflict")); - case SA_NOT_IMPLEMENTED: - return (dgettext(TEXT_DOMAIN, "not implemented")); - case SA_INVALID_PATH: - return (dgettext(TEXT_DOMAIN, "invalid path")); - case SA_NOT_SUPPORTED: - return (dgettext(TEXT_DOMAIN, "operation not supported")); - case SA_PROP_SHARE_ONLY: - return (dgettext(TEXT_DOMAIN, "property not valid for group")); - case SA_NOT_SHARED: - return (dgettext(TEXT_DOMAIN, "not shared")); - case SA_NO_SUCH_RESOURCE: - return (dgettext(TEXT_DOMAIN, "no such resource")); - case SA_RESOURCE_REQUIRED: - return (dgettext(TEXT_DOMAIN, "resource name required")); - case SA_MULTIPLE_ERROR: - return (dgettext(TEXT_DOMAIN, - "errors from multiple protocols")); - case SA_PATH_IS_SUBDIR: - return (dgettext(TEXT_DOMAIN, "path is a subpath of share")); - case SA_PATH_IS_PARENTDIR: - return (dgettext(TEXT_DOMAIN, "path is parent of a share")); - case SA_NO_SECTION: - return (dgettext(TEXT_DOMAIN, "protocol requires a section")); - case SA_NO_PROPERTIES: - return (dgettext(TEXT_DOMAIN, "properties not found")); - case SA_NO_SUCH_SECTION: - return (dgettext(TEXT_DOMAIN, "section not found")); - case SA_PASSWORD_ENC: - return (dgettext(TEXT_DOMAIN, "passwords must be encrypted")); - case SA_SHARE_EXISTS: - return (dgettext(TEXT_DOMAIN, - "path or file is already shared")); - default: - (void) snprintf(errstr, sizeof (errstr), - dgettext(TEXT_DOMAIN, "unknown %d"), err); - return (errstr); - } -} diff --git a/lib/libshare/libshare_impl.h b/lib/libshare/libshare_impl.h deleted file mode 100644 index 79f081bb8312..000000000000 --- a/lib/libshare/libshare_impl.h +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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) 2019, 2022 by Delphix. All rights reserved. - */ -#ifndef _LIBSPL_LIBSHARE_IMPL_H -#define _LIBSPL_LIBSHARE_IMPL_H - -typedef const struct sa_share_impl { - const char *sa_zfsname; - const char *sa_mountpoint; - const char *sa_shareopts; -} *sa_share_impl_t; - -typedef struct { - int (*const enable_share)(sa_share_impl_t share); - int (*const disable_share)(sa_share_impl_t share); - boolean_t (*const is_shared)(sa_share_impl_t share); - int (*const validate_shareopts)(const char *shareopts); - int (*const commit_shares)(void); - void (*const truncate_shares)(void); -} sa_fstype_t; - -extern const sa_fstype_t libshare_nfs_type, libshare_smb_type; - -#endif /* _LIBSPL_LIBSHARE_IMPL_H */ diff --git a/lib/libshare/nfs.c b/lib/libshare/nfs.c deleted file mode 100644 index e4c5b904f51f..000000000000 --- a/lib/libshare/nfs.c +++ /dev/null @@ -1,318 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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 - */ - - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/file.h> -#include <fcntl.h> -#include <ctype.h> -#include <stdio.h> -#include <errno.h> -#include <libshare.h> -#include <unistd.h> -#include <libzutil.h> -#include "nfs.h" - - -/* - * nfs_exports_[lock|unlock] are used to guard against conconcurrent - * updates to the exports file. Each protocol is responsible for - * providing the necessary locking to ensure consistency. - */ -static int -nfs_exports_lock(const char *name, int *nfs_lock_fd) -{ - int err; - - *nfs_lock_fd = open(name, O_RDWR | O_CREAT | O_CLOEXEC, 0600); - if (*nfs_lock_fd == -1) { - err = errno; - fprintf(stderr, "failed to lock %s: %s\n", name, - zfs_strerror(err)); - return (err); - } - - while ((err = flock(*nfs_lock_fd, LOCK_EX)) != 0 && errno == EINTR) - ; - if (err != 0) { - err = errno; - fprintf(stderr, "failed to lock %s: %s\n", name, - zfs_strerror(err)); - (void) close(*nfs_lock_fd); - *nfs_lock_fd = -1; - return (err); - } - - return (0); -} - -static void -nfs_exports_unlock(const char *name, int *nfs_lock_fd) -{ - verify(*nfs_lock_fd > 0); - - if (flock(*nfs_lock_fd, LOCK_UN) != 0) - fprintf(stderr, "failed to unlock %s: %s\n", - name, zfs_strerror(errno)); - - (void) close(*nfs_lock_fd); - *nfs_lock_fd = -1; -} - -struct tmpfile { - /* - * This only needs to be as wide as ZFS_EXPORTS_FILE and mktemp suffix, - * 64 is more than enough. - */ - char name[64]; - FILE *fp; -}; - -static boolean_t -nfs_init_tmpfile(const char *prefix, const char *mdir, struct tmpfile *tmpf) -{ - if (mdir != NULL && - mkdir(mdir, 0755) < 0 && - errno != EEXIST) { - fprintf(stderr, "failed to create %s: %s\n", - // cppcheck-suppress uninitvar - mdir, zfs_strerror(errno)); - return (B_FALSE); - } - - strlcpy(tmpf->name, prefix, sizeof (tmpf->name)); - strlcat(tmpf->name, ".XXXXXXXX", sizeof (tmpf->name)); - - int fd = mkostemp(tmpf->name, O_CLOEXEC); - if (fd == -1) { - fprintf(stderr, "Unable to create temporary file: %s", - zfs_strerror(errno)); - return (B_FALSE); - } - - tmpf->fp = fdopen(fd, "w+"); - if (tmpf->fp == NULL) { - fprintf(stderr, "Unable to reopen temporary file: %s", - zfs_strerror(errno)); - close(fd); - return (B_FALSE); - } - - return (B_TRUE); -} - -static void -nfs_abort_tmpfile(struct tmpfile *tmpf) -{ - unlink(tmpf->name); - fclose(tmpf->fp); -} - -static int -nfs_fini_tmpfile(const char *exports, struct tmpfile *tmpf) -{ - if (fflush(tmpf->fp) != 0) { - fprintf(stderr, "Failed to write to temporary file: %s\n", - zfs_strerror(errno)); - nfs_abort_tmpfile(tmpf); - return (SA_SYSTEM_ERR); - } - - if (rename(tmpf->name, exports) == -1) { - fprintf(stderr, "Unable to rename %s -> %s: %s\n", - tmpf->name, exports, zfs_strerror(errno)); - nfs_abort_tmpfile(tmpf); - return (SA_SYSTEM_ERR); - } - - (void) fchmod(fileno(tmpf->fp), 0644); - fclose(tmpf->fp); - return (SA_OK); -} - -int -nfs_escape_mountpoint(const char *mp, char **out, boolean_t *need_free) -{ - if (strpbrk(mp, "\t\n\v\f\r \\") == NULL) { - *out = (char *)mp; - *need_free = B_FALSE; - return (SA_OK); - } else { - size_t len = strlen(mp); - *out = malloc(len * 4 + 1); - if (!*out) - return (SA_NO_MEMORY); - *need_free = B_TRUE; - - char *oc = *out; - for (const char *c = mp; c < mp + len; ++c) - if (memchr("\t\n\v\f\r \\", *c, - strlen("\t\n\v\f\r \\"))) { - sprintf(oc, "\\%03hho", *c); - oc += 4; - } else - *oc++ = *c; - *oc = '\0'; - } - - return (SA_OK); -} - -static int -nfs_process_exports(const char *exports, const char *mountpoint, - boolean_t (*cbk)(void *userdata, char *line, boolean_t found_mountpoint), - void *userdata) -{ - int error = SA_OK; - boolean_t cont = B_TRUE; - - FILE *oldfp = fopen(exports, "re"); - if (oldfp != NULL) { - boolean_t need_mp_free; - char *mp; - if ((error = nfs_escape_mountpoint(mountpoint, - &mp, &need_mp_free)) != SA_OK) { - (void) fclose(oldfp); - return (error); - } - - char *buf = NULL, *sep; - size_t buflen = 0, mplen = strlen(mp); - - while (cont && getline(&buf, &buflen, oldfp) != -1) { - if (buf[0] == '\n' || buf[0] == '#') - continue; - - cont = cbk(userdata, buf, - (sep = strpbrk(buf, "\t \n")) != NULL && - sep - buf == mplen && - strncmp(buf, mp, mplen) == 0); - } - free(buf); - if (need_mp_free) - free(mp); - - if (ferror(oldfp) != 0) - error = ferror(oldfp); - - if (fclose(oldfp) != 0) { - fprintf(stderr, "Unable to close file %s: %s\n", - exports, zfs_strerror(errno)); - error = error != SA_OK ? error : SA_SYSTEM_ERR; - } - } - - return (error); -} - -static boolean_t -nfs_copy_entries_cb(void *userdata, char *line, boolean_t found_mountpoint) -{ - FILE *newfp = userdata; - if (!found_mountpoint) - fputs(line, newfp); - return (B_TRUE); -} - -/* - * Copy all entries from the exports file (if it exists) to newfp, - * omitting any entries for the specified mountpoint. - */ -static int -nfs_copy_entries(FILE *newfp, const char *exports, const char *mountpoint) -{ - fputs(FILE_HEADER, newfp); - - int error = nfs_process_exports( - exports, mountpoint, nfs_copy_entries_cb, newfp); - - if (error == SA_OK && ferror(newfp) != 0) - error = ferror(newfp); - - return (error); -} - -int -nfs_toggle_share(const char *lockfile, const char *exports, - const char *expdir, sa_share_impl_t impl_share, - int(*cbk)(sa_share_impl_t impl_share, FILE *tmpfile)) -{ - int error, nfs_lock_fd = -1; - struct tmpfile tmpf; - - if (!nfs_init_tmpfile(exports, expdir, &tmpf)) - return (SA_SYSTEM_ERR); - - error = nfs_exports_lock(lockfile, &nfs_lock_fd); - if (error != 0) { - nfs_abort_tmpfile(&tmpf); - return (error); - } - - error = nfs_copy_entries(tmpf.fp, exports, impl_share->sa_mountpoint); - if (error != SA_OK) - goto fullerr; - - error = cbk(impl_share, tmpf.fp); - if (error != SA_OK) - goto fullerr; - - error = nfs_fini_tmpfile(exports, &tmpf); - nfs_exports_unlock(lockfile, &nfs_lock_fd); - return (error); - -fullerr: - nfs_abort_tmpfile(&tmpf); - nfs_exports_unlock(lockfile, &nfs_lock_fd); - return (error); -} - -void -nfs_reset_shares(const char *lockfile, const char *exports) -{ - int nfs_lock_fd = -1; - - if (nfs_exports_lock(lockfile, &nfs_lock_fd) == 0) { - (void) ! truncate(exports, 0); - nfs_exports_unlock(lockfile, &nfs_lock_fd); - } -} - -static boolean_t -nfs_is_shared_cb(void *userdata, char *line, boolean_t found_mountpoint) -{ - (void) line; - - boolean_t *found = userdata; - *found = found_mountpoint; - return (!found_mountpoint); -} - -boolean_t -nfs_is_shared_impl(const char *exports, sa_share_impl_t impl_share) -{ - boolean_t found = B_FALSE; - nfs_process_exports(exports, impl_share->sa_mountpoint, - nfs_is_shared_cb, &found); - return (found); -} diff --git a/lib/libshare/nfs.h b/lib/libshare/nfs.h deleted file mode 100644 index 1b8ed890d7bd..000000000000 --- a/lib/libshare/nfs.h +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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) 2022 by Delphix. All rights reserved. - */ - -#include "libshare_impl.h" - -#define FILE_HEADER "# !!! DO NOT EDIT THIS FILE MANUALLY !!!\n\n" - -int nfs_escape_mountpoint(const char *mp, char **out, boolean_t *need_free); -boolean_t nfs_is_shared_impl(const char *exports, sa_share_impl_t impl_share); -int nfs_toggle_share(const char *lockfile, const char *exports, - const char *expdir, sa_share_impl_t impl_share, - int(*cbk)(sa_share_impl_t impl_share, FILE *tmpfile)); -void nfs_reset_shares(const char *lockfile, const char *exports); diff --git a/lib/libshare/os/freebsd/nfs.c b/lib/libshare/os/freebsd/nfs.c deleted file mode 100644 index 969194f2881a..000000000000 --- a/lib/libshare/os/freebsd/nfs.c +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -/* - * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (c) 2020, 2022 by Delphix. All rights reserved. - */ - -#include <sys/param.h> -#include <sys/vfs.h> - -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <libutil.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <libintl.h> - -#include <libshare.h> -#include "libshare_impl.h" -#include "nfs.h" - -#define _PATH_MOUNTDPID "/var/run/mountd.pid" -#define ZFS_EXPORTS_FILE "/etc/zfs/exports" -#define ZFS_EXPORTS_LOCK ZFS_EXPORTS_FILE".lock" - -/* - * This function translates options to a format acceptable by exports(5), eg. - * - * -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \ - * zfs.freebsd.org 69.147.83.54 - * - * Accepted input formats: - * - * ro,network=192.168.0.0,mask=255.255.255.0,maproot=0,zfs.freebsd.org - * ro network=192.168.0.0 mask=255.255.255.0 maproot=0 zfs.freebsd.org - * -ro,-network=192.168.0.0,-mask=255.255.255.0,-maproot=0,zfs.freebsd.org - * -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \ - * zfs.freebsd.org - * - * Recognized keywords: - * - * ro, maproot, mapall, mask, network, sec, alldirs, public, webnfs, - * index, quiet - */ -static int -translate_opts(char *oldopts, FILE *out) -{ - static const char *const known_opts[] = { "ro", "maproot", "mapall", - "mask", "network", "sec", "alldirs", "public", "webnfs", "index", - "quiet" }; - char *newopts, *o, *s = NULL; - unsigned int i; - size_t len, newopts_len; - int ret; - - /* - * Calculate the length needed for the worst case of a single - * character option: - * - Add one to strlen(oldopts) so that the trailing nul is counted - * as a separator. - * - Multiply by 3/2 since the single character option plus separator - * is expanded to 3 characters. - * - Add one for the trailing nul. Needed for a single repetition of - * the single character option and certain other cases. - */ - newopts_len = (strlen(oldopts) + 1) * 3 / 2 + 1; - newopts = malloc(newopts_len); - if (newopts == NULL) - return (EOF); - newopts[0] = '\0'; - s = oldopts; - while ((o = strsep(&s, ", ")) != NULL) { - if (o[0] == '-') - o++; - if (o[0] == '\0') - continue; - for (i = 0; i < ARRAY_SIZE(known_opts); ++i) { - len = strlen(known_opts[i]); - if (strncmp(known_opts[i], o, len) == 0 && - (o[len] == '\0' || o[len] == '=')) { - strlcat(newopts, "-", newopts_len); - break; - } - } - strlcat(newopts, o, newopts_len); - strlcat(newopts, " ", newopts_len); - } - ret = fputs(newopts, out); - free(newopts); - return (ret); -} - -static int -nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) -{ - const char *shareopts = impl_share->sa_shareopts; - if (strcmp(shareopts, "on") == 0) - shareopts = ""; - - boolean_t need_free, fnd_semi; - char *mp, *lineopts, *exportopts, *s; - size_t whitelen; - int rc = nfs_escape_mountpoint(impl_share->sa_mountpoint, &mp, - &need_free); - if (rc != SA_OK) - return (rc); - - lineopts = strdup(shareopts); - if (lineopts == NULL) - return (SA_SYSTEM_ERR); - s = lineopts; - fnd_semi = B_FALSE; - while ((exportopts = strsep(&s, ";")) != NULL) { - if (s != NULL) - fnd_semi = B_TRUE; - /* Ignore only whitespace between ';' separated option sets. */ - if (fnd_semi) { - whitelen = strspn(exportopts, "\t "); - if (exportopts[whitelen] == '\0') - continue; - } - if (fputs(mp, tmpfile) == EOF || - fputc('\t', tmpfile) == EOF || - translate_opts(exportopts, tmpfile) == EOF || - fputc('\n', tmpfile) == EOF) { - fprintf(stderr, "failed to write to temporary file\n"); - rc = SA_SYSTEM_ERR; - break; - } - } - free(lineopts); - - if (need_free) - free(mp); - return (rc); -} - -static int -nfs_enable_share(sa_share_impl_t impl_share) -{ - return (nfs_toggle_share( - ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share, - nfs_enable_share_impl)); -} - -static int -nfs_disable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) -{ - (void) impl_share, (void) tmpfile; - return (SA_OK); -} - -static int -nfs_disable_share(sa_share_impl_t impl_share) -{ - return (nfs_toggle_share( - ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share, - nfs_disable_share_impl)); -} - -static boolean_t -nfs_is_shared(sa_share_impl_t impl_share) -{ - return (nfs_is_shared_impl(ZFS_EXPORTS_FILE, impl_share)); -} - -static int -nfs_validate_shareopts(const char *shareopts) -{ - if (strlen(shareopts) == 0) - return (SA_SYNTAX_ERR); - return (SA_OK); -} - -/* - * Commit the shares by restarting mountd. - */ -static int -nfs_commit_shares(void) -{ - struct pidfh *pfh; - pid_t mountdpid; - -start: - pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid); - if (pfh != NULL) { - /* mountd(8) is not running. */ - pidfile_remove(pfh); - return (SA_OK); - } - if (errno != EEXIST) { - /* Cannot open pidfile for some reason. */ - return (SA_SYSTEM_ERR); - } - if (mountdpid == -1) { - /* mountd(8) exists, but didn't write the PID yet */ - usleep(500); - goto start; - } - /* We have mountd(8) PID in mountdpid variable. */ - kill(mountdpid, SIGHUP); - return (SA_OK); -} - -static void -nfs_truncate_shares(void) -{ - nfs_reset_shares(ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE); -} - -const sa_fstype_t libshare_nfs_type = { - .enable_share = nfs_enable_share, - .disable_share = nfs_disable_share, - .is_shared = nfs_is_shared, - - .validate_shareopts = nfs_validate_shareopts, - .commit_shares = nfs_commit_shares, - .truncate_shares = nfs_truncate_shares, -}; diff --git a/lib/libshare/os/freebsd/smb.c b/lib/libshare/os/freebsd/smb.c deleted file mode 100644 index c6b8bdde2d41..000000000000 --- a/lib/libshare/os/freebsd/smb.c +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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) 2020 by Delphix. All rights reserved. - */ - -#include <stdio.h> -#include <libshare.h> -#include "libshare_impl.h" - -/* - * Enables SMB sharing for the specified share. - */ -static int -smb_enable_share(sa_share_impl_t impl_share) -{ - (void) impl_share; - fputs("No SMB support in FreeBSD yet.\n", stderr); - return (SA_NOT_SUPPORTED); -} -/* - * Disables SMB sharing for the specified share. - */ -static int -smb_disable_share(sa_share_impl_t impl_share) -{ - (void) impl_share; - fputs("No SMB support in FreeBSD yet.\n", stderr); - return (SA_NOT_SUPPORTED); -} - -/* - * Checks whether the specified SMB share options are syntactically correct. - */ -static int -smb_validate_shareopts(const char *shareopts) -{ - (void) shareopts; - fputs("No SMB support in FreeBSD yet.\n", stderr); - return (SA_NOT_SUPPORTED); -} - -/* - * Checks whether a share is currently active. - */ -static boolean_t -smb_is_share_active(sa_share_impl_t impl_share) -{ - (void) impl_share; - return (B_FALSE); -} - -static int -smb_update_shares(void) -{ - /* Not implemented */ - return (0); -} - -const sa_fstype_t libshare_smb_type = { - .enable_share = smb_enable_share, - .disable_share = smb_disable_share, - .is_shared = smb_is_share_active, - - .validate_shareopts = smb_validate_shareopts, - .commit_shares = smb_update_shares, -}; diff --git a/lib/libshare/os/linux/nfs.c b/lib/libshare/os/linux/nfs.c deleted file mode 100644 index 6a9bb3788523..000000000000 --- a/lib/libshare/os/linux/nfs.c +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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) 2012 Cyril Plisko. All rights reserved. - * Copyright (c) 2019, 2022 by Delphix. All rights reserved. - */ - -#include <dirent.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <libzfs.h> -#include <libshare.h> -#include "libshare_impl.h" -#include "nfs.h" - -#define ZFS_EXPORTS_DIR "/etc/exports.d" -#define ZFS_EXPORTS_FILE ZFS_EXPORTS_DIR"/zfs.exports" -#define ZFS_EXPORTS_LOCK ZFS_EXPORTS_FILE".lock" - - -static boolean_t nfs_available(void); -static boolean_t exports_available(void); - -typedef int (*nfs_shareopt_callback_t)(const char *opt, const char *value, - void *cookie); - -typedef int (*nfs_host_callback_t)(FILE *tmpfile, const char *sharepath, - const char *host, const char *security, const char *access, void *cookie); - -/* - * Invokes the specified callback function for each Solaris share option - * listed in the specified string. - */ -static int -foreach_nfs_shareopt(const char *shareopts, - nfs_shareopt_callback_t callback, void *cookie) -{ - char *shareopts_dup, *opt, *cur, *value; - int was_nul, error; - - if (shareopts == NULL) - return (SA_OK); - - if (strcmp(shareopts, "on") == 0) - shareopts = "rw,crossmnt"; - - shareopts_dup = strdup(shareopts); - - - if (shareopts_dup == NULL) - return (SA_NO_MEMORY); - - opt = shareopts_dup; - was_nul = 0; - - while (1) { - cur = opt; - - while (*cur != ',' && *cur != '\0') - cur++; - - if (*cur == '\0') - was_nul = 1; - - *cur = '\0'; - - if (cur > opt) { - value = strchr(opt, '='); - - if (value != NULL) { - *value = '\0'; - value++; - } - - error = callback(opt, value, cookie); - - if (error != SA_OK) { - free(shareopts_dup); - return (error); - } - } - - opt = cur + 1; - - if (was_nul) - break; - } - - free(shareopts_dup); - - return (SA_OK); -} - -typedef struct nfs_host_cookie_s { - nfs_host_callback_t callback; - const char *sharepath; - void *cookie; - FILE *tmpfile; - const char *security; -} nfs_host_cookie_t; - -/* - * Helper function for foreach_nfs_host. This function checks whether the - * current share option is a host specification and invokes a callback - * function with information about the host. - */ -static int -foreach_nfs_host_cb(const char *opt, const char *value, void *pcookie) -{ - int error; - const char *access; - char *host_dup, *host, *next, *v6Literal; - nfs_host_cookie_t *udata = (nfs_host_cookie_t *)pcookie; - int cidr_len; - -#ifdef DEBUG - fprintf(stderr, "foreach_nfs_host_cb: key=%s, value=%s\n", opt, value); -#endif - - if (strcmp(opt, "sec") == 0) - udata->security = value; - - if (strcmp(opt, "rw") == 0 || strcmp(opt, "ro") == 0) { - if (value == NULL) - value = "*"; - - access = opt; - - host_dup = strdup(value); - - if (host_dup == NULL) - return (SA_NO_MEMORY); - - host = host_dup; - - do { - if (*host == '[') { - host++; - v6Literal = strchr(host, ']'); - if (v6Literal == NULL) { - free(host_dup); - return (SA_SYNTAX_ERR); - } - if (v6Literal[1] == '\0') { - *v6Literal = '\0'; - next = NULL; - } else if (v6Literal[1] == '/') { - next = strchr(v6Literal + 2, ':'); - if (next == NULL) { - cidr_len = - strlen(v6Literal + 1); - memmove(v6Literal, - v6Literal + 1, - cidr_len); - v6Literal[cidr_len] = '\0'; - } else { - cidr_len = next - v6Literal - 1; - memmove(v6Literal, - v6Literal + 1, - cidr_len); - v6Literal[cidr_len] = '\0'; - next++; - } - } else if (v6Literal[1] == ':') { - *v6Literal = '\0'; - next = v6Literal + 2; - } else { - free(host_dup); - return (SA_SYNTAX_ERR); - } - } else { - next = strchr(host, ':'); - if (next != NULL) { - *next = '\0'; - next++; - } - } - - error = udata->callback(udata->tmpfile, - udata->sharepath, host, udata->security, - access, udata->cookie); - - if (error != SA_OK) { - free(host_dup); - - return (error); - } - - host = next; - } while (host != NULL); - - free(host_dup); - } - - return (SA_OK); -} - -/* - * Invokes a callback function for all NFS hosts that are set for a share. - */ -static int -foreach_nfs_host(sa_share_impl_t impl_share, FILE *tmpfile, - nfs_host_callback_t callback, void *cookie) -{ - nfs_host_cookie_t udata; - - udata.callback = callback; - udata.sharepath = impl_share->sa_mountpoint; - udata.cookie = cookie; - udata.tmpfile = tmpfile; - udata.security = "sys"; - - return (foreach_nfs_shareopt(impl_share->sa_shareopts, - foreach_nfs_host_cb, &udata)); -} - -/* - * Converts a Solaris NFS host specification to its Linux equivalent. - */ -static const char * -get_linux_hostspec(const char *solaris_hostspec) -{ - /* - * For now we just support CIDR masks (e.g. @192.168.0.0/16) and host - * wildcards (e.g. *.example.org). - */ - if (solaris_hostspec[0] == '@') { - /* - * Solaris host specifier, e.g. @192.168.0.0/16; we just need - * to skip the @ in this case - */ - return (solaris_hostspec + 1); - } else { - return (solaris_hostspec); - } -} - -/* - * Adds a Linux share option to an array of NFS options. - */ -static int -add_linux_shareopt(char **plinux_opts, const char *key, const char *value) -{ - size_t len = 0; - char *new_linux_opts; - - if (*plinux_opts != NULL) - len = strlen(*plinux_opts); - - new_linux_opts = realloc(*plinux_opts, len + 1 + strlen(key) + - (value ? 1 + strlen(value) : 0) + 1); - - if (new_linux_opts == NULL) - return (SA_NO_MEMORY); - - new_linux_opts[len] = '\0'; - - if (len > 0) - strcat(new_linux_opts, ","); - - strcat(new_linux_opts, key); - - if (value != NULL) { - strcat(new_linux_opts, "="); - strcat(new_linux_opts, value); - } - - *plinux_opts = new_linux_opts; - - return (SA_OK); -} - -static int string_cmp(const void *lhs, const void *rhs) { - const char *const *l = lhs, *const *r = rhs; - return (strcmp(*l, *r)); -} - -/* - * Validates and converts a single Solaris share option to its Linux - * equivalent. - */ -static int -get_linux_shareopts_cb(const char *key, const char *value, void *cookie) -{ - /* This list must remain sorted, since we bsearch() it */ - static const char *const valid_keys[] = { "all_squash", "anongid", - "anonuid", "async", "auth_nlm", "crossmnt", "fsid", "fsuid", "hide", - "insecure", "insecure_locks", "mountpoint", "mp", "no_acl", - "no_all_squash", "no_auth_nlm", "no_root_squash", - "no_subtree_check", "no_wdelay", "nohide", "refer", "replicas", - "root_squash", "secure", "secure_locks", "subtree_check", "sync", - "wdelay" }; - - char **plinux_opts = (char **)cookie; - char *host, *val_dup, *literal, *next; - - if (strcmp(key, "sec") == 0) - return (SA_OK); - - if (strcmp(key, "ro") == 0 || strcmp(key, "rw") == 0) { - if (value == NULL || strlen(value) == 0) - return (SA_OK); - val_dup = strdup(value); - host = val_dup; - if (host == NULL) - return (SA_NO_MEMORY); - do { - if (*host == '[') { - host++; - literal = strchr(host, ']'); - if (literal == NULL) { - free(val_dup); - return (SA_SYNTAX_ERR); - } - if (literal[1] == '\0') - next = NULL; - else if (literal[1] == '/') { - next = strchr(literal + 2, ':'); - if (next != NULL) - ++next; - } else if (literal[1] == ':') - next = literal + 2; - else { - free(val_dup); - return (SA_SYNTAX_ERR); - } - } else { - next = strchr(host, ':'); - if (next != NULL) - ++next; - } - host = next; - } while (host != NULL); - free(val_dup); - return (SA_OK); - } - - if (strcmp(key, "anon") == 0) - key = "anonuid"; - - if (strcmp(key, "root_mapping") == 0) { - (void) add_linux_shareopt(plinux_opts, "root_squash", NULL); - key = "anonuid"; - } - - if (strcmp(key, "nosub") == 0) - key = "subtree_check"; - - if (bsearch(&key, valid_keys, ARRAY_SIZE(valid_keys), - sizeof (*valid_keys), string_cmp) == NULL) - return (SA_SYNTAX_ERR); - - (void) add_linux_shareopt(plinux_opts, key, value); - - return (SA_OK); -} - -/* - * Takes a string containing Solaris share options (e.g. "sync,no_acl") and - * converts them to a NULL-terminated array of Linux NFS options. - */ -static int -get_linux_shareopts(const char *shareopts, char **plinux_opts) -{ - int error; - - assert(plinux_opts != NULL); - - *plinux_opts = NULL; - - /* no_subtree_check - Default as of nfs-utils v1.1.0 */ - (void) add_linux_shareopt(plinux_opts, "no_subtree_check", NULL); - - /* mountpoint - Restrict exports to ZFS mountpoints */ - (void) add_linux_shareopt(plinux_opts, "mountpoint", NULL); - - error = foreach_nfs_shareopt(shareopts, get_linux_shareopts_cb, - plinux_opts); - - if (error != SA_OK) { - free(*plinux_opts); - *plinux_opts = NULL; - } - - return (error); -} - -/* - * This function populates an entry into /etc/exports.d/zfs.exports. - * This file is consumed by the linux nfs server so that zfs shares are - * automatically exported upon boot or whenever the nfs server restarts. - */ -static int -nfs_add_entry(FILE *tmpfile, const char *sharepath, - const char *host, const char *security, const char *access_opts, - void *pcookie) -{ - const char *linux_opts = (const char *)pcookie; - - if (linux_opts == NULL) - linux_opts = ""; - - boolean_t need_free; - char *mp; - int rc = nfs_escape_mountpoint(sharepath, &mp, &need_free); - if (rc != SA_OK) - return (rc); - if (fprintf(tmpfile, "%s %s(sec=%s,%s,%s)\n", mp, - get_linux_hostspec(host), security, access_opts, - linux_opts) < 0) { - fprintf(stderr, "failed to write to temporary file\n"); - rc = SA_SYSTEM_ERR; - } - - if (need_free) - free(mp); - return (rc); -} - -/* - * Enables NFS sharing for the specified share. - */ -static int -nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) -{ - char *linux_opts = NULL; - int error = get_linux_shareopts(impl_share->sa_shareopts, &linux_opts); - if (error != SA_OK) - return (error); - - error = foreach_nfs_host(impl_share, tmpfile, nfs_add_entry, - linux_opts); - free(linux_opts); - return (error); -} - -static int -nfs_enable_share(sa_share_impl_t impl_share) -{ - if (!nfs_available()) - return (SA_SYSTEM_ERR); - - return (nfs_toggle_share( - ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, ZFS_EXPORTS_DIR, impl_share, - nfs_enable_share_impl)); -} - -/* - * Disables NFS sharing for the specified share. - */ -static int -nfs_disable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) -{ - (void) impl_share, (void) tmpfile; - return (SA_OK); -} - -static int -nfs_disable_share(sa_share_impl_t impl_share) -{ - if (!nfs_available()) - return (SA_OK); - - return (nfs_toggle_share( - ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, ZFS_EXPORTS_DIR, impl_share, - nfs_disable_share_impl)); -} - -static boolean_t -nfs_is_shared(sa_share_impl_t impl_share) -{ - if (!nfs_available()) - return (SA_SYSTEM_ERR); - - return (nfs_is_shared_impl(ZFS_EXPORTS_FILE, impl_share)); -} - -/* - * Checks whether the specified NFS share options are syntactically correct. - */ -static int -nfs_validate_shareopts(const char *shareopts) -{ - char *linux_opts = NULL; - - if (strlen(shareopts) == 0) - return (SA_SYNTAX_ERR); - - int error = get_linux_shareopts(shareopts, &linux_opts); - if (error != SA_OK) - return (error); - - free(linux_opts); - return (SA_OK); -} - -static int -nfs_commit_shares(void) -{ - if (!nfs_available()) - return (SA_SYSTEM_ERR); - - char *argv[] = { - (char *)"/usr/sbin/exportfs", - (char *)"-ra", - NULL - }; - - return (libzfs_run_process(argv[0], argv, 0)); -} - -static void -nfs_truncate_shares(void) -{ - if (!exports_available()) - return; - nfs_reset_shares(ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE); -} - -const sa_fstype_t libshare_nfs_type = { - .enable_share = nfs_enable_share, - .disable_share = nfs_disable_share, - .is_shared = nfs_is_shared, - - .validate_shareopts = nfs_validate_shareopts, - .commit_shares = nfs_commit_shares, - .truncate_shares = nfs_truncate_shares, -}; - -static boolean_t -nfs_available(void) -{ - static int avail; - - if (!avail) { - if (access("/usr/sbin/exportfs", F_OK) != 0) - avail = -1; - else - avail = 1; - } - - return (avail == 1); -} - -static boolean_t -exports_available(void) -{ - static int avail; - - if (!avail) { - if (access(ZFS_EXPORTS_DIR, F_OK) != 0) - avail = -1; - else - avail = 1; - } - - return (avail == 1); -} diff --git a/lib/libshare/os/linux/smb.c b/lib/libshare/os/linux/smb.c deleted file mode 100644 index 40996ecc8f89..000000000000 --- a/lib/libshare/os/linux/smb.c +++ /dev/null @@ -1,407 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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,2012 Turbo Fredriksson <turbo@bayour.com>, based on nfs.c - * by Gunnar Beutner - * Copyright (c) 2019, 2020 by Delphix. All rights reserved. - * - * This is an addition to the zfs device driver to add, modify and remove SMB - * shares using the 'net share' command that comes with Samba. - * - * TESTING - * Make sure that samba listens to 'localhost' (127.0.0.1) and that the options - * 'usershare max shares' and 'usershare owner only' have been reviewed/set - * accordingly (see zfs(8) for information). - * - * Once configuration in samba have been done, test that this - * works with the following three commands (in this case, my ZFS - * filesystem is called 'share/Test1'): - * - * (root)# net -U root -S 127.0.0.1 usershare add Test1 /share/Test1 \ - * "Comment: /share/Test1" "Everyone:F" - * (root)# net usershare list | grep -i test - * (root)# net -U root -S 127.0.0.1 usershare delete Test1 - * - * The first command will create a user share that gives everyone full access. - * To limit the access below that, use normal UNIX commands (chmod, chown etc). - */ - -#include <time.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <sys/wait.h> -#include <unistd.h> -#include <dirent.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <libzfs.h> -#include <libshare.h> -#include "libshare_impl.h" -#include "smb.h" - -static boolean_t smb_available(void); - -static smb_share_t *smb_shares; -static int smb_disable_share(sa_share_impl_t impl_share); -static boolean_t smb_is_share_active(sa_share_impl_t impl_share); - -/* - * Retrieve the list of SMB shares. - */ -static int -smb_retrieve_shares(void) -{ - int rc = SA_OK; - char file_path[PATH_MAX], line[512], *token, *key, *value; - char *dup_value = NULL, *path = NULL, *comment = NULL, *name = NULL; - char *guest_ok = NULL; - DIR *shares_dir; - FILE *share_file_fp = NULL; - struct dirent *directory; - struct stat eStat; - smb_share_t *shares, *new_shares = NULL; - - /* opendir(), stat() */ - shares_dir = opendir(SHARE_DIR); - if (shares_dir == NULL) - return (SA_SYSTEM_ERR); - - /* Go through the directory, looking for shares */ - while ((directory = readdir(shares_dir))) { - int fd; - - if (directory->d_name[0] == '.') - continue; - - snprintf(file_path, sizeof (file_path), - "%s/%s", SHARE_DIR, directory->d_name); - - if ((fd = open(file_path, O_RDONLY | O_CLOEXEC)) == -1) { - rc = SA_SYSTEM_ERR; - goto out; - } - - if (fstat(fd, &eStat) == -1) { - close(fd); - rc = SA_SYSTEM_ERR; - goto out; - } - - if (!S_ISREG(eStat.st_mode)) { - close(fd); - continue; - } - - if ((share_file_fp = fdopen(fd, "r")) == NULL) { - close(fd); - rc = SA_SYSTEM_ERR; - goto out; - } - - name = strdup(directory->d_name); - if (name == NULL) { - rc = SA_NO_MEMORY; - goto out; - } - - while (fgets(line, sizeof (line), share_file_fp)) { - if (line[0] == '#') - continue; - - /* Trim trailing new-line character(s). */ - while (line[strlen(line) - 1] == '\r' || - line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; - - /* Split the line in two, separated by '=' */ - token = strchr(line, '='); - if (token == NULL) - continue; - - key = line; - value = token + 1; - *token = '\0'; - - dup_value = strdup(value); - if (dup_value == NULL) { - rc = SA_NO_MEMORY; - goto out; - } - - if (strcmp(key, "path") == 0) { - free(path); - path = dup_value; - } else if (strcmp(key, "comment") == 0) { - free(comment); - comment = dup_value; - } else if (strcmp(key, "guest_ok") == 0) { - free(guest_ok); - guest_ok = dup_value; - } else - free(dup_value); - - dup_value = NULL; - - if (path == NULL || comment == NULL || guest_ok == NULL) - continue; /* Incomplete share definition */ - else { - shares = (smb_share_t *) - malloc(sizeof (smb_share_t)); - if (shares == NULL) { - rc = SA_NO_MEMORY; - goto out; - } - - (void) strlcpy(shares->name, name, - sizeof (shares->name)); - - (void) strlcpy(shares->path, path, - sizeof (shares->path)); - - (void) strlcpy(shares->comment, comment, - sizeof (shares->comment)); - - shares->guest_ok = atoi(guest_ok); - - shares->next = new_shares; - new_shares = shares; - - free(path); - free(comment); - free(guest_ok); - - path = NULL; - comment = NULL; - guest_ok = NULL; - } - } - -out: - if (share_file_fp != NULL) { - fclose(share_file_fp); - share_file_fp = NULL; - } - - free(name); - free(path); - free(comment); - free(guest_ok); - - name = NULL; - path = NULL; - comment = NULL; - guest_ok = NULL; - } - closedir(shares_dir); - - smb_shares = new_shares; - - return (rc); -} - -/* - * Used internally by smb_enable_share to enable sharing for a single host. - */ -static int -smb_enable_share_one(const char *sharename, const char *sharepath) -{ - char name[SMB_NAME_MAX], comment[SMB_COMMENT_MAX]; - - /* Support ZFS share name regexp '[[:alnum:]_-.: ]' */ - strlcpy(name, sharename, sizeof (name)); - for (char *itr = name; *itr != '\0'; ++itr) - switch (*itr) { - case '/': - case '-': - case ':': - case ' ': - *itr = '_'; - } - - /* - * CMD: net -S NET_CMD_ARG_HOST usershare add Test1 /share/Test1 \ - * "Comment" "Everyone:F" - */ - snprintf(comment, sizeof (comment), "Comment: %s", sharepath); - - char *argv[] = { - (char *)NET_CMD_PATH, - (char *)"-S", - (char *)NET_CMD_ARG_HOST, - (char *)"usershare", - (char *)"add", - name, - (char *)sharepath, - comment, - (char *)"Everyone:F", - NULL, - }; - - if (libzfs_run_process(argv[0], argv, 0) != 0) - return (SA_SYSTEM_ERR); - - /* Reload the share file */ - (void) smb_retrieve_shares(); - - return (SA_OK); -} - -/* - * Enables SMB sharing for the specified share. - */ -static int -smb_enable_share(sa_share_impl_t impl_share) -{ - if (!smb_available()) - return (SA_SYSTEM_ERR); - - if (smb_is_share_active(impl_share)) - smb_disable_share(impl_share); - - if (impl_share->sa_shareopts == NULL) /* on/off */ - return (SA_SYSTEM_ERR); - - if (strcmp(impl_share->sa_shareopts, "off") == 0) - return (SA_OK); - - /* Magic: Enable (i.e., 'create new') share */ - return (smb_enable_share_one(impl_share->sa_zfsname, - impl_share->sa_mountpoint)); -} - -/* - * Used internally by smb_disable_share to disable sharing for a single host. - */ -static int -smb_disable_share_one(const char *sharename) -{ - /* CMD: net -S NET_CMD_ARG_HOST usershare delete Test1 */ - char *argv[] = { - (char *)NET_CMD_PATH, - (char *)"-S", - (char *)NET_CMD_ARG_HOST, - (char *)"usershare", - (char *)"delete", - (char *)sharename, - NULL, - }; - - if (libzfs_run_process(argv[0], argv, 0) != 0) - return (SA_SYSTEM_ERR); - else - return (SA_OK); -} - -/* - * Disables SMB sharing for the specified share. - */ -static int -smb_disable_share(sa_share_impl_t impl_share) -{ - if (!smb_available()) { - /* - * The share can't possibly be active, so nothing - * needs to be done to disable it. - */ - return (SA_OK); - } - - for (const smb_share_t *i = smb_shares; i != NULL; i = i->next) - if (strcmp(impl_share->sa_mountpoint, i->path) == 0) - return (smb_disable_share_one(i->name)); - - return (SA_OK); -} - -/* - * Checks whether the specified SMB share options are syntactically correct. - */ -static int -smb_validate_shareopts(const char *shareopts) -{ - /* TODO: Accept 'name' and sec/acl (?) */ - if ((strcmp(shareopts, "off") == 0) || (strcmp(shareopts, "on") == 0)) - return (SA_OK); - - return (SA_SYNTAX_ERR); -} - -/* - * Checks whether a share is currently active. - */ -static boolean_t -smb_is_share_active(sa_share_impl_t impl_share) -{ - if (!smb_available()) - return (B_FALSE); - - /* Retrieve the list of (possible) active shares */ - smb_retrieve_shares(); - - for (const smb_share_t *i = smb_shares; i != NULL; i = i->next) - if (strcmp(impl_share->sa_mountpoint, i->path) == 0) - return (B_TRUE); - - return (B_FALSE); -} - -static int -smb_update_shares(void) -{ - /* Not implemented */ - return (0); -} - -const sa_fstype_t libshare_smb_type = { - .enable_share = smb_enable_share, - .disable_share = smb_disable_share, - .is_shared = smb_is_share_active, - - .validate_shareopts = smb_validate_shareopts, - .commit_shares = smb_update_shares, -}; - -/* - * Provides a convenient wrapper for determining SMB availability - */ -static boolean_t -smb_available(void) -{ - static int avail; - - if (!avail) { - struct stat statbuf; - - if (access(NET_CMD_PATH, F_OK) != 0 || - lstat(SHARE_DIR, &statbuf) != 0 || - !S_ISDIR(statbuf.st_mode)) - avail = -1; - else - avail = 1; - } - - return (avail == 1); -} diff --git a/lib/libshare/smb.h b/lib/libshare/smb.h deleted file mode 100644 index 79e67bd7c45a..000000000000 --- a/lib/libshare/smb.h +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: CDDL-1.0 -/* - * 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 https://opensource.org/licenses/CDDL-1.0. - * 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) 2011 Turbo Fredriksson <turbo@bayour.com>. - */ - -/* - * The maximum SMB share name seems to be 254 characters, though good - * references are hard to find. - */ - -#define SMB_NAME_MAX 255 -#define SMB_COMMENT_MAX 255 - -#define SHARE_DIR "/var/lib/samba/usershares" -#define NET_CMD_PATH "/usr/bin/net" -#define NET_CMD_ARG_HOST "127.0.0.1" - -typedef struct smb_share_s { - char name[SMB_NAME_MAX]; /* Share name */ - char path[PATH_MAX]; /* Share path */ - char comment[SMB_COMMENT_MAX]; /* Share's comment */ - boolean_t guest_ok; /* 'y' or 'n' */ - - struct smb_share_s *next; -} smb_share_t; |