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;