/dev/fd driver
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
index 42cea13..205d5c2 100644 (file)
@@ -1,9 +1,9 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
+ * 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.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)vfs_syscalls.c      6.21 (Berkeley) %G%
+ *     @(#)vfs_syscalls.c      7.6 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -41,8 +41,9 @@ chdir()
 chroot()
 {
 
 chroot()
 {
 
-       if (suser())
-               chdirec(&u.u_rdir);
+       if (u.u_error = suser(u.u_cred, &u.u_acflag))
+               return;
+       chdirec(&u.u_rdir);
 }
 
 /*
 }
 
 /*
@@ -208,7 +209,7 @@ mknod()
        } *uap = (struct a *)u.u_ap;
        register struct nameidata *ndp = &u.u_nd;
 
        } *uap = (struct a *)u.u_ap;
        register struct nameidata *ndp = &u.u_nd;
 
-       if (!suser())
+       if (u.u_error = suser(u.u_cred, &u.u_acflag))
                return;
        ndp->ni_nameiop = CREATE;
        ndp->ni_segflg = UIO_USERSPACE;
                return;
        ndp->ni_nameiop = CREATE;
        ndp->ni_segflg = UIO_USERSPACE;
@@ -260,7 +261,13 @@ link()
        ip = namei(ndp);        /* well, this routine is doomed anyhow */
        if (ip == NULL)
                return;
        ip = namei(ndp);        /* well, this routine is doomed anyhow */
        if (ip == NULL)
                return;
-       if ((ip->i_mode&IFMT) == IFDIR && !suser()) {
+       if ((ip->i_mode&IFMT) == IFDIR &&
+           (u.u_error = suser(u.u_cred, &u.u_acflag))) {
+               iput(ip);
+               return;
+       }
+       if (ip->i_nlink == LINK_MAX - 1) {
+               u.u_error = EMLINK;
                iput(ip);
                return;
        }
                iput(ip);
                return;
        }
@@ -331,7 +338,8 @@ symlink()
        ip = maknode(IFLNK | 0777, ndp);
        if (ip == NULL)
                return;
        ip = maknode(IFLNK | 0777, ndp);
        if (ip == NULL)
                return;
-       u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0);
+       u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, (off_t)0, 0,
+           (int *)0);
        /* handle u.u_error != 0 */
        iput(ip);
 }
        /* handle u.u_error != 0 */
        iput(ip);
 }
@@ -356,7 +364,8 @@ unlink()
        if (ip == NULL)
                return;
        dp = ndp->ni_pdir;
        if (ip == NULL)
                return;
        dp = ndp->ni_pdir;
-       if ((ip->i_mode&IFMT) == IFDIR && !suser())
+       if ((ip->i_mode&IFMT) == IFDIR &&
+           (u.u_error = suser(u.u_cred, &u.u_acflag)))
                goto out;
        /*
         * Don't unlink a mounted file.
                goto out;
        /*
         * Don't unlink a mounted file.
@@ -516,7 +525,8 @@ readlink()
                u.u_error = EINVAL;
                goto out;
        }
                u.u_error = EINVAL;
                goto out;
        }
-       u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid);
+       u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, (off_t)0, 0,
+           &resid);
 out:
        iput(ip);
        u.u_r.r_val1 = uap->count - resid;
 out:
        iput(ip);
        u.u_r.r_val1 = uap->count - resid;
@@ -555,7 +565,8 @@ fchmod()
        if (fp == NULL)
                return;
        ip = (struct inode *)fp->f_data;
        if (fp == NULL)
                return;
        ip = (struct inode *)fp->f_data;
-       if (u.u_uid != ip->i_uid && !suser())
+       if (u.u_uid != ip->i_uid &&
+           (u.u_error = suser(u.u_cred, &u.u_acflag)))
                return;
        ILOCK(ip);
        u.u_error = chmod1(ip, uap->fmode);
                return;
        ILOCK(ip);
        u.u_error = chmod1(ip, uap->fmode);
@@ -598,8 +609,13 @@ chown()
                int     uid;
                int     gid;
        } *uap = (struct a *)u.u_ap;
                int     uid;
                int     gid;
        } *uap = (struct a *)u.u_ap;
+       register struct nameidata *ndp = &u.u_nd;
 
 
-       if (!suser() || (ip = owner(uap->fname, NOFOLLOW)) == NULL)
+       ndp->ni_nameiop = LOOKUP | NOFOLLOW;
+       ndp->ni_segflg = UIO_USERSPACE;
+       ndp->ni_dirp = uap->fname;
+       ip = namei(ndp);
+       if (ip == NULL)
                return;
        u.u_error = chown1(ip, uap->uid, uap->gid);
        iput(ip);
                return;
        u.u_error = chown1(ip, uap->uid, uap->gid);
        iput(ip);
@@ -622,8 +638,6 @@ fchown()
        if (fp == NULL)
                return;
        ip = (struct inode *)fp->f_data;
        if (fp == NULL)
                return;
        ip = (struct inode *)fp->f_data;
-       if (!suser())
-               return;
        ILOCK(ip);
        u.u_error = chown1(ip, uap->uid, uap->gid);
        IUNLOCK(ip);
        ILOCK(ip);
        u.u_error = chown1(ip, uap->uid, uap->gid);
        IUNLOCK(ip);
@@ -647,6 +661,15 @@ chown1(ip, uid, gid)
                uid = ip->i_uid;
        if (gid == -1)
                gid = ip->i_gid;
                uid = ip->i_uid;
        if (gid == -1)
                gid = ip->i_gid;
+       /*
+        * If we don't own the file, are trying to change the owner
+        * of the file, or are not a member of the target group,
+        * the caller must be superuser or the call fails.
+        */
+       if ((u.u_uid != ip->i_uid || uid != ip->i_uid ||
+           !groupmember((gid_t)gid)) &&
+           (u.u_error = suser(u.u_cred, &u.u_acflag)))
+               return (u.u_error);
 #ifdef QUOTA
        if (ip->i_uid == uid)           /* this just speeds things a little */
                change = 0;
 #ifdef QUOTA
        if (ip->i_uid == uid)           /* this just speeds things a little */
                change = 0;
