From de7ba27c1d154695b0a840f5a81cd5f17619e945 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 26 Dec 2008 23:26:18 +0000 Subject: [PATCH] DEVEL15-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. (cherry picked from commit 9e2d9f6fa8862d33dfc7352c961f7945d0e04f4f) --- src/WINNT/afsd/cm_vnodeops.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 2ab6c5b0c5..c7a4cabf41 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