LCOV - code coverage report
Current view: top level - kern - vfs_vnops.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 1 310 0.3 %
Date: 2018-10-19 03:25:38 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: vfs_vnops.c,v 1.97 2018/08/20 16:00:22 mpi Exp $      */
       2             : /*      $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $  */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1982, 1986, 1989, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  * (c) UNIX System Laboratories, Inc.
       8             :  * All or some portions of this file are derived from material licensed
       9             :  * to the University of California by American Telephone and Telegraph
      10             :  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
      11             :  * the permission of UNIX System Laboratories, Inc.
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  * 1. Redistributions of source code must retain the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer.
      18             :  * 2. Redistributions in binary form must reproduce the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer in the
      20             :  *    documentation and/or other materials provided with the distribution.
      21             :  * 3. Neither the name of the University nor the names of its contributors
      22             :  *    may be used to endorse or promote products derived from this software
      23             :  *    without specific prior written permission.
      24             :  *
      25             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35             :  * SUCH DAMAGE.
      36             :  *
      37             :  *      @(#)vfs_vnops.c 8.5 (Berkeley) 12/8/94
      38             :  */
      39             : 
      40             : #include <sys/param.h>
      41             : #include <sys/systm.h>
      42             : #include <sys/kernel.h>
      43             : #include <sys/malloc.h>
      44             : #include <sys/fcntl.h>
      45             : #include <sys/file.h>
      46             : #include <sys/stat.h>
      47             : #include <sys/proc.h>
      48             : #include <sys/resourcevar.h>
      49             : #include <sys/signalvar.h>
      50             : #include <sys/mount.h>
      51             : #include <sys/namei.h>
      52             : #include <sys/lock.h>
      53             : #include <sys/vnode.h>
      54             : #include <sys/ioctl.h>
      55             : #include <sys/tty.h>
      56             : #include <sys/cdio.h>
      57             : #include <sys/poll.h>
      58             : #include <sys/filedesc.h>
      59             : #include <sys/specdev.h>
      60             : #include <sys/unistd.h>
      61             : 
      62             : int vn_read(struct file *, struct uio *, int);
      63             : int vn_write(struct file *, struct uio *, int);
      64             : int vn_poll(struct file *, int, struct proc *);
      65             : int vn_kqfilter(struct file *, struct knote *);
      66             : int vn_closefile(struct file *, struct proc *);
      67             : int vn_seek(struct file *, off_t *, int, struct proc *);
      68             : 
      69             : struct  fileops vnops = {
      70             :         .fo_read        = vn_read,
      71             :         .fo_write       = vn_write,
      72             :         .fo_ioctl       = vn_ioctl,
      73             :         .fo_poll        = vn_poll,
      74             :         .fo_kqfilter    = vn_kqfilter,
      75             :         .fo_stat        = vn_statfile,
      76             :         .fo_close       = vn_closefile,
      77             :         .fo_seek        = vn_seek,
      78             : };
      79             : 
      80             : /*
      81             :  * Common code for vnode open operations.
      82             :  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
      83             :  */
      84             : int
      85           0 : vn_open(struct nameidata *ndp, int fmode, int cmode)
      86             : {
      87             :         struct vnode *vp;
      88           0 :         struct proc *p = ndp->ni_cnd.cn_proc;
      89           0 :         struct ucred *cred = p->p_ucred;
      90           0 :         struct vattr va;
      91             :         struct cloneinfo *cip;
      92             :         int error;
      93             : 
      94           0 :         if ((fmode & (FREAD|FWRITE)) == 0)
      95           0 :                 return (EINVAL);
      96           0 :         if ((fmode & (O_TRUNC | FWRITE)) == O_TRUNC)
      97           0 :                 return (EINVAL);
      98           0 :         if (fmode & O_CREAT) {
      99           0 :                 ndp->ni_cnd.cn_nameiop = CREATE;
     100           0 :                 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
     101           0 :                 if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
     102           0 :                         ndp->ni_cnd.cn_flags |= FOLLOW;
     103           0 :                 if ((error = namei(ndp)) != 0)
     104           0 :                         return (error);
     105             : 
     106           0 :                 if (ndp->ni_vp == NULL) {
     107           0 :                         VATTR_NULL(&va);
     108           0 :                         va.va_type = VREG;
     109           0 :                         va.va_mode = cmode;
     110           0 :                         if (fmode & O_EXCL)
     111           0 :                                 va.va_vaflags |= VA_EXCLUSIVE;
     112           0 :                         error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
     113             :                                            &ndp->ni_cnd, &va);
     114           0 :                         vput(ndp->ni_dvp);
     115           0 :                         if (error)
     116           0 :                                 return (error);
     117           0 :                         fmode &= ~O_TRUNC;
     118           0 :                         vp = ndp->ni_vp;
     119           0 :                 } else {
     120           0 :                         VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
     121           0 :                         if (ndp->ni_dvp == ndp->ni_vp)
     122           0 :                                 vrele(ndp->ni_dvp);
     123             :                         else
     124           0 :                                 vput(ndp->ni_dvp);
     125           0 :                         ndp->ni_dvp = NULL;
     126           0 :                         vp = ndp->ni_vp;
     127           0 :                         if (fmode & O_EXCL) {
     128             :                                 error = EEXIST;
     129           0 :                                 goto bad;
     130             :                         }
     131           0 :                         fmode &= ~O_CREAT;
     132             :                 }
     133             :         } else {
     134           0 :                 ndp->ni_cnd.cn_nameiop = LOOKUP;
     135           0 :                 ndp->ni_cnd.cn_flags =
     136           0 :                     ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF;
     137           0 :                 if ((error = namei(ndp)) != 0)
     138           0 :                         return (error);
     139           0 :                 vp = ndp->ni_vp;
     140             :         }
     141           0 :         if (vp->v_type == VSOCK) {
     142             :                 error = EOPNOTSUPP;
     143           0 :                 goto bad;
     144             :         }
     145           0 :         if (vp->v_type == VLNK) {
     146             :                 error = ELOOP;
     147           0 :                 goto bad;
     148             :         }
     149           0 :         if ((fmode & O_DIRECTORY) && vp->v_type != VDIR) {
     150             :                 error = ENOTDIR;
     151           0 :                 goto bad;
     152             :         }
     153           0 :         if ((fmode & O_CREAT) == 0) {
     154           0 :                 if (fmode & FREAD) {
     155           0 :                         if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
     156             :                                 goto bad;
     157             :                 }
     158           0 :                 if (fmode & FWRITE) {
     159           0 :                         if (vp->v_type == VDIR) {
     160             :                                 error = EISDIR;
     161           0 :                                 goto bad;
     162             :                         }
     163           0 :                         if ((error = vn_writechk(vp)) != 0 ||
     164           0 :                             (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
     165             :                                 goto bad;
     166             :                 }
     167             :         }
     168           0 :         if ((fmode & O_TRUNC) && vp->v_type == VREG) {
     169           0 :                 VATTR_NULL(&va);
     170           0 :                 va.va_size = 0;
     171           0 :                 if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
     172             :                         goto bad;
     173             :         }
     174           0 :         if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0)
     175             :                 goto bad;
     176             : 
     177           0 :         if (vp->v_flag & VCLONED) {
     178           0 :                 cip = (struct cloneinfo *)vp->v_data;
     179             : 
     180           0 :                 vp->v_flag &= ~VCLONED;
     181             : 
     182           0 :                 ndp->ni_vp = cip->ci_vp;  /* return cloned vnode */
     183           0 :                 vp->v_data = cip->ci_data;        /* restore v_data */
     184           0 :                 VOP_UNLOCK(vp);                 /* keep a reference */
     185           0 :                 vp = ndp->ni_vp;             /* for the increment below */
     186             : 
     187           0 :                 free(cip, M_TEMP, sizeof(*cip));
     188           0 :         }
     189             : 
     190           0 :         if (fmode & FWRITE)
     191           0 :                 vp->v_writecount++;
     192           0 :         return (0);
     193             : bad:
     194           0 :         vput(vp);
     195           0 :         return (error);
     196           0 : }
     197             : 
     198             : /*
     199             :  * Check for write permissions on the specified vnode.
     200             :  * Prototype text segments cannot be written.
     201             :  */
     202             : int
     203           0 : vn_writechk(struct vnode *vp)
     204             : {
     205             :         /*
     206             :          * Disallow write attempts on read-only file systems;
     207             :          * unless the file is a socket or a block or character
     208             :          * device resident on the file system.
     209             :          */
     210           0 :         if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
     211           0 :                 switch (vp->v_type) {
     212             :                 case VREG:
     213             :                 case VDIR:
     214             :                 case VLNK:
     215           0 :                         return (EROFS);
     216             :                 case VNON:
     217             :                 case VCHR:
     218             :                 case VSOCK:
     219             :                 case VFIFO:
     220             :                 case VBAD:
     221             :                 case VBLK:
     222             :                         break;
     223             :                 }
     224             :         }
     225             :         /*
     226             :          * If there's shared text associated with
     227             :          * the vnode, try to free it up once.  If
     228             :          * we fail, we can't allow writing.
     229             :          */
     230           0 :         if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp))
     231           0 :                 return (ETXTBSY);
     232             : 
     233           0 :         return (0);
     234           0 : }
     235             : 
     236             : /*
     237             :  * Check whether a write operation would exceed the file size rlimit
     238             :  * for the process, if one should be applied for this operation.
     239             :  * If a partial write should take place, the uio is adjusted and the
     240             :  * amount by which the request would have exceeded the limit is returned
     241             :  * via the 'overrun' argument.
     242             :  */
     243             : int
     244           0 : vn_fsizechk(struct vnode *vp, struct uio *uio, int ioflag, ssize_t *overrun)
     245             : {
     246           0 :         struct proc *p = uio->uio_procp;
     247             : 
     248           0 :         *overrun = 0;
     249           0 :         if (vp->v_type == VREG && p != NULL && !(ioflag & IO_NOLIMIT)) {
     250           0 :                 rlim_t limit = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
     251             : 
     252             :                 /* if already at or over the limit, send the signal and fail */
     253           0 :                 if (uio->uio_offset >= limit) {
     254           0 :                         psignal(p, SIGXFSZ);
     255           0 :                         return (EFBIG);
     256             :                 }
     257             : 
     258             :                 /* otherwise, clamp the write to stay under the limit */
     259           0 :                 if (uio->uio_resid > limit - uio->uio_offset) {
     260           0 :                         *overrun = uio->uio_resid - (limit - uio->uio_offset);
     261           0 :                         uio->uio_resid = limit - uio->uio_offset;
     262           0 :                 }
     263           0 :         }
     264             : 
     265           0 :         return (0);
     266           0 : }
     267             : 
     268             : 
     269             : /*
     270             :  * Mark a vnode as being the text image of a running process.
     271             :  */
     272             : void
     273           0 : vn_marktext(struct vnode *vp)
     274             : {
     275           0 :         vp->v_flag |= VTEXT;
     276           0 : }
     277             : 
     278             : /*
     279             :  * Vnode close call
     280             :  */
     281             : int
     282           0 : vn_close(struct vnode *vp, int flags, struct ucred *cred, struct proc *p)
     283             : {
     284             :         int error;
     285             : 
     286           0 :         if (flags & FWRITE)
     287           0 :                 vp->v_writecount--;
     288           0 :         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     289           0 :         error = VOP_CLOSE(vp, flags, cred, p);
     290           0 :         vput(vp);
     291           0 :         return (error);
     292             : }
     293             : 
     294             : /*
     295             :  * Package up an I/O request on a vnode into a uio and do it.
     296             :  */
     297             : int
     298           0 : vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset,
     299             :     enum uio_seg segflg, int ioflg, struct ucred *cred, size_t *aresid,
     300             :     struct proc *p)
     301             : {
     302           0 :         struct uio auio;
     303           0 :         struct iovec aiov;
     304             :         int error;
     305             : 
     306           0 :         auio.uio_iov = &aiov;
     307           0 :         auio.uio_iovcnt = 1;
     308           0 :         aiov.iov_base = base;
     309           0 :         aiov.iov_len = len;
     310           0 :         auio.uio_resid = len;
     311           0 :         auio.uio_offset = offset;
     312           0 :         auio.uio_segflg = segflg;
     313           0 :         auio.uio_rw = rw;
     314           0 :         auio.uio_procp = p;
     315             : 
     316           0 :         if ((ioflg & IO_NODELOCKED) == 0)
     317           0 :                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     318           0 :         if (rw == UIO_READ) {
     319           0 :                 error = VOP_READ(vp, &auio, ioflg, cred);
     320           0 :         } else {
     321           0 :                 error = VOP_WRITE(vp, &auio, ioflg, cred);
     322             :         }
     323           0 :         if ((ioflg & IO_NODELOCKED) == 0)
     324           0 :                 VOP_UNLOCK(vp);
     325             : 
     326           0 :         if (aresid)
     327           0 :                 *aresid = auio.uio_resid;
     328             :         else
     329           0 :                 if (auio.uio_resid && error == 0)
     330           0 :                         error = EIO;
     331           0 :         return (error);
     332           0 : }
     333             : 
     334             : /*
     335             :  * File table vnode read routine.
     336             :  */
     337             : int
     338           0 : vn_read(struct file *fp, struct uio *uio, int fflags)
     339             : {
     340           0 :         struct vnode *vp = fp->f_data;
     341           0 :         struct ucred *cred = fp->f_cred;
     342           0 :         size_t count = uio->uio_resid;
     343             :         off_t offset;
     344             :         int error;
     345             : 
     346             :         /*
     347             :          * Check below can race.  We can block on the vnode lock
     348             :          * and resume with a different `fp->f_offset' value.
     349             :          */
     350           0 :         if ((fflags & FO_POSITION) == 0)
     351           0 :                 offset = fp->f_offset;
     352             :         else
     353           0 :                 offset = uio->uio_offset;
     354             : 
     355             :         /* no wrap around of offsets except on character devices */
     356           0 :         if (vp->v_type != VCHR && count > LLONG_MAX - offset)
     357           0 :                 return (EINVAL);
     358             : 
     359           0 :         if (vp->v_type == VDIR)
     360           0 :                 return (EISDIR);
     361             : 
     362           0 :         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     363           0 :         if ((fflags & FO_POSITION) == 0)
     364           0 :                 uio->uio_offset = fp->f_offset;
     365           0 :         error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
     366             :             cred);
     367           0 :         if ((fflags & FO_POSITION) == 0)
     368           0 :                 fp->f_offset += count - uio->uio_resid;
     369           0 :         VOP_UNLOCK(vp);
     370           0 :         return (error);
     371           0 : }
     372             : 
     373             : /*
     374             :  * File table vnode write routine.
     375             :  */
     376             : int
     377           0 : vn_write(struct file *fp, struct uio *uio, int fflags)
     378             : {
     379           0 :         struct vnode *vp = fp->f_data;
     380           0 :         struct ucred *cred = fp->f_cred;
     381             :         int error, ioflag = IO_UNIT;
     382             :         size_t count;
     383             : 
     384             :         /* note: pwrite/pwritev are unaffected by O_APPEND */
     385           0 :         if (vp->v_type == VREG && (fp->f_flag & O_APPEND) &&
     386           0 :             (fflags & FO_POSITION) == 0)
     387           0 :                 ioflag |= IO_APPEND;
     388           0 :         if (fp->f_flag & FNONBLOCK)
     389           0 :                 ioflag |= IO_NDELAY;
     390           0 :         if ((fp->f_flag & FFSYNC) ||
     391           0 :             (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
     392           0 :                 ioflag |= IO_SYNC;
     393           0 :         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     394           0 :         if ((fflags & FO_POSITION) == 0)
     395           0 :                 uio->uio_offset = fp->f_offset;
     396           0 :         count = uio->uio_resid;
     397           0 :         error = VOP_WRITE(vp, uio, ioflag, cred);
     398           0 :         if ((fflags & FO_POSITION) == 0) {
     399           0 :                 if (ioflag & IO_APPEND)
     400           0 :                         fp->f_offset = uio->uio_offset;
     401             :                 else
     402           0 :                         fp->f_offset += count - uio->uio_resid;
     403             :         }
     404           0 :         VOP_UNLOCK(vp);
     405           0 :         return (error);
     406             : }
     407             : 
     408             : /*
     409             :  * File table wrapper for vn_stat
     410             :  */
     411             : int
     412           0 : vn_statfile(struct file *fp, struct stat *sb, struct proc *p)
     413             : {
     414           0 :         struct vnode *vp = fp->f_data;
     415           0 :         return vn_stat(vp, sb, p);
     416             : }
     417             : 
     418             : /*
     419             :  * vnode stat routine.
     420             :  */
     421             : int
     422           0 : vn_stat(struct vnode *vp, struct stat *sb, struct proc *p)
     423             : {
     424           0 :         struct vattr va;
     425             :         int error;
     426             :         mode_t mode;
     427             : 
     428           0 :         error = VOP_GETATTR(vp, &va, p->p_ucred, p);
     429           0 :         if (error)
     430           0 :                 return (error);
     431             :         /*
     432             :          * Copy from vattr table
     433             :          */
     434           0 :         memset(sb, 0, sizeof(*sb));
     435           0 :         sb->st_dev = va.va_fsid;
     436           0 :         sb->st_ino = va.va_fileid;
     437           0 :         mode = va.va_mode;
     438           0 :         switch (vp->v_type) {
     439             :         case VREG:
     440           0 :                 mode |= S_IFREG;
     441           0 :                 break;
     442             :         case VDIR:
     443           0 :                 mode |= S_IFDIR;
     444           0 :                 break;
     445             :         case VBLK:
     446           0 :                 mode |= S_IFBLK;
     447           0 :                 break;
     448             :         case VCHR:
     449           0 :                 mode |= S_IFCHR;
     450           0 :                 break;
     451             :         case VLNK:
     452           0 :                 mode |= S_IFLNK;
     453           0 :                 break;
     454             :         case VSOCK:
     455           0 :                 mode |= S_IFSOCK;
     456           0 :                 break;
     457             :         case VFIFO:
     458           0 :                 mode |= S_IFIFO;
     459           0 :                 break;
     460             :         default:
     461           0 :                 return (EBADF);
     462             :         }
     463           0 :         sb->st_mode = mode;
     464           0 :         sb->st_nlink = va.va_nlink;
     465           0 :         sb->st_uid = va.va_uid;
     466           0 :         sb->st_gid = va.va_gid;
     467           0 :         sb->st_rdev = va.va_rdev;
     468           0 :         sb->st_size = va.va_size;
     469           0 :         sb->st_atim.tv_sec  = va.va_atime.tv_sec;
     470           0 :         sb->st_atim.tv_nsec = va.va_atime.tv_nsec;
     471           0 :         sb->st_mtim.tv_sec  = va.va_mtime.tv_sec;
     472           0 :         sb->st_mtim.tv_nsec = va.va_mtime.tv_nsec;
     473           0 :         sb->st_ctim.tv_sec  = va.va_ctime.tv_sec;
     474           0 :         sb->st_ctim.tv_nsec = va.va_ctime.tv_nsec;
     475           0 :         sb->st_blksize = va.va_blocksize;
     476           0 :         sb->st_flags = va.va_flags;
     477           0 :         sb->st_gen = va.va_gen;
     478           0 :         sb->st_blocks = va.va_bytes / S_BLKSIZE;
     479           0 :         return (0);
     480           0 : }
     481             : 
     482             : /*
     483             :  * File table vnode ioctl routine.
     484             :  */
     485             : int
     486           0 : vn_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
     487             : {
     488           0 :         struct vnode *vp = fp->f_data;
     489           0 :         struct vattr vattr;
     490             :         int error;
     491             : 
     492           0 :         switch (vp->v_type) {
     493             : 
     494             :         case VREG:
     495             :         case VDIR:
     496           0 :                 if (com == FIONREAD) {
     497           0 :                         error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
     498           0 :                         if (error)
     499           0 :                                 return (error);
     500           0 :                         *(int *)data = vattr.va_size - fp->f_offset;
     501           0 :                         return (0);
     502             :                 }
     503           0 :                 if (com == FIONBIO || com == FIOASYNC)  /* XXX */
     504           0 :                         return (0);                     /* XXX */
     505             :                 /* FALLTHROUGH */
     506             :         default:
     507           0 :                 return (ENOTTY);
     508             : 
     509             :         case VFIFO:
     510             :         case VCHR:
     511             :         case VBLK:
     512           0 :                 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
     513          60 :                 if (error == 0 && com == TIOCSCTTY) {
     514           0 :                         struct session *s = p->p_p->ps_session;
     515           0 :                         struct vnode *ovp = s->s_ttyvp;
     516           0 :                         s->s_ttyvp = vp;
     517           0 :                         vref(vp);
     518           0 :                         if (ovp)
     519           0 :                                 vrele(ovp);
     520           0 :                 }
     521           0 :                 return (error);
     522             :         }
     523           0 : }
     524             : 
     525             : /*
     526             :  * File table vnode poll routine.
     527             :  */
     528             : int
     529           0 : vn_poll(struct file *fp, int events, struct proc *p)
     530             : {
     531           0 :         return (VOP_POLL(fp->f_data, fp->f_flag, events, p));
     532             : }
     533             : 
     534             : /*
     535             :  * Check that the vnode is still valid, and if so
     536             :  * acquire requested lock.
     537             :  */
     538             : int
     539           0 : vn_lock(struct vnode *vp, int flags)
     540             : {
     541             :         int error;
     542             : 
     543           0 :         do {
     544           0 :                 if (vp->v_flag & VXLOCK) {
     545           0 :                         vp->v_flag |= VXWANT;
     546           0 :                         tsleep(vp, PINOD, "vn_lock", 0);
     547             :                         error = ENOENT;
     548           0 :                 } else {
     549           0 :                         error = VOP_LOCK(vp, flags);
     550           0 :                         if (error == 0)
     551           0 :                                 return (error);
     552             :                 }
     553           0 :         } while (flags & LK_RETRY);
     554           0 :         return (error);
     555           0 : }
     556             : 
     557             : /*
     558             :  * File table vnode close routine.
     559             :  */
     560             : int
     561           0 : vn_closefile(struct file *fp, struct proc *p)
     562             : {
     563           0 :         struct vnode *vp = fp->f_data;
     564           0 :         struct flock lf;
     565             :         int error;
     566             : 
     567           0 :         KERNEL_LOCK();
     568           0 :         if ((fp->f_iflags & FIF_HASLOCK)) {
     569           0 :                 lf.l_whence = SEEK_SET;
     570           0 :                 lf.l_start = 0;
     571           0 :                 lf.l_len = 0;
     572           0 :                 lf.l_type = F_UNLCK;
     573           0 :                 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
     574           0 :         }
     575           0 :         error = vn_close(vp, fp->f_flag, fp->f_cred, p);
     576           0 :         KERNEL_UNLOCK();
     577           0 :         return (error);
     578           0 : }
     579             : 
     580             : int
     581           0 : vn_kqfilter(struct file *fp, struct knote *kn)
     582             : {
     583           0 :         return (VOP_KQFILTER(fp->f_data, kn));
     584             : }
     585             : 
     586             : int
     587           0 : vn_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
     588             : {
     589           0 :         struct ucred *cred = p->p_ucred;
     590           0 :         struct vnode *vp = fp->f_data;
     591           0 :         struct vattr vattr;
     592             :         off_t newoff;
     593             :         int error, special;
     594             : 
     595           0 :         if (vp->v_type == VFIFO)
     596           0 :                 return (ESPIPE);
     597           0 :         if (vp->v_type == VCHR)
     598           0 :                 special = 1;
     599             :         else
     600             :                 special = 0;
     601             : 
     602           0 :         switch (whence) {
     603             :         case SEEK_CUR:
     604           0 :                 newoff = fp->f_offset + *offset;
     605           0 :                 break;
     606             :         case SEEK_END:
     607           0 :                 error = VOP_GETATTR(vp, &vattr, cred, p);
     608           0 :                 if (error)
     609           0 :                         return (error);
     610           0 :                 newoff = *offset + (off_t)vattr.va_size;
     611           0 :                 break;
     612             :         case SEEK_SET:
     613           0 :                 newoff = *offset;
     614           0 :                 break;
     615             :         default:
     616           0 :                 return (EINVAL);
     617             :         }
     618           0 :         if (!special) {
     619           0 :                 if (newoff < 0)
     620           0 :                         return(EINVAL);
     621             :         }
     622           0 :         fp->f_offset = *offset = newoff;
     623           0 :         return (0);
     624           0 : }
     625             : 
     626             : /*
     627             :  * Common code for vnode access operations.
     628             :  */
     629             : 
     630             : /* Check if a directory can be found inside another in the hierarchy */
     631             : int
     632           0 : vn_isunder(struct vnode *lvp, struct vnode *rvp, struct proc *p)
     633             : {
     634             :         int error;
     635             : 
     636           0 :         error = vfs_getcwd_common(lvp, rvp, NULL, NULL, MAXPATHLEN/2, 0, p);
     637             : 
     638           0 :         if (!error)
     639           0 :                 return (1);
     640             : 
     641           0 :         return (0);
     642           0 : }

Generated by: LCOV version 1.13