@@ -664,7 +687,7 @@ chown1(ip, uid, gid)
 #ifdef QUOTA
        ip->i_dquot = inoquota(ip);
        (void) chkdq(ip, change, 1);
 #ifdef QUOTA
        ip->i_dquot = inoquota(ip);
        (void) chkdq(ip, change, 1);
-       (void) chkiq(ip->i_dev, (struct inode *)NULL, uid, 1);
+       (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1);
        return (u.u_error);             /* should == 0 ALWAYS !! */
 #else
        return (0);
        return (u.u_error);             /* should == 0 ALWAYS !! */
 #else
        return (0);
@@ -711,7 +734,7 @@ truncate()
 {
        struct a {
                char    *fname;
 {
        struct a {
                char    *fname;
-               u_long  length;
+               off_t   length;
        } *uap = (struct a *)u.u_ap;
        struct inode *ip;
        register struct nameidata *ndp = &u.u_nd;
        } *uap = (struct a *)u.u_ap;
        struct inode *ip;
        register struct nameidata *ndp = &u.u_nd;
@@ -728,7 +751,7 @@ truncate()
                u.u_error = EISDIR;
                goto bad;
        }
                u.u_error = EISDIR;
                goto bad;
        }
-       itrunc(ip, uap->length);
+       itrunc(ip, (u_long)uap->length);
 bad:
        iput(ip);
 }
 bad:
        iput(ip);
 }
@@ -740,7 +763,7 @@ ftruncate()
 {
        struct a {
                int     fd;
 {
        struct a {
                int     fd;
-               u_long  length;
+               off_t   length;
        } *uap = (struct a *)u.u_ap;
        struct inode *ip;
        struct file *fp;
        } *uap = (struct a *)u.u_ap;
        struct inode *ip;
        struct file *fp;
@@ -754,7 +777,7 @@ ftruncate()
        }
        ip = (struct inode *)fp->f_data;
        ILOCK(ip);
        }
        ip = (struct inode *)fp->f_data;
        ILOCK(ip);
-       itrunc(ip, uap->length);
+       itrunc(ip, (u_long)uap->length);
        IUNLOCK(ip);
 }
 
        IUNLOCK(ip);
 }
 
@@ -774,6 +797,8 @@ fsync()
                return;
        ip = (struct inode *)fp->f_data;
        ILOCK(ip);
                return;
        ip = (struct inode *)fp->f_data;
        ILOCK(ip);
+       if (fp->f_flag&FWRITE)
+               ip->i_flag |= ICHG;
        syncip(ip);
        IUNLOCK(ip);
 }
        syncip(ip);
        IUNLOCK(ip);
 }
@@ -1107,7 +1132,8 @@ maknode(mode, ndp)
        ip->i_nlink = 1;
        ip->i_uid = u.u_uid;
        ip->i_gid = pdir->i_gid;
        ip->i_nlink = 1;
        ip->i_uid = u.u_uid;
        ip->i_gid = pdir->i_gid;
-       if (ip->i_mode & ISGID && !groupmember(ip->i_gid))
+       if (ip->i_mode & ISGID && !groupmember(ip->i_gid) &&
+           (u.u_error = suser(u.u_cred, &u.u_acflag)))
                ip->i_mode &= ~ISGID;
 #ifdef QUOTA
        ip->i_dquot = inoquota(ip);
                ip->i_mode &= ~ISGID;
 #ifdef QUOTA
        ip->i_dquot = inoquota(ip);