git: 6eefabd4ca40 - main - syscalls: improve nstat, nfstat, nlstat
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 22 Nov 2021 22:37:40 UTC
The branch main has been updated by brooks:
URL: https://cgit.FreeBSD.org/src/commit/?id=6eefabd4ca40348f0bc0ab829bceb3a308e577b7
commit 6eefabd4ca40348f0bc0ab829bceb3a308e577b7
Author: Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2021-11-22 22:36:56 +0000
Commit: Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2021-11-22 22:36:56 +0000
syscalls: improve nstat, nfstat, nlstat
Optionally return errors when truncating dev_t, ino_t, and nlink_t.
In the interest of code reuse, use freebsd11_cvtstat() to perform the
truncation and error handling and then convert the resulting struct
freebsd11_stat to struct nstat.
Add missing freebsd32 compat syscalls. These syscalls require
translation because struct nstat contains four instances of struct
timespec which in turn contains a time_t and a long.
Reviewed by: kib
---
sys/compat/freebsd32/freebsd32.h | 25 ++++++++++
sys/compat/freebsd32/freebsd32_misc.c | 87 +++++++++++++++++++++++++++++++++++
sys/compat/freebsd32/syscalls.master | 10 ++--
sys/kern/kern_descrip.c | 7 +--
sys/kern/vfs_syscalls.c | 56 +++++++++++++---------
sys/sys/vnode.h | 2 +-
6 files changed, 157 insertions(+), 30 deletions(-)
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index e5bb253aef78..4d5cea688a21 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -167,6 +167,31 @@ struct ostatfs32 {
int32_t f_spare[2];
};
+struct nstat32 {
+ __uint32_t st_dev; /* inode's device */
+ __uint32_t st_ino; /* inode's number */
+ __uint32_t st_mode; /* inode protection mode */
+ __uint32_t st_nlink; /* number of hard links */
+ uid_t st_uid; /* user ID of the file's owner */
+ gid_t st_gid; /* group ID of the file's group */
+ __uint32_t st_rdev; /* device type */
+ struct timespec32 st_atim; /* time of last access */
+ struct timespec32 st_mtim; /* time of last data modification */
+ struct timespec32 st_ctim; /* time of last file status change */
+ off_t st_size; /* file size, in bytes */
+ blkcnt_t st_blocks; /* blocks allocated for file */
+ blksize_t st_blksize; /* optimal blocksize for I/O */
+ fflags_t st_flags; /* user defined flags for file */
+ __uint32_t st_gen; /* file generation number */
+ struct timespec32 st_birthtim; /* time of file creation */
+ /*
+ * See comment in the definition of struct freebsd11_stat
+ * in sys/stat.h about the following padding.
+ */
+ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
+ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
+};
+
struct iovec32 {
u_int32_t iov_base;
int iov_len;
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 69ae3a1cd85d..e81148d3577c 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -2473,6 +2473,93 @@ freebsd11_freebsd32_fhstat(struct thread *td,
error = copyout(&sb32, uap->sb, sizeof (sb32));
return (error);
}
+
+static int
+freebsd11_cvtnstat32(struct stat *sb, struct nstat32 *nsb32)
+{
+ struct nstat nsb;
+ int error;
+
+ error = freebsd11_cvtnstat(sb, &nsb);
+ if (error != 0)
+ return (error);
+
+ bzero(nsb32, sizeof(*nsb32));
+ CP(nsb, *nsb32, st_dev);
+ CP(nsb, *nsb32, st_ino);
+ CP(nsb, *nsb32, st_mode);
+ CP(nsb, *nsb32, st_nlink);
+ CP(nsb, *nsb32, st_uid);
+ CP(nsb, *nsb32, st_gid);
+ CP(nsb, *nsb32, st_rdev);
+ CP(nsb, *nsb32, st_atim.tv_sec);
+ CP(nsb, *nsb32, st_atim.tv_nsec);
+ CP(nsb, *nsb32, st_mtim.tv_sec);
+ CP(nsb, *nsb32, st_mtim.tv_nsec);
+ CP(nsb, *nsb32, st_ctim.tv_sec);
+ CP(nsb, *nsb32, st_ctim.tv_nsec);
+ CP(nsb, *nsb32, st_size);
+ CP(nsb, *nsb32, st_blocks);
+ CP(nsb, *nsb32, st_blksize);
+ CP(nsb, *nsb32, st_flags);
+ CP(nsb, *nsb32, st_gen);
+ CP(nsb, *nsb32, st_birthtim.tv_sec);
+ CP(nsb, *nsb32, st_birthtim.tv_nsec);
+ return (0);
+}
+
+int
+freebsd11_freebsd32_nstat(struct thread *td,
+ struct freebsd11_freebsd32_nstat_args *uap)
+{
+ struct stat sb;
+ struct nstat32 nsb;
+ int error;
+
+ error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
+ &sb, NULL);
+ if (error != 0)
+ return (error);
+ error = freebsd11_cvtnstat32(&sb, &nsb);
+ if (error != 0)
+ error = copyout(&nsb, uap->ub, sizeof (nsb));
+ return (error);
+}
+
+int
+freebsd11_freebsd32_nlstat(struct thread *td,
+ struct freebsd11_freebsd32_nlstat_args *uap)
+{
+ struct stat sb;
+ struct nstat32 nsb;
+ int error;
+
+ error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
+ UIO_USERSPACE, &sb, NULL);
+ if (error != 0)
+ return (error);
+ error = freebsd11_cvtnstat32(&sb, &nsb);
+ if (error == 0)
+ error = copyout(&nsb, uap->ub, sizeof (nsb));
+ return (error);
+}
+
+int
+freebsd11_freebsd32_nfstat(struct thread *td,
+ struct freebsd11_freebsd32_nfstat_args *uap)
+{
+ struct nstat32 nub;
+ struct stat ub;
+ int error;
+
+ error = kern_fstat(td, uap->fd, &ub);
+ if (error != 0)
+ return (error);
+ error = freebsd11_cvtnstat32(&ub, &nub);
+ if (error == 0)
+ error = copyout(&nub, uap->sb, sizeof(nub));
+ return (error);
+}
#endif
int
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 2e11fdb03a17..4fd7b2235d99 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -525,11 +525,11 @@
276 AUE_LUTIMES STD { int freebsd32_lutimes(const char *path, \
const struct timeval32 *tptr); }
277 AUE_NULL OBSOL netbsd_msync
-278 AUE_STAT COMPAT11|NOPROTO { int nstat(const char *path, \
- struct nstat *ub); }
-279 AUE_FSTAT COMPAT11|NOPROTO { int nfstat(int fd, struct nstat *sb); }
-280 AUE_LSTAT COMPAT11|NOPROTO { int nlstat(const char *path, \
- struct nstat *ub); }
+278 AUE_STAT COMPAT11 { int freebsd32_nstat(const char *path, \
+ struct nstat32 *ub); }
+279 AUE_FSTAT COMPAT11 { int freebsd32_nfstat(int fd, struct nstat32 *sb); }
+280 AUE_LSTAT COMPAT11 { int freebsd32_nlstat(const char *path, \
+ struct nstat32 *ub); }
281 AUE_NULL RESERVED
282 AUE_NULL RESERVED
283 AUE_NULL RESERVED
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 37d978e96de5..37fec097dcfc 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1561,10 +1561,11 @@ freebsd11_nfstat(struct thread *td, struct freebsd11_nfstat_args *uap)
int error;
error = kern_fstat(td, uap->fd, &ub);
- if (error == 0) {
- freebsd11_cvtnstat(&ub, &nub);
+ if (error != 0)
+ return (error);
+ error = freebsd11_cvtnstat(&ub, &nub);
+ if (error != 0)
error = copyout(&nub, uap->sb, sizeof(nub));
- }
return (error);
}
#endif /* COMPAT_FREEBSD11 */
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 1cffe903aef3..4391853337bd 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -44,6 +44,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#ifdef COMPAT_FREEBSD11
+#include <sys/abi_compat.h>
+#endif
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/capsicum.h>
@@ -2475,27 +2478,34 @@ kern_statat(struct thread *td, int flag, int fd, const char *path,
/*
* Implementation of the NetBSD [l]stat() functions.
*/
-void
+int
freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb)
{
+ struct freebsd11_stat sb11;
+ int error;
+
+ error = freebsd11_cvtstat(sb, &sb11);
+ if (error != 0)
+ return (error);
bzero(nsb, sizeof(*nsb));
- nsb->st_dev = sb->st_dev;
- nsb->st_ino = sb->st_ino;
- nsb->st_mode = sb->st_mode;
- nsb->st_nlink = sb->st_nlink;
- nsb->st_uid = sb->st_uid;
- nsb->st_gid = sb->st_gid;
- nsb->st_rdev = sb->st_rdev;
- nsb->st_atim = sb->st_atim;
- nsb->st_mtim = sb->st_mtim;
- nsb->st_ctim = sb->st_ctim;
- nsb->st_size = sb->st_size;
- nsb->st_blocks = sb->st_blocks;
- nsb->st_blksize = sb->st_blksize;
- nsb->st_flags = sb->st_flags;
- nsb->st_gen = sb->st_gen;
- nsb->st_birthtim = sb->st_birthtim;
+ CP(sb11, *nsb, st_dev);
+ CP(sb11, *nsb, st_ino);
+ CP(sb11, *nsb, st_mode);
+ CP(sb11, *nsb, st_nlink);
+ CP(sb11, *nsb, st_uid);
+ CP(sb11, *nsb, st_gid);
+ CP(sb11, *nsb, st_rdev);
+ CP(sb11, *nsb, st_atim);
+ CP(sb11, *nsb, st_mtim);
+ CP(sb11, *nsb, st_ctim);
+ CP(sb11, *nsb, st_size);
+ CP(sb11, *nsb, st_blocks);
+ CP(sb11, *nsb, st_blksize);
+ CP(sb11, *nsb, st_flags);
+ CP(sb11, *nsb, st_gen);
+ CP(sb11, *nsb, st_birthtim);
+ return (0);
}
#ifndef _SYS_SYSPROTO_H_
@@ -2515,8 +2525,10 @@ freebsd11_nstat(struct thread *td, struct freebsd11_nstat_args *uap)
&sb, NULL);
if (error != 0)
return (error);
- freebsd11_cvtnstat(&sb, &nsb);
- return (copyout(&nsb, uap->ub, sizeof (nsb)));
+ error = freebsd11_cvtnstat(&sb, &nsb);
+ if (error == 0)
+ error = copyout(&nsb, uap->ub, sizeof (nsb));
+ return (error);
}
/*
@@ -2539,8 +2551,10 @@ freebsd11_nlstat(struct thread *td, struct freebsd11_nlstat_args *uap)
UIO_USERSPACE, &sb, NULL);
if (error != 0)
return (error);
- freebsd11_cvtnstat(&sb, &nsb);
- return (copyout(&nsb, uap->ub, sizeof (nsb)));
+ error = freebsd11_cvtnstat(&sb, &nsb);
+ if (error == 0)
+ error = copyout(&nsb, uap->ub, sizeof (nsb));
+ return (error);
}
#endif /* COMPAT_FREEBSD11 */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 1a202abfd4dd..3d04b6f68784 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -682,7 +682,7 @@ cache_validate(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
void cache_fast_lookup_enabled_recalc(void);
int change_dir(struct vnode *vp, struct thread *td);
void cvtstat(struct stat *st, struct ostat *ost);
-void freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb);
+int freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb);
int freebsd11_cvtstat(struct stat *st, struct freebsd11_stat *ost);
int getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
struct vnode **vpp);