summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mountd
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2007-02-03 00:12:18 +0000
committerpjd <pjd@FreeBSD.org>2007-02-03 00:12:18 +0000
commit8d0230d7615c8c86af0b5722ac7ca8a1578a0630 (patch)
tree9f446e73aa9775e301967a2b65cd022b99f0664a /usr.sbin/mountd
parentdc15ae189680b2124fae98087bdac446047f0f6d (diff)
downloadFreeBSD-src-8d0230d7615c8c86af0b5722ac7ca8a1578a0630.zip
FreeBSD-src-8d0230d7615c8c86af0b5722ac7ca8a1578a0630.tar.gz
Add support for multiple exports files. This will be useful for example for
ZFS, where we have automatically generated /etc/zfs/exports file, which should not be edited directly. Discussed with: rwatson
Diffstat (limited to 'usr.sbin/mountd')
-rw-r--r--usr.sbin/mountd/mountd.85
-rw-r--r--usr.sbin/mountd/mountd.c265
2 files changed, 145 insertions, 125 deletions
diff --git a/usr.sbin/mountd/mountd.8 b/usr.sbin/mountd/mountd.8
index d1f472a..7aa1477 100644
--- a/usr.sbin/mountd/mountd.8
+++ b/usr.sbin/mountd/mountd.8
@@ -28,7 +28,7 @@
.\" @(#)mountd.8 8.4 (Berkeley) 4/28/95
.\" $FreeBSD$
.\"
-.Dd May 2, 2006
+.Dd February 3, 2007
.Dt MOUNTD 8
.Os
.Sh NAME
@@ -40,7 +40,7 @@ mount requests
.Nm
.Op Fl 2dlnr
.Op Fl p Ar port
-.Op Ar exportsfile
+.Op Ar exportsfile ...
.Sh DESCRIPTION
The
.Nm
@@ -106,6 +106,7 @@ flag.
.It Ar exportsfile
Specify an alternate location
for the exports file.
+There can many exports files.
.El
.Pp
When
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index 4097ddd..55100d9 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -205,7 +205,8 @@ void terminate(int);
struct exportlist *exphead;
struct mountlist *mlhead;
struct grouplist *grphead;
-char exname[MAXPATHLEN];
+char *exnames_default[2] = { _PATH_EXPORTS, NULL };
+char **exnames;
struct xucred def_anon = {
XUCRED_VERSION,
(uid_t)-2,
@@ -322,11 +323,10 @@ main(argc, argv)
grphead = (struct grouplist *)NULL;
exphead = (struct exportlist *)NULL;
mlhead = (struct mountlist *)NULL;
- if (argc == 1) {
- strncpy(exname, *argv, MAXPATHLEN-1);
- exname[MAXPATHLEN-1] = '\0';
- } else
- strcpy(exname, _PATH_EXPORTS);
+ if (argc > 0)
+ exnames = argv;
+ else
+ exnames = exnames_default;
openlog("mountd", LOG_PID, LOG_DAEMON);
if (debug)
warnx("getting export list");
@@ -541,7 +541,7 @@ usage()
{
fprintf(stderr,
"usage: mountd [-2] [-d] [-l] [-n] [-p <port>] [-r] "
- "[export_file]\n");
+ "[export_file ...]\n");
exit(1);
}
@@ -953,130 +953,20 @@ int linesize;
FILE *exp_file;
/*
- * Get the export list
+ * Get the export list from one, currently open file
*/
-void
-get_exportlist()
+static void
+get_exportlist_one()
{
struct exportlist *ep, *ep2;
struct grouplist *grp, *tgrp;
struct exportlist **epp;
- struct export_args export;
struct dirlist *dirhead;
- struct iovec *iov;
- struct statfs fsb, *fsp, *mntbufp;
+ struct statfs fsb;
struct xucred anon;
- struct xvfsconf vfc;
char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc;
- char errmsg[255];
- int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp;
- int iovlen;
-
- bzero(&export, sizeof(export));
- export.ex_flags = MNT_DELEXPORT;
- dirp = NULL;
- dirplen = 0;
- iov = NULL;
- iovlen = 0;
- bzero(errmsg, sizeof(errmsg));
-
- /*
- * First, get rid of the old list
- */
- ep = exphead;
- while (ep) {
- ep2 = ep;
- ep = ep->ex_next;
- free_exp(ep2);
- }
- exphead = (struct exportlist *)NULL;
-
- grp = grphead;
- while (grp) {
- tgrp = grp;
- grp = grp->gr_next;
- free_grp(tgrp);
- }
- grphead = (struct grouplist *)NULL;
-
- /*
- * And delete exports that are in the kernel for all local
- * filesystems.
- * XXX: Should know how to handle all local exportable filesystems.
- */
- num = getmntinfo(&mntbufp, MNT_NOWAIT);
-
- if (num > 0) {
- build_iovec(&iov, &iovlen, "fstype", NULL, 0);
- build_iovec(&iov, &iovlen, "fspath", NULL, 0);
- build_iovec(&iov, &iovlen, "from", NULL, 0);
- build_iovec(&iov, &iovlen, "update", NULL, 0);
- build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
- build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
- }
-
- for (i = 0; i < num; i++) {
- fsp = &mntbufp[i];
- if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
- syslog(LOG_ERR, "getvfsbyname() failed for %s",
- fsp->f_fstypename);
- continue;
- }
-
- /*
- * Do not delete export for network filesystem by
- * passing "export" arg to nmount().
- * It only makes sense to do this for local filesystems.
- */
- if (vfc.vfc_flags & VFCF_NETWORK)
- continue;
-
- iov[1].iov_base = fsp->f_fstypename;
- iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
- iov[3].iov_base = fsp->f_mntonname;
- iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
- iov[5].iov_base = fsp->f_mntfromname;
- iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
-
- /*
- * Kick out MNT_ROOTFS. It should not be passed from
- * userland to kernel. It should only be used
- * internally in the kernel.
- */
- if (fsp->f_flags & MNT_ROOTFS) {
- fsp->f_flags &= ~MNT_ROOTFS;
- }
-
- if (nmount(iov, iovlen, fsp->f_flags) < 0 &&
- errno != ENOENT && errno != ENOTSUP) {
- syslog(LOG_ERR,
- "can't delete exports for %s: %m %s",
- fsp->f_mntonname, errmsg);
- }
- }
-
- if (iov != NULL) {
- /* Free strings allocated by strdup() in getmntopts.c */
- free(iov[0].iov_base); /* fstype */
- free(iov[2].iov_base); /* fspath */
- free(iov[4].iov_base); /* from */
- free(iov[6].iov_base); /* update */
- free(iov[8].iov_base); /* export */
- free(iov[10].iov_base); /* errmsg */
+ int len, has_host, exflags, got_nondir, dirplen, netgrp;
- /* free iov, allocated by realloc() */
- free(iov);
- iovlen = 0;
- }
-
- /*
- * Read in the exports file and build the list, calling
- * nmount() as we go along to push the export rules into the kernel.
- */
- if ((exp_file = fopen(exname, "r")) == NULL) {
- syslog(LOG_ERR, "can't open %s", exname);
- exit(2);
- }
dirhead = (struct dirlist *)NULL;
while (get_line()) {
if (debug)
@@ -1294,7 +1184,136 @@ nextline:
dirhead = (struct dirlist *)NULL;
}
}
- fclose(exp_file);
+}
+
+/*
+ * Get the export list from all specified files
+ */
+void
+get_exportlist()
+{
+ struct exportlist *ep, *ep2;
+ struct grouplist *grp, *tgrp;
+ struct export_args export;
+ struct iovec *iov;
+ struct statfs *fsp, *mntbufp;
+ struct xvfsconf vfc;
+ char *dirp;
+ char errmsg[255];
+ int dirplen, num, i;
+ int iovlen;
+
+ bzero(&export, sizeof(export));
+ export.ex_flags = MNT_DELEXPORT;
+ dirp = NULL;
+ dirplen = 0;
+ iov = NULL;
+ iovlen = 0;
+ bzero(errmsg, sizeof(errmsg));
+
+ /*
+ * First, get rid of the old list
+ */
+ ep = exphead;
+ while (ep) {
+ ep2 = ep;
+ ep = ep->ex_next;
+ free_exp(ep2);
+ }
+ exphead = (struct exportlist *)NULL;
+
+ grp = grphead;
+ while (grp) {
+ tgrp = grp;
+ grp = grp->gr_next;
+ free_grp(tgrp);
+ }
+ grphead = (struct grouplist *)NULL;
+
+ /*
+ * And delete exports that are in the kernel for all local
+ * filesystems.
+ * XXX: Should know how to handle all local exportable filesystems.
+ */
+ num = getmntinfo(&mntbufp, MNT_NOWAIT);
+
+ if (num > 0) {
+ build_iovec(&iov, &iovlen, "fstype", NULL, 0);
+ build_iovec(&iov, &iovlen, "fspath", NULL, 0);
+ build_iovec(&iov, &iovlen, "from", NULL, 0);
+ build_iovec(&iov, &iovlen, "update", NULL, 0);
+ build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
+ build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
+ }
+
+ for (i = 0; i < num; i++) {
+ fsp = &mntbufp[i];
+ if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
+ syslog(LOG_ERR, "getvfsbyname() failed for %s",
+ fsp->f_fstypename);
+ continue;
+ }
+
+ /*
+ * Do not delete export for network filesystem by
+ * passing "export" arg to nmount().
+ * It only makes sense to do this for local filesystems.
+ */
+ if (vfc.vfc_flags & VFCF_NETWORK)
+ continue;
+
+ iov[1].iov_base = fsp->f_fstypename;
+ iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
+ iov[3].iov_base = fsp->f_mntonname;
+ iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
+ iov[5].iov_base = fsp->f_mntfromname;
+ iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
+
+ /*
+ * Kick out MNT_ROOTFS. It should not be passed from
+ * userland to kernel. It should only be used
+ * internally in the kernel.
+ */
+ if (fsp->f_flags & MNT_ROOTFS) {
+ fsp->f_flags &= ~MNT_ROOTFS;
+ }
+
+ if (nmount(iov, iovlen, fsp->f_flags) < 0 &&
+ errno != ENOENT && errno != ENOTSUP) {
+ syslog(LOG_ERR,
+ "can't delete exports for %s: %m %s",
+ fsp->f_mntonname, errmsg);
+ }
+ }
+
+ if (iov != NULL) {
+ /* Free strings allocated by strdup() in getmntopts.c */
+ free(iov[0].iov_base); /* fstype */
+ free(iov[2].iov_base); /* fspath */
+ free(iov[4].iov_base); /* from */
+ free(iov[6].iov_base); /* update */
+ free(iov[8].iov_base); /* export */
+ free(iov[10].iov_base); /* errmsg */
+
+ /* free iov, allocated by realloc() */
+ free(iov);
+ iovlen = 0;
+ }
+
+ /*
+ * Read in the exports file and build the list, calling
+ * nmount() as we go along to push the export rules into the kernel.
+ */
+ for (i = 0; exnames[i] != NULL; i++) {
+ if (debug)
+ warnx("reading exports from %s", exnames[i]);
+ if ((exp_file = fopen(exnames[i], "r")) == NULL) {
+ syslog(LOG_ERR, "can't open %s", exnames[i]);
+ exit(2);
+ }
+ get_exportlist_one();
+ fclose(exp_file);
+ }
}
/*
OpenPOWER on IntegriCloud