mpcc ports hang with TS_BUSY; bug report 4.3BSD-tahoe/sys/23
[unix-history] / usr / src / sys / kern / vfs_vnops.c
index 19077a0..1e92578 100644 (file)
-/*     vfs_vnops.c     4.13    81/10/11        */
-
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/filsys.h"
-#include "../h/file.h"
-#include "../h/conf.h"
-#include "../h/inode.h"
-#include "../h/reg.h"
-#include "../h/acct.h"
-#include "../h/mount.h"
-
-/*
- * Convert a user supplied
- * file descriptor into a pointer
- * to a file structure.
- * Only task is to check range
- * of the descriptor.
- */
-struct file *
-getf(f)
-register int f;
-{
-       register struct file *fp;
-
-       if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
-               u.u_error = EBADF;
-               return (NULL);
-       }
-       return (fp);
-}
-
 /*
 /*
- * Internal form of close.
- * Decrement reference count on
- * file structure.
- * Also make sure the pipe protocol
- * does not constipate.
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
  *
  *
- * Decrement reference count on the inode following
- * removal to the referencing file structure.
- * Call device handler on last close.
+ *     @(#)vfs_vnops.c 7.1 (Berkeley) %G%
  */
  */
-closef(fp)
-register struct file *fp;
-{
-       register struct inode *ip;
-       register struct mount *mp;
-       int flag, mode;
-       dev_t dev;
-       register int (*cfunc)();
 
 
-       if(fp == NULL)
-               return;
-       if (fp->f_count > 1) {
-               fp->f_count--;
-               return;
-       }
-       flag = fp->f_flag;
-#ifdef BBNNET
-       if (flag&FNET) {
-               netclose(fp);
-               return;
-       }
-#endif
-       if (flag & FPORT) {
-               ptclose(fp);
-               fp->f_count = 0;
-               return;
-       }
-       ip = fp->f_inode;
-       dev = (dev_t)ip->i_un.i_rdev;
-       mode = ip->i_mode & IFMT;
-       plock(ip);
-       iput(ip);
-       fp->f_count = 0;
-
-       switch (mode) {
-
-       case IFCHR:
-               cfunc = cdevsw[major(dev)].d_close;
-               break;
-
-       case IFBLK:
-               /*
-                * We don't want to really close the device if it is mounted
-                */
-               for (mp = mount; mp < &mount[NMOUNT]; mp++)
-                       if (mp->m_bufp != NULL && mp->m_dev == dev)
-                               return;
-               cfunc = bdevsw[major(dev)].d_close;
-               break;
-       default:
-               return;
-       }
-
-       for(fp=file; fp < fileNFILE; fp++) {
-#ifdef BBNNET
-                       if (fp->f_flag & FNET)
-                               continue;
-#endif
-               if (fp->f_count && (ip = fp->f_inode) &&
-                   ip->i_un.i_rdev == dev &&
-                   (ip->i_mode&IFMT) == mode)
-                       return;
-       }
-       if (mode == IFBLK) {
-               /*
-                * on last close of a block device (that isn't mounted)
-                * we must invalidate any in core blocks
-                */
-               bflush(dev);
-               binval(dev);
-       }
-       (*cfunc)(dev, flag, fp);
-}
-
-/*
- * openi called to allow handler
- * of special files to initialize and
- * validate before actual IO.
- */
-openi(ip, rw)
-register struct inode *ip;
-{
-       dev_t dev;
-       register unsigned int maj;
-
-       dev = (dev_t)ip->i_un.i_rdev;
-       maj = major(dev);
-       switch(ip->i_mode&IFMT) {
-
-       case IFCHR:
-               if(maj >= nchrdev)
-                       goto bad;
-               (*cdevsw[maj].d_open)(dev, rw);
-               break;
-
-       case IFBLK:
-               if(maj >= nblkdev)
-                       goto bad;
-               (*bdevsw[maj].d_open)(dev, rw);
-       }
-       return;
-
-bad:
-       u.u_error = ENXIO;
-}
+#include "../machine/reg.h"
+
+#include "param.h"
+#include "systm.h"
+#include "dir.h"
+#include "user.h"
+#include "fs.h"
+#include "file.h"
+#include "conf.h"
+#include "inode.h"
+#include "acct.h"
+#include "mount.h"
+#include "socket.h"
+#include "socketvar.h"
+#include "proc.h"
 
 /*
  * Check mode permission on inode pointer.
 
 /*
  * Check mode permission on inode pointer.
@@ -163,35 +36,68 @@ bad:
  * permissions.
  */
 access(ip, mode)
  * permissions.
  */
 access(ip, mode)
-register struct inode *ip;
+       register struct inode *ip;
+       int mode;
 {
        register m;
 {
        register m;
+       register gid_t *gp;
 
        m = mode;
 
        m = mode;
-       if(m == IWRITE) {
-               if(getfs(ip->i_dev)->s_ronly != 0) {
-                       u.u_error = EROFS;
-                       return(1);
+       if (m == IWRITE) {
+               /*
+                * Disallow write attempts on read-only
+                * file systems; unless the file is a block
+                * or character device resident on the
+                * file system.
+                */
+               if (ip->i_fs->fs_ronly != 0) {
+                       if ((ip->i_mode & IFMT) != IFCHR &&
+                           (ip->i_mode & IFMT) != IFBLK) {
+                               u.u_error = EROFS;
+                               return (1);
+                       }
                }
                }
-               if (ip->i_flag&ITEXT)           /* try to free text */
+               /*
+                * If there's shared text associated with
+                * the inode, try to free it up once.  If
+                * we fail, we can't allow writing.
+                */
+               if (ip->i_flag&ITEXT)
                        xrele(ip);
                        xrele(ip);
-               if(ip->i_flag & ITEXT) {
+               if (ip->i_flag & ITEXT) {
                        u.u_error = ETXTBSY;
                        u.u_error = ETXTBSY;
-                       return(1);
+                       return (1);
                }
        }
                }
        }
-       if(u.u_uid == 0)
-               return(0);
-       if(u.u_uid != ip->i_uid) {
+       /*
+        * If you're the super-user,
+        * you always get access.
+        */
+       if (u.u_uid == 0)
+               return (0);
+       /*
+        * Access check is based on only
+        * one of owner, group, public.
+        * If not owner, then check group.
+        * If not a member of the group, then
+        * check public access.
+        */
+       if (u.u_uid != ip->i_uid) {
                m >>= 3;
                m >>= 3;
-               if(u.u_gid != ip->i_gid)
-                       m >>= 3;
+               if (u.u_gid == ip->i_gid)
+                       goto found;
+               gp = u.u_groups;
+               for (; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
+                       if (ip->i_gid == *gp)
+                               goto found;
+               m >>= 3;
+found:
+               ;
        }
        }
-       if((ip->i_mode&m) != 0)
-               return(0);
-
+       if ((ip->i_mode&m) != 0)
+               return (0);
        u.u_error = EACCES;
        u.u_error = EACCES;
-       return(1);
+       return (1);
 }
 
 /*
 }
 
 /*
@@ -203,19 +109,25 @@ register struct inode *ip;
  * return inode pointer.
  */
 struct inode *
  * return inode pointer.
  */
 struct inode *
-owner()
+owner(fname, follow)
+       caddr_t fname;
+       int follow;
 {
        register struct inode *ip;
 {
        register struct inode *ip;
+       register struct nameidata *ndp = &u.u_nd;
 
 
-       ip = namei(uchar, 0);
-       if(ip == NULL)
-               return(NULL);
-       if(u.u_uid == ip->i_uid)
-               return(ip);
-       if(suser())
-               return(ip);
+       ndp->ni_nameiop = LOOKUP | follow;
+       ndp->ni_segflg = UIO_USERSPACE;
+       ndp->ni_dirp = fname;
+       ip = namei(ndp);
+       if (ip == NULL)
+               return (NULL);
+       if (u.u_uid == ip->i_uid)
+               return (ip);
+       if (suser())
+               return (ip);
        iput(ip);
        iput(ip);
-       return(NULL);
+       return (NULL);
 }
 
 /*
 }
 
 /*
@@ -225,63 +137,10 @@ owner()
 suser()
 {
 
 suser()
 {
 
-       if(u.u_uid == 0) {
+       if (u.u_uid == 0) {
                u.u_acflag |= ASU;
                u.u_acflag |= ASU;
-               return(1);
+               return (1);
        }
        u.u_error = EPERM;
        }
        u.u_error = EPERM;
-       return(0);
-}
-
-/*
- * Allocate a user file descriptor.
- */
-ufalloc()
-{
-       register i;
-
-       for(i=0; i<NOFILE; i++)
-               if(u.u_ofile[i] == NULL) {
-                       u.u_r.r_val1 = i;
-                       u.u_pofile[i] = 0;
-                       return(i);
-               }
-       u.u_error = EMFILE;
-       return(-1);
-}
-
-struct file *lastf;
-/*
- * Allocate a user file descriptor
- * and a file structure.
- * Initialize the descriptor
- * to point at the file structure.
- */
-struct file *
-falloc()
-{
-       register struct file *fp;
-       register i;
-
-       i = ufalloc();
-       if (i < 0)
-               return(NULL);
-       if (lastf == 0)
-               lastf = file;
-       for (fp = lastf; fp < fileNFILE; fp++)
-               if (fp->f_count == 0)
-                       goto slot;
-       for (fp = file; fp < lastf; fp++)
-               if (fp->f_count == 0)
-                       goto slot;
-       tablefull("file");
-       u.u_error = ENFILE;
-       return (NULL);
-slot:
-       u.u_ofile[i] = fp;
-       fp->f_count++;
-       fp->f_un.f_offset = 0;
-       fp->f_inode = 0;
-       lastf = fp + 1;
-       return (fp);
+       return (0);
 }
 }