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/common/vfs_syscalls_43.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 /*      $NetBSD: vfs_syscalls_43.c,v 1.47 2008/06/24 11:18:15 ad Exp $  */
    2 
    3 /*
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)vfs_syscalls.c      8.28 (Berkeley) 12/10/94
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_43.c,v 1.47 2008/06/24 11:18:15 ad Exp $");
   41 
   42 #if defined(_KERNEL_OPT)
   43 #include "fs_union.h"
   44 #endif
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/filedesc.h>
   49 #include <sys/kernel.h>
   50 #include <sys/proc.h>
   51 #include <sys/file.h>
   52 #include <sys/vnode.h>
   53 #include <sys/namei.h>
   54 #include <sys/dirent.h>
   55 #include <sys/socket.h>
   56 #include <sys/socketvar.h>
   57 #include <sys/stat.h>
   58 #include <sys/malloc.h>
   59 #include <sys/ioctl.h>
   60 #include <sys/fcntl.h>
   61 #include <sys/syslog.h>
   62 #include <sys/unistd.h>
   63 #include <sys/resourcevar.h>
   64 #include <sys/sysctl.h>
   65 
   66 #include <sys/mount.h>
   67 #include <sys/syscallargs.h>
   68 #include <sys/vfs_syscalls.h>
   69 
   70 #include <compat/sys/stat.h>
   71 #include <compat/sys/mount.h>
   72 
   73 static void cvtstat(struct stat *, struct stat43 *);
   74 
   75 /*
   76  * Convert from an old to a new stat structure.
   77  */
   78 static void
   79 cvtstat(struct stat *st, struct stat43 *ost)
   80 {
   81 
   82         ost->st_dev = st->st_dev;
   83         ost->st_ino = st->st_ino;
   84         ost->st_mode = st->st_mode & 0xffff;
   85         ost->st_nlink = st->st_nlink;
   86         ost->st_uid = st->st_uid;
   87         ost->st_gid = st->st_gid;
   88         ost->st_rdev = st->st_rdev;
   89         if (st->st_size < (quad_t)1 << 32)
   90                 ost->st_size = st->st_size;
   91         else
   92                 ost->st_size = -2;
   93         ost->st_atime = st->st_atime;
   94         ost->st_mtime = st->st_mtime;
   95         ost->st_ctime = st->st_ctime;
   96         ost->st_blksize = st->st_blksize;
   97         ost->st_blocks = st->st_blocks;
   98         ost->st_flags = st->st_flags;
   99         ost->st_gen = st->st_gen;
  100 }
  101 
  102 /*
  103  * Get file status; this version follows links.
  104  */
  105 /* ARGSUSED */
  106 int
  107 compat_43_sys_stat(struct lwp *l, const struct compat_43_sys_stat_args *uap, register_t *retval)
  108 {
  109         /* {
  110                 syscallarg(char *) path;
  111                 syscallarg(struct stat43 *) ub;
  112         } */
  113         struct stat sb;
  114         struct stat43 osb;
  115         int error;
  116 
  117         error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
  118         if (error)
  119                 return (error);
  120         cvtstat(&sb, &osb);
  121         error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
  122         return (error);
  123 }
  124 
  125 /*
  126  * Get file status; this version does not follow links.
  127  */
  128 /* ARGSUSED */
  129 int
  130 compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval)
  131 {
  132         /* {
  133                 syscallarg(char *) path;
  134                 syscallarg(struct ostat *) ub;
  135         } */
  136         struct vnode *vp, *dvp;
  137         struct stat sb, sb1;
  138         struct stat43 osb;
  139         int error;
  140         struct nameidata nd;
  141         int ndflags;
  142 
  143         ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT | TRYEMULROOT;
  144 again:
  145         NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, SCARG(uap, path));
  146         if ((error = namei(&nd))) {
  147                 if (error == EISDIR && (ndflags & LOCKPARENT) != 0) {
  148                         /*
  149                          * Should only happen on '/'. Retry without LOCKPARENT;
  150                          * this is safe since the vnode won't be a VLNK.
  151                          */
  152                         ndflags &= ~LOCKPARENT;
  153                         goto again;
  154                 }
  155                 return (error);
  156         }
  157         /*
  158          * For symbolic links, always return the attributes of its
  159          * containing directory, except for mode, size, and links.
  160          */
  161         vp = nd.ni_vp;
  162         dvp = nd.ni_dvp;
  163         if (vp->v_type != VLNK) {
  164                 if ((ndflags & LOCKPARENT) != 0) {
  165                         if (dvp == vp)
  166                                 vrele(dvp);
  167                         else
  168                                 vput(dvp);
  169                 }
  170                 error = vn_stat(vp, &sb);
  171                 vput(vp);
  172                 if (error)
  173                         return (error);
  174         } else {
  175                 error = vn_stat(dvp, &sb);
  176                 vput(dvp);
  177                 if (error) {
  178                         vput(vp);
  179                         return (error);
  180                 }
  181                 error = vn_stat(vp, &sb1);
  182                 vput(vp);
  183                 if (error)
  184                         return (error);
  185                 sb.st_mode &= ~S_IFDIR;
  186                 sb.st_mode |= S_IFLNK;
  187                 sb.st_nlink = sb1.st_nlink;
  188                 sb.st_size = sb1.st_size;
  189                 sb.st_blocks = sb1.st_blocks;
  190         }
  191         cvtstat(&sb, &osb);
  192         error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
  193         return (error);
  194 }
  195 
  196 /*
  197  * Return status information about a file descriptor.
  198  */
  199 /* ARGSUSED */
  200 int
  201 compat_43_sys_fstat(struct lwp *l, const struct compat_43_sys_fstat_args *uap, register_t *retval)
  202 {
  203         /* {
  204                 syscallarg(int) fd;
  205                 syscallarg(struct stat43 *) sb;
  206         } */
  207         int fd = SCARG(uap, fd);
  208         struct file *fp;
  209         struct stat ub;
  210         struct stat43 oub;
  211         int error;
  212 
  213         if ((fp = fd_getfile(fd)) == NULL)
  214                 return (EBADF);
  215         error = (*fp->f_ops->fo_stat)(fp, &ub);
  216         fd_putfile(fd);
  217         if (error == 0) {
  218                 cvtstat(&ub, &oub);
  219                 error = copyout((void *)&oub, (void *)SCARG(uap, sb),
  220                     sizeof (oub));
  221         }
  222 
  223 
  224         return (error);
  225 }
  226 
  227 
  228 /*
  229  * Truncate a file given a file descriptor.
  230  */
  231 /* ARGSUSED */
  232 int
  233 compat_43_sys_ftruncate(struct lwp *l, const struct compat_43_sys_ftruncate_args *uap, register_t *retval)
  234 {
  235         /* {
  236                 syscallarg(int) fd;
  237                 syscallarg(long) length;
  238         } */
  239         struct sys_ftruncate_args /* {
  240                 syscallarg(int) fd;
  241                 syscallarg(int) pad;
  242                 syscallarg(off_t) length;
  243         } */ nuap;
  244 
  245         SCARG(&nuap, fd) = SCARG(uap, fd);
  246         SCARG(&nuap, length) = SCARG(uap, length);
  247         return (sys_ftruncate(l, &nuap, retval));
  248 }
  249 
  250 /*
  251  * Truncate a file given its path name.
  252  */
  253 /* ARGSUSED */
  254 int
  255 compat_43_sys_truncate(struct lwp *l, const struct compat_43_sys_truncate_args *uap, register_t *retval)
  256 {
  257         /* {
  258                 syscallarg(char *) path;
  259                 syscallarg(long) length;
  260         } */
  261         struct sys_truncate_args /* {
  262                 syscallarg(char *) path;
  263                 syscallarg(int) pad;
  264                 syscallarg(off_t) length;
  265         } */ nuap;
  266 
  267         SCARG(&nuap, path) = SCARG(uap, path);
  268         SCARG(&nuap, length) = SCARG(uap, length);
  269         return (sys_truncate(l, &nuap, retval));
  270 }
  271 
  272 
  273 /*
  274  * Reposition read/write file offset.
  275  */
  276 int
  277 compat_43_sys_lseek(struct lwp *l, const struct compat_43_sys_lseek_args *uap, register_t *retval)
  278 {
  279         /* {
  280                 syscallarg(int) fd;
  281                 syscallarg(long) offset;
  282                 syscallarg(int) whence;
  283         } */
  284         struct sys_lseek_args /* {
  285                 syscallarg(int) fd;
  286                 syscallarg(int) pad;
  287                 syscallarg(off_t) offset;
  288                 syscallarg(int) whence;
  289         } */ nuap;
  290         off_t qret;
  291         int error;
  292 
  293         SCARG(&nuap, fd) = SCARG(uap, fd);
  294         SCARG(&nuap, offset) = SCARG(uap, offset);
  295         SCARG(&nuap, whence) = SCARG(uap, whence);
  296         error = sys_lseek(l, &nuap, (void *)&qret);
  297         *(long *)retval = qret;
  298         return (error);
  299 }
  300 
  301 
  302 /*
  303  * Create a file.
  304  */
  305 int
  306 compat_43_sys_creat(struct lwp *l, const struct compat_43_sys_creat_args *uap, register_t *retval)
  307 {
  308         /* {
  309                 syscallarg(char *) path;
  310                 syscallarg(int) mode;
  311         } */
  312         struct sys_open_args /* {
  313                 syscallarg(char *) path;
  314                 syscallarg(int) flags;
  315                 syscallarg(int) mode;
  316         } */ nuap;
  317 
  318         SCARG(&nuap, path) = SCARG(uap, path);
  319         SCARG(&nuap, mode) = SCARG(uap, mode);
  320         SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
  321         return (sys_open(l, &nuap, retval));
  322 }
  323 
  324 /*ARGSUSED*/
  325 int
  326 compat_43_sys_quota(struct lwp *l, const void *v, register_t *retval)
  327 {
  328 
  329         return (ENOSYS);
  330 }
  331 
  332 
  333 /*
  334  * Read a block of directory entries in a file system independent format.
  335  */
  336 int
  337 compat_43_sys_getdirentries(struct lwp *l, const struct compat_43_sys_getdirentries_args *uap, register_t *retval)
  338 {
  339         /* {
  340                 syscallarg(int) fd;
  341                 syscallarg(char *) buf;
  342                 syscallarg(u_int) count;
  343                 syscallarg(long *) basep;
  344         } */
  345         struct vnode *vp;
  346         struct file *fp;
  347         struct uio auio, kuio;
  348         struct iovec aiov, kiov;
  349         struct dirent *dp, *edp;
  350         char *dirbuf;
  351         size_t count = min(MAXBSIZE, (size_t)SCARG(uap, count));
  352 
  353         int error, eofflag, readcnt;
  354         long loff;
  355 
  356         /* fd_getvnode() will use the descriptor for us */
  357         if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
  358                 return (error);
  359         if ((fp->f_flag & FREAD) == 0) {
  360                 error = EBADF;
  361                 goto out;
  362         }
  363         vp = (struct vnode *)fp->f_data;
  364 unionread:
  365         if (vp->v_type != VDIR) {
  366                 error = EINVAL;
  367                 goto out;
  368         }
  369         aiov.iov_base = SCARG(uap, buf);
  370         aiov.iov_len = count;
  371         auio.uio_iov = &aiov;
  372         auio.uio_iovcnt = 1;
  373         auio.uio_rw = UIO_READ;
  374         auio.uio_resid = count;
  375         KASSERT(l == curlwp);
  376         auio.uio_vmspace = curproc->p_vmspace;
  377         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  378         loff = auio.uio_offset = fp->f_offset;
  379 #       if (BYTE_ORDER != LITTLE_ENDIAN)
  380                 if ((vp->v_mount->mnt_iflag & IMNT_DTYPE) == 0) {
  381                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
  382                             (off_t **)0, (int *)0);
  383                         fp->f_offset = auio.uio_offset;
  384                 } else
  385 #       endif
  386         {
  387                 kuio = auio;
  388                 kuio.uio_iov = &kiov;
  389                 kiov.iov_len = count;
  390                 dirbuf = malloc(count, M_TEMP, M_WAITOK);
  391                 kiov.iov_base = dirbuf;
  392                 UIO_SETUP_SYSSPACE(&kuio);
  393                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
  394                             (off_t **)0, (int *)0);
  395                 fp->f_offset = kuio.uio_offset;
  396                 if (error == 0) {
  397                         readcnt = count - kuio.uio_resid;
  398                         edp = (struct dirent *)&dirbuf[readcnt];
  399                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
  400 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
  401                                         /*
  402                                          * The expected low byte of
  403                                          * dp->d_namlen is our dp->d_type.
  404                                          * The high MBZ byte of dp->d_namlen
  405                                          * is our dp->d_namlen.
  406                                          */
  407                                         dp->d_type = dp->d_namlen;
  408                                         dp->d_namlen = 0;
  409 #                               else
  410                                         /*
  411                                          * The dp->d_type is the high byte
  412                                          * of the expected dp->d_namlen,
  413                                          * so must be zero'ed.
  414                                          */
  415                                         dp->d_type = 0;
  416 #                               endif
  417                                 if (dp->d_reclen > 0) {
  418                                         dp = (struct dirent *)
  419                                             ((char *)dp + dp->d_reclen);
  420                                 } else {
  421                                         error = EIO;
  422                                         break;
  423                                 }
  424                         }
  425                         if (dp >= edp)
  426                                 error = uiomove(dirbuf, readcnt, &auio);
  427                 }
  428                 free(dirbuf, M_TEMP);
  429         }
  430         VOP_UNLOCK(vp, 0);
  431         if (error)
  432                 goto out;
  433 
  434         if ((count == auio.uio_resid) &&
  435             (vp->v_vflag & VV_ROOT) &&
  436             (vp->v_mount->mnt_flag & MNT_UNION)) {
  437                 struct vnode *tvp = vp;
  438                 vp = vp->v_mount->mnt_vnodecovered;
  439                 VREF(vp);
  440                 fp->f_data = (void *) vp;
  441                 fp->f_offset = 0;
  442                 vrele(tvp);
  443                 goto unionread;
  444         }
  445         error = copyout((void *)&loff, (void *)SCARG(uap, basep),
  446             sizeof(long));
  447         *retval = count - auio.uio_resid;
  448  out:
  449         fd_putfile(SCARG(uap, fd));
  450         return (error);
  451 }
  452 
  453 /*
  454  * sysctl helper routine for vfs.generic.conf lookups.
  455  */
  456 #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_44)
  457 static int
  458 sysctl_vfs_generic_conf(SYSCTLFN_ARGS)
  459 {
  460         struct vfsconf vfc;
  461         extern const char * const mountcompatnames[];
  462         extern int nmountcompatnames;
  463         struct sysctlnode node;
  464         struct vfsops *vfsp;
  465         u_int vfsnum;
  466 
  467         if (namelen != 1)
  468                 return (ENOTDIR);
  469         vfsnum = name[0];
  470         if (vfsnum >= nmountcompatnames ||
  471             mountcompatnames[vfsnum] == NULL)
  472                 return (EOPNOTSUPP);
  473         vfsp = vfs_getopsbyname(mountcompatnames[vfsnum]);
  474         if (vfsp == NULL)
  475                 return (EOPNOTSUPP);
  476 
  477         vfc.vfc_vfsops = vfsp;
  478         strncpy(vfc.vfc_name, vfsp->vfs_name, sizeof(vfc.vfc_name));
  479         vfc.vfc_typenum = vfsnum;
  480         vfc.vfc_refcount = vfsp->vfs_refcount;
  481         vfc.vfc_flags = 0;
  482         vfc.vfc_mountroot = vfsp->vfs_mountroot;
  483         vfc.vfc_next = NULL;
  484         vfs_delref(vfsp);
  485 
  486         node = *rnode;
  487         node.sysctl_data = &vfc;
  488         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  489 }
  490 
  491 /*
  492  * Top level filesystem related information gathering.
  493  */
  494 SYSCTL_SETUP(compat_sysctl_vfs_setup, "compat sysctl vfs subtree setup")
  495 {
  496         extern int nmountcompatnames;
  497 
  498         sysctl_createv(clog, 0, NULL, NULL,
  499                        CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
  500                        CTLTYPE_INT, "maxtypenum",
  501                        SYSCTL_DESCR("Highest valid filesystem type number"),
  502                        NULL, nmountcompatnames, NULL, 0,
  503                        CTL_VFS, VFS_GENERIC, VFS_MAXTYPENUM, CTL_EOL);
  504         sysctl_createv(clog, 0, NULL, NULL,
  505                        CTLFLAG_PERMANENT,
  506                        CTLTYPE_STRUCT, "conf",
  507                        SYSCTL_DESCR("Filesystem configuration information"),
  508                        sysctl_vfs_generic_conf, 0, NULL,
  509                        sizeof(struct vfsconf),
  510                        CTL_VFS, VFS_GENERIC, VFS_CONF, CTL_EOL);
  511 }
  512 #endif

Cache object: 59e0db98d4df40dfa51ccf223a9641f2


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