static VOID PvfsCleanupFailedCreate( int fd, PCSTR pszPath, BOOLEAN bWasCreated ) { NTSTATUS ntError = STATUS_SUCCESS; PVFS_STAT Stat1 = {0}; PVFS_STAT Stat2 = {0}; /* Remove the file if it was created and the Dev/Inode matches our fd */ if (bWasCreated && (pszPath != NULL)) { ntError = PvfsSysFstat(fd, &Stat1); if (ntError == STATUS_SUCCESS) { ntError = PvfsSysStat(pszPath, &Stat2); if (ntError == STATUS_SUCCESS) { if ((Stat1.s_dev == Stat1.s_dev) && (Stat2.s_ino == Stat2.s_ino)) { ntError = PvfsSysRemove(pszPath); } } } } ntError = PvfsSysClose(fd); return; }
NTSTATUS PvfsCcbQueryFileBasicInformation( PPVFS_CCB pCcb, PFILE_BASIC_INFORMATION pFileInfo ) { NTSTATUS ntError = STATUS_SUCCESS; PVFS_STAT Stat = {0}; PVFS_FILE_NAME baseObjectFileName = { 0 }; if (PvfsIsDefaultStream(pCcb->pScb)) { ntError = PvfsGetFileAttributes(pCcb, &pFileInfo->FileAttributes); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysFstat(pCcb->fd, &Stat); BAIL_ON_NT_STATUS(ntError); } else { // Named Streams share meta-data with the owning FCB ntError = PvfsBuildFileNameFromCString( &baseObjectFileName, pCcb->pScb->pOwnerFcb->pszFilename, 0); BAIL_ON_NT_STATUS(ntError); ntError = PvfsGetFilenameAttributes( PvfsGetCStringBaseFileName(&baseObjectFileName), &pFileInfo->FileAttributes); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStatByFileName(&baseObjectFileName, &Stat); BAIL_ON_NT_STATUS(ntError); } ntError = PvfsUnixToWinTime(&pFileInfo->LastAccessTime, Stat.s_atime); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->LastWriteTime, Stat.s_mtime); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->ChangeTime, Stat.s_ctime); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->CreationTime, Stat.s_crtime); BAIL_ON_NT_STATUS(ntError); error: PvfsDestroyFileName(&baseObjectFileName); return ntError; }
NTSTATUS PvfsCcbQueryFileStandardInformation( PPVFS_CCB pCcb, PFILE_STANDARD_INFORMATION pFileInfo ) { NTSTATUS ntError = STATUS_SUCCESS; PVFS_STAT Stat = {0}; BOOLEAN bDeletePending = FALSE; LONG64 allocationSize = 0; ntError = PvfsSysFstat(pCcb->fd, &Stat); BAIL_ON_NT_STATUS(ntError); bDeletePending = PvfsScbIsPendingDelete(pCcb->pScb); if (PVFS_IS_DIR(pCcb)) { /* NTFS reports the allocation and end-of-file on directories as 0. smbtorture cares about this even if no apps that I know of do. */ pFileInfo->AllocationSize = 0; pFileInfo->EndOfFile = 0; pFileInfo->NumberOfLinks = bDeletePending ? 0 : 1; } else { allocationSize = PvfsGetScbAllocationSize(pCcb->pScb); pFileInfo->EndOfFile = Stat.s_size; pFileInfo->AllocationSize = PVFS_MAX((Stat.s_alloc > Stat.s_size ? Stat.s_alloc : Stat.s_size), allocationSize); pFileInfo->NumberOfLinks = bDeletePending ? Stat.s_nlink - 1 : Stat.s_nlink; } pFileInfo->DeletePending = bDeletePending; pFileInfo->Directory = S_ISDIR(Stat.s_mode) ? TRUE : FALSE; cleanup: return ntError; error: goto cleanup; }
static NTSTATUS PvfsQueryFileInternalInfo( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIRP pIrp = pIrpContext->pIrp; PPVFS_CCB pCcb = NULL; PFILE_INTERNAL_INFORMATION pFileInfo = NULL; IRP_ARGS_QUERY_SET_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetInformation; PVFS_STAT Stat = {0}; /* Sanity checks */ ntError = PvfsAcquireCCB(pIrp->FileHandle, &pCcb); BAIL_ON_NT_STATUS(ntError); BAIL_ON_INVALID_PTR(Args.FileInformation, ntError); if (Args.Length < sizeof(*pFileInfo)) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pFileInfo = (PFILE_INTERNAL_INFORMATION)Args.FileInformation; /* Real work starts here */ ntError = PvfsSysFstat(pCcb->fd, &Stat); BAIL_ON_NT_STATUS(ntError); /* Just let this be the inode number */ pFileInfo->IndexNumber = Stat.s_ino; pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo); ntError = STATUS_SUCCESS; cleanup: if (pCcb) { PvfsReleaseCCB(pCcb); } return ntError; error: goto cleanup; }
NTSTATUS PvfsSaveFileDeviceInfo( PPVFS_CCB pCcb ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PVFS_STAT Stat = {0}; PPVFS_SCB pScb = pCcb->pScb; PPVFS_FCB pFcb = pCcb->pScb->pOwnerFcb; BOOLEAN scbLocked = FALSE; BOOLEAN fcbLocked = FALSE; ntError = PvfsSysFstat(pCcb->fd, &Stat); BAIL_ON_NT_STATUS(ntError); pCcb->FileId.Device = Stat.s_dev; pCcb->FileId.Inode = Stat.s_ino; pCcb->FileSize = Stat.s_size; LWIO_LOCK_MUTEX(scbLocked, &pScb->BaseControlBlock.Mutex); // Have to set the FileID on the Stream Block pScb->FileId = pCcb->FileId; if (PvfsIsDefaultStream(pScb)) { // Push the FIleId through to the File Block if unset LWIO_LOCK_MUTEX(fcbLocked, &pFcb->BaseControlBlock.Mutex); pFcb->FileId = pScb->FileId; LWIO_UNLOCK_MUTEX(fcbLocked, &pFcb->BaseControlBlock.Mutex); } LWIO_UNLOCK_MUTEX(scbLocked, &pScb->BaseControlBlock.Mutex); error: return ntError; }
NTSTATUS PvfsCcbSetFileBasicInformation( PPVFS_CCB pCcb, PFILE_BASIC_INFORMATION pFileInfo ) { NTSTATUS ntError = STATUS_SUCCESS; LONG64 WriteTime = 0; LONG64 AccessTime = 0; FILE_NOTIFY_CHANGE NotifyFilter = FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS; PVFS_STAT Stat = {0}; BOOLEAN fcbControlLocked = FALSE; PPVFS_FCB pFcb = PvfsReferenceFCB(pCcb->pScb->pOwnerFcb); if (PvfsIsDefaultStream(pCcb->pScb)) { ntError = PvfsValidatePathSCB(pCcb->pScb, &pCcb->FileId); } else { // Have to grab the base file object LWIO_LOCK_MUTEX(fcbControlLocked, &pFcb->BaseControlBlock.Mutex); ntError = PvfsValidatePathFCB(pFcb, &pFcb->FileId); BAIL_ON_NT_STATUS(ntError); LWIO_UNLOCK_MUTEX(fcbControlLocked, &pFcb->BaseControlBlock.Mutex); } /* We cant's set the Change Time so ignore it */ WriteTime = pFileInfo->LastWriteTime; AccessTime = pFileInfo->LastAccessTime; /* Ignore 0xffffffff */ if (WriteTime == (LONG64)-1) { WriteTime = 0; } if (AccessTime == (LONG64)-1) { AccessTime = 0; } /* Save for "sticky" WriteTime sematics */ if (WriteTime != 0) { PvfsSetLastWriteTimeFCB(pFcb, WriteTime); } /* Check if we need to preserve any original timestamps */ if (WriteTime == 0 || AccessTime == 0) { if (PvfsIsDefaultStream(pCcb->pScb)) { ntError = PvfsSysFstat(pCcb->fd, &Stat); } else { // Have to grab the stat() on the base file object ntError = PvfsSysStatByFcb(pFcb, &Stat); } BAIL_ON_NT_STATUS(ntError); if (WriteTime == 0) { NotifyFilter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; ntError = PvfsUnixToWinTime(&WriteTime, Stat.s_mtime); BAIL_ON_NT_STATUS(ntError); } if (AccessTime == 0) { NotifyFilter &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; ntError = PvfsUnixToWinTime(&AccessTime, Stat.s_atime); BAIL_ON_NT_STATUS(ntError); } } ntError = PvfsSysUtimeByFcb(pFcb, WriteTime, AccessTime); BAIL_ON_NT_STATUS(ntError); if (pFileInfo->FileAttributes != 0) { ntError = PvfsSetFileAttributes(pCcb, pFileInfo->FileAttributes); BAIL_ON_NT_STATUS(ntError); } if (NotifyFilter != 0) { PvfsNotifyScheduleFullReport( pFcb, NotifyFilter, FILE_ACTION_MODIFIED, pFcb->pszFilename); } error: LWIO_UNLOCK_MUTEX(fcbControlLocked, &pFcb->BaseControlBlock.Mutex); if (pFcb) { PvfsReleaseFCB(&pFcb); } return ntError; }
static NTSTATUS PvfsQueryFileFsVolInfo( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIRP pIrp = pIrpContext->pIrp; PPVFS_CCB pCcb = NULL; PFILE_FS_VOLUME_INFORMATION pFileInfo = NULL; IRP_ARGS_QUERY_SET_VOLUME_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetVolumeInformation; PWSTR pwszVolumeName = NULL; PCSTR pszVolName = "LIKEWISE"; size_t VolNameLenBytes = RtlCStringNumChars(pszVolName) * sizeof(WCHAR); PVFS_STAT stat = { 0 }; /* Sanity checks */ ntError = PvfsAcquireCCB(pIrp->FileHandle, &pCcb); BAIL_ON_NT_STATUS(ntError); /* not sure exact access rights to check for here */ ntError = PvfsAccessCheckFileHandle(pCcb, FILE_READ_ATTRIBUTES); BAIL_ON_NT_STATUS(ntError); BAIL_ON_INVALID_PTR(Args.FsInformation, ntError); if (Args.Length < sizeof(*pFileInfo) + VolNameLenBytes) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pFileInfo = (PFILE_FS_VOLUME_INFORMATION)Args.FsInformation; /* Real work starts here */ ntError = PvfsSysFstat(pCcb->fd, &stat); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->VolumeCreationTime, stat.s_crtime); BAIL_ON_NT_STATUS(ntError); pFileInfo->VolumeSerialNumber = 0x009a9a03; pFileInfo->SupportsObjects = FALSE; ntError = RtlWC16StringAllocateFromCString(&pwszVolumeName, pszVolName); BAIL_ON_NT_STATUS(ntError); pFileInfo->VolumeLabelLength = VolNameLenBytes; memcpy(pFileInfo->VolumeLabel, pwszVolumeName, VolNameLenBytes); pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo); ntError = STATUS_SUCCESS; cleanup: if (pCcb) { PvfsReleaseCCB(pCcb); } PVFS_FREE(&pwszVolumeName); return ntError; error: goto cleanup; }