X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/943685687a914f34bb028d07fefeff4a802b6d5b..67361d543188004c23e8675506802b52a85fa12f:/usr/src/sys/ufs/lfs/lfs_vnops.c diff --git a/usr/src/sys/ufs/lfs/lfs_vnops.c b/usr/src/sys/ufs/lfs/lfs_vnops.c index cf71517b40..60735780d8 100644 --- a/usr/src/sys/ufs/lfs/lfs_vnops.c +++ b/usr/src/sys/ufs/lfs/lfs_vnops.c @@ -1,4 +1,10 @@ -/* lfs_vnops.c 6.14 84/08/29 */ +/* + * 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. + * + * @(#)lfs_vnops.c 7.3 (Berkeley) %G% + */ #include "param.h" #include "systm.h" @@ -113,31 +119,31 @@ copen(mode, arg, fname) register struct inode *ip; register struct file *fp; register struct nameidata *ndp = &u.u_nd; - int i; + int indx; -#ifdef notdef - if ((mode&(FREAD|FWRITE)) == 0) { - u.u_error = EINVAL; + fp = falloc(); + if (fp == NULL) return; - } -#endif + indx = u.u_r.r_val1; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = fname; if (mode&FCREAT) { - ndp->ni_nameiop = CREATE | FOLLOW; + if (mode & FEXCL) + ndp->ni_nameiop = CREATE; + else + ndp->ni_nameiop = CREATE | FOLLOW; ip = namei(ndp); if (ip == NULL) { if (u.u_error) - return; + goto bad1; ip = maknode(arg&07777&(~ISVTX), ndp); if (ip == NULL) - return; + goto bad1; mode &= ~FTRUNC; } else { if (mode&FEXCL) { u.u_error = EEXIST; - iput(ip); - return; + goto bad; } mode &= ~FCREAT; } @@ -145,7 +151,7 @@ copen(mode, arg, fname) ndp->ni_nameiop = LOOKUP | FOLLOW; ip = namei(ndp); if (ip == NULL) - return; + goto bad1; } if ((ip->i_mode & IFMT) == IFSOCK) { u.u_error = EOPNOTSUPP; @@ -164,9 +170,6 @@ copen(mode, arg, fname) } } } - fp = falloc(); - if (fp == NULL) - goto bad; if (mode&FTRUNC) itrunc(ip, (u_long)0); IUNLOCK(ip); @@ -174,23 +177,22 @@ copen(mode, arg, fname) fp->f_type = DTYPE_INODE; fp->f_ops = &inodeops; fp->f_data = (caddr_t)ip; - i = u.u_r.r_val1; if (setjmp(&u.u_qsave)) { if (u.u_error == 0) u.u_error = EINTR; - u.u_ofile[i] = NULL; + u.u_ofile[indx] = NULL; closef(fp); return; } u.u_error = openi(ip, mode); if (u.u_error == 0) return; - u.u_ofile[i] = NULL; - fp->f_count--; - irele(ip); - return; + ILOCK(ip); bad: iput(ip); +bad1: + u.u_ofile[indx] = NULL; + fp->f_count--; } /* @@ -329,7 +331,8 @@ symlink() 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); } @@ -511,10 +514,11 @@ readlink() if (ip == NULL) return; if ((ip->i_mode&IFMT) != IFLNK) { - u.u_error = ENXIO; + 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; @@ -533,7 +537,7 @@ chmod() if ((ip = owner(uap->fname, FOLLOW)) == NULL) return; - chmod1(ip, uap->fmode); + u.u_error = chmod1(ip, uap->fmode); iput(ip); } @@ -556,7 +560,7 @@ fchmod() if (u.u_uid != ip->i_uid && !suser()) return; ILOCK(ip); - chmod1(ip, uap->fmode); + u.u_error = chmod1(ip, uap->fmode); IUNLOCK(ip); } @@ -569,9 +573,12 @@ chmod1(ip, mode) register int mode; { + if (ip->i_fs->fs_ronly) + return (EROFS); ip->i_mode &= ~07777; if (u.u_uid) { - mode &= ~ISVTX; + if ((ip->i_mode & IFMT) != IFDIR) + mode &= ~ISVTX; if (!groupmember(ip->i_gid)) mode &= ~ISGID; } @@ -579,6 +586,7 @@ chmod1(ip, mode) ip->i_flag |= ICHG; if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) xrele(ip); + return (0); } /* @@ -593,7 +601,7 @@ chown() int gid; } *uap = (struct a *)u.u_ap; - if (!suser() || (ip = owner(uap->fname, NOFOLLOW)) == NULL) + if ((ip = owner(uap->fname, NOFOLLOW)) == NULL) return; u.u_error = chown1(ip, uap->uid, uap->gid); iput(ip); @@ -616,8 +624,6 @@ fchown() 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); @@ -635,10 +641,16 @@ chown1(ip, uid, gid) register long change; #endif + if (ip->i_fs->fs_ronly) + return (EROFS); if (uid == -1) uid = ip->i_uid; if (gid == -1) gid = ip->i_gid; + if (uid != ip->i_uid && !suser()) + return (u.u_error); + if (gid != ip->i_gid && !groupmember((gid_t)gid) && !suser()) + return (u.u_error); #ifdef QUOTA if (ip->i_uid == uid) /* this just speeds things a little */ change = 0; @@ -656,7 +668,7 @@ chown1(ip, uid, gid) #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); @@ -674,6 +686,11 @@ utimes() if ((ip = owner(uap->fname, FOLLOW)) == NULL) return; + if (ip->i_fs->fs_ronly) { + u.u_error = EROFS; + iput(ip); + return; + } u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); if (u.u_error == 0) { ip->i_flag |= IACC|IUPD|ICHG; @@ -698,7 +715,7 @@ truncate() { 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; @@ -715,7 +732,7 @@ truncate() u.u_error = EISDIR; goto bad; } - itrunc(ip, uap->length); + itrunc(ip, (u_long)uap->length); bad: iput(ip); } @@ -727,7 +744,7 @@ ftruncate() { struct a { int fd; - u_long length; + off_t length; } *uap = (struct a *)u.u_ap; struct inode *ip; struct file *fp; @@ -741,7 +758,7 @@ ftruncate() } ip = (struct inode *)fp->f_data; ILOCK(ip); - itrunc(ip, uap->length); + itrunc(ip, (u_long)uap->length); IUNLOCK(ip); } @@ -761,6 +778,8 @@ fsync() return; ip = (struct inode *)fp->f_data; ILOCK(ip); + if (fp->f_flag&FWRITE) + ip->i_flag |= ICHG; syncip(ip); IUNLOCK(ip); } @@ -922,6 +941,17 @@ rename() */ if (xp->i_number == ip->i_number) goto bad; + /* + * If the parent directory is "sticky", then the user must + * own the parent directory, or the destination of the rename, + * otherwise the destination may not be changed (except by + * root). This implements append-only directories. + */ + if ((dp->i_mode & ISVTX) && u.u_uid != 0 && + u.u_uid != dp->i_uid && xp->i_uid != u.u_uid) { + error = EPERM; + goto bad; + } /* * Target must be empty if a directory * and have no links to it. @@ -976,7 +1006,10 @@ rename() ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->from; xp = namei(ndp); - dp = ndp->ni_pdir; + if (xp != NULL) + dp = ndp->ni_pdir; + else + dp = NULL; /* * Insure that the directory entry still exists and has not * changed while the new name has been entered. If the source is @@ -987,9 +1020,9 @@ rename() * The IRENAME flag insures that it cannot be moved by another * rename. */ - if (dp == NULL || xp != ip) { + if (xp != ip) { if (doingdirectory) - panic("rename: lost entry"); + panic("rename: lost dir entry"); } else { /* * If the source is a directory with a @@ -1080,7 +1113,7 @@ maknode(mode, ndp) 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) && !suser()) ip->i_mode &= ~ISGID; #ifdef QUOTA ip->i_dquot = inoquota(ip); @@ -1189,6 +1222,10 @@ mkdir() dp->i_flag |= ICHG; goto bad; } + if (DIRBLKSIZ > ip->i_fs->fs_fsize) + panic("mkdir: blksize"); /* XXX - should grow with bmap() */ + else + ip->i_size = DIRBLKSIZ; /* * Directory all set up, now * install the entry for it in