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/5.2/sys/compat/linux/linux_stats.c 122153 2003-11-05 23:52:54Z anholt $");
   31 
   32 #include "opt_mac.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/conf.h>
   36 #include <sys/dirent.h>
   37 #include <sys/file.h>
   38 #include <sys/filedesc.h>
   39 #include <sys/proc.h>
   40 #include <sys/mac.h>
   41 #include <sys/malloc.h>
   42 #include <sys/mount.h>
   43 #include <sys/namei.h>
   44 #include <sys/stat.h>
   45 #include <sys/systm.h>
   46 #include <sys/vnode.h>
   47 
   48 #include <machine/../linux/linux.h>
   49 #include <machine/../linux/linux_proto.h>
   50 
   51 #include <compat/linux/linux_util.h>
   52 
   53 static int
   54 newstat_copyout(struct stat *buf, void *ubuf)
   55 {
   56         struct l_newstat tbuf;
   57         struct cdevsw *cdevsw;
   58         dev_t dev;
   59 
   60         bzero(&tbuf, sizeof(tbuf));
   61         tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
   62         tbuf.st_ino = buf->st_ino;
   63         tbuf.st_mode = buf->st_mode;
   64         tbuf.st_nlink = buf->st_nlink;
   65         tbuf.st_uid = buf->st_uid;
   66         tbuf.st_gid = buf->st_gid;
   67         tbuf.st_rdev = buf->st_rdev;
   68         tbuf.st_size = buf->st_size;
   69         tbuf.st_atime = buf->st_atime;
   70         tbuf.st_mtime = buf->st_mtime;
   71         tbuf.st_ctime = buf->st_ctime;
   72         tbuf.st_blksize = buf->st_blksize;
   73         tbuf.st_blocks = buf->st_blocks;
   74 
   75         /* Lie about disk drives which are character devices
   76          * in FreeBSD but block devices under Linux.
   77          */
   78         if (S_ISCHR(tbuf.st_mode) &&
   79             (dev = udev2dev(buf->st_rdev, 0)) != NODEV) {
   80                 cdevsw = devsw(dev);
   81                 if (cdevsw != NULL && (cdevsw->d_flags & D_DISK)) {
   82                         tbuf.st_mode &= ~S_IFMT;
   83                         tbuf.st_mode |= S_IFBLK;
   84 
   85                         /* XXX this may not be quite right */
   86                         /* Map major number to 0 */
   87                         tbuf.st_dev = uminor(buf->st_dev) & 0xf;
   88                         tbuf.st_rdev = buf->st_rdev & 0xff;
   89                 }
   90         }
   91 
   92         return (copyout(&tbuf, ubuf, sizeof(tbuf)));
   93 }
   94 
   95 int
   96 linux_newstat(struct thread *td, struct linux_newstat_args *args)
   97 {
   98         struct stat buf;
   99         struct nameidata nd;
  100         char *path;
  101         int error;
  102 
  103         LCONVPATHEXIST(td, args->path, &path);
  104 
  105 #ifdef DEBUG
  106         if (ldebug(newstat))
  107                 printf(ARGS(newstat, "%s, *"), path);
  108 #endif
  109 
  110         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_SYSSPACE, path, td);
  111         error = namei(&nd);
  112         LFREEPATH(path);
  113         if (error)
  114                 return (error);
  115         NDFREE(&nd, NDF_ONLY_PNBUF);
  116 
  117         error = vn_stat(nd.ni_vp, &buf, td->td_ucred, NOCRED, td);
  118         vput(nd.ni_vp);
  119         if (error)
  120                 return (error);
  121 
  122         return (newstat_copyout(&buf, args->buf));
  123 }
  124 
  125 int
  126 linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
  127 {
  128         int error;
  129         struct stat sb;
  130         struct nameidata nd;
  131         char *path;
  132 
  133         LCONVPATHEXIST(td, args->path, &path);
  134 
  135 #ifdef DEBUG
  136         if (ldebug(newlstat))
  137                 printf(ARGS(newlstat, "%s, *"), path);
  138 #endif
  139 
  140         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_SYSSPACE, path,
  141             td);
  142         error = namei(&nd);
  143         LFREEPATH(path);
  144         if (error)
  145                 return (error);
  146         NDFREE(&nd, NDF_ONLY_PNBUF);
  147 
  148         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
  149         vput(nd.ni_vp);
  150         if (error)
  151                 return (error);
  152 
  153         return (newstat_copyout(&sb, args->buf));
  154 }
  155 
  156 int
  157 linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
  158 {
  159         struct file *fp;
  160         struct stat buf;
  161         int error;
  162 
  163 #ifdef DEBUG
  164         if (ldebug(newfstat))
  165                 printf(ARGS(newfstat, "%d, *"), args->fd);
  166 #endif
  167 
  168         if ((error = fget(td, args->fd, &fp)) != 0)
  169                 return (error);
  170 
  171         error = fo_stat(fp, &buf, td->td_ucred, td);
  172         fdrop(fp, td);
  173         if (!error)
  174                 error = newstat_copyout(&buf, args->buf);
  175 
  176         return (error);
  177 }
  178 
  179 /* XXX - All fields of type l_int are defined as l_long on i386 */
  180 struct l_statfs {
  181         l_int           f_type;
  182         l_int           f_bsize;
  183         l_int           f_blocks;
  184         l_int           f_bfree;
  185         l_int           f_bavail;
  186         l_int           f_files;
  187         l_int           f_ffree;
  188         l_fsid_t        f_fsid;
  189         l_int           f_namelen;
  190         l_int           f_spare[6];
  191 };
  192 
  193 #define LINUX_CODA_SUPER_MAGIC  0x73757245L
  194 #define LINUX_EXT2_SUPER_MAGIC  0xEF53L
  195 #define LINUX_HPFS_SUPER_MAGIC  0xf995e849L
  196 #define LINUX_ISOFS_SUPER_MAGIC 0x9660L
  197 #define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
  198 #define LINUX_NCP_SUPER_MAGIC   0x564cL
  199 #define LINUX_NFS_SUPER_MAGIC   0x6969L
  200 #define LINUX_NTFS_SUPER_MAGIC  0x5346544EL
  201 #define LINUX_PROC_SUPER_MAGIC  0x9fa0L
  202 #define LINUX_UFS_SUPER_MAGIC   0x00011954L     /* XXX - UFS_MAGIC in Linux */
  203 
  204 static long
  205 bsd_to_linux_ftype(const char *fstypename)
  206 {
  207         int i;
  208         static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
  209                 {"ufs",     LINUX_UFS_SUPER_MAGIC},
  210                 {"cd9660",  LINUX_ISOFS_SUPER_MAGIC},
  211                 {"nfs",     LINUX_NFS_SUPER_MAGIC},
  212                 {"ext2fs",  LINUX_EXT2_SUPER_MAGIC},
  213                 {"procfs",  LINUX_PROC_SUPER_MAGIC},
  214                 {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
  215                 {"ntfs",    LINUX_NTFS_SUPER_MAGIC},
  216                 {"nwfs",    LINUX_NCP_SUPER_MAGIC},
  217                 {"hpfs",    LINUX_HPFS_SUPER_MAGIC},
  218                 {"coda",    LINUX_CODA_SUPER_MAGIC},
  219                 {NULL,      0L}};
  220 
  221         for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
  222                 if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
  223                         return (b2l_tbl[i].linux_type);
  224 
  225         return (0L);
  226 }
  227 
  228 int
  229 linux_statfs(struct thread *td, struct linux_statfs_args *args)
  230 {
  231         struct mount *mp;
  232         struct nameidata *ndp;
  233         struct statfs *bsd_statfs;
  234         struct nameidata nd;
  235         struct l_statfs linux_statfs;
  236         char *path;
  237         int error;
  238 
  239         LCONVPATHEXIST(td, args->path, &path);
  240 
  241 #ifdef DEBUG
  242         if (ldebug(statfs))
  243                 printf(ARGS(statfs, "%s, *"), path);
  244 #endif
  245         ndp = &nd;
  246         NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
  247         error = namei(ndp);
  248         LFREEPATH(path);
  249         if (error)
  250                 return error;
  251         NDFREE(ndp, NDF_ONLY_PNBUF);
  252         mp = ndp->ni_vp->v_mount;
  253         bsd_statfs = &mp->mnt_stat;
  254         vrele(ndp->ni_vp);
  255 #ifdef MAC
  256         error = mac_check_mount_stat(td->td_ucred, mp);
  257         if (error)
  258                 return (error);
  259 #endif
  260         error = VFS_STATFS(mp, bsd_statfs, td);
  261         if (error)
  262                 return error;
  263         bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  264         linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
  265         linux_statfs.f_bsize = bsd_statfs->f_bsize;
  266         linux_statfs.f_blocks = bsd_statfs->f_blocks;
  267         linux_statfs.f_bfree = bsd_statfs->f_bfree;
  268         linux_statfs.f_bavail = bsd_statfs->f_bavail;
  269         linux_statfs.f_ffree = bsd_statfs->f_ffree;
  270         linux_statfs.f_files = bsd_statfs->f_files;
  271         if (suser(td)) {
  272                 linux_statfs.f_fsid.val[0] = 0;
  273                 linux_statfs.f_fsid.val[1] = 0;
  274         } else {
  275                 linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
  276                 linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
  277         }
  278         linux_statfs.f_namelen = MAXNAMLEN;
  279         return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
  280 }
  281 
  282 int
  283 linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
  284 {
  285         struct file *fp;
  286         struct mount *mp;
  287         struct statfs *bsd_statfs;
  288         struct l_statfs linux_statfs;
  289         int error;
  290 
  291 #ifdef DEBUG
  292         if (ldebug(fstatfs))
  293                 printf(ARGS(fstatfs, "%d, *"), args->fd);
  294 #endif
  295         error = getvnode(td->td_proc->p_fd, args->fd, &fp);
  296         if (error)
  297                 return error;
  298         mp = fp->f_vnode->v_mount;
  299 #ifdef MAC
  300         error = mac_check_mount_stat(td->td_ucred, mp);
  301         if (error) {
  302                 fdrop(fp, td);
  303                 return (error);
  304         }
  305 #endif
  306         bsd_statfs = &mp->mnt_stat;
  307         error = VFS_STATFS(mp, bsd_statfs, td);
  308         if (error) {
  309                 fdrop(fp, td);
  310                 return error;
  311         }
  312         bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  313         linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
  314         linux_statfs.f_bsize = bsd_statfs->f_bsize;
  315         linux_statfs.f_blocks = bsd_statfs->f_blocks;
  316         linux_statfs.f_bfree = bsd_statfs->f_bfree;
  317         linux_statfs.f_bavail = bsd_statfs->f_bavail;
  318         linux_statfs.f_ffree = bsd_statfs->f_ffree;
  319         linux_statfs.f_files = bsd_statfs->f_files;
  320         if (suser(td)) {
  321                 linux_statfs.f_fsid.val[0] = 0;
  322                 linux_statfs.f_fsid.val[1] = 0;
  323         } else {
  324                 linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
  325                 linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
  326         }
  327         linux_statfs.f_namelen = MAXNAMLEN;
  328         error = copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
  329         fdrop(fp, td);
  330         return error;
  331 }
  332 
  333 struct l_ustat
  334 {
  335         l_daddr_t       f_tfree;
  336         l_ino_t         f_tinode;
  337         char            f_fname[6];
  338         char            f_fpack[6];
  339 };
  340 
  341 int
  342 linux_ustat(struct thread *td, struct linux_ustat_args *args)
  343 {
  344         struct l_ustat lu;
  345         dev_t dev;
  346         struct vnode *vp;
  347         struct statfs *stat;
  348         int error;
  349 
  350 #ifdef DEBUG
  351         if (ldebug(ustat))
  352                 printf(ARGS(ustat, "%d, *"), args->dev);
  353 #endif
  354 
  355         /*
  356          * lu.f_fname and lu.f_fpack are not used. They are always zeroed.
  357          * lu.f_tinode and lu.f_tfree are set from the device's super block.
  358          */
  359         bzero(&lu, sizeof(lu));
  360 
  361         /*
  362          * XXX - Don't return an error if we can't find a vnode for the
  363          * device. Our dev_t is 32-bits whereas Linux only has a 16-bits
  364          * dev_t. The dev_t that is used now may as well be a truncated
  365          * dev_t returned from previous syscalls. Just return a bzeroed
  366          * ustat in that case.
  367          */
  368         dev = makedev(args->dev >> 8, args->dev & 0xFF);
  369         if (vfinddev(dev, VCHR, &vp)) {
  370                 if (vp->v_mount == NULL)
  371                         return (EINVAL);
  372 #ifdef MAC
  373                 error = mac_check_mount_stat(td->td_ucred, vp->v_mount);
  374                 if (error)
  375                         return (error);
  376 #endif
  377                 stat = &(vp->v_mount->mnt_stat);
  378                 error = VFS_STATFS(vp->v_mount, stat, td);
  379                 if (error)
  380                         return (error);
  381 
  382                 lu.f_tfree = stat->f_bfree;
  383                 lu.f_tinode = stat->f_ffree;
  384         }
  385 
  386         return (copyout(&lu, args->ubuf, sizeof(lu)));
  387 }
  388 
  389 #if defined(__i386__)
  390 
  391 static int
  392 stat64_copyout(struct stat *buf, void *ubuf)
  393 {
  394         struct l_stat64 lbuf;
  395         struct cdevsw *cdevsw;
  396         dev_t dev;
  397 
  398         bzero(&lbuf, sizeof(lbuf));
  399         lbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
  400         lbuf.st_ino = buf->st_ino;
  401         lbuf.st_mode = buf->st_mode;
  402         lbuf.st_nlink = buf->st_nlink;
  403         lbuf.st_uid = buf->st_uid;
  404         lbuf.st_gid = buf->st_gid;
  405         lbuf.st_rdev = buf->st_rdev;
  406         lbuf.st_size = buf->st_size;
  407         lbuf.st_atime = buf->st_atime;
  408         lbuf.st_mtime = buf->st_mtime;
  409         lbuf.st_ctime = buf->st_ctime;
  410         lbuf.st_blksize = buf->st_blksize;
  411         lbuf.st_blocks = buf->st_blocks;
  412 
  413         /* Lie about disk drives which are character devices
  414          * in FreeBSD but block devices under Linux.
  415          */
  416         if (S_ISCHR(lbuf.st_mode) &&
  417             (dev = udev2dev(buf->st_rdev, 0)) != NODEV) {
  418                 cdevsw = devsw(dev);
  419                 if (cdevsw != NULL && (cdevsw->d_flags & D_DISK)) {
  420                         lbuf.st_mode &= ~S_IFMT;
  421                         lbuf.st_mode |= S_IFBLK;
  422 
  423                         /* XXX this may not be quite right */
  424                         /* Map major number to 0 */
  425                         lbuf.st_dev = uminor(buf->st_dev) & 0xf;
  426                         lbuf.st_rdev = buf->st_rdev & 0xff;
  427                 }
  428         }
  429 
  430         /*
  431          * The __st_ino field makes all the difference. In the Linux kernel
  432          * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
  433          * but without the assignment to __st_ino the runtime linker refuses
  434          * to mmap(2) any shared libraries. I guess it's broken alright :-)
  435          */
  436         lbuf.__st_ino = buf->st_ino;
  437 
  438         return (copyout(&lbuf, ubuf, sizeof(lbuf)));
  439 }
  440 
  441 int
  442 linux_stat64(struct thread *td, struct linux_stat64_args *args)
  443 {
  444         struct stat buf;
  445         struct nameidata nd;
  446         int error;
  447         char *filename;
  448 
  449         LCONVPATHEXIST(td, args->filename, &filename);
  450 
  451 #ifdef DEBUG
  452         if (ldebug(stat64))
  453                 printf(ARGS(stat64, "%s, *"), filename);
  454 #endif
  455 
  456         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_SYSSPACE, filename,
  457             td);
  458         error = namei(&nd);
  459         LFREEPATH(filename);
  460         if (error)
  461                 return (error);
  462         NDFREE(&nd, NDF_ONLY_PNBUF);
  463 
  464         error = vn_stat(nd.ni_vp, &buf, td->td_ucred, NOCRED, td);
  465         vput(nd.ni_vp);
  466         if (error)
  467                 return (error);
  468 
  469         return (stat64_copyout(&buf, args->statbuf));
  470 }
  471 
  472 int
  473 linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
  474 {
  475         int error;
  476         struct stat sb;
  477         struct nameidata nd;
  478         char *filename;
  479 
  480         LCONVPATHEXIST(td, args->filename, &filename);
  481 
  482 #ifdef DEBUG
  483         if (ldebug(lstat64))
  484                 printf(ARGS(lstat64, "%s, *"), args->filename);
  485 #endif
  486 
  487         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_SYSSPACE, filename,
  488             td);
  489         error = namei(&nd);
  490         LFREEPATH(filename);
  491         if (error)
  492                 return (error);
  493         NDFREE(&nd, NDF_ONLY_PNBUF);
  494 
  495         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
  496         vput(nd.ni_vp);
  497         if (error)
  498                 return (error);
  499 
  500         return (stat64_copyout(&sb, args->statbuf));
  501 }
  502 
  503 int
  504 linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
  505 {
  506         struct filedesc *fdp;
  507         struct file *fp;
  508         struct stat buf;
  509         int error;
  510 
  511 #ifdef DEBUG
  512         if (ldebug(fstat64))
  513                 printf(ARGS(fstat64, "%d, *"), args->fd);
  514 #endif
  515 
  516         fdp = td->td_proc->p_fd;
  517         if ((unsigned)args->fd >= fdp->fd_nfiles ||
  518             (fp = fdp->fd_ofiles[args->fd]) == NULL)
  519                 return (EBADF);
  520 
  521         error = fo_stat(fp, &buf, td->td_ucred, td);
  522         if (!error)
  523                 error = stat64_copyout(&buf, args->statbuf);
  524 
  525         return (error);
  526 }
  527 
  528 #endif /* __i386__ */

Cache object: cf6c59bd0a87086de5c26a09ed6d07e7


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