NTSTATUS PvfsCreateDirDoSysOpen( IN PVOID pContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_CREATE pCreateContext = (PPVFS_PENDING_CREATE)pContext; PIRP pIrp = pCreateContext->pIrpContext->pIrp; IRP_ARGS_CREATE Args = pIrp->Args.Create; int fd = -1; int unixFlags = 0; PIO_CREATE_SECURITY_CONTEXT pSecCtx = Args.SecurityContext; FILE_CREATE_RESULT CreateResult = 0; IO_MATCH_FILE_SPEC FileSpec = {0}; WCHAR wszPattern[2] = {L'*', 0x0 }; PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcess = NULL; PBOOLEAN pbEnableAbe = NULL; ULONG ulEcpSize = 0; pProcess = IoSecurityGetProcessInfo(pSecCtx); /* Fail any create that requires setting the security but doesn't have the Unix uid/gid information */ if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && (pProcess == NULL)) { ntError = STATUS_ACCESS_DENIED; BAIL_ON_NT_STATUS(ntError); } /* Do the open() */ ntError = MapPosixOpenFlags( &unixFlags, pCreateContext->GrantedAccess, Args); BAIL_ON_NT_STATUS(ntError); if (!pCreateContext->bFileExisted) { ntError = PvfsSysMkDir( pCreateContext->pszDiskFilename, (mode_t)gPvfsDriverConfig.CreateDirectoryMode); BAIL_ON_NT_STATUS(ntError); } /* Open the DIR* and then open a fd based on that */ ntError = PvfsAllocateMemory( (PVOID)&pCreateContext->pCcb->pDirContext, sizeof(PVFS_DIRECTORY_CONTEXT)); BAIL_ON_NT_STATUS(ntError); pCreateContext->pCcb->pszFilename = pCreateContext->pszDiskFilename; pCreateContext->pszDiskFilename = NULL; ntError = IoRtlEcpListFind( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_ABE, OUT_PPVOID(&pbEnableAbe), &ulEcpSize); if (ntError != STATUS_NOT_FOUND) { BAIL_ON_NT_STATUS(ntError); if (ulEcpSize != sizeof(BOOLEAN)) { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } if (*pbEnableAbe) { pCreateContext->pCcb->EcpFlags |= PVFS_ECP_ENABLE_ABE; } } do { ntError = PvfsSysOpen( &fd, pCreateContext->pCcb->pszFilename, 0, 0); } while (ntError == STATUS_MORE_PROCESSING_REQUIRED); BAIL_ON_NT_STATUS(ntError); /* Save our state */ pCreateContext->pCcb->fd = fd; pCreateContext->pCcb->ShareFlags = Args.ShareAccess; pCreateContext->pCcb->AccessGranted = pCreateContext->GrantedAccess; pCreateContext->pCcb->CreateOptions = Args.CreateOptions; ntError = PvfsAddCCBToFCB(pCreateContext->pFcb, pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSaveFileDeviceInfo(pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && pSecCtx) { /* Unix Security */ ntError = PvfsSysChown( pCreateContext->pCcb, pProcess->Uid, pProcess->Gid); BAIL_ON_NT_STATUS(ntError); /* Security Descriptor */ ntError = PvfsCreateFileSecurity( pCreateContext->pCcb->pUserToken, pCreateContext->pCcb, Args.SecurityDescriptor, TRUE); BAIL_ON_NT_STATUS(ntError); } if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_ATTRIB) && (Args.FileAttributes != 0)) { ntError = PvfsSetFileAttributes( pCreateContext->pCcb, Args.FileAttributes); BAIL_ON_NT_STATUS(ntError); } /* Save the delete-on-close flag to the FCB */ if (Args.CreateOptions & FILE_DELETE_ON_CLOSE) { LwRtlUnicodeStringInit(&FileSpec.Pattern, wszPattern); ntError = PvfsEnumerateDirectory(pCreateContext->pCcb, &FileSpec, 1, FALSE); if (ntError == STATUS_SUCCESS) { ntError = STATUS_DIRECTORY_NOT_EMPTY; BAIL_ON_NT_STATUS(ntError); } pCreateContext->pCcb->bPendingDeleteHandle = TRUE; } ntError = PvfsStoreCCB(pIrp->FileHandle, pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); PvfsInitializeZctSupport(pCreateContext->pCcb, pIrp->FileHandle); CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateContext->bFileExisted, STATUS_SUCCESS); if (CreateResult == FILE_CREATED) { PvfsNotifyScheduleFullReport( pCreateContext->pCcb->pFcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED, pCreateContext->pCcb->pszFilename); } /* The CCB has been handled off to the FileHandle so make sure we don't think we still own it */ pCreateContext->pCcb = NULL; cleanup: pIrp->IoStatusBlock.CreateResult = CreateResult; return ntError; error: CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateContext->bFileExisted, ntError); if (fd != -1) { PSTR pszRemovePath = NULL; /* Pick up where we started the pathname */ pszRemovePath = pCreateContext->pszDiskFilename ? pCreateContext->pszDiskFilename : pCreateContext->pCcb->pszFilename; PvfsCleanupFailedCreate( fd, pszRemovePath, !pCreateContext->bFileExisted); } goto cleanup; }
NTSTATUS PvfsCreateFileDoSysOpen( IN PVOID pContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_CREATE pCreateContext = (PPVFS_PENDING_CREATE)pContext; PIRP pIrp = pCreateContext->pIrpContext->pIrp; IRP_ARGS_CREATE Args = pIrp->Args.Create; int fd = -1; int unixFlags = 0; PIO_CREATE_SECURITY_CONTEXT pSecCtx = Args.SecurityContext; FILE_CREATE_RESULT CreateResult = 0; PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcess = NULL; pProcess = IoSecurityGetProcessInfo(pSecCtx); /* Fail any create that requires setting the security but doesn't have the Unix uid/gid information */ if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && (pProcess == NULL)) { ntError = STATUS_ACCESS_DENIED; BAIL_ON_NT_STATUS(ntError); } ntError = PvfsEnforceShareMode( pCreateContext->pFcb, Args.ShareAccess, pCreateContext->GrantedAccess); BAIL_ON_NT_STATUS(ntError); /* Do the open() */ ntError = MapPosixOpenFlags(&unixFlags, pCreateContext->GrantedAccess, Args); BAIL_ON_NT_STATUS(ntError); do { ntError = PvfsSysOpen( &fd, pCreateContext->pszDiskFilename, unixFlags, (mode_t)gPvfsDriverConfig.CreateFileMode); } while (ntError == STATUS_MORE_PROCESSING_REQUIRED); BAIL_ON_NT_STATUS(ntError); /* Perform preallocation is requested */ if (Args.AllocationSize > 0) { BOOLEAN bAllocate = FALSE; switch (Args.CreateDisposition) { case FILE_SUPERSEDE: case FILE_CREATE: case FILE_OVERWRITE: case FILE_OVERWRITE_IF: bAllocate = TRUE; break; case FILE_OPEN_IF: if (!pCreateContext->bFileExisted) { bAllocate = TRUE; } break; } if (bAllocate) { ntError = PvfsSysFtruncate(fd, (off_t)Args.AllocationSize); BAIL_ON_NT_STATUS(ntError); } } /* Save our state */ pCreateContext->pCcb->fd = fd; pCreateContext->pCcb->ShareFlags = Args.ShareAccess; pCreateContext->pCcb->AccessGranted = pCreateContext->GrantedAccess; pCreateContext->pCcb->CreateOptions = Args.CreateOptions; pCreateContext->pCcb->pszFilename = pCreateContext->pszDiskFilename; pCreateContext->pszDiskFilename = NULL; ntError = PvfsAddCCBToFCB(pCreateContext->pFcb, pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSaveFileDeviceInfo(pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); /* CCB is now complete */ if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && pSecCtx) { /* Unix Security */ ntError = PvfsSysChown( pCreateContext->pCcb, pProcess->Uid, pProcess->Gid); BAIL_ON_NT_STATUS(ntError); /* Security Descriptor */ ntError = PvfsCreateFileSecurity( pCreateContext->pCcb->pUserToken, pCreateContext->pCcb, Args.SecurityDescriptor, FALSE); BAIL_ON_NT_STATUS(ntError); } if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_ATTRIB) && (Args.FileAttributes != 0)) { ntError = PvfsSetFileAttributes( pCreateContext->pCcb, Args.FileAttributes); BAIL_ON_NT_STATUS(ntError); } /* Save the delete-on-close flag to the FCB */ if (Args.CreateOptions & FILE_DELETE_ON_CLOSE) { pCreateContext->pCcb->bPendingDeleteHandle = TRUE; } ntError = PvfsStoreCCB(pIrp->FileHandle, pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); PvfsInitializeZctSupport(pCreateContext->pCcb, pIrp->FileHandle); CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateContext->bFileExisted, STATUS_SUCCESS); if (CreateResult == FILE_CREATED) { PvfsNotifyScheduleFullReport( pCreateContext->pCcb->pFcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED, pCreateContext->pCcb->pszFilename); } /* The CCB has been handled off to the FileHandle so make sure we don't think we still own it */ pCreateContext->pCcb = NULL; cleanup: pIrp->IoStatusBlock.CreateResult = CreateResult; return ntError; error: CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateContext->bFileExisted, ntError); if (fd != -1) { PSTR pszRemovePath = NULL; /* Pick up where we started the pathname */ pszRemovePath = pCreateContext->pszDiskFilename ? pCreateContext->pszDiskFilename : pCreateContext->pCcb->pszFilename; PvfsCleanupFailedCreate( fd, pszRemovePath, !pCreateContext->bFileExisted); } goto cleanup; }
static NTSTATUS PvfsCreateDirOpen( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create; PPVFS_PENDING_CREATE pCreateCtx = NULL; PVFS_STAT Stat = {0}; ntError = PvfsAllocateCreateContext(&pCreateCtx, pIrpContext); BAIL_ON_NT_STATUS(ntError); if (IsSetFlag( pCreateCtx->OriginalFileName->NameOptions, PVFS_FILE_NAME_OPTION_DEFINED_STREAM_TYPE)) { // Disallow named streams here (shouldn't happen) and "::$DATA" ntError = STATUS_NOT_A_DIRECTORY; BAIL_ON_NT_STATUS(ntError); } ntError = PvfsLookupPath2( &pCreateCtx->ResolvedFileName, &Stat, pCreateCtx->OriginalFileName, IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE)); BAIL_ON_NT_STATUS(ntError); if (!S_ISDIR(Stat.s_mode)) { ntError = STATUS_NOT_A_DIRECTORY; BAIL_ON_NT_STATUS(ntError); } ntError = PvfsAccessCheckFile( pCreateCtx->pCcb->pUserToken, pCreateCtx->ResolvedFileName, Args.DesiredAccess, &pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCheckDosAttributes( Args, pCreateCtx->bFileExisted ? pCreateCtx->ResolvedFileName : NULL, pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCheckShareMode( pCreateCtx->ResolvedFileName, Args.ShareAccess, pCreateCtx->GrantedAccess, &pCreateCtx->pScb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCreateFileCheckPendingDelete(pCreateCtx->pScb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCheckQuotaFile(&Args, pCreateCtx->pCcb); BAIL_ON_NT_STATUS(ntError); pCreateCtx->bFileExisted = TRUE; ntError = PvfsAddCCBToSCB(pCreateCtx->pScb, pCreateCtx->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCreateDirDoSysOpen(pCreateCtx); BAIL_ON_NT_STATUS(ntError); cleanup: PvfsFreeCreateContext(OUT_PPVOID(&pCreateCtx)); return ntError; error: if (ntError != STATUS_PENDING) { pIrpContext->pIrp->IoStatusBlock.CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateCtx ? pCreateCtx->bFileExisted : FALSE, ntError); } if (pCreateCtx && pCreateCtx->pCcb && pCreateCtx->pCcb->pDirContext && pCreateCtx->pCcb->pDirContext->pDir) { PvfsSysCloseDir(pCreateCtx->pCcb->pDirContext->pDir); } goto cleanup; }
static NTSTATUS PvfsCreateDirOpenIf( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create; PPVFS_PENDING_CREATE pCreateCtx = NULL; PVFS_STAT statPath = { 0 }; PVFS_STAT statFile = { 0 }; PPVFS_FILE_NAME directoryName = NULL; PPVFS_FILE_NAME resolvedDirName = NULL; PPVFS_FILE_NAME relativeFileName = NULL; ntError = PvfsAllocateCreateContext(&pCreateCtx, pIrpContext); BAIL_ON_NT_STATUS(ntError); if (IsSetFlag( pCreateCtx->OriginalFileName->NameOptions, PVFS_FILE_NAME_OPTION_DEFINED_STREAM_TYPE)) { // Disallow named streams here (shouldn't happen) and "::$DATA" ntError = STATUS_NOT_A_DIRECTORY; BAIL_ON_NT_STATUS(ntError); } ntError = PvfsSplitFileNamePath( &directoryName, &relativeFileName, pCreateCtx->OriginalFileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsLookupPath2( &resolvedDirName, &statPath, directoryName, IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE)); BAIL_ON_NT_STATUS(ntError); /* Check for file existence */ ntError = PvfsLookupFile2( &pCreateCtx->ResolvedFileName, &statFile, directoryName, relativeFileName, IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE)); pCreateCtx->bFileExisted = NT_SUCCESS(ntError) ? TRUE : FALSE; if (!pCreateCtx->bFileExisted) { ntError = PvfsAppendFileName( &pCreateCtx->ResolvedFileName, resolvedDirName, relativeFileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsAccessCheckFile( pCreateCtx->pCcb->pUserToken, resolvedDirName, FILE_ADD_SUBDIRECTORY, &pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); pCreateCtx->GrantedAccess = PvfsGetGrantedAccessForNewObject( Args.DesiredAccess); } else { if (!S_ISDIR(statFile.s_mode)) { ntError = STATUS_NOT_A_DIRECTORY; BAIL_ON_NT_STATUS(ntError); } ntError = PvfsAccessCheckFile( pCreateCtx->pCcb->pUserToken, pCreateCtx->ResolvedFileName, Args.DesiredAccess, &pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); } ntError = PvfsCheckDosAttributes( Args, pCreateCtx->bFileExisted ? pCreateCtx->ResolvedFileName : NULL, pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCheckShareMode( pCreateCtx->ResolvedFileName, Args.ShareAccess, pCreateCtx->GrantedAccess, &pCreateCtx->pScb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCreateFileCheckPendingDelete(pCreateCtx->pScb); BAIL_ON_NT_STATUS(ntError); if (!pCreateCtx->bFileExisted) { pCreateCtx->SetPropertyFlags = PVFS_SET_PROP_SECURITY| PVFS_SET_PROP_ATTRIB; } ntError = PvfsAddCCBToSCB(pCreateCtx->pScb, pCreateCtx->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCreateDirDoSysOpen(pCreateCtx); BAIL_ON_NT_STATUS(ntError); cleanup: PvfsFreeCreateContext(OUT_PPVOID(&pCreateCtx)); if (directoryName) { PvfsFreeFileName(directoryName); } if (relativeFileName) { PvfsFreeFileName(relativeFileName); } if (resolvedDirName) { PvfsFreeFileName(resolvedDirName); } return ntError; error: if (ntError != STATUS_PENDING) { pIrpContext->pIrp->IoStatusBlock.CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateCtx ? pCreateCtx->bFileExisted : FALSE, ntError); } if (pCreateCtx && pCreateCtx->pCcb && pCreateCtx->pCcb->pDirContext && pCreateCtx->pCcb->pDirContext->pDir) { PvfsSysCloseDir(pCreateCtx->pCcb->pDirContext->pDir); } goto cleanup; }
static NTSTATUS PvfsCreateDirCreate( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create; PPVFS_PENDING_CREATE pCreateCtx = NULL; PVFS_STAT statPath = { 0 }; PPVFS_FILE_NAME directoryName = NULL; PPVFS_FILE_NAME relativeFileName = NULL; PPVFS_FILE_NAME resolvedDirName = NULL; ntError = PvfsAllocateCreateContext(&pCreateCtx, pIrpContext); BAIL_ON_NT_STATUS(ntError); if (IsSetFlag( pCreateCtx->OriginalFileName->NameOptions, PVFS_FILE_NAME_OPTION_DEFINED_STREAM_TYPE)) { // Disallow named streams here (shouldn't happen) and "::$DATA" ntError = STATUS_NOT_A_DIRECTORY; BAIL_ON_NT_STATUS(ntError); } /* We expect this call to fail with OBJECT_NAME_NOT_FOUND */ ntError = PvfsLookupPath2( &pCreateCtx->ResolvedFileName, &statPath, pCreateCtx->OriginalFileName, IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE)); switch (ntError) { case STATUS_SUCCESS: ntError = STATUS_OBJECT_NAME_COLLISION; break; case STATUS_OBJECT_NAME_NOT_FOUND: ntError = STATUS_SUCCESS; break; default: /* do nothing */ break; } BAIL_ON_NT_STATUS(ntError); ntError = PvfsSplitFileNamePath( &directoryName, &relativeFileName, pCreateCtx->OriginalFileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsLookupPath2( &resolvedDirName, &statPath, directoryName, IsSetFlag(Args.FileName.IoNameOptions, IO_NAME_OPTION_CASE_SENSITIVE)); if (ntError == STATUS_OBJECT_NAME_NOT_FOUND) { ntError = STATUS_OBJECT_PATH_NOT_FOUND; } BAIL_ON_NT_STATUS(ntError); ntError = PvfsAppendFileName( &pCreateCtx->ResolvedFileName, resolvedDirName, relativeFileName); BAIL_ON_NT_STATUS(ntError); /* check parent here */ ntError = PvfsAccessCheckFile( pCreateCtx->pCcb->pUserToken, resolvedDirName, FILE_ADD_SUBDIRECTORY, &pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); pCreateCtx->GrantedAccess = PvfsGetGrantedAccessForNewObject( Args.DesiredAccess); ntError = PvfsCheckDosAttributes( Args, NULL, /* New directory */ pCreateCtx->GrantedAccess); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCheckShareMode( pCreateCtx->ResolvedFileName, Args.ShareAccess, pCreateCtx->GrantedAccess, &pCreateCtx->pScb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCreateFileCheckPendingDelete(pCreateCtx->pScb); BAIL_ON_NT_STATUS(ntError); pCreateCtx->bFileExisted = FALSE; pCreateCtx->SetPropertyFlags = PVFS_SET_PROP_SECURITY|PVFS_SET_PROP_ATTRIB; ntError = PvfsAddCCBToSCB(pCreateCtx->pScb, pCreateCtx->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCreateDirDoSysOpen(pCreateCtx); BAIL_ON_NT_STATUS(ntError); cleanup: PvfsFreeCreateContext(OUT_PPVOID(&pCreateCtx)); if (directoryName) { PvfsFreeFileName(directoryName); } if (relativeFileName) { PvfsFreeFileName(relativeFileName); } if (resolvedDirName) { PvfsFreeFileName(resolvedDirName); } return ntError; error: if (ntError != STATUS_PENDING) { pIrpContext->pIrp->IoStatusBlock.CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateCtx ? pCreateCtx->bFileExisted : FALSE, ntError); } if (pCreateCtx && pCreateCtx->pCcb && pCreateCtx->pCcb->pDirContext && pCreateCtx->pCcb->pDirContext->pDir) { PvfsSysCloseDir(pCreateCtx->pCcb->pDirContext->pDir); } goto cleanup; }