1c21dee17SSøren Schmidt /*- 20ba1b365SEd Maste * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 3016dbc7f2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3116dbc7f2SDavid E. O'Brien 32cb858340SDmitry Chagin #include "opt_ktrace.h" 33cb858340SDmitry Chagin 34c21dee17SSøren Schmidt #include <sys/param.h> 359802eb9eSDmitry Chagin #include <sys/capsicum.h> 36c21dee17SSøren Schmidt #include <sys/dirent.h> 37d8e53d94SDmitry Chagin #include <sys/lock.h> 3885422e62SBruce Evans #include <sys/malloc.h> 39d8e53d94SDmitry Chagin #include <sys/mutex.h> 40cb858340SDmitry Chagin #include <sys/namei.h> 41d8e53d94SDmitry Chagin #include <sys/proc.h> 42c21dee17SSøren Schmidt #include <sys/stat.h> 43f7a25872SJohn Baldwin #include <sys/syscallsubr.h> 44bc093719SEd Schouten #include <sys/tty.h> 45c21dee17SSøren Schmidt #include <sys/vnode.h> 46cb858340SDmitry Chagin #ifdef KTRACE 47cb858340SDmitry Chagin #include <sys/ktrace.h> 48cb858340SDmitry Chagin #endif 49c21dee17SSøren Schmidt 50994ed958SDmitry Chagin #include <security/audit/audit.h> 51994ed958SDmitry Chagin 521997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32 534af27623STim J. Robbins #include <machine/../linux32/linux.h> 544af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h> 551997c537SDavid E. O'Brien #else 561997c537SDavid E. O'Brien #include <machine/../linux/linux.h> 571997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h> 584af27623STim J. Robbins #endif 5985422e62SBruce Evans 60*166e2e5aSDmitry Chagin #include <compat/linux/linux.h> 6148b05c3fSKonstantin Belousov #include <compat/linux/linux_file.h> 622a38f51cSDmitry Chagin #include <compat/linux/linux_util.h> 63762e6b85SEivind Eklund 640eee862aSEd Schouten 650eee862aSEd Schouten static int 66994ed958SDmitry Chagin linux_kern_fstat(struct thread *td, int fd, struct stat *sbp) 67994ed958SDmitry Chagin { 68994ed958SDmitry Chagin struct vnode *vp; 69994ed958SDmitry Chagin struct file *fp; 70994ed958SDmitry Chagin int error; 71994ed958SDmitry Chagin 72994ed958SDmitry Chagin AUDIT_ARG_FD(fd); 73994ed958SDmitry Chagin 74994ed958SDmitry Chagin error = fget(td, fd, &cap_fstat_rights, &fp); 75994ed958SDmitry Chagin if (__predict_false(error != 0)) 76994ed958SDmitry Chagin return (error); 77994ed958SDmitry Chagin 78994ed958SDmitry Chagin AUDIT_ARG_FILE(td->td_proc, fp); 79994ed958SDmitry Chagin 80994ed958SDmitry Chagin error = fo_stat(fp, sbp, td->td_ucred); 81994ed958SDmitry Chagin if (error == 0 && (vp = fp->f_vnode) != NULL) 82994ed958SDmitry Chagin translate_vnhook_major_minor(vp, sbp); 83994ed958SDmitry Chagin fdrop(fp, td); 84994ed958SDmitry Chagin #ifdef KTRACE 85994ed958SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT)) 86994ed958SDmitry Chagin ktrstat_error(sbp, error); 87994ed958SDmitry Chagin #endif 88994ed958SDmitry Chagin return (error); 89994ed958SDmitry Chagin } 90994ed958SDmitry Chagin 91994ed958SDmitry Chagin static int 92a125ed50SMateusz Guzik linux_kern_statat(struct thread *td, int flag, int fd, const char *path, 930eee862aSEd Schouten enum uio_seg pathseg, struct stat *sbp) 940eee862aSEd Schouten { 95cb858340SDmitry Chagin struct nameidata nd; 96cb858340SDmitry Chagin int error; 970eee862aSEd Schouten 98cb858340SDmitry Chagin if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH | 99cb858340SDmitry Chagin AT_EMPTY_PATH)) != 0) 100cb858340SDmitry Chagin return (EINVAL); 101cb858340SDmitry Chagin 102cb858340SDmitry Chagin NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_RESOLVE_BENEATH | 103cb858340SDmitry Chagin AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH) | LOCKSHARED | LOCKLEAF | 104cb858340SDmitry Chagin AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights); 105cb858340SDmitry Chagin 106cb858340SDmitry Chagin if ((error = namei(&nd)) != 0) { 107cb858340SDmitry Chagin if (error == ENOTDIR && 108cb858340SDmitry Chagin (nd.ni_resflags & NIRES_EMPTYPATH) != 0) 109994ed958SDmitry Chagin error = linux_kern_fstat(td, fd, sbp); 110cb858340SDmitry Chagin return (error); 111cb858340SDmitry Chagin } 112cb858340SDmitry Chagin error = VOP_STAT(nd.ni_vp, sbp, td->td_ucred, NOCRED); 113cb858340SDmitry Chagin if (error == 0) 114cb858340SDmitry Chagin translate_vnhook_major_minor(nd.ni_vp, sbp); 115cb858340SDmitry Chagin NDFREE_PNBUF(&nd); 116cb858340SDmitry Chagin vput(nd.ni_vp); 117cb858340SDmitry Chagin #ifdef KTRACE 118cb858340SDmitry Chagin if (KTRPOINT(td, KTR_STRUCT)) 119cb858340SDmitry Chagin ktrstat_error(sbp, error); 120cb858340SDmitry Chagin #endif 121cb858340SDmitry Chagin return (error); 1220eee862aSEd Schouten } 1230eee862aSEd Schouten 124931e2a1aSEd Maste #ifdef LINUX_LEGACY_SYSCALLS 1250eee862aSEd Schouten static int 126a125ed50SMateusz Guzik linux_kern_stat(struct thread *td, const char *path, enum uio_seg pathseg, 1270eee862aSEd Schouten struct stat *sbp) 1280eee862aSEd Schouten { 1290eee862aSEd Schouten 1300eee862aSEd Schouten return (linux_kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp)); 1310eee862aSEd Schouten } 1320eee862aSEd Schouten 1330eee862aSEd Schouten static int 134a125ed50SMateusz Guzik linux_kern_lstat(struct thread *td, const char *path, enum uio_seg pathseg, 1350eee862aSEd Schouten struct stat *sbp) 1360eee862aSEd Schouten { 1370eee862aSEd Schouten 1380eee862aSEd Schouten return (linux_kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path, 1390eee862aSEd Schouten pathseg, sbp)); 1400eee862aSEd Schouten } 141931e2a1aSEd Maste #endif 1420eee862aSEd Schouten 143bbbc2d96SPoul-Henning Kamp static int 144bbbc2d96SPoul-Henning Kamp newstat_copyout(struct stat *buf, void *ubuf) 145bbbc2d96SPoul-Henning Kamp { 146bbbc2d96SPoul-Henning Kamp struct l_newstat tbuf; 147bbbc2d96SPoul-Henning Kamp 148bbbc2d96SPoul-Henning Kamp bzero(&tbuf, sizeof(tbuf)); 149*166e2e5aSDmitry Chagin tbuf.st_dev = linux_new_encode_dev(buf->st_dev); 150bbbc2d96SPoul-Henning Kamp tbuf.st_ino = buf->st_ino; 151bbbc2d96SPoul-Henning Kamp tbuf.st_mode = buf->st_mode; 152bbbc2d96SPoul-Henning Kamp tbuf.st_nlink = buf->st_nlink; 153bbbc2d96SPoul-Henning Kamp tbuf.st_uid = buf->st_uid; 154bbbc2d96SPoul-Henning Kamp tbuf.st_gid = buf->st_gid; 155*166e2e5aSDmitry Chagin tbuf.st_rdev = linux_new_encode_dev(buf->st_rdev); 156bbbc2d96SPoul-Henning Kamp tbuf.st_size = buf->st_size; 157510ea843SEd Schouten tbuf.st_atim.tv_sec = buf->st_atim.tv_sec; 158510ea843SEd Schouten tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; 159510ea843SEd Schouten tbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec; 160510ea843SEd Schouten tbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec; 161510ea843SEd Schouten tbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec; 162510ea843SEd Schouten tbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec; 163bbbc2d96SPoul-Henning Kamp tbuf.st_blksize = buf->st_blksize; 164bbbc2d96SPoul-Henning Kamp tbuf.st_blocks = buf->st_blocks; 165bbbc2d96SPoul-Henning Kamp 1664e0eaf69SMarcel Moolenaar return (copyout(&tbuf, ubuf, sizeof(tbuf))); 167c21dee17SSøren Schmidt } 168c21dee17SSøren Schmidt 1692362ad45SPhilippe Michaud-Boudreault 170931e2a1aSEd Maste #ifdef LINUX_LEGACY_SYSCALLS 171c21dee17SSøren Schmidt int 172b40ce416SJulian Elischer linux_newstat(struct thread *td, struct linux_newstat_args *args) 173c21dee17SSøren Schmidt { 174c21dee17SSøren Schmidt struct stat buf; 175206a5d3aSIan Dowse char *path; 176c21dee17SSøren Schmidt int error; 177d66a5066SPeter Wemm 178a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 179a125ed50SMateusz Guzik error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf); 180a125ed50SMateusz Guzik } else { 181af4051d2SMateusz Guzik LCONVPATHEXIST(args->path, &path); 1820eee862aSEd Schouten error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf); 183206a5d3aSIan Dowse LFREEPATH(path); 184a125ed50SMateusz Guzik } 1854e0eaf69SMarcel Moolenaar if (error) 1864e0eaf69SMarcel Moolenaar return (error); 1874e0eaf69SMarcel Moolenaar return (newstat_copyout(&buf, args->buf)); 188c21dee17SSøren Schmidt } 189c21dee17SSøren Schmidt 190c21dee17SSøren Schmidt int 191b40ce416SJulian Elischer linux_newlstat(struct thread *td, struct linux_newlstat_args *args) 192c21dee17SSøren Schmidt { 1934e0eaf69SMarcel Moolenaar struct stat sb; 194206a5d3aSIan Dowse char *path; 195f7a25872SJohn Baldwin int error; 196d66a5066SPeter Wemm 197a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 198a125ed50SMateusz Guzik error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &sb); 199a125ed50SMateusz Guzik } else { 200af4051d2SMateusz Guzik LCONVPATHEXIST(args->path, &path); 2010eee862aSEd Schouten error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb); 202206a5d3aSIan Dowse LFREEPATH(path); 203a125ed50SMateusz Guzik } 204d66a5066SPeter Wemm if (error) 205d66a5066SPeter Wemm return (error); 2065002a60fSMarcel Moolenaar return (newstat_copyout(&sb, args->buf)); 207d66a5066SPeter Wemm } 208931e2a1aSEd Maste #endif 209c21dee17SSøren Schmidt 210c21dee17SSøren Schmidt int 211b40ce416SJulian Elischer linux_newfstat(struct thread *td, struct linux_newfstat_args *args) 212c21dee17SSøren Schmidt { 213c21dee17SSøren Schmidt struct stat buf; 214c21dee17SSøren Schmidt int error; 215c21dee17SSøren Schmidt 216994ed958SDmitry Chagin error = linux_kern_fstat(td, args->fd, &buf); 217c21dee17SSøren Schmidt if (!error) 218c21dee17SSøren Schmidt error = newstat_copyout(&buf, args->buf); 2194e0eaf69SMarcel Moolenaar 2204e0eaf69SMarcel Moolenaar return (error); 221c21dee17SSøren Schmidt } 222c21dee17SSøren Schmidt 2237f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 224*166e2e5aSDmitry Chagin 225*166e2e5aSDmitry Chagin static __inline uint16_t 226*166e2e5aSDmitry Chagin linux_old_encode_dev(dev_t _dev) 227*166e2e5aSDmitry Chagin { 228*166e2e5aSDmitry Chagin 229*166e2e5aSDmitry Chagin return (_dev == NODEV ? 0 : linux_encode_dev(major(_dev), minor(_dev))); 230*166e2e5aSDmitry Chagin } 231*166e2e5aSDmitry Chagin 2325c8919adSAlexander Leidinger static int 233a408fc09SDmitry Chagin old_stat_copyout(struct stat *buf, void *ubuf) 2345c8919adSAlexander Leidinger { 235a408fc09SDmitry Chagin struct l_old_stat lbuf; 2365c8919adSAlexander Leidinger 2375c8919adSAlexander Leidinger bzero(&lbuf, sizeof(lbuf)); 238*166e2e5aSDmitry Chagin lbuf.st_dev = linux_old_encode_dev(buf->st_dev); 2395c8919adSAlexander Leidinger lbuf.st_ino = buf->st_ino; 2405c8919adSAlexander Leidinger lbuf.st_mode = buf->st_mode; 2415c8919adSAlexander Leidinger lbuf.st_nlink = buf->st_nlink; 2425c8919adSAlexander Leidinger lbuf.st_uid = buf->st_uid; 2435c8919adSAlexander Leidinger lbuf.st_gid = buf->st_gid; 244*166e2e5aSDmitry Chagin lbuf.st_rdev = linux_old_encode_dev(buf->st_rdev); 245372639f9SBruce Evans lbuf.st_size = MIN(buf->st_size, INT32_MAX); 246510ea843SEd Schouten lbuf.st_atim.tv_sec = buf->st_atim.tv_sec; 247510ea843SEd Schouten lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; 248510ea843SEd Schouten lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec; 249510ea843SEd Schouten lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec; 250510ea843SEd Schouten lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec; 251510ea843SEd Schouten lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec; 2525c8919adSAlexander Leidinger lbuf.st_blksize = buf->st_blksize; 2535c8919adSAlexander Leidinger lbuf.st_blocks = buf->st_blocks; 2545c8919adSAlexander Leidinger lbuf.st_flags = buf->st_flags; 2555c8919adSAlexander Leidinger lbuf.st_gen = buf->st_gen; 2565c8919adSAlexander Leidinger 2575c8919adSAlexander Leidinger return (copyout(&lbuf, ubuf, sizeof(lbuf))); 2585c8919adSAlexander Leidinger } 2595c8919adSAlexander Leidinger 2605c8919adSAlexander Leidinger int 2615c8919adSAlexander Leidinger linux_stat(struct thread *td, struct linux_stat_args *args) 2625c8919adSAlexander Leidinger { 2635c8919adSAlexander Leidinger struct stat buf; 26415b78ac5SKonstantin Belousov char *path; 2655c8919adSAlexander Leidinger int error; 26615b78ac5SKonstantin Belousov 267a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 268a125ed50SMateusz Guzik error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf); 269a125ed50SMateusz Guzik } else { 270af4051d2SMateusz Guzik LCONVPATHEXIST(args->path, &path); 2710eee862aSEd Schouten error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf); 27215b78ac5SKonstantin Belousov LFREEPATH(path); 273a125ed50SMateusz Guzik } 274a125ed50SMateusz Guzik if (error) { 2755c8919adSAlexander Leidinger return (error); 276d075105dSKonstantin Belousov } 277a408fc09SDmitry Chagin return (old_stat_copyout(&buf, args->up)); 2785c8919adSAlexander Leidinger } 2795c8919adSAlexander Leidinger 2805c8919adSAlexander Leidinger int 2815c8919adSAlexander Leidinger linux_lstat(struct thread *td, struct linux_lstat_args *args) 2825c8919adSAlexander Leidinger { 2835c8919adSAlexander Leidinger struct stat buf; 28415b78ac5SKonstantin Belousov char *path; 2855c8919adSAlexander Leidinger int error; 2865c8919adSAlexander Leidinger 287a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 288a125ed50SMateusz Guzik error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &buf); 289a125ed50SMateusz Guzik } else { 290af4051d2SMateusz Guzik LCONVPATHEXIST(args->path, &path); 2910eee862aSEd Schouten error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf); 29215b78ac5SKonstantin Belousov LFREEPATH(path); 293a125ed50SMateusz Guzik } 294a125ed50SMateusz Guzik if (error) { 2955c8919adSAlexander Leidinger return (error); 296d075105dSKonstantin Belousov } 297a408fc09SDmitry Chagin return (old_stat_copyout(&buf, args->up)); 2985c8919adSAlexander Leidinger } 2997f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 3005c8919adSAlexander Leidinger 3015002a60fSMarcel Moolenaar struct l_statfs { 302297f61ccSDmitry Chagin l_long f_type; 303297f61ccSDmitry Chagin l_long f_bsize; 304297f61ccSDmitry Chagin l_long f_blocks; 305297f61ccSDmitry Chagin l_long f_bfree; 306297f61ccSDmitry Chagin l_long f_bavail; 307297f61ccSDmitry Chagin l_long f_files; 308297f61ccSDmitry Chagin l_long f_ffree; 3095002a60fSMarcel Moolenaar l_fsid_t f_fsid; 310297f61ccSDmitry Chagin l_long f_namelen; 311e801ac78SEdward Tomasz Napierala l_long f_frsize; 312e801ac78SEdward Tomasz Napierala l_long f_flags; 313e801ac78SEdward Tomasz Napierala l_long f_spare[4]; 314c21dee17SSøren Schmidt }; 315c21dee17SSøren Schmidt 316dca60efcSMarcel Moolenaar #define LINUX_CODA_SUPER_MAGIC 0x73757245L 317dca60efcSMarcel Moolenaar #define LINUX_EXT2_SUPER_MAGIC 0xEF53L 318dca60efcSMarcel Moolenaar #define LINUX_HPFS_SUPER_MAGIC 0xf995e849L 319dca60efcSMarcel Moolenaar #define LINUX_ISOFS_SUPER_MAGIC 0x9660L 320dca60efcSMarcel Moolenaar #define LINUX_MSDOS_SUPER_MAGIC 0x4d44L 321dca60efcSMarcel Moolenaar #define LINUX_NCP_SUPER_MAGIC 0x564cL 322dca60efcSMarcel Moolenaar #define LINUX_NFS_SUPER_MAGIC 0x6969L 323dca60efcSMarcel Moolenaar #define LINUX_NTFS_SUPER_MAGIC 0x5346544EL 324dca60efcSMarcel Moolenaar #define LINUX_PROC_SUPER_MAGIC 0x9fa0L 325dca60efcSMarcel Moolenaar #define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */ 326dbaa9ebfSEd Maste #define LINUX_ZFS_SUPER_MAGIC 0x2FC12FC1 327e83d253bSOlivier Houchard #define LINUX_DEVFS_SUPER_MAGIC 0x1373L 3282166e4e0SDmitry Chagin #define LINUX_SHMFS_MAGIC 0x01021994 329dca60efcSMarcel Moolenaar 330dca60efcSMarcel Moolenaar static long 331962cf420SMaxim Sobolev bsd_to_linux_ftype(const char *fstypename) 332dca60efcSMarcel Moolenaar { 333962cf420SMaxim Sobolev int i; 334962cf420SMaxim Sobolev static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = { 335962cf420SMaxim Sobolev {"ufs", LINUX_UFS_SUPER_MAGIC}, 336dbaa9ebfSEd Maste {"zfs", LINUX_ZFS_SUPER_MAGIC}, 337962cf420SMaxim Sobolev {"cd9660", LINUX_ISOFS_SUPER_MAGIC}, 338962cf420SMaxim Sobolev {"nfs", LINUX_NFS_SUPER_MAGIC}, 339962cf420SMaxim Sobolev {"ext2fs", LINUX_EXT2_SUPER_MAGIC}, 340962cf420SMaxim Sobolev {"procfs", LINUX_PROC_SUPER_MAGIC}, 341962cf420SMaxim Sobolev {"msdosfs", LINUX_MSDOS_SUPER_MAGIC}, 342962cf420SMaxim Sobolev {"ntfs", LINUX_NTFS_SUPER_MAGIC}, 343962cf420SMaxim Sobolev {"nwfs", LINUX_NCP_SUPER_MAGIC}, 344962cf420SMaxim Sobolev {"hpfs", LINUX_HPFS_SUPER_MAGIC}, 345962cf420SMaxim Sobolev {"coda", LINUX_CODA_SUPER_MAGIC}, 346e83d253bSOlivier Houchard {"devfs", LINUX_DEVFS_SUPER_MAGIC}, 3472166e4e0SDmitry Chagin {"tmpfs", LINUX_SHMFS_MAGIC}, 348962cf420SMaxim Sobolev {NULL, 0L}}; 349dca60efcSMarcel Moolenaar 350962cf420SMaxim Sobolev for (i = 0; b2l_tbl[i].bsd_name != NULL; i++) 351962cf420SMaxim Sobolev if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0) 352962cf420SMaxim Sobolev return (b2l_tbl[i].linux_type); 353dca60efcSMarcel Moolenaar 354dca60efcSMarcel Moolenaar return (0L); 355dca60efcSMarcel Moolenaar } 356dca60efcSMarcel Moolenaar 357525c9796SDmitry Chagin static int 3589922bccbSDmitry Chagin bsd_to_linux_mnt_flags(int f_flags) 3599922bccbSDmitry Chagin { 3609922bccbSDmitry Chagin int flags = LINUX_ST_VALID; 3619922bccbSDmitry Chagin 3629922bccbSDmitry Chagin if (f_flags & MNT_RDONLY) 3639922bccbSDmitry Chagin flags |= LINUX_ST_RDONLY; 3649922bccbSDmitry Chagin if (f_flags & MNT_NOEXEC) 3659922bccbSDmitry Chagin flags |= LINUX_ST_NOEXEC; 3669922bccbSDmitry Chagin if (f_flags & MNT_NOSUID) 3679922bccbSDmitry Chagin flags |= LINUX_ST_NOSUID; 3689922bccbSDmitry Chagin if (f_flags & MNT_NOATIME) 3699922bccbSDmitry Chagin flags |= LINUX_ST_NOATIME; 3709922bccbSDmitry Chagin if (f_flags & MNT_NOSYMFOLLOW) 3719922bccbSDmitry Chagin flags |= LINUX_ST_NOSYMFOLLOW; 3729922bccbSDmitry Chagin if (f_flags & MNT_SYNCHRONOUS) 3739922bccbSDmitry Chagin flags |= LINUX_ST_SYNCHRONOUS; 3749922bccbSDmitry Chagin 3759922bccbSDmitry Chagin return (flags); 3769922bccbSDmitry Chagin } 3779922bccbSDmitry Chagin 3789922bccbSDmitry Chagin static int 379d0cad55dSPawel Jakub Dawidek bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs) 380f7a25872SJohn Baldwin { 381953688e8SDmitry Chagin 382525c9796SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 383953688e8SDmitry Chagin statfs_scale_blocks(bsd_statfs, INT32_MAX); 384525c9796SDmitry Chagin #endif 385f7a25872SJohn Baldwin linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename); 386f7a25872SJohn Baldwin linux_statfs->f_bsize = bsd_statfs->f_bsize; 387f7a25872SJohn Baldwin linux_statfs->f_blocks = bsd_statfs->f_blocks; 388f7a25872SJohn Baldwin linux_statfs->f_bfree = bsd_statfs->f_bfree; 389f7a25872SJohn Baldwin linux_statfs->f_bavail = bsd_statfs->f_bavail; 390953688e8SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 391953688e8SDmitry Chagin linux_statfs->f_ffree = MIN(bsd_statfs->f_ffree, INT32_MAX); 392953688e8SDmitry Chagin linux_statfs->f_files = MIN(bsd_statfs->f_files, INT32_MAX); 393953688e8SDmitry Chagin #else 394f7a25872SJohn Baldwin linux_statfs->f_ffree = bsd_statfs->f_ffree; 395f7a25872SJohn Baldwin linux_statfs->f_files = bsd_statfs->f_files; 396953688e8SDmitry Chagin #endif 397f7a25872SJohn Baldwin linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0]; 398f7a25872SJohn Baldwin linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1]; 399f7a25872SJohn Baldwin linux_statfs->f_namelen = MAXNAMLEN; 400e801ac78SEdward Tomasz Napierala linux_statfs->f_frsize = bsd_statfs->f_bsize; 4019922bccbSDmitry Chagin linux_statfs->f_flags = bsd_to_linux_mnt_flags(bsd_statfs->f_flags); 402e801ac78SEdward Tomasz Napierala memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare)); 403525c9796SDmitry Chagin 404525c9796SDmitry Chagin return (0); 405f7a25872SJohn Baldwin } 406f7a25872SJohn Baldwin 407c21dee17SSøren Schmidt int 408b40ce416SJulian Elischer linux_statfs(struct thread *td, struct linux_statfs_args *args) 409c21dee17SSøren Schmidt { 4105002a60fSMarcel Moolenaar struct l_statfs linux_statfs; 4112f304845SKonstantin Belousov struct statfs *bsd_statfs; 412206a5d3aSIan Dowse char *path; 4132166e4e0SDmitry Chagin int error; 414d66a5066SPeter Wemm 415a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 416a125ed50SMateusz Guzik bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 417a125ed50SMateusz Guzik error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs); 418a125ed50SMateusz Guzik } else { 419af4051d2SMateusz Guzik LCONVPATHEXIST(args->path, &path); 4202f304845SKonstantin Belousov bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 4212f304845SKonstantin Belousov error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs); 422206a5d3aSIan Dowse LFREEPATH(path); 423a125ed50SMateusz Guzik } 4242f304845SKonstantin Belousov if (error == 0) 4252f304845SKonstantin Belousov error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs); 4262f304845SKonstantin Belousov free(bsd_statfs, M_STATFS); 4272f304845SKonstantin Belousov if (error != 0) 4282ad02313SDmitry Chagin return (error); 4297958a34cSDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs))); 430c21dee17SSøren Schmidt } 431c21dee17SSøren Schmidt 4327f8f1d7fSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 433835e5061SAlexander Leidinger static void 434835e5061SAlexander Leidinger bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs) 435835e5061SAlexander Leidinger { 436835e5061SAlexander Leidinger 437835e5061SAlexander Leidinger linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename); 438835e5061SAlexander Leidinger linux_statfs->f_bsize = bsd_statfs->f_bsize; 439835e5061SAlexander Leidinger linux_statfs->f_blocks = bsd_statfs->f_blocks; 440835e5061SAlexander Leidinger linux_statfs->f_bfree = bsd_statfs->f_bfree; 441835e5061SAlexander Leidinger linux_statfs->f_bavail = bsd_statfs->f_bavail; 442835e5061SAlexander Leidinger linux_statfs->f_ffree = bsd_statfs->f_ffree; 443835e5061SAlexander Leidinger linux_statfs->f_files = bsd_statfs->f_files; 444835e5061SAlexander Leidinger linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0]; 445835e5061SAlexander Leidinger linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1]; 446835e5061SAlexander Leidinger linux_statfs->f_namelen = MAXNAMLEN; 447e801ac78SEdward Tomasz Napierala linux_statfs->f_frsize = bsd_statfs->f_bsize; 4489922bccbSDmitry Chagin linux_statfs->f_flags = bsd_to_linux_mnt_flags(bsd_statfs->f_flags); 449e801ac78SEdward Tomasz Napierala memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare)); 450835e5061SAlexander Leidinger } 451835e5061SAlexander Leidinger 452835e5061SAlexander Leidinger int 453835e5061SAlexander Leidinger linux_statfs64(struct thread *td, struct linux_statfs64_args *args) 454835e5061SAlexander Leidinger { 455835e5061SAlexander Leidinger struct l_statfs64 linux_statfs; 4562f304845SKonstantin Belousov struct statfs *bsd_statfs; 457835e5061SAlexander Leidinger char *path; 458835e5061SAlexander Leidinger int error; 459835e5061SAlexander Leidinger 4603ab85269SDavid Malone if (args->bufsize != sizeof(struct l_statfs64)) 461340f4a8dSEd Maste return (EINVAL); 4623ab85269SDavid Malone 463a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 464a125ed50SMateusz Guzik bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 465a125ed50SMateusz Guzik error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs); 466a125ed50SMateusz Guzik } else { 467af4051d2SMateusz Guzik LCONVPATHEXIST(args->path, &path); 4682f304845SKonstantin Belousov bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 4692f304845SKonstantin Belousov error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs); 470835e5061SAlexander Leidinger LFREEPATH(path); 471a125ed50SMateusz Guzik } 4722f304845SKonstantin Belousov if (error == 0) 4732f304845SKonstantin Belousov bsd_to_linux_statfs64(bsd_statfs, &linux_statfs); 4742f304845SKonstantin Belousov free(bsd_statfs, M_STATFS); 4752f304845SKonstantin Belousov if (error != 0) 476835e5061SAlexander Leidinger return (error); 4777958a34cSDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs))); 478835e5061SAlexander Leidinger } 47999546279SDmitry Chagin 48099546279SDmitry Chagin int 48199546279SDmitry Chagin linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args) 48299546279SDmitry Chagin { 48399546279SDmitry Chagin struct l_statfs64 linux_statfs; 4842f304845SKonstantin Belousov struct statfs *bsd_statfs; 48599546279SDmitry Chagin int error; 48699546279SDmitry Chagin 48799546279SDmitry Chagin if (args->bufsize != sizeof(struct l_statfs64)) 48899546279SDmitry Chagin return (EINVAL); 48999546279SDmitry Chagin 4902f304845SKonstantin Belousov bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 4912f304845SKonstantin Belousov error = kern_fstatfs(td, args->fd, bsd_statfs); 4922f304845SKonstantin Belousov if (error == 0) 4932f304845SKonstantin Belousov bsd_to_linux_statfs64(bsd_statfs, &linux_statfs); 4942f304845SKonstantin Belousov free(bsd_statfs, M_STATFS); 4952f304845SKonstantin Belousov if (error != 0) 4962f304845SKonstantin Belousov return (error); 49799546279SDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs))); 49899546279SDmitry Chagin } 4997f8f1d7fSDmitry Chagin #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 500835e5061SAlexander Leidinger 501c21dee17SSøren Schmidt int 502b40ce416SJulian Elischer linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args) 503c21dee17SSøren Schmidt { 5045002a60fSMarcel Moolenaar struct l_statfs linux_statfs; 5052f304845SKonstantin Belousov struct statfs *bsd_statfs; 506c21dee17SSøren Schmidt int error; 507c21dee17SSøren Schmidt 5082f304845SKonstantin Belousov bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 5092f304845SKonstantin Belousov error = kern_fstatfs(td, args->fd, bsd_statfs); 5102f304845SKonstantin Belousov if (error == 0) 5112f304845SKonstantin Belousov error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs); 5122f304845SKonstantin Belousov free(bsd_statfs, M_STATFS); 5132f304845SKonstantin Belousov if (error != 0) 5142ad02313SDmitry Chagin return (error); 5157958a34cSDmitry Chagin return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs))); 516c21dee17SSøren Schmidt } 517408da119SMarcel Moolenaar 5185002a60fSMarcel Moolenaar struct l_ustat 519408da119SMarcel Moolenaar { 5205002a60fSMarcel Moolenaar l_daddr_t f_tfree; 5215002a60fSMarcel Moolenaar l_ino_t f_tinode; 5225002a60fSMarcel Moolenaar char f_fname[6]; 5235002a60fSMarcel Moolenaar char f_fpack[6]; 5245002a60fSMarcel Moolenaar }; 5255002a60fSMarcel Moolenaar 526931e2a1aSEd Maste #ifdef LINUX_LEGACY_SYSCALLS 5275002a60fSMarcel Moolenaar int 528b40ce416SJulian Elischer linux_ustat(struct thread *td, struct linux_ustat_args *args) 5295002a60fSMarcel Moolenaar { 5301e247cc2SPoul-Henning Kamp 5311e247cc2SPoul-Henning Kamp return (EOPNOTSUPP); 532408da119SMarcel Moolenaar } 533931e2a1aSEd Maste #endif 5345002a60fSMarcel Moolenaar 5351997c537SDavid E. O'Brien #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 5365002a60fSMarcel Moolenaar 5375002a60fSMarcel Moolenaar static int 5385002a60fSMarcel Moolenaar stat64_copyout(struct stat *buf, void *ubuf) 5395002a60fSMarcel Moolenaar { 5405002a60fSMarcel Moolenaar struct l_stat64 lbuf; 5415002a60fSMarcel Moolenaar 5425002a60fSMarcel Moolenaar bzero(&lbuf, sizeof(lbuf)); 543*166e2e5aSDmitry Chagin lbuf.st_dev = linux_new_encode_dev(buf->st_dev); 5445002a60fSMarcel Moolenaar lbuf.st_ino = buf->st_ino; 5455002a60fSMarcel Moolenaar lbuf.st_mode = buf->st_mode; 5465002a60fSMarcel Moolenaar lbuf.st_nlink = buf->st_nlink; 5475002a60fSMarcel Moolenaar lbuf.st_uid = buf->st_uid; 5485002a60fSMarcel Moolenaar lbuf.st_gid = buf->st_gid; 549*166e2e5aSDmitry Chagin lbuf.st_rdev = linux_new_encode_dev(buf->st_rdev); 5505002a60fSMarcel Moolenaar lbuf.st_size = buf->st_size; 551510ea843SEd Schouten lbuf.st_atim.tv_sec = buf->st_atim.tv_sec; 552510ea843SEd Schouten lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; 553510ea843SEd Schouten lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec; 554510ea843SEd Schouten lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec; 555510ea843SEd Schouten lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec; 556510ea843SEd Schouten lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec; 5575002a60fSMarcel Moolenaar lbuf.st_blksize = buf->st_blksize; 5585002a60fSMarcel Moolenaar lbuf.st_blocks = buf->st_blocks; 5595002a60fSMarcel Moolenaar 5605002a60fSMarcel Moolenaar /* 5615002a60fSMarcel Moolenaar * The __st_ino field makes all the difference. In the Linux kernel 5625002a60fSMarcel Moolenaar * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO, 5635002a60fSMarcel Moolenaar * but without the assignment to __st_ino the runtime linker refuses 5645002a60fSMarcel Moolenaar * to mmap(2) any shared libraries. I guess it's broken alright :-) 5655002a60fSMarcel Moolenaar */ 5665002a60fSMarcel Moolenaar lbuf.__st_ino = buf->st_ino; 5675002a60fSMarcel Moolenaar 5685002a60fSMarcel Moolenaar return (copyout(&lbuf, ubuf, sizeof(lbuf))); 5695002a60fSMarcel Moolenaar } 5705002a60fSMarcel Moolenaar 5715002a60fSMarcel Moolenaar int 572b40ce416SJulian Elischer linux_stat64(struct thread *td, struct linux_stat64_args *args) 5735002a60fSMarcel Moolenaar { 5745002a60fSMarcel Moolenaar struct stat buf; 575206a5d3aSIan Dowse char *filename; 576f7a25872SJohn Baldwin int error; 5775002a60fSMarcel Moolenaar 578a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 579a125ed50SMateusz Guzik error = linux_kern_stat(td, args->filename, UIO_USERSPACE, &buf); 580a125ed50SMateusz Guzik } else { 581af4051d2SMateusz Guzik LCONVPATHEXIST(args->filename, &filename); 5820eee862aSEd Schouten error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf); 583206a5d3aSIan Dowse LFREEPATH(filename); 584a125ed50SMateusz Guzik } 5855002a60fSMarcel Moolenaar if (error) 5865002a60fSMarcel Moolenaar return (error); 5875002a60fSMarcel Moolenaar return (stat64_copyout(&buf, args->statbuf)); 5885002a60fSMarcel Moolenaar } 5895002a60fSMarcel Moolenaar 5905002a60fSMarcel Moolenaar int 591b40ce416SJulian Elischer linux_lstat64(struct thread *td, struct linux_lstat64_args *args) 5925002a60fSMarcel Moolenaar { 5935002a60fSMarcel Moolenaar struct stat sb; 594206a5d3aSIan Dowse char *filename; 595f7a25872SJohn Baldwin int error; 5965002a60fSMarcel Moolenaar 597a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 598a125ed50SMateusz Guzik error = linux_kern_lstat(td, args->filename, UIO_USERSPACE, &sb); 599a125ed50SMateusz Guzik } else { 600af4051d2SMateusz Guzik LCONVPATHEXIST(args->filename, &filename); 6010eee862aSEd Schouten error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb); 602206a5d3aSIan Dowse LFREEPATH(filename); 603a125ed50SMateusz Guzik } 6045002a60fSMarcel Moolenaar if (error) 6055002a60fSMarcel Moolenaar return (error); 6065002a60fSMarcel Moolenaar return (stat64_copyout(&sb, args->statbuf)); 6075002a60fSMarcel Moolenaar } 6085002a60fSMarcel Moolenaar 6095002a60fSMarcel Moolenaar int 610b40ce416SJulian Elischer linux_fstat64(struct thread *td, struct linux_fstat64_args *args) 6115002a60fSMarcel Moolenaar { 6125002a60fSMarcel Moolenaar struct stat buf; 6135002a60fSMarcel Moolenaar int error; 6145002a60fSMarcel Moolenaar 615994ed958SDmitry Chagin error = linux_kern_fstat(td, args->fd, &buf); 6165002a60fSMarcel Moolenaar if (!error) 6175002a60fSMarcel Moolenaar error = stat64_copyout(&buf, args->statbuf); 6185002a60fSMarcel Moolenaar 6195002a60fSMarcel Moolenaar return (error); 6205002a60fSMarcel Moolenaar } 6215002a60fSMarcel Moolenaar 62248b05c3fSKonstantin Belousov int 62348b05c3fSKonstantin Belousov linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args) 62448b05c3fSKonstantin Belousov { 62548b05c3fSKonstantin Belousov char *path; 6269d167945SEdward Tomasz Napierala int error, dfd, flag, unsupported; 62748b05c3fSKonstantin Belousov struct stat buf; 62848b05c3fSKonstantin Belousov 6299d167945SEdward Tomasz Napierala unsupported = args->flag & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH); 6309d167945SEdward Tomasz Napierala if (unsupported != 0) { 6319d167945SEdward Tomasz Napierala linux_msg(td, "fstatat64 unsupported flag 0x%x", unsupported); 63248b05c3fSKonstantin Belousov return (EINVAL); 6334b45c2bbSEdward Tomasz Napierala } 63448b05c3fSKonstantin Belousov flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ? 63548b05c3fSKonstantin Belousov AT_SYMLINK_NOFOLLOW : 0; 6364b45c2bbSEdward Tomasz Napierala flag |= (args->flag & LINUX_AT_EMPTY_PATH) ? 6374b45c2bbSEdward Tomasz Napierala AT_EMPTY_PATH : 0; 63848b05c3fSKonstantin Belousov 63948b05c3fSKonstantin Belousov dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 640a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 641a125ed50SMateusz Guzik error = linux_kern_statat(td, flag, dfd, args->pathname, 642a125ed50SMateusz Guzik UIO_USERSPACE, &buf); 643a125ed50SMateusz Guzik } else { 644af4051d2SMateusz Guzik LCONVPATHEXIST_AT(args->pathname, &path, dfd); 6450eee862aSEd Schouten error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); 64648b05c3fSKonstantin Belousov LFREEPATH(path); 647a125ed50SMateusz Guzik } 648a125ed50SMateusz Guzik if (error == 0) 649a125ed50SMateusz Guzik error = stat64_copyout(&buf, args->statbuf); 65048b05c3fSKonstantin Belousov 65148b05c3fSKonstantin Belousov return (error); 65248b05c3fSKonstantin Belousov } 65348b05c3fSKonstantin Belousov 654606bcc17SDmitry Chagin #else /* __amd64__ && !COMPAT_LINUX32 */ 655606bcc17SDmitry Chagin 656606bcc17SDmitry Chagin int 657606bcc17SDmitry Chagin linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args) 658606bcc17SDmitry Chagin { 659606bcc17SDmitry Chagin char *path; 6609d167945SEdward Tomasz Napierala int error, dfd, flag, unsupported; 661606bcc17SDmitry Chagin struct stat buf; 662606bcc17SDmitry Chagin 6639d167945SEdward Tomasz Napierala unsupported = args->flag & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH); 6649d167945SEdward Tomasz Napierala if (unsupported != 0) { 6659d167945SEdward Tomasz Napierala linux_msg(td, "fstatat unsupported flag 0x%x", unsupported); 666606bcc17SDmitry Chagin return (EINVAL); 6674b45c2bbSEdward Tomasz Napierala } 6684b45c2bbSEdward Tomasz Napierala 669606bcc17SDmitry Chagin flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ? 670606bcc17SDmitry Chagin AT_SYMLINK_NOFOLLOW : 0; 6714b45c2bbSEdward Tomasz Napierala flag |= (args->flag & LINUX_AT_EMPTY_PATH) ? 6724b45c2bbSEdward Tomasz Napierala AT_EMPTY_PATH : 0; 673606bcc17SDmitry Chagin 674606bcc17SDmitry Chagin dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 675a125ed50SMateusz Guzik if (!LUSECONVPATH(td)) { 676a125ed50SMateusz Guzik error = linux_kern_statat(td, flag, dfd, args->pathname, 677a125ed50SMateusz Guzik UIO_USERSPACE, &buf); 678a125ed50SMateusz Guzik } else { 679af4051d2SMateusz Guzik LCONVPATHEXIST_AT(args->pathname, &path, dfd); 680606bcc17SDmitry Chagin error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); 681a125ed50SMateusz Guzik LFREEPATH(path); 682a125ed50SMateusz Guzik } 683606bcc17SDmitry Chagin if (error == 0) 684606bcc17SDmitry Chagin error = newstat_copyout(&buf, args->statbuf); 685606bcc17SDmitry Chagin 686606bcc17SDmitry Chagin return (error); 687606bcc17SDmitry Chagin } 688606bcc17SDmitry Chagin 6891997c537SDavid E. O'Brien #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 6909802eb9eSDmitry Chagin 6919802eb9eSDmitry Chagin int 6929802eb9eSDmitry Chagin linux_syncfs(struct thread *td, struct linux_syncfs_args *args) 6939802eb9eSDmitry Chagin { 6949802eb9eSDmitry Chagin struct mount *mp; 6959802eb9eSDmitry Chagin struct vnode *vp; 6969802eb9eSDmitry Chagin int error, save; 6979802eb9eSDmitry Chagin 698cbd92ce6SMatt Macy error = fgetvp(td, args->fd, &cap_fsync_rights, &vp); 6999802eb9eSDmitry Chagin if (error != 0) 7009802eb9eSDmitry Chagin /* 7019802eb9eSDmitry Chagin * Linux syncfs() returns only EBADF, however fgetvp() 7029802eb9eSDmitry Chagin * can return EINVAL in case of file descriptor does 7039802eb9eSDmitry Chagin * not represent a vnode. XXX. 7049802eb9eSDmitry Chagin */ 7059802eb9eSDmitry Chagin return (error); 7069802eb9eSDmitry Chagin 7079802eb9eSDmitry Chagin mp = vp->v_mount; 7089802eb9eSDmitry Chagin mtx_lock(&mountlist_mtx); 7099802eb9eSDmitry Chagin error = vfs_busy(mp, MBF_MNTLSTLOCK); 7109802eb9eSDmitry Chagin if (error != 0) { 7119802eb9eSDmitry Chagin /* See comment above. */ 7129802eb9eSDmitry Chagin mtx_unlock(&mountlist_mtx); 7139802eb9eSDmitry Chagin goto out; 7149802eb9eSDmitry Chagin } 7159802eb9eSDmitry Chagin if ((mp->mnt_flag & MNT_RDONLY) == 0 && 7169802eb9eSDmitry Chagin vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 7179802eb9eSDmitry Chagin save = curthread_pflags_set(TDP_SYNCIO); 718c8b3463dSMateusz Guzik vfs_periodic(mp, MNT_NOWAIT); 7199802eb9eSDmitry Chagin VFS_SYNC(mp, MNT_NOWAIT); 7209802eb9eSDmitry Chagin curthread_pflags_restore(save); 7219802eb9eSDmitry Chagin vn_finished_write(mp); 7229802eb9eSDmitry Chagin } 7239802eb9eSDmitry Chagin vfs_unbusy(mp); 7249802eb9eSDmitry Chagin 7259802eb9eSDmitry Chagin out: 7269802eb9eSDmitry Chagin vrele(vp); 7279802eb9eSDmitry Chagin return (error); 7289802eb9eSDmitry Chagin } 7292362ad45SPhilippe Michaud-Boudreault 730e9204c5cSDmitry Chagin static int 731e9204c5cSDmitry Chagin statx_copyout(struct stat *buf, void *ubuf) 732e9204c5cSDmitry Chagin { 733e9204c5cSDmitry Chagin struct l_statx tbuf; 734e9204c5cSDmitry Chagin 735e9204c5cSDmitry Chagin bzero(&tbuf, sizeof(tbuf)); 736e9204c5cSDmitry Chagin tbuf.stx_mask = STATX_ALL; 737e9204c5cSDmitry Chagin tbuf.stx_blksize = buf->st_blksize; 738e9204c5cSDmitry Chagin tbuf.stx_attributes = 0; 739e9204c5cSDmitry Chagin tbuf.stx_nlink = buf->st_nlink; 740e9204c5cSDmitry Chagin tbuf.stx_uid = buf->st_uid; 741e9204c5cSDmitry Chagin tbuf.stx_gid = buf->st_gid; 742e9204c5cSDmitry Chagin tbuf.stx_mode = buf->st_mode; 743e9204c5cSDmitry Chagin tbuf.stx_ino = buf->st_ino; 744e9204c5cSDmitry Chagin tbuf.stx_size = buf->st_size; 745e9204c5cSDmitry Chagin tbuf.stx_blocks = buf->st_blocks; 746e9204c5cSDmitry Chagin 747e9204c5cSDmitry Chagin tbuf.stx_atime.tv_sec = buf->st_atim.tv_sec; 748e9204c5cSDmitry Chagin tbuf.stx_atime.tv_nsec = buf->st_atim.tv_nsec; 749e9204c5cSDmitry Chagin tbuf.stx_btime.tv_sec = buf->st_birthtim.tv_sec; 750e9204c5cSDmitry Chagin tbuf.stx_btime.tv_nsec = buf->st_birthtim.tv_nsec; 751e9204c5cSDmitry Chagin tbuf.stx_ctime.tv_sec = buf->st_ctim.tv_sec; 752e9204c5cSDmitry Chagin tbuf.stx_ctime.tv_nsec = buf->st_ctim.tv_nsec; 753e9204c5cSDmitry Chagin tbuf.stx_mtime.tv_sec = buf->st_mtim.tv_sec; 754e9204c5cSDmitry Chagin tbuf.stx_mtime.tv_nsec = buf->st_mtim.tv_nsec; 755*166e2e5aSDmitry Chagin tbuf.stx_rdev_major = linux_encode_major(buf->st_rdev); 756*166e2e5aSDmitry Chagin tbuf.stx_rdev_minor = linux_encode_minor(buf->st_rdev); 757*166e2e5aSDmitry Chagin tbuf.stx_dev_major = linux_encode_major(buf->st_dev); 758*166e2e5aSDmitry Chagin tbuf.stx_dev_minor = linux_encode_minor(buf->st_dev); 759e9204c5cSDmitry Chagin 760e9204c5cSDmitry Chagin return (copyout(&tbuf, ubuf, sizeof(tbuf))); 761e9204c5cSDmitry Chagin } 762e9204c5cSDmitry Chagin 7632362ad45SPhilippe Michaud-Boudreault int 7642362ad45SPhilippe Michaud-Boudreault linux_statx(struct thread *td, struct linux_statx_args *args) 7652362ad45SPhilippe Michaud-Boudreault { 7662362ad45SPhilippe Michaud-Boudreault char *path; 7679d167945SEdward Tomasz Napierala int error, dirfd, flags, unsupported; 7682362ad45SPhilippe Michaud-Boudreault struct stat buf; 7692362ad45SPhilippe Michaud-Boudreault 770ff39d74aSDmitry Chagin unsupported = args->flags & ~(LINUX_AT_SYMLINK_NOFOLLOW | 771ff39d74aSDmitry Chagin LINUX_AT_EMPTY_PATH | LINUX_AT_NO_AUTOMOUNT); 7729d167945SEdward Tomasz Napierala if (unsupported != 0) { 7739d167945SEdward Tomasz Napierala linux_msg(td, "statx unsupported flags 0x%x", unsupported); 7742362ad45SPhilippe Michaud-Boudreault return (EINVAL); 7752362ad45SPhilippe Michaud-Boudreault } 7762362ad45SPhilippe Michaud-Boudreault 7772362ad45SPhilippe Michaud-Boudreault flags = (args->flags & LINUX_AT_SYMLINK_NOFOLLOW) ? 7782362ad45SPhilippe Michaud-Boudreault AT_SYMLINK_NOFOLLOW : 0; 7792362ad45SPhilippe Michaud-Boudreault flags |= (args->flags & LINUX_AT_EMPTY_PATH) ? 7802362ad45SPhilippe Michaud-Boudreault AT_EMPTY_PATH : 0; 7812362ad45SPhilippe Michaud-Boudreault 7822362ad45SPhilippe Michaud-Boudreault dirfd = (args->dirfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dirfd; 7832362ad45SPhilippe Michaud-Boudreault if (!LUSECONVPATH(td)) { 7842362ad45SPhilippe Michaud-Boudreault error = linux_kern_statat(td, flags, dirfd, args->pathname, 7852362ad45SPhilippe Michaud-Boudreault UIO_USERSPACE, &buf); 7862362ad45SPhilippe Michaud-Boudreault } else { 787af4051d2SMateusz Guzik LCONVPATHEXIST_AT(args->pathname, &path, dirfd); 7882362ad45SPhilippe Michaud-Boudreault error = linux_kern_statat(td, flags, dirfd, path, UIO_SYSSPACE, &buf); 7892362ad45SPhilippe Michaud-Boudreault LFREEPATH(path); 7902362ad45SPhilippe Michaud-Boudreault } 7912362ad45SPhilippe Michaud-Boudreault if (error == 0) 7922362ad45SPhilippe Michaud-Boudreault error = statx_copyout(&buf, args->statxbuf); 7932362ad45SPhilippe Michaud-Boudreault 7942362ad45SPhilippe Michaud-Boudreault return (error); 7952362ad45SPhilippe Michaud-Boudreault } 796