-/* lfs_vnops.c 4.58 83/05/28 */
-
-#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"
+/* lfs_vnops.c 6.17 85/03/19 */
+
+#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();
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) {
}
if (access(ip, IEXEC))
goto bad;
- iunlock(ip);
+ IUNLOCK(ip);
if (*ipp)
irele(*ipp);
*ipp = ip;
int crtmode;
} *uap = (struct a *) u.u_ap;
- copen(uap->mode-FOPEN, uap->crtmode);
+ copen(uap->mode-FOPEN, uap->crtmode, uap->fname);
}
/*
int fmode;
} *uap = (struct a *)u.u_ap;
- copen(FWRITE|FCREAT|FTRUNC, uap->fmode);
+ copen(FWRITE|FCREAT|FTRUNC, uap->fmode, uap->fname);
}
/*
* 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
return;
}
#endif
+ ndp->ni_segflg = UIO_USERSPACE;
+ ndp->ni_dirp = fname;
if (mode&FCREAT) {
- ip = namei(uchar, CREATE, 1);
+ if (mode & FEXCL)
+ ndp->ni_nameiop = CREATE;
+ else
+ 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;
mode &= ~FCREAT;
}
} else {
- ip = namei(uchar, LOOKUP, 1);
+ ndp->ni_nameiop = LOOKUP | FOLLOW;
+ ip = namei(ndp);
if (ip == NULL)
return;
}
if (mode&FREAD)
if (access(ip, IREAD))
goto bad;
- if (mode&FWRITE) {
+ if (mode&(FWRITE|FTRUNC)) {
if (access(ip, IWRITE))
goto bad;
if ((ip->i_mode&IFMT) == IFDIR) {
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;
fp->f_data = (caddr_t)ip;
i = u.u_r.r_val1;
-#ifdef notdef
if (setjmp(&u.u_qsave)) {
if (u.u_error == 0)
u.u_error = EINTR;
closef(fp);
return;
}
-#endif
u.u_error = openi(ip, mode);
if (u.u_error == 0)
return;
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) {
+ case IFMT: /* used by badsect to flag bad sectors */
case IFCHR:
case IFBLK:
if (uap->dev) {
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()) {
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);
}
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--;
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)) {
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;
}
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);
{
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;
/*
}
if (ip->i_flag&ITEXT)
xrele(ip); /* try once to free text */
- if (dirremove()) {
+ if (dirremove(ndp)) {
ip->i_nlink--;
ip->i_flag |= ICHG;
}
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:
+ fp->f_offset += uap->off;
+ break;
+
+ case L_XTND:
+ fp->f_offset = uap->off + ((struct inode *)fp->f_data)->i_size;
+ break;
+
+ case L_SET:
+ fp->f_offset = uap->off;
+ break;
+
+ default:
+ u.u_error = EINVAL;
return;
- if (uap->sbase == L_INCR)
- uap->off += fp->f_offset;
- else if (uap->sbase == L_XTND)
- uap->off += ((struct inode *)fp->f_data)->i_size;
- fp->f_offset = uap->off;
- u.u_r.r_off = uap->off;
+ }
+ u.u_r.r_off = fp->f_offset;
}
/*
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;
stat()
{
- stat1(1);
+ stat1(FOLLOW);
}
/*
lstat()
{
- stat1(0);
+ stat1(NOFOLLOW);
}
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) statinode(ip, &sb);
+ (void) ino_stat(ip, &sb);
iput(ip);
u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
}
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) {
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);
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);
}
/*
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);
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);
}
/*
if (gid == -1)
gid = ip->i_gid;
#ifdef QUOTA
- if (ip->i_uid != uid) /* this just speeds things a little */
+ if (ip->i_uid == uid) /* this just speeds things a little */
change = 0;
else
change = ip->i_blocks;
#endif
}
-#ifndef NOCOMPAT
-/*
- * Set IUPD and IACC times on file.
- * Can't set ICHG.
- */
-outime()
-{
- register struct a {
- char *fname;
- time_t *tptr;
- } *uap = (struct a *)u.u_ap;
- register struct inode *ip;
- time_t tv[2];
- struct timeval tv0, tv1;
-
- if ((ip = owner(1)) == NULL)
- 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;
- tv0.tv_sec = tv[0]; tv0.tv_usec = 0;
- tv1.tv_sec = tv[1]; tv1.tv_usec = 0;
- iupdat(ip, &tv0, &tv1, 0);
- }
- iput(ip);
-}
-#endif
-
utimes()
{
register struct a {
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) {
update();
}
-/*
- * Apply an advisory lock on a file descriptor.
- */
-flock()
-{
- register struct a {
- int fd;
- int how;
- } *uap = (struct a *)u.u_ap;
- register struct file *fp;
- register int cmd, flags;
-
- fp = getinode(uap->fd);
- if (fp == NULL)
- return;
- cmd = uap->how;
- flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK);
- if (cmd&LOCK_UN) {
- if (flags == 0) {
- u.u_error = EINVAL;
- return;
- }
- funlocki((struct inode *)fp->f_data, flags);
- u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK);
- return;
- }
- /*
- * No reason to write lock a file we've already
- * write locked, similarly with a read lock.
- */
- if ((flags&UF_EXLOCK) && (cmd&LOCK_EX) ||
- (flags&UF_SHLOCK) && (cmd&LOCK_SH))
- return;
- u.u_pofile[uap->fd] =
- flocki((struct inode *)fp->f_data, u.u_pofile[uap->fd], cmd);
-}
-
/*
* Truncate a file given its path name.
*/
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))
return;
}
ip = (struct inode *)fp->f_data;
- ilock(ip);
+ ILOCK(ip);
itrunc(ip, uap->length);
- iunlock(ip);
+ IUNLOCK(ip);
}
/*
if (fp == NULL)
return;
ip = (struct inode *)fp->f_data;
- ilock(ip);
+ ILOCK(ip);
syncip(ip);
- iunlock(ip);
+ IUNLOCK(ip);
}
/*
*
* 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.
*
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);
u.u_error = EINVAL;
return;
}
+ ip->i_flag |= IRENAME;
oldparent = dp->i_number;
doingdirectory++;
}
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, 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
* 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, 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
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 {
* 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;
}
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;
* 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) {
/*
* 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);
ip->i_nlink--;
ip->i_flag |= ICHG;
irele(ip);
-done:
if (error)
u.u_error = error;
}
* 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
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
* 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
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) {
u.u_error = EEXIST;
return;
}
- dp = u.u_pdir;
+ dp = ndp->ni_pdir;
uap->dmode &= 0777;
uap->dmode |= IFDIR;
/*
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, 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;
{
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.
*/
* 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;
}
* 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;
/*
*/
ip->i_nlink -= 2;
itrunc(ip, (u_long)0);
+ cacheinval(ip);
out:
if (dp)
iput(dp);
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);
}
{
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;
}