The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_stats.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1994-1995 Søren Schmidt
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/12.0/sys/compat/linux/linux_stats.c 335201 2018-06-15 14:41:51Z emaste $");
   31 
   32 #include "opt_compat.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/capsicum.h>
   36 #include <sys/dirent.h>
   37 #include <sys/file.h>
   38 #include <sys/filedesc.h>
   39 #include <sys/proc.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mount.h>
   42 #include <sys/namei.h>
   43 #include <sys/stat.h>
   44 #include <sys/syscallsubr.h>
   45 #include <sys/systm.h>
   46 #include <sys/tty.h>
   47 #include <sys/vnode.h>
   48 #include <sys/conf.h>
   49 #include <sys/fcntl.h>
   50 
   51 #ifdef COMPAT_LINUX32
   52 #include <machine/../linux32/linux.h>
   53 #include <machine/../linux32/linux32_proto.h>
   54 #else
   55 #include <machine/../linux/linux.h>
   56 #include <machine/../linux/linux_proto.h>
   57 #endif
   58 
   59 #include <compat/linux/linux_util.h>
   60 #include <compat/linux/linux_file.h>
   61 
   62 
   63 static void
   64 translate_vnhook_major_minor(struct vnode *vp, struct stat *sb)
   65 {
   66         int major, minor;
   67 
   68         if (vp->v_type == VCHR && vp->v_rdev != NULL &&
   69             linux_driver_get_major_minor(devtoname(vp->v_rdev),
   70             &major, &minor) == 0) {
   71                 sb->st_rdev = (major << 8 | minor);
   72         }
   73 }
   74 
   75 static int
   76 linux_kern_statat(struct thread *td, int flag, int fd, char *path,
   77     enum uio_seg pathseg, struct stat *sbp)
   78 {
   79 
   80         return (kern_statat(td, flag, fd, path, pathseg, sbp,
   81             translate_vnhook_major_minor));
   82 }
   83 
   84 #ifdef LINUX_LEGACY_SYSCALLS
   85 static int
   86 linux_kern_stat(struct thread *td, char *path, enum uio_seg pathseg,
   87     struct stat *sbp)
   88 {
   89 
   90         return (linux_kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp));
   91 }
   92 
   93 static int
   94 linux_kern_lstat(struct thread *td, char *path, enum uio_seg pathseg,
   95     struct stat *sbp)
   96 {
   97 
   98         return (linux_kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
   99             pathseg, sbp));
  100 }
  101 #endif
  102 
  103 static void
  104 translate_fd_major_minor(struct thread *td, int fd, struct stat *buf)
  105 {
  106         struct file *fp;
  107         struct vnode *vp;
  108         int major, minor;
  109 
  110         /*
  111          * No capability rights required here.
  112          */
  113         if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) ||
  114             fget(td, fd, &cap_no_rights, &fp) != 0)
  115                 return;
  116         vp = fp->f_vnode;
  117         if (vp != NULL && vp->v_rdev != NULL &&
  118             linux_driver_get_major_minor(devtoname(vp->v_rdev),
  119                                          &major, &minor) == 0) {
  120                 buf->st_rdev = (major << 8 | minor);
  121         } else if (fp->f_type == DTYPE_PTS) {
  122                 struct tty *tp = fp->f_data;
  123 
  124                 /* Convert the numbers for the slave device. */
  125                 if (linux_driver_get_major_minor(devtoname(tp->t_dev),
  126                                          &major, &minor) == 0) {
  127                         buf->st_rdev = (major << 8 | minor);
  128                 }
  129         }
  130         fdrop(fp, td);
  131 }
  132 
  133 /*
  134  * l_dev_t has the same encoding as dev_t in the latter's low 16 bits, so
  135  * truncation of a dev_t to 16 bits gives the same result as unpacking
  136  * using major() and minor() and repacking in the l_dev_t format.  This
  137  * detail is hidden in dev_to_ldev().  Overflow in conversions of dev_t's
  138  * are not checked for, as for other fields.
  139  *
  140  * dev_to_ldev() is only used for translating st_dev.  When we convert
  141  * st_rdev for copying it out, it isn't really a dev_t, but has already
  142  * been translated to an l_dev_t in a nontrivial way.  Translating it
  143  * again would be illogical but would have no effect since the low 16
  144  * bits have the same encoding.
  145  *
  146  * The nontrivial translation for st_rdev renumbers some devices, but not
  147  * ones that can be mounted on, so it is consistent with the translation
  148  * for st_dev except when the renumbering or truncation causes conflicts.
  149  */
  150 #define dev_to_ldev(d)  ((uint16_t)(d))
  151 
  152 static int
  153 newstat_copyout(struct stat *buf, void *ubuf)
  154 {
  155         struct l_newstat tbuf;
  156 
  157         bzero(&tbuf, sizeof(tbuf));
  158         tbuf.st_dev = dev_to_ldev(buf->st_dev);
  159         tbuf.st_ino = buf->st_ino;
  160         tbuf.st_mode = buf->st_mode;
  161         tbuf.st_nlink = buf->st_nlink;
  162         tbuf.st_uid = buf->st_uid;
  163         tbuf.st_gid = buf->st_gid;
  164         tbuf.st_rdev = buf->st_rdev;
  165         tbuf.st_size = buf->st_size;
  166         tbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
  167         tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
  168         tbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
  169         tbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
  170         tbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
  171         tbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
  172         tbuf.st_blksize = buf->st_blksize;
  173         tbuf.st_blocks = buf->st_blocks;
  174 
  175         return (copyout(&tbuf, ubuf, sizeof(tbuf)));
  176 }
  177 
  178 #ifdef LINUX_LEGACY_SYSCALLS
  179 int
  180 linux_newstat(struct thread *td, struct linux_newstat_args *args)
  181 {
  182         struct stat buf;
  183         char *path;
  184         int error;
  185 
  186         LCONVPATHEXIST(td, args->path, &path);
  187 
  188 #ifdef DEBUG
  189         if (ldebug(newstat))
  190                 printf(ARGS(newstat, "%s, *"), path);
  191 #endif
  192 
  193         error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf);
  194         LFREEPATH(path);
  195         if (error)
  196                 return (error);
  197         return (newstat_copyout(&buf, args->buf));
  198 }
  199 
  200 int
  201 linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
  202 {
  203         struct stat sb;
  204         char *path;
  205         int error;
  206 
  207         LCONVPATHEXIST(td, args->path, &path);
  208 
  209 #ifdef DEBUG
  210         if (ldebug(newlstat))
  211                 printf(ARGS(newlstat, "%s, *"), path);
  212 #endif
  213 
  214         error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb);
  215         LFREEPATH(path);
  216         if (error)
  217                 return (error);
  218         return (newstat_copyout(&sb, args->buf));
  219 }
  220 #endif
  221 
  222 int
  223 linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
  224 {
  225         struct stat buf;
  226         int error;
  227 
  228 #ifdef DEBUG
  229         if (ldebug(newfstat))
  230                 printf(ARGS(newfstat, "%d, *"), args->fd);
  231 #endif
  232 
  233         error = kern_fstat(td, args->fd, &buf);
  234         translate_fd_major_minor(td, args->fd, &buf);
  235         if (!error)
  236                 error = newstat_copyout(&buf, args->buf);
  237 
  238         return (error);
  239 }
  240 
  241 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  242 static int
  243 stat_copyout(struct stat *buf, void *ubuf)
  244 {
  245         struct l_stat lbuf;
  246 
  247         bzero(&lbuf, sizeof(lbuf));
  248         lbuf.st_dev = dev_to_ldev(buf->st_dev);
  249         lbuf.st_ino = buf->st_ino;
  250         lbuf.st_mode = buf->st_mode;
  251         lbuf.st_nlink = buf->st_nlink;
  252         lbuf.st_uid = buf->st_uid;
  253         lbuf.st_gid = buf->st_gid;
  254         lbuf.st_rdev = buf->st_rdev;
  255         lbuf.st_size = MIN(buf->st_size, INT32_MAX);
  256         lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
  257         lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
  258         lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
  259         lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
  260         lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
  261         lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
  262         lbuf.st_blksize = buf->st_blksize;
  263         lbuf.st_blocks = buf->st_blocks;
  264         lbuf.st_flags = buf->st_flags;
  265         lbuf.st_gen = buf->st_gen;
  266 
  267         return (copyout(&lbuf, ubuf, sizeof(lbuf)));
  268 }
  269 
  270 int
  271 linux_stat(struct thread *td, struct linux_stat_args *args)
  272 {
  273         struct stat buf;
  274         char *path;
  275         int error;
  276 
  277         LCONVPATHEXIST(td, args->path, &path);
  278 
  279 #ifdef DEBUG
  280         if (ldebug(stat))
  281                 printf(ARGS(stat, "%s, *"), path);
  282 #endif
  283         error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf);
  284         if (error) {
  285                 LFREEPATH(path);
  286                 return (error);
  287         }
  288         LFREEPATH(path);
  289         return (stat_copyout(&buf, args->up));
  290 }
  291 
  292 int
  293 linux_lstat(struct thread *td, struct linux_lstat_args *args)
  294 {
  295         struct stat buf;
  296         char *path;
  297         int error;
  298 
  299         LCONVPATHEXIST(td, args->path, &path);
  300 
  301 #ifdef DEBUG
  302         if (ldebug(lstat))
  303                 printf(ARGS(lstat, "%s, *"), path);
  304 #endif
  305         error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf);
  306         if (error) {
  307                 LFREEPATH(path);
  308                 return (error);
  309         }
  310         LFREEPATH(path);
  311         return (stat_copyout(&buf, args->up));
  312 }
  313 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
  314 
  315 struct l_statfs {
  316         l_long          f_type;
  317         l_long          f_bsize;
  318         l_long          f_blocks;
  319         l_long          f_bfree;
  320         l_long          f_bavail;
  321         l_long          f_files;
  322         l_long          f_ffree;
  323         l_fsid_t        f_fsid;
  324         l_long          f_namelen;
  325         l_long          f_frsize;
  326         l_long          f_flags;
  327         l_long          f_spare[4];
  328 };
  329 
  330 #define LINUX_CODA_SUPER_MAGIC  0x73757245L
  331 #define LINUX_EXT2_SUPER_MAGIC  0xEF53L
  332 #define LINUX_HPFS_SUPER_MAGIC  0xf995e849L
  333 #define LINUX_ISOFS_SUPER_MAGIC 0x9660L
  334 #define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
  335 #define LINUX_NCP_SUPER_MAGIC   0x564cL
  336 #define LINUX_NFS_SUPER_MAGIC   0x6969L
  337 #define LINUX_NTFS_SUPER_MAGIC  0x5346544EL
  338 #define LINUX_PROC_SUPER_MAGIC  0x9fa0L
  339 #define LINUX_UFS_SUPER_MAGIC   0x00011954L     /* XXX - UFS_MAGIC in Linux */
  340 #define LINUX_ZFS_SUPER_MAGIC   0x2FC12FC1
  341 #define LINUX_DEVFS_SUPER_MAGIC 0x1373L
  342 #define LINUX_SHMFS_MAGIC       0x01021994
  343 
  344 static long
  345 bsd_to_linux_ftype(const char *fstypename)
  346 {
  347         int i;
  348         static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
  349                 {"ufs",     LINUX_UFS_SUPER_MAGIC},
  350                 {"zfs",     LINUX_ZFS_SUPER_MAGIC},
  351                 {"cd9660",  LINUX_ISOFS_SUPER_MAGIC},
  352                 {"nfs",     LINUX_NFS_SUPER_MAGIC},
  353                 {"ext2fs",  LINUX_EXT2_SUPER_MAGIC},
  354                 {"procfs",  LINUX_PROC_SUPER_MAGIC},
  355                 {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
  356                 {"ntfs",    LINUX_NTFS_SUPER_MAGIC},
  357                 {"nwfs",    LINUX_NCP_SUPER_MAGIC},
  358                 {"hpfs",    LINUX_HPFS_SUPER_MAGIC},
  359                 {"coda",    LINUX_CODA_SUPER_MAGIC},
  360                 {"devfs",   LINUX_DEVFS_SUPER_MAGIC},
  361                 {"tmpfs",   LINUX_SHMFS_MAGIC},
  362                 {NULL,      0L}};
  363 
  364         for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
  365                 if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
  366                         return (b2l_tbl[i].linux_type);
  367 
  368         return (0L);
  369 }
  370 
  371 static int
  372 bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
  373 {
  374 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  375         uint64_t tmp;
  376 
  377 #define LINUX_HIBITS    0xffffffff00000000ULL
  378 
  379         tmp = bsd_statfs->f_blocks | bsd_statfs->f_bfree | bsd_statfs->f_files |
  380             bsd_statfs->f_bsize;
  381         if ((bsd_statfs->f_bavail != -1 && (bsd_statfs->f_bavail & LINUX_HIBITS)) ||
  382             (bsd_statfs->f_ffree != -1 && (bsd_statfs->f_ffree & LINUX_HIBITS)) ||
  383             (tmp & LINUX_HIBITS))
  384                 return (EOVERFLOW);
  385 #undef  LINUX_HIBITS
  386 #endif
  387         linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
  388         linux_statfs->f_bsize = bsd_statfs->f_bsize;
  389         linux_statfs->f_blocks = bsd_statfs->f_blocks;
  390         linux_statfs->f_bfree = bsd_statfs->f_bfree;
  391         linux_statfs->f_bavail = bsd_statfs->f_bavail;
  392         linux_statfs->f_ffree = bsd_statfs->f_ffree;
  393         linux_statfs->f_files = bsd_statfs->f_files;
  394         linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
  395         linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
  396         linux_statfs->f_namelen = MAXNAMLEN;
  397         linux_statfs->f_frsize = bsd_statfs->f_bsize;
  398         linux_statfs->f_flags = 0;
  399         memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
  400 
  401         return (0);
  402 }
  403 
  404 int
  405 linux_statfs(struct thread *td, struct linux_statfs_args *args)
  406 {
  407         struct l_statfs linux_statfs;
  408         struct statfs *bsd_statfs;
  409         char *path;
  410         int error;
  411 
  412         LCONVPATHEXIST(td, args->path, &path);
  413 
  414 #ifdef DEBUG
  415         if (ldebug(statfs))
  416                 printf(ARGS(statfs, "%s, *"), path);
  417 #endif
  418         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  419         error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs);
  420         LFREEPATH(path);
  421         if (error == 0)
  422                 error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
  423         free(bsd_statfs, M_STATFS);
  424         if (error != 0)
  425                 return (error);
  426         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  427 }
  428 
  429 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  430 static void
  431 bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs)
  432 {
  433 
  434         linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
  435         linux_statfs->f_bsize = bsd_statfs->f_bsize;
  436         linux_statfs->f_blocks = bsd_statfs->f_blocks;
  437         linux_statfs->f_bfree = bsd_statfs->f_bfree;
  438         linux_statfs->f_bavail = bsd_statfs->f_bavail;
  439         linux_statfs->f_ffree = bsd_statfs->f_ffree;
  440         linux_statfs->f_files = bsd_statfs->f_files;
  441         linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
  442         linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
  443         linux_statfs->f_namelen = MAXNAMLEN;
  444         linux_statfs->f_frsize = bsd_statfs->f_bsize;
  445         linux_statfs->f_flags = 0;
  446         memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
  447 }
  448 
  449 int
  450 linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
  451 {
  452         struct l_statfs64 linux_statfs;
  453         struct statfs *bsd_statfs;
  454         char *path;
  455         int error;
  456 
  457         if (args->bufsize != sizeof(struct l_statfs64))
  458                 return (EINVAL);
  459 
  460         LCONVPATHEXIST(td, args->path, &path);
  461 
  462 #ifdef DEBUG
  463         if (ldebug(statfs64))
  464                 printf(ARGS(statfs64, "%s, *"), path);
  465 #endif
  466         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  467         error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs);
  468         LFREEPATH(path);
  469         if (error == 0)
  470                 bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
  471         free(bsd_statfs, M_STATFS);
  472         if (error != 0)
  473                 return (error);
  474         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  475 }
  476 
  477 int
  478 linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
  479 {
  480         struct l_statfs64 linux_statfs;
  481         struct statfs *bsd_statfs;
  482         int error;
  483 
  484 #ifdef DEBUG
  485         if (ldebug(fstatfs64))
  486                 printf(ARGS(fstatfs64, "%d, *"), args->fd);
  487 #endif
  488         if (args->bufsize != sizeof(struct l_statfs64))
  489                 return (EINVAL);
  490 
  491         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  492         error = kern_fstatfs(td, args->fd, bsd_statfs);
  493         if (error == 0)
  494                 bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
  495         free(bsd_statfs, M_STATFS);
  496         if (error != 0)
  497                 return (error);
  498         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  499 }
  500 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
  501 
  502 int
  503 linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
  504 {
  505         struct l_statfs linux_statfs;
  506         struct statfs *bsd_statfs;
  507         int error;
  508 
  509 #ifdef DEBUG
  510         if (ldebug(fstatfs))
  511                 printf(ARGS(fstatfs, "%d, *"), args->fd);
  512 #endif
  513         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  514         error = kern_fstatfs(td, args->fd, bsd_statfs);
  515         if (error == 0)
  516                 error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
  517         free(bsd_statfs, M_STATFS);
  518         if (error != 0)
  519                 return (error);
  520         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  521 }
  522 
  523 struct l_ustat
  524 {
  525         l_daddr_t       f_tfree;
  526         l_ino_t         f_tinode;
  527         char            f_fname[6];
  528         char            f_fpack[6];
  529 };
  530 
  531 #ifdef LINUX_LEGACY_SYSCALLS
  532 int
  533 linux_ustat(struct thread *td, struct linux_ustat_args *args)
  534 {
  535 #ifdef DEBUG
  536         if (ldebug(ustat))
  537                 printf(ARGS(ustat, "%ju, *"), (uintmax_t)args->dev);
  538 #endif
  539 
  540         return (EOPNOTSUPP);
  541 }
  542 #endif
  543 
  544 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  545 
  546 static int
  547 stat64_copyout(struct stat *buf, void *ubuf)
  548 {
  549         struct l_stat64 lbuf;
  550 
  551         bzero(&lbuf, sizeof(lbuf));
  552         lbuf.st_dev = dev_to_ldev(buf->st_dev);
  553         lbuf.st_ino = buf->st_ino;
  554         lbuf.st_mode = buf->st_mode;
  555         lbuf.st_nlink = buf->st_nlink;
  556         lbuf.st_uid = buf->st_uid;
  557         lbuf.st_gid = buf->st_gid;
  558         lbuf.st_rdev = buf->st_rdev;
  559         lbuf.st_size = buf->st_size;
  560         lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
  561         lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
  562         lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
  563         lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
  564         lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
  565         lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
  566         lbuf.st_blksize = buf->st_blksize;
  567         lbuf.st_blocks = buf->st_blocks;
  568 
  569         /*
  570          * The __st_ino field makes all the difference. In the Linux kernel
  571          * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
  572          * but without the assignment to __st_ino the runtime linker refuses
  573          * to mmap(2) any shared libraries. I guess it's broken alright :-)
  574          */
  575         lbuf.__st_ino = buf->st_ino;
  576 
  577         return (copyout(&lbuf, ubuf, sizeof(lbuf)));
  578 }
  579 
  580 int
  581 linux_stat64(struct thread *td, struct linux_stat64_args *args)
  582 {
  583         struct stat buf;
  584         char *filename;
  585         int error;
  586 
  587         LCONVPATHEXIST(td, args->filename, &filename);
  588 
  589 #ifdef DEBUG
  590         if (ldebug(stat64))
  591                 printf(ARGS(stat64, "%s, *"), filename);
  592 #endif
  593 
  594         error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf);
  595         LFREEPATH(filename);
  596         if (error)
  597                 return (error);
  598         return (stat64_copyout(&buf, args->statbuf));
  599 }
  600 
  601 int
  602 linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
  603 {
  604         struct stat sb;
  605         char *filename;
  606         int error;
  607 
  608         LCONVPATHEXIST(td, args->filename, &filename);
  609 
  610 #ifdef DEBUG
  611         if (ldebug(lstat64))
  612                 printf(ARGS(lstat64, "%s, *"), args->filename);
  613 #endif
  614 
  615         error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb);
  616         LFREEPATH(filename);
  617         if (error)
  618                 return (error);
  619         return (stat64_copyout(&sb, args->statbuf));
  620 }
  621 
  622 int
  623 linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
  624 {
  625         struct stat buf;
  626         int error;
  627 
  628 #ifdef DEBUG
  629         if (ldebug(fstat64))
  630                 printf(ARGS(fstat64, "%d, *"), args->fd);
  631 #endif
  632 
  633         error = kern_fstat(td, args->fd, &buf);
  634         translate_fd_major_minor(td, args->fd, &buf);
  635         if (!error)
  636                 error = stat64_copyout(&buf, args->statbuf);
  637 
  638         return (error);
  639 }
  640 
  641 int
  642 linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args)
  643 {
  644         char *path;
  645         int error, dfd, flag;
  646         struct stat buf;
  647 
  648         if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
  649                 return (EINVAL);
  650         flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
  651             AT_SYMLINK_NOFOLLOW : 0;
  652 
  653         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
  654         LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
  655 
  656 #ifdef DEBUG
  657         if (ldebug(fstatat64))
  658                 printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag);
  659 #endif
  660 
  661         error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
  662         if (!error)
  663                 error = stat64_copyout(&buf, args->statbuf);
  664         LFREEPATH(path);
  665 
  666         return (error);
  667 }
  668 
  669 #else /* __amd64__ && !COMPAT_LINUX32 */
  670 
  671 int
  672 linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args)
  673 {
  674         char *path;
  675         int error, dfd, flag;
  676         struct stat buf;
  677 
  678         if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
  679                 return (EINVAL);
  680         flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
  681             AT_SYMLINK_NOFOLLOW : 0;
  682 
  683         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
  684         LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
  685 
  686 #ifdef DEBUG
  687         if (ldebug(newfstatat))
  688                 printf(ARGS(newfstatat, "%i, %s, %i"), args->dfd, path, args->flag);
  689 #endif
  690 
  691         error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
  692         if (error == 0)
  693                 error = newstat_copyout(&buf, args->statbuf);
  694         LFREEPATH(path);
  695 
  696         return (error);
  697 }
  698 
  699 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
  700 
  701 int
  702 linux_syncfs(struct thread *td, struct linux_syncfs_args *args)
  703 {
  704         struct mount *mp;
  705         struct vnode *vp;
  706         int error, save;
  707 
  708         error = fgetvp(td, args->fd, &cap_fsync_rights, &vp);
  709         if (error != 0)
  710                 /*
  711                  * Linux syncfs() returns only EBADF, however fgetvp()
  712                  * can return EINVAL in case of file descriptor does
  713                  * not represent a vnode. XXX.
  714                  */
  715                 return (error);
  716 
  717         mp = vp->v_mount;
  718         mtx_lock(&mountlist_mtx);
  719         error = vfs_busy(mp, MBF_MNTLSTLOCK);
  720         if (error != 0) {
  721                 /* See comment above. */
  722                 mtx_unlock(&mountlist_mtx);
  723                 goto out;
  724         }
  725         if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
  726             vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
  727                 save = curthread_pflags_set(TDP_SYNCIO);
  728                 vfs_msync(mp, MNT_NOWAIT);
  729                 VFS_SYNC(mp, MNT_NOWAIT);
  730                 curthread_pflags_restore(save);
  731                 vn_finished_write(mp);
  732         }
  733         vfs_unbusy(mp);
  734 
  735  out:
  736         vrele(vp);
  737         return (error);
  738 }

Cache object: 5dd14f98fa362efadfe41ccfbe0f20e5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.