mpcc ports hang with TS_BUSY; bug report 4.3BSD-tahoe/sys/23
[unix-history] / usr / src / sys / kern / vfs_vnops.c
index 3240d68..1e92578 100644 (file)
-/*     vfs_vnops.c     4.17    81/11/18        */
-
-#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"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-
 /*
 /*
- * Convert a user supplied file descriptor into a pointer
- * to a file structure.  Only task is to check range of the descriptor.
- * Critical paths should use the GETF macro, defined in inline.h.
- */
-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;
-       if (flag & FSOCKET) {
-               soclose(fp->f_socket);
-               fp->f_socket = 0;
-               fp->f_count = 0;
-               return;
-       }
-       ip = fp->f_inode;
-       dev = (dev_t)ip->i_un.i_rdev;
-       mode = ip->i_mode & IFMT;
-       ilock(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++) {
-               if (fp->f_flag & FSOCKET)
-                       continue;
-               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.
@@ -159,26 +40,59 @@ access(ip, mode)
        int mode;
 {
        register m;
        int mode;
 {
        register m;
+       register gid_t *gp;
 
        m = mode;
        if (m == IWRITE) {
 
        m = mode;
        if (m == IWRITE) {
-               if (getfs(ip->i_dev)->s_ronly != 0) {
-                       u.u_error = EROFS;
-                       return (1);
+               /*
+                * 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);
                if (ip->i_flag & ITEXT) {
                        u.u_error = ETXTBSY;
                        return (1);
                }
        }
                        xrele(ip);
                if (ip->i_flag & ITEXT) {
                        u.u_error = ETXTBSY;
                        return (1);
                }
        }
+       /*
+        * If you're the super-user,
+        * you always get access.
+        */
        if (u.u_uid == 0)
                return (0);
        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;
        if (u.u_uid != ip->i_uid) {
                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);
@@ -195,11 +109,17 @@ access(ip, mode)
  * 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);
+       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)
        if (ip == NULL)
                return (NULL);
        if (u.u_uid == ip->i_uid)
@@ -224,56 +144,3 @@ suser()
        u.u_error = EPERM;
        return (0);
 }
        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_offset = 0;
-       fp->f_inode = 0;
-       lastf = fp + 1;
-       return (fp);
-}