Module Name:    src
Committed By:   ryo
Date:           Thu Nov 25 02:27:09 UTC 2021

Modified Files:
        src/sys/compat/linux/common: linux_fcntl.h linux_file64.c linux_types.h
        src/sys/compat/linux32/common: linux32_stat.c linux32_types.h

Log Message:
- Add compat_linux statx(2) syscall.
- The AT_EMPTY_PATH processing from the modification of
  sys/compat/linux/common/linux_file64.c r1.63 has been separated, and made
  common to linux_statat(), so that it can be used not only by
  linux32_sys_fstatat64() but also by other *statat() variants.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/compat/linux/common/linux_fcntl.h
cvs rdiff -u -r1.66 -r1.67 src/sys/compat/linux/common/linux_file64.c
cvs rdiff -u -r1.32 -r1.33 src/sys/compat/linux/common/linux_types.h
cvs rdiff -u -r1.17 -r1.18 src/sys/compat/linux32/common/linux32_stat.c
cvs rdiff -u -r1.15 -r1.16 src/sys/compat/linux32/common/linux32_types.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/linux/common/linux_fcntl.h
diff -u src/sys/compat/linux/common/linux_fcntl.h:1.19 src/sys/compat/linux/common/linux_fcntl.h:1.20
--- src/sys/compat/linux/common/linux_fcntl.h:1.19	Thu Sep 23 06:56:27 2021
+++ src/sys/compat/linux/common/linux_fcntl.h	Thu Nov 25 02:27:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_fcntl.h,v 1.19 2021/09/23 06:56:27 ryo Exp $	*/
+/*	$NetBSD: linux_fcntl.h,v 1.20 2021/11/25 02:27:08 ryo Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -52,6 +52,8 @@
 
 int linux_to_bsd_ioflags(int);
 int linux_to_bsd_atflags(int);
+int bsd_to_linux_statx(struct stat *, struct linux_statx *, unsigned int);
+int linux_statat(struct lwp *, int, const char *, int, struct stat *);
 
 struct linux_flock {
 	short       l_type;

Index: src/sys/compat/linux/common/linux_file64.c
diff -u src/sys/compat/linux/common/linux_file64.c:1.66 src/sys/compat/linux/common/linux_file64.c:1.67
--- src/sys/compat/linux/common/linux_file64.c:1.66	Thu Nov 25 02:09:23 2021
+++ src/sys/compat/linux/common/linux_file64.c	Thu Nov 25 02:27:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_file64.c,v 1.66 2021/11/25 02:09:23 ryo Exp $	*/
+/*	$NetBSD: linux_file64.c,v 1.67 2021/11/25 02:27:08 ryo Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_file64.c,v 1.66 2021/11/25 02:09:23 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_file64.c,v 1.67 2021/11/25 02:27:08 ryo Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -65,6 +65,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_file64
 #include <compat/linux/common/linux_ipc.h>
 #include <compat/linux/common/linux_sem.h>
 
+#include <compat/linux/linux_syscall.h>
 #include <compat/linux/linux_syscallargs.h>
 
 static void bsd_to_linux_stat64(struct stat *, struct linux_stat64 *);
@@ -107,6 +108,73 @@ bsd_to_linux_stat64(struct stat *bsp, st
 #  endif
 }
 
+int
+bsd_to_linux_statx(struct stat *st, struct linux_statx *stx,
+    unsigned int mask)
+{
+	if (mask & STATX__RESERVED)
+		return EINVAL;
+
+	/* XXX: STATX_MNT_ID is not supported */
+	unsigned int rmask = STATX_TYPE | STATX_MODE | STATX_NLINK |
+	    STATX_UID | STATX_GID | STATX_ATIME | STATX_MTIME | STATX_CTIME |
+	    STATX_INO | STATX_SIZE | STATX_BLOCKS | STATX_BTIME;
+
+	memset(stx, 0, sizeof(*stx));
+
+	if ((st->st_flags & UF_NODUMP) != 0)
+		stx->stx_attributes |= STATX_ATTR_NODUMP;
+	if ((st->st_flags & (UF_IMMUTABLE|SF_IMMUTABLE)) != 0)
+		stx->stx_attributes |= STATX_ATTR_IMMUTABLE;
+	if ((st->st_flags & (UF_APPEND|SF_APPEND)) != 0)
+		stx->stx_attributes |= STATX_ATTR_APPEND;
+
+	stx->stx_attributes_mask =
+	    STATX_ATTR_NODUMP | STATX_ATTR_IMMUTABLE | STATX_ATTR_APPEND;
+
+	stx->stx_blksize = st->st_blksize;
+
+	stx->stx_nlink = st->st_nlink;
+	stx->stx_uid = st->st_uid;
+	stx->stx_gid = st->st_gid;
+	stx->stx_mode |= st->st_mode & S_IFMT;
+	stx->stx_mode |= st->st_mode & ~S_IFMT;
+	stx->stx_ino = st->st_ino;
+	stx->stx_size = st->st_size;
+	stx->stx_blocks = st->st_blocks;
+
+	stx->stx_atime.tv_sec = st->st_atime;
+	stx->stx_atime.tv_nsec = st->st_atimensec;
+
+	/* some filesystem has no birthtime returns 0 or -1 */
+	if ((st->st_birthtime == 0 && st->st_birthtimensec == 0) ||
+	    (st->st_birthtime == (time_t)-1 &&
+	    st->st_birthtimensec == (long)-1)) {
+		rmask &= ~STATX_BTIME;
+	} else {
+		stx->stx_btime.tv_sec = st->st_birthtime;
+		stx->stx_btime.tv_nsec = st->st_birthtimensec;
+	}
+
+	stx->stx_ctime.tv_sec = st->st_ctime;
+	stx->stx_ctime.tv_nsec = st->st_ctimensec;
+
+	stx->stx_mtime.tv_sec = st->st_mtime;
+	stx->stx_mtime.tv_nsec = st->st_mtimensec;
+
+	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+		stx->stx_rdev_major = major(st->st_rdev);
+		stx->stx_rdev_minor = minor(st->st_rdev);
+	} else {
+		stx->stx_dev_major = major(st->st_rdev);
+		stx->stx_dev_minor = minor(st->st_rdev);
+	}
+
+	stx->stx_mask = rmask;
+
+	return 0;
+}
+
 /*
  * The stat functions below are plain sailing. stat and lstat are handled
  * by one function to avoid code duplication.
@@ -171,65 +239,105 @@ linux_sys_lstat64(struct lwp *l, const s
 }
 #endif
 
+/*
+ * This is an internal function for the *statat() variant of linux,
+ * which returns struct stat, but flags and other handling are
+ * the same as in linux.
+ */
 int
