aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2023-01-15 18:20:48 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2023-02-06 23:17:39 +0000
commit668dfa01669858c2468a96d7d0a8b5c808aea5e2 (patch)
tree0993dd89da9cafd11a3d4fd77529c8dcde39b981
parent7aaa7dad32ca350e972d7c4688e39c50d818b45b (diff)
downloadsrc-668dfa01669858c2468a96d7d0a8b5c808aea5e2.tar.gz
src-668dfa01669858c2468a96d7d0a8b5c808aea5e2.zip
Document the mntopts(3) functions.
Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D37907 (cherry picked from commit 906c312bbf7493ccbcce883936d67e5c66a9c3c2)
-rw-r--r--sbin/fsck/Makefile4
-rw-r--r--sbin/fsck/fsck.c5
-rw-r--r--sbin/fsck/fsutil.c44
-rw-r--r--sbin/fsck/fsutil.h1
-rw-r--r--sbin/fsck_ffs/main.c96
-rw-r--r--sbin/growfs/growfs.c110
-rw-r--r--sbin/mount/Makefile11
-rw-r--r--sbin/mount/getmntopts.3181
-rw-r--r--sbin/mount/getmntopts.c95
-rw-r--r--sbin/mount/mntopts.3381
-rw-r--r--sbin/mount/mntopts.h2
-rw-r--r--sbin/mount/mount.c18
-rw-r--r--sbin/tunefs/tunefs.c33
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"
+is returned.
+The returned result is stored in a static buffer that is over-written
+each time the
+.Fn getmntpoint
+function or the
+.Xr getmntinfo 3
+library routine is called.
+If no mount is found, NULL is returned.
+.Pp
+The
+.Fn chkdoreload
+function takes a pointer to a
+.Vt "struct statfs" .
+If the filesystem associated with the mount point is mounted read-only,
+.Fn chkdoreload
+requests the filesystem to reload all of its metadata from its backing store.
+The second parameter is the function to call to print an error message
+if the reload fails.
+If no error message is desired, a
+.Dv NULL
+can be passed as the second argument.
+The
+.Fn chkdoreload
+function returns zero on success or non-zero on failure.
+.Pp
+The
+.Fn build_iovec
+function adds a parameter to a list of parameters to be passed to the
+.Xr nmount 2
+system call.
+The parameter list is built up in
+.Va iov
+and its length is kept in
+.Va iovlen .
+Before the first call to
+.Fn build_iovec ,
+.Va iov
+should be set to
+.Dv NULL
+and
+.Va iovlen
+should be set to 0.
+The parameter name is passed in
+.Va name .
+The value of the parameter name is pointed to by
+.Va val .
+The size of the value is passed in
+.Va len .
+If the value is a string, a
+.Va len
+of -1 is passed to indicate that the length should be determined using
+.Xr strlen 3 .
+If the parameter has no value,
+.Va name
+should be
+.Dv NULL
+and
+.Va len
+should be 0.
+.Pp
+The
+.Fn build_iovec_argf
+function adds a formatted parameter to a list of parameters to be passed
+to the
+.Xr nmount 2
+system call.
+The parameter list is built up in
+.Va iov
+and its length is kept in
+.Va iovlen .
+Before the first call to
+.Fn build_iovec_argf ,
+.Va iov
+should be set to
+.Dv NULL
+and
+.Va iovlen
+should be set to 0.
+The parameter name is passed in
+.Va name .
+The value of the parameter name is described by a format string pointed to by
+.Va fmt .
+If the parameter has no value,
+.Va name
+should be
+.Dv NULL .
+.Pp
+The
+.Fn free_iovec
+function frees the memory in the
+.Va iov
+vector of the length specified in
+.Va iovlen
+that was previously allocated by the
+.Fn build_iovec
+and / or
+.Fn build_iovec_argf
+functions.
+The
+.Va iov
+is set to
+.Dv NULL
+and the
+.Va iovlen
+is set to 0 to indicate that the space has been freed.
+.Pp
+The
+.Fn checkpath
+function uses
+.Xr realpath 3
+to verify that its
+.Va path
+argument is valid and references a directory.
+The
+.Fn checkpath
+function returns zero on success or non-zero on failure.
+.Pp
+The
+.Fn rmslashes
+function removes all double slashes and trailing slashes from its
+.Va rrpin
+pathname parameter and returns the resulting pathname in its
+.Va rrpout
+parameter.
+.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 ,
+.Xr nmount 8
+.Sh HISTORY
+The
+.Fn getmntopts
+function appeared in
+.Bx 4.4 .
+The
+.Fn build_iovec ,
+.Fn build_iovec_argf ,
+.Fn free_iovec ,
+.Fn checkpath ,
+and
+.Fn rmslashes
+functions were added with
+.Xr nmount 8
+in
+.Fx 5.0 .
+The
+.Fn getmntpoint
+and
+.Fn chkdoreload
+functions were added in
+.Fx 14.0 .
diff --git a/sbin/mount/mntopts.h b/sbin/mount/mntopts.h
index 1d8b80069355..3488d34fe96c 100644
--- a/sbin/mount/mntopts.h
+++ b/sbin/mount/mntopts.h
@@ -104,6 +104,8 @@ void getmntopts(const char *, const struct mntopt *, int *, int *);
void rmslashes(char *, char *);
int checkpath(const char *, char resolved_path[]);
int checkpath_allow_file(const char *, char resolved_path[]);
+struct statfs *getmntpoint(const char *);
+int chkdoreload(struct statfs *, void (*)(const char *, ...) __printflike(1,2));
extern int getmnt_silent;
void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len);
void build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, const char *fmt, ...);
diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c
index 66c1c1d1d000..22e596eaafbc 100644
--- a/sbin/mount/mount.c
+++ b/sbin/mount/mount.c
@@ -85,7 +85,6 @@ struct cpa {
};
char *catopt(char *, const char *);
-struct statfs *getmntpt(const char *);
int hasopt(const char *, const char *);
int ismounted(struct fstab *, struct statfs *, int);
int isremountable(const char *);
@@ -394,7 +393,7 @@ main(int argc, char *argv[])
if (init_flags & MNT_UPDATE) {
mntfromname = NULL;
have_fstab = 0;
- if ((mntbuf = getmntpt(*argv)) == NULL)
+ if ((mntbuf = getmntpoint(*argv)) == NULL)
xo_errx(1, "not currently mounted %s", *argv);
/*
* Only get the mntflags from fstab if both mntpoint
@@ -738,21 +737,6 @@ prmount(struct statfs *sfp)
xo_emit("{D:)}\n");
}
-struct statfs *
-getmntpt(const char *name)
-{
- struct statfs *mntbuf;
- int i, mntsize;
-
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = mntsize - 1; i >= 0; i--) {
- if (strcmp(mntbuf[i].f_mntfromname, name) == 0 ||
- strcmp(mntbuf[i].f_mntonname, name) == 0)
- return (&mntbuf[i]);
- }
- return (NULL);
-}
-
char *
catopt(char *s0, const char *s1)
{
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index 3e0e609c2b2c..872c26f673b0 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -89,18 +89,14 @@ main(int argc, char *argv[])
{
const char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue;
const char *tvalue;
- const char *special, *on;
+ const char *special;
const char *name;
- int active;
+ char *diskname;
int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, kflag;
int kvalue, Lflag, lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue;
int pflag, sflag, svalue, Svalue, tflag;
int ch, found_arg, i;
- int iovlen = 0;
const char *chg[2];
- struct statfs stfs;
- struct iovec *iov = NULL;
- char errmsg[255] = {0};
if (argc < 3)
usage();
@@ -108,7 +104,6 @@ main(int argc, char *argv[])
lflag = mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0;
avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL;
evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0;
- active = 0;
found_arg = 0; /* At least one arg is required. */
while ((ch = getopt(argc, argv, "Aa:e:f:j:J:k:L:l:m:N:n:o:ps:S:t:"))
!= -1)
@@ -307,7 +302,7 @@ main(int argc, char *argv[])
if (found_arg == 0 || argc != 1)
usage();
- on = special = argv[0];
+ special = argv[0];
if (ufs_disk_fillout(&disk, special) == -1)
goto err;
/*
@@ -317,13 +312,6 @@ main(int argc, char *argv[])
(sblock.fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) != 0) &&
(found_arg > 1 || !pflag))
errx(1, "%s is not clean - run fsck.\n", special);
- if (disk.d_name != special) {
- if (statfs(special, &stfs) != 0)
- warn("Can't stat %s", special);
- if (strcmp(special, stfs.f_mntonname) == 0)
- active = 1;
- }
-
if (pflag) {
printfs();
exit(0);
@@ -568,20 +556,9 @@ main(int argc, char *argv[])
if (sbwrite(&disk, Aflag) == -1)
goto err;
+ diskname = strdup(disk.d_name);
ufs_disk_close(&disk);
- if (active) {
- build_iovec_argf(&iov, &iovlen, "fstype", "ufs");
- build_iovec_argf(&iov, &iovlen, "fspath", "%s", on);
- build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
- if (nmount(iov, iovlen,
- stfs.f_flags | MNT_UPDATE | MNT_RELOAD) < 0) {
- if (errmsg[0])
- err(9, "%s: reload: %s", special, errmsg);
- else
- err(9, "%s: reload", special);
- }
- warnx("file system reloaded");
- }
+ chkdoreload(getmntpoint(diskname), warnx);
exit(0);
err:
if (disk.d_error != NULL)