fixing handling of delete_on_close

file can be opened with a delete_on_close flag set. this file can be
opened again as long as opens specify "file_share_delete" access.
after receiving the cleanup irp, the handle enters "delete-pending"
state. opens in this state must fail with status_delete_pending.
file query for standard_info.delete_pending now should return true.

calling setattr with disposition=1 puts the file in "delete-pending"
state.

calling setattr with dispositon=0 will clear delete_on_close only
if file is in "delete-pending" state. otherwise, setattr is ignored.
This commit is contained in:
Olga Kornievskaia 2012-03-23 14:01:48 -04:00 committed by unknown
parent 7a8861699f
commit 0020104b95

View file

@ -401,6 +401,7 @@ typedef struct _NFS41_FCB {
FILE_BASIC_INFORMATION BasicInfo;
FILE_STANDARD_INFORMATION StandardInfo;
BOOLEAN Renamed;
BOOLEAN DeletePending;
DWORD mode;
ULONGLONG changeattr;
} NFS41_FCB, *PNFS41_FCB;
@ -3373,6 +3374,7 @@ NTSTATUS nfs41_Create(
__notnull PMRX_FCB Fcb = RxContext->pFcb;
__notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
PNFS41_FOBX nfs41_fobx = NULL;
BOOLEAN oldDeletePending = nfs41_fcb->StandardInfo.DeletePending;
#ifdef ENABLE_TIMINGS
LARGE_INTEGER t1, t2;
t1 = KeQueryPerformanceCounter(NULL);
@ -3415,17 +3417,24 @@ NTSTATUS nfs41_Create(
goto out;
}
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
* If FILE_SHARE_DELETE flag is not specified, but the file or device has been
* opened for delete access, the function fails.
/* if FCB was marked for deletion and opened multiple times, as soon
* as first close happen, FCB transitions into delete_pending state
* no more opens allowed
*/
if (Fcb->OpenCount && nfs41_fcb->StandardInfo.DeletePending &&
!(params.ShareAccess & FILE_SHARE_DELETE)) {
DbgP("File opened already and marked for deletion\n");
if (Fcb->OpenCount && nfs41_fcb->DeletePending) {
status = STATUS_DELETE_PENDING;
goto out;
}
/* ms-fsa: 3.1.5.1.2.1 page 68 */
if (Fcb->OpenCount && nfs41_fcb->StandardInfo.DeletePending &&
!(params.ShareAccess & FILE_SHARE_DELETE) &&
(params.DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA |
FILE_WRITE_DATA | FILE_APPEND_DATA))) {
status = STATUS_SHARING_VIOLATION;
goto out;
}
if (isFilenameTooLong(SrvOpen->pAlreadyPrefixedName, pVNetRootContext)) {
status = STATUS_OBJECT_NAME_INVALID;
goto out;
@ -3574,10 +3583,6 @@ NTSTATUS nfs41_Create(
if (Fcb->OpenCount == 0 ||
(Fcb->OpenCount > 0 &&
nfs41_fcb->changeattr != entry->u.Open.changeattr)) {
#ifdef DEBUG_OPEN
print_basic_info(1, &entry->u.Open.binfo);
print_std_info(1, &entry->u.Open.sinfo);
#endif
RtlCopyMemory(&nfs41_fcb->BasicInfo, &entry->u.Open.binfo,
sizeof(entry->u.Open.binfo));
RtlCopyMemory(&nfs41_fcb->StandardInfo, &entry->u.Open.sinfo,
@ -3585,6 +3590,9 @@ NTSTATUS nfs41_Create(
nfs41_fcb->mode = entry->u.Open.mode;
nfs41_fcb->changeattr = entry->u.Open.changeattr;
nfs41_fcb->Flags = FCB_BASIC_INFO_CACHED | FCB_STANDARD_INFO_CACHED;
if (((params.CreateOptions & FILE_DELETE_ON_CLOSE) &&
!pVNetRootContext->read_only) || oldDeletePending)
nfs41_fcb->StandardInfo.DeletePending = TRUE;
RxFormInitPacket(InitPacket,
&entry->u.Open.binfo.FileAttributes,
@ -3606,13 +3614,11 @@ NTSTATUS nfs41_Create(
&InitPacket);
}
#ifdef DEBUG_OPEN
else {
else
DbgP("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
if (nfs41_fcb->Flags) {
print_basic_info(1, &nfs41_fcb->BasicInfo);
print_std_info(1, &nfs41_fcb->StandardInfo);
}
}
print_basic_info(1, &nfs41_fcb->BasicInfo);
print_std_info(1, &nfs41_fcb->StandardInfo);
#endif
if (Fcb->OpenCount > 0 &&
@ -3848,6 +3854,8 @@ NTSTATUS nfs41_CloseSrvOpen(
entry->u.Close.srv_open = SrvOpen;
entry->u.Close.filename = SrvOpen->pAlreadyPrefixedName;
if (nfs41_fcb->StandardInfo.DeletePending)
nfs41_fcb->DeletePending = TRUE;
if (!RxContext->pFcb->OpenCount ||
(nfs41_fcb->StandardInfo.DeletePending &&
nfs41_fcb->StandardInfo.Directory))
@ -4915,6 +4923,7 @@ NTSTATUS nfs41_QueryFileInformation(
std_info->EndOfFile.QuadPart =
nfs41_fcb->StandardInfo.EndOfFile.QuadPart;
}
std_info->DeletePending = nfs41_fcb->DeletePending;
}
#endif
if (nfs41_fcb->StandardInfo.DeletePending)
@ -5061,6 +5070,12 @@ NTSTATUS nfs41_SetFileInformation(
PFILE_DISPOSITION_INFORMATION dinfo =
(PFILE_DISPOSITION_INFORMATION)RxContext->Info.Buffer;
if (dinfo->DeleteFile) {
if (nfs41_fcb->DeletePending) {
status = STATUS_DELETE_PENDING;
goto out;
}
nfs41_fcb->DeletePending = TRUE;
// we can delete directories right away
if (nfs41_fcb->StandardInfo.Directory)
break;
@ -5075,6 +5090,14 @@ NTSTATUS nfs41_SetFileInformation(
nfs41_fcb->Renamed = TRUE;
break;
}
} else {
/* section 4.3.3 of [FSBO]
* "file system behavior in the microsoft windows environment"
*/
if (nfs41_fcb->DeletePending) {
nfs41_fcb->DeletePending = 0;
nfs41_fcb->StandardInfo.DeletePending = 0;
}
}
status = STATUS_SUCCESS;
goto out;