1c21dee17SSøren Schmidt /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
37f2d13d6SPedro F. Giffuni *
49a14aa01SUlrich Spörlein * Copyright (c) 1994-1995 Søren Schmidt
5c21dee17SSøren Schmidt * All rights reserved.
6c21dee17SSøren Schmidt *
7c21dee17SSøren Schmidt * Redistribution and use in source and binary forms, with or without
8c21dee17SSøren Schmidt * modification, are permitted provided that the following conditions
9c21dee17SSøren Schmidt * are met:
10c21dee17SSøren Schmidt * 1. Redistributions of source code must retain the above copyright
110ba1b365SEd Maste * notice, this list of conditions and the following disclaimer.
12c21dee17SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright
13c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer in the
14c21dee17SSøren Schmidt * documentation and/or other materials provided with the distribution.
15c21dee17SSøren Schmidt *
160ba1b365SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170ba1b365SEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180ba1b365SEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190ba1b365SEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200ba1b365SEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210ba1b365SEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220ba1b365SEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230ba1b365SEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240ba1b365SEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250ba1b365SEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260ba1b365SEd Maste * SUCH DAMAGE.
27c21dee17SSøren Schmidt */
28c21dee17SSøren Schmidt
29cb858340SDmitry Chagin #include "opt_ktrace.h"
30cb858340SDmitry Chagin
31c21dee17SSøren Schmidt #include <sys/param.h>
329802eb9eSDmitry Chagin #include <sys/capsicum.h>
33c21dee17SSøren Schmidt #include <sys/dirent.h>
34d8e53d94SDmitry Chagin #include <sys/lock.h>
3585422e62SBruce Evans #include <sys/malloc.h>
36d8e53d94SDmitry Chagin #include <sys/mutex.h>
37cb858340SDmitry Chagin #include <sys/namei.h>
38d8e53d94SDmitry Chagin #include <sys/proc.h>
39c21dee17SSøren Schmidt #include <sys/stat.h>
40f7a25872SJohn Baldwin #include <sys/syscallsubr.h>
41bc093719SEd Schouten #include <sys/tty.h>
42c21dee17SSøren Schmidt #include <sys/vnode.h>
43cb858340SDmitry Chagin #ifdef KTRACE
44cb858340SDmitry Chagin #include <sys/ktrace.h>
45cb858340SDmitry Chagin #endif
46c21dee17SSøren Schmidt
47994ed958SDmitry Chagin #include <security/audit/audit.h>
48994ed958SDmitry Chagin
491997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
504af27623STim J. Robbins #include <machine/../linux32/linux.h>
514af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
521997c537SDavid E. O'Brien #else
531997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
541997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
554af27623STim J. Robbins #endif
5685422e62SBruce Evans
57166e2e5aSDmitry Chagin #include <compat/linux/linux.h>
5848b05c3fSKonstantin Belousov #include <compat/linux/linux_file.h>
592a38f51cSDmitry Chagin #include <compat/linux/linux_util.h>
60762e6b85SEivind Eklund
610eee862aSEd Schouten
620eee862aSEd Schouten static int
linux_kern_fstat(struct thread * td,int fd,struct stat * sbp)63994ed958SDmitry Chagin linux_kern_fstat(struct thread *td, int fd, struct stat *sbp)
64994ed958SDmitry Chagin {
65994ed958SDmitry Chagin struct vnode *vp;
66994ed958SDmitry Chagin struct file *fp;
67994ed958SDmitry Chagin int error;
68994ed958SDmitry Chagin
69994ed958SDmitry Chagin AUDIT_ARG_FD(fd);
70994ed958SDmitry Chagin
71994ed958SDmitry Chagin error = fget(td, fd, &cap_fstat_rights, &fp);
72994ed958SDmitry Chagin if (__predict_false(error != 0))
73994ed958SDmitry Chagin return (error);
74994ed958SDmitry Chagin
75994ed958SDmitry Chagin AUDIT_ARG_FILE(td->td_proc, fp);
76994ed958SDmitry Chagin
77994ed958SDmitry Chagin error = fo_stat(fp, sbp, td->td_ucred);
78994ed958SDmitry Chagin if (error == 0 && (vp = fp->f_vnode) != NULL)
79994ed958SDmitry Chagin translate_vnhook_major_minor(vp, sbp);
80994ed958SDmitry Chagin fdrop(fp, td);
81994ed958SDmitry Chagin #ifdef KTRACE
82994ed958SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
83994ed958SDmitry Chagin ktrstat_error(sbp, error);
84994ed958SDmitry Chagin #endif
85994ed958SDmitry Chagin return (error);
86994ed958SDmitry Chagin }
87994ed958SDmitry Chagin
88994ed958SDmitry Chagin static int
linux_kern_statat(struct thread * td,int flag,int fd,const char * path,enum uio_seg pathseg,struct stat * sbp)89a125ed50SMateusz Guzik linux_kern_statat(struct thread *td, int flag, int fd, const char *path,
900eee862aSEd Schouten enum uio_seg pathseg, struct stat *sbp)
910eee862aSEd Schouten {
92cb858340SDmitry Chagin struct nameidata nd;
93cb858340SDmitry Chagin int error;
940eee862aSEd Schouten
95cb858340SDmitry Chagin if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH |
96cb858340SDmitry Chagin AT_EMPTY_PATH)) != 0)
97cb858340SDmitry Chagin return (EINVAL);
98cb858340SDmitry Chagin
99cb858340SDmitry Chagin NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_RESOLVE_BENEATH |
100cb858340SDmitry Chagin AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH) | LOCKSHARED | LOCKLEAF |
101cb858340SDmitry Chagin AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights);
102cb858340SDmitry Chagin
103cb858340SDmitry Chagin if ((error = namei(&nd)) != 0) {
104cb858340SDmitry Chagin if (error == ENOTDIR &&
105cb858340SDmitry Chagin (nd.ni_resflags & NIRES_EMPTYPATH) != 0)
106994ed958SDmitry Chagin error = linux_kern_fstat(td, fd, sbp);
107cb858340SDmitry Chagin return (error);
108cb858340SDmitry Chagin }
109cb858340SDmitry Chagin error = VOP_STAT(nd.ni_vp, sbp, td->td_ucred, NOCRED);
110cb858340SDmitry Chagin if (error == 0)
111cb858340SDmitry Chagin translate_vnhook_major_minor(nd.ni_vp, sbp);
112cb858340SDmitry Chagin NDFREE_PNBUF(&nd);
113cb858340SDmitry Chagin vput(nd.ni_vp);
114cb858340SDmitry Chagin #ifdef KTRACE
115cb858340SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT))
116cb858340SDmitry Chagin ktrstat_error(sbp, error);
117cb858340SDmitry Chagin #endif
118cb858340SDmitry Chagin return (error);
1190eee862aSEd Schouten }
1200eee862aSEd Schouten
121931e2a1aSEd Maste #ifdef LINUX_LEGACY_SYSCALLS
1220eee862aSEd Schouten static int
linux_kern_stat(struct thread * td,const char * path,enum uio_seg pathseg,struct stat * sbp)123a125ed50SMateusz Guzik linux_kern_stat(struct thread *td, const char *path, enum uio_seg pathseg,
1240eee862aSEd Schouten struct stat *sbp)
1250eee862aSEd Schouten {
1260eee862aSEd Schouten
1270eee862aSEd Schouten return (linux_kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp));
1280eee862aSEd Schouten }
1290eee862aSEd Schouten
1300eee862aSEd Schouten static int
linux_kern_lstat(struct thread * td,const char * path,enum uio_seg pathseg,struct stat * sbp)131a125ed50SMateusz Guzik linux_kern_lstat(struct thread *td, const char *path, enum uio_seg pathseg,
1320eee862aSEd Schouten struct stat *sbp)
1330eee862aSEd Schouten {
1340eee862aSEd Schouten
1350eee862aSEd Schouten return (linux_kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
1360eee862aSEd Schouten pathseg, sbp));
1370eee862aSEd Schouten }
138931e2a1aSEd Maste #endif
1390eee862aSEd Schouten
140bbbc2d96SPoul-Henning Kamp static int
newstat_copyout(struct stat * buf,void * ubuf)141bbbc2d96SPoul-Henning Kamp newstat_copyout(struct stat *buf, void *ubuf)
142bbbc2d96SPoul-Henning Kamp {
143bbbc2d96SPoul-Henning Kamp struct l_newstat tbuf;
144bbbc2d96SPoul-Henning Kamp
145bbbc2d96SPoul-Henning Kamp bzero(&tbuf, sizeof(tbuf));
146166e2e5aSDmitry Chagin tbuf.st_dev = linux_new_encode_dev(buf->st_dev);
147bbbc2d96SPoul-Henning Kamp tbuf.st_ino = buf->st_ino;
148bbbc2d96SPoul-Henning Kamp tbuf.st_mode = buf->st_mode;
149bbbc2d96SPoul-Henning Kamp tbuf.st_nlink = buf->st_nlink;
150bbbc2d96SPoul-Henning Kamp tbuf.st_uid = buf->st_uid;
151bbbc2d96SPoul-Henning Kamp tbuf.st_gid = buf->st_gid;
152166e2e5aSDmitry Chagin tbuf.st_rdev = linux_new_encode_dev(buf->st_rdev);
153bbbc2d96SPoul-Henning Kamp tbuf.st_size = buf->st_size;
154510ea843SEd Schouten tbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
155510ea843SEd Schouten tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
156510ea843SEd Schouten tbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
157510ea843SEd Schouten tbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
158510ea843SEd Schouten tbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
159510ea843SEd Schouten tbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
160bbbc2d96SPoul-Henning Kamp tbuf.st_blksize = buf->st_blksize;
161bbbc2d96SPoul-Henning Kamp tbuf.st_blocks = buf->st_blocks;
162bbbc2d96SPoul-Henning Kamp
1634e0eaf69SMarcel Moolenaar return (copyout(&tbuf, ubuf, sizeof(tbuf)));
164c21dee17SSøren Schmidt }
165c21dee17SSøren Schmidt
1662362ad45SPhilippe Michaud-Boudreault
167931e2a1aSEd Maste #ifdef LINUX_LEGACY_SYSCALLS
168c21dee17SSøren Schmidt int
linux_newstat(struct thread * td,struct linux_newstat_args * args)169b40ce416SJulian Elischer linux_newstat(struct thread *td, struct linux_newstat_args *args)
170c21dee17SSøren Schmidt {
171c21dee17SSøren Schmidt struct stat buf;
172c21dee17SSøren Schmidt int error;
173d66a5066SPeter Wemm
174a125ed50SMateusz Guzik error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf);
1754e0eaf69SMarcel Moolenaar if (error)
1764e0eaf69SMarcel Moolenaar return (error);
1774e0eaf69SMarcel Moolenaar return (newstat_copyout(&buf, args->buf));
178c21dee17SSøren Schmidt }
179c21dee17SSøren Schmidt
180c21dee17SSøren Schmidt int
linux_newlstat(struct thread * td,struct linux_newlstat_args * args)181b40ce416SJulian Elischer linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
182c21dee17SSøren Schmidt {
1834e0eaf69SMarcel Moolenaar struct stat sb;
184f7a25872SJohn Baldwin int error;
185d66a5066SPeter Wemm
186a125ed50SMateusz Guzik error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &sb);
187d66a5066SPeter Wemm if (error)
188d66a5066SPeter Wemm return (error);
1895002a60fSMarcel Moolenaar return (newstat_copyout(&sb, args->buf));
190d66a5066SPeter Wemm }
191931e2a1aSEd Maste #endif
192c21dee17SSøren Schmidt
193c21dee17SSøren Schmidt int
linux_newfstat(struct thread * td,struct linux_newfstat_args * args)194b40ce416SJulian Elischer linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
195c21dee17SSøren Schmidt {
196c21dee17SSøren Schmidt struct stat buf;
197c21dee17SSøren Schmidt int error;
198c21dee17SSøren Schmidt
199994ed958SDmitry Chagin error = linux_kern_fstat(td, args->fd, &buf);
200c21dee17SSøren Schmidt if (!error)
201c21dee17SSøren Schmidt error = newstat_copyout(&buf, args->buf);
2024e0eaf69SMarcel Moolenaar
2034e0eaf69SMarcel Moolenaar return (error);
204c21dee17SSøren Schmidt }
205c21dee17SSøren Schmidt
2067f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
207166e2e5aSDmitry Chagin
208166e2e5aSDmitry Chagin static __inline uint16_t
linux_old_encode_dev(dev_t _dev)209166e2e5aSDmitry Chagin linux_old_encode_dev(dev_t _dev)
210166e2e5aSDmitry Chagin {
211166e2e5aSDmitry Chagin
212166e2e5aSDmitry Chagin return (_dev == NODEV ? 0 : linux_encode_dev(major(_dev), minor(_dev)));
213166e2e5aSDmitry Chagin }
214166e2e5aSDmitry Chagin
2155c8919adSAlexander Leidinger static int
old_stat_copyout(struct stat * buf,void * ubuf)216a408fc09SDmitry Chagin old_stat_copyout(struct stat *buf, void *ubuf)
2175c8919adSAlexander Leidinger {
218a408fc09SDmitry Chagin struct l_old_stat lbuf;
2195c8919adSAlexander Leidinger
2205c8919adSAlexander Leidinger bzero(&lbuf, sizeof(lbuf));
221166e2e5aSDmitry Chagin lbuf.st_dev = linux_old_encode_dev(buf->st_dev);
2225c8919adSAlexander Leidinger lbuf.st_ino = buf->st_ino;
2235c8919adSAlexander Leidinger lbuf.st_mode = buf->st_mode;
2245c8919adSAlexander Leidinger lbuf.st_nlink = buf->st_nlink;
2255c8919adSAlexander Leidinger lbuf.st_uid = buf->st_uid;
2265c8919adSAlexander Leidinger lbuf.st_gid = buf->st_gid;
227166e2e5aSDmitry Chagin lbuf.st_rdev = linux_old_encode_dev(buf->st_rdev);
228372639f9SBruce Evans lbuf.st_size = MIN(buf->st_size, INT32_MAX);
229510ea843SEd Schouten lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
230510ea843SEd Schouten lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
231510ea843SEd Schouten lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
232510ea843SEd Schouten lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
233510ea843SEd Schouten lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
234510ea843SEd Schouten lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
2355c8919adSAlexander Leidinger lbuf.st_blksize = buf->st_blksize;
2365c8919adSAlexander Leidinger lbuf.st_blocks = buf->st_blocks;
2375c8919adSAlexander Leidinger lbuf.st_flags = buf->st_flags;
2385c8919adSAlexander Leidinger lbuf.st_gen = buf->st_gen;
2395c8919adSAlexander Leidinger
2405c8919adSAlexander Leidinger return (copyout(&lbuf, ubuf, sizeof(lbuf)));
2415c8919adSAlexander Leidinger }
2425c8919adSAlexander Leidinger
2435c8919adSAlexander Leidinger int
linux_stat(struct thread * td,struct linux_stat_args * args)2445c8919adSAlexander Leidinger linux_stat(struct thread *td, struct linux_stat_args *args)
2455c8919adSAlexander Leidinger {
2465c8919adSAlexander Leidinger struct stat buf;
2475c8919adSAlexander Leidinger int error;
24815b78ac5SKonstantin Belousov
249a125ed50SMateusz Guzik error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf);
250a125ed50SMateusz Guzik if (error) {
2515c8919adSAlexander Leidinger return (error);
252d075105dSKonstantin Belousov }
253a408fc09SDmitry Chagin return (old_stat_copyout(&buf, args->up));
2545c8919adSAlexander Leidinger }
2555c8919adSAlexander Leidinger
2565c8919adSAlexander Leidinger int
linux_lstat(struct thread * td,struct linux_lstat_args * args)2575c8919adSAlexander Leidinger linux_lstat(struct thread *td, struct linux_lstat_args *args)
2585c8919adSAlexander Leidinger {
2595c8919adSAlexander Leidinger struct stat buf;
2605c8919adSAlexander Leidinger int error;
2615c8919adSAlexander Leidinger
262a125ed50SMateusz Guzik error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &buf);
263a125ed50SMateusz Guzik if (error) {
2645c8919adSAlexander Leidinger return (error);
265d075105dSKonstantin Belousov }
266a408fc09SDmitry Chagin return (old_stat_copyout(&buf, args->up));
2675c8919adSAlexander Leidinger }
2687f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
2695c8919adSAlexander Leidinger
2705002a60fSMarcel Moolenaar struct l_statfs {
271297f61ccSDmitry Chagin l_long f_type;
272297f61ccSDmitry Chagin l_long f_bsize;
273297f61ccSDmitry Chagin l_long f_blocks;
274297f61ccSDmitry Chagin l_long f_bfree;
275297f61ccSDmitry Chagin l_long f_bavail;
276297f61ccSDmitry Chagin l_long f_files;
277297f61ccSDmitry Chagin l_long f_ffree;
2785002a60fSMarcel Moolenaar l_fsid_t f_fsid;
279297f61ccSDmitry Chagin l_long f_namelen;
280e801ac78SEdward Tomasz Napierala l_long f_frsize;
281e801ac78SEdward Tomasz Napierala l_long f_flags;
282e801ac78SEdward Tomasz Napierala l_long f_spare[4];
283c21dee17SSøren Schmidt };
284c21dee17SSøren Schmidt
285dca60efcSMarcel Moolenaar #define LINUX_CODA_SUPER_MAGIC 0x73757245L
286dca60efcSMarcel Moolenaar #define LINUX_EXT2_SUPER_MAGIC 0xEF53L
287dca60efcSMarcel Moolenaar #define LINUX_HPFS_SUPER_MAGIC 0xf995e849L
288dca60efcSMarcel Moolenaar #define LINUX_ISOFS_SUPER_MAGIC 0x9660L
289dca60efcSMarcel Moolenaar #define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
290dca60efcSMarcel Moolenaar #define LINUX_NCP_SUPER_MAGIC 0x564cL
291dca60efcSMarcel Moolenaar #define LINUX_NFS_SUPER_MAGIC 0x6969L
292dca60efcSMarcel Moolenaar #define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
293dca60efcSMarcel Moolenaar #define LINUX_PROC_SUPER_MAGIC 0x9fa0L
294dca60efcSMarcel Moolenaar #define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
295dbaa9ebfSEd Maste #define LINUX_ZFS_SUPER_MAGIC 0x2FC12FC1
296e83d253bSOlivier Houchard #define LINUX_DEVFS_SUPER_MAGIC 0x1373L
2972166e4e0SDmitry Chagin #define LINUX_SHMFS_MAGIC 0x01021994
298dca60efcSMarcel Moolenaar
299dca60efcSMarcel Moolenaar static long
bsd_to_linux_ftype(const char * fstypename)300962cf420SMaxim Sobolev bsd_to_linux_ftype(const char *fstypename)
301dca60efcSMarcel Moolenaar {
302962cf420SMaxim Sobolev int i;
303962cf420SMaxim Sobolev static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
304962cf420SMaxim Sobolev {"ufs", LINUX_UFS_SUPER_MAGIC},
305dbaa9ebfSEd Maste {"zfs", LINUX_ZFS_SUPER_MAGIC},
306962cf420SMaxim Sobolev {"cd9660", LINUX_ISOFS_SUPER_MAGIC},
307962cf420SMaxim Sobolev {"nfs", LINUX_NFS_SUPER_MAGIC},
308962cf420SMaxim Sobolev {"ext2fs", LINUX_EXT2_SUPER_MAGIC},
309962cf420SMaxim Sobolev {"procfs", LINUX_PROC_SUPER_MAGIC},
310962cf420SMaxim Sobolev {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
311962cf420SMaxim Sobolev {"ntfs", LINUX_NTFS_SUPER_MAGIC},
312962cf420SMaxim Sobolev {"nwfs", LINUX_NCP_SUPER_MAGIC},
313962cf420SMaxim Sobolev {"hpfs", LINUX_HPFS_SUPER_MAGIC},
314962cf420SMaxim Sobolev {"coda", LINUX_CODA_SUPER_MAGIC},
315e83d253bSOlivier Houchard {"devfs", LINUX_DEVFS_SUPER_MAGIC},
3162166e4e0SDmitry Chagin {"tmpfs", LINUX_SHMFS_MAGIC},
317962cf420SMaxim Sobolev {NULL, 0L}};
318dca60efcSMarcel Moolenaar
319962cf420SMaxim Sobolev for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
320962cf420SMaxim Sobolev if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
321962cf420SMaxim Sobolev return (b2l_tbl[i].linux_type);
322dca60efcSMarcel Moolenaar
323dca60efcSMarcel Moolenaar return (0L);
324dca60efcSMarcel Moolenaar }
325dca60efcSMarcel Moolenaar
326525c9796SDmitry Chagin static int
bsd_to_linux_mnt_flags(int f_flags)3279922bccbSDmitry Chagin bsd_to_linux_mnt_flags(int f_flags)
3289922bccbSDmitry Chagin {
3299922bccbSDmitry Chagin int flags = LINUX_ST_VALID;
3309922bccbSDmitry Chagin
3319922bccbSDmitry Chagin if (f_flags & MNT_RDONLY)
3329922bccbSDmitry Chagin flags |= LINUX_ST_RDONLY;
3339922bccbSDmitry Chagin if (f_flags & MNT_NOEXEC)
3349922bccbSDmitry Chagin flags |= LINUX_ST_NOEXEC;
3359922bccbSDmitry Chagin if (f_flags & MNT_NOSUID)
3369922bccbSDmitry Chagin flags |= LINUX_ST_NOSUID;
3379922bccbSDmitry Chagin if (f_flags & MNT_NOATIME)
3389922bccbSDmitry Chagin flags |= LINUX_ST_NOATIME;
3399922bccbSDmitry Chagin if (f_flags & MNT_NOSYMFOLLOW)
3409922bccbSDmitry Chagin flags |= LINUX_ST_NOSYMFOLLOW;
3419922bccbSDmitry Chagin if (f_flags & MNT_SYNCHRONOUS)
3429922bccbSDmitry Chagin flags |= LINUX_ST_SYNCHRONOUS;
3439922bccbSDmitry Chagin
3449922bccbSDmitry Chagin return (flags);
3459922bccbSDmitry Chagin }
3469922bccbSDmitry Chagin
3479922bccbSDmitry Chagin static int
bsd_to_linux_statfs(struct statfs * bsd_statfs,struct l_statfs * linux_statfs)348d0cad55dSPawel Jakub Dawidek bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
349f7a25872SJohn Baldwin {
350953688e8SDmitry Chagin
351525c9796SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
352953688e8SDmitry Chagin statfs_scale_blocks(bsd_statfs, INT32_MAX);
353525c9796SDmitry Chagin #endif
354f7a25872SJohn Baldwin linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
355f7a25872SJohn Baldwin linux_statfs->f_bsize = bsd_statfs->f_bsize;
356f7a25872SJohn Baldwin linux_statfs->f_blocks = bsd_statfs->f_blocks;
357f7a25872SJohn Baldwin linux_statfs->f_bfree = bsd_statfs->f_bfree;
358f7a25872SJohn Baldwin linux_statfs->f_bavail = bsd_statfs->f_bavail;
359953688e8SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
360953688e8SDmitry Chagin linux_statfs->f_ffree = MIN(bsd_statfs->f_ffree, INT32_MAX);
361953688e8SDmitry Chagin linux_statfs->f_files = MIN(bsd_statfs->f_files, INT32_MAX);
362953688e8SDmitry Chagin #else
363f7a25872SJohn Baldwin linux_statfs->f_ffree = bsd_statfs->f_ffree;
364f7a25872SJohn Baldwin linux_statfs->f_files = bsd_statfs->f_files;
365953688e8SDmitry Chagin #endif
366f7a25872SJohn Baldwin linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
367f7a25872SJohn Baldwin linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
368f7a25872SJohn Baldwin linux_statfs->f_namelen = MAXNAMLEN;
369e801ac78SEdward Tomasz Napierala linux_statfs->f_frsize = bsd_statfs->f_bsize;
3709922bccbSDmitry Chagin linux_statfs->f_flags = bsd_to_linux_mnt_flags(bsd_statfs->f_flags);
371e801ac78SEdward Tomasz Napierala memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
372525c9796SDmitry Chagin
373525c9796SDmitry Chagin return (0);
374f7a25872SJohn Baldwin }
375f7a25872SJohn Baldwin
376c21dee17SSøren Schmidt int
linux_statfs(struct thread * td,struct linux_statfs_args * args)377b40ce416SJulian Elischer linux_statfs(struct thread *td, struct linux_statfs_args *args)
378c21dee17SSøren Schmidt {
3795002a60fSMarcel Moolenaar struct l_statfs linux_statfs;
3802f304845SKonstantin Belousov struct statfs *bsd_statfs;
3812166e4e0SDmitry Chagin int error;
382d66a5066SPeter Wemm
383a125ed50SMateusz Guzik bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
384a125ed50SMateusz Guzik error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs);
3852f304845SKonstantin Belousov if (error == 0)
3862f304845SKonstantin Belousov error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
3872f304845SKonstantin Belousov free(bsd_statfs, M_STATFS);
3882f304845SKonstantin Belousov if (error != 0)
3892ad02313SDmitry Chagin return (error);
3907958a34cSDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
391c21dee17SSøren Schmidt }
392c21dee17SSøren Schmidt
3937f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
394835e5061SAlexander Leidinger static void
bsd_to_linux_statfs64(struct statfs * bsd_statfs,struct l_statfs64 * linux_statfs)395835e5061SAlexander Leidinger bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs)
396835e5061SAlexander Leidinger {
397835e5061SAlexander Leidinger
398835e5061SAlexander Leidinger linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
399835e5061SAlexander Leidinger linux_statfs->f_bsize = bsd_statfs->f_bsize;
400835e5061SAlexander Leidinger linux_statfs->f_blocks = bsd_statfs->f_blocks;
401835e5061SAlexander Leidinger linux_statfs->f_bfree = bsd_statfs->f_bfree;
402835e5061SAlexander Leidinger linux_statfs->f_bavail = bsd_statfs->f_bavail;
403835e5061SAlexander Leidinger linux_statfs->f_ffree = bsd_statfs->f_ffree;
404835e5061SAlexander Leidinger linux_statfs->f_files = bsd_statfs->f_files;
405835e5061SAlexander Leidinger linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
406835e5061SAlexander Leidinger linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
407835e5061SAlexander Leidinger linux_statfs->f_namelen = MAXNAMLEN;
408e801ac78SEdward Tomasz Napierala linux_statfs->f_frsize = bsd_statfs->f_bsize;
4099922bccbSDmitry Chagin linux_statfs->f_flags = bsd_to_linux_mnt_flags(bsd_statfs->f_flags);
410e801ac78SEdward Tomasz Napierala memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
411835e5061SAlexander Leidinger }
412835e5061SAlexander Leidinger
413835e5061SAlexander Leidinger int
linux_statfs64(struct thread * td,struct linux_statfs64_args * args)414835e5061SAlexander Leidinger linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
415835e5061SAlexander Leidinger {
416835e5061SAlexander Leidinger struct l_statfs64 linux_statfs;
4172f304845SKonstantin Belousov struct statfs *bsd_statfs;
418835e5061SAlexander Leidinger int error;
419835e5061SAlexander Leidinger
4203ab85269SDavid Malone if (args->bufsize != sizeof(struct l_statfs64))
421340f4a8dSEd Maste return (EINVAL);
4223ab85269SDavid Malone
423a125ed50SMateusz Guzik bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
424a125ed50SMateusz Guzik error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs);
4252f304845SKonstantin Belousov if (error == 0)
4262f304845SKonstantin Belousov bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
4272f304845SKonstantin Belousov free(bsd_statfs, M_STATFS);
4282f304845SKonstantin Belousov if (error != 0)
429835e5061SAlexander Leidinger return (error);
4307958a34cSDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
431835e5061SAlexander Leidinger }
43299546279SDmitry Chagin
43399546279SDmitry Chagin int
linux_fstatfs64(struct thread * td,struct linux_fstatfs64_args * args)43499546279SDmitry Chagin linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
43599546279SDmitry Chagin {
43699546279SDmitry Chagin struct l_statfs64 linux_statfs;
4372f304845SKonstantin Belousov struct statfs *bsd_statfs;
43899546279SDmitry Chagin int error;
43999546279SDmitry Chagin
44099546279SDmitry Chagin if (args->bufsize != sizeof(struct l_statfs64))
44199546279SDmitry Chagin return (EINVAL);
44299546279SDmitry Chagin
4432f304845SKonstantin Belousov bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
4442f304845SKonstantin Belousov error = kern_fstatfs(td, args->fd, bsd_statfs);
4452f304845SKonstantin Belousov if (error == 0)
4462f304845SKonstantin Belousov bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
4472f304845SKonstantin Belousov free(bsd_statfs, M_STATFS);
4482f304845SKonstantin Belousov if (error != 0)
4492f304845SKonstantin Belousov return (error);
45099546279SDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
45199546279SDmitry Chagin }
4527f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
453835e5061SAlexander Leidinger
454c21dee17SSøren Schmidt int
linux_fstatfs(struct thread * td,struct linux_fstatfs_args * args)455b40ce416SJulian Elischer linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
456c21dee17SSøren Schmidt {
4575002a60fSMarcel Moolenaar struct l_statfs linux_statfs;
4582f304845SKonstantin Belousov struct statfs *bsd_statfs;
459c21dee17SSøren Schmidt int error;
460c21dee17SSøren Schmidt
4612f304845SKonstantin Belousov bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
4622f304845SKonstantin Belousov error = kern_fstatfs(td, args->fd, bsd_statfs);
4632f304845SKonstantin Belousov if (error == 0)
4642f304845SKonstantin Belousov error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
4652f304845SKonstantin Belousov free(bsd_statfs, M_STATFS);
4662f304845SKonstantin Belousov if (error != 0)
4672ad02313SDmitry Chagin return (error);
4687958a34cSDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
469c21dee17SSøren Schmidt }
470408da119SMarcel Moolenaar
4715002a60fSMarcel Moolenaar struct l_ustat
472408da119SMarcel Moolenaar {
4735002a60fSMarcel Moolenaar l_daddr_t f_tfree;
4745002a60fSMarcel Moolenaar l_ino_t f_tinode;
4755002a60fSMarcel Moolenaar char f_fname[6];
4765002a60fSMarcel Moolenaar char f_fpack[6];
4775002a60fSMarcel Moolenaar };
4785002a60fSMarcel Moolenaar
479931e2a1aSEd Maste #ifdef LINUX_LEGACY_SYSCALLS
4805002a60fSMarcel Moolenaar int
linux_ustat(struct thread * td,struct linux_ustat_args * args)481b40ce416SJulian Elischer linux_ustat(struct thread *td, struct linux_ustat_args *args)
4825002a60fSMarcel Moolenaar {
4831e247cc2SPoul-Henning Kamp
4841e247cc2SPoul-Henning Kamp return (EOPNOTSUPP);
485408da119SMarcel Moolenaar }
486931e2a1aSEd Maste #endif
4875002a60fSMarcel Moolenaar
488*3cf834d0SEd Maste /*
489*3cf834d0SEd Maste * Convert Linux stat flags to BSD flags. Return value indicates successful
490*3cf834d0SEd Maste * conversion (no unknown flags).
491*3cf834d0SEd Maste */
492*3cf834d0SEd Maste static bool
linux_to_bsd_stat_flags(int linux_flags,int * out_flags)493*3cf834d0SEd Maste linux_to_bsd_stat_flags(int linux_flags, int *out_flags)
494*3cf834d0SEd Maste {
495*3cf834d0SEd Maste int flags, unsupported;
496*3cf834d0SEd Maste
497*3cf834d0SEd Maste unsupported = linux_flags & ~(LINUX_AT_SYMLINK_NOFOLLOW |
498*3cf834d0SEd Maste LINUX_AT_EMPTY_PATH | LINUX_AT_NO_AUTOMOUNT);
499*3cf834d0SEd Maste if (unsupported != 0) {
500*3cf834d0SEd Maste *out_flags = unsupported;
501*3cf834d0SEd Maste return (false);
502*3cf834d0SEd Maste }
503*3cf834d0SEd Maste
504*3cf834d0SEd Maste flags = 0;
505*3cf834d0SEd Maste if (linux_flags & LINUX_AT_SYMLINK_NOFOLLOW)
506*3cf834d0SEd Maste flags |= AT_SYMLINK_NOFOLLOW;
507*3cf834d0SEd Maste if (linux_flags & LINUX_AT_EMPTY_PATH)
508*3cf834d0SEd Maste flags |= AT_EMPTY_PATH;
509*3cf834d0SEd Maste *out_flags = flags;
510*3cf834d0SEd Maste return (true);
511*3cf834d0SEd Maste }
512*3cf834d0SEd Maste
5131997c537SDavid E. O'Brien #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
5145002a60fSMarcel Moolenaar
5155002a60fSMarcel Moolenaar static int
stat64_copyout(struct stat * buf,void * ubuf)5165002a60fSMarcel Moolenaar stat64_copyout(struct stat *buf, void *ubuf)
5175002a60fSMarcel Moolenaar {
5185002a60fSMarcel Moolenaar struct l_stat64 lbuf;
5195002a60fSMarcel Moolenaar
5205002a60fSMarcel Moolenaar bzero(&lbuf, sizeof(lbuf));
521166e2e5aSDmitry Chagin lbuf.st_dev = linux_new_encode_dev(buf->st_dev);
5225002a60fSMarcel Moolenaar lbuf.st_ino = buf->st_ino;
5235002a60fSMarcel Moolenaar lbuf.st_mode = buf->st_mode;
5245002a60fSMarcel Moolenaar lbuf.st_nlink = buf->st_nlink;
5255002a60fSMarcel Moolenaar lbuf.st_uid = buf->st_uid;
5265002a60fSMarcel Moolenaar lbuf.st_gid = buf->st_gid;
527166e2e5aSDmitry Chagin lbuf.st_rdev = linux_new_encode_dev(buf->st_rdev);
5285002a60fSMarcel Moolenaar lbuf.st_size = buf->st_size;
529510ea843SEd Schouten lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
530510ea843SEd Schouten lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
531510ea843SEd Schouten lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
532510ea843SEd Schouten lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
533510ea843SEd Schouten lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
534510ea843SEd Schouten lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
5355002a60fSMarcel Moolenaar lbuf.st_blksize = buf->st_blksize;
5365002a60fSMarcel Moolenaar lbuf.st_blocks = buf->st_blocks;
5375002a60fSMarcel Moolenaar
5385002a60fSMarcel Moolenaar /*
5395002a60fSMarcel Moolenaar * The __st_ino field makes all the difference. In the Linux kernel
5405002a60fSMarcel Moolenaar * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
5415002a60fSMarcel Moolenaar * but without the assignment to __st_ino the runtime linker refuses
5425002a60fSMarcel Moolenaar * to mmap(2) any shared libraries. I guess it's broken alright :-)
5435002a60fSMarcel Moolenaar */
5445002a60fSMarcel Moolenaar lbuf.__st_ino = buf->st_ino;
5455002a60fSMarcel Moolenaar
5465002a60fSMarcel Moolenaar return (copyout(&lbuf, ubuf, sizeof(lbuf)));
5475002a60fSMarcel Moolenaar }
5485002a60fSMarcel Moolenaar
5495002a60fSMarcel Moolenaar int
linux_stat64(struct thread * td,struct linux_stat64_args * args)550b40ce416SJulian Elischer linux_stat64(struct thread *td, struct linux_stat64_args *args)
5515002a60fSMarcel Moolenaar {
5525002a60fSMarcel Moolenaar struct stat buf;
553f7a25872SJohn Baldwin int error;
5545002a60fSMarcel Moolenaar
555a125ed50SMateusz Guzik error = linux_kern_stat(td, args->filename, UIO_USERSPACE, &buf);
5565002a60fSMarcel Moolenaar if (error)
5575002a60fSMarcel Moolenaar return (error);
5585002a60fSMarcel Moolenaar return (stat64_copyout(&buf, args->statbuf));
5595002a60fSMarcel Moolenaar }
5605002a60fSMarcel Moolenaar
5615002a60fSMarcel Moolenaar int
linux_lstat64(struct thread * td,struct linux_lstat64_args * args)562b40ce416SJulian Elischer linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
5635002a60fSMarcel Moolenaar {
5645002a60fSMarcel Moolenaar struct stat sb;
565f7a25872SJohn Baldwin int error;
5665002a60fSMarcel Moolenaar
567a125ed50SMateusz Guzik error = linux_kern_lstat(td, args->filename, UIO_USERSPACE, &sb);
5685002a60fSMarcel Moolenaar if (error)
5695002a60fSMarcel Moolenaar return (error);
5705002a60fSMarcel Moolenaar return (stat64_copyout(&sb, args->statbuf));
5715002a60fSMarcel Moolenaar }
5725002a60fSMarcel Moolenaar
5735002a60fSMarcel Moolenaar int
linux_fstat64(struct thread * td,struct linux_fstat64_args * args)574b40ce416SJulian Elischer linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
5755002a60fSMarcel Moolenaar {
5765002a60fSMarcel Moolenaar struct stat buf;
5775002a60fSMarcel Moolenaar int error;
5785002a60fSMarcel Moolenaar
579994ed958SDmitry Chagin error = linux_kern_fstat(td, args->fd, &buf);
5805002a60fSMarcel Moolenaar if (!error)
5815002a60fSMarcel Moolenaar error = stat64_copyout(&buf, args->statbuf);
5825002a60fSMarcel Moolenaar
5835002a60fSMarcel Moolenaar return (error);
5845002a60fSMarcel Moolenaar }
5855002a60fSMarcel Moolenaar
58648b05c3fSKonstantin Belousov int
linux_fstatat64(struct thread * td,struct linux_fstatat64_args * args)58748b05c3fSKonstantin Belousov linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args)
58848b05c3fSKonstantin Belousov {
589*3cf834d0SEd Maste int error, dfd, flags;
59048b05c3fSKonstantin Belousov struct stat buf;
59148b05c3fSKonstantin Belousov
592*3cf834d0SEd Maste if (!linux_to_bsd_stat_flags(args->flag, &flags)) {
593*3cf834d0SEd Maste linux_msg(td, "fstatat64 unsupported flags 0x%x", flags);
59448b05c3fSKonstantin Belousov return (EINVAL);
5954b45c2bbSEdward Tomasz Napierala }
59648b05c3fSKonstantin Belousov
59748b05c3fSKonstantin Belousov dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
598*3cf834d0SEd Maste error = linux_kern_statat(td, flags, dfd, args->pathname,
599a125ed50SMateusz Guzik UIO_USERSPACE, &buf);
600a125ed50SMateusz Guzik if (error == 0)
601a125ed50SMateusz Guzik error = stat64_copyout(&buf, args->statbuf);
60248b05c3fSKonstantin Belousov
60348b05c3fSKonstantin Belousov return (error);
60448b05c3fSKonstantin Belousov }
60548b05c3fSKonstantin Belousov
606606bcc17SDmitry Chagin #else /* __amd64__ && !COMPAT_LINUX32 */
607606bcc17SDmitry Chagin
608606bcc17SDmitry Chagin int
linux_newfstatat(struct thread * td,struct linux_newfstatat_args * args)609606bcc17SDmitry Chagin linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args)
610606bcc17SDmitry Chagin {
611*3cf834d0SEd Maste int error, dfd, flags;
612606bcc17SDmitry Chagin struct stat buf;
613606bcc17SDmitry Chagin
614*3cf834d0SEd Maste if (!linux_to_bsd_stat_flags(args->flag, &flags)) {
615*3cf834d0SEd Maste linux_msg(td, "fstatat unsupported flags 0x%x", flags);
616606bcc17SDmitry Chagin return (EINVAL);
6174b45c2bbSEdward Tomasz Napierala }
6184b45c2bbSEdward Tomasz Napierala
619606bcc17SDmitry Chagin dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
620*3cf834d0SEd Maste error = linux_kern_statat(td, flags, dfd, args->pathname,
621a125ed50SMateusz Guzik UIO_USERSPACE, &buf);
622606bcc17SDmitry Chagin if (error == 0)
623606bcc17SDmitry Chagin error = newstat_copyout(&buf, args->statbuf);
624606bcc17SDmitry Chagin
625606bcc17SDmitry Chagin return (error);
626606bcc17SDmitry Chagin }
627606bcc17SDmitry Chagin
6281997c537SDavid E. O'Brien #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
6299802eb9eSDmitry Chagin
6309802eb9eSDmitry Chagin int
linux_syncfs(struct thread * td,struct linux_syncfs_args * args)6319802eb9eSDmitry Chagin linux_syncfs(struct thread *td, struct linux_syncfs_args *args)
6329802eb9eSDmitry Chagin {
6339802eb9eSDmitry Chagin struct mount *mp;
6349802eb9eSDmitry Chagin struct vnode *vp;
6359802eb9eSDmitry Chagin int error, save;
6369802eb9eSDmitry Chagin
637cbd92ce6SMatt Macy error = fgetvp(td, args->fd, &cap_fsync_rights, &vp);
6389802eb9eSDmitry Chagin if (error != 0)
6399802eb9eSDmitry Chagin /*
6409802eb9eSDmitry Chagin * Linux syncfs() returns only EBADF, however fgetvp()
6419802eb9eSDmitry Chagin * can return EINVAL in case of file descriptor does
6429802eb9eSDmitry Chagin * not represent a vnode. XXX.
6439802eb9eSDmitry Chagin */
6449802eb9eSDmitry Chagin return (error);
6459802eb9eSDmitry Chagin
6469802eb9eSDmitry Chagin mp = vp->v_mount;
6479802eb9eSDmitry Chagin mtx_lock(&mountlist_mtx);
6489802eb9eSDmitry Chagin error = vfs_busy(mp, MBF_MNTLSTLOCK);
6499802eb9eSDmitry Chagin if (error != 0) {
6509802eb9eSDmitry Chagin /* See comment above. */
6519802eb9eSDmitry Chagin mtx_unlock(&mountlist_mtx);
6529802eb9eSDmitry Chagin goto out;
6539802eb9eSDmitry Chagin }
6549802eb9eSDmitry Chagin if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
6559802eb9eSDmitry Chagin vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
6569802eb9eSDmitry Chagin save = curthread_pflags_set(TDP_SYNCIO);
657c8b3463dSMateusz Guzik vfs_periodic(mp, MNT_NOWAIT);
6589802eb9eSDmitry Chagin VFS_SYNC(mp, MNT_NOWAIT);
6599802eb9eSDmitry Chagin curthread_pflags_restore(save);
6609802eb9eSDmitry Chagin vn_finished_write(mp);
6619802eb9eSDmitry Chagin }
6629802eb9eSDmitry Chagin vfs_unbusy(mp);
6639802eb9eSDmitry Chagin
6649802eb9eSDmitry Chagin out:
6659802eb9eSDmitry Chagin vrele(vp);
6669802eb9eSDmitry Chagin return (error);
6679802eb9eSDmitry Chagin }
6682362ad45SPhilippe Michaud-Boudreault
669e9204c5cSDmitry Chagin static int
statx_copyout(struct stat * buf,void * ubuf)670e9204c5cSDmitry Chagin statx_copyout(struct stat *buf, void *ubuf)
671e9204c5cSDmitry Chagin {
672e9204c5cSDmitry Chagin struct l_statx tbuf;
673e9204c5cSDmitry Chagin
674e9204c5cSDmitry Chagin bzero(&tbuf, sizeof(tbuf));
675e9204c5cSDmitry Chagin tbuf.stx_mask = STATX_ALL;
676e9204c5cSDmitry Chagin tbuf.stx_blksize = buf->st_blksize;
677e9204c5cSDmitry Chagin tbuf.stx_attributes = 0;
678e9204c5cSDmitry Chagin tbuf.stx_nlink = buf->st_nlink;
679e9204c5cSDmitry Chagin tbuf.stx_uid = buf->st_uid;
680e9204c5cSDmitry Chagin tbuf.stx_gid = buf->st_gid;
681e9204c5cSDmitry Chagin tbuf.stx_mode = buf->st_mode;
682e9204c5cSDmitry Chagin tbuf.stx_ino = buf->st_ino;
683e9204c5cSDmitry Chagin tbuf.stx_size = buf->st_size;
684e9204c5cSDmitry Chagin tbuf.stx_blocks = buf->st_blocks;
685e9204c5cSDmitry Chagin
686e9204c5cSDmitry Chagin tbuf.stx_atime.tv_sec = buf->st_atim.tv_sec;
687e9204c5cSDmitry Chagin tbuf.stx_atime.tv_nsec = buf->st_atim.tv_nsec;
688e9204c5cSDmitry Chagin tbuf.stx_btime.tv_sec = buf->st_birthtim.tv_sec;
689e9204c5cSDmitry Chagin tbuf.stx_btime.tv_nsec = buf->st_birthtim.tv_nsec;
690e9204c5cSDmitry Chagin tbuf.stx_ctime.tv_sec = buf->st_ctim.tv_sec;
691e9204c5cSDmitry Chagin tbuf.stx_ctime.tv_nsec = buf->st_ctim.tv_nsec;
692e9204c5cSDmitry Chagin tbuf.stx_mtime.tv_sec = buf->st_mtim.tv_sec;
693e9204c5cSDmitry Chagin tbuf.stx_mtime.tv_nsec = buf->st_mtim.tv_nsec;
694166e2e5aSDmitry Chagin tbuf.stx_rdev_major = linux_encode_major(buf->st_rdev);
695166e2e5aSDmitry Chagin tbuf.stx_rdev_minor = linux_encode_minor(buf->st_rdev);
696166e2e5aSDmitry Chagin tbuf.stx_dev_major = linux_encode_major(buf->st_dev);
697166e2e5aSDmitry Chagin tbuf.stx_dev_minor = linux_encode_minor(buf->st_dev);
698e9204c5cSDmitry Chagin
699e9204c5cSDmitry Chagin return (copyout(&tbuf, ubuf, sizeof(tbuf)));
700e9204c5cSDmitry Chagin }
701e9204c5cSDmitry Chagin
7022362ad45SPhilippe Michaud-Boudreault int
linux_statx(struct thread * td,struct linux_statx_args * args)7032362ad45SPhilippe Michaud-Boudreault linux_statx(struct thread *td, struct linux_statx_args *args)
7042362ad45SPhilippe Michaud-Boudreault {
705*3cf834d0SEd Maste int error, dirfd, flags;
7062362ad45SPhilippe Michaud-Boudreault struct stat buf;
7072362ad45SPhilippe Michaud-Boudreault
708*3cf834d0SEd Maste if (!linux_to_bsd_stat_flags(args->flags, &flags)) {
709*3cf834d0SEd Maste linux_msg(td, "statx unsupported flags 0x%x", flags);
7102362ad45SPhilippe Michaud-Boudreault return (EINVAL);
7112362ad45SPhilippe Michaud-Boudreault }
7122362ad45SPhilippe Michaud-Boudreault
7132362ad45SPhilippe Michaud-Boudreault dirfd = (args->dirfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dirfd;
7142362ad45SPhilippe Michaud-Boudreault error = linux_kern_statat(td, flags, dirfd, args->pathname,
7152362ad45SPhilippe Michaud-Boudreault UIO_USERSPACE, &buf);
7162362ad45SPhilippe Michaud-Boudreault if (error == 0)
7172362ad45SPhilippe Michaud-Boudreault error = statx_copyout(&buf, args->statxbuf);
7182362ad45SPhilippe Michaud-Boudreault
7192362ad45SPhilippe Michaud-Boudreault return (error);
7202362ad45SPhilippe Michaud-Boudreault }
721