422 lines
8 KiB
C
422 lines
8 KiB
C
/*++
|
||
|
||
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 <sys/stat.h>
|
||
#include <time.h>
|
||
#include <wchar.h>
|
||
#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 = (ino_t)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;
|
||
}
|