- } *uap = (struct a *)u.u_ap;
- register struct inode *ip, *xp, *dp;
- struct dirtemplate dirbuf;
- int doingdirectory = 0, oldparent = 0, newparent = 0;
- register struct nameidata *ndp = &u.u_nd;
- int error = 0;
-
- ndp->ni_nameiop = DELETE | LOCKPARENT;
- ndp->ni_segflg = UIO_USERSPACE;
- ndp->ni_dirp = uap->from;
- ip = namei(ndp);
- if (ip == NULL)
- return;
- dp = ndp->ni_pdir;
- if ((ip->i_mode&IFMT) == IFDIR) {
- register struct direct *d;
-
- 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) || (ip->i_flag & IRENAME)) {
- iput(dp);
- if (dp == ip)
- irele(ip);
- else
- iput(ip);
- u.u_error = EINVAL;
- return;
- }
- ip->i_flag |= IRENAME;
- oldparent = dp->i_number;
- doingdirectory++;
- }
- iput(dp);
-
- /*
- * 1) Bump link count while we're moving stuff
- * around. If we crash somewhere before
- * completing our work, the link count
- * may be wrong, but correctable.
- */
- ip->i_nlink++;
- ip->i_flag |= ICHG;
- iupdat(ip, &time, &time, 1);
- IUNLOCK(ip);
-
- /*
- * When the target exists, both the directory
- * and target inodes are returned locked.
- */
- 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 = ndp->ni_pdir;
- /*
- * If ".." must be changed (ie the directory gets a new
- * parent) then the source directory must not be in the
- * directory heirarchy above the target, as this would
- * orphan everything below the source directory. Also
- * the user must have write permission in the source so
- * as to be able to change "..". We must repeat the call
- * to namei, as the parent directory is unlocked by the
- * call to checkpath().
- */
- if (oldparent != dp->i_number)
- newparent = dp->i_number;
- if (doingdirectory && newparent) {
- if (access(ip, IWRITE))
- goto bad;
- do {
- dp = ndp->ni_pdir;
- if (xp != NULL)
- iput(xp);
- u.u_error = checkpath(ip, dp);
- if (u.u_error)
- goto out;
- xp = namei(ndp);
- if (u.u_error) {
- error = u.u_error;
- goto out;
- }
- } while (dp != ndp->ni_pdir);
+ } *uap;
+ int *retval;
+{
+ register struct vnode *tvp, *fvp, *tdvp;
+ struct nameidata fromnd, tond;
+ int error;
+
+ CHECKPOINTREF;
+ NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
+ uap->from, p);
+ if (error = namei(&fromnd))
+ return (error);
+ fvp = fromnd.ni_vp;
+ NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
+ UIO_USERSPACE, uap->to, p);
+ if (error = namei(&tond)) {
+ VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
+ vrele(fromnd.ni_dvp);
+ vrele(fvp);
+ goto out1;