-linux_sys_fstatat64(struct lwp *l, const struct linux_sys_fstatat64_args *uap, register_t *retval)
+linux_statat(struct lwp *l, int fd, const char *path, int lflag,
+    struct stat *st)
 {
-	/* {
-		syscallarg(int) fd;
-		syscallarg(const char *) path;
-		syscallarg(struct linux_stat64 *) sp;
-		syscallarg(int) flag;
-	} */
-	struct linux_stat64 tmplst;
-	struct stat tmpst;
 	struct vnode *vp;
-	int error, nd_flag, fd;
+	int error, nd_flag;
 	uint8_t c;
 
-	if (SCARG(uap, flag) & LINUX_AT_EMPTY_PATH) {
+	if (lflag & LINUX_AT_EMPTY_PATH) {
 		/*
 		 * If path is null string:
 		 */
-		error = ufetch_8(SCARG(uap, path), &c);
+		error = ufetch_8(path, &c);
 		if (error != 0)
 			return error;
 		if (c == '\0') {
-			fd = SCARG(uap, fd);
-			if (fd == AT_FDCWD) {
+			if (fd == LINUX_AT_FDCWD) {
 				/*
 				 * operate on current directory
 				 */
 				vp = l->l_proc->p_cwdi->cwdi_cdir;
 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-				error = vn_stat(vp, &tmpst);
+				error = vn_stat(vp, st);
 				VOP_UNLOCK(vp);
 			} else {
 				/*
 				 * operate on fd
 				 */
-				error = do_sys_fstat(fd, &tmpst);
+				error = do_sys_fstat(fd, st);
 			}
-			if (error != 0)
-				return error;
-			goto done;
+			return error;
 		}
 	}
 
-	if (SCARG(uap, flag) & LINUX_AT_SYMLINK_NOFOLLOW)
+	if (lflag & LINUX_AT_SYMLINK_NOFOLLOW)
 		nd_flag = NOFOLLOW;
 	else
 		nd_flag = FOLLOW;
 
-	error = do_sys_statat(l, SCARG(uap, fd), SCARG(uap, path), nd_flag, &tmpst);
+	return do_sys_statat(l, fd, path, nd_flag, st);
+}
+
+int
+linux_sys_fstatat64(struct lwp *l, const struct linux_sys_fstatat64_args *uap, register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(const char *) path;
+		syscallarg(struct linux_stat64 *) sp;
+		syscallarg(int) flag;
+	} */
+	struct linux_stat64 tmplst;
+	struct stat tmpst;
+	int error;
+
+	error = linux_statat(l, SCARG(uap, fd), SCARG(uap, path),
+	    SCARG(uap, flag), &tmpst);
 	if (error != 0)
 		return error;
 
-done:
 	bsd_to_linux_stat64(&tmpst, &tmplst);
 
 	return copyout(&tmplst, SCARG(uap, sp), sizeof tmplst);
 }
 
+#ifdef LINUX_SYS_statx
+int
+linux_sys_statx(struct lwp *l, const struct linux_sys_statx_args *uap,
+    register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(const char *) path;
+		syscallarg(int) flag;
+		syscallarg(unsigned int) mask;
+		syscallarg(struct linux_statx *) sp;
+	} */
+	struct linux_statx stx;
+	struct stat st;
+	int error;
+
+	error = linux_statat(l, SCARG(uap, fd), SCARG(uap, path),
+	    SCARG(uap, flag), &st);
+	if (error != 0)
+		return error;
+
+	error = bsd_to_linux_statx(&st, &stx, SCARG(uap, mask));
+	if (error != 0)
+		return error;
+
+	return copyout(&stx, SCARG(uap, sp), sizeof stx);
+}
+#endif /* LINUX_SYS_statx */
+
 #ifndef __alpha__
 int
 linux_sys_truncate64(struct lwp *l, const struct linux_sys_truncate64_args *uap, register_t *retval)

Index: src/sys/compat/linux/common/linux_types.h
diff -u src/sys/compat/linux/common/linux_types.h:1.32 src/sys/compat/linux/common/linux_types.h:1.33
--- src/sys/compat/linux/common/linux_types.h:1.32	Thu Sep 23 06:56:27 2021
+++ src/sys/compat/linux/common/linux_types.h	Thu Nov 25 02:27:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_types.h,v 1.32 2021/09/23 06:56:27 ryo Exp $	*/
+/*	$NetBSD: linux_types.h,v 1.33 2021/11/25 02:27:08 ryo Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -173,4 +173,63 @@ struct linux_statfs64 {
 };
 #endif /* !LINUX_STATFS_64BIT */
 
+struct linux_statx_timestamp {
+	int64_t tv_sec;
+	uint32_t tv_nsec;
+	int32_t __reserved;
+};
+
+#define STATX_TYPE		0x00000001
+#define STATX_MODE		0x00000002
+#define STATX_NLINK		0x00000004
+#define STATX_UID		0x00000008
+#define STATX_GID		0x00000010
+#define STATX_ATIME		0x00000020
+#define STATX_MTIME		0x00000040
+#define STATX_CTIME		0x00000080
+#define STATX_INO		0x00000100
+#define STATX_SIZE		0x00000200
+#define STATX_BLOCKS		0x00000400
+#define STATX_BASIC_STATS	0x000007ff
+#define STATX_BTIME		0x00000800
+#define STATX_MNT_ID		0x00001000
+#define STATX_ALL		0x00000fff
+#define STATX__RESERVED		0x80000000
+
+#define STATX_ATTR_COMPRESSED	0x00000004
+#define STATX_ATTR_IMMUTABLE	0x00000010
+#define STATX_ATTR_APPEND	0x00000020
+#define STATX_ATTR_NODUMP	0x00000040
+#define STATX_ATTR_ENCRYPTED	0x00000800
+#define STATX_ATTR_AUTOMOUNT	0x00001000
+#define STATX_ATTR_MOUNT_ROOT	0x00002000
+#define STATX_ATTR_VERITY	0x00100000
+#define STATX_ATTR_DAX		0x00200000
+
+struct linux_statx {
+	uint32_t stx_mask;
+	uint32_t stx_blksize;
+	uint64_t stx_attributes;
+	uint32_t stx_nlink;
+	uint32_t stx_uid;
+	uint32_t stx_gid;
+	uint16_t stx_mode;
+	uint16_t __pad1;
+	uint64_t stx_ino;
+	uint64_t stx_size;
+	uint64_t stx_blocks;
+	uint64_t stx_attributes_mask;
+	struct linux_statx_timestamp stx_atime;
+	struct linux_statx_timestamp stx_btime;
+	struct linux_statx_timestamp stx_ctime;
+	struct linux_statx_timestamp stx_mtime;
+	uint32_t stx_rdev_major;
+	uint32_t stx_rdev_minor;
+	uint32_t stx_dev_major;
+	uint32_t stx_dev_minor;
+	uint64_t stx_mnt_id;
+	uint64_t __spare2;
+	uint64_t __spare3[12];
+} __packed;
+
 #endif /* !_LINUX_TYPES_H */

Index: src/sys/compat/linux32/common/linux32_stat.c
diff -u src/sys/compat/linux32/common/linux32_stat.c:1.17 src/sys/compat/linux32/common/linux32_stat.c:1.18
--- src/sys/compat/linux32/common/linux32_stat.c:1.17	Mon Nov 18 01:32:52 2013
+++ src/sys/compat/linux32/common/linux32_stat.c	Thu Nov 25 02:27:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux32_stat.c,v 1.17 2013/11/18 01:32:52 chs Exp $ */
+/*	$NetBSD: linux32_stat.c,v 1.18 2021/11/25 02:27:08 ryo Exp $ */
 
 /*-
  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -33,7 +33,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: linux32_stat.c,v 1.17 2013/11/18 01:32:52 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux32_stat.c,v 1.18 2021/11/25 02:27:08 ryo Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -73,6 +73,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_stat
 #include <compat/linux32/common/linux32_machdep.h>
 #include <compat/linux32/common/linux32_sysctl.h>
 #include <compat/linux32/common/linux32_socketcall.h>
+#include <compat/linux32/linux32_syscall.h>
 #include <compat/linux32/linux32_syscallargs.h>
 
 static inline void bsd_to_linux32_stat(struct stat *, struct linux32_stat *);
@@ -252,7 +253,8 @@ linux32_sys_fstat64(struct lwp *l, const
 }
 
 int
-linux32_sys_fstatat64(struct lwp *l, const struct linux32_sys_fstatat64_args *uap, register_t *retval)
+linux32_sys_fstatat64(struct lwp *l,
+    const struct linux32_sys_fstatat64_args *uap, register_t *retval)
 {
 	/* {
 		syscallarg(int) fd;
@@ -260,16 +262,12 @@ linux32_sys_fstatat64(struct lwp *l, con
 		syscallarg(linux32_stat64p) sp;
 		syscallarg(int) flag;
 	} */
-	int error, nd_flag;
-	struct stat st;
 	struct linux32_stat64 st32;
+	struct stat st;
+	int error;
 
-	if (SCARG(uap, flag) & LINUX_AT_SYMLINK_NOFOLLOW)
-		nd_flag = NOFOLLOW;
-	else
-		nd_flag = FOLLOW;
-
-	error = do_sys_statat(l, SCARG(uap, fd), SCARG_P32(uap, path), nd_flag, &st);
+	error = linux_statat(l, SCARG(uap, fd), SCARG_P32(uap, path),
+	    SCARG(uap, flag), &st);
 	if (error != 0)
 		return error;
 
@@ -277,3 +275,33 @@ linux32_sys_fstatat64(struct lwp *l, con
 
 	return copyout(&st32, SCARG_P32(uap, sp), sizeof st32);
 }
+
+#ifdef LINUX32_SYS_statx
+int
+linux32_sys_statx(struct lwp *l, const struct linux32_sys_statx_args *uap,
+    register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(netbsd32_charp) path;
+		syscallarg(int) flag;
+		syscallarg(unsigned int) mask;
+		syscallarg(linux32_statxp) sp;
+	} */
+	struct linux_statx stx;
+	struct stat st;
+	int error;
+
+	error = linux_statat(l, SCARG(uap, fd), SCARG_P32(uap, path),
+	    SCARG(uap, flag), &st);
+	if (error != 0)
+		return error;
+
+	/* struct statx has binary compatibilities between 32bit and 64bit */
+	error = bsd_to_linux_statx(&st, &stx, SCARG(uap, mask));
+	if (error != 0)
+		return error;
+
+	return copyout(&stx, SCARG_P32(uap, sp), sizeof stx);
+}
+#endif /* LINUX32_SYS_statx */

Index: src/sys/compat/linux32/common/linux32_types.h
diff -u src/sys/compat/linux32/common/linux32_types.h:1.15 src/sys/compat/linux32/common/linux32_types.h:1.16
--- src/sys/compat/linux32/common/linux32_types.h:1.15	Fri Nov 18 04:08:56 2011
+++ src/sys/compat/linux32/common/linux32_types.h	Thu Nov 25 02:27:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux32_types.h,v 1.15 2011/11/18 04:08:56 christos Exp $ */
+/*	$NetBSD: linux32_types.h,v 1.16 2021/11/25 02:27:08 ryo Exp $ */
 
 /*-
  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -47,6 +47,7 @@ typedef netbsd32_pointer_t linux32_stat6
 typedef netbsd32_pointer_t linux32_statp;
 typedef netbsd32_pointer_t linux32_statfsp;
 typedef netbsd32_pointer_t linux32_statfs64p;
+typedef netbsd32_pointer_t linux32_statxp;
 typedef netbsd32_pointer_t linux32_sigactionp_t;
 typedef netbsd32_pointer_t linux32_sigsetp_t;
 typedef netbsd32_pointer_t linux32___sysctlp_t;

Reply via email to