-/* lfs_vnops.c 4.24 82/06/04 */
+/* lfs_vnops.c 4.30 82/07/24 */
-#ifdef SIMFS
-#include "../h/sysrenam.h"
-#endif
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/buf.h"
#include "../h/proc.h"
#include "../h/inline.h"
+#ifdef EFS
+#include "../net/in.h"
+#include "../h/efs.h"
+#endif
+#include "../h/quota.h"
+#include "../h/descrip.h"
chdir()
{
}
if(access(ip, IEXEC))
goto bad;
- irele(ip);
- if (*ipp) {
- ilock(*ipp);
- iput(*ipp);
- }
+ iunlock(ip);
+ if (*ipp)
+ irele(*ipp);
*ipp = ip;
return;
/*
* Creat system call.
*/
-creat()
+ocreat()
{
register struct inode *ip;
register struct a {
u.u_error = EISDIR;
}
}
- if (u.u_error)
- goto out;
+ if (u.u_error) {
+ iput(ip);
+ return;
+ }
if (trf == 1)
itrunc(ip);
- irele(ip);
+ iunlock(ip);
if ((fp = falloc()) == NULL)
goto out;
fp->f_flag = mode&(FREAD|FWRITE);
+ fp->f_type = DTYPE_FILE;
i = u.u_r.r_val1;
fp->f_inode = ip;
+#ifdef EFS
+ openi(ip, mode&(FREAD|FWRITE), trf);
+#else
openi(ip, mode&(FREAD|FWRITE));
+#endif
if (u.u_error == 0)
return;
u.u_ofile[i] = NULL;
fp->f_count--;
out:
- if (ip != NULL)
- iput(ip);
+ irele(ip);
}
/*
ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */
if (ip == NULL)
return;
- if ((ip->i_mode&IFMT)==IFDIR && !suser())
- goto out1;
+ if ((ip->i_mode&IFMT)==IFDIR && !suser()) {
+ iput(ip);
+ return;
+ }
ip->i_nlink++;
ip->i_flag |= ICHG;
iupdat(ip, &time, &time, 1);
- irele(ip);
+ iunlock(ip);
u.u_dirp = (caddr_t)uap->linkname;
xp = namei(uchar, 1, 0);
if (xp != NULL) {
ip->i_flag |= ICHG;
}
out1:
- iput(ip);
+ irele(ip);
}
/*
struct fs *fs;
struct buf *bp;
int lbn, bn, base;
+ int unlinkingdot = 0;
pp = namei(uchar, 2, 0);
if(pp == NULL)
return;
+#ifdef EFS
+ /* divert to extended file system if off machine. */
+ if (efsinode(pp)) {
+ dev_t ndev = pp->i_rdev;
+
+ iput(pp); /* avoid recursive hang on inode */
+ efsunlink(ndev);
+ if (u.u_error != EEXIST)
+ return;
+
+ /*
+ * If a null pathname remainder, then do
+ * the unlink locally after restoring state.
+ */
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ pp = namei(uchar, 2, 0);
+ }
+#endif
+
/*
* Check for unlink(".")
* to avoid hanging on the iget
if (pp->i_number == u.u_dent.d_ino) {
ip = pp;
ip->i_count++;
+ unlinkingdot++;
} else
ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
if(ip == NULL)
/*
* first entry in block, so set d_ino to zero.
*/
+/*ZZ*/if(u.u_offset&0x1ff)printf("missed dir compact dir %s/%d off %d file %s\n"
+/*ZZ*/,pp->i_fs->fs_fsmnt,pp->i_number,u.u_offset,u.u_dent.d_name);
u.u_base = (caddr_t)&u.u_dent;
u.u_count = DIRSIZ(&u.u_dent);
u.u_dent.d_ino = 0;
}
((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
u.u_dent.d_reclen;
+/*ZZ*/if(((int)(bp->b_un.b_addr + base)&0x1ff)+u.u_dent.d_reclen>512)
+/*ZZ*/ panic("unlink: reclen");
bwrite(bp);
pp->i_flag |= IUPD|ICHG;
}
ip->i_flag |= ICHG;
out:
- iput(ip);
+ if (unlinkingdot)
+ irele(ip);
+ else
+ iput(ip);
out1:
iput(pp);
}
fp = getf(uap->fdes);
if (fp == NULL)
return;
- if (fp->f_flag&FSOCKET) {
+ if (fp->f_type == DTYPE_SOCKET) {
u.u_error = ESPIPE;
return;
}
if (uap->sbase == 1)
uap->off += fp->f_offset;
- else if (uap->sbase == 2)
+ else if (uap->sbase == 2) {
+#ifdef EFS
+ struct inode *ip = fp->f_inode;
+ uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size;
+#else
uap->off += fp->f_inode->i_size;
+#endif
+ }
fp->f_offset = uap->off;
u.u_r.r_off = uap->off;
}
u.u_uid = u.u_ruid;
u.u_gid = u.u_rgid;
ip = namei(uchar, 0, 1);
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efssaccess(ndev);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = namei(uchar, 0, 1);
+ }
+#endif
if (ip != NULL) {
if (uap->fmode&(IREAD>>6))
(void) access(ip, IREAD);
fp = getf(uap->fdes);
if (fp == NULL)
return;
- if (fp->f_flag & FSOCKET)
+#ifdef EFS
+ if (efsinode(fp->f_inode)) {
+ efsfstat(fp->f_inode->i_rdev, fp);
+ return;
+ }
+#endif
+ if (fp->f_type == DTYPE_SOCKET)
u.u_error = sostat(fp->f_socket, uap->sb);
else
stat1(fp->f_inode, uap->sb);
ip = namei(uchar, 0, 1);
if (ip == NULL)
return;
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efsstat(ndev);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = namei(uchar, 0, 1);
+ }
+#endif
stat1(ip, uap->sb);
iput(ip);
}
ip = namei(uchar, 0, 0);
if (ip == NULL)
return;
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efslstat(ndev);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = namei(uchar, 0, 0);
+ }
+#endif
stat1(ip, uap->sb);
iput(ip);
}
ip = namei(uchar, 0, 0);
if (ip == NULL)
return;
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efsreadlink(ndev);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = namei(uchar, 0, 0);
+ return (0);
+ }
+#endif
if ((ip->i_mode&IFMT) != IFLNK) {
u.u_error = ENXIO;
goto out;
uap = (struct a *)u.u_ap;
if ((ip = owner(1)) == NULL)
return;
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efschmod(ndev);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = owner(1);
+ }
+#endif
ip->i_mode &= ~07777;
- if (u.u_uid)
+ if (u.u_uid) {
uap->fmode &= ~ISVTX;
+ if (ip->i_gid >= NGRPS ||
+ (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
+ (1 << ip->i_gid%(sizeof(int)*8))) == 0)
+ uap->fmode &= ~ISGID;
+#if MUSH
+ if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
+ (ip->i_mode & IFMT) != IFCHR)
+ uap->fmode &= ~u.u_cmask;
+#endif
+ }
ip->i_mode |= uap->fmode&07777;
ip->i_flag |= ICHG;
if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
xrele(ip);
+#ifdef MELB
+ if ((ip->i_mode & ISUID) && ip->i_uid == 0)
+ printf("%s: ino %d (%s) setuid root\n"
+ , getfs(ip->i_dev)->s_fsmnt
+ , ip->i_number
+ , u.u_dent.d_name
+ );
+#endif
iput(ip);
}
int uid;
int gid;
} *uap;
+#if QUOTA
+ register long change;
+#endif
uap = (struct a *)u.u_ap;
if (!suser() || (ip = owner(0)) == NULL)
return;
- ip->i_uid = uap->uid;
- ip->i_gid = uap->gid;
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efschown(ndev);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = owner(0);
+ }
+#endif
+#if QUOTA
+ /*
+ * This doesn't allow for holes in files (which hopefully don't
+ * happen often in files that we chown), and is not accurate anyway
+ * (eg: it totally ignores 3 level indir blk files - but hopefully
+ * noone who can make a file that big will have a quota)
+ */
+ if (ip->i_uid == uap->uid)
+ change = 0;
+ else {
+ register struct fs *fs = ip->i_fs;
+
+ if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
+ register off_t size;
+
+ size = blkroundup(fs, ip->i_size) - change;
+ change += size;
+ change += fs->fs_bsize;
+ /* This assumes NIADDR <= 2 */
+ if (size > NINDIR(fs) * fs->fs_bsize)
+ change += fs->fs_bsize;
+ } else
+ change = fragroundup(fs, ip->i_size);
+ change /= DEV_BSIZE;
+ }
+ chkdq(ip, -change, 1);
+ chkiq(ip->i_dev, ip, ip->i_uid, 1);
+ dqrele(ip->i_dquot);
+#endif
+ /*
+ * keep uid/gid's in sane range - no err, so chown(file, uid, -1)
+ * will do something useful
+ */
+ if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */
+ ip->i_uid = uap->uid;
+ if (uap->gid >= 0 && uap->gid <= 32767) /* same here */
+ ip->i_gid = uap->gid;
ip->i_flag |= ICHG;
if (u.u_ruid != 0)
ip->i_mode &= ~(ISUID|ISGID);
+#if QUOTA
+ ip->i_dquot = inoquota(ip);
+ chkdq(ip, change, 1);
+ chkiq(ip->i_dev, NULL, uap->uid, 1);
+#endif
iput(ip);
}
if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
u.u_error = EFAULT;
} else {
+#ifdef EFS
+ if (efsinode(ip)) {
+ dev_t ndev = ip->i_rdev;
+
+ iput(ip);
+ efsutime(ndev, uap->fname, tv);
+ if (u.u_error != EEXIST)
+ return;
+ u.u_error = 0;
+ u.u_dirp = (caddr_t)u.u_arg[0];
+ ip = owner(1);
+ }
+#endif
ip->i_flag |= IACC|IUPD|ICHG;
iupdat(ip, &tv[0], &tv[1], 0);
}