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/emulation/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  * $FreeBSD: src/sys/compat/linux/linux_stats.c,v 1.22.2.3 2001/11/05 19:08:23 marcel Exp $
   29  * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.27 2008/09/28 05:08:16 dillon Exp $
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/conf.h>
   35 #include <sys/dirent.h>
   36 #include <sys/file.h>
   37 #include <sys/filedesc.h>
   38 #include <sys/proc.h>
   39 #include <sys/mount.h>
   40 #include <sys/nlookup.h>
   41 #include <sys/stat.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/systm.h>
   44 #include <sys/unistd.h>
   45 #include <sys/vnode.h>
   46 #include <sys/device.h>
   47 #include <sys/kern_syscall.h>
   48 #include <emulation/43bsd/stat.h>
   49 
   50 #include <sys/file2.h>
   51 #include <sys/mplock2.h>
   52 
   53 #include <arch_linux/linux.h>
   54 #include <arch_linux/linux_proto.h>
   55 #include "linux_util.h"
   56 
   57 static int
   58 newstat_copyout(struct stat *buf, void *ubuf)
   59 {
   60         struct l_newstat tbuf;
   61         int error;
   62 
   63         bzero(&tbuf, sizeof(tbuf));
   64         tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
   65         tbuf.st_ino = INO64TO32(buf->st_ino);
   66         tbuf.st_mode = buf->st_mode;
   67         tbuf.st_nlink = buf->st_nlink;
   68         tbuf.st_uid = buf->st_uid;
   69         tbuf.st_gid = buf->st_gid;
   70         tbuf.st_rdev = buf->st_rdev;
   71         tbuf.st_size = buf->st_size;
   72         tbuf.st_atime = buf->st_atime;
   73         tbuf.st_mtime = buf->st_mtime;
   74         tbuf.st_ctime = buf->st_ctime;
   75         tbuf.st_blksize = buf->st_blksize;
   76         tbuf.st_blocks = buf->st_blocks;
   77 
   78         error = copyout(&tbuf, ubuf, sizeof(tbuf));
   79         return (error);
   80 }
   81 
   82 static int
   83 ostat_copyout(struct stat *st, struct ostat *uaddr)
   84 {
   85         struct ostat ost;
   86         int error;
   87 
   88         ost.st_dev = st->st_dev;
   89         ost.st_ino = st->st_ino;
   90         ost.st_mode = st->st_mode;
   91         ost.st_nlink = st->st_nlink;
   92         ost.st_uid = st->st_uid;
   93         ost.st_gid = st->st_gid;
   94         ost.st_rdev = st->st_rdev;
   95         if (st->st_size < (quad_t)1 << 32)
   96                 ost.st_size = st->st_size;
   97         else
   98                 ost.st_size = -2;
   99         ost.st_atime = st->st_atime;
  100         ost.st_mtime = st->st_mtime;
  101         ost.st_ctime = st->st_ctime;
  102         ost.st_blksize = st->st_blksize;
  103         ost.st_blocks = st->st_blocks;
  104         ost.st_flags = st->st_flags;
  105         ost.st_gen = st->st_gen;
  106 
  107         error = copyout(&ost, uaddr, sizeof(ost));
  108         return (error);
  109 }
  110 
  111 /*
  112  * MPALMOSTSAFE
  113  */
  114 int
  115 sys_linux_newstat(struct linux_newstat_args *args)
  116 {
  117         struct stat buf;
  118         struct nlookupdata nd;
  119         char *path;
  120         int error;
  121 
  122         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
  123         if (error)
  124                 return (error);
  125 #ifdef DEBUG
  126         if (ldebug(newstat))
  127                 kprintf(ARGS(newstat, "%s, *"), path);
  128 #endif
  129         get_mplock();
  130         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
  131         if (error == 0) {
  132                 error = kern_stat(&nd, &buf);
  133                 if (error == 0)
  134                         error = newstat_copyout(&buf, args->buf);
  135                 nlookup_done(&nd);
  136         }
  137         rel_mplock();
  138         linux_free_path(&path);
  139         return (error);
  140 }
  141 
  142 /*
  143  * MPALMOSTSAFE
  144  */
  145 int
  146 sys_linux_newlstat(struct linux_newlstat_args *args)
  147 {
  148         struct stat sb;
  149         struct nlookupdata nd;
  150         char *path;
  151         int error;
  152 
  153         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
  154         if (error)
  155                 return (error);
  156 #ifdef DEBUG
  157         if (ldebug(newlstat))
  158                 kprintf(ARGS(newlstat, "%s, *"), path);
  159 #endif
  160         get_mplock();
  161         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
  162         if (error == 0) {
  163                 error = kern_stat(&nd, &sb);
  164                 if (error == 0)
  165                         error = newstat_copyout(&sb, args->buf);
  166                 nlookup_done(&nd);
  167         }
  168         rel_mplock();
  169         linux_free_path(&path);
  170         return (error);
  171 }
  172 
  173 /*
  174  * MPALMOSTSAFE
  175  */
  176 int
  177 sys_linux_newfstat(struct linux_newfstat_args *args)
  178 {
  179         struct stat buf;
  180         int error;
  181 
  182 #ifdef DEBUG
  183         if (ldebug(newfstat))
  184                 kprintf(ARGS(newfstat, "%d, *"), args->fd);
  185 #endif
  186         get_mplock();
  187         error = kern_fstat(args->fd, &buf);
  188         rel_mplock();
  189 
  190         if (error == 0)
  191                 error = newstat_copyout(&buf, args->buf);
  192         return (error);
  193 }
  194 
  195 /* XXX - All fields of type l_int are defined as l_long on i386 */
  196 struct l_statfs {
  197         l_int           f_type;
  198         l_int           f_bsize;
  199         l_int           f_blocks;
  200         l_int           f_bfree;
  201         l_int           f_bavail;
  202         l_int           f_files;
  203         l_int           f_ffree;
  204         l_fsid_t        f_fsid;
  205         l_int           f_namelen;
  206         l_int           f_spare[6];
  207 };
  208 
  209 #define LINUX_CODA_SUPER_MAGIC  0x73757245L
  210 #define LINUX_EXT2_SUPER_MAGIC  0xEF53L
  211 #define LINUX_HPFS_SUPER_MAGIC  0xf995e849L
  212 #define LINUX_ISOFS_SUPER_MAGIC 0x9660L
  213 #define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
  214 #define LINUX_NCP_SUPER_MAGIC   0x564cL
  215 #define LINUX_NFS_SUPER_MAGIC   0x6969L
  216 #define LINUX_NTFS_SUPER_MAGIC  0x5346544EL
  217 #define LINUX_PROC_SUPER_MAGIC  0x9fa0L
  218 #define LINUX_UFS_SUPER_MAGIC   0x00011954L     /* XXX - UFS_MAGIC in Linux */
  219 
  220 static long
  221 bsd_to_linux_ftype(const char *fstypename)
  222 {
  223         int i;
  224         static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
  225                 {"ufs",     LINUX_UFS_SUPER_MAGIC},
  226                 {"cd9660",  LINUX_ISOFS_SUPER_MAGIC},
  227                 {"nfs",     LINUX_NFS_SUPER_MAGIC},
  228                 {"ext2fs",  LINUX_EXT2_SUPER_MAGIC},
  229                 {"procfs",  LINUX_PROC_SUPER_MAGIC},
  230                 {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
  231                 {"ntfs",    LINUX_NTFS_SUPER_MAGIC},
  232                 {"nwfs",    LINUX_NCP_SUPER_MAGIC},
  233                 {"hpfs",    LINUX_HPFS_SUPER_MAGIC},
  234                 {NULL,      0L}};
  235 
  236         for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
  237                 if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
  238                         return (b2l_tbl[i].linux_type);
  239 
  240         return (0L);
  241 }
  242 
  243 static int
  244 statfs_copyout(struct statfs *statfs, struct l_statfs_buf *buf, l_int namelen)
  245 {
  246         struct l_statfs linux_statfs;
  247         int error;
  248 
  249         linux_statfs.f_type = bsd_to_linux_ftype(statfs->f_fstypename);
  250         linux_statfs.f_bsize = statfs->f_bsize;
  251         linux_statfs.f_blocks = statfs->f_blocks;
  252         linux_statfs.f_bfree = statfs->f_bfree;
  253         linux_statfs.f_bavail = statfs->f_bavail;
  254         linux_statfs.f_ffree = statfs->f_ffree;
  255         linux_statfs.f_files = statfs->f_files;
  256         linux_statfs.f_fsid.val[0] = statfs->f_fsid.val[0];
  257         linux_statfs.f_fsid.val[1] = statfs->f_fsid.val[1];
  258         linux_statfs.f_namelen = namelen;
  259 
  260         error = copyout(&linux_statfs, buf, sizeof(linux_statfs));
  261         return (error);
  262 }
  263 
  264 /*
  265  * MPALMOSTSAFE
  266  */
  267 int
  268 sys_linux_statfs(struct linux_statfs_args *args)
  269 {
  270         struct statfs statfs;
  271         struct nlookupdata nd;
  272         char *path;
  273         int error, namelen;
  274 
  275         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
  276         if (error)
  277                 return (error);
  278 #ifdef DEBUG
  279         if (ldebug(statfs))
  280                 kprintf(ARGS(statfs, "%s, *"), path);
  281 #endif
  282         get_mplock();
  283         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
  284         if (error == 0)
  285                 error = kern_statfs(&nd, &statfs);
  286         if (error == 0) {
  287                 if (nd.nl_nch.ncp->nc_vp != NULL)
  288                         error = vn_get_namelen(nd.nl_nch.ncp->nc_vp, &namelen);
  289                 else
  290                         error = EINVAL;
  291         }
  292         nlookup_done(&nd);
  293         rel_mplock();
  294         if (error == 0)
  295                 error = statfs_copyout(&statfs, args->buf, (l_int)namelen);
  296         linux_free_path(&path);
  297         return (error);
  298 }
  299 
  300 /*
  301  * MPALMOSTSAFE
  302  */
  303 int
  304 sys_linux_fstatfs(struct linux_fstatfs_args *args)
  305 {
  306         struct proc *p = curthread->td_proc;
  307         struct file *fp;
  308         struct statfs statfs;
  309         int error, namelen;
  310 
  311 #ifdef DEBUG
  312         if (ldebug(fstatfs))
  313                 kprintf(ARGS(fstatfs, "%d, *"), args->fd);
  314 #endif
  315         get_mplock();
  316         if ((error = kern_fstatfs(args->fd, &statfs)) != 0)
  317                 return (error);
  318         if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0)
  319                 return (error);
  320         error = vn_get_namelen((struct vnode *)fp->f_data, &namelen);
  321         rel_mplock();
  322         fdrop(fp);
  323         if (error == 0)
  324                 error = statfs_copyout(&statfs, args->buf, (l_int)namelen);
  325         return (error);
  326 }
  327 
  328 struct l_ustat 
  329 {
  330         l_daddr_t       f_tfree;
  331         l_ino_t         f_tinode;
  332         char            f_fname[6];
  333         char            f_fpack[6];
  334 };
  335 
  336 /*
  337  * MPALMOSTSAFE
  338  */
  339 int
  340 sys_linux_ustat(struct linux_ustat_args *args)
  341 {
  342         struct thread *td = curthread;
  343         struct l_ustat lu;
  344         cdev_t dev;
  345         struct vnode *vp;
  346         struct statfs *stat;
  347         int error;
  348 
  349 #ifdef DEBUG
  350         if (ldebug(ustat))
  351                 kprintf(ARGS(ustat, "%d, *"), args->dev);
  352 #endif
  353 
  354         /*
  355          * lu.f_fname and lu.f_fpack are not used. They are always zeroed.
  356          * lu.f_tinode and lu.f_tfree are set from the device's super block.
  357          */
  358         bzero(&lu, sizeof(lu));
  359 
  360         /*
  361          * XXX - Don't return an error if we can't find a vnode for the
  362          * device. Our cdev_t is 32-bits whereas Linux only has a 16-bits
  363          * cdev_t. The dev_t that is used now may as well be a truncated
  364          * cdev_t returned from previous syscalls. Just return a bzeroed
  365          * ustat in that case.
  366          */
  367         get_mplock();
  368         dev = udev2dev(makeudev(args->dev >> 8, args->dev & 0xFF), 0);
  369         if (dev != NULL && vfinddev(dev, VCHR, &vp)) {
  370                 if (vp->v_mount == NULL) {
  371                         vrele(vp);
  372                         error = EINVAL;
  373                         goto done;
  374                 }
  375                 stat = &(vp->v_mount->mnt_stat);
  376                 error = VFS_STATFS(vp->v_mount, stat, td->td_ucred);
  377                 vrele(vp);
  378                 if (error == 0) {
  379                         lu.f_tfree = stat->f_bfree;
  380                         lu.f_tinode = stat->f_ffree;
  381                 }
  382         } else {
  383                 error = 0;
  384         }
  385 done:
  386         rel_mplock();
  387         if (error == 0)
  388                 error = copyout(&lu, args->ubuf, sizeof(lu));
  389         return (error);
  390 }
  391 
  392 #if defined(__i386__)
  393 
  394 static int
  395 stat64_copyout(struct stat *buf, void *ubuf)
  396 {
  397         struct l_stat64 lbuf;
  398         int error;
  399 
  400         bzero(&lbuf, sizeof(lbuf));
  401         lbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
  402         lbuf.st_ino = INO64TO32(buf->st_ino);
  403         lbuf.st_mode = buf->st_mode;
  404         lbuf.st_nlink = buf->st_nlink;
  405         lbuf.st_uid = buf->st_uid;
  406         lbuf.st_gid = buf->st_gid;
  407         lbuf.st_rdev = buf->st_rdev;
  408         lbuf.st_size = buf->st_size;
  409         lbuf.st_atime = buf->st_atime;
  410         lbuf.st_mtime = buf->st_mtime;
  411         lbuf.st_ctime = buf->st_ctime;
  412         lbuf.st_blksize = buf->st_blksize;
  413         lbuf.st_blocks = buf->st_blocks;
  414 
  415         /*
  416          * The __st_ino field makes all the difference. In the Linux kernel
  417          * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
  418          * but without the assignment to __st_ino the runtime linker refuses
  419          * to mmap(2) any shared libraries. I guess it's broken alright :-)
  420          */
  421         lbuf.__st_ino = INO64TO32(buf->st_ino);
  422 
  423         error = copyout(&lbuf, ubuf, sizeof(lbuf));
  424         return (error);
  425 }
  426 
  427 /*
  428  * MPALMOSTSAFE
  429  */
  430 int
  431 sys_linux_stat64(struct linux_stat64_args *args)
  432 {
  433         struct nlookupdata nd;
  434         struct stat buf;
  435         char *path;
  436         int error;
  437 
  438         error = linux_copyin_path(args->filename, &path, LINUX_PATH_EXISTS);
  439         if (error)
  440                 return (error);
  441 #ifdef DEBUG
  442         if (ldebug(stat64))
  443                 kprintf(ARGS(stat64, "%s, *"), path);
  444 #endif
  445         get_mplock();
  446         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
  447         if (error == 0) {
  448                 error = kern_stat(&nd, &buf);
  449                 nlookup_done(&nd);
  450         }
  451         rel_mplock();
  452         if (error == 0)
  453                 error = stat64_copyout(&buf, args->statbuf);
  454         linux_free_path(&path);
  455         return (error);
  456 }
  457 
  458 /*
  459  * MPALMOSTSAFE
  460  */
  461 int
  462 sys_linux_lstat64(struct linux_lstat64_args *args)
  463 {
  464         struct nlookupdata nd;
  465         struct stat sb;
  466         char *path;
  467         int error;
  468 
  469         error = linux_copyin_path(args->filename, &path, LINUX_PATH_EXISTS);
  470         if (error)
  471                 return (error);
  472 #ifdef DEBUG
  473         if (ldebug(lstat64))
  474                 kprintf(ARGS(lstat64, "%s, *"), path);
  475 #endif
  476         get_mplock();
  477         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
  478         if (error == 0) {
  479                 error = kern_stat(&nd, &sb);
  480                 nlookup_done(&nd);
  481         }
  482         rel_mplock();
  483         if (error == 0)
  484                 error = stat64_copyout(&sb, args->statbuf);
  485         linux_free_path(&path);
  486         return (error);
  487 }
  488 
  489 /*
  490  * MPALMOSTSAFE
  491  */
  492 int
  493 sys_linux_fstat64(struct linux_fstat64_args *args)
  494 {
  495         struct stat buf;
  496         int error;
  497 
  498 #ifdef DEBUG
  499         if (ldebug(fstat64))
  500                 kprintf(ARGS(fstat64, "%d, *"), args->fd);
  501 #endif
  502         get_mplock();
  503         error = kern_fstat(args->fd, &buf);
  504         rel_mplock();
  505 
  506         if (error == 0)
  507                 error = stat64_copyout(&buf, args->statbuf);
  508         return (error);
  509 }
  510 
  511 int
  512 sys_linux_fstatat64(struct linux_fstatat64_args *args)
  513 {
  514         struct nlookupdata nd;
  515         struct file *fp;
  516         struct stat st;
  517         char *path;
  518         int error, flags, dfd;
  519 
  520         if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
  521                 return (EINVAL);
  522 
  523         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
  524         if (error)
  525                 return (error);
  526 #ifdef DEBUG
  527         if (ldebug(fstatat64))
  528                 kprintf(ARGS(fstatat64, "%s"), path);
  529 #endif
  530         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
  531         flags = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
  532 
  533         error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, flags);
  534         if (error == 0) {
  535                 error = kern_stat(&nd, &st);
  536                 if (error == 0)
  537                         error = stat64_copyout(&st, args->statbuf);
  538         }
  539         nlookup_done_at(&nd, fp);
  540         linux_free_path(&path);
  541         return (error);
  542 }
  543 
  544 int
  545 sys_linux_ostat(struct linux_ostat_args *args)
  546 {
  547         struct nlookupdata nd;
  548         struct stat buf;
  549         char *path;
  550         int error;
  551 
  552         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
  553         if (error)
  554                 return (error);
  555 #ifdef DEBUG
  556         if (ldebug(ostat))
  557                 kprintf(ARGS(ostat, "%s, *"), path);
  558 #endif
  559         get_mplock();
  560         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
  561         if (error == 0) {
  562                 error = kern_stat(&nd, &buf);
  563                 nlookup_done(&nd);
  564         }
  565         rel_mplock();
  566         if (error == 0)
  567                 error = ostat_copyout(&buf, args->statbuf);
  568         linux_free_path(&path);
  569         return (error);
  570 }
  571 
  572 #endif /* __i386__ */

Cache object: bf37910748f9878e83b3c65d6a86642c


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