X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/09bf91df773a593f64f4181ecefbb77a2259ca2c..23de9f204f2e6d2b17fd99eb756f5ca80ecb715a:/usr/src/sys/ufs/ffs/ufs_vnops.c diff --git a/usr/src/sys/ufs/ffs/ufs_vnops.c b/usr/src/sys/ufs/ffs/ufs_vnops.c index e65f93663d..94b9fab046 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -1,22 +1,21 @@ -/* ufs_vnops.c 6.5 84/02/10 */ - -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/kernel.h" -#include "../h/file.h" -#include "../h/stat.h" -#include "../h/inode.h" -#include "../h/fs.h" -#include "../h/buf.h" -#include "../h/proc.h" -#include "../h/quota.h" -#include "../h/uio.h" -#include "../h/socket.h" -#include "../h/socketvar.h" -#include "../h/nami.h" -#include "../h/mount.h" +/* ufs_vnops.c 6.16 85/02/22 */ + +#include "param.h" +#include "systm.h" +#include "dir.h" +#include "user.h" +#include "kernel.h" +#include "file.h" +#include "stat.h" +#include "inode.h" +#include "fs.h" +#include "buf.h" +#include "proc.h" +#include "quota.h" +#include "uio.h" +#include "socket.h" +#include "socketvar.h" +#include "mount.h" extern struct fileops inodeops; struct file *getinode(); @@ -49,9 +48,13 @@ chdirec(ipp) register struct inode *ip; struct a { char *fname; - }; + } *uap = (struct a *)u.u_ap; + register struct nameidata *ndp = &u.u_nd; - ip = namei(uchar, LOOKUP, 1); + ndp->ni_nameiop = LOOKUP | FOLLOW; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->fname; + ip = namei(ndp); if (ip == NULL) return; if ((ip->i_mode&IFMT) != IFDIR) { @@ -60,7 +63,7 @@ chdirec(ipp) } if (access(ip, IEXEC)) goto bad; - iunlock(ip); + IUNLOCK(ip); if (*ipp) irele(*ipp); *ipp = ip; @@ -81,7 +84,7 @@ open() int crtmode; } *uap = (struct a *) u.u_ap; - copen(uap->mode-FOPEN, uap->crtmode); + copen(uap->mode-FOPEN, uap->crtmode, uap->fname); } /* @@ -94,7 +97,7 @@ creat() int fmode; } *uap = (struct a *)u.u_ap; - copen(FWRITE|FCREAT|FTRUNC, uap->fmode); + copen(FWRITE|FCREAT|FTRUNC, uap->fmode, uap->fname); } /* @@ -102,12 +105,14 @@ creat() * Check permissions, allocate an open file structure, * and call the device open routine if any. */ -copen(mode, arg) +copen(mode, arg, fname) register int mode; int arg; + caddr_t fname; { register struct inode *ip; register struct file *fp; + register struct nameidata *ndp = &u.u_nd; int i; #ifdef notdef @@ -116,12 +121,15 @@ copen(mode, arg) return; } #endif + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = fname; if (mode&FCREAT) { - ip = namei(uchar, CREATE, 1); + ndp->ni_nameiop = CREATE | FOLLOW; + ip = namei(ndp); if (ip == NULL) { if (u.u_error) return; - ip = maknode(arg&07777&(~ISVTX)); + ip = maknode(arg&07777&(~ISVTX), ndp); if (ip == NULL) return; mode &= ~FTRUNC; @@ -134,7 +142,8 @@ copen(mode, arg) mode &= ~FCREAT; } } else { - ip = namei(uchar, LOOKUP, 1); + ndp->ni_nameiop = LOOKUP | FOLLOW; + ip = namei(ndp); if (ip == NULL) return; } @@ -160,7 +169,7 @@ copen(mode, arg) goto bad; if (mode&FTRUNC) itrunc(ip, (u_long)0); - iunlock(ip); + IUNLOCK(ip); fp->f_flag = mode&FMASK; fp->f_type = DTYPE_INODE; fp->f_ops = &inodeops; @@ -194,19 +203,22 @@ mknod() char *fname; int fmode; int dev; - } *uap; + } *uap = (struct a *)u.u_ap; + register struct nameidata *ndp = &u.u_nd; - uap = (struct a *)u.u_ap; if (!suser()) return; - ip = namei(uchar, CREATE, 0); + ndp->ni_nameiop = CREATE; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->fname; + ip = namei(ndp); if (ip != NULL) { u.u_error = EEXIST; goto out; } if (u.u_error) return; - ip = maknode(uap->fmode); + ip = maknode(uap->fmode, ndp); if (ip == NULL) return; switch (ip->i_mode & IFMT) { @@ -237,10 +249,13 @@ link() register struct a { char *target; char *linkname; - } *uap; + } *uap = (struct a *)u.u_ap; + register struct nameidata *ndp = &u.u_nd; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 1); /* well, this routine is doomed anyhow */ + ndp->ni_nameiop = LOOKUP | FOLLOW; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->target; + ip = namei(ndp); /* well, this routine is doomed anyhow */ if (ip == NULL) return; if ((ip->i_mode&IFMT) == IFDIR && !suser()) { @@ -250,9 +265,11 @@ link() ip->i_nlink++; ip->i_flag |= ICHG; iupdat(ip, &time, &time, 1); - iunlock(ip); - u.u_dirp = (caddr_t)uap->linkname; - xp = namei(uchar, CREATE, 0); + IUNLOCK(ip); + ndp->ni_nameiop = CREATE; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = (caddr_t)uap->linkname; + xp = namei(ndp); if (xp != NULL) { u.u_error = EEXIST; iput(xp); @@ -260,12 +277,12 @@ link() } if (u.u_error) goto out; - if (u.u_pdir->i_dev != ip->i_dev) { - iput(u.u_pdir); + if (ndp->ni_pdir->i_dev != ip->i_dev) { + iput(ndp->ni_pdir); u.u_error = EXDEV; goto out; } - u.u_error = direnter(ip); + u.u_error = direnter(ip, ndp); out: if (u.u_error) { ip->i_nlink--; @@ -282,12 +299,12 @@ symlink() register struct a { char *target; char *linkname; - } *uap; + } *uap = (struct a *)u.u_ap; register struct inode *ip; register char *tp; register c, nc; + register struct nameidata *ndp = &u.u_nd; - uap = (struct a *)u.u_ap; tp = uap->target; nc = 0; while (c = fubyte(tp)) { @@ -298,8 +315,10 @@ symlink() tp++; nc++; } - u.u_dirp = uap->linkname; - ip = namei(uchar, CREATE, 0); + ndp->ni_nameiop = CREATE; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->linkname; + ip = namei(ndp); if (ip) { iput(ip); u.u_error = EEXIST; @@ -307,7 +326,7 @@ symlink() } if (u.u_error) return; - ip = maknode(IFLNK | 0777); + ip = maknode(IFLNK | 0777, ndp); if (ip == NULL) return; u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); @@ -324,13 +343,17 @@ unlink() { struct a { char *fname; - }; + } *uap = (struct a *)u.u_ap; register struct inode *ip, *dp; + register struct nameidata *ndp = &u.u_nd; - ip = namei(uchar, DELETE | LOCKPARENT, 0); + ndp->ni_nameiop = DELETE | LOCKPARENT; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->fname; + ip = namei(ndp); if (ip == NULL) return; - dp = u.u_pdir; + dp = ndp->ni_pdir; if ((ip->i_mode&IFMT) == IFDIR && !suser()) goto out; /* @@ -342,7 +365,7 @@ unlink() } if (ip->i_flag&ITEXT) xrele(ip); /* try once to free text */ - if (dirremove()) { + if (dirremove(ndp)) { ip->i_nlink--; ip->i_flag |= ICHG; } @@ -364,12 +387,13 @@ lseek() int fd; off_t off; int sbase; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - fp = getinode(uap->fd); - if (fp == NULL) + GETF(fp, uap->fd); + if (fp->f_type != DTYPE_INODE) { + u.u_error = ESPIPE; return; + } switch (uap->sbase) { case L_INCR: @@ -401,14 +425,17 @@ saccess() register struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; + register struct nameidata *ndp = &u.u_nd; - uap = (struct a *)u.u_ap; svuid = u.u_uid; svgid = u.u_gid; u.u_uid = u.u_ruid; u.u_gid = u.u_rgid; - ip = namei(uchar, LOOKUP, 1); + ndp->ni_nameiop = LOOKUP | FOLLOW; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->fname; + ip = namei(ndp); if (ip != NULL) { if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; @@ -429,7 +456,7 @@ done: stat() { - stat1(1); + stat1(FOLLOW); } /* @@ -438,7 +465,7 @@ stat() lstat() { - stat1(0); + stat1(NOFOLLOW); } stat1(follow) @@ -448,11 +475,14 @@ stat1(follow) register struct a { char *fname; struct stat *ub; - } *uap; + } *uap = (struct a *)u.u_ap; struct stat sb; + register struct nameidata *ndp = &u.u_nd; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, follow); + ndp->ni_nameiop = LOOKUP | follow; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->fname; + ip = namei(ndp); if (ip == NULL) return; (void) ino_stat(ip, &sb); @@ -471,9 +501,13 @@ readlink() char *buf; int count; } *uap = (struct a *)u.u_ap; + register struct nameidata *ndp = &u.u_nd; int resid; - ip = namei(uchar, LOOKUP, 0); + ndp->ni_nameiop = LOOKUP; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->name; + ip = namei(ndp); if (ip == NULL) return; if ((ip->i_mode&IFMT) != IFLNK) { @@ -495,10 +529,9 @@ chmod() struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - if ((ip = owner(1)) == NULL) + if ((ip = owner(uap->fname, FOLLOW)) == NULL) return; chmod1(ip, uap->fmode); iput(ip); @@ -512,20 +545,19 @@ fchmod() struct a { int fd; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; register struct inode *ip; register struct file *fp; - uap = (struct a *)u.u_ap; fp = getinode(uap->fd); if (fp == NULL) return; ip = (struct inode *)fp->f_data; if (u.u_uid != ip->i_uid && !suser()) return; - ilock(ip); + ILOCK(ip); chmod1(ip, uap->fmode); - iunlock(ip); + IUNLOCK(ip); } /* @@ -559,10 +591,9 @@ chown() char *fname; int uid; int gid; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - if (!suser() || (ip = owner(0)) == NULL) + if (!suser() || (ip = owner(uap->fname, NOFOLLOW)) == NULL) return; u.u_error = chown1(ip, uap->uid, uap->gid); iput(ip); @@ -577,20 +608,19 @@ fchown() int fd; int uid; int gid; - } *uap; + } *uap = (struct a *)u.u_ap; register struct inode *ip; register struct file *fp; - uap = (struct a *)u.u_ap; fp = getinode(uap->fd); if (fp == NULL) return; ip = (struct inode *)fp->f_data; if (!suser()) return; - ilock(ip); + ILOCK(ip); u.u_error = chown1(ip, uap->uid, uap->gid); - iunlock(ip); + IUNLOCK(ip); } /* @@ -642,7 +672,7 @@ utimes() register struct inode *ip; struct timeval tv[2]; - if ((ip = owner(1)) == NULL) + if ((ip = owner(uap->fname, FOLLOW)) == NULL) return; u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); if (u.u_error == 0) { @@ -671,8 +701,12 @@ truncate() u_long length; } *uap = (struct a *)u.u_ap; struct inode *ip; + register struct nameidata *ndp = &u.u_nd; - ip = namei(uchar, LOOKUP, 1); + ndp->ni_nameiop = LOOKUP | FOLLOW; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->fname; + ip = namei(ndp); if (ip == NULL) return; if (access(ip, IWRITE)) @@ -706,9 +740,9 @@ ftruncate() return; } ip = (struct inode *)fp->f_data; - ilock(ip); + ILOCK(ip); itrunc(ip, uap->length); - iunlock(ip); + IUNLOCK(ip); } /* @@ -726,9 +760,9 @@ fsync() if (fp == NULL) return; ip = (struct inode *)fp->f_data; - ilock(ip); + ILOCK(ip); syncip(ip); - iunlock(ip); + IUNLOCK(ip); } /* @@ -746,11 +780,12 @@ fsync() * * 1) Bump link count on source while we're linking it to the * target. This also insure the inode won't be deleted out - * from underneath us while we work. + * from underneath us while we work (it may be truncated by + * a concurrent `trunc' or `open' for creation). * 2) Link source to destination. If destination already exists, * delete it first. - * 3) Unlink source reference to inode if still around. - * 4) If a directory was moved and the parent of the destination + * 3) Unlink source reference to inode if still around. If a + * directory was moved and the parent of the destination * is different from the source, patch the ".." entry in the * directory. * @@ -762,27 +797,30 @@ rename() struct a { char *from; char *to; - } *uap; + } *uap = (struct a *)u.u_ap; register struct inode *ip, *xp, *dp; - int oldparent, parentdifferent, doingdirectory; + struct dirtemplate dirbuf; + int doingdirectory = 0, oldparent = 0, newparent = 0; + register struct nameidata *ndp = &u.u_nd; int error = 0; - uap = (struct a *)u.u_ap; - ip = namei(uchar, DELETE | LOCKPARENT, 0); + ndp->ni_nameiop = DELETE | LOCKPARENT; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->from; + ip = namei(ndp); if (ip == NULL) return; - dp = u.u_pdir; - oldparent = 0, doingdirectory = 0; + dp = ndp->ni_pdir; if ((ip->i_mode&IFMT) == IFDIR) { register struct direct *d; - d = &u.u_dent; + d = &ndp->ni_dent; /* * Avoid ".", "..", and aliases of "." for obvious reasons. */ if ((d->d_namlen == 1 && d->d_name[0] == '.') || (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || - (dp == ip)) { + (dp == ip) || (ip->i_flag & IRENAME)) { iput(dp); if (dp == ip) irele(ip); @@ -791,6 +829,7 @@ rename() u.u_error = EINVAL; return; } + ip->i_flag |= IRENAME; oldparent = dp->i_number; doingdirectory++; } @@ -805,19 +844,20 @@ rename() ip->i_nlink++; ip->i_flag |= ICHG; iupdat(ip, &time, &time, 1); - iunlock(ip); + IUNLOCK(ip); /* * When the target exists, both the directory * and target inodes are returned locked. */ - u.u_dirp = (caddr_t)uap->to; - xp = namei(uchar, CREATE | LOCKPARENT | NOCACHE, 0); + ndp->ni_nameiop = CREATE | LOCKPARENT | NOCACHE; + ndp->ni_dirp = (caddr_t)uap->to; + xp = namei(ndp); if (u.u_error) { error = u.u_error; goto out; } - dp = u.u_pdir; + dp = ndp->ni_pdir; /* * If ".." must be changed (ie the directory gets a new * parent) then the source directory must not be in the @@ -828,24 +868,24 @@ rename() * to namei, as the parent directory is unlocked by the * call to checkpath(). */ - parentdifferent = oldparent != dp->i_number; - if (doingdirectory && parentdifferent) { + if (oldparent != dp->i_number) + newparent = dp->i_number; + if (doingdirectory && newparent) { if (access(ip, IWRITE)) goto bad; do { - dp = u.u_pdir; + dp = ndp->ni_pdir; if (xp != NULL) iput(xp); u.u_error = checkpath(ip, dp); if (u.u_error) goto out; - u.u_dirp = (caddr_t)uap->to; - xp = namei(uchar, CREATE | LOCKPARENT | NOCACHE, 0); + xp = namei(ndp); if (u.u_error) { error = u.u_error; goto out; } - } while (dp != u.u_pdir); + } while (dp != ndp->ni_pdir); } /* * 2) If target doesn't exist, link the target @@ -860,18 +900,16 @@ rename() goto bad; } /* - * Account for ".." in directory. - * When source and destination have the - * same parent we don't fool with the - * link count -- this isn't required - * because we do a similar check below. + * Account for ".." in new directory. + * When source and destination have the same + * parent we don't fool with the link count. */ - if (doingdirectory && parentdifferent) { + if (doingdirectory && newparent) { dp->i_nlink++; dp->i_flag |= ICHG; iupdat(dp, &time, &time, 1); } - error = direnter(ip); + error = direnter(ip, ndp); if (error) goto out; } else { @@ -892,7 +930,7 @@ rename() * not directories). */ if ((xp->i_mode&IFMT) == IFDIR) { - if (!dirempty(xp) || xp->i_nlink > 2) { + if (!dirempty(xp, dp->i_number) || xp->i_nlink > 2) { error = ENOTEMPTY; goto bad; } @@ -900,11 +938,12 @@ rename() error = ENOTDIR; goto bad; } + cacheinval(dp); } else if (doingdirectory) { error = EISDIR; goto bad; } - dirrewrite(dp, ip); + dirrewrite(dp, ip, ndp); if (u.u_error) { error = u.u_error; goto bad1; @@ -916,9 +955,8 @@ rename() * no links to it, so we can squash the inode and * any space associated with it. We disallowed * renaming over top of a directory with links to - * it above, as we've no way to determine if - * we've got a link or the directory itself, and - * if we get a link, then ".." will be screwed up. + * it above, as the remaining link would point to + * a directory without "." or ".." entries. */ xp->i_nlink--; if (doingdirectory) { @@ -934,78 +972,71 @@ rename() /* * 3) Unlink the source. */ - u.u_dirp = uap->from; - dp = namei(uchar, DELETE, 0); + ndp->ni_nameiop = DELETE | LOCKPARENT; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->from; + xp = namei(ndp); + if (xp != NULL) + dp = ndp->ni_pdir; + else + dp = NULL; /* - * Insure directory entry still exists and - * has not changed since the start of all - * this. If either has occured, forget about - * about deleting the original entry and just - * adjust the link count in the inode. + * Insure that the directory entry still exists and has not + * changed while the new name has been entered. If the source is + * a file then the entry may have been unlinked or renamed. In + * either case there is no further work to be done. If the source + * is a directory then it cannot have been rmdir'ed; its link + * count of three would cause a rmdir to fail with ENOTEMPTY. + * The IRENAME flag insures that it cannot be moved by another + * rename. */ - if (dp == NULL || u.u_dent.d_ino != ip->i_number) { - ip->i_nlink--; - ip->i_flag |= ICHG; + if (xp != ip) { + if (doingdirectory) + panic("rename: lost dir entry"); } else { /* - * If source is a directory, must adjust - * link count of parent directory also. - * If target didn't exist and source and - * target have the same parent, then we - * needn't touch the link count, it all - * balances out in the end. Otherwise, we - * must do so to reflect deletion of ".." - * done above. + * If the source is a directory with a + * new parent, the link count of the old + * parent directory must be decremented + * and ".." set to point to the new parent. */ - if (doingdirectory && (xp != NULL || parentdifferent)) { + if (doingdirectory && newparent) { dp->i_nlink--; dp->i_flag |= ICHG; + error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf, + sizeof (struct dirtemplate), (off_t)0, 1, + (int *)0); + if (error == 0) { + if (dirbuf.dotdot_namlen != 2 || + dirbuf.dotdot_name[0] != '.' || + dirbuf.dotdot_name[1] != '.') { + printf("rename: mangled dir\n"); + } else { + dirbuf.dotdot_ino = newparent; + (void) rdwri(UIO_WRITE, xp, + (caddr_t)&dirbuf, + sizeof (struct dirtemplate), + (off_t)0, 1, (int *)0); + cacheinval(dp); + } + } } - if (dirremove()) { - ip->i_nlink--; - ip->i_flag |= ICHG; + if (dirremove(ndp)) { + xp->i_nlink--; + xp->i_flag |= ICHG; } - if (error == 0) /* conservative */ + xp->i_flag &= ~IRENAME; + if (error == 0) /* XXX conservative */ error = u.u_error; } - irele(ip); if (dp) iput(dp); - - /* - * 4) Renaming a directory with the parent - * different requires ".." to be rewritten. - * The window is still there for ".." to - * be inconsistent, but this is unavoidable, - * and a lot shorter than when it was done - * in a user process. - */ - if (doingdirectory && parentdifferent && error == 0) { - struct dirtemplate dirbuf; - - u.u_dirp = uap->to; - ip = namei(uchar, LOOKUP | LOCKPARENT, 0); - if (ip == NULL) { - printf("rename: .. went away\n"); - return; - } - dp = u.u_pdir; - if ((ip->i_mode&IFMT) != IFDIR) { - printf("rename: .. not a directory\n"); - goto stuck; - } - error = rdwri(UIO_READ, ip, (caddr_t)&dirbuf, - sizeof (struct dirtemplate), (off_t)0, 1, (int *)0); - if (error == 0) { - dirbuf.dotdot_ino = dp->i_number; - (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf, - sizeof (struct dirtemplate), (off_t)0, 1, (int *)0); - } -stuck: - irele(dp); - iput(ip); - } - goto done; + if (xp) + iput(xp); + irele(ip); + if (error) + u.u_error = error; + return; bad: iput(dp); @@ -1016,7 +1047,6 @@ out: ip->i_nlink--; ip->i_flag |= ICHG; irele(ip); -done: if (error) u.u_error = error; } @@ -1025,19 +1055,21 @@ done: * Make a new file. */ struct inode * -maknode(mode) +maknode(mode, ndp) int mode; + register struct nameidata *ndp; { register struct inode *ip; + register struct inode *pdir = ndp->ni_pdir; ino_t ipref; if ((mode & IFMT) == IFDIR) - ipref = dirpref(u.u_pdir->i_fs); + ipref = dirpref(pdir->i_fs); else - ipref = u.u_pdir->i_number; - ip = ialloc(u.u_pdir, ipref, mode); + ipref = pdir->i_number; + ip = ialloc(pdir, ipref, mode); if (ip == NULL) { - iput(u.u_pdir); + iput(pdir); return (NULL); } #ifdef QUOTA @@ -1050,7 +1082,7 @@ maknode(mode) ip->i_mode = mode & ~u.u_cmask; ip->i_nlink = 1; ip->i_uid = u.u_uid; - ip->i_gid = u.u_pdir->i_gid; + ip->i_gid = pdir->i_gid; if (ip->i_mode & ISGID && !groupmember(ip->i_gid)) ip->i_mode &= ~ISGID; #ifdef QUOTA @@ -1061,7 +1093,7 @@ maknode(mode) * Make sure inode goes to disk before directory entry. */ iupdat(ip, &time, &time, 1); - u.u_error = direnter(ip); + u.u_error = direnter(ip, ndp); if (u.u_error) { /* * Write error occurred trying to update directory @@ -1091,12 +1123,15 @@ mkdir() struct a { char *name; int dmode; - } *uap; + } *uap = (struct a *)u.u_ap; register struct inode *ip, *dp; struct dirtemplate dirtemplate; + register struct nameidata *ndp = &u.u_nd; - uap = (struct a *)u.u_ap; - ip = namei(uchar, CREATE, 0); + ndp->ni_nameiop = CREATE; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->name; + ip = namei(ndp); if (u.u_error) return; if (ip != NULL) { @@ -1104,7 +1139,7 @@ mkdir() u.u_error = EEXIST; return; } - dp = u.u_pdir; + dp = ndp->ni_pdir; uap->dmode &= 0777; uap->dmode |= IFDIR; /* @@ -1157,16 +1192,22 @@ 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 * the parent directory. */ - u.u_error = direnter(ip); + u.u_error = direnter(ip, ndp); dp = NULL; if (u.u_error) { - u.u_dirp = uap->name; - dp = namei(uchar, LOOKUP | NOCACHE, 0); + ndp->ni_nameiop = LOOKUP | NOCACHE; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->name; + dp = namei(ndp); if (dp) { dp->i_nlink--; dp->i_flag |= ICHG; @@ -1194,13 +1235,17 @@ rmdir() { struct a { char *name; - }; + } *uap = (struct a *)u.u_ap; register struct inode *ip, *dp; + register struct nameidata *ndp = &u.u_nd; - ip = namei(uchar, DELETE | LOCKPARENT, 0); + ndp->ni_nameiop = DELETE | LOCKPARENT; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = uap->name; + ip = namei(ndp); if (ip == NULL) return; - dp = u.u_pdir; + dp = ndp->ni_pdir; /* * No rmdir "." please. */ @@ -1228,7 +1273,7 @@ rmdir() * the current directory and thus be * non-empty.) */ - if (ip->i_nlink != 2 || !dirempty(ip)) { + if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number)) { u.u_error = ENOTEMPTY; goto out; } @@ -1237,10 +1282,11 @@ rmdir() * inode. If we crash in between, the directory * will be reattached to lost+found, */ - if (dirremove() == 0) + if (dirremove(ndp) == 0) goto out; dp->i_nlink--; dp->i_flag |= ICHG; + cacheinval(dp); iput(dp); dp = NULL; /* @@ -1256,6 +1302,7 @@ rmdir() */ ip->i_nlink -= 2; itrunc(ip, (u_long)0); + cacheinval(ip); out: if (dp) iput(dp); @@ -1266,14 +1313,15 @@ struct file * getinode(fdes) int fdes; { - register struct file *fp; + struct file *fp; - fp = getf(fdes); - if (fp == 0) - return (0); + if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { + u.u_error = EBADF; + return ((struct file *)0); + } if (fp->f_type != DTYPE_INODE) { u.u_error = EINVAL; - return (0); + return ((struct file *)0); } return (fp); } @@ -1285,9 +1333,8 @@ umask() { register struct a { int mask; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; u.u_r.r_val1 = u.u_cmask; u.u_cmask = uap->mask & 07777; }