}
/* return success if we can open this file in this mode */
-long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
- unsigned int createDisp, cm_user_t *userp, cm_req_t *reqp,
+long cm_CheckNTOpen(cm_scache_t *scp,
+ unsigned int desiredAccess,
+ unsigned int shareAccess,
+ unsigned int createDisp,
+ afs_offs_t process_id,
+ afs_offs_t handle_id,
+ cm_user_t *userp, cm_req_t *reqp,
cm_lock_data_t **ldpp)
{
long rights;
long code = 0;
+ afs_uint16 session_id;
osi_assertx(ldpp != NULL, "null cm_lock_data_t");
*ldpp = NULL;
+ /* compute the session id */
+ if (reqp->flags & CM_REQ_SOURCE_SMB)
+ session_id = CM_SESSION_SMB;
+ else if (reqp->flags & CM_REQ_SOURCE_REDIR)
+ session_id = CM_SESSION_IFS;
+ else
+ session_id = CM_SESSION_CMINT;
+
/* Ignore the SYNCHRONIZE privilege */
desiredAccess &= ~SYNCHRONIZE;
if (desiredAccess == DELETE)
goto done_2;
+ /* Always allow reading attributes (Hidden, System, Readonly, ...) */
+ if (desiredAccess == FILE_READ_ATTRIBUTES)
+ goto done_2;
+
if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
rights |= (scp->fileType == CM_SCACHETYPE_DIRECTORY ? PRSFS_LOOKUP : PRSFS_READ);
code = CM_ERROR_NOACCESS;
if (code == 0 &&
- ((rights & PRSFS_WRITE) || (rights & PRSFS_READ)) &&
- scp->fileType == CM_SCACHETYPE_FILE) {
+ !(shareAccess & FILE_SHARE_WRITE) &&
+ ((rights & PRSFS_WRITE) || (rights & PRSFS_READ)) &&
+ scp->fileType == CM_SCACHETYPE_FILE) {
cm_key_t key;
unsigned int sLockType;
LARGE_INTEGER LOffset, LLength;
/* Check if there's some sort of lock on the file at the
moment. */
- key = cm_GenerateKey(CM_SESSION_CMINT,0,0);
if (rights & PRSFS_WRITE)
sLockType = 0;
else
sLockType = LOCKING_ANDX_SHARED_LOCK;
+ key = cm_GenerateKey(session_id, process_id, 0);
+
/* single byte lock at offset 0x0100 0000 0000 0000 */
LOffset.HighPart = CM_FLSHARE_OFFSET_HIGH;
LOffset.LowPart = CM_FLSHARE_OFFSET_LOW;
code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, reqp, NULL);
if (code == 0) {
- (*ldpp) = (cm_lock_data_t *)malloc(sizeof(cm_lock_data_t));
- if (!*ldpp) {
- code = ENOMEM;
- goto _done;
- }
+ (*ldpp) = (cm_lock_data_t *)malloc(sizeof(cm_lock_data_t));
+ if (!*ldpp) {
+ code = ENOMEM;
+ goto _done;
+ }
- (*ldpp)->key = key;
- (*ldpp)->sLockType = sLockType;
- (*ldpp)->LOffset.HighPart = LOffset.HighPart;
- (*ldpp)->LOffset.LowPart = LOffset.LowPart;
- (*ldpp)->LLength.HighPart = LLength.HighPart;
- (*ldpp)->LLength.LowPart = LLength.LowPart;
+ (*ldpp)->key = key;
+ (*ldpp)->sLockType = sLockType;
+ (*ldpp)->LOffset.HighPart = LOffset.HighPart;
+ (*ldpp)->LOffset.LowPart = LOffset.LowPart;
+ (*ldpp)->LLength.HighPart = LLength.HighPart;
+ (*ldpp)->LLength.LowPart = LLength.LowPart;
} else {
- /* In this case, we allow the file open to go through even
- though we can't enforce mandatory locking on the
- file. */
+ /*
+ * In this case, we allow the file open to go through even
+ * though we can't enforce mandatory locking on the
+ * file. */
if (code == CM_ERROR_NOACCESS &&
- !(rights & PRSFS_WRITE))
+ !(rights & PRSFS_WRITE))
code = 0;
else {
- if (code == CM_ERROR_LOCK_NOT_GRANTED)
- code = CM_ERROR_SHARING_VIOLATION;
- }
+ if (code == CM_ERROR_LOCK_NOT_GRANTED)
+ code = CM_ERROR_SHARING_VIOLATION;
+ }
}
} else if (code != 0) {
goto _done;
extern long cm_CheckNTOpenDone(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
cm_lock_data_t ** ldpp)
{
- osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, *ldpp);
+ osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, ldpp ? *ldpp : 0);
lock_ObtainWrite(&scp->rw);
- if (*ldpp) {
+ if (ldpp && *ldpp) {
cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength,
(*ldpp)->key, 0, userp, reqp);
free(*ldpp);
return code;
}
-int cm_ExpandSysName(clientchar_t *inp, clientchar_t *outp, long outSizeCch, unsigned int index)
+int cm_ExpandSysName(cm_req_t * reqp, clientchar_t *inp, clientchar_t *outp, long outSizeCch, unsigned int index)
{
clientchar_t *tp;
int prefixCount;
+#ifdef _WIN64
+ int use_sysname64 = 0;
+
+ if (cm_sysName64Count > 0 && reqp && (reqp->flags & CM_REQ_WOW64) && (reqp->flags & CM_REQ_SOURCE_REDIR))
+ use_sysname64 = 1;
+#endif
tp = cm_ClientStrRChr(inp, '@');
if (tp == NULL)
if (outp == NULL)
return 1;
+#ifdef _WIN64
+ if (use_sysname64 && index >= cm_sysName64Count)
+ return -1;
+ else
+#endif
if (index >= cm_sysNameCount)
return -1;
prefixCount = (int)(tp - inp);
cm_ClientStrCpyN(outp, outSizeCch, inp, prefixCount); /* copy out "a." from "a.@sys" */
- outp[prefixCount] = 0; /* null terminate the "a." */
- cm_ClientStrCat(outp, outSizeCch, cm_sysNameList[index]);/* append i386_nt40 */
+ outp[prefixCount] = 0; /* null terminate the "a." */
+#ifdef _WIN64
+ if (use_sysname64)
+ cm_ClientStrCat(outp, outSizeCch, cm_sysName64List[index]);
+ else
+#endif
+ cm_ClientStrCat(outp, outSizeCch, cm_sysNameList[index]);
+
return 1;
}
return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outScpp);
}
- if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) {
+ if (cm_ExpandSysName(reqp, namep, NULL, 0, 0) > 0) {
for ( sysNameIndex = 0; sysNameIndex < MAXNUMSYSNAMES; sysNameIndex++) {
- code = cm_ExpandSysName(namep, tname, lengthof(tname), sysNameIndex);
+ code = cm_ExpandSysName(reqp, namep, tname, lengthof(tname), sysNameIndex);
if (code > 0) {
code = cm_LookupInternal(dscp, tname, flags, userp, reqp, &scp);
#ifdef DEBUG_REFCOUNT
cm_dnlcRemove(dscp, cnamep);
if (code == 0) {
cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
+ if (RDR_Initialized &&
+ scp->fileType != CM_SCACHETYPE_FILE && scp->fileType != CM_SCACHETYPE_DIRECTORY)
+ RDR_InvalidateObject(dscp->fid.cell, dscp->fid.volume, dscp->fid.vnode,
+ dscp->fid.unique, dscp->fid.hash,
+ dscp->fileType, AFS_INVALIDATE_DATA_VERSION);
} else if (code == CM_ERROR_NOSUCHFILE) {
/* windows would not have allowed the request to delete the file
* if it did not believe the file existed. therefore, we must
}
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
+ if (RDR_Initialized && !(reqp->flags & CM_REQ_SOURCE_REDIR) &&
+ !RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode,
+ scp->fid.unique, scp->fid.hash,
+ scp->fileType, AFS_INVALIDATE_DELETED))
+ buf_ClearRDRFlag(scp, "unlink");
}
}
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
- if (cm_ExpandSysName(cnamep, NULL, 0, 0)) {
+ if (cm_ExpandSysName(NULL, cnamep, NULL, 0, 0)) {
return CM_ERROR_ATSYS;
}
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
- if (cm_ExpandSysName(cnamep, NULL, 0, 0)) {
+ if (cm_ExpandSysName(NULL, cnamep, NULL, 0, 0)) {
return CM_ERROR_ATSYS;
}
lock_ObtainWrite(&dscp->rw);
if (code == 0) {
cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
+ if (RDR_Initialized)
+ RDR_InvalidateObject(dscp->fid.cell, dscp->fid.volume, dscp->fid.vnode,
+ dscp->fid.unique, dscp->fid.hash,
+ dscp->fileType, AFS_INVALIDATE_DATA_VERSION);
}
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
lock_ReleaseWrite(&dscp->rw);
cm_RemoveSCacheFromHashTable(scp);
lock_ReleaseWrite(&cm_scacheLock);
lock_ReleaseWrite(&scp->rw);
+ if (RDR_Initialized && !(reqp->flags & CM_REQ_SOURCE_REDIR) &&
+ !RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode,
+ scp->fid.unique, scp->fid.hash,
+ scp->fileType, AFS_INVALIDATE_DELETED))
+ buf_ClearRDRFlag(scp, "rmdir");
}
}
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));
+ /* Case sensitive lookup. If this succeeds we are done. */
+ code = cm_Lookup(newDscp, cNewNamep, 0, userp, reqp, &newScp);
+ if (code) {
+ /*
+ * Case insensitive lookup. If this succeeds, it could have found the
+ * same file with a name that differs only by case or it could be a
+ * different file entirely.
+ */
+ 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 {
+ /* The target does not exist. Clear the error and perform the rename. */
+ code = 0;
}
- cm_ReleaseSCache(newScp);
- newScp = NULL;
- } else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
- code = CM_ERROR_EXISTS;
- } else {
- code = 0;
}
/* Check for RO volume */
cm_DiscardSCache(oldScp);
lock_ReleaseWrite(&oldScp->rw);
+ if (RDR_Initialized)
+ RDR_InvalidateObject(oldScp->fid.cell, oldScp->fid.volume, oldScp->fid.vnode, oldScp->fid.unique,
+ oldScp->fid.hash, oldScp->fileType, AFS_INVALIDATE_CALLBACK);
done:
if (oldScp)
cm_ReleaseSCache(oldScp);
AFSVolSync volSync;
afs_uint32 reqflags = reqp->flags;
+ osi_Log2(afsd_logp, "CALL SetLock scp 0x%p for lock %d", scp, lockType);
+
+ if ((lockType != LOCKING_ANDX_SHARED_LOCK && scp->fsLockCount != 0) ||
+ (lockType == LOCKING_ANDX_SHARED_LOCK && scp->fsLockCount < 0))
+ {
+ code = CM_ERROR_LOCK_NOT_GRANTED;
+ osi_Log2(afsd_logp, "CALL SetLock FAILURE, fsLockCount %d code 0x%x", scp->fsLockCount, code);
+ return code;
+ }
+
memset(&volSync, 0, sizeof(volSync));
tfid.Volume = scp->fid.volume;
tfid.Unique = scp->fid.unique;
cfid = scp->fid;
- osi_Log2(afsd_logp, "CALL SetLock scp 0x%p for lock %d", scp, lockType);
-
reqp->flags |= CM_REQ_NORETRY;
lock_ReleaseWrite(&scp->rw);
fileLock->flags |= CM_FILELOCK_FLAG_DELETED;
+ cm_ReleaseUser(fileLock->userp);
+ cm_ReleaseSCacheNoLock(scp);
+
+ fileLock->userp = NULL;
+ fileLock->scp = NULL;
+
n_unlocks++;
}
}
return 0;
}
- osi_Log1(afsd_logp, "cm_UnlockByKey done with %d locks", n_unlocks);
-
+ code = cm_IntUnlock(scp, userp, reqp);
osi_Log1(afsd_logp, "cm_UnlockByKey code 0x%x", code);
+
osi_Log4(afsd_logp, " Leaving scp with excl[%d], shared[%d], client[%d], serverLock[%d]",
scp->exclusiveLocks, scp->sharedLocks, scp->clientLocks,
(int)(signed char) scp->serverLock);
return code;
}
+/* Called with scp->rw held */
long cm_Unlock(cm_scache_t *scp,
unsigned char sLockType,
LARGE_INTEGER LOffset, LARGE_INTEGER LLength,
}
fileLock->flags |= CM_FILELOCK_FLAG_DELETED;
+
+ if (userp != NULL) {
+ cm_ReleaseUser(fileLock->userp);
+ } else {
+ userp = fileLock->userp;
+ release_userp = TRUE;
+ }
+ cm_ReleaseSCacheNoLock(scp);
+ fileLock->userp = NULL;
+ fileLock->scp = NULL;
lock_ReleaseWrite(&cm_scacheLock);
+ code = cm_IntUnlock(scp, userp, reqp);
+
if (release_userp) {
cm_ReleaseUser(userp);
release_userp = FALSE;
fileLock->userp = NULL;
fileLock->scp = NULL;
- lock_ReleaseWrite(&cm_scacheLock);
- lock_ObtainWrite(&scp->rw);
- code = cm_IntUnlock(scp, userp, &req);
- lock_ReleaseWrite(&scp->rw);
-
- cm_ReleaseUser(fileLock->userp);
- lock_ObtainWrite(&cm_scacheLock);
- cm_ReleaseSCacheNoLock(scp);
+ if (scp && userp) {
+ lock_ReleaseWrite(&cm_scacheLock);
+ lock_ObtainWrite(&scp->rw);
+ code = cm_IntUnlock(scp, userp, &req);
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseUser(userp);
+ lock_ObtainWrite(&cm_scacheLock);
+ cm_ReleaseSCacheNoLock(scp);
+ }
osi_QRemove(&cm_allFileLocks, q);
cm_PutFileLock(fileLock);
return code;
}
-cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint16 file_id)
+cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint64 file_id)
{
cm_key_t key;
int cm_KeyEquals(cm_key_t *k1, cm_key_t *k2, int flags)
{
return (k1->session_id == k2->session_id) && (k1->file_id == k2->file_id) &&
- ((flags & CM_UNLOCK_BY_FID) || (k1->process_id == k2->process_id));
+ ((flags & CM_UNLOCK_FLAG_BY_FID) || (k1->process_id == k2->process_id));
}
void cm_ReleaseAllLocks(void)