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

Cache object: 5b17cf6b693b974616797290fcfd77ce


[ 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.