From: Jeffrey Altman Date: Fri, 26 Dec 2008 23:26:09 +0000 (+0000) Subject: windows-afsd-rename-collision-20081226 X-Git-Tag: openafs-devel-1_5_61~647 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=9e2d9f6fa8862d33dfc7352c961f7945d0e04f4f windows-afsd-rename-collision-20081226 LICENSE MIT Do not permit cm_Rename() to rename an existing object such that it creates a case-insensitive name collision with another object. This change in behavior is consistent with the restrictions when creating new objects. This change prevents the explorer shell from getting confused when it creates a new folder. --- diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 2ab6c5b..c7a4cab 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -3307,12 +3307,47 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep cm_dirOp_t newDirOp; fschar_t * newNamep = NULL; int free_oldNamep = FALSE; + cm_scache_t *oldScp = NULL, *newScp = NULL; if (cOldNamep == NULL || cNewNamep == NULL || cm_ClientStrLen(cOldNamep) == 0 || cm_ClientStrLen(cNewNamep) == 0) return CM_ERROR_INVAL; + /* + * Before we permit the operation, make sure that we do not already have + * an object in the destination directory that has a case-insensitive match + * for this name UNLESS the matching object is the object we are renaming. + */ + code = cm_Lookup(oldDscp, cOldNamep, 0, userp, reqp, &oldScp); + if (code) { + osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p cOldName %S old name lookup failed", + oldDscp, osi_LogSaveStringW(afsd_logp, cOldNamep)); + goto done; + } + + code = cm_Lookup(newDscp, cNewNamep, CM_FLAG_CASEFOLD, userp, reqp, &newScp); + if (code == 0) { + /* found a matching object with the new name */ + if (cm_FidCmp(&oldScp->fid, &newScp->fid)) { + /* and they don't match so return an error */ + osi_Log2(afsd_logp, "cm_Rename newDscp 0x%p cNewName %S new name already exists", + newDscp, osi_LogSaveStringW(afsd_logp, cNewNamep)); + code = CM_ERROR_EXISTS; + } + cm_ReleaseSCache(newScp); + newScp = NULL; + } else if (code == CM_ERROR_AMBIGUOUS_FILENAME) { + code = CM_ERROR_EXISTS; + } else { + code = 0; + } + cm_ReleaseSCache(oldScp); + oldScp = NULL; + + if (code) + goto done; + if (oldNamep == NULL) { code = -1; #ifdef USE_BPLUS