Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/msdosfs/msdosfs_vnops.c
Show First 20 Lines • Show All 1,001 Lines • ▼ Show 20 Lines | abortit: | ||||
*/ | */ | ||||
if (ip->de_Attributes & ATTR_DIRECTORY) { | if (ip->de_Attributes & ATTR_DIRECTORY) { | ||||
/* | /* | ||||
* Avoid ".", "..", and aliases of "." for obvious reasons. | * Avoid ".", "..", and aliases of "." for obvious reasons. | ||||
*/ | */ | ||||
if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || | if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || | ||||
dp == ip || | dp == ip || | ||||
(fcnp->cn_flags & ISDOTDOT) || | (fcnp->cn_flags & ISDOTDOT) || | ||||
(tcnp->cn_flags & ISDOTDOT) || | (tcnp->cn_flags & ISDOTDOT)) { | ||||
(ip->de_flag & DE_RENAME)) { | |||||
VOP_UNLOCK(fvp); | VOP_UNLOCK(fvp); | ||||
error = EINVAL; | error = EINVAL; | ||||
goto abortit; | goto abortit; | ||||
} | } | ||||
ip->de_flag |= DE_RENAME; | |||||
doingdirectory++; | doingdirectory++; | ||||
} | } | ||||
/* | /* | ||||
* When the target exists, both the directory | * When the target exists, both the directory | ||||
* and target vnodes are returned locked. | * and target vnodes are returned locked. | ||||
*/ | */ | ||||
dp = VTODE(tdvp); | dp = VTODE(tdvp); | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | abortit: | ||||
fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; | fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; | ||||
if ((fcnp->cn_flags & SAVESTART) == 0) | if ((fcnp->cn_flags & SAVESTART) == 0) | ||||
panic("msdosfs_rename: lost from startdir"); | panic("msdosfs_rename: lost from startdir"); | ||||
if (!newparent) | if (!newparent) | ||||
VOP_UNLOCK(tdvp); | VOP_UNLOCK(tdvp); | ||||
if (relookup(fdvp, &fvp, fcnp) == 0) | if (relookup(fdvp, &fvp, fcnp) == 0) | ||||
vrele(fdvp); | vrele(fdvp); | ||||
if (fvp == NULL) { | if (fvp == NULL) { | ||||
/* | |||||
* From name has disappeared. | |||||
*/ | |||||
if (doingdirectory) | |||||
panic("rename: lost dir entry"); | |||||
if (newparent) | if (newparent) | ||||
VOP_UNLOCK(tdvp); | VOP_UNLOCK(tdvp); | ||||
vrele(tdvp); | vrele(tdvp); | ||||
vrele(ap->a_fvp); | vrele(ap->a_fvp); | ||||
/* | /* | ||||
* fdvp may be locked and has a reference. We need to | * fdvp may be locked and has a reference. We need to | ||||
* release the lock and reference, unless to and from | * release the lock and reference, unless to and from | ||||
* directories are the same. In that case it is already | * directories are the same. In that case it is already | ||||
* unlocked. | * unlocked. | ||||
*/ | */ | ||||
if (tdvp != fdvp) | if (tdvp != fdvp) | ||||
vput(fdvp); | vput(fdvp); | ||||
return 0; | return 0; | ||||
} | } | ||||
xp = VTODE(fvp); | xp = VTODE(fvp); | ||||
zp = VTODE(fdvp); | zp = VTODE(fdvp); | ||||
from_diroffset = zp->de_fndoffset; | from_diroffset = zp->de_fndoffset; | ||||
/* | /* | ||||
* Ensure that the directory entry still exists and has not | * Ensure that the directory entry still exists and has not | ||||
* changed till now. If the source is a file the entry may | * changed till now. If the source is a file the entry may | ||||
* have been unlinked or renamed. In either case there is | * have been unlinked or renamed. In either case there is | ||||
* no further work to be done. If the source is a directory | * no further work to be done. | ||||
* then it cannot have been rmdir'ed or renamed; this is | |||||
* prohibited by the DE_RENAME flag. | |||||
*/ | */ | ||||
if (xp != ip) { | if (xp != ip) { | ||||
if (doingdirectory) | |||||
panic("rename: lost dir entry"); | |||||
if (newparent) | if (newparent) | ||||
VOP_UNLOCK(fdvp); | VOP_UNLOCK(fdvp); | ||||
vrele(ap->a_fvp); | vrele(ap->a_fvp); | ||||
ip = NULL; | |||||
xp = NULL; | xp = NULL; | ||||
} else { | } else { | ||||
vrele(fvp); | vrele(fvp); | ||||
xp = NULL; | xp = NULL; | ||||
/* | /* | ||||
* First write a new entry in the destination | * First write a new entry in the destination | ||||
* directory and mark the entry in the source directory | * directory and mark the entry in the source directory | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | if (xp != ip) { | ||||
if (newparent) | if (newparent) | ||||
VOP_UNLOCK(fdvp); | VOP_UNLOCK(fdvp); | ||||
} | } | ||||
/* | /* | ||||
* If we moved a directory to a new parent directory, then we must | * If we moved a directory to a new parent directory, then we must | ||||
* fixup the ".." entry in the moved directory. | * fixup the ".." entry in the moved directory. | ||||
*/ | */ | ||||
if (doingdirectory && newparent) { | if (ip != NULL && doingdirectory && newparent) { | ||||
cn = ip->de_StartCluster; | cn = ip->de_StartCluster; | ||||
if (cn == MSDOSFSROOT) { | if (cn == MSDOSFSROOT) { | ||||
/* this should never happen */ | /* this should never happen */ | ||||
panic("msdosfs_rename(): updating .. in root directory?"); | panic("msdosfs_rename(): updating .. in root directory?"); | ||||
} else | } else | ||||
bn = cntobn(pmp, cn); | bn = cntobn(pmp, cn); | ||||
error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, | error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, | ||||
NOCRED, &bp); | NOCRED, &bp); | ||||
Show All 27 Lines | abortit: | ||||
*/ | */ | ||||
cache_purge(fvp); | cache_purge(fvp); | ||||
VOP_UNLOCK(fvp); | VOP_UNLOCK(fvp); | ||||
bad: | bad: | ||||
if (xp) | if (xp) | ||||
vput(tvp); | vput(tvp); | ||||
vput(tdvp); | vput(tdvp); | ||||
out: | out: | ||||
ip->de_flag &= ~DE_RENAME; | |||||
vrele(fdvp); | vrele(fdvp); | ||||
vrele(fvp); | vrele(fvp); | ||||
return (error); | return (error); | ||||
} | } | ||||
static struct { | static struct { | ||||
struct direntry dot; | struct direntry dot; | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | msdosfs_rmdir(struct vop_rmdir_args *ap) | ||||
/* | /* | ||||
* Verify the directory is empty (and valid). | * Verify the directory is empty (and valid). | ||||
* (Rmdir ".." won't be valid since | * (Rmdir ".." won't be valid since | ||||
* ".." will contain a reference to | * ".." will contain a reference to | ||||
* the current directory and thus be | * the current directory and thus be | ||||
* non-empty.) | * non-empty.) | ||||
*/ | */ | ||||
error = 0; | error = 0; | ||||
if (!dosdirempty(ip) || ip->de_flag & DE_RENAME) { | if (!dosdirempty(ip)) { | ||||
error = ENOTEMPTY; | error = ENOTEMPTY; | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* Delete the entry from the directory. For dos filesystems this | * Delete the entry from the directory. For dos filesystems this | ||||
* gets rid of the directory entry on disk, the in memory copy | * gets rid of the directory entry on disk, the in memory copy | ||||
* still exists but the de_refcnt is <= 0. This prevents it from | * still exists but the de_refcnt is <= 0. This prevents it from | ||||
* being found by deget(). When the vput() on dep is done we give | * being found by deget(). When the vput() on dep is done we give | ||||
▲ Show 20 Lines • Show All 535 Lines • Show Last 20 Lines |