From 8357bbff1fdf99554d6a296dee4841e41d87b7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sun, 11 Apr 2021 19:42:07 +0200 Subject: [PATCH] libshare: nfs: commonify nfs_{init,fini}_tmpfile(), nfs_disable_share() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also open the temp file cloexec Reviewed-by: Brian Behlendorf Reviewed-by: George Wilson Signed-off-by: Ahelenia ZiemiaƄska Closes #11886 --- lib/libshare/libshare_impl.h | 4 ++ lib/libshare/nfs.c | 77 +++++++++++++++++++++++++++++++++++ lib/libshare/nfs.h | 9 ++++ lib/libshare/os/freebsd/nfs.c | 68 +++---------------------------- lib/libshare/os/linux/nfs.c | 75 +++------------------------------- 5 files changed, 101 insertions(+), 132 deletions(-) diff --git a/lib/libshare/libshare_impl.h b/lib/libshare/libshare_impl.h index cc5ef4008..63a690753 100644 --- a/lib/libshare/libshare_impl.h +++ b/lib/libshare/libshare_impl.h @@ -24,6 +24,8 @@ * Copyright (c) 2011 Gunnar Beutner * Copyright (c) 2019, 2020 by Delphix. All rights reserved. */ +#ifndef _LIBSPL_LIBSHARE_IMPL_H +#define _LIBSPL_LIBSHARE_IMPL_H typedef struct sa_share_fsinfo { char *shareopts; @@ -59,3 +61,5 @@ typedef struct sa_fstype { } sa_fstype_t; sa_fstype_t *register_fstype(const char *name, const sa_share_ops_t *ops); + +#endif /* _LIBSPL_LIBSHARE_IMPL_H */ diff --git a/lib/libshare/nfs.c b/lib/libshare/nfs.c index 7657c9d72..bdf5e5483 100644 --- a/lib/libshare/nfs.c +++ b/lib/libshare/nfs.c @@ -22,8 +22,11 @@ #include #include +#include #include #include +#include +#include #include "nfs.h" @@ -71,3 +74,77 @@ nfs_exports_unlock(const char *name) (void) close(nfs_lock_fd); nfs_lock_fd = -1; } + +__attribute__((visibility("hidden"))) char * +nfs_init_tmpfile(const char *prefix, const char *mdir) +{ + char *tmpfile = NULL; + struct stat sb; + + if (mdir != NULL && + stat(mdir, &sb) < 0 && + mkdir(mdir, 0755) < 0) { + fprintf(stderr, "failed to create %s: %s\n", + mdir, strerror(errno)); + return (NULL); + } + + if (asprintf(&tmpfile, "%s.XXXXXXXX", prefix) == -1) { + fprintf(stderr, "Unable to allocate temporary file\n"); + return (NULL); + } + + int fd = mkostemp(tmpfile, O_CLOEXEC); + if (fd == -1) { + fprintf(stderr, "Unable to create temporary file: %s", + strerror(errno)); + free(tmpfile); + return (NULL); + } + close(fd); + return (tmpfile); +} + +__attribute__((visibility("hidden"))) int +nfs_fini_tmpfile(const char *exports, char *tmpfile) +{ + if (rename(tmpfile, exports) == -1) { + fprintf(stderr, "Unable to rename %s: %s\n", tmpfile, + strerror(errno)); + unlink(tmpfile); + free(tmpfile); + return (SA_SYSTEM_ERR); + } + free(tmpfile); + return (SA_OK); +} + +__attribute__((visibility("hidden"))) int +nfs_disable_share_impl(const char *lockfile, const char *exports, + const char *expdir, sa_share_impl_t impl_share) +{ + int error; + char *filename; + + if ((filename = nfs_init_tmpfile(exports, expdir)) == NULL) + return (SA_SYSTEM_ERR); + + error = nfs_exports_lock(lockfile); + if (error != 0) { + unlink(filename); + free(filename); + return (error); + } + + error = nfs_copy_entries(filename, impl_share->sa_mountpoint); + if (error != SA_OK) { + unlink(filename); + free(filename); + nfs_exports_unlock(lockfile); + return (error); + } + + error = nfs_fini_tmpfile(exports, filename); + nfs_exports_unlock(lockfile); + return (error); +} diff --git a/lib/libshare/nfs.h b/lib/libshare/nfs.h index 79c28bb7f..9eca798db 100644 --- a/lib/libshare/nfs.h +++ b/lib/libshare/nfs.h @@ -24,9 +24,18 @@ * Copyright (c) 2011 Gunnar Beutner */ +#include "libshare_impl.h" + #define FILE_HEADER "# !!! DO NOT EDIT THIS FILE MANUALLY !!!\n\n" void libshare_nfs_init(void); int nfs_exports_lock(const char *name); void nfs_exports_unlock(const char *name); + +char *nfs_init_tmpfile(const char *prefix, const char *mdir); +int nfs_fini_tmpfile(const char *exports, char *tmpfile); + +int nfs_copy_entries(char *filename, const char *mountpoint); +int nfs_disable_share_impl(const char *lockfile, const char *exports, + const char *expdir, sa_share_impl_t impl_share); diff --git a/lib/libshare/os/freebsd/nfs.c b/lib/libshare/os/freebsd/nfs.c index 40e3d8bbf..6f8955cfa 100644 --- a/lib/libshare/os/freebsd/nfs.c +++ b/lib/libshare/os/freebsd/nfs.c @@ -143,47 +143,11 @@ translate_opts(const char *shareopts) return (newopts); } -static char * -nfs_init_tmpfile(void) -{ - char *tmpfile = NULL; - - if (asprintf(&tmpfile, "%s%s", ZFS_EXPORTS_FILE, ".XXXXXXXX") == -1) { - fprintf(stderr, "Unable to allocate buffer for temporary " - "file name\n"); - return (NULL); - } - - int fd = mkstemp(tmpfile); - if (fd == -1) { - fprintf(stderr, "Unable to create temporary file: %s", - strerror(errno)); - free(tmpfile); - return (NULL); - } - close(fd); - return (tmpfile); -} - -static int -nfs_fini_tmpfile(char *tmpfile) -{ - if (rename(tmpfile, ZFS_EXPORTS_FILE) == -1) { - fprintf(stderr, "Unable to rename %s: %s\n", tmpfile, - strerror(errno)); - unlink(tmpfile); - free(tmpfile); - return (SA_SYSTEM_ERR); - } - free(tmpfile); - return (SA_OK); -} - /* * This function copies all entries from the exports file to "filename", * omitting any entries for the specified mountpoint. */ -static int +__attribute__((visibility("hidden"))) int nfs_copy_entries(char *filename, const char *mountpoint) { int error = SA_OK; @@ -234,7 +198,7 @@ nfs_enable_share(sa_share_impl_t impl_share) char *filename = NULL; int error; - if ((filename = nfs_init_tmpfile()) == NULL) + if ((filename = nfs_init_tmpfile(ZFS_EXPORTS_FILE, NULL)) == NULL) return (SA_SYSTEM_ERR); error = nfs_exports_lock(ZFS_EXPORTS_LOCK); @@ -283,7 +247,7 @@ nfs_enable_share(sa_share_impl_t impl_share) nfs_exports_unlock(ZFS_EXPORTS_LOCK); return (SA_SYSTEM_ERR); } - error = nfs_fini_tmpfile(filename); + error = nfs_fini_tmpfile(ZFS_EXPORTS_FILE, filename); nfs_exports_unlock(ZFS_EXPORTS_LOCK); return (error); } @@ -291,30 +255,8 @@ nfs_enable_share(sa_share_impl_t impl_share) static int nfs_disable_share(sa_share_impl_t impl_share) { - int error; - char *filename = NULL; - - if ((filename = nfs_init_tmpfile()) == NULL) - return (SA_SYSTEM_ERR); - - error = nfs_exports_lock(ZFS_EXPORTS_LOCK); - if (error != 0) { - unlink(filename); - free(filename); - return (error); - } - - error = nfs_copy_entries(filename, impl_share->sa_mountpoint); - if (error != SA_OK) { - unlink(filename); - free(filename); - nfs_exports_unlock(ZFS_EXPORTS_LOCK); - return (error); - } - - error = nfs_fini_tmpfile(filename); - nfs_exports_unlock(ZFS_EXPORTS_LOCK); - return (error); + return (nfs_disable_share_impl( + ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, NULL, impl_share)); } /* diff --git a/lib/libshare/os/linux/nfs.c b/lib/libshare/os/linux/nfs.c index 08c7db1bc..1abb5bf16 100644 --- a/lib/libshare/os/linux/nfs.c +++ b/lib/libshare/os/linux/nfs.c @@ -350,49 +350,6 @@ get_linux_shareopts(const char *shareopts, char **plinux_opts) return (error); } -static char * -nfs_init_tmpfile(void) -{ - char *tmpfile = NULL; - struct stat sb; - - if (stat(ZFS_EXPORTS_DIR, &sb) < 0 && - mkdir(ZFS_EXPORTS_DIR, 0755) < 0) { - fprintf(stderr, "failed to create %s: %s\n", - ZFS_EXPORTS_DIR, strerror(errno)); - return (NULL); - } - - if (asprintf(&tmpfile, "%s%s", ZFS_EXPORTS_FILE, ".XXXXXXXX") == -1) { - fprintf(stderr, "Unable to allocate temporary file\n"); - return (NULL); - } - - int fd = mkstemp(tmpfile); - if (fd == -1) { - fprintf(stderr, "Unable to create temporary file: %s", - strerror(errno)); - free(tmpfile); - return (NULL); - } - close(fd); - return (tmpfile); -} - -static int -nfs_fini_tmpfile(char *tmpfile) -{ - if (rename(tmpfile, ZFS_EXPORTS_FILE) == -1) { - fprintf(stderr, "Unable to rename %s: %s\n", tmpfile, - strerror(errno)); - unlink(tmpfile); - free(tmpfile); - return (SA_SYSTEM_ERR); - } - free(tmpfile); - return (SA_OK); -} - /* * 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 @@ -443,7 +400,7 @@ nfs_add_entry(const char *filename, const char *sharepath, * This function copies all entries from the exports file to "filename", * omitting any entries for the specified mountpoint. */ -static int +__attribute__((visibility("hidden"))) int nfs_copy_entries(char *filename, const char *mountpoint) { char *buf = NULL; @@ -516,7 +473,8 @@ nfs_enable_share(sa_share_impl_t impl_share) char *filename = NULL; int error; - if ((filename = nfs_init_tmpfile()) == NULL) + if ((filename = + nfs_init_tmpfile(ZFS_EXPORTS_FILE, ZFS_EXPORTS_DIR)) == NULL) return (SA_SYSTEM_ERR); error = nfs_exports_lock(ZFS_EXPORTS_LOCK); @@ -547,7 +505,7 @@ nfs_enable_share(sa_share_impl_t impl_share) linux_opts); free(linux_opts); if (error == 0) { - error = nfs_fini_tmpfile(filename); + error = nfs_fini_tmpfile(ZFS_EXPORTS_FILE, filename); } else { unlink(filename); free(filename); @@ -562,29 +520,8 @@ nfs_enable_share(sa_share_impl_t impl_share) static int nfs_disable_share(sa_share_impl_t impl_share) { - int error; - char *filename = NULL; - - if ((filename = nfs_init_tmpfile()) == NULL) - return (SA_SYSTEM_ERR); - - error = nfs_exports_lock(ZFS_EXPORTS_LOCK); - if (error != 0) { - unlink(filename); - free(filename); - return (error); - } - - error = nfs_copy_entries(filename, impl_share->sa_mountpoint); - if (error != SA_OK) { - unlink(filename); - free(filename); - nfs_exports_unlock(ZFS_EXPORTS_LOCK); - return (error); - } - error = nfs_fini_tmpfile(filename); - nfs_exports_unlock(ZFS_EXPORTS_LOCK); - return (error); + return (nfs_disable_share_impl( + ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, ZFS_EXPORTS_DIR, impl_share)); } static boolean_t