/*++ Copyright (c) 1989 Microsoft Corporation Module Name: nullio.c Abstract: This module implements io on the 'null' device. It's pretty simple. Author: Matthew Bradburn (mattbr) 01-Aug-1995 Revision History: --*/ #include #include #include #include "psxsrv.h" BOOLEAN NullOpen( IN PPSX_PROCESS p, IN PFILEDESCRIPTOR Fd, IN OUT PPSX_API_MSG m ); BOOLEAN NullRead( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd ); BOOLEAN NullWrite( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd ); BOOLEAN NullDup( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd, IN PFILEDESCRIPTOR FdDup ); BOOLEAN NullLseek( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd ); BOOLEAN NullStat( IN PIONODE IoNode, IN HANDLE FileHandle, OUT struct stat *StatBuf, OUT NTSTATUS *pStatus ); void FindOwnerModeFile( IN HANDLE FileHandle, OUT struct stat *StatBuf ); PSXIO_VECTORS NullVectors = { NullOpen, // OpenNewHandle NULL, // NewHandle NULL, // Close NULL, // LastClose NULL, // IoNodeClose NullRead, // Read NullWrite, // Write NullDup, // Dup NullLseek, // Lseek NullStat // Stat }; BOOLEAN NullOpen( IN PPSX_PROCESS p, IN PFILEDESCRIPTOR Fd, IN OUT PPSX_API_MSG m ) /*++ Routine Description: This routine Arguments: Return Value: FALSE - Failure. TRUE - Success. --*/ { PPSX_OPEN_MSG args; LARGE_INTEGER time; ULONG posix_time; args = &m->u.Open; NtQuerySystemTime(&time); if (!RtlTimeToSecondsSince1970(&time, &posix_time)) { posix_time = 0; } KdPrint(("Posix time: %x\n", posix_time)); RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock); Fd->SystemOpenFileDesc->IoNode->ModifyDataTime = posix_time; Fd->SystemOpenFileDesc->IoNode->ModifyIoNodeTime = posix_time; Fd->SystemOpenFileDesc->IoNode->AccessDataTime = posix_time; RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock); return TRUE; } BOOLEAN NullWrite( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd ) /*++ Routine Description: This procedure implements write when the device being written is the null device. Writes to the null device succeed, and the data is discarded. Arguments: p - Supplies the address of the process making the call. m - Supplies the address of the message associated with the request. Fd - supplies the address of the file descriptor being written. Return Value: --*/ { PPSX_WRITE_MSG args; LARGE_INTEGER time; ULONG posix_time; NTSTATUS st; args = &m->u.Write; if (args->Nbytes > 0) { // // Update the times for stat. // NtQuerySystemTime(&time); if (!RtlTimeToSecondsSince1970(&time, &posix_time)) { posix_time = 0; } RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock); Fd->SystemOpenFileDesc->IoNode->ModifyDataTime = posix_time; Fd->SystemOpenFileDesc->IoNode->ModifyIoNodeTime = posix_time; RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock); } m->ReturnValue = args->Nbytes; return TRUE; } BOOLEAN NullRead( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd ) /*++ Routine Description: This procedure implements read when the device being read is the null device. Reads from this device always return EOF. Arguments: p - Supplies the address of the process making the call. m - Supplies the address of the message associated with the request. Fd - supplies the address of the file descriptor being read. Return Value: --*/ { PPSX_READ_MSG args; NTSTATUS st; LARGE_INTEGER ByteOffset; ULONG IoBufferSize; LARGE_INTEGER Time; ULONG posix_time; args = &m->u.Read; if (args->Nbytes > 0) { // // Update the access time on the ionode. // NtQuerySystemTime(&Time); if (!RtlTimeToSecondsSince1970(&Time, &posix_time)) { posix_time = 0; } RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock); Fd->SystemOpenFileDesc->IoNode->AccessDataTime = posix_time; RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock); } m->ReturnValue = 0; return TRUE; } BOOLEAN NullDup( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd, IN PFILEDESCRIPTOR FdDup ) /*++ Routine Description: This procedure implements dup and dup2. Arguments: p - Supplies the address of the process making the call. m - Supplies the address of the message associated with the request. Fd - supplies the address of the file descriptor being duplicated. FdDup - supplies the address of the duplicate file descriptor. Return Value: TRUE. --*/ { PPSX_DUP_MSG args; args = &m->u.Dup; // // Copy contents of source file descriptor slot into new descriptor // Note that FD_CLOEXEC must be CLEAR on FdDup. // *FdDup = *Fd; FdDup->Flags &= ~PSX_FD_CLOSE_ON_EXEC; // // Increment reference count associated with the SystemOpenFile // descriptor for this file. // // Grab system open file lock RtlEnterCriticalSection(&SystemOpenFileLock); Fd->SystemOpenFileDesc->HandleCount++; RtlLeaveCriticalSection(&SystemOpenFileLock); return TRUE; } BOOLEAN NullLseek( IN PPSX_PROCESS p, IN OUT PPSX_API_MSG m, IN PFILEDESCRIPTOR Fd ) /*++ Routine Description: This procedure implements lseek when the device being seeked on is the null device. We allow these seeks, but they have no effect. Arguments: p - Supplies the address of the process making the call. m - Supplies the address of the message associated with the request. Fd - supplies the address of the file descriptor being seekd Return Value: TRUE --*/ { PPSX_LSEEK_MSG args; NTSTATUS st; LARGE_INTEGER Offset, NewByteOffset; args = &m->u.Lseek; Offset = RtlConvertLongToLargeInteger(args->Offset); NewByteOffset = Offset; if (SEEK_CUR != args->Whence && SEEK_SET != args->Whence && SEEK_END != args->Whence) { m->Error = EINVAL; return TRUE; } // Check for overflow. POSIX limited to arithmetic data type for off_t if (NewByteOffset.HighPart != 0 || (off_t)NewByteOffset.LowPart < 0) { m->Error = EINVAL; } return TRUE; } BOOLEAN NullStat( IN PIONODE IoNode, IN HANDLE FileHandle, OUT struct stat *StatBuf, OUT NTSTATUS *pStatus ) /*++ Routine Description: This procedure implements stat when the device being read is the null device. Arguments: IoNode - supplies a pointer to the ionode of the file for which stat is requested. NULL if no active Ionode entry. FileHandle - supplies the Nt file handle of the file . StatBuf - Supplies the address of the statbuf portion of the message associated with the request. Return Value: TRUE. --*/ { IO_STATUS_BLOCK Iosb; // // First get the static information on the file from the ionode if // there is one (i.e. if the file currently open. // Open() sets the fields in the ionode. // if (NULL != IoNode) { StatBuf->st_mode = IoNode->Mode; StatBuf->st_ino = IoNode->FileSerialNumber; StatBuf->st_dev = IoNode->DeviceSerialNumber; StatBuf->st_atime = IoNode->AccessDataTime; StatBuf->st_ctime = IoNode->ModifyIoNodeTime; StatBuf->st_mtime = IoNode->ModifyDataTime; } StatBuf->st_uid = 0; StatBuf->st_gid = 0; StatBuf->st_size = 0; StatBuf->st_nlink = 1; return TRUE; }