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