git: 668dfa016698 - stable/13 - Document the mntopts(3) functions.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 06 Feb 2023 23:17:56 UTC
The branch stable/13 has been updated by mckusick:
URL: https://cgit.FreeBSD.org/src/commit/?id=668dfa01669858c2468a96d7d0a8b5c808aea5e2
commit 668dfa01669858c2468a96d7d0a8b5c808aea5e2
Author: Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2023-01-15 18:20:48 +0000
Commit: Kirk McKusick <mckusick@FreeBSD.org>
CommitDate: 2023-02-06 23:17:39 +0000
Document the mntopts(3) functions.
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D37907
(cherry picked from commit 906c312bbf7493ccbcce883936d67e5c66a9c3c2)
---
sbin/fsck/Makefile | 4 +
sbin/fsck/fsck.c | 5 +-
sbin/fsck/fsutil.c | 44 ------
sbin/fsck/fsutil.h | 1 -
sbin/fsck_ffs/main.c | 96 +-----------
sbin/growfs/growfs.c | 110 ++------------
sbin/mount/Makefile | 11 +-
sbin/mount/getmntopts.3 | 181 -----------------------
sbin/mount/getmntopts.c | 95 +++++++++++-
sbin/mount/mntopts.3 | 381 ++++++++++++++++++++++++++++++++++++++++++++++++
sbin/mount/mntopts.h | 2 +
sbin/mount/mount.c | 18 +--
sbin/tunefs/tunefs.c | 33 +----
13 files changed, 513 insertions(+), 468 deletions(-)
diff --git a/sbin/fsck/Makefile b/sbin/fsck/Makefile
index 8d3dd214857e..d8106d082230 100644
--- a/sbin/fsck/Makefile
+++ b/sbin/fsck/Makefile
@@ -4,6 +4,10 @@
PACKAGE=runtime
PROG= fsck
SRCS= fsck.c fsutil.c preen.c
+SRCS+= getmntopts.c
MAN= fsck.8
+MOUNT= ${SRCTOP}/sbin/mount
+CFLAGS+= -I${MOUNT}
+.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/fsck/fsck.c b/sbin/fsck/fsck.c
index bb053fe56253..b6ad92ebf49b 100644
--- a/sbin/fsck/fsck.c
+++ b/sbin/fsck/fsck.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <fstab.h>
#include <fcntl.h>
+#include <mntopts.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
@@ -206,7 +207,7 @@ main(int argc, char *argv[])
_PATH_DEV, spec);
spec = device;
}
- mntp = getmntpt(spec);
+ mntp = getmntpoint(spec);
if (mntp != NULL) {
spec = mntp->f_mntfromname;
mntpt = mntp->f_mntonname;
@@ -269,7 +270,7 @@ isok(struct fstab *fs)
if (flags & DO_BACKGRD) {
if (!strcmp(fs->fs_type, FSTAB_RO))
return (0);
- if (getmntpt(fs->fs_spec) == NULL)
+ if (getmntpoint(fs->fs_spec) == NULL)
return (0);
if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0))
return (0);
diff --git a/sbin/fsck/fsutil.c b/sbin/fsck/fsutil.c
index 9644697e2530..a3888eeea25a 100644
--- a/sbin/fsck/fsutil.c
+++ b/sbin/fsck/fsutil.c
@@ -188,50 +188,6 @@ devcheck(const char *origname)
return (origname);
}
-/*
- * Get the mount point information for name.
- */
-struct statfs *
-getmntpt(const char *name)
-{
- struct stat devstat, mntdevstat;
- char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
- char *dev_name;
- struct statfs *mntbuf, *statfsp;
- int i, mntsize, isdev;
-
- if (stat(name, &devstat) != 0)
- return (NULL);
- if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
- isdev = 1;
- else
- isdev = 0;
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
- dev_name = statfsp->f_mntfromname;
- if (*dev_name != '/') {
- if (strlen(_PATH_DEV) + strlen(dev_name) + 1 >
- sizeof(statfsp->f_mntfromname))
- continue;
- strcpy(device, _PATH_DEV);
- strcat(device, dev_name);
- strcpy(statfsp->f_mntfromname, device);
- }
- if (isdev == 0) {
- if (strcmp(name, statfsp->f_mntonname))
- continue;
- return (statfsp);
- }
- if (stat(dev_name, &mntdevstat) == 0 &&
- mntdevstat.st_rdev == devstat.st_rdev)
- return (statfsp);
- }
- statfsp = NULL;
- return (statfsp);
-}
-
-
void *
emalloc(size_t s)
{
diff --git a/sbin/fsck/fsutil.h b/sbin/fsck/fsutil.h
index e65f5ddecb01..bd0954d44ba1 100644
--- a/sbin/fsck/fsutil.h
+++ b/sbin/fsck/fsutil.h
@@ -39,7 +39,6 @@ void panic(const char *, ...) __dead2 __printflike(1, 2);
const char *devcheck(const char *);
const char *cdevname(void);
void setcdevname(const char *, int);
-struct statfs *getmntpt(const char *);
void *emalloc(size_t);
void *erealloc(void *, size_t);
char *estrdup(const char *);
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 3a492c289bfe..c5dc10f1c3b0 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -76,8 +76,6 @@ static void usage(void) __dead2;
static intmax_t argtoimax(int flag, const char *req, const char *str, int base);
static int checkfilesys(char *filesys);
static int setup_bkgrdchk(struct statfs *mntp, int sbrdfailed, char **filesys);
-static int chkdoreload(struct statfs *mntp);
-static struct statfs *getmntpt(const char *);
int
main(int argc, char *argv[])
@@ -258,7 +256,7 @@ checkfilesys(char *filesys)
* if it is listed among the mounted file systems. Failing that
* check to see if it is listed in /etc/fstab.
*/
- mntp = getmntpt(filesys);
+ mntp = getmntpoint(filesys);
if (mntp != NULL)
filesys = mntp->f_mntfromname;
else
@@ -311,7 +309,7 @@ checkfilesys(char *filesys)
(FS_UNCLEAN | FS_NEEDSFSCK)) == 0) {
bufinit();
gjournal_check(filesys);
- if (chkdoreload(mntp) == 0)
+ if (chkdoreload(mntp, pwarn) == 0)
exit(0);
exit(4);
} else {
@@ -357,7 +355,7 @@ checkfilesys(char *filesys)
sujrecovery = 1;
if (suj_check(filesys) == 0) {
printf("\n***** FILE SYSTEM MARKED CLEAN *****\n");
- if (chkdoreload(mntp) == 0)
+ if (chkdoreload(mntp, pwarn) == 0)
exit(0);
exit(4);
}
@@ -561,7 +559,7 @@ checkfilesys(char *filesys)
return (ERESTART);
printf("\n***** PLEASE RERUN FSCK *****\n");
}
- if (chkdoreload(mntp) != 0) {
+ if (chkdoreload(mntp, pwarn) != 0) {
if (!fsmodified)
return (0);
if (!preen)
@@ -715,92 +713,6 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
return (1);
}
-static int
-chkdoreload(struct statfs *mntp)
-{
- struct iovec *iov;
- int iovlen;
- char errmsg[255];
-
- if (mntp == NULL)
- return (0);
-
- iov = NULL;
- iovlen = 0;
- errmsg[0] = '\0';
- /*
- * We modified a mounted file system. Do a mount update on
- * it unless it is read-write, so we can continue using it
- * as safely as possible.
- */
- if (mntp->f_flags & MNT_RDONLY) {
- build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
- build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname,
- (size_t)-1);
- build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname,
- (size_t)-1);
- build_iovec(&iov, &iovlen, "errmsg", errmsg,
- sizeof(errmsg));
- build_iovec(&iov, &iovlen, "update", NULL, 0);
- build_iovec(&iov, &iovlen, "reload", NULL, 0);
- /*
- * XX: We need the following line until we clean up
- * nmount parsing of root mounts and NFS root mounts.
- */
- build_iovec(&iov, &iovlen, "ro", NULL, 0);
- if (nmount(iov, iovlen, mntp->f_flags) == 0) {
- return (0);
- }
- pwarn("mount reload of '%s' failed: %s %s\n\n",
- mntp->f_mntonname, strerror(errno), errmsg);
- return (1);
- }
- return (0);
-}
-
-/*
- * Get the mount point information for name.
- */
-static struct statfs *
-getmntpt(const char *name)
-{
- struct stat devstat, mntdevstat;
- char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
- char *ddevname;
- struct statfs *mntbuf, *statfsp;
- int i, mntsize, isdev;
-
- if (stat(name, &devstat) != 0)
- return (NULL);
- if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
- isdev = 1;
- else
- isdev = 0;
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
- ddevname = statfsp->f_mntfromname;
- if (*ddevname != '/') {
- if (strlen(_PATH_DEV) + strlen(ddevname) + 1 >
- sizeof(statfsp->f_mntfromname))
- continue;
- strcpy(device, _PATH_DEV);
- strcat(device, ddevname);
- strcpy(statfsp->f_mntfromname, device);
- }
- if (isdev == 0) {
- if (strcmp(name, statfsp->f_mntonname))
- continue;
- return (statfsp);
- }
- if (stat(ddevname, &mntdevstat) == 0 &&
- mntdevstat.st_rdev == devstat.st_rdev)
- return (statfsp);
- }
- statfsp = NULL;
- return (statfsp);
-}
-
static void
usage(void)
{
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index 69e6f04dd4c2..c7ef0ced4ed6 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -118,7 +118,6 @@ static void updjcg(int, time_t, int, int, unsigned int);
static void updcsloc(time_t, int, int, unsigned int);
static void frag_adjust(ufs2_daddr_t, int);
static void updclst(int);
-static void mount_reload(const struct statfs *stfs);
static void cgckhash(struct cg *);
/*
@@ -1263,76 +1262,11 @@ is_dev(const char *name)
return (1);
}
-/*
- * Return mountpoint on which the device is currently mounted.
- */
-static const struct statfs *
-dev_to_statfs(const char *dev)
-{
- struct stat devstat, mntdevstat;
- struct statfs *mntbuf, *statfsp;
- char device[MAXPATHLEN];
- char *mntdevname;
- int i, mntsize;
-
- /*
- * First check the mounted filesystems.
- */
- if (stat(dev, &devstat) != 0)
- return (NULL);
- if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode))
- return (NULL);
-
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
- mntdevname = statfsp->f_mntfromname;
- if (*mntdevname != '/') {
- strcpy(device, _PATH_DEV);
- strcat(device, mntdevname);
- mntdevname = device;
- }
- if (stat(mntdevname, &mntdevstat) == 0 &&
- mntdevstat.st_rdev == devstat.st_rdev)
- return (statfsp);
- }
-
- return (NULL);
-}
-
static const char *
-mountpoint_to_dev(const char *mountpoint)
-{
- struct statfs *mntbuf, *statfsp;
- struct fstab *fs;
- int i, mntsize;
-
- /*
- * First check the mounted filesystems.
- */
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
-
- if (strcmp(statfsp->f_mntonname, mountpoint) == 0)
- return (statfsp->f_mntfromname);
- }
-
- /*
- * Check the fstab.
- */
- fs = getfsfile(mountpoint);
- if (fs != NULL)
- return (fs->fs_spec);
-
- return (NULL);
-}
-
-static const char *
-getdev(const char *name)
+getdev(const char *name, struct statfs *statfsp)
{
static char device[MAXPATHLEN];
- const char *cp, *dev;
+ const char *cp;
if (is_dev(name))
return (name);
@@ -1344,9 +1278,8 @@ getdev(const char *name)
return (device);
}
- dev = mountpoint_to_dev(name);
- if (dev != NULL && is_dev(dev))
- return (dev);
+ if (statfsp != NULL)
+ return (statfsp->f_mntfromname);
return (NULL);
}
@@ -1378,7 +1311,7 @@ main(int argc, char **argv)
DBG_FUNC("main")
struct fs *fs;
const char *device;
- const struct statfs *statfsp;
+ struct statfs *statfsp;
uint64_t size = 0;
off_t mediasize;
int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0;
@@ -1430,12 +1363,11 @@ main(int argc, char **argv)
/*
* Now try to guess the device name.
*/
- device = getdev(*argv);
+ statfsp = getmntpoint(*argv);
+ device = getdev(*argv, statfsp);
if (device == NULL)
errx(1, "cannot find special device for %s", *argv);
- statfsp = dev_to_statfs(device);
-
fsi = open(device, O_RDONLY);
if (fsi < 0)
err(1, "%s", device);
@@ -1666,8 +1598,9 @@ main(int argc, char **argv)
error = close(fso);
if (error != 0)
err(1, "close");
- if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0)
- mount_reload(statfsp);
+ if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0 &&
+ chkdoreload(statfsp, warn) != 0)
+ exit(9);
}
DBG_CLOSE;
@@ -1734,29 +1667,6 @@ updclst(int block)
return;
}
-static void
-mount_reload(const struct statfs *stfs)
-{
- char errmsg[255];
- struct iovec *iov;
- int iovlen;
-
- iov = NULL;
- iovlen = 0;
- *errmsg = '\0';
- build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4);
- build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, stfs->f_mntonname), (size_t)-1);
- build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
- build_iovec(&iov, &iovlen, "update", NULL, 0);
- build_iovec(&iov, &iovlen, "reload", NULL, 0);
-
- if (nmount(iov, iovlen, stfs->f_flags) < 0) {
- errmsg[sizeof(errmsg) - 1] = '\0';
- err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname,
- *errmsg != '\0' ? ": " : "", errmsg);
- }
-}
-
/*
* Calculate the check-hash of the cylinder group.
*/
diff --git a/sbin/mount/Makefile b/sbin/mount/Makefile
index 34ba498a2a3f..1bc84039b121 100644
--- a/sbin/mount/Makefile
+++ b/sbin/mount/Makefile
@@ -4,8 +4,15 @@
PACKAGE=runtime
PROG= mount
SRCS= mount.c mount_fs.c getmntopts.c vfslist.c
-MAN= mount.8
-# We do NOT install the getmntopts.3 man page.
+MAN= mntopts.3 mount.8
+MLINKS+= mntopts.3 getmntopts.3
+MLINKS+= mntopts.3 getmntpoint.3
+MLINKS+= mntopts.3 chkdoreload.3
+MLINKS+= mntopts.3 build_iovec.3
+MLINKS+= mntopts.3 build_iovec_argf.3
+MLINKS+= mntopts.3 free_iovec.3
+MLINKS+= mntopts.3 checkpath.3
+MLINKS+= mntopts.3 rmslashes.3
LIBADD= util xo
diff --git a/sbin/mount/getmntopts.3 b/sbin/mount/getmntopts.3
deleted file mode 100644
index b87956d051b7..000000000000
--- a/sbin/mount/getmntopts.3
+++ /dev/null
@@ -1,181 +0,0 @@
-.\" Copyright (c) 1994
-.\" The Regents of the University of California. 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.
-.\" 3. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
-.\"
-.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95
-.\" $FreeBSD$
-.\"
-.Dd February 17, 2008
-.Dt GETMNTOPTS 3
-.Os
-.Sh NAME
-.Nm getmntopts
-.Nd scan mount options
-.Sh SYNOPSIS
-.Fd #include \&"mntopts.h"
-.Ft void
-.Fo getmntopts
-.Fa "const char *options" "const struct mntopt *mopts"
-.Fa "int *flagp" "int *altflagp"
-.Fc
-.Sh DESCRIPTION
-The
-.Fn getmntopts
-function takes a comma separated option list and a list
-of valid option names, and computes the bitmask
-corresponding to the requested set of options.
-.Pp
-The string
-.Fa options
-is broken down into a sequence of comma separated tokens.
-Each token is looked up in the table described by
-.Fa mopts
-and the bits in
-the word referenced by either
-.Fa flagp
-or
-.Fa altflagp
-(depending on the
-.Va m_altloc
-field of the option's table entry)
-are updated.
-The flag words are not initialized by
-.Fn getmntopts .
-The table,
-.Fa mopts ,
-has the following format:
-.Bd -literal
-struct mntopt {
- char *m_option; /* option name */
- int m_inverse; /* is this a negative option, e.g., "dev" */
- int m_flag; /* bit to set, e.g., MNT_RDONLY */
- int m_altloc; /* non-zero to use altflagp rather than flagp */
-};
-.Ed
-.Pp
-The members of this structure are:
-.Bl -tag -width m_inverse
-.It Va m_option
-the option name,
-for example
-.Dq Li suid .
-.It Va m_inverse
-tells
-.Fn getmntopts
-that the name has the inverse meaning of the
-bit.
-For example,
-.Dq Li suid
-is the string, whereas the
-mount flag is
-.Dv MNT_NOSUID .
-In this case, the sense of the string and the flag
-are inverted, so the
-.Va m_inverse
-flag should be set.
-.It Va m_flag
-the value of the bit to be set or cleared in
-the flag word when the option is recognized.
-The bit is set when the option is discovered,
-but cleared if the option name was preceded
-by the letters
-.Dq Li no .
-The
-.Va m_inverse
-flag causes these two operations to be reversed.
-.It Va m_altloc
-the bit should be set or cleared in
-.Fa altflagp
-rather than
-.Fa flagp .
-.El
-.Pp
-Each of the user visible
-.Dv MNT_
-flags has a corresponding
-.Dv MOPT_
-macro which defines an appropriate
-.Vt "struct mntopt"
-entry.
-To simplify the program interface and ensure consistency across all
-programs, a general purpose macro,
-.Dv MOPT_STDOPTS ,
-is defined which
-contains an entry for all the generic VFS options.
-In addition, the macros
-.Dv MOPT_FORCE
-and
-.Dv MOPT_UPDATE
-exist to enable the
-.Dv MNT_FORCE
-and
-.Dv MNT_UPDATE
-flags to be set.
-Finally, the table must be terminated by an entry with a
-.Dv NULL
-first element.
-.Sh EXAMPLES
-Most commands will use the standard option set.
-Local file systems which support the
-.Dv MNT_UPDATE
-flag, would also have an
-.Dv MOPT_UPDATE
-entry.
-This can be declared and used as follows:
-.Bd -literal
-#include "mntopts.h"
-
-struct mntopt mopts[] = {
- MOPT_STDOPTS,
- MOPT_UPDATE,
- { NULL }
-};
-
- ...
- mntflags = mntaltflags = 0;
- ...
- getmntopts(options, mopts, &mntflags, &mntaltflags);
- ...
-.Ed
-.Sh DIAGNOSTICS
-If the external integer variable
-.Va getmnt_silent
-is zero, then the
-.Fn getmntopts
-function displays an error message and exits if an
-unrecognized option is encountered.
-Otherwise unrecognized options are silently ignored.
-By default
-.Va getmnt_silent
-is zero.
-.Sh SEE ALSO
-.Xr err 3 ,
-.Xr mount 8
-.Sh HISTORY
-The
-.Fn getmntopts
-function appeared in
-.Bx 4.4 .
diff --git a/sbin/mount/getmntopts.c b/sbin/mount/getmntopts.c
index 0ee6d99ed8b9..e6607c385341 100644
--- a/sbin/mount/getmntopts.c
+++ b/sbin/mount/getmntopts.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
+#include <paths.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -153,6 +154,98 @@ checkpath_allow_file(const char *path, char *resolved)
return (0);
}
+/*
+ * Get the mount point information for name. Name may be mount point name
+ * or device name (with or without /dev/ preprended).
+ */
+struct statfs *
+getmntpoint(const char *name)
+{
+ struct stat devstat, mntdevstat;
+ char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
+ char *ddevname;
+ struct statfs *mntbuf, *statfsp;
+ int i, mntsize, isdev;
+
+ if (stat(name, &devstat) != 0)
+ return (NULL);
+ if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
+ isdev = 1;
+ else
+ isdev = 0;
+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+ for (i = 0; i < mntsize; i++) {
+ statfsp = &mntbuf[i];
+ ddevname = statfsp->f_mntfromname;
+ if (*ddevname != '/') {
+ if (strlen(_PATH_DEV) + strlen(ddevname) + 1 >
+ sizeof(statfsp->f_mntfromname))
+ continue;
+ strcpy(device, _PATH_DEV);
+ strcat(device, ddevname);
+ strcpy(statfsp->f_mntfromname, device);
+ }
+ if (isdev == 0) {
+ if (strcmp(name, statfsp->f_mntonname))
+ continue;
+ return (statfsp);
+ }
+ if (stat(ddevname, &mntdevstat) == 0 &&
+ mntdevstat.st_rdev == devstat.st_rdev)
+ return (statfsp);
+ }
+ return (NULL);
+}
+
+/*
+ * If possible reload a mounted filesystem.
+ * When prtmsg != NULL print a warning if a reload is attempted, but fails.
+ * Return 0 on success, 1 on failure.
+ */
+int
+chkdoreload(struct statfs *mntp,
+ void (*prtmsg)(const char *, ...) __printflike(1,2))
+{
+ struct iovec *iov;
+ int iovlen, error;
+ char errmsg[255];
+
+ /*
+ * If the filesystem is not mounted it does not need to be reloaded.
+ * If it is mounted for writing, then it could not have been opened
+ * for writing by a utility, so does not need to be reloaded.
+ */
+ if (mntp == NULL || (mntp->f_flags & MNT_RDONLY) == 0)
+ return (0);
+
+ /*
+ * We modified a mounted file system. Do a mount update on
+ * it so we can continue using it as safely as possible.
+ */
+ iov = NULL;
+ iovlen = 0;
+ errmsg[0] = '\0';
+ build_iovec(&iov, &iovlen, "fstype", __DECONST(void *, "ffs"), 4);
+ build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname, (size_t)-1);
+ build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, (size_t)-1);
+ build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
+ build_iovec(&iov, &iovlen, "update", NULL, 0);
+ build_iovec(&iov, &iovlen, "reload", NULL, 0);
+ /*
+ * XX: We need the following line until we clean up
+ * nmount parsing of root mounts and NFS root mounts.
+ */
+ build_iovec(&iov, &iovlen, "ro", NULL, 0);
+ error = nmount(iov, iovlen, mntp->f_flags);
+ free_iovec(&iov, &iovlen);
+ if (error == 0)
+ return (0);
+ if (prtmsg != NULL)
+ prtmsg("mount reload of '%s' failed: %s %s\n\n",
+ mntp->f_mntonname, strerror(errno), errmsg);
+ return (1);
+}
+
void
build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
size_t len)
@@ -207,7 +300,7 @@ free_iovec(struct iovec **iov, int *iovlen)
{
int i;
- for (i = 0; i < *iovlen; i++)
+ for (i = 0; i < *iovlen; i += 2)
free((*iov)[i].iov_base);
free(*iov);
}
diff --git a/sbin/mount/mntopts.3 b/sbin/mount/mntopts.3
new file mode 100644
index 000000000000..782acabef1a0
--- /dev/null
+++ b/sbin/mount/mntopts.3
@@ -0,0 +1,381 @@
+.\" Copyright (c) 2023 Marshall Kirk McKusick
+.\" Copyright (c) 1994 The Regents of the University of California.
+.\"
+.\" 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.
+.\"
+.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95
+.\"
+.Dd January 19, 2023
+.Dt MNTOPTS 3
+.Os
+.Sh NAME
+.Nm getmntopts ,
+.Nm getmntpoint ,
+.Nm chkdoreload ,
+.Nm build_iovec ,
+.Nm build_iovec_argf ,
+.Nm free_iovec ,
+.Nm checkpath ,
+.Nm rmslashes
+.Nd "mount point operations"
+.Sh SYNOPSIS
+.In mntopts.h
+.Ft void
+.Fo getmntopts
+.Fa "const char *options" "const struct mntopt *mopts"
+.Fa "int *flagp" "int *altflagp"
+.Fc
+.Ft struct statfs *
+.Fn getmntpoint "const char *name"
+.Ft int
+.Fo chkdoreload
+.Fa "struct statfs *mntp"
+.Fa "void (*prtmsg)(const char *fmt, ...)"
+.Fc
+.Ft void
+.Fo build_iovec
+.Fa "struct iovec **iov" "int *iovlen" "const char *name" "void *val"
+.Fa "size_t len"
+.Fc
+.Ft void
+.Fo build_iovec_argf
+.Fa "struct iovec **iov" "int *iovlen" "const char *name"
+.Fa "const char *fmt" "..."
+.Fc
+.Ft void
+.Fn free_iovec "struct iovec **iov" "int *iovlen"
+.Ft int
+.Fn checkpath "const char *path" "char *resolved"
+.Ft void
+.Fn rmslashes "char *rrpin" "char *rrpout"
+.Sh DESCRIPTION
+The
+.Nm mntopts
+functions support operations associated with a mount point.
+For historic reasons are in a file in the sources for the
+.Xr mount 8
+program.
+Thus, to access them the following lines need to be added to the
+.Nm Makefile
+of the program wanting to use them:
+.Bd -literal
+SRCS+= getmntopts.c
+MOUNT= ${SRCTOP}/sbin/mount
+CFLAGS+= -I${MOUNT}
+\&.PATH: ${MOUNT}
+.Ed
+.Pp
+The
+.Fn getmntopts
+function takes a comma separated option list and a list
+of valid option names, and computes the bitmask
+corresponding to the requested set of options.
+.Pp
+The string
+.Fa options
+is broken down into a sequence of comma separated tokens.
+Each token is looked up in the table described by
+.Fa mopts
+and the bits in
+the word referenced by either
+.Fa flagp
+or
+.Fa altflagp
+(depending on the
+.Va m_altloc
+field of the option's table entry)
+are updated.
+The flag words are not initialized by
+.Fn getmntopts .
+The table,
+.Fa mopts ,
+has the following format:
+.Bd -literal
+struct mntopt {
+ char *m_option; /* option name */
+ int m_inverse; /* is this a negative option, e.g., "dev" */
+ int m_flag; /* bit to set, e.g., MNT_RDONLY */
+ int m_altloc; /* non-zero to use altflagp rather than flagp */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width m_inverse
+.It Va m_option
+the option name,
+for example
+.Dq Li suid .
+.It Va m_inverse
+tells
+.Fn getmntopts
+that the name has the inverse meaning of the
+bit.
+For example,
+.Dq Li suid
+is the string, whereas the
+mount flag is
+.Dv MNT_NOSUID .
+In this case, the sense of the string and the flag
+are inverted, so the
+.Va m_inverse
+flag should be set.
+.It Va m_flag
+the value of the bit to be set or cleared in
+the flag word when the option is recognized.
+The bit is set when the option is discovered,
+but cleared if the option name was preceded
+by the letters
+.Dq Li no .
+The
+.Va m_inverse
+flag causes these two operations to be reversed.
+.It Va m_altloc
+the bit should be set or cleared in
+.Fa altflagp
+rather than
+.Fa flagp .
+.El
+.Pp
+Each of the user visible
+.Dv MNT_
+flags has a corresponding
+.Dv MOPT_
+macro which defines an appropriate
+.Vt "struct mntopt"
+entry.
+To simplify the program interface and ensure consistency across all
+programs, a general purpose macro,
+.Dv MOPT_STDOPTS ,
+is defined which
+contains an entry for all the generic VFS options.
+In addition, the macros
+.Dv MOPT_FORCE
+and
+.Dv MOPT_UPDATE
+exist to enable the
+.Dv MNT_FORCE
+and
+.Dv MNT_UPDATE
+flags to be set.
+Finally, the table must be terminated by an entry with a
+.Dv NULL
+first element.
+.Pp
+The
+.Fn getmntpoint
+function takes the pathname of a possible mount point
+or of a device (with or without
+.Pa /dev/
+prepended to it).
+If the pathname is a directory or a file,
+.Fn getmntpoint
+checks to see if the mount point currently has a filesystem
+mounted on it.
+If the pathname is a device,
+.Fn getmntpoint
+checks to see if it is currently mounted.
+If there is an associated mount, a pointer to a
+.Vt "struct statfs"
*** 319 LINES SKIPPED ***