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/11.2/sys/compat/linux/linux_stats.c 330997 2018-03-15 12:56:22Z 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 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_ZFS_SUPER_MAGIC   0x2FC12FC1
  322 #define LINUX_DEVFS_SUPER_MAGIC 0x1373L
  323 #define LINUX_SHMFS_MAGIC       0x01021994
  324 
  325 static long
  326 bsd_to_linux_ftype(const char *fstypename)
  327 {
  328         int i;
  329         static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
  330                 {"ufs",     LINUX_UFS_SUPER_MAGIC},
  331                 {"zfs",     LINUX_ZFS_SUPER_MAGIC},
  332                 {"cd9660",  LINUX_ISOFS_SUPER_MAGIC},
  333                 {"nfs",     LINUX_NFS_SUPER_MAGIC},
  334                 {"ext2fs",  LINUX_EXT2_SUPER_MAGIC},
  335                 {"procfs",  LINUX_PROC_SUPER_MAGIC},
  336                 {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
  337                 {"ntfs",    LINUX_NTFS_SUPER_MAGIC},
  338                 {"nwfs",    LINUX_NCP_SUPER_MAGIC},
  339                 {"hpfs",    LINUX_HPFS_SUPER_MAGIC},
  340                 {"coda",    LINUX_CODA_SUPER_MAGIC},
  341                 {"devfs",   LINUX_DEVFS_SUPER_MAGIC},
  342                 {"tmpfs",   LINUX_SHMFS_MAGIC},
  343                 {NULL,      0L}};
  344 
  345         for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
  346                 if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
  347                         return (b2l_tbl[i].linux_type);
  348 
  349         return (0L);
  350 }
  351 
  352 static int
  353 bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
  354 {
  355 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  356         uint64_t tmp;
  357 
  358 #define LINUX_HIBITS    0xffffffff00000000ULL
  359 
  360         tmp = bsd_statfs->f_blocks | bsd_statfs->f_bfree | bsd_statfs->f_files |
  361             bsd_statfs->f_bsize;
  362         if ((bsd_statfs->f_bavail != -1 && (bsd_statfs->f_bavail & LINUX_HIBITS)) ||
  363             (bsd_statfs->f_ffree != -1 && (bsd_statfs->f_ffree & LINUX_HIBITS)) ||
  364             (tmp & LINUX_HIBITS))
  365                 return (EOVERFLOW);
  366 #undef  LINUX_HIBITS
  367 #endif
  368         linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
  369         linux_statfs->f_bsize = bsd_statfs->f_bsize;
  370         linux_statfs->f_blocks = bsd_statfs->f_blocks;
  371         linux_statfs->f_bfree = bsd_statfs->f_bfree;
  372         linux_statfs->f_bavail = bsd_statfs->f_bavail;
  373         linux_statfs->f_ffree = bsd_statfs->f_ffree;
  374         linux_statfs->f_files = bsd_statfs->f_files;
  375         linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
  376         linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
  377         linux_statfs->f_namelen = MAXNAMLEN;
  378         linux_statfs->f_frsize = bsd_statfs->f_bsize;
  379         linux_statfs->f_flags = 0;
  380         memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
  381 
  382         return (0);
  383 }
  384 
  385 int
  386 linux_statfs(struct thread *td, struct linux_statfs_args *args)
  387 {
  388         struct l_statfs linux_statfs;
  389         struct statfs *bsd_statfs;
  390         char *path;
  391         int error;
  392 
  393         LCONVPATHEXIST(td, args->path, &path);
  394 
  395 #ifdef DEBUG
  396         if (ldebug(statfs))
  397                 printf(ARGS(statfs, "%s, *"), path);
  398 #endif
  399         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  400         error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs);
  401         LFREEPATH(path);
  402         if (error == 0)
  403                 error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
  404         free(bsd_statfs, M_STATFS);
  405         if (error != 0)
  406                 return (error);
  407         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  408 }
  409 
  410 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  411 static void
  412 bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs)
  413 {
  414 
  415         linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
  416         linux_statfs->f_bsize = bsd_statfs->f_bsize;
  417         linux_statfs->f_blocks = bsd_statfs->f_blocks;
  418         linux_statfs->f_bfree = bsd_statfs->f_bfree;
  419         linux_statfs->f_bavail = bsd_statfs->f_bavail;
  420         linux_statfs->f_ffree = bsd_statfs->f_ffree;
  421         linux_statfs->f_files = bsd_statfs->f_files;
  422         linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
  423         linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
  424         linux_statfs->f_namelen = MAXNAMLEN;
  425         linux_statfs->f_frsize = bsd_statfs->f_bsize;
  426         linux_statfs->f_flags = 0;
  427         memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
  428 }
  429 
  430 int
  431 linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
  432 {
  433         struct l_statfs64 linux_statfs;
  434         struct statfs *bsd_statfs;
  435         char *path;
  436         int error;
  437 
  438         if (args->bufsize != sizeof(struct l_statfs64))
  439                 return EINVAL;
  440 
  441         LCONVPATHEXIST(td, args->path, &path);
  442 
  443 #ifdef DEBUG
  444         if (ldebug(statfs64))
  445                 printf(ARGS(statfs64, "%s, *"), path);
  446 #endif
  447         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  448         error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs);
  449         LFREEPATH(path);
  450         if (error == 0)
  451                 bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
  452         free(bsd_statfs, M_STATFS);
  453         if (error != 0)
  454                 return (error);
  455         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  456 }
  457 
  458 int
  459 linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
  460 {
  461         struct l_statfs64 linux_statfs;
  462         struct statfs *bsd_statfs;
  463         int error;
  464 
  465 #ifdef DEBUG
  466         if (ldebug(fstatfs64))
  467                 printf(ARGS(fstatfs64, "%d, *"), args->fd);
  468 #endif
  469         if (args->bufsize != sizeof(struct l_statfs64))
  470                 return (EINVAL);
  471 
  472         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  473         error = kern_fstatfs(td, args->fd, bsd_statfs);
  474         if (error == 0)
  475                 bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
  476         free(bsd_statfs, M_STATFS);
  477         if (error != 0)
  478                 return (error);
  479         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  480 }
  481 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
  482 
  483 int
  484 linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
  485 {
  486         struct l_statfs linux_statfs;
  487         struct statfs *bsd_statfs;
  488         int error;
  489 
  490 #ifdef DEBUG
  491         if (ldebug(fstatfs))
  492                 printf(ARGS(fstatfs, "%d, *"), args->fd);
  493 #endif
  494         bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
  495         error = kern_fstatfs(td, args->fd, bsd_statfs);
  496         if (error == 0)
  497                 error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
  498         free(bsd_statfs, M_STATFS);
  499         if (error != 0)
  500                 return (error);
  501         return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
  502 }
  503 
  504 struct l_ustat
  505 {
  506         l_daddr_t       f_tfree;
  507         l_ino_t         f_tinode;
  508         char            f_fname[6];
  509         char            f_fpack[6];
  510 };
  511 
  512 int
  513 linux_ustat(struct thread *td, struct linux_ustat_args *args)
  514 {
  515 #ifdef DEBUG
  516         if (ldebug(ustat))
  517                 printf(ARGS(ustat, "%ju, *"), (uintmax_t)args->dev);
  518 #endif
  519 
  520         return (EOPNOTSUPP);
  521 }
  522 
  523 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  524 
  525 static int
  526 stat64_copyout(struct stat *buf, void *ubuf)
  527 {
  528         struct l_stat64 lbuf;
  529 
  530         bzero(&lbuf, sizeof(lbuf));
  531         lbuf.st_dev = minor(buf->st_dev) | (major(buf->st_dev) << 8);
  532         lbuf.st_ino = buf->st_ino;
  533         lbuf.st_mode = buf->st_mode;
  534         lbuf.st_nlink = buf->st_nlink;
  535         lbuf.st_uid = buf->st_uid;
  536         lbuf.st_gid = buf->st_gid;
  537         lbuf.st_rdev = buf->st_rdev;
  538         lbuf.st_size = buf->st_size;
  539         lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
  540         lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
  541         lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
  542         lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
  543         lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
  544         lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
  545         lbuf.st_blksize = buf->st_blksize;
  546         lbuf.st_blocks = buf->st_blocks;
  547 
  548         /*
  549          * The __st_ino field makes all the difference. In the Linux kernel
  550          * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
  551          * but without the assignment to __st_ino the runtime linker refuses
  552          * to mmap(2) any shared libraries. I guess it's broken alright :-)
  553          */
  554         lbuf.__st_ino = buf->st_ino;
  555 
  556         return (copyout(&lbuf, ubuf, sizeof(lbuf)));
  557 }
  558 
  559 int
  560 linux_stat64(struct thread *td, struct linux_stat64_args *args)
  561 {
  562         struct stat buf;
  563         char *filename;
  564         int error;
  565 
  566         LCONVPATHEXIST(td, args->filename, &filename);
  567 
  568 #ifdef DEBUG
  569         if (ldebug(stat64))
  570                 printf(ARGS(stat64, "%s, *"), filename);
  571 #endif
  572 
  573         error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf);
  574         LFREEPATH(filename);
  575         if (error)
  576                 return (error);
  577         return (stat64_copyout(&buf, args->statbuf));
  578 }
  579 
  580 int
  581 linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
  582 {
  583         struct stat sb;
  584         char *filename;
  585         int error;
  586 
  587         LCONVPATHEXIST(td, args->filename, &filename);
  588 
  589 #ifdef DEBUG
  590         if (ldebug(lstat64))
  591                 printf(ARGS(lstat64, "%s, *"), args->filename);
  592 #endif
  593 
  594         error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb);
  595         LFREEPATH(filename);
  596         if (error)
  597                 return (error);
  598         return (stat64_copyout(&sb, args->statbuf));
  599 }
  600 
  601 int
  602 linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
  603 {
  604         struct stat buf;
  605         int error;
  606 
  607 #ifdef DEBUG
  608         if (ldebug(fstat64))
  609                 printf(ARGS(fstat64, "%d, *"), args->fd);
  610 #endif
  611 
  612         error = kern_fstat(td, args->fd, &buf);
  613         translate_fd_major_minor(td, args->fd, &buf);
  614         if (!error)
  615                 error = stat64_copyout(&buf, args->statbuf);
  616 
  617         return (error);
  618 }
  619 
  620 int
  621 linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args)
  622 {
  623         char *path;
  624         int error, dfd, flag;
  625         struct stat buf;
  626 
  627         if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
  628                 return (EINVAL);
  629         flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
  630             AT_SYMLINK_NOFOLLOW : 0;
  631 
  632         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
  633         LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
  634 
  635 #ifdef DEBUG
  636         if (ldebug(fstatat64))
  637                 printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag);
  638 #endif
  639 
  640         error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
  641         if (!error)
  642                 error = stat64_copyout(&buf, args->statbuf);
  643         LFREEPATH(path);
  644 
  645         return (error);
  646 }
  647 
  648 #else /* __amd64__ && !COMPAT_LINUX32 */
  649 
  650 int
  651 linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args)
  652 {
  653         char *path;
  654         int error, dfd, flag;
  655         struct stat buf;
  656 
  657         if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
  658                 return (EINVAL);
  659         flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
  660             AT_SYMLINK_NOFOLLOW : 0;
  661 
  662         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
  663         LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
  664 
  665 #ifdef DEBUG
  666         if (ldebug(newfstatat))
  667                 printf(ARGS(newfstatat, "%i, %s, %i"), args->dfd, path, args->flag);
  668 #endif
  669 
  670         error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
  671         if (error == 0)
  672                 error = newstat_copyout(&buf, args->statbuf);
  673         LFREEPATH(path);
  674 
  675         return (error);
  676 }
  677 
  678 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
  679 
  680 int
  681 linux_syncfs(struct thread *td, struct linux_syncfs_args *args)
  682 {
  683         cap_rights_t rights;
  684         struct mount *mp;
  685         struct vnode *vp;
  686         int error, save;
  687 
  688         error = fgetvp(td, args->fd, cap_rights_init(&rights, CAP_FSYNC), &vp);
  689         if (error != 0)
  690                 /*
  691                  * Linux syncfs() returns only EBADF, however fgetvp()
  692                  * can return EINVAL in case of file descriptor does
  693                  * not represent a vnode. XXX.
  694                  */
  695                 return (error);
  696 
  697         mp = vp->v_mount;
  698         mtx_lock(&mountlist_mtx);
  699         error = vfs_busy(mp, MBF_MNTLSTLOCK);
  700         if (error != 0) {
  701                 /* See comment above. */
  702                 mtx_unlock(&mountlist_mtx);
  703                 goto out;
  704         }
  705         if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
  706             vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
  707                 save = curthread_pflags_set(TDP_SYNCIO);
  708                 vfs_msync(mp, MNT_NOWAIT);
  709                 VFS_SYNC(mp, MNT_NOWAIT);
  710                 curthread_pflags_restore(save);
  711                 vn_finished_write(mp);
  712         }
  713         vfs_unbusy(mp);
  714 
  715  out:
  716         vrele(vp);
  717         return (error);
  718 }

Cache object: 5c252b28890face75c4e80fce8e835a8


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