- 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.
This commit is contained in:
parent
6d8ced6337
commit
5fe0554c47
|
@ -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;
|
||||
|
|
|
@ -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.c,v 1.66 2021/11/25 02:09:23 ryo Exp $"
|
|||
#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, struct linux_stat64 *lsp)
|
|||
# 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,6 +239,53 @@ linux_sys_lstat64(struct lwp *l, const struct linux_sys_lstat64_args *uap, regis
|
|||
}
|
||||
#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_statat(struct lwp *l, int fd, const char *path, int lflag,
|
||||
struct stat *st)
|
||||
{
|
||||
struct vnode *vp;
|
||||
int error, nd_flag;
|
||||
uint8_t c;
|
||||
|
||||
if (lflag & LINUX_AT_EMPTY_PATH) {
|
||||
/*
|
||||
* If path is null string:
|
||||
*/
|
||||
error = ufetch_8(path, &c);
|
||||
if (error != 0)
|
||||
return error;
|
||||
if (c == '\0') {
|
||||
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, st);
|
||||
VOP_UNLOCK(vp);
|
||||
} else {
|
||||
/*
|
||||
* operate on fd
|
||||
*/
|
||||
error = do_sys_fstat(fd, st);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (lflag & LINUX_AT_SYMLINK_NOFOLLOW)
|
||||
nd_flag = NOFOLLOW;
|
||||
else
|
||||
nd_flag = FOLLOW;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -182,54 +297,47 @@ linux_sys_fstatat64(struct lwp *l, const struct linux_sys_fstatat64_args *uap, r
|
|||
} */
|
||||
struct linux_stat64 tmplst;
|
||||
struct stat tmpst;
|
||||
struct vnode *vp;
|
||||
int error, nd_flag, fd;
|
||||
uint8_t c;
|
||||
int error;
|
||||
|
||||
if (SCARG(uap, flag) & LINUX_AT_EMPTY_PATH) {
|
||||
/*
|
||||
* If path is null string:
|
||||
*/
|
||||
error = ufetch_8(SCARG(uap, path), &c);
|
||||
if (error != 0)
|
||||
return error;
|
||||
if (c == '\0') {
|
||||
fd = SCARG(uap, fd);
|
||||
if (fd == 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);
|
||||
VOP_UNLOCK(vp);
|
||||
} else {
|
||||
/*
|
||||
* operate on fd
|
||||
*/
|
||||
error = do_sys_fstat(fd, &tmpst);
|
||||
}
|
||||
if (error != 0)
|
||||
return error;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (SCARG(uap, flag) & 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);
|
||||
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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.c,v 1.17 2013/11/18 01:32:52 chs Exp $"
|
|||
#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 struct linux32_sys_fstat64_args *uap, r
|
|||
}
|
||||
|
||||
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, const struct linux32_sys_fstatat64_args *ua
|
|||
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, const struct linux32_sys_fstatat64_args *ua
|
|||
|
||||
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 */
|
||||
|
|
|
@ -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_stat64p;
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue