mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-03-29 15:03:51 +03:00
Add support for multiple lines to the sharenfs property for FreeBSD (#16338)
There has been a bugzilla PR#147881 requesting this for a long time (14 years!). It extends the syntax of the ZFS shanenfs property (for FreeBSD only) to allow multiple sets of options for different hosts/nets, separated by ';'s. Signed-off-by: Rick Macklem <rmacklem@FreeBSD.org> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Tino Reichardt <milky-zfs@mcmilk.de> Reviewed-by: Tony Hutter <hutter2@llnl.gov>
This commit is contained in:
parent
fb6d8cf229
commit
dbe07928ba
@ -44,8 +44,6 @@
|
|||||||
#include "nfs.h"
|
#include "nfs.h"
|
||||||
|
|
||||||
#define _PATH_MOUNTDPID "/var/run/mountd.pid"
|
#define _PATH_MOUNTDPID "/var/run/mountd.pid"
|
||||||
#define OPTSSIZE 1024
|
|
||||||
#define MAXLINESIZE (PATH_MAX + OPTSSIZE)
|
|
||||||
#define ZFS_EXPORTS_FILE "/etc/zfs/exports"
|
#define ZFS_EXPORTS_FILE "/etc/zfs/exports"
|
||||||
#define ZFS_EXPORTS_LOCK ZFS_EXPORTS_FILE".lock"
|
#define ZFS_EXPORTS_LOCK ZFS_EXPORTS_FILE".lock"
|
||||||
|
|
||||||
@ -69,17 +67,30 @@
|
|||||||
* index, quiet
|
* index, quiet
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
translate_opts(const char *shareopts, FILE *out)
|
translate_opts(char *oldopts, FILE *out)
|
||||||
{
|
{
|
||||||
static const char *const known_opts[] = { "ro", "maproot", "mapall",
|
static const char *const known_opts[] = { "ro", "maproot", "mapall",
|
||||||
"mask", "network", "sec", "alldirs", "public", "webnfs", "index",
|
"mask", "network", "sec", "alldirs", "public", "webnfs", "index",
|
||||||
"quiet" };
|
"quiet" };
|
||||||
char oldopts[OPTSSIZE], newopts[OPTSSIZE];
|
char *newopts, *o, *s = NULL;
|
||||||
char *o, *s = NULL;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
size_t len;
|
size_t len, newopts_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
strlcpy(oldopts, shareopts, sizeof (oldopts));
|
/*
|
||||||
|
* 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';
|
newopts[0] = '\0';
|
||||||
s = oldopts;
|
s = oldopts;
|
||||||
while ((o = strsep(&s, "-, ")) != NULL) {
|
while ((o = strsep(&s, "-, ")) != NULL) {
|
||||||
@ -89,14 +100,16 @@ translate_opts(const char *shareopts, FILE *out)
|
|||||||
len = strlen(known_opts[i]);
|
len = strlen(known_opts[i]);
|
||||||
if (strncmp(known_opts[i], o, len) == 0 &&
|
if (strncmp(known_opts[i], o, len) == 0 &&
|
||||||
(o[len] == '\0' || o[len] == '=')) {
|
(o[len] == '\0' || o[len] == '=')) {
|
||||||
strlcat(newopts, "-", sizeof (newopts));
|
strlcat(newopts, "-", newopts_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strlcat(newopts, o, sizeof (newopts));
|
strlcat(newopts, o, newopts_len);
|
||||||
strlcat(newopts, " ", sizeof (newopts));
|
strlcat(newopts, " ", newopts_len);
|
||||||
}
|
}
|
||||||
return (fputs(newopts, out));
|
ret = fputs(newopts, out);
|
||||||
|
free(newopts);
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -106,20 +119,38 @@ nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile)
|
|||||||
if (strcmp(shareopts, "on") == 0)
|
if (strcmp(shareopts, "on") == 0)
|
||||||
shareopts = "";
|
shareopts = "";
|
||||||
|
|
||||||
boolean_t need_free;
|
boolean_t need_free, fnd_semi;
|
||||||
char *mp;
|
char *mp, *lineopts, *exportopts, *s;
|
||||||
|
size_t whitelen;
|
||||||
int rc = nfs_escape_mountpoint(impl_share->sa_mountpoint, &mp,
|
int rc = nfs_escape_mountpoint(impl_share->sa_mountpoint, &mp,
|
||||||
&need_free);
|
&need_free);
|
||||||
if (rc != SA_OK)
|
if (rc != SA_OK)
|
||||||
return (rc);
|
return (rc);
|
||||||
|
|
||||||
if (fputs(mp, tmpfile) == EOF ||
|
lineopts = strdup(shareopts);
|
||||||
fputc('\t', tmpfile) == EOF ||
|
if (lineopts == NULL)
|
||||||
translate_opts(shareopts, tmpfile) == EOF ||
|
return (SA_SYSTEM_ERR);
|
||||||
fputc('\n', tmpfile) == EOF) {
|
s = lineopts;
|
||||||
fprintf(stderr, "failed to write to temporary file\n");
|
fnd_semi = B_FALSE;
|
||||||
rc = SA_SYSTEM_ERR;
|
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)
|
if (need_free)
|
||||||
free(mp);
|
free(mp);
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
.\" Copyright (c) 2019, Kjeld Schouten-Lebbing
|
.\" Copyright (c) 2019, Kjeld Schouten-Lebbing
|
||||||
.\" Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
|
.\" Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
|
||||||
.\"
|
.\"
|
||||||
.Dd August 8, 2023
|
.Dd June 29, 2024
|
||||||
.Dt ZFSPROPS 7
|
.Dt ZFSPROPS 7
|
||||||
.Os
|
.Os
|
||||||
.
|
.
|
||||||
@ -1727,6 +1727,18 @@ Please note that the options are comma-separated, unlike those found in
|
|||||||
This is done to negate the need for quoting, as well as to make parsing
|
This is done to negate the need for quoting, as well as to make parsing
|
||||||
with scripts easier.
|
with scripts easier.
|
||||||
.Pp
|
.Pp
|
||||||
|
For
|
||||||
|
.Fx ,
|
||||||
|
there may be multiple sets of options separated by semicolon(s).
|
||||||
|
Each set of options must apply to different hosts or networks and each
|
||||||
|
set of options will create a separate line for
|
||||||
|
.Xr exports 5 .
|
||||||
|
Any semicolon separated option set that consists entirely of whitespace
|
||||||
|
will be ignored.
|
||||||
|
This use of semicolons is only for
|
||||||
|
.Fx
|
||||||
|
at this time.
|
||||||
|
.Pp
|
||||||
See
|
See
|
||||||
.Xr exports 5
|
.Xr exports 5
|
||||||
for the meaning of the default options.
|
for the meaning of the default options.
|
||||||
|
Loading…
Reference in New Issue
Block a user