SCCS-vsn: sys/ufs/ffs/ffs_vnops.c 7.63
SCCS-vsn: sys/ufs/ffs/ufs_vnops.c 7.63
SCCS-vsn: sys/ufs/lfs/lfs_vnops.c 7.63
SCCS-vsn: sys/ufs/ufs/ufs_vnops.c 7.63
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)ffs_vnops.c 7.62 (Berkeley) %G%
+ * @(#)ffs_vnops.c 7.63 (Berkeley) %G%
#include "lockf.h"
#include "quota.h"
#include "inode.h"
#include "lockf.h"
#include "quota.h"
#include "inode.h"
register struct inode *ip = VTOI(vp);
int error;
register struct inode *ip = VTOI(vp);
int error;
- if ((unsigned short)ip->i_nlink >= LINK_MAX)
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_link: no name");
+#endif
+ if ((unsigned short)ip->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
+#ifdef DIANOSTIC
+ if ((tndp->ni_nameiop & HASBUF) == 0 ||
+ (fndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_rename: no name");
+#endif
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
+ /*
+ * Check if just deleting a link name.
+ */
+ if (fndp->ni_vp == tndp->ni_vp) {
+ VOP_ABORTOP(tndp);
+ vput(tndp->ni_dvp);
+ vput(tndp->ni_vp);
+ vrele(fndp->ni_dvp);
+ if ((ip->i_mode&IFMT) == IFDIR) {
+ VOP_ABORTOP(fndp);
+ vrele(fndp->ni_vp);
+ return (EINVAL);
+ }
+ doingdirectory = 0;
+ goto unlinkit;
+ }
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
- register struct direct *d = &fndp->ni_dent;
-
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
- if ((d->d_namlen == 1 && d->d_name[0] == '.') || dp == ip ||
- fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
+ if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
+ dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
- tndp->ni_nameiop &= ~(MODMASK | OPMASK);
- tndp->ni_nameiop |= RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
- do {
- dp = VTOI(tndp->ni_dvp);
- if (xp != NULL)
- iput(xp);
- if (error = checkpath(ip, dp, tndp->ni_cred))
- goto out;
- if (error = namei(tndp, p))
- goto out;
- xp = NULL;
- if (tndp->ni_vp)
- xp = VTOI(tndp->ni_vp);
- } while (dp != VTOI(tndp->ni_dvp));
+ if (xp != NULL)
+ iput(xp);
+ if (error = checkpath(ip, dp, tndp->ni_cred))
+ goto out;
+ if ((tndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost to startdir");
+ if (error = lookup(tndp, p))
+ goto out;
+ dp = VTOI(tndp->ni_dvp);
+ xp = NULL;
+ if (tndp->ni_vp)
+ xp = VTOI(tndp->ni_vp);
}
/*
* 2) If target doesn't exist, link the target
}
/*
* 2) If target doesn't exist, link the target
- * Target must be empty if a directory
- * and have no links to it.
- * Also, insure source and target are
- * compatible (both directories, or both
- * not directories).
+ * Target must be empty if a directory and have no links
+ * to it. Also, ensure source and target are compatible
+ * (both directories, or both not directories).
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
/*
* 3) Unlink the source.
*/
/*
* 3) Unlink the source.
*/
- fndp->ni_nameiop &= ~(MODMASK | OPMASK);
- fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF;
- (void)namei(fndp, p);
+unlinkit:
+ fndp->ni_nameiop &= ~MODMASK;
+ fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
+ if ((fndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost from startdir");
+ (void) lookup(fndp, p);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_mkdir: no name");
+#endif
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
- * Must simulate part of maknode here
- * in order to acquire the inode, but
- * not have it entered in the parent
- * directory. The entry is made later
- * after writing "." and ".." entries out.
+ * Must simulate part of maknode here to acquire the inode, but
+ * not have it entered in the parent directory. The entry is made
+ * later after writing "." and ".." entries.
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
- * done. Nothing to do at the moment.
+ * done. If a buffer has been saved in anticipation of a CREATE, delete it.
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
+ if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("maknode: no name");
+#endif
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
return (error);
}
iput(pdir);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
goto bad;
if (error = direnter(ip, ndp))
goto bad;
goto bad;
if (error = direnter(ip, ndp))
goto bad;
+ if ((ndp->ni_nameiop & SAVESTART) == 0)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
*ipp = ip;
return (0);
iput(pdir);
*ipp = ip;
return (0);
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)ufs_vnops.c 7.62 (Berkeley) %G%
+ * @(#)ufs_vnops.c 7.63 (Berkeley) %G%
#include "lockf.h"
#include "quota.h"
#include "inode.h"
#include "lockf.h"
#include "quota.h"
#include "inode.h"
register struct inode *ip = VTOI(vp);
int error;
register struct inode *ip = VTOI(vp);
int error;
- if ((unsigned short)ip->i_nlink >= LINK_MAX)
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_link: no name");
+#endif
+ if ((unsigned short)ip->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
+#ifdef DIANOSTIC
+ if ((tndp->ni_nameiop & HASBUF) == 0 ||
+ (fndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_rename: no name");
+#endif
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
+ /*
+ * Check if just deleting a link name.
+ */
+ if (fndp->ni_vp == tndp->ni_vp) {
+ VOP_ABORTOP(tndp);
+ vput(tndp->ni_dvp);
+ vput(tndp->ni_vp);
+ vrele(fndp->ni_dvp);
+ if ((ip->i_mode&IFMT) == IFDIR) {
+ VOP_ABORTOP(fndp);
+ vrele(fndp->ni_vp);
+ return (EINVAL);
+ }
+ doingdirectory = 0;
+ goto unlinkit;
+ }
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
- register struct direct *d = &fndp->ni_dent;
-
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
- if ((d->d_namlen == 1 && d->d_name[0] == '.') || dp == ip ||
- fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
+ if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
+ dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
- tndp->ni_nameiop &= ~(MODMASK | OPMASK);
- tndp->ni_nameiop |= RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
- do {
- dp = VTOI(tndp->ni_dvp);
- if (xp != NULL)
- iput(xp);
- if (error = checkpath(ip, dp, tndp->ni_cred))
- goto out;
- if (error = namei(tndp, p))
- goto out;
- xp = NULL;
- if (tndp->ni_vp)
- xp = VTOI(tndp->ni_vp);
- } while (dp != VTOI(tndp->ni_dvp));
+ if (xp != NULL)
+ iput(xp);
+ if (error = checkpath(ip, dp, tndp->ni_cred))
+ goto out;
+ if ((tndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost to startdir");
+ if (error = lookup(tndp, p))
+ goto out;
+ dp = VTOI(tndp->ni_dvp);
+ xp = NULL;
+ if (tndp->ni_vp)
+ xp = VTOI(tndp->ni_vp);
}
/*
* 2) If target doesn't exist, link the target
}
/*
* 2) If target doesn't exist, link the target
- * Target must be empty if a directory
- * and have no links to it.
- * Also, insure source and target are
- * compatible (both directories, or both
- * not directories).
+ * Target must be empty if a directory and have no links
+ * to it. Also, ensure source and target are compatible
+ * (both directories, or both not directories).
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
/*
* 3) Unlink the source.
*/
/*
* 3) Unlink the source.
*/
- fndp->ni_nameiop &= ~(MODMASK | OPMASK);
- fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF;
- (void)namei(fndp, p);
+unlinkit:
+ fndp->ni_nameiop &= ~MODMASK;
+ fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
+ if ((fndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost from startdir");
+ (void) lookup(fndp, p);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_mkdir: no name");
+#endif
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
- * Must simulate part of maknode here
- * in order to acquire the inode, but
- * not have it entered in the parent
- * directory. The entry is made later
- * after writing "." and ".." entries out.
+ * Must simulate part of maknode here to acquire the inode, but
+ * not have it entered in the parent directory. The entry is made
+ * later after writing "." and ".." entries.
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
- * done. Nothing to do at the moment.
+ * done. If a buffer has been saved in anticipation of a CREATE, delete it.
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
+ if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("maknode: no name");
+#endif
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
return (error);
}
iput(pdir);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
goto bad;
if (error = direnter(ip, ndp))
goto bad;
goto bad;
if (error = direnter(ip, ndp))
goto bad;
+ if ((ndp->ni_nameiop & SAVESTART) == 0)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
*ipp = ip;
return (0);
iput(pdir);
*ipp = ip;
return (0);
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)lfs_vnops.c 7.62 (Berkeley) %G%
+ * @(#)lfs_vnops.c 7.63 (Berkeley) %G%
#include "lockf.h"
#include "quota.h"
#include "inode.h"
#include "lockf.h"
#include "quota.h"
#include "inode.h"
register struct inode *ip = VTOI(vp);
int error;
register struct inode *ip = VTOI(vp);
int error;
- if ((unsigned short)ip->i_nlink >= LINK_MAX)
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_link: no name");
+#endif
+ if ((unsigned short)ip->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
+#ifdef DIANOSTIC
+ if ((tndp->ni_nameiop & HASBUF) == 0 ||
+ (fndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_rename: no name");
+#endif
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
+ /*
+ * Check if just deleting a link name.
+ */
+ if (fndp->ni_vp == tndp->ni_vp) {
+ VOP_ABORTOP(tndp);
+ vput(tndp->ni_dvp);
+ vput(tndp->ni_vp);
+ vrele(fndp->ni_dvp);
+ if ((ip->i_mode&IFMT) == IFDIR) {
+ VOP_ABORTOP(fndp);
+ vrele(fndp->ni_vp);
+ return (EINVAL);
+ }
+ doingdirectory = 0;
+ goto unlinkit;
+ }
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
- register struct direct *d = &fndp->ni_dent;
-
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
- if ((d->d_namlen == 1 && d->d_name[0] == '.') || dp == ip ||
- fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
+ if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
+ dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
- tndp->ni_nameiop &= ~(MODMASK | OPMASK);
- tndp->ni_nameiop |= RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
- do {
- dp = VTOI(tndp->ni_dvp);
- if (xp != NULL)
- iput(xp);
- if (error = checkpath(ip, dp, tndp->ni_cred))
- goto out;
- if (error = namei(tndp, p))
- goto out;
- xp = NULL;
- if (tndp->ni_vp)
- xp = VTOI(tndp->ni_vp);
- } while (dp != VTOI(tndp->ni_dvp));
+ if (xp != NULL)
+ iput(xp);
+ if (error = checkpath(ip, dp, tndp->ni_cred))
+ goto out;
+ if ((tndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost to startdir");
+ if (error = lookup(tndp, p))
+ goto out;
+ dp = VTOI(tndp->ni_dvp);
+ xp = NULL;
+ if (tndp->ni_vp)
+ xp = VTOI(tndp->ni_vp);
}
/*
* 2) If target doesn't exist, link the target
}
/*
* 2) If target doesn't exist, link the target
- * Target must be empty if a directory
- * and have no links to it.
- * Also, insure source and target are
- * compatible (both directories, or both
- * not directories).
+ * Target must be empty if a directory and have no links
+ * to it. Also, ensure source and target are compatible
+ * (both directories, or both not directories).
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
/*
* 3) Unlink the source.
*/
/*
* 3) Unlink the source.
*/
- fndp->ni_nameiop &= ~(MODMASK | OPMASK);
- fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF;
- (void)namei(fndp, p);
+unlinkit:
+ fndp->ni_nameiop &= ~MODMASK;
+ fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
+ if ((fndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost from startdir");
+ (void) lookup(fndp, p);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_mkdir: no name");
+#endif
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
- * Must simulate part of maknode here
- * in order to acquire the inode, but
- * not have it entered in the parent
- * directory. The entry is made later
- * after writing "." and ".." entries out.
+ * Must simulate part of maknode here to acquire the inode, but
+ * not have it entered in the parent directory. The entry is made
+ * later after writing "." and ".." entries.
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
- * done. Nothing to do at the moment.
+ * done. If a buffer has been saved in anticipation of a CREATE, delete it.
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
+ if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("maknode: no name");
+#endif
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
return (error);
}
iput(pdir);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
goto bad;
if (error = direnter(ip, ndp))
goto bad;
goto bad;
if (error = direnter(ip, ndp))
goto bad;
+ if ((ndp->ni_nameiop & SAVESTART) == 0)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
*ipp = ip;
return (0);
iput(pdir);
*ipp = ip;
return (0);
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)ufs_vnops.c 7.62 (Berkeley) %G%
+ * @(#)ufs_vnops.c 7.63 (Berkeley) %G%
#include "lockf.h"
#include "quota.h"
#include "inode.h"
#include "lockf.h"
#include "quota.h"
#include "inode.h"
register struct inode *ip = VTOI(vp);
int error;
register struct inode *ip = VTOI(vp);
int error;
- if ((unsigned short)ip->i_nlink >= LINK_MAX)
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_link: no name");
+#endif
+ if ((unsigned short)ip->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
if (ndp->ni_dvp != vp)
ILOCK(ip);
ip->i_nlink++;
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
error = direnter(ip, ndp);
if (ndp->ni_dvp != vp)
IUNLOCK(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
vput(ndp->ni_dvp);
if (error) {
ip->i_nlink--;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
+#ifdef DIANOSTIC
+ if ((tndp->ni_nameiop & HASBUF) == 0 ||
+ (fndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_rename: no name");
+#endif
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
ip = VTOI(fndp->ni_vp);
+ /*
+ * Check if just deleting a link name.
+ */
+ if (fndp->ni_vp == tndp->ni_vp) {
+ VOP_ABORTOP(tndp);
+ vput(tndp->ni_dvp);
+ vput(tndp->ni_vp);
+ vrele(fndp->ni_dvp);
+ if ((ip->i_mode&IFMT) == IFDIR) {
+ VOP_ABORTOP(fndp);
+ vrele(fndp->ni_vp);
+ return (EINVAL);
+ }
+ doingdirectory = 0;
+ goto unlinkit;
+ }
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
ILOCK(ip);
if ((ip->i_mode&IFMT) == IFDIR) {
- register struct direct *d = &fndp->ni_dent;
-
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
- if ((d->d_namlen == 1 && d->d_name[0] == '.') || dp == ip ||
- fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
+ if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
+ dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_ABORTOP(tndp);
vput(tndp->ni_dvp);
if (tndp->ni_vp)
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
VOP_UNLOCK(fndp->ni_vp);
if (error)
goto bad;
- tndp->ni_nameiop &= ~(MODMASK | OPMASK);
- tndp->ni_nameiop |= RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
- do {
- dp = VTOI(tndp->ni_dvp);
- if (xp != NULL)
- iput(xp);
- if (error = checkpath(ip, dp, tndp->ni_cred))
- goto out;
- if (error = namei(tndp, p))
- goto out;
- xp = NULL;
- if (tndp->ni_vp)
- xp = VTOI(tndp->ni_vp);
- } while (dp != VTOI(tndp->ni_dvp));
+ if (xp != NULL)
+ iput(xp);
+ if (error = checkpath(ip, dp, tndp->ni_cred))
+ goto out;
+ if ((tndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost to startdir");
+ if (error = lookup(tndp, p))
+ goto out;
+ dp = VTOI(tndp->ni_dvp);
+ xp = NULL;
+ if (tndp->ni_vp)
+ xp = VTOI(tndp->ni_vp);
}
/*
* 2) If target doesn't exist, link the target
}
/*
* 2) If target doesn't exist, link the target
- * Target must be empty if a directory
- * and have no links to it.
- * Also, insure source and target are
- * compatible (both directories, or both
- * not directories).
+ * Target must be empty if a directory and have no links
+ * to it. Also, ensure source and target are compatible
+ * (both directories, or both not directories).
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
/*
* 3) Unlink the source.
*/
/*
* 3) Unlink the source.
*/
- fndp->ni_nameiop &= ~(MODMASK | OPMASK);
- fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF;
- (void)namei(fndp, p);
+unlinkit:
+ fndp->ni_nameiop &= ~MODMASK;
+ fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
+ if ((fndp->ni_nameiop & SAVESTART) == 0)
+ panic("ufs_rename: lost from startdir");
+ (void) lookup(fndp, p);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
if (fndp->ni_vp != NULL) {
xp = VTOI(fndp->ni_vp);
dp = VTOI(fndp->ni_dvp);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("ufs_mkdir: no name");
+#endif
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
dvp = ndp->ni_dvp;
dp = VTOI(dvp);
if ((unsigned short)dp->i_nlink >= LINK_MAX) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
iput(dp);
return (EMLINK);
}
dmode = vap->va_mode&0777;
dmode |= IFDIR;
/*
- * Must simulate part of maknode here
- * in order to acquire the inode, but
- * not have it entered in the parent
- * directory. The entry is made later
- * after writing "." and ".." entries out.
+ * Must simulate part of maknode here to acquire the inode, but
+ * not have it entered in the parent directory. The entry is made
+ * later after writing "." and ".." entries.
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
*/
if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
ifree(ip, ip->i_number, dmode);
iput(ip);
iput(dp);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
iput(ip);
} else
ndp->ni_vp = ITOV(ip);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(dp);
return (error);
}
iput(dp);
return (error);
}
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
- * done. Nothing to do at the moment.
+ * done. If a buffer has been saved in anticipation of a CREATE, delete it.
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
*/
/* ARGSUSED */
ufs_abortop(ndp)
struct nameidata *ndp;
{
+ if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
+#ifdef DIANOSTIC
+ if ((ndp->ni_nameiop & HASBUF) == 0)
+ panic("maknode: no name");
+#endif
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
*ipp = 0;
if ((mode & IFMT) == 0)
mode |= IFREG;
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
else
ipref = pdir->i_number;
if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
return (error);
}
iput(pdir);
return (error);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+ free(ndp->ni_pnbuf, M_NAMEI);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
ifree(ip, ip->i_number, mode);
iput(ip);
iput(pdir);
goto bad;
if (error = direnter(ip, ndp))
goto bad;
goto bad;
if (error = direnter(ip, ndp))
goto bad;
+ if ((ndp->ni_nameiop & SAVESTART) == 0)
+ FREE(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
*ipp = ip;
return (0);
iput(pdir);
*ipp = ip;
return (0);
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
+ free(ndp->ni_pnbuf, M_NAMEI);
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;
iput(pdir);
ip->i_nlink = 0;
ip->i_flag |= ICHG;