home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / vfs_vnops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-29  |  9.6 KB  |  431 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
  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.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)vfs_vnops.c    7.33 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "kernel.h"
  39. #include "file.h"
  40. #include "stat.h"
  41. #include "buf.h"
  42. #include "proc.h"
  43. #include "mount.h"
  44. #include "namei.h"
  45. #include "vnode.h"
  46. #include "ioctl.h"
  47. #include "tty.h"
  48.  
  49. struct     fileops vnops =
  50.     { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile };
  51.  
  52. /*
  53.  * Common code for vnode open operations.
  54.  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
  55.  */
  56. vn_open(ndp, p, fmode, cmode)
  57.     register struct nameidata *ndp;
  58.     struct proc *p;
  59.     int fmode, cmode;
  60. {
  61.     register struct vnode *vp;
  62.     register struct ucred *cred = p->p_ucred;
  63.     struct vattr vat;
  64.     struct vattr *vap = &vat;
  65.     int error;
  66.  
  67.     if (fmode & O_CREAT) {
  68.         ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF;
  69.         if ((fmode & O_EXCL) == 0)
  70.             ndp->ni_nameiop |= FOLLOW;
  71.         if (error = namei(ndp, p))
  72.             return (error);
  73.         if (ndp->ni_vp == NULL) {
  74.             VATTR_NULL(vap);
  75.             vap->va_type = VREG;
  76.             vap->va_mode = cmode;
  77.             if (error = VOP_CREATE(ndp, vap, p))
  78.                 return (error);
  79.             fmode &= ~O_TRUNC;
  80.             vp = ndp->ni_vp;
  81.         } else {
  82.             VOP_ABORTOP(ndp);
  83.             if (ndp->ni_dvp == ndp->ni_vp)
  84.                 vrele(ndp->ni_dvp);
  85.             else
  86.                 vput(ndp->ni_dvp);
  87.             ndp->ni_dvp = NULL;
  88.             vp = ndp->ni_vp;
  89.             if (fmode & O_EXCL) {
  90.                 error = EEXIST;
  91.                 goto bad;
  92.             }
  93.             fmode &= ~O_CREAT;
  94.         }
  95.     } else {
  96.         ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
  97.         if (error = namei(ndp, p))
  98.             return (error);
  99.         vp = ndp->ni_vp;
  100.     }
  101.     if (vp->v_type == VSOCK) {
  102.         error = EOPNOTSUPP;
  103.         goto bad;
  104.     }
  105.     if ((fmode & O_CREAT) == 0) {
  106.         if (fmode & FREAD) {
  107.             if (error = VOP_ACCESS(vp, VREAD, cred, p))
  108.                 goto bad;
  109.         }
  110.         if (fmode & (FWRITE | O_TRUNC)) {
  111.             if (vp->v_type == VDIR) {
  112.                 error = EISDIR;
  113.                 goto bad;
  114.             }
  115.             if ((error = vn_writechk(vp)) ||
  116.                 (error = VOP_ACCESS(vp, VWRITE, cred, p)))
  117.                 goto bad;
  118.         }
  119.     }
  120.     if (fmode & O_TRUNC) {
  121.         VATTR_NULL(vap);
  122.         vap->va_size = 0;
  123.         if (error = VOP_SETATTR(vp, vap, cred, p))
  124.             goto bad;
  125.     }
  126.     if (error = VOP_OPEN(vp, fmode, cred, p))
  127.         goto bad;
  128.     if (fmode & FWRITE)
  129.         vp->v_writecount++;
  130.     return (0);
  131. bad:
  132.     vput(vp);
  133.     return (error);
  134. }
  135.  
  136. /*
  137.  * Check for write permissions on the specified vnode.
  138.  * The read-only status of the file system is checked.
  139.  * Also, prototype text segments cannot be written.
  140.  */
  141. vn_writechk(vp)
  142.     register struct vnode *vp;
  143. {
  144.  
  145.     /*
  146.      * Disallow write attempts on read-only file systems;
  147.      * unless the file is a socket or a block or character
  148.      * device resident on the file system.
  149.      */
  150.     if (vp->v_mount->mnt_flag & MNT_RDONLY) {
  151.         switch (vp->v_type) {
  152.         case VREG: case VDIR: case VLNK:
  153.             return (EROFS);
  154.         }
  155.     }
  156.     /*
  157.      * If there's shared text associated with
  158.      * the vnode, try to free it up once.  If
  159.      * we fail, we can't allow writing.
  160.      */
  161.     if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
  162.         return (ETXTBSY);
  163.     return (0);
  164. }
  165.  
  166. /*
  167.  * Vnode close call
  168.  */
  169. vn_close(vp, flags, cred, p)
  170.     register struct vnode *vp;
  171.     int flags;
  172.     struct ucred *cred;
  173.     struct proc *p;
  174. {
  175.     int error;
  176.  
  177.     if (flags & FWRITE)
  178.         vp->v_writecount--;
  179.     error = VOP_CLOSE(vp, flags, cred, p);
  180.     vrele(vp);
  181.     return (error);
  182. }
  183.  
  184. /*
  185.  * Package up an I/O request on a vnode into a uio and do it.
  186.  */
  187. vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
  188.     enum uio_rw rw;
  189.     struct vnode *vp;
  190.     caddr_t base;
  191.     int len;
  192.     off_t offset;
  193.     enum uio_seg segflg;
  194.     int ioflg;
  195.     struct ucred *cred;
  196.     int *aresid;
  197.     struct proc *p;
  198. {
  199.     struct uio auio;
  200.     struct iovec aiov;
  201.     int error;
  202.  
  203.     if ((ioflg & IO_NODELOCKED) == 0)
  204.         VOP_LOCK(vp);
  205.     auio.uio_iov = &aiov;
  206.     auio.uio_iovcnt = 1;
  207.     aiov.iov_base = base;
  208.     aiov.iov_len = len;
  209.     auio.uio_resid = len;
  210.     auio.uio_offset = offset;
  211.     auio.uio_segflg = segflg;
  212.     auio.uio_rw = rw;
  213.     auio.uio_procp = p;
  214.     if (rw == UIO_READ)
  215.         error = VOP_READ(vp, &auio, ioflg, cred);
  216.     else
  217.         error = VOP_WRITE(vp, &auio, ioflg, cred);
  218.     if (aresid)
  219.         *aresid = auio.uio_resid;
  220.     else
  221.         if (auio.uio_resid && error == 0)
  222.             error = EIO;
  223.     if ((ioflg & IO_NODELOCKED) == 0)
  224.         VOP_UNLOCK(vp);
  225.     return (error);
  226. }
  227.  
  228. /*
  229.  * File table vnode read routine.
  230.  */
  231. vn_read(fp, uio, cred)
  232.     struct file *fp;
  233.     struct uio *uio;
  234.     struct ucred *cred;
  235. {
  236.     register struct vnode *vp = (struct vnode *)fp->f_data;
  237.     int count, error;
  238.  
  239.     VOP_LOCK(vp);
  240.     uio->uio_offset = fp->f_offset;
  241.     count = uio->uio_resid;
  242.     error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
  243.         cred);
  244.     fp->f_offset += count - uio->uio_resid;
  245.     VOP_UNLOCK(vp);
  246.     return (error);
  247. }
  248.  
  249. /*
  250.  * File table vnode write routine.
  251.  */
  252. vn_write(fp, uio, cred)
  253.     struct file *fp;
  254.     struct uio *uio;
  255.     struct ucred *cred;
  256. {
  257.     register struct vnode *vp = (struct vnode *)fp->f_data;
  258.     int count, error, ioflag = 0;
  259.  
  260.     if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
  261.         ioflag |= IO_APPEND;
  262.     if (fp->f_flag & FNONBLOCK)
  263.         ioflag |= IO_NDELAY;
  264.     VOP_LOCK(vp);
  265.     uio->uio_offset = fp->f_offset;
  266.     count = uio->uio_resid;
  267.     error = VOP_WRITE(vp, uio, ioflag, cred);
  268.     if (ioflag & IO_APPEND)
  269.         fp->f_offset = uio->uio_offset;
  270.     else
  271.         fp->f_offset += count - uio->uio_resid;
  272.     VOP_UNLOCK(vp);
  273.     return (error);
  274. }
  275.  
  276. /*
  277.  * File table vnode stat routine.
  278.  */
  279. vn_stat(vp, sb, p)
  280.     struct vnode *vp;
  281.     register struct stat *sb;
  282.     struct proc *p;
  283. {
  284.     struct vattr vattr;
  285.     register struct vattr *vap;
  286.     int error;
  287.     u_short mode;
  288.  
  289.     vap = &vattr;
  290.     error = VOP_GETATTR(vp, vap, p->p_ucred, p);
  291.     if (error)
  292.         return (error);
  293.     /*
  294.      * Copy from vattr table
  295.      */
  296.     sb->st_dev = vap->va_fsid;
  297.     sb->st_ino = vap->va_fileid;
  298.     mode = vap->va_mode;
  299.     switch (vp->v_type) {
  300.     case VREG:
  301.         mode |= S_IFREG;
  302.         break;
  303.     case VDIR:
  304.         mode |= S_IFDIR;
  305.         break;
  306.     case VBLK:
  307.         mode |= S_IFBLK;
  308.         break;
  309.     case VCHR:
  310.         mode |= S_IFCHR;
  311.         break;
  312.     case VLNK:
  313.         mode |= S_IFLNK;
  314.         break;
  315.     case VSOCK:
  316.         mode |= S_IFSOCK;
  317.         break;
  318.     case VFIFO:
  319.         mode |= S_IFIFO;
  320.         break;
  321.     default:
  322.         return (EBADF);
  323.     };
  324.     sb->st_mode = mode;
  325.     sb->st_nlink = vap->va_nlink;
  326.     sb->st_uid = vap->va_uid;
  327.     sb->st_gid = vap->va_gid;
  328.     sb->st_rdev = vap->va_rdev;
  329.     sb->st_size = vap->va_size;
  330.     sb->st_atime = vap->va_atime.tv_sec;
  331.     sb->st_spare1 = 0;
  332.     sb->st_mtime = vap->va_mtime.tv_sec;
  333.     sb->st_spare2 = 0;
  334.     sb->st_ctime = vap->va_ctime.tv_sec;
  335.     sb->st_spare3 = 0;
  336.     sb->st_blksize = vap->va_blocksize;
  337.     sb->st_flags = vap->va_flags;
  338.     sb->st_gen = vap->va_gen;
  339.     sb->st_blocks = vap->va_bytes / S_BLKSIZE;
  340.     return (0);
  341. }
  342.  
  343. /*
  344.  * File table vnode ioctl routine.
  345.  */
  346. vn_ioctl(fp, com, data, p)
  347.     struct file *fp;
  348.     int com;
  349.     caddr_t data;
  350.     struct proc *p;
  351. {
  352.     register struct vnode *vp = ((struct vnode *)fp->f_data);
  353.     struct vattr vattr;
  354.     int error;
  355.  
  356.     switch (vp->v_type) {
  357.  
  358.     case VREG:
  359.     case VDIR:
  360.         if (com == FIONREAD) {
  361.             if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
  362.                 return (error);
  363.             *(off_t *)data = vattr.va_size - fp->f_offset;
  364.             return (0);
  365.         }
  366.         if (com == FIONBIO || com == FIOASYNC)    /* XXX */
  367.             return (0);            /* XXX */
  368.         /* fall into ... */
  369.  
  370.     default:
  371.         return (ENOTTY);
  372.  
  373.     case VFIFO:
  374.     case VCHR:
  375.     case VBLK:
  376.         error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
  377.         if (error == 0 && com == TIOCSCTTY) {
  378.             p->p_session->s_ttyvp = vp;
  379.             VREF(vp);
  380.         }
  381.         return (error);
  382.     }
  383. }
  384.  
  385. /*
  386.  * File table vnode select routine.
  387.  */
  388. vn_select(fp, which, p)
  389.     struct file *fp;
  390.     int which;
  391.     struct proc *p;
  392. {
  393.  
  394.     return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
  395.         fp->f_cred, p));
  396. }
  397.  
  398. /*
  399.  * File table vnode close routine.
  400.  */
  401. vn_closefile(fp, p)
  402.     struct file *fp;
  403.     struct proc *p;
  404. {
  405.  
  406.     return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
  407.         fp->f_cred, p));
  408. }
  409.  
  410. /*
  411.  * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
  412.  *     - look up fsid in mount list (if not found ret error)
  413.  *    - get vp by calling VFS_FHTOVP() macro
  414.  *    - if lockflag lock it with VOP_LOCK()
  415.  */
  416. vn_fhtovp(fhp, lockflag, vpp)
  417.     fhandle_t *fhp;
  418.     int lockflag;
  419.     struct vnode **vpp;
  420. {
  421.     register struct mount *mp;
  422.  
  423.     if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
  424.         return (ESTALE);
  425.     if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
  426.         return (ESTALE);
  427.     if (!lockflag)
  428.         VOP_UNLOCK(*vpp);
  429.     return (0);
  430. }
  431.