ignore bogus (large) return values from read
[unix-history] / usr / src / sys / kern / vfs_vnops.c
index 8dba099..0e4a8d0 100644 (file)
@@ -1,4 +1,6 @@
-/*     vfs_vnops.c     4.28    82/10/17        */
+/*     vfs_vnops.c     4.33    83/02/20        */
+
+#include "../machine/reg.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/file.h"
 #include "../h/conf.h"
 #include "../h/inode.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"
 #include "../h/proc.h"
 #include "../h/acct.h"
 #include "../h/mount.h"
 #include "../h/socket.h"
 #include "../h/socketvar.h"
 #include "../h/proc.h"
+#include "../h/nami.h"
 
 /*
  * Openi called to allow handler
 
 /*
  * Openi called to allow handler
@@ -63,23 +65,50 @@ access(ip, mode)
 
        m = mode;
        if (m == IWRITE) {
 
        m = mode;
        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_fs->fs_ronly != 0) {
-                       u.u_error = EROFS;
-                       return (1);
+                       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)
+                       goto found;
                for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
                for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
-                       if (ip->i_gid != *gp)
+                       if (ip->i_gid == *gp)
                                goto found;
                m >>= 3;
 found:
                                goto found;
                m >>= 3;
 found:
@@ -105,7 +134,7 @@ owner(follow)
 {
        register struct inode *ip;
 
 {
        register struct inode *ip;
 
-       ip = namei(uchar, 0, follow);
+       ip = namei(uchar, LOOKUP, follow);
        if (ip == NULL)
                return (NULL);
        if (u.u_uid == ip->i_uid)
        if (ip == NULL)
                return (NULL);
        if (u.u_uid == ip->i_uid)