From 4017b235dbd3351a7ef4e6ffa9cfd8925e8543d8 Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Wed, 14 Mar 2012 13:30:55 -0400 Subject: [PATCH] handling creating new file for no access windows can send a create irp with dispostion representing creation of the file and specify DesiredAccess of 0. we were treating no data access as lookup but in this case, we still need to create a file. so send an open with a read access and request no delegation to be returned. --- daemon/open.c | 20 +++++++++++++++++--- sys/nfs41_driver.c | 22 +++++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/daemon/open.c b/daemon/open.c index 2a7fe84..39c6742 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -303,7 +303,11 @@ static BOOLEAN open_for_attributes(uint32_t type, ULONG access_mask, if ((access_mask & FILE_READ_DATA) || (access_mask & FILE_WRITE_DATA) || (access_mask & FILE_APPEND_DATA) || - (access_mask & FILE_EXECUTE)) + (access_mask & FILE_EXECUTE) || + disposition == FILE_CREATE || + disposition == FILE_OVERWRITE_IF || + disposition == FILE_SUPERSEDE || + disposition == FILE_OPEN_IF) return FALSE; else { dprintf(1, "Open call that wants to manage attributes\n"); @@ -363,7 +367,7 @@ static int map_disposition_2_nfsopen(ULONG disposition, int in_status, bool_t pe } static void map_access_2_allowdeny(ULONG access_mask, ULONG access_mode, - uint32_t *allow, uint32_t *deny) + ULONG disposition, uint32_t *allow, uint32_t *deny) { if ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES)) && @@ -374,6 +378,16 @@ static void map_access_2_allowdeny(ULONG access_mask, ULONG access_mode, else if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES)) *allow = OPEN4_SHARE_ACCESS_WRITE; + /* if we are creating a file and no data access is specified, then + * do an open and request no delegations. example open with share access 0 + * and share deny 0 (ie deny_both). + */ + if ((disposition == FILE_CREATE || disposition == FILE_OPEN_IF || + disposition == FILE_OVERWRITE_IF || disposition == FILE_SUPERSEDE) && + !(access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA | + FILE_WRITE_ATTRIBUTES | FILE_READ_DATA | FILE_EXECUTE))) + *allow = OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_NO_DELEG; + #define FIX_ALLOW_DENY_WIN2NFS_CONVERSION #ifdef FIX_ALLOW_DENY_WIN2NFS_CONVERSION if ((access_mode & FILE_SHARE_READ) && @@ -570,7 +584,7 @@ static int handle_open(nfs41_upcall *upcall) uint32_t create = 0, createhowmode = 0; map_access_2_allowdeny(args->access_mask, args->access_mode, - &state->share_access, &state->share_deny); + args->disposition, &state->share_access, &state->share_deny); status = map_disposition_2_nfsopen(args->disposition, status, state->session->flags & CREATE_SESSION4_FLAG_PERSIST, &create, &createhowmode, &upcall->last_error); diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 8acb735..bea18fd 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -3247,6 +3247,15 @@ BOOLEAN isDataAccess( return FALSE; } +BOOLEAN isOpen2Create( + ULONG disposition) +{ + if (disposition == FILE_CREATE || disposition == FILE_OPEN_IF || + disposition == FILE_OVERWRITE_IF || disposition == FILE_SUPERSEDE) + return TRUE; + return FALSE; +} + NTSTATUS map_open_errors( DWORD status, USHORT len) @@ -3357,6 +3366,17 @@ 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->OpenCount && nfs41_fcb->StandardInfo.DeletePending && + !(params.ShareAccess & FILE_SHARE_DELETE)) { + DbgP("File opened already and marked for deletion\n"); + status = STATUS_DELETE_PENDING; + goto out; + } + #if defined(STORE_MOUNT_SEC_CONTEXT) && defined (USE_MOUNT_SEC_CONTEXT) status = nfs41_UpcallCreate(NFS41_OPEN, &pVNetRootContext->mount_sec_ctx, #else @@ -3374,7 +3394,7 @@ NTSTATUS nfs41_Create( entry->u.Open.disp = params.Disposition; entry->u.Open.copts = params.CreateOptions; entry->u.Open.srv_open = SrvOpen; - if (isDataAccess(params.DesiredAccess)) + if (isDataAccess(params.DesiredAccess) || isOpen2Create(params.Disposition)) { entry->u.Open.open_owner_id = InterlockedIncrement(&open_owner_id); // if we are creating a file check if nfsv3attributes were passed in if (params.Disposition != FILE_OPEN && params.Disposition != FILE_OVERWRITE) {