Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Feb 2023 23:17:56 GMT
From:      Kirk McKusick <mckusick@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 668dfa016698 - stable/13 - Document the mntopts(3) functions.
Message-ID:  <202302062317.316NHuFa037599@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302062317.316NHuFa037599>