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;
|
|||
|
}
|