mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
now introducing the POSIX+ client DLL! (my first check-in, hope I don't f*** up something)
svn path=/trunk/; revision=2634
This commit is contained in:
parent
4e9d91b819
commit
ad8ae0a2f5
43 changed files with 4239 additions and 0 deletions
117
posix/lib/psxdll/Makefile
Normal file
117
posix/lib/psxdll/Makefile
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
# $Id:
|
||||||
|
|
||||||
|
PATH_TO_TOP = ../../../..
|
||||||
|
|
||||||
|
TARGET_TYPE = dynlink
|
||||||
|
|
||||||
|
TARGET_NAME = psxdll
|
||||||
|
|
||||||
|
TARGET_LFLAGS = -nostartfiles
|
||||||
|
|
||||||
|
TARGET_SDKLIBS = ntdll.a
|
||||||
|
|
||||||
|
TARGET_BASE = 0x68EB0000
|
||||||
|
|
||||||
|
TARGET_ENTRY = _DllMain@12
|
||||||
|
|
||||||
|
TARGET_CFLAGS = -W -nostdinc -nostdlib -fno-builtin -I$(PATH_TO_TOP)/subsys/psx/include -D__PSXDLL__ -D__PSX_DEBUG_WANT_ALL__
|
||||||
|
|
||||||
|
TARGET_OBJECTS = $(TARGET_NAME).o
|
||||||
|
|
||||||
|
TARGET_CLEAN = $(OBJECTS)
|
||||||
|
|
||||||
|
include $(PATH_TO_TOP)/rules.mak
|
||||||
|
include $(TOOLS_PATH)/helper.mk
|
||||||
|
|
||||||
|
OBJECTS_MISC = \
|
||||||
|
misc/main.o \
|
||||||
|
misc/interlock.o \
|
||||||
|
misc/safeobj.o \
|
||||||
|
misc/path.o \
|
||||||
|
misc/fdtable.o
|
||||||
|
|
||||||
|
OBJECTS_DIRENT = \
|
||||||
|
dirent/opendir.o \
|
||||||
|
dirent/readdir.o \
|
||||||
|
dirent/closedir.o
|
||||||
|
|
||||||
|
OBJECTS_DLFCN = \
|
||||||
|
dlfcn/dlopen.o \
|
||||||
|
dlfcn/dlclose.o \
|
||||||
|
dlfcn/dlsym.o \
|
||||||
|
dlfcn/dlerror.o
|
||||||
|
|
||||||
|
OBJECTS_ERRNO = \
|
||||||
|
errno/errno.o
|
||||||
|
|
||||||
|
OBJECTS_FCNTL = \
|
||||||
|
fcntl/open.o \
|
||||||
|
fcntl/fcntl.o
|
||||||
|
|
||||||
|
OBJECTS_LIBGEN = \
|
||||||
|
libgen/basename.o
|
||||||
|
|
||||||
|
OBJECTS_SCHED = \
|
||||||
|
sched/yield.o
|
||||||
|
|
||||||
|
OBJECTS_SIGNAL = \
|
||||||
|
pthread/kill.o \
|
||||||
|
signal/raise.o
|
||||||
|
|
||||||
|
OBJECTS_STDLIB = \
|
||||||
|
stdlib/abort.o \
|
||||||
|
stdlib/malloc.o \
|
||||||
|
stdlib/exit.o
|
||||||
|
|
||||||
|
OBJECTS_STRING = \
|
||||||
|
string/strdup.o \
|
||||||
|
string/strerror.o
|
||||||
|
|
||||||
|
OBJECTS_PTHREAD = \
|
||||||
|
pthread/create.o \
|
||||||
|
pthread/exit.o \
|
||||||
|
pthread/join.o \
|
||||||
|
pthread/mutex.o \
|
||||||
|
pthread/self.o
|
||||||
|
|
||||||
|
OBJECTS_SYS_UTSNAME = \
|
||||||
|
sys/utsname/uname.o
|
||||||
|
|
||||||
|
OBJECTS_UNISTD = \
|
||||||
|
unistd/close.o \
|
||||||
|
unistd/dup.o \
|
||||||
|
unistd/getcwd.o \
|
||||||
|
unistd/getpid.o \
|
||||||
|
unistd/getppid.o
|
||||||
|
|
||||||
|
OBJECTS = \
|
||||||
|
$(OBJECTS_MISC) \
|
||||||
|
$(OBJECTS_DIRENT) \
|
||||||
|
$(OBJECTS_DLFCN) \
|
||||||
|
$(OBJECTS_ERRNO) \
|
||||||
|
$(OBJECTS_FCNTL) \
|
||||||
|
$(OBJECTS_LIBGEN) \
|
||||||
|
$(OBJECTS_SCHED) \
|
||||||
|
$(OBJECTS_SIGNAL) \
|
||||||
|
$(OBJECTS_STDLIB) \
|
||||||
|
$(OBJECTS_STRING) \
|
||||||
|
$(OBJECTS_PTHREAD) \
|
||||||
|
$(OBJECTS_SYS_UTSNAME) \
|
||||||
|
$(OBJECTS_UNISTD)
|
||||||
|
|
||||||
|
DEP_OBJECTS = $(OBJECTS)
|
||||||
|
|
||||||
|
include $(TOOLS_PATH)/depend.mk
|
||||||
|
|
||||||
|
$(TARGET_NAME).o: $(OBJECTS)
|
||||||
|
$(LD) -r $(OBJECTS) -o $(TARGET_NAME).o
|
||||||
|
|
||||||
|
DTFLAGS = -k -l $@
|
||||||
|
|
||||||
|
$(TARGET_NAME).a: $(TARGET_NAME).def
|
||||||
|
$(DLLTOOL) \
|
||||||
|
$(DTFLAGS) \
|
||||||
|
-D $(TARGET_NAME).dll \
|
||||||
|
-d $(TARGET_NAME).def
|
||||||
|
|
||||||
|
# EOF
|
36
posix/lib/psxdll/dirent/closedir.c
Normal file
36
posix/lib/psxdll/dirent/closedir.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* $Id: closedir.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dirent/closedir.c
|
||||||
|
* PURPOSE: Close a directory stream
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 01/02/2002: Created
|
||||||
|
* 13/02/2002: KJK::Hyperion: modified to use file descriptors
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <psx/dirent.h>
|
||||||
|
#include <psx/safeobj.h>
|
||||||
|
|
||||||
|
int closedir(DIR *dirp)
|
||||||
|
{
|
||||||
|
/* check the "magic" signature */
|
||||||
|
if(!__safeobj_validate(dirp, __IDIR_MAGIC))
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this will close the handle, deallocate the internal object and
|
||||||
|
invalidate the descriptor */
|
||||||
|
return (close(((struct __internal_DIR *)dirp)->fildes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
100
posix/lib/psxdll/dirent/opendir.c
Normal file
100
posix/lib/psxdll/dirent/opendir.c
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* $Id: opendir.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dirent/opendir.c
|
||||||
|
* PURPOSE: Open a directory
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/01/2002: Created
|
||||||
|
* 13/02/2002: KJK::Hyperion: modified to use file descriptors
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/dirent.h>
|
||||||
|
#include <psx/safeobj.h>
|
||||||
|
|
||||||
|
DIR *opendir(const char *dirname)
|
||||||
|
{
|
||||||
|
ANSI_STRING strDirName;
|
||||||
|
UNICODE_STRING wstrDirName;
|
||||||
|
DIR *pdData;
|
||||||
|
|
||||||
|
RtlInitAnsiString(&strDirName, (PCSZ)dirname);
|
||||||
|
RtlAnsiStringToUnicodeString(&wstrDirName, &strDirName, TRUE);
|
||||||
|
|
||||||
|
pdData = (DIR *)_Wopendir(wstrDirName.Buffer);
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&wstrDirName);
|
||||||
|
|
||||||
|
return (pdData);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR *_Wopendir(const wchar_t *dirname)
|
||||||
|
{
|
||||||
|
struct __internal_DIR *pidData;
|
||||||
|
int nFileNo;
|
||||||
|
|
||||||
|
/* allocate internal object */
|
||||||
|
pidData = __malloc(sizeof(*pidData));
|
||||||
|
|
||||||
|
/* allocation failed */
|
||||||
|
if(pidData == 0)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the directory */
|
||||||
|
nFileNo = _Wopen(dirname, O_RDONLY | _O_DIRFILE);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(nFileNo < 0)
|
||||||
|
{
|
||||||
|
__free(pidData);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* directory file descriptors must be closed on exec() */
|
||||||
|
if(fcntl(nFileNo, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
WARN
|
||||||
|
(
|
||||||
|
"couldn't set FD_CLOEXEC flag on file number %u, errno %u",
|
||||||
|
nFileNo,
|
||||||
|
errno
|
||||||
|
);
|
||||||
|
|
||||||
|
/* associate the internal data to the file descriptor */
|
||||||
|
if(fcntl(nFileNo, F_SETXP, pidData) == -1)
|
||||||
|
WARN
|
||||||
|
(
|
||||||
|
"couldn't associate the object at 0x%X to the file number %u, errno %u",
|
||||||
|
pidData,
|
||||||
|
nFileNo,
|
||||||
|
errno
|
||||||
|
);
|
||||||
|
|
||||||
|
if(fcntl(nFileNo, F_SETXS, sizeof(*pidData)) == -1)
|
||||||
|
WARN
|
||||||
|
(
|
||||||
|
"couldn't set the extra data size of the file number %u, errno %u",
|
||||||
|
nFileNo,
|
||||||
|
errno
|
||||||
|
);
|
||||||
|
|
||||||
|
pidData->signature = __IDIR_MAGIC;
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return ((DIR *)pidData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
214
posix/lib/psxdll/dirent/readdir.c
Normal file
214
posix/lib/psxdll/dirent/readdir.c
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/* $Id: readdir.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dirent/readdir.c
|
||||||
|
* PURPOSE: Read directory
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/01/2002: Created
|
||||||
|
* 13/02/2002: KJK::Hyperion: modified to use file descriptors
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <psx/dirent.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/safeobj.h>
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
struct dirent *readdir(DIR *dirp)
|
||||||
|
{
|
||||||
|
struct _Wdirent *lpwdReturn;
|
||||||
|
struct __internal_DIR *pidData;
|
||||||
|
ANSI_STRING strFileName;
|
||||||
|
UNICODE_STRING wstrFileName;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
/* call Unicode function */
|
||||||
|
lpwdReturn = _Wreaddir(dirp);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(lpwdReturn == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* get the internal data object */
|
||||||
|
pidData = ((struct __internal_DIR *)dirp);
|
||||||
|
|
||||||
|
/* create NT Unicode string from the Unicode dirent's buffer */
|
||||||
|
RtlInitUnicodeString(&wstrFileName, pidData->ent.de_unicode.d_name);
|
||||||
|
|
||||||
|
/* HACK: make the ANSI string point to the same buffer where the Unicode string is stored */
|
||||||
|
strFileName.Buffer = (PCSZ)&pidData->info.FileName[0];
|
||||||
|
strFileName.Length = 0;
|
||||||
|
strFileName.MaximumLength = MAX_PATH;
|
||||||
|
|
||||||
|
/* convert the filename to ANSI */
|
||||||
|
nErrCode = RtlUnicodeStringToAnsiString(&strFileName, &wstrFileName, FALSE);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make the ANSI dirent filename point to the ANSI buffer */
|
||||||
|
pidData->ent.de_ansi.d_name = strFileName.Buffer;
|
||||||
|
|
||||||
|
/* null-terminate the ANSI name */
|
||||||
|
pidData->ent.de_ansi.d_name[strFileName.Length] = 0;
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (&(pidData->ent.de_ansi));
|
||||||
|
}
|
||||||
|
|
||||||
|
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _Wdirent *_Wreaddir(DIR *dirp)
|
||||||
|
{
|
||||||
|
HANDLE hFile;
|
||||||
|
HANDLE hDir;
|
||||||
|
OBJECT_ATTRIBUTES oaFileAttribs;
|
||||||
|
UNICODE_STRING wstrFileName;
|
||||||
|
FILE_INTERNAL_INFORMATION fiiInfo;
|
||||||
|
IO_STATUS_BLOCK isbStatus;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
struct __internal_DIR *pidData;
|
||||||
|
|
||||||
|
/* check the "magic" signature */
|
||||||
|
if(!__safeobj_validate(dirp, __IDIR_MAGIC))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get internal data */
|
||||||
|
pidData = (struct __internal_DIR *)dirp;
|
||||||
|
|
||||||
|
/* get handle */
|
||||||
|
hDir = (HANDLE)fcntl(pidData->fildes, F_GETFH);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(((int)hDir) == -1)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* read next directory entry */
|
||||||
|
nErrCode = NtQueryDirectoryFile
|
||||||
|
(
|
||||||
|
hDir,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&isbStatus,
|
||||||
|
(PVOID)&pidData->info,
|
||||||
|
sizeof(pidData->info) + sizeof(WCHAR) * (MAX_PATH - 1),
|
||||||
|
FileDirectoryInformation,
|
||||||
|
TRUE,
|
||||||
|
NULL,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure or EOF */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
if(nErrCode == (NTSTATUS)STATUS_NO_MORE_FILES)
|
||||||
|
return (0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("NtQueryDirectoryFile() failed with status 0x%08X", nErrCode);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* null-terminate the filename, just in case */
|
||||||
|
pidData->info.FileName[pidData->info.FileNameLength / sizeof(WCHAR)] = 0;
|
||||||
|
|
||||||
|
INFO("this entry: %ls", pidData->info.FileName);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* file inodes are not returned by NtQueryDirectoryFile, we have to open every file */
|
||||||
|
/* set file's object attributes */
|
||||||
|
wstrFileName.Length = pidData->info.FileNameLength;
|
||||||
|
wstrFileName.MaximumLength = sizeof(WCHAR) * MAX_PATH;
|
||||||
|
wstrFileName.Buffer = &pidData->info.FileName[0];
|
||||||
|
|
||||||
|
oaFileAttribs.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||||
|
oaFileAttribs.RootDirectory = pidData->dirhandle;
|
||||||
|
oaFileAttribs.ObjectName = &wstrFileName;
|
||||||
|
oaFileAttribs.Attributes = 0;
|
||||||
|
oaFileAttribs.SecurityDescriptor = NULL;
|
||||||
|
oaFileAttribs.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
/* open the file */
|
||||||
|
nErrCode = NtOpenFile
|
||||||
|
(
|
||||||
|
&hFile,
|
||||||
|
FILE_READ_ATTRIBUTES,
|
||||||
|
&oaFileAttribs,
|
||||||
|
&isbStatus,
|
||||||
|
0,
|
||||||
|
FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
ERR("NtOpenFile() failed with status %#X", nErrCode);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the internal information for the file */
|
||||||
|
nErrCode = NtQueryInformationFile
|
||||||
|
(
|
||||||
|
hFile,
|
||||||
|
&isbStatus,
|
||||||
|
&fiiInfo,
|
||||||
|
sizeof(FILE_INTERNAL_INFORMATION),
|
||||||
|
FileInternalInformation
|
||||||
|
);
|
||||||
|
|
||||||
|
/* close the handle (not needed anymore) */
|
||||||
|
NtClose(hFile);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
ERR("NtQueryInformationFile() failed with status %#X", nErrCode);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return file inode */
|
||||||
|
pidData->ent.de_unicode.d_ino = (ino_t)fiiInfo.IndexNumber.QuadPart;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FIXME("file inodes currently hardcoded to 0");
|
||||||
|
pidData->ent.de_unicode.d_ino = 0;
|
||||||
|
|
||||||
|
/* return file name */
|
||||||
|
pidData->ent.de_unicode.d_name = &pidData->info.FileName[0];
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return &(pidData->ent.de_unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _Wreaddir_r(DIR *dirp, struct _Wdirent *entry, struct _Wdirent **result)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
60
posix/lib/psxdll/dlfcn/dlclose.c
Normal file
60
posix/lib/psxdll/dlfcn/dlclose.c
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* $Id: dlclose.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dlfcn/dlclose.c
|
||||||
|
* PURPOSE: Close a dlopen() object
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/dlfcn.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
int dlclose(void *handle)
|
||||||
|
{
|
||||||
|
if(handle == 0)
|
||||||
|
{
|
||||||
|
ERR("invalid handle passed to dlclose");
|
||||||
|
|
||||||
|
__dl_set_last_error(EFAULT); /* FIXME? maybe EINVAL? */
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((struct __dlobj *)handle)->global)
|
||||||
|
{
|
||||||
|
TODO("global symbol matching not implemented");
|
||||||
|
|
||||||
|
__dl_set_last_error(EINVAL);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NTSTATUS nErrCode = LdrUnloadDll(((struct __dlobj *)handle)->handle);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
ERR("LdrUnloadDll(%#x) failed with status %d", ((struct __dlobj *)handle)->handle, nErrCode);
|
||||||
|
|
||||||
|
free(handle);
|
||||||
|
__dl_set_last_error(__status_to_errno(nErrCode));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(handle);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
36
posix/lib/psxdll/dlfcn/dlerror.c
Normal file
36
posix/lib/psxdll/dlfcn/dlerror.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* $Id: dlerror.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dlfcn/dlerror.c
|
||||||
|
* PURPOSE: Gain access to an executable object file
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/dlfcn.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
static int __dl_last_error = 0;
|
||||||
|
|
||||||
|
void __dl_set_last_error(int err)
|
||||||
|
{
|
||||||
|
FIXME("dlfcn error handling not thread safe");
|
||||||
|
__dl_last_error = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dlerror(void)
|
||||||
|
{
|
||||||
|
return strerror(__dl_last_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
129
posix/lib/psxdll/dlfcn/dlopen.c
Normal file
129
posix/lib/psxdll/dlfcn/dlopen.c
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/* $Id: dlopen.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dlfcn/dlopen.c
|
||||||
|
* PURPOSE: Gain access to an executable object file
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <psx/dlfcn.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
void *__wdlopen(const wchar_t *, int);
|
||||||
|
|
||||||
|
void *dlopen(const char *file, int mode)
|
||||||
|
{
|
||||||
|
/* TODO: ANSI-to-Unicode stubs like this need to be standardized in some way */
|
||||||
|
void * pRetVal;
|
||||||
|
ANSI_STRING strFile;
|
||||||
|
UNICODE_STRING wstrFile;
|
||||||
|
|
||||||
|
RtlInitAnsiString(&strFile, (LPSTR)file);
|
||||||
|
RtlAnsiStringToUnicodeString (&wstrFile, &strFile, TRUE);
|
||||||
|
|
||||||
|
pRetVal = __wdlopen((wchar_t *)wstrFile.Buffer, mode);
|
||||||
|
|
||||||
|
free(wstrFile.Buffer);
|
||||||
|
|
||||||
|
return pRetVal;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__wdlopen(const wchar_t *file, int mode)
|
||||||
|
{
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
UNICODE_STRING wstrNativePath;
|
||||||
|
struct __dlobj * pdloObject;
|
||||||
|
|
||||||
|
if(file == 0)
|
||||||
|
{
|
||||||
|
/* POSIX dynamic linking allows for global symbol matching */
|
||||||
|
pdloObject = (struct __dlobj *)malloc(sizeof(struct __dlobj));
|
||||||
|
|
||||||
|
TODO("\
|
||||||
|
move the global symbol matching semantics into the PE Loader \
|
||||||
|
(NTDLL Ldr family of calls), and just return a pointer to the module \
|
||||||
|
image\
|
||||||
|
");
|
||||||
|
|
||||||
|
pdloObject->global = 1;
|
||||||
|
return (pdloObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIXME("\
|
||||||
|
LdrLoadDll() only accepts DOS paths - probably because the POSIX \
|
||||||
|
standard didn't specify dynamic linking interfaces at the time Windows NT \
|
||||||
|
was born \
|
||||||
|
");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* TODO: LdrLoadNtDll() or LdrLoadDllEx() (the former is preferrable, since
|
||||||
|
the latter is more likely to be implemented with different purposes from
|
||||||
|
Microsoft), accepting native NT paths */
|
||||||
|
|
||||||
|
if(wcschr(file, '/'L) != NULL)
|
||||||
|
{
|
||||||
|
/* TODO: RtlPosixPathNameToNtPathName_U */
|
||||||
|
if(!RtlPosixPathNameToNtPathName_U((LPWSTR)file, &wstrNativePath, NULL, NULL))
|
||||||
|
{
|
||||||
|
__dl_set_last_error(ENOENT);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&wstrNativePath, (LPWSTR)file);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&wstrNativePath, (LPWSTR)file);
|
||||||
|
|
||||||
|
pdloObject = (struct __dlobj *)malloc(sizeof(struct __dlobj));
|
||||||
|
pdloObject->global = 0;
|
||||||
|
|
||||||
|
WARN("\
|
||||||
|
mode flags are not fully supported by Windows NT, due to the \
|
||||||
|
completely different semantics of dynamical linking (for \
|
||||||
|
example the global symbol matching is unsupported). This \
|
||||||
|
implementation will then behave as if mode was set to \
|
||||||
|
(RTLD_NOW | RTLD_GLOBAL), and fail if other flags are set.\
|
||||||
|
");
|
||||||
|
|
||||||
|
if(__dl_get_scope_flag(mode) == RTLD_LOCAL)
|
||||||
|
{
|
||||||
|
__dl_set_last_error(EINVAL);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load the DLL */
|
||||||
|
nErrCode = LdrLoadDll
|
||||||
|
(
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&wstrNativePath,
|
||||||
|
(PVOID*)&pdloObject->handle
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
__dl_set_last_error(__status_to_errno(nErrCode));
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pdloObject);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
92
posix/lib/psxdll/dlfcn/dlsym.c
Normal file
92
posix/lib/psxdll/dlfcn/dlsym.c
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/* $Id: dlsym.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/dlfcn/dlsym.c
|
||||||
|
* PURPOSE: Obtain the address of a symbol from a dlopen() object
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <psx/dlfcn.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
void *__dlsymn(void *, unsigned long int);
|
||||||
|
void *__dlsym(void *, int, const char *, unsigned long int);
|
||||||
|
|
||||||
|
void *dlsym(void *handle, const char *name)
|
||||||
|
{
|
||||||
|
return (__dlsym(handle, 1, name, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__dlsymn(void *handle, unsigned long int ordinal)
|
||||||
|
{
|
||||||
|
return (__dlsym(handle, 0, 0, ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__dlsym(void *handle, int by_name, const char *name, unsigned long int ordinal)
|
||||||
|
{
|
||||||
|
struct __dlobj * pdloObject;
|
||||||
|
|
||||||
|
void * pProcAddr;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
if(handle == RTLD_NEXT)
|
||||||
|
{
|
||||||
|
FIXME("implement RTLD_NEXT semantics");
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pdloObject = (struct __dlobj *) handle;
|
||||||
|
|
||||||
|
if(pdloObject->global)
|
||||||
|
{
|
||||||
|
FIXME("implement global symbol matching");
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(by_name)
|
||||||
|
{
|
||||||
|
ANSI_STRING strName;
|
||||||
|
|
||||||
|
RtlInitAnsiString(&strName, (LPSTR)name);
|
||||||
|
|
||||||
|
nErrCode = LdrGetProcedureAddress
|
||||||
|
(
|
||||||
|
pdloObject->handle,
|
||||||
|
&strName,
|
||||||
|
0,
|
||||||
|
(PVOID *)&pProcAddr
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nErrCode = LdrGetProcedureAddress
|
||||||
|
(
|
||||||
|
pdloObject->handle,
|
||||||
|
NULL,
|
||||||
|
ordinal,
|
||||||
|
(PVOID *)&pProcAddr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
__dl_set_last_error(__status_to_errno(nErrCode));
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pProcAddr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
25
posix/lib/psxdll/errno/errno.c
Normal file
25
posix/lib/psxdll/errno/errno.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* $Id: errno.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/errno/errno.c
|
||||||
|
* PURPOSE: Internal errno implementation
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
static int __errno_storage = 0;
|
||||||
|
|
||||||
|
int * __PdxGetThreadErrNum(void)
|
||||||
|
{
|
||||||
|
FIXME("errno currently not thread-safe");
|
||||||
|
return (&__errno_storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
311
posix/lib/psxdll/fcntl/fcntl.c
Normal file
311
posix/lib/psxdll/fcntl/fcntl.c
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
/* $Id: fcntl.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/fcntl/fcntl.c
|
||||||
|
* PURPOSE: File control
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 13/02/2002: Created
|
||||||
|
* 15/02/2002: Implemented fcntl() (KJK::Hyperion)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/fdtable.h>
|
||||||
|
#include <psx/pdata.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
int fcntl(int fildes, int cmd, ...)
|
||||||
|
{
|
||||||
|
__fdtable_t *pftFdTable;
|
||||||
|
__fildes_t *pfdDescriptor;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
int nRetVal;
|
||||||
|
int nThirdArg;
|
||||||
|
void *pThirdArg;
|
||||||
|
va_list vlArgs;
|
||||||
|
|
||||||
|
/* lock the environment */
|
||||||
|
__PdxAcquirePdataLock();
|
||||||
|
|
||||||
|
/* get the file descriptors table */
|
||||||
|
pftFdTable = __PdxGetProcessData()->FdTable;
|
||||||
|
|
||||||
|
/* fildes is an invalid, closed or uninitialized descriptor */
|
||||||
|
if
|
||||||
|
(
|
||||||
|
fildes < 0 ||
|
||||||
|
fildes >= OPEN_MAX ||
|
||||||
|
__fdtable_entry_isavail(pftFdTable, fildes) == 0 ||
|
||||||
|
__fdtable_entry_get(pftFdTable, fildes) == 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the file descriptor referenced by fildes */
|
||||||
|
pfdDescriptor = __fdtable_entry_get(pftFdTable, fildes);
|
||||||
|
|
||||||
|
/* get third argument as integer */
|
||||||
|
va_start(vlArgs, cmd);
|
||||||
|
nThirdArg = va_arg(vlArgs, int);
|
||||||
|
va_end(vlArgs);
|
||||||
|
|
||||||
|
/* get third argument as pointer */
|
||||||
|
va_start(vlArgs, cmd);
|
||||||
|
pThirdArg = va_arg(vlArgs, void *);
|
||||||
|
va_end(vlArgs);
|
||||||
|
|
||||||
|
/* initialize return value */
|
||||||
|
nRetVal = -1;
|
||||||
|
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case F_DUPFD:
|
||||||
|
{
|
||||||
|
va_list vlArgs;
|
||||||
|
int nDupFileNo;
|
||||||
|
__fildes_t *pfdDupDescriptor;
|
||||||
|
|
||||||
|
/* allocate the duplicated descriptor */
|
||||||
|
nDupFileNo = __fdtable_entry_add(pftFdTable, nThirdArg, 0, &pfdDupDescriptor);
|
||||||
|
|
||||||
|
if(nDupFileNo)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* copy the open flags */
|
||||||
|
pfdDupDescriptor->OpenFlags = pfdDescriptor->OpenFlags;
|
||||||
|
|
||||||
|
/* clear the FD_CLOEXEC flag */
|
||||||
|
pfdDupDescriptor->FdFlags = pfdDescriptor->FdFlags & ~FD_CLOEXEC;
|
||||||
|
|
||||||
|
/* duplicate the extra data */
|
||||||
|
if(pfdDescriptor->ExtraDataSize != 0 && pfdDescriptor->ExtraData != 0)
|
||||||
|
{
|
||||||
|
/* allocate space for the duplicated extra data */
|
||||||
|
pfdDupDescriptor->ExtraDataSize = pfdDescriptor->ExtraDataSize;
|
||||||
|
pfdDupDescriptor->ExtraData = __malloc(pfdDupDescriptor->ExtraDataSize);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(pfdDupDescriptor->ExtraData == 0)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy the extra data */
|
||||||
|
memcpy(pfdDupDescriptor->ExtraData, pfdDescriptor->ExtraData, pfdDupDescriptor->ExtraDataSize);
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
"copied %u bytes from 0x%08X into 0x%08X",
|
||||||
|
pfdDupDescriptor->ExtraDataSize,
|
||||||
|
pfdDescriptor->ExtraData,
|
||||||
|
pfdDupDescriptor->ExtraData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* duplicate the handle */
|
||||||
|
nErrCode = NtDuplicateObject
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
pfdDescriptor->FileHandle,
|
||||||
|
NtCurrentProcess(),
|
||||||
|
&pfdDupDescriptor->FileHandle,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DUPLICATE_SAME_ACCESS /* | DUPLICATE_SAME_ATTRIBUTES */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
__free(pfdDupDescriptor->ExtraData);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
"duplicated handle 0x%08X into handle 0x%08X",
|
||||||
|
pfdDescriptor->FileHandle,
|
||||||
|
pfdDupDescriptor->FileHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
/* return the duplicated file number */
|
||||||
|
nRetVal = nDupFileNo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETFD:
|
||||||
|
{
|
||||||
|
nRetVal = pfdDescriptor->FdFlags;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETFD:
|
||||||
|
{
|
||||||
|
pfdDescriptor->FdFlags = nThirdArg;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETFL:
|
||||||
|
{
|
||||||
|
nRetVal = pfdDescriptor->OpenFlags;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETFL:
|
||||||
|
{
|
||||||
|
pfdDescriptor->OpenFlags = nThirdArg;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETLK:
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETLK:
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETLKW:
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_NEWFD:
|
||||||
|
{
|
||||||
|
/* allocate a new descriptor */
|
||||||
|
nRetVal = __fdtable_entry_add(pftFdTable, fildes, (__fildes_t *)pThirdArg, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_DELFD:
|
||||||
|
{
|
||||||
|
/* invalid return pointer */
|
||||||
|
if(pThirdArg == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((__fildes_t *)pThirdArg, pfdDescriptor, sizeof(*pfdDescriptor));
|
||||||
|
|
||||||
|
/* remove file descriptor */
|
||||||
|
nRetVal = __fdtable_entry_remove(pftFdTable, fildes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETALL:
|
||||||
|
{
|
||||||
|
/* invalid return pointer */
|
||||||
|
if(pThirdArg == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return a copy of the file descriptor */
|
||||||
|
memcpy((__fildes_t *)pThirdArg, pfdDescriptor, sizeof(*pfdDescriptor));
|
||||||
|
nRetVal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETALL:
|
||||||
|
{
|
||||||
|
/* invalid file descriptor to copy attributes from */
|
||||||
|
if(pThirdArg == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy the attributes of file descriptor from the provided descriptor */
|
||||||
|
memcpy(pfdDescriptor, pThirdArg, sizeof(*pfdDescriptor));
|
||||||
|
nRetVal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETXP:
|
||||||
|
{
|
||||||
|
/* invalid return pointer */
|
||||||
|
if(pThirdArg == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return a pointer to the extra data associated to the descriptor */
|
||||||
|
*((void **)pThirdArg) = pfdDescriptor->ExtraData;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETXP:
|
||||||
|
{
|
||||||
|
/* set the pointer to the extra data associated */
|
||||||
|
pfdDescriptor->ExtraData = pThirdArg;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETXS:
|
||||||
|
{
|
||||||
|
nRetVal = pfdDescriptor->ExtraDataSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETXS:
|
||||||
|
{
|
||||||
|
pfdDescriptor->ExtraDataSize = nThirdArg;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_GETFH:
|
||||||
|
{
|
||||||
|
/* invalid return pointer */
|
||||||
|
if(pThirdArg == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the handle associated to the descriptor */
|
||||||
|
*((void **)pThirdArg) = pfdDescriptor->FileHandle;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case F_SETFH:
|
||||||
|
{
|
||||||
|
pfdDescriptor->FileHandle = pThirdArg;
|
||||||
|
nRetVal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock the environment */
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
|
||||||
|
return (nRetVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
181
posix/lib/psxdll/fcntl/open.c
Normal file
181
posix/lib/psxdll/fcntl/open.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/* $Id: open.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/fcntl/open.c
|
||||||
|
* PURPOSE: Open a file
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 04/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <psx/path.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/pdata.h>
|
||||||
|
|
||||||
|
int open(const char *path, int oflag, ...)
|
||||||
|
{
|
||||||
|
ANSI_STRING strPath;
|
||||||
|
UNICODE_STRING wstrPath;
|
||||||
|
int nRetVal;
|
||||||
|
|
||||||
|
RtlInitAnsiString(&strPath, (PCSZ)path);
|
||||||
|
RtlAnsiStringToUnicodeString(&wstrPath, &strPath, TRUE);
|
||||||
|
|
||||||
|
nRetVal = _Wopen(wstrPath.Buffer, oflag);
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&wstrPath);
|
||||||
|
|
||||||
|
return (nRetVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _Wopen(const wchar_t *path, int oflag, ...)
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES oaFileAttribs;
|
||||||
|
IO_STATUS_BLOCK isbStatus;
|
||||||
|
UNICODE_STRING wstrNativePath;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
ULONG nDesiredAccess;
|
||||||
|
ULONG nCreateDisposition;
|
||||||
|
ULONG nCreateOptions;
|
||||||
|
HANDLE hFile;
|
||||||
|
#if 0
|
||||||
|
mode_t mFileMode;
|
||||||
|
#endif
|
||||||
|
int nFileNo;
|
||||||
|
__fdtable_t *pftTable;
|
||||||
|
__fildes_t fdDescriptor;
|
||||||
|
|
||||||
|
/* translate file access flag */
|
||||||
|
switch(oflag & O_ACCMODE)
|
||||||
|
{
|
||||||
|
case O_RDONLY:
|
||||||
|
{
|
||||||
|
nDesiredAccess = FILE_READ_ACCESS;
|
||||||
|
nCreateOptions = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case O_WRONLY:
|
||||||
|
{
|
||||||
|
nDesiredAccess = FILE_WRITE_ACCESS;
|
||||||
|
nCreateOptions = FILE_NON_DIRECTORY_FILE; /* required by the specification */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case O_RDWR:
|
||||||
|
{
|
||||||
|
nDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS;
|
||||||
|
nCreateOptions = FILE_NON_DIRECTORY_FILE; /* required by the specification */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* miscellaneous flags */
|
||||||
|
if((oflag & _O_DIRFILE) == _O_DIRFILE)
|
||||||
|
nCreateOptions |= FILE_DIRECTORY_FILE;
|
||||||
|
|
||||||
|
/* creation disposition */
|
||||||
|
if((oflag & O_CREAT) == O_CREAT)
|
||||||
|
if((oflag & O_EXCL) == O_EXCL)
|
||||||
|
nCreateDisposition = FILE_CREATE; /* O_CREAT + O_EXCL: create file, fail if file exists */
|
||||||
|
else
|
||||||
|
nCreateDisposition = FILE_OPEN_IF; /* O_CREAT: open file, create if file doesn't exist */
|
||||||
|
else if((oflag & O_TRUNC) == O_TRUNC)
|
||||||
|
nCreateDisposition = FILE_OVERWRITE; /* O_TRUNC: truncate existing file */
|
||||||
|
else
|
||||||
|
nCreateDisposition = FILE_OPEN; /* normal: open file, fail if file doesn't exist */
|
||||||
|
|
||||||
|
/* lock the environment */
|
||||||
|
__PdxAcquirePdataLock();
|
||||||
|
|
||||||
|
/* convert the path into a native path */
|
||||||
|
if(!__PdxPosixPathNameToNtPathName((LPWSTR)path, __PdxGetNativePathBuffer(), __PdxGetCurDir(), NULL))
|
||||||
|
{
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set file generic object attributes */
|
||||||
|
oaFileAttribs.Length = sizeof(oaFileAttribs);
|
||||||
|
oaFileAttribs.RootDirectory = __PdxGetRootHandle();
|
||||||
|
oaFileAttribs.ObjectName = &wstrNativePath;
|
||||||
|
oaFileAttribs.Attributes = OBJ_INHERIT; /* child processes inherit all file descriptors */
|
||||||
|
oaFileAttribs.SecurityDescriptor = NULL;
|
||||||
|
oaFileAttribs.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
/* open or create the file */
|
||||||
|
nErrCode = NtCreateFile
|
||||||
|
(
|
||||||
|
&hFile,
|
||||||
|
nDesiredAccess | SYNCHRONIZE,
|
||||||
|
&oaFileAttribs,
|
||||||
|
&isbStatus,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
nCreateDisposition,
|
||||||
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||||
|
NULL,
|
||||||
|
nCreateOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
ERR("NtCreateFile() failed with status 0x%08X", nErrCode);
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize descriptor constructor */
|
||||||
|
memset(&fdDescriptor, 0, sizeof(fdDescriptor));
|
||||||
|
fdDescriptor.FileHandle = hFile;
|
||||||
|
fdDescriptor.OpenFlags = oflag;
|
||||||
|
|
||||||
|
/* allocate a new file descriptor */
|
||||||
|
nFileNo = fcntl(0, F_NEWFD, &fdDescriptor);
|
||||||
|
|
||||||
|
/* unlock the environment */
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
|
||||||
|
/* could not allocate the file descriptor */
|
||||||
|
if(nFileNo < 0)
|
||||||
|
{
|
||||||
|
NtClose(hFile);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the file number */
|
||||||
|
return (nFileNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int creat(const char *path, mode_t mode)
|
||||||
|
{
|
||||||
|
return (open(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
int _Wcreat(const wchar_t *path, mode_t mode)
|
||||||
|
{
|
||||||
|
return (_Wopen(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
114
posix/lib/psxdll/libgen/basename.c
Normal file
114
posix/lib/psxdll/libgen/basename.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/* $Id: basename.c,v 1.1 2002/02/20 07:06:51 hyperion Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/libgen/basename.c
|
||||||
|
* PURPOSE: Return the last component of a pathname
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <psx/path.h>
|
||||||
|
|
||||||
|
static const char *__basename_dot = ".";
|
||||||
|
static const wchar_t *__Wbasename_dot = L".";
|
||||||
|
|
||||||
|
char *basename(char *path)
|
||||||
|
{
|
||||||
|
char *pcTail;
|
||||||
|
size_t nStrLen;
|
||||||
|
|
||||||
|
/* null or empty string */
|
||||||
|
if(path == 0 && ((nStrLen = strlen(path)) == 0))
|
||||||
|
return ((char *)__basename_dot);
|
||||||
|
|
||||||
|
if(nStrLen == 1)
|
||||||
|
{
|
||||||
|
/* path is "/", return "/" */
|
||||||
|
if(IS_CHAR_DELIMITER_A(path[0]))
|
||||||
|
{
|
||||||
|
path[0] = '/';
|
||||||
|
path[1] = 0;
|
||||||
|
return (path);
|
||||||
|
}
|
||||||
|
/* path is a single character, return it */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tail of the string (null terminator excluded) */
|
||||||
|
pcTail = &path[nStrLen - 1];
|
||||||
|
|
||||||
|
/* skip trailing slashes */
|
||||||
|
while(pcTail > path && IS_CHAR_DELIMITER_A(*pcTail))
|
||||||
|
pcTail --;
|
||||||
|
|
||||||
|
pcTail[1] = 0;
|
||||||
|
|
||||||
|
/* go backwards until a delimiter char or the beginning of the string */
|
||||||
|
while(pcTail >= path)
|
||||||
|
/* delimiter found, return the basename */
|
||||||
|
if(IS_CHAR_DELIMITER_A(*pcTail))
|
||||||
|
return (&pcTail[1]);
|
||||||
|
else
|
||||||
|
pcTail --;
|
||||||
|
|
||||||
|
/* return all the path */
|
||||||
|
return (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *_Wbasename(wchar_t *path)
|
||||||
|
{
|
||||||
|
wchar_t *pwcTail;
|
||||||
|
size_t nStrLen;
|
||||||
|
|
||||||
|
/* null or empty string */
|
||||||
|
if(path == 0 && ((nStrLen = wcslen(path)) == 0))
|
||||||
|
return ((wchar_t *)__Wbasename_dot);
|
||||||
|
|
||||||
|
if(nStrLen == 1)
|
||||||
|
{
|
||||||
|
/* path is "/", return "/" */
|
||||||
|
if(IS_CHAR_DELIMITER_U(path[0]))
|
||||||
|
{
|
||||||
|
path[0] = L'/';
|
||||||
|
path[1] = 0;
|
||||||
|
return (path);
|
||||||
|
}
|
||||||
|
/* path is a single character, return it */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tail of the string (null terminator excluded) */
|
||||||
|
pwcTail = &path[nStrLen - 1];
|
||||||
|
|
||||||
|
/* skip trailing slashes */
|
||||||
|
while(pwcTail > path && IS_CHAR_DELIMITER_U(*pwcTail))
|
||||||
|
pwcTail --;
|
||||||
|
|
||||||
|
pwcTail[1] = 0;
|
||||||
|
|
||||||
|
/* go backwards until a delimiter char or the beginning of the string */
|
||||||
|
while(pwcTail >= path)
|
||||||
|
/* delimiter found, return the basename */
|
||||||
|
if(IS_CHAR_DELIMITER_U(*pwcTail))
|
||||||
|
return (&pwcTail[1]);
|
||||||
|
else
|
||||||
|
pwcTail --;
|
||||||
|
|
||||||
|
/* return all the path */
|
||||||
|
return (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
234
posix/lib/psxdll/misc/fdtable.c
Normal file
234
posix/lib/psxdll/misc/fdtable.c
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/misc/fdtable.c
|
||||||
|
* PURPOSE: File descriptors table functions
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 12/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <psx/fdtable.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/safeobj.h>
|
||||||
|
|
||||||
|
int __fdtable_init(__fdtable_t * fdtable)
|
||||||
|
{
|
||||||
|
if(fdtable == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(fdtable, 0, sizeof(*fdtable));
|
||||||
|
|
||||||
|
fdtable->Signature = __FDTABLE_MAGIC;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __fdtable_free(__fdtable_t * fdtable)
|
||||||
|
{
|
||||||
|
if(fdtable == 0)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
__free(&fdtable->Descriptors);
|
||||||
|
|
||||||
|
memset(fdtable, 0, sizeof(*fdtable));
|
||||||
|
|
||||||
|
fdtable->Signature = MAGIC('B', 'A', 'A', 'D');
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __fdtable_entry_isavail(__fdtable_t * fdtable, int fileno)
|
||||||
|
{
|
||||||
|
return ((fdtable->DescriptorsBitmap[fileno / 32] >> (fileno % 32)) % 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __fdtable_entry_nextavail(__fdtable_t * fdtable, int fileno)
|
||||||
|
{
|
||||||
|
int nCurMapIndex;
|
||||||
|
int nUnusedIndex;
|
||||||
|
uint32_t nCurMapCell;
|
||||||
|
|
||||||
|
nUnusedIndex = fileno;
|
||||||
|
|
||||||
|
/* The file descriptors bitmap is an array of 32 bit unsigned integers (32 bit
|
||||||
|
integers were chosen for proper data alignment without padding). The array is
|
||||||
|
big enough to hold at least OPEN_MAX bits, that is it has OPEN_MAX / 32 cells
|
||||||
|
(see also the __fdtable_t definition in psx/fdtable.h). Bits correspond to
|
||||||
|
file numbers: if a bit is 1, the corresponding file number is in use, else
|
||||||
|
it's unused. Bit numbering is right-to-left wise, that is the rightmost (least
|
||||||
|
significative) bit of cell 0 corresponds to file number 0, the leftmost (most
|
||||||
|
significative) bit of cell 0 to file number 7, the leftmost bit of cell 1 to
|
||||||
|
file number 8, and so on
|
||||||
|
*/
|
||||||
|
/* NOTE: I'm sure the algorytm can be greatly optimized, but I prefer to privilege
|
||||||
|
readability - it allows for more maintenable code. Please don't pretend to
|
||||||
|
outsmart the compiler: such optimizations as performing divisions as bit shifts
|
||||||
|
are useless */
|
||||||
|
|
||||||
|
/* index of the bitmap cell containing nUnusedIndex */
|
||||||
|
nCurMapIndex = nUnusedIndex / 32;
|
||||||
|
|
||||||
|
/* get a copy of the bitmap cell containg nUnusedIndex, and shift it to the right
|
||||||
|
so that the rightmost (least significative) bit is the one referencing nUnusedIndex */
|
||||||
|
nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex] >> (nUnusedIndex % 32);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
/* if the least significative bit of the current cell is 0, we've found an unused
|
||||||
|
fileno, and we return it */
|
||||||
|
if((nCurMapCell % 2) == 0)
|
||||||
|
return (nUnusedIndex);
|
||||||
|
|
||||||
|
/* on to next fileno */
|
||||||
|
nUnusedIndex ++;
|
||||||
|
|
||||||
|
/* this is NOT a failure. -1 with undefined errno means that no unused file
|
||||||
|
number exists */
|
||||||
|
if(nUnusedIndex >= OPEN_MAX)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/* this fileno is referenced in the next cell */
|
||||||
|
if((nUnusedIndex % 32) == 0)
|
||||||
|
{
|
||||||
|
nCurMapIndex ++;
|
||||||
|
nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex];
|
||||||
|
}
|
||||||
|
/* on to next fileno (bit) in the current cell */
|
||||||
|
else
|
||||||
|
nCurMapCell >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __fdtable_entry_add(__fdtable_t * fdtable, int fileno, __fildes_t * fildes, __fildes_t ** newfd)
|
||||||
|
{
|
||||||
|
int nFileNo;
|
||||||
|
|
||||||
|
/* descriptors count reached OPEN_MAX */
|
||||||
|
if(fdtable->UsedDescriptors >= OPEN_MAX)
|
||||||
|
{
|
||||||
|
ERR("file descriptor table full");
|
||||||
|
errno = EMFILE;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base fileno less than zero: use the lowest unused fileno */
|
||||||
|
if(fileno < 0)
|
||||||
|
nFileNo = fdtable->LowestUnusedFileNo;
|
||||||
|
/* base fileno greater than or equal to zero: use the next available fileno */
|
||||||
|
else
|
||||||
|
nFileNo = __fdtable_entry_nextavail(fdtable, fileno);
|
||||||
|
|
||||||
|
INFO("lowest unused file number is %d", nFileNo);
|
||||||
|
|
||||||
|
/* descriptors count reached OPEN_MAX */
|
||||||
|
if(nFileNo < 0)
|
||||||
|
{
|
||||||
|
ERR("nFileNo is less than zero");
|
||||||
|
errno = EMFILE;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if the table doesn't have enough space for the next entry ... */
|
||||||
|
if(nFileNo >= fdtable->AllocatedDescriptors)
|
||||||
|
{
|
||||||
|
void * pTemp;
|
||||||
|
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
"growing the array from %lu to %lu bytes",
|
||||||
|
fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors),
|
||||||
|
(nFileNo + 1) * sizeof(*fdtable->Descriptors)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ... try to increase the size of the table */
|
||||||
|
pTemp = __realloc
|
||||||
|
(
|
||||||
|
fdtable->Descriptors,
|
||||||
|
(nFileNo + 1) * sizeof(*fdtable->Descriptors)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* reallocation failed */
|
||||||
|
if(pTemp == 0)
|
||||||
|
{
|
||||||
|
ERR("__realloc() failed");
|
||||||
|
errno = ENOMEM;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the table */
|
||||||
|
fdtable->AllocatedDescriptors = nFileNo + 1;
|
||||||
|
fdtable->Descriptors = pTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize descriptor */
|
||||||
|
if(fildes == 0)
|
||||||
|
memset(&fdtable->Descriptors[nFileNo], 0, sizeof(__fildes_t));
|
||||||
|
else
|
||||||
|
memcpy(&fdtable->Descriptors[nFileNo], fildes, sizeof(__fildes_t));
|
||||||
|
|
||||||
|
if(newfd != 0)
|
||||||
|
*newfd = &fdtable->Descriptors[nFileNo];
|
||||||
|
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
"file number %d: handle 0x%08X, open flags 0x%08X, flags 0x%08X, extra data size %u, extra data at 0x%08X",
|
||||||
|
nFileNo,
|
||||||
|
fdtable->Descriptors[nFileNo].FileHandle,
|
||||||
|
fdtable->Descriptors[nFileNo].OpenFlags,
|
||||||
|
fdtable->Descriptors[nFileNo].FdFlags,
|
||||||
|
fdtable->Descriptors[nFileNo].ExtraDataSize,
|
||||||
|
fdtable->Descriptors[nFileNo].ExtraData
|
||||||
|
);
|
||||||
|
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
"incrementing used descriptors count from %u to %u",
|
||||||
|
fdtable->UsedDescriptors,
|
||||||
|
fdtable->UsedDescriptors + 1
|
||||||
|
);
|
||||||
|
fdtable->UsedDescriptors ++;
|
||||||
|
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
"setting bit %u of cell %u of the bitmap to 1",
|
||||||
|
nFileNo % 32,
|
||||||
|
nFileNo / 32
|
||||||
|
);
|
||||||
|
fdtable->DescriptorsBitmap[nFileNo / 32] |= (1 << (nFileNo % 32));
|
||||||
|
|
||||||
|
fdtable->LowestUnusedFileNo = __fdtable_entry_nextavail(fdtable, nFileNo);
|
||||||
|
INFO("setting the lowest unused file number to %d", fdtable->LowestUnusedFileNo);
|
||||||
|
|
||||||
|
return (nFileNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __fdtable_entry_remove(__fdtable_t * fdtable, int fileno)
|
||||||
|
{
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
__fildes_t *__fdtable_entry_get(__fdtable_t * fdtable, int fileno)
|
||||||
|
{
|
||||||
|
/* this fileno hasn't been allocated */
|
||||||
|
if(fileno >= fdtable->AllocatedDescriptors)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
return (&fdtable->Descriptors[fileno]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
83
posix/lib/psxdll/misc/interlock.c
Normal file
83
posix/lib/psxdll/misc/interlock.c
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/misc/interlock.c
|
||||||
|
* PURPOSE: inter-locked increments/decrements
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 20/01/2002: Adapted from lib/kernel32/synch/intrlck.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE by KJK::Hyperion: I do not understand what's behind these functions.
|
||||||
|
* Don't ask me how they work, or to fix errors in them.
|
||||||
|
* Please refer to the authors referenced in the original
|
||||||
|
* file, lib/kernel32/synch/intrlck.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO? move these in some shared library */
|
||||||
|
|
||||||
|
#include <psx/interlock.h>
|
||||||
|
|
||||||
|
int __interlock_inc(int * addend)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
__asm__
|
||||||
|
(
|
||||||
|
" lock\n" /* for SMP systems */
|
||||||
|
" incl (%1)\n"
|
||||||
|
" je 2f\n"
|
||||||
|
" jl 1f\n"
|
||||||
|
" incl %0\n"
|
||||||
|
" jmp 2f\n"
|
||||||
|
"1: dec %0\n"
|
||||||
|
"2:\n"
|
||||||
|
:"=r" (ret):"r" (addend), "0" (0): "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __interlock_dec(int * addend)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
__asm__
|
||||||
|
(
|
||||||
|
" lock\n" /* for SMP systems */
|
||||||
|
" decl (%1)\n"
|
||||||
|
" je 2f\n"
|
||||||
|
" jl 1f\n"
|
||||||
|
" incl %0\n"
|
||||||
|
" jmp 2f\n"
|
||||||
|
"1: dec %0\n"
|
||||||
|
"2:\n"
|
||||||
|
:"=r" (ret):"r" (addend), "0" (0): "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int __interlock_add(int * addend, int increment)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
__asm__
|
||||||
|
(
|
||||||
|
" lock\n" /* for SMP systems */
|
||||||
|
" xaddl %0,(%1)"
|
||||||
|
:"=r" (ret)
|
||||||
|
:"r" (addend), "0" (increment)
|
||||||
|
:"memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
19
posix/lib/psxdll/misc/main.c
Normal file
19
posix/lib/psxdll/misc/main.c
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/misc/main.c
|
||||||
|
* PURPOSE: psxdll.dll entry point
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
int __stdcall DllMain(void *hinstDll, unsigned long int dwReason, void *reserved)
|
||||||
|
{
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
460
posix/lib/psxdll/misc/path.c
Normal file
460
posix/lib/psxdll/misc/path.c
Normal file
|
@ -0,0 +1,460 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/misc/path.c
|
||||||
|
* PURPOSE: POSIX subsystem path utilities
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 31/01/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/pdata.h>
|
||||||
|
#include <psx/path.h>
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
__PdxPosixPathGetNextComponent_U
|
||||||
|
(
|
||||||
|
IN UNICODE_STRING PathName,
|
||||||
|
IN OUT PUNICODE_STRING PathComponent,
|
||||||
|
OUT PBOOLEAN TrailingDelimiter OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
USHORT l = PathName.Length / sizeof(WCHAR);
|
||||||
|
|
||||||
|
if(PathComponent->Buffer == 0)
|
||||||
|
i = 0;
|
||||||
|
else
|
||||||
|
i = ((ULONG)PathComponent->Buffer - (ULONG)PathName.Buffer + PathComponent->Length) / sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* skip leading empty components */
|
||||||
|
while(1)
|
||||||
|
if(i >= l)
|
||||||
|
{
|
||||||
|
PathComponent->Length = PathComponent->MaximumLength = 0;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
else if(IS_CHAR_DELIMITER_U(PathName.Buffer[i]))
|
||||||
|
i ++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(i > l)
|
||||||
|
{
|
||||||
|
PathComponent->Length = PathComponent->MaximumLength = 0;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PathComponent->Buffer = &PathName.Buffer[i];
|
||||||
|
|
||||||
|
j = i + 1;
|
||||||
|
|
||||||
|
/* advance until the end of the string, or the next delimiter */
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if(j >= l)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(TrailingDelimiter != 0)
|
||||||
|
*TrailingDelimiter = FALSE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (IS_CHAR_DELIMITER_U(PathName.Buffer[j]))
|
||||||
|
{
|
||||||
|
|
||||||
|
if(TrailingDelimiter != 0)
|
||||||
|
*TrailingDelimiter = TRUE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
j ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathComponent->Length = PathComponent->MaximumLength = (j - i) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
__PdxPosixPathResolve_U
|
||||||
|
(
|
||||||
|
IN UNICODE_STRING PathName,
|
||||||
|
OUT PUNICODE_STRING ResolvedPathName,
|
||||||
|
IN WCHAR PathDelimiter OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UNICODE_STRING wstrThisComponent = {0, 0, NULL};
|
||||||
|
PWCHAR pwcCurPos;
|
||||||
|
PWCHAR pwcStartPos;
|
||||||
|
BOOLEAN bIsDirectory;
|
||||||
|
|
||||||
|
if(PathDelimiter == 0)
|
||||||
|
PathDelimiter = L'/';
|
||||||
|
|
||||||
|
/* start from the beginning of the return buffer */
|
||||||
|
pwcCurPos = ResolvedPathName->Buffer;
|
||||||
|
|
||||||
|
/* path begins with a delimiter (absolute path) */
|
||||||
|
if(IS_CHAR_DELIMITER_U(PathName.Buffer[0]))
|
||||||
|
{
|
||||||
|
/* put a delimiter in front of the return buffer */
|
||||||
|
*pwcCurPos = PathDelimiter;
|
||||||
|
/* move to next character */
|
||||||
|
pwcCurPos ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwcStartPos = pwcCurPos;
|
||||||
|
|
||||||
|
/* repeat until the end of the path string */
|
||||||
|
while(__PdxPosixPathGetNextComponent_U(PathName, &wstrThisComponent, &bIsDirectory))
|
||||||
|
{
|
||||||
|
/* ".": skip */
|
||||||
|
if(IS_COMPONENT_DOT_U(wstrThisComponent))
|
||||||
|
continue;
|
||||||
|
/* "..": go back to the last component */
|
||||||
|
else if(IS_COMPONENT_DOTDOT_U(wstrThisComponent))
|
||||||
|
{
|
||||||
|
if(pwcCurPos == pwcStartPos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* skip the last (undefined) character */
|
||||||
|
pwcCurPos --;
|
||||||
|
/* down to the previous path delimiter */
|
||||||
|
do{ pwcCurPos --; }while(!IS_CHAR_DELIMITER_U(*pwcCurPos));
|
||||||
|
/* include the delimiter */
|
||||||
|
pwcCurPos ++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* copy this component into the return string */
|
||||||
|
memcpy
|
||||||
|
(
|
||||||
|
pwcCurPos,
|
||||||
|
wstrThisComponent.Buffer,
|
||||||
|
wstrThisComponent.Length
|
||||||
|
);
|
||||||
|
|
||||||
|
/* move the current position to the end of the string */
|
||||||
|
pwcCurPos = (PWCHAR)((PBYTE)pwcCurPos + wstrThisComponent.Length);
|
||||||
|
|
||||||
|
/* component had a trailing delimiter */
|
||||||
|
if(bIsDirectory)
|
||||||
|
{
|
||||||
|
/* append a delimiter */
|
||||||
|
*pwcCurPos = PathDelimiter;
|
||||||
|
/* on to next character */
|
||||||
|
pwcCurPos ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the return string's length as the byte offset between the initial buffer
|
||||||
|
position and the current position */
|
||||||
|
ResolvedPathName->Length = ((ULONG)pwcCurPos - (ULONG)ResolvedPathName->Buffer);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
__PdxPosixPathGetNextComponent_A
|
||||||
|
(
|
||||||
|
IN ANSI_STRING PathName,
|
||||||
|
IN OUT PANSI_STRING PathComponent,
|
||||||
|
OUT PBOOLEAN TrailingDelimiter OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if(PathComponent->Buffer == 0)
|
||||||
|
i = 0;
|
||||||
|
else
|
||||||
|
i = ((ULONG)PathComponent->Buffer - (ULONG)PathName.Buffer + PathComponent->Length);
|
||||||
|
|
||||||
|
/* skip leading empty components */
|
||||||
|
while(1)
|
||||||
|
if(i >= PathName.Length)
|
||||||
|
{
|
||||||
|
PathComponent->Length = PathComponent->MaximumLength = 0;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
else if(IS_CHAR_DELIMITER_A(PathName.Buffer[i]))
|
||||||
|
i ++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(i > PathName.Length)
|
||||||
|
{
|
||||||
|
PathComponent->Length = PathComponent->MaximumLength = 0;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PathComponent->Buffer = &PathName.Buffer[i];
|
||||||
|
|
||||||
|
j = i + 1;
|
||||||
|
|
||||||
|
/* advance until the end of the string, or the next delimiter */
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if(j >= PathName.Length)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(TrailingDelimiter != 0)
|
||||||
|
*TrailingDelimiter = FALSE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (IS_CHAR_DELIMITER_A(PathName.Buffer[j]))
|
||||||
|
{
|
||||||
|
|
||||||
|
if(TrailingDelimiter != 0)
|
||||||
|
*TrailingDelimiter = TRUE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
j ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathComponent->Length = PathComponent->MaximumLength = j - i;
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
__PdxPosixPathResolve_A
|
||||||
|
(
|
||||||
|
IN ANSI_STRING PathName,
|
||||||
|
OUT PANSI_STRING ResolvedPathName,
|
||||||
|
IN CHAR PathDelimiter OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ANSI_STRING strThisComponent = {0, 0, NULL};
|
||||||
|
PCHAR pcCurPos;
|
||||||
|
PCHAR pcStartPos;
|
||||||
|
BOOLEAN bIsDirectory;
|
||||||
|
|
||||||
|
if(PathDelimiter == 0)
|
||||||
|
PathDelimiter = '/';
|
||||||
|
|
||||||
|
/* start from the beginning of the return buffer */
|
||||||
|
pcCurPos = ResolvedPathName->Buffer;
|
||||||
|
|
||||||
|
/* path begins with a delimiter (absolute path) */
|
||||||
|
if(IS_CHAR_DELIMITER_A(PathName.Buffer[0]))
|
||||||
|
{
|
||||||
|
/* put a delimiter in front of the return buffer */
|
||||||
|
*pcCurPos = PathDelimiter;
|
||||||
|
/* move to next character */
|
||||||
|
pcCurPos ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcStartPos = pcCurPos;
|
||||||
|
|
||||||
|
/* repeat until the end of the path string */
|
||||||
|
while(__PdxPosixPathGetNextComponent_A(PathName, &strThisComponent, &bIsDirectory))
|
||||||
|
{
|
||||||
|
/* ".": skip */
|
||||||
|
if(IS_COMPONENT_DOT_A(strThisComponent))
|
||||||
|
continue;
|
||||||
|
/* "..": go back to the last component */
|
||||||
|
else if(IS_COMPONENT_DOTDOT_A(strThisComponent))
|
||||||
|
{
|
||||||
|
if(pcCurPos == pcStartPos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* skip the last (undefined) character */
|
||||||
|
pcCurPos --;
|
||||||
|
/* down to the previous path delimiter */
|
||||||
|
do{ pcCurPos --; }while(!IS_CHAR_DELIMITER_A(*pcCurPos));
|
||||||
|
/* include the delimiter */
|
||||||
|
pcCurPos ++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* copy this component into the return string */
|
||||||
|
strncpy
|
||||||
|
(
|
||||||
|
pcCurPos,
|
||||||
|
strThisComponent.Buffer,
|
||||||
|
strThisComponent.Length
|
||||||
|
);
|
||||||
|
|
||||||
|
/* move the current position to the end of the string */
|
||||||
|
pcCurPos = (PCHAR)((PBYTE)pcCurPos + strThisComponent.Length);
|
||||||
|
|
||||||
|
/* component had a trailing delimiter */
|
||||||
|
if(bIsDirectory)
|
||||||
|
{
|
||||||
|
/* append a delimiter */
|
||||||
|
*pcCurPos = PathDelimiter;
|
||||||
|
/* on to next character */
|
||||||
|
pcCurPos ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the return string's length as the byte offset between the initial buffer
|
||||||
|
position and the current position */
|
||||||
|
ResolvedPathName->Length = ((ULONG)pcCurPos - (ULONG)ResolvedPathName->Buffer);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
__PdxPosixPathNameToNtPathName
|
||||||
|
(
|
||||||
|
IN PWCHAR PosixPath,
|
||||||
|
OUT PUNICODE_STRING NativePath,
|
||||||
|
IN PUNICODE_STRING CurDir OPTIONAL,
|
||||||
|
IN PUNICODE_STRING RootDir OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UNICODE_STRING wstrPosixPath;
|
||||||
|
UNICODE_STRING wstrTempString;
|
||||||
|
|
||||||
|
/* parameter validation */
|
||||||
|
if
|
||||||
|
(
|
||||||
|
PosixPath == 0 ||
|
||||||
|
NativePath == 0 ||
|
||||||
|
NativePath->Buffer == 0 ||
|
||||||
|
NativePath->MaximumLength == 0 ||
|
||||||
|
(RootDir != 0 && RootDir->Buffer == 0)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&wstrPosixPath, PosixPath);
|
||||||
|
|
||||||
|
/* path is null */
|
||||||
|
if(0 == wstrPosixPath.Length)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first, copy the root path into the return buffer */
|
||||||
|
/* if no root dir passed by the caller... */
|
||||||
|
if(RootDir == 0)
|
||||||
|
/* return buffer too small */
|
||||||
|
if(NativePath->MaximumLength < sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
errno = ENOBUFS;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
/* set the first character to a backslash, and set length accordingly */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NativePath->Buffer[0] = L'\\';
|
||||||
|
NativePath->Length = sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
/* ... else copy the root dir into the return buffer */
|
||||||
|
else
|
||||||
|
/* return buffer too small */
|
||||||
|
if(NativePath->MaximumLength < RootDir->Length)
|
||||||
|
{
|
||||||
|
errno = ENOBUFS;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
/* copy the root directory into the return buffer, and set length */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(NativePath->Buffer, RootDir->Buffer, RootDir->Length);
|
||||||
|
NativePath->Length = RootDir->Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* path is "/" - our work is done */
|
||||||
|
if(sizeof(WCHAR) == wstrPosixPath.Length && IS_CHAR_DELIMITER_U(wstrPosixPath.Buffer[0]))
|
||||||
|
return (TRUE);
|
||||||
|
|
||||||
|
/* temp string pointing to the tail of the return buffer */
|
||||||
|
wstrTempString.Length = 0;
|
||||||
|
wstrTempString.MaximumLength = NativePath->MaximumLength - NativePath->Length;
|
||||||
|
wstrTempString.Buffer = (PWCHAR)(((PBYTE)(NativePath->Buffer)) + NativePath->Length);
|
||||||
|
|
||||||
|
/* path begins with '/': absolute path. Append the resolved path to the return buffer */
|
||||||
|
if(IS_CHAR_DELIMITER_U(wstrPosixPath.Buffer[0]))
|
||||||
|
{
|
||||||
|
/* copy the resolved path in the return buffer */
|
||||||
|
__PdxPosixPathResolve_U(wstrPosixPath, &wstrTempString, L'\\');
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UNICODE_STRING wstrAbsolutePath;
|
||||||
|
|
||||||
|
if(CurDir == 0)
|
||||||
|
CurDir = __PdxGetCurDir();
|
||||||
|
|
||||||
|
/* initialize the buffer for the absolute path */
|
||||||
|
wstrAbsolutePath.Length = 0;
|
||||||
|
wstrAbsolutePath.MaximumLength = 0xFFFF;
|
||||||
|
wstrAbsolutePath.Buffer = __malloc(0xFFFF);
|
||||||
|
|
||||||
|
/* if the current directory is not null... */
|
||||||
|
if(!(CurDir->Buffer == 0 || CurDir->Length == 0))
|
||||||
|
{
|
||||||
|
/* copy it into the absolute path buffer */
|
||||||
|
memcpy(wstrAbsolutePath.Buffer, CurDir->Buffer, CurDir->Length);
|
||||||
|
wstrAbsolutePath.Length += CurDir->Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not enough space to append an extra slash */
|
||||||
|
if((wstrAbsolutePath.MaximumLength - wstrAbsolutePath.Length) < (USHORT)sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
__free(wstrAbsolutePath.Buffer);
|
||||||
|
NativePath->Length = 0;
|
||||||
|
errno = ENOBUFS;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append an extra slash */
|
||||||
|
wstrAbsolutePath.Buffer[wstrAbsolutePath.Length / sizeof(WCHAR)] = L'/';
|
||||||
|
wstrAbsolutePath.Length += sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* not enough space to copy the relative path */
|
||||||
|
if((wstrAbsolutePath.MaximumLength - wstrAbsolutePath.Length) < wstrPosixPath.Length)
|
||||||
|
{
|
||||||
|
__free(wstrAbsolutePath.Buffer);
|
||||||
|
NativePath->Length = 0;
|
||||||
|
errno = ENOBUFS;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append the relative path to the absolute path */
|
||||||
|
memcpy(
|
||||||
|
(PWCHAR)(((PBYTE)wstrAbsolutePath.Buffer) + wstrAbsolutePath.Length),
|
||||||
|
wstrPosixPath.Buffer,
|
||||||
|
wstrPosixPath.Length
|
||||||
|
);
|
||||||
|
wstrAbsolutePath.Length += wstrPosixPath.Length;
|
||||||
|
|
||||||
|
/* resolve the path */
|
||||||
|
__PdxPosixPathResolve_U(wstrAbsolutePath, &wstrTempString, L'\\');
|
||||||
|
|
||||||
|
__free(wstrAbsolutePath.Buffer);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (FALSE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
45
posix/lib/psxdll/misc/safeobj.c
Normal file
45
posix/lib/psxdll/misc/safeobj.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/misc/safeobj.c
|
||||||
|
* PURPOSE: safe checking of user-provided objects
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 09/01/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <psx/safeobj.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
int __safeobj_validate(void *obj, __magic_t refsignature)
|
||||||
|
{
|
||||||
|
if(obj == 0)
|
||||||
|
return (0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* cast the object to a magic number */
|
||||||
|
__magic_t mSignature = *((__magic_t *)obj);
|
||||||
|
|
||||||
|
ERRIF
|
||||||
|
(
|
||||||
|
mSignature != refsignature,
|
||||||
|
"invalid object at %X: signature is \"%c%c%c%c\", should be \"%c%c%c%c\"",
|
||||||
|
obj,
|
||||||
|
MAGIC_DECOMPOSE(refsignature),
|
||||||
|
MAGIC_DECOMPOSE(mSignature)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(mSignature == refsignature)
|
||||||
|
/* signatures match: ok */
|
||||||
|
return (-1);
|
||||||
|
else
|
||||||
|
/* signatures mismatch: fail */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
15
posix/lib/psxdll/misc/template.c
Normal file
15
posix/lib/psxdll/misc/template.c
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS POSIX+ Subsystem
|
||||||
|
* FILE:
|
||||||
|
* PURPOSE:
|
||||||
|
* PROGRAMMER:
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* : Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
143
posix/lib/psxdll/psxdll.def
Normal file
143
posix/lib/psxdll/psxdll.def
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
; $Id: psxdll.def,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
;
|
||||||
|
; ReactOS POSIX Client Library
|
||||||
|
;
|
||||||
|
|
||||||
|
LIBRARY PSXDLL.DLL
|
||||||
|
EXPORTS
|
||||||
|
|
||||||
|
;dirent
|
||||||
|
opendir
|
||||||
|
readdir
|
||||||
|
closedir
|
||||||
|
|
||||||
|
;dlfcn
|
||||||
|
dlopen
|
||||||
|
dlclose
|
||||||
|
dlsym
|
||||||
|
dlerror
|
||||||
|
|
||||||
|
;errno
|
||||||
|
__PdxGetThreadErrNum
|
||||||
|
|
||||||
|
;fcntl
|
||||||
|
open
|
||||||
|
creat
|
||||||
|
fcntl
|
||||||
|
|
||||||
|
;libgen
|
||||||
|
basename
|
||||||
|
|
||||||
|
;misc
|
||||||
|
;path
|
||||||
|
__PdxPosixPathGetNextComponent_A
|
||||||
|
__PdxPosixPathGetNextComponent_U
|
||||||
|
__PdxPosixPathResolve_A
|
||||||
|
__PdxPosixPathResolve_U
|
||||||
|
__PdxPosixPathNameToNtPathName
|
||||||
|
;fdtable
|
||||||
|
__fdtable_init
|
||||||
|
__fdtable_free
|
||||||
|
__fdtable_entry_nextavail
|
||||||
|
__fdtable_entry_add
|
||||||
|
__fdtable_entry_remove
|
||||||
|
__fdtable_entry_get
|
||||||
|
;safeobj
|
||||||
|
__safeobj_validate
|
||||||
|
|
||||||
|
;pthread
|
||||||
|
pthread_create
|
||||||
|
pthread_exit
|
||||||
|
pthread_join
|
||||||
|
pthread_mutex_destroy
|
||||||
|
pthread_mutex_init
|
||||||
|
pthread_mutex_lock
|
||||||
|
pthread_mutex_trylock
|
||||||
|
pthread_mutex_unlock
|
||||||
|
pthread_mutex_getprioceiling
|
||||||
|
pthread_mutex_setprioceiling
|
||||||
|
pthread_mutexattr_destroy
|
||||||
|
pthread_mutexattr_getpshared
|
||||||
|
pthread_mutexattr_init
|
||||||
|
pthread_mutexattr_setpshared
|
||||||
|
pthread_mutexattr_gettype
|
||||||
|
pthread_mutexattr_settype
|
||||||
|
pthread_mutexattr_getprioceiling
|
||||||
|
pthread_mutexattr_getprotocol
|
||||||
|
pthread_mutexattr_setprioceiling
|
||||||
|
pthread_mutexattr_setprotocol
|
||||||
|
|
||||||
|
;sched
|
||||||
|
sched_yield
|
||||||
|
|
||||||
|
;signal
|
||||||
|
pthread_kill
|
||||||
|
raise
|
||||||
|
|
||||||
|
;stdio
|
||||||
|
printf
|
||||||
|
gets
|
||||||
|
|
||||||
|
;stdlib
|
||||||
|
abort
|
||||||
|
malloc
|
||||||
|
realloc
|
||||||
|
free
|
||||||
|
calloc
|
||||||
|
exit
|
||||||
|
|
||||||
|
;string
|
||||||
|
;forward-exports to NTDLL
|
||||||
|
memchr
|
||||||
|
memcmp
|
||||||
|
memcpy
|
||||||
|
memmove
|
||||||
|
memset
|
||||||
|
strcat
|
||||||
|
strchr
|
||||||
|
strcmp
|
||||||
|
strcpy
|
||||||
|
strcspn
|
||||||
|
strlen
|
||||||
|
strncat
|
||||||
|
strncmp
|
||||||
|
strncpy
|
||||||
|
strpbrk
|
||||||
|
strrchr
|
||||||
|
strspn
|
||||||
|
strstr
|
||||||
|
;implemented internally
|
||||||
|
strdup
|
||||||
|
|
||||||
|
;sys/utsname
|
||||||
|
uname
|
||||||
|
|
||||||
|
;unistd
|
||||||
|
close
|
||||||
|
dup
|
||||||
|
dup2
|
||||||
|
getcwd
|
||||||
|
getpid
|
||||||
|
getppid
|
||||||
|
|
||||||
|
;wchar
|
||||||
|
;forward-exports to NTDLL
|
||||||
|
wcscat
|
||||||
|
wcschr
|
||||||
|
wcscmp
|
||||||
|
wcscpy
|
||||||
|
wcscspn
|
||||||
|
wcslen
|
||||||
|
wcsncat
|
||||||
|
wcsncmp
|
||||||
|
wcsncpy
|
||||||
|
wcspbrk
|
||||||
|
wcsrchr
|
||||||
|
wcsspn
|
||||||
|
wcsstr
|
||||||
|
wcstol
|
||||||
|
wcstombs
|
||||||
|
wcstoul
|
||||||
|
;implemented internally
|
||||||
|
|
||||||
|
;EOF
|
143
posix/lib/psxdll/psxdll.edf
Normal file
143
posix/lib/psxdll/psxdll.edf
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
; $Id: psxdll.edf,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
;
|
||||||
|
; ReactOS POSIX Client Library
|
||||||
|
;
|
||||||
|
|
||||||
|
LIBRARY PSXDLL.DLL
|
||||||
|
EXPORTS
|
||||||
|
|
||||||
|
;dirent
|
||||||
|
opendir=opendir
|
||||||
|
readdir=readdir
|
||||||
|
closedir=closedir
|
||||||
|
|
||||||
|
;dlfcn
|
||||||
|
dlopen=dlopen
|
||||||
|
dlclose=dlclose
|
||||||
|
dlsym=dlsym
|
||||||
|
dlerror=dlerror
|
||||||
|
|
||||||
|
;errno
|
||||||
|
__PdxGetThreadErrNum=__PdxGetThreadErrNum
|
||||||
|
|
||||||
|
;fcntl
|
||||||
|
open=open
|
||||||
|
creat=creat
|
||||||
|
fcntl=fcntl
|
||||||
|
|
||||||
|
;libgen
|
||||||
|
basename=basename
|
||||||
|
|
||||||
|
;misc
|
||||||
|
;path
|
||||||
|
__PdxPosixPathGetNextComponent_A=__PdxPosixPathGetNextComponent_A
|
||||||
|
__PdxPosixPathGetNextComponent_U=__PdxPosixPathGetNextComponent_U
|
||||||
|
__PdxPosixPathResolve_A=__PdxPosixPathResolve_A
|
||||||
|
__PdxPosixPathResolve_U=__PdxPosixPathResolve_U
|
||||||
|
__PdxPosixPathNameToNtPathName=__PdxPosixPathNameToNtPathName
|
||||||
|
;fdtable
|
||||||
|
__fdtable_init=__fdtable_init
|
||||||
|
__fdtable_free=__fdtable_free
|
||||||
|
__fdtable_entry_nextavail=__fdtable_entry_nextavail
|
||||||
|
__fdtable_entry_add=__fdtable_entry_add
|
||||||
|
__fdtable_entry_remove=__fdtable_entry_remove
|
||||||
|
__fdtable_entry_get=__fdtable_entry_get
|
||||||
|
;safeobj
|
||||||
|
__safeobj_validate=__safeobj_validate
|
||||||
|
|
||||||
|
;pthread
|
||||||
|
pthread_create=pthread_create
|
||||||
|
pthread_exit=pthread_exit
|
||||||
|
pthread_join=pthread_join
|
||||||
|
pthread_mutex_destroy=pthread_mutex_destroy
|
||||||
|
pthread_mutex_init=pthread_mutex_init
|
||||||
|
pthread_mutex_lock=pthread_mutex_lock
|
||||||
|
pthread_mutex_trylock=pthread_mutex_trylock
|
||||||
|
pthread_mutex_unlock=pthread_mutex_unlock
|
||||||
|
pthread_mutex_getprioceiling=pthread_mutex_getprioceiling
|
||||||
|
pthread_mutex_setprioceiling=pthread_mutex_setprioceiling
|
||||||
|
pthread_mutexattr_destroy=pthread_mutexattr_destroy
|
||||||
|
pthread_mutexattr_getpshared=pthread_mutexattr_getpshared
|
||||||
|
pthread_mutexattr_init=pthread_mutexattr_init
|
||||||
|
pthread_mutexattr_setpshared=pthread_mutexattr_setpshared
|
||||||
|
pthread_mutexattr_gettype=pthread_mutexattr_gettype
|
||||||
|
pthread_mutexattr_settype=pthread_mutexattr_settype
|
||||||
|
pthread_mutexattr_getprioceiling=pthread_mutexattr_getprioceiling
|
||||||
|
pthread_mutexattr_getprotocol=pthread_mutexattr_getprotocol
|
||||||
|
pthread_mutexattr_setprioceiling=pthread_mutexattr_setprioceiling
|
||||||
|
pthread_mutexattr_setprotocol=pthread_mutexattr_setprotocol
|
||||||
|
|
||||||
|
;sched
|
||||||
|
sched_yield=sched_yield
|
||||||
|
|
||||||
|
;signal
|
||||||
|
pthread_kill=pthread_kill
|
||||||
|
raise=raise
|
||||||
|
|
||||||
|
;stdio
|
||||||
|
printf=MSVCRT.printf
|
||||||
|
gets=MSVCRT.gets
|
||||||
|
|
||||||
|
;stdlib
|
||||||
|
abort=abort
|
||||||
|
malloc=malloc
|
||||||
|
realloc=realloc
|
||||||
|
free=free
|
||||||
|
calloc=calloc
|
||||||
|
exit=exit
|
||||||
|
|
||||||
|
;string
|
||||||
|
;forward-exports to NTDLL
|
||||||
|
memchr=NTDLL.memchr
|
||||||
|
memcmp=NTDLL.memcmp
|
||||||
|
memcpy=NTDLL.memcpy
|
||||||
|
memmove=NTDLL.memmove
|
||||||
|
memset=NTDLL.memset
|
||||||
|
strcat=NTDLL.strcat
|
||||||
|
strchr=NTDLL.strchr
|
||||||
|
strcmp=NTDLL.strcmp
|
||||||
|
strcpy=NTDLL.strcpy
|
||||||
|
strcspn=NTDLL.strcspn
|
||||||
|
strlen=NTDLL.strlen
|
||||||
|
strncat=NTDLL.strncat
|
||||||
|
strncmp=NTDLL.strncmp
|
||||||
|
strncpy=NTDLL.strncpy
|
||||||
|
strpbrk=NTDLL.strpbrk
|
||||||
|
strrchr=NTDLL.strrchr
|
||||||
|
strspn=NTDLL.strspn
|
||||||
|
strstr=NTDLL.strstr
|
||||||
|
;implemented internally
|
||||||
|
strdup
|
||||||
|
|
||||||
|
;sys/utsname
|
||||||
|
uname=uname
|
||||||
|
|
||||||
|
;unistd
|
||||||
|
close=close
|
||||||
|
dup=dup
|
||||||
|
dup2=dup2
|
||||||
|
getcwd=getcwd
|
||||||
|
getpid=getpid
|
||||||
|
getppid=getppid
|
||||||
|
|
||||||
|
;wchar
|
||||||
|
;forward-exports to NTDLL
|
||||||
|
wcscat=NTDLL.wcscat
|
||||||
|
wcschr=NTDLL.wcschr
|
||||||
|
wcscmp=NTDLL.wcscmp
|
||||||
|
wcscpy=NTDLL.wcscpy
|
||||||
|
wcscspn=NTDLL.wcscspn
|
||||||
|
wcslen=NTDLL.wcslen
|
||||||
|
wcsncat=NTDLL.wcsncat
|
||||||
|
wcsncmp=NTDLL.wcsncmp
|
||||||
|
wcsncpy=NTDLL.wcsncpy
|
||||||
|
wcspbrk=NTDLL.wcspbrk
|
||||||
|
wcsrchr=NTDLL.wcsrchr
|
||||||
|
wcsspn=NTDLL.wcsspn
|
||||||
|
wcsstr=NTDLL.wcsstr
|
||||||
|
wcstol=NTDLL.wcstol
|
||||||
|
wcstombs=NTDLL.wcstombs
|
||||||
|
wcstoul=NTDLL.wcstoul
|
||||||
|
;implemented internally
|
||||||
|
|
||||||
|
;EOF
|
39
posix/lib/psxdll/psxdll.rc
Normal file
39
posix/lib/psxdll/psxdll.rc
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* $Id: psxdll.rc,v 1.1 2002/02/20 07:06:50 hyperion Exp $
|
||||||
|
*/
|
||||||
|
#include <defines.h>
|
||||||
|
#include <reactos/resource.h>
|
||||||
|
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
|
||||||
|
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", RES_STR_COMPANY_NAME
|
||||||
|
VALUE "FileDescription", "Posix Client DLL\0"
|
||||||
|
VALUE "FileVersion", RES_STR_FILE_VERSION
|
||||||
|
VALUE "InternalName", "psxdll\0"
|
||||||
|
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
|
||||||
|
VALUE "OriginalFilename", "psxdll.dll\0"
|
||||||
|
VALUE "ProductName", RES_STR_PRODUCT_NAME
|
||||||
|
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
198
posix/lib/psxdll/pthread/create.c
Normal file
198
posix/lib/psxdll/pthread/create.c
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/pthread/create.c
|
||||||
|
* PURPOSE: Thread creation
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <napi/i386/segment.h>
|
||||||
|
|
||||||
|
/* thread creation code adapted from kernel32's CreateRemoteThread() function */
|
||||||
|
|
||||||
|
static void __threadentry (void *(*start_routine)(void*), void *arg)
|
||||||
|
{
|
||||||
|
INFO("hello world! thread successfully created");
|
||||||
|
|
||||||
|
TODO("initialize thread data");
|
||||||
|
TODO("notify DLLs");
|
||||||
|
TODO("notify psxss");
|
||||||
|
|
||||||
|
INFO("about to call start routine at %#x with argument %#x", start_routine, arg);
|
||||||
|
|
||||||
|
pthread_exit(start_routine(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
|
void *(*start_routine)(void*), void *arg)
|
||||||
|
{
|
||||||
|
HANDLE hThread;
|
||||||
|
OBJECT_ATTRIBUTES oaThreadAttrs;
|
||||||
|
CLIENT_ID ciId;
|
||||||
|
CONTEXT cxThreadContext;
|
||||||
|
INITIAL_TEB itInitialTeb;
|
||||||
|
BOOLEAN fSuspended;
|
||||||
|
ULONG nOldPageProtection;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
/* initialize generic object attributes */
|
||||||
|
oaThreadAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||||
|
oaThreadAttrs.RootDirectory = NULL;
|
||||||
|
oaThreadAttrs.ObjectName = NULL;
|
||||||
|
oaThreadAttrs.Attributes = 0;
|
||||||
|
oaThreadAttrs.SecurityDescriptor = NULL;
|
||||||
|
oaThreadAttrs.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
/* initialize thread attributes */
|
||||||
|
fSuspended = FALSE; /* FIXME? really needed? can we hardcode this to FALSE? */
|
||||||
|
|
||||||
|
/* stack attributes */
|
||||||
|
FIXME("stack size defaulted to 0x100000 - thread attributes ignored");
|
||||||
|
|
||||||
|
/* stack reserve size */
|
||||||
|
itInitialTeb.StackReserve = 0x100000;
|
||||||
|
|
||||||
|
/* stack commit size */
|
||||||
|
itInitialTeb.StackCommit = itInitialTeb.StackReserve - PAGESIZE;
|
||||||
|
|
||||||
|
/* guard page */
|
||||||
|
itInitialTeb.StackCommit += PAGESIZE;
|
||||||
|
|
||||||
|
/* reserve stack */
|
||||||
|
itInitialTeb.StackAllocate = NULL;
|
||||||
|
|
||||||
|
nErrCode = NtAllocateVirtualMemory
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
&itInitialTeb.StackAllocate,
|
||||||
|
0,
|
||||||
|
&itInitialTeb.StackReserve,
|
||||||
|
MEM_RESERVE,
|
||||||
|
PAGE_READWRITE
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode)); /* FIXME? TODO? pthread specific error codes? */
|
||||||
|
}
|
||||||
|
|
||||||
|
itInitialTeb.StackBase = (PVOID)((ULONG)itInitialTeb.StackAllocate + itInitialTeb.StackReserve);
|
||||||
|
itInitialTeb.StackLimit = (PVOID)((ULONG)itInitialTeb.StackBase - itInitialTeb.StackCommit);
|
||||||
|
|
||||||
|
/* commit stack */
|
||||||
|
nErrCode = NtAllocateVirtualMemory
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
&itInitialTeb.StackLimit,
|
||||||
|
0,
|
||||||
|
&itInitialTeb.StackCommit,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_READWRITE
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
NtFreeVirtualMemory
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
itInitialTeb.StackAllocate,
|
||||||
|
&itInitialTeb.StackReserve,
|
||||||
|
MEM_RELEASE
|
||||||
|
);
|
||||||
|
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* protect guard page */
|
||||||
|
nErrCode = NtProtectVirtualMemory
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
itInitialTeb.StackLimit,
|
||||||
|
PAGESIZE,
|
||||||
|
PAGE_GUARD | PAGE_READWRITE,
|
||||||
|
&nOldPageProtection
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
NtFreeVirtualMemory
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
itInitialTeb.StackAllocate,
|
||||||
|
&itInitialTeb.StackReserve,
|
||||||
|
MEM_RELEASE
|
||||||
|
);
|
||||||
|
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize thread registers */
|
||||||
|
|
||||||
|
//#ifdef __i386__
|
||||||
|
memset(&cxThreadContext, 0, sizeof(CONTEXT));
|
||||||
|
cxThreadContext.Eip = (LONG)__threadentry;
|
||||||
|
cxThreadContext.SegGs = USER_DS;
|
||||||
|
cxThreadContext.SegFs = TEB_SELECTOR;
|
||||||
|
cxThreadContext.SegEs = USER_DS;
|
||||||
|
cxThreadContext.SegDs = USER_DS;
|
||||||
|
cxThreadContext.SegCs = USER_CS;
|
||||||
|
cxThreadContext.SegSs = USER_DS;
|
||||||
|
cxThreadContext.Esp = (ULONG)itInitialTeb.StackBase - 12;
|
||||||
|
cxThreadContext.EFlags = (1<<1) + (1<<9);
|
||||||
|
|
||||||
|
/* initialize call stack */
|
||||||
|
*((PULONG)((ULONG)itInitialTeb.StackBase - 4)) = (ULONG)arg; /* thread argument */
|
||||||
|
*((PULONG)((ULONG)itInitialTeb.StackBase - 8)) = (ULONG)start_routine; /* thread start routine */
|
||||||
|
*((PULONG)((ULONG)itInitialTeb.StackBase - 12)) = 0xDEADBEEF; /* "shouldn't see me" */
|
||||||
|
//#else
|
||||||
|
//#error Unsupported architecture
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
INFO("about to create new thread - start routine at %#x, argument %#x", start_routine, arg);
|
||||||
|
|
||||||
|
/* create thread */
|
||||||
|
nErrCode = NtCreateThread
|
||||||
|
(
|
||||||
|
&hThread,
|
||||||
|
THREAD_ALL_ACCESS,
|
||||||
|
&oaThreadAttrs,
|
||||||
|
NtCurrentProcess(),
|
||||||
|
&ciId,
|
||||||
|
&cxThreadContext,
|
||||||
|
&itInitialTeb,
|
||||||
|
fSuspended
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
NtFreeVirtualMemory
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
itInitialTeb.StackAllocate,
|
||||||
|
&itInitialTeb.StackReserve,
|
||||||
|
MEM_RELEASE
|
||||||
|
);
|
||||||
|
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME? should we return the thread handle or the thread id? */
|
||||||
|
if(thread != 0)
|
||||||
|
*thread = (pthread_t)&ciId.UniqueThread; /* for the moment, we return the id */
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
78
posix/lib/psxdll/pthread/exit.c
Normal file
78
posix/lib/psxdll/pthread/exit.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/pthread/exit.c
|
||||||
|
* PURPOSE: Thread termination
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
void pthread_exit(void *value_ptr)
|
||||||
|
{
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
BOOLEAN fLastThread;
|
||||||
|
|
||||||
|
/* terminate process if this is the last thread of the current process */
|
||||||
|
nErrCode = NtQueryInformationThread
|
||||||
|
(
|
||||||
|
NtCurrentThread(),
|
||||||
|
ThreadAmILastThread,
|
||||||
|
&fLastThread,
|
||||||
|
sizeof(BOOLEAN),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if(NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
if(fLastThread)
|
||||||
|
{
|
||||||
|
INFO("this thread is the last in the current process - about to call exit(0)");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN
|
||||||
|
(
|
||||||
|
"NtQueryInformationThread(ThreadAmILastThread) failed with status %#x. \
|
||||||
|
Can't determine if the current thread is the last in the process. The process \
|
||||||
|
could hang",
|
||||||
|
nErrCode
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TODO("Notify psxss of thread termination");
|
||||||
|
|
||||||
|
LdrShutdownThread(); /* detach DLLs */
|
||||||
|
|
||||||
|
/* kill this thread */
|
||||||
|
|
||||||
|
WARNIF(
|
||||||
|
sizeof(ULONG) < sizeof(typeof(value_ptr)),
|
||||||
|
"\
|
||||||
|
the value returned from the current thread will be truncated (pointers shorter \
|
||||||
|
than long integers on this architecture?) - expect trouble"
|
||||||
|
);
|
||||||
|
|
||||||
|
INFO("bye bye. Current thread about to die");
|
||||||
|
|
||||||
|
NtTerminateThread(NtCurrentThread(), (ULONG)value_ptr);
|
||||||
|
|
||||||
|
/* "The pthread_exit() function cannot return to its caller." */
|
||||||
|
NtDelayExecution(FALSE, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
98
posix/lib/psxdll/pthread/join.c
Normal file
98
posix/lib/psxdll/pthread/join.c
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/pthread/join.c
|
||||||
|
* PURPOSE: Wait for thread termination
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
int pthread_join(pthread_t thread, void **value_ptr)
|
||||||
|
{
|
||||||
|
HANDLE hThread;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
OBJECT_ATTRIBUTES oaThreadAttrs;
|
||||||
|
CLIENT_ID ciId;
|
||||||
|
THREAD_BASIC_INFORMATION tbiThreadInfo;
|
||||||
|
|
||||||
|
/* "[EDEADLK] A deadlock was detected or the value of thread specifies
|
||||||
|
the calling thread" */
|
||||||
|
if(thread == pthread_self())
|
||||||
|
return (EDEADLK);
|
||||||
|
|
||||||
|
/* initialize id */
|
||||||
|
ciId.UniqueProcess = (HANDLE)-1;
|
||||||
|
ciId.UniqueThread = (HANDLE)thread;
|
||||||
|
|
||||||
|
/* initialize object attributes */
|
||||||
|
oaThreadAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||||
|
oaThreadAttrs.RootDirectory = NULL;
|
||||||
|
oaThreadAttrs.ObjectName = NULL;
|
||||||
|
oaThreadAttrs.Attributes = 0;
|
||||||
|
oaThreadAttrs.SecurityDescriptor = NULL;
|
||||||
|
oaThreadAttrs.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
/* open the thread */
|
||||||
|
nErrCode = NtOpenThread
|
||||||
|
(
|
||||||
|
&hThread,
|
||||||
|
SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
||||||
|
&oaThreadAttrs,
|
||||||
|
&ciId
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for thread termination */
|
||||||
|
nErrCode = NtWaitForSingleObject
|
||||||
|
(
|
||||||
|
hThread,
|
||||||
|
FALSE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
NtClose(hThread);
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get thread basic information (includes return code) */
|
||||||
|
nErrCode = NtQueryInformationThread
|
||||||
|
(
|
||||||
|
hThread,
|
||||||
|
ThreadBasicInformation,
|
||||||
|
&tbiThreadInfo,
|
||||||
|
sizeof(THREAD_BASIC_INFORMATION),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
NtClose(hThread);
|
||||||
|
|
||||||
|
if(!value_ptr)
|
||||||
|
return (EFAULT);
|
||||||
|
|
||||||
|
*value_ptr = (void *)tbiThreadInfo.ExitStatus;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
22
posix/lib/psxdll/pthread/kill.c
Normal file
22
posix/lib/psxdll/pthread/kill.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/pthread/kill.c
|
||||||
|
* PURPOSE: Send a signal to a thread
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int pthread_kill(pthread_t thread, int sig)
|
||||||
|
{
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
465
posix/lib/psxdll/pthread/mutex.c
Normal file
465
posix/lib/psxdll/pthread/mutex.c
Normal file
|
@ -0,0 +1,465 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/pthread/mutex.c
|
||||||
|
* PURPOSE: Mutex functions
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ntos.h>
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/pthread.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/safeobj.h>
|
||||||
|
|
||||||
|
int pthread_mutex_init(pthread_mutex_t *mutex,
|
||||||
|
const pthread_mutexattr_t *attr)
|
||||||
|
{
|
||||||
|
struct __mutex *pmMutex;
|
||||||
|
struct __mutexattr *pmaMutexAttrs;
|
||||||
|
BOOL bShared;
|
||||||
|
OBJECT_ATTRIBUTES oaMutexAttrs;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
/* invalid return buffer */
|
||||||
|
if(mutex == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* object still open */
|
||||||
|
if(__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
|
||||||
|
return (EBUSY);
|
||||||
|
|
||||||
|
if(attr == NULL)
|
||||||
|
{
|
||||||
|
/* use default attributes */
|
||||||
|
/* create new mutex object */
|
||||||
|
pmMutex = (struct __mutex *)malloc(sizeof(struct __mutex));
|
||||||
|
|
||||||
|
/* malloc() failure */
|
||||||
|
if(!pmMutex)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
/* set the attributes */
|
||||||
|
bShared = FALSE;
|
||||||
|
pmMutex->type = PTHREAD_MUTEX_RECURSIVE;
|
||||||
|
}
|
||||||
|
else if(__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
|
||||||
|
{
|
||||||
|
/* use provided attributes */
|
||||||
|
/* create new mutex object */
|
||||||
|
pmMutex = (struct __mutex *)malloc(sizeof(struct __mutex));
|
||||||
|
|
||||||
|
/* malloc() failure */
|
||||||
|
if(!pmMutex)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
/* get the attributes object */
|
||||||
|
pmaMutexAttrs = (struct __mutexattr *) *attr;
|
||||||
|
|
||||||
|
/* set the attributes */
|
||||||
|
bShared = (pmaMutexAttrs->pshared != PTHREAD_PROCESS_PRIVATE);
|
||||||
|
pmMutex->type = pmaMutexAttrs->type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* necessary for the mutex to be considered valid later */
|
||||||
|
pmMutex->signature = __PTHREAD_MUTEX_MAGIC;
|
||||||
|
|
||||||
|
/* creation of the native mutex object */
|
||||||
|
pmMutex->handle = 0;
|
||||||
|
|
||||||
|
/* initialize generic object attributes */
|
||||||
|
oaMutexAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||||
|
oaMutexAttrs.RootDirectory = NULL;
|
||||||
|
oaMutexAttrs.ObjectName = NULL;
|
||||||
|
oaMutexAttrs.Attributes = 0;
|
||||||
|
oaMutexAttrs.SecurityDescriptor = NULL;
|
||||||
|
oaMutexAttrs.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
/* process-exclusive mutex */
|
||||||
|
if(bShared)
|
||||||
|
oaMutexAttrs.Attributes |= OBJ_EXCLUSIVE;
|
||||||
|
|
||||||
|
/* try to create the object */
|
||||||
|
nErrCode = NtCreateMutant
|
||||||
|
(
|
||||||
|
&pmMutex->handle,
|
||||||
|
MUTANT_ALL_ACCESS,
|
||||||
|
&oaMutexAttrs,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
/* free the internal mutex object */
|
||||||
|
free(pmMutex);
|
||||||
|
/* return errno */
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the pointer to the mutex */
|
||||||
|
*mutex = (pthread_mutex_t)pmMutex;
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
struct __mutex *pmMutex;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
MUTANT_BASIC_INFORMATION mbiMutexInfo;
|
||||||
|
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
|
||||||
|
{
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pmMutex = (struct __mutex *)*mutex;
|
||||||
|
|
||||||
|
/* query the mutex's status */
|
||||||
|
nErrCode = NtQueryMutant
|
||||||
|
(
|
||||||
|
pmMutex->handle,
|
||||||
|
MutantBasicInformation,
|
||||||
|
&mbiMutexInfo,
|
||||||
|
sizeof(MUTANT_BASIC_INFORMATION),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the thread is owned - cannot destroy it */
|
||||||
|
if(mbiMutexInfo.Count <= 0)
|
||||||
|
{
|
||||||
|
return (EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to close the handle */
|
||||||
|
nErrCode = NtClose(pmMutex->handle);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free the object, nil the pointer */
|
||||||
|
free(*mutex);
|
||||||
|
*mutex = NULL;
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
struct __mutex * pmMutex;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
pmMutex = (struct __mutex *)*mutex;
|
||||||
|
|
||||||
|
/* decide the behavior from the mutex type */
|
||||||
|
switch(pmMutex->type)
|
||||||
|
{
|
||||||
|
case PTHREAD_MUTEX_NORMAL:
|
||||||
|
{
|
||||||
|
/* unconditionally try to lock the mutex */
|
||||||
|
/* FIXME? should we "artificially" hang the thread if it's the mutex owner, since
|
||||||
|
NT mutexes always behave recursively? */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(0 /* mutex owner */ == pthread_self() */)
|
||||||
|
NtDelayExecution(FALSE, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PTHREAD_MUTEX_ERRORCHECK:
|
||||||
|
{
|
||||||
|
/* prevent a thread from recursively locking the same mutex */
|
||||||
|
if(0 /* mutex owner */ == pthread_self()) /* FIXME: implement the correct logic */
|
||||||
|
return (EDEADLK);
|
||||||
|
else
|
||||||
|
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PTHREAD_MUTEX_RECURSIVE:
|
||||||
|
{
|
||||||
|
/* allow recursive locking */
|
||||||
|
/* ASSERT: this is the default behavior for NT */
|
||||||
|
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* we should never reach this point */
|
||||||
|
INFO("you should never read this");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nErrCode == STATUS_ABANDONED)
|
||||||
|
{
|
||||||
|
FIXME("mutex abandoned, not sure on what to do: should we try to lock the mutex again?");
|
||||||
|
}
|
||||||
|
else if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
struct __mutex * pmMutex;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
MUTANT_BASIC_INFORMATION mbiMutexInfo;
|
||||||
|
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
pmMutex = (struct __mutex *)*mutex;
|
||||||
|
|
||||||
|
/* query the mutex's status */
|
||||||
|
nErrCode = NtQueryMutant
|
||||||
|
(
|
||||||
|
pmMutex->handle,
|
||||||
|
MutantBasicInformation,
|
||||||
|
&mbiMutexInfo,
|
||||||
|
sizeof(MUTANT_BASIC_INFORMATION),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mutex already locked */
|
||||||
|
if(mbiMutexInfo.Count <= 0)
|
||||||
|
return (EBUSY);
|
||||||
|
|
||||||
|
/* mutex not locked - mutex type attribute doesn't matter */
|
||||||
|
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
struct __mutex * pmMutex;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
pmMutex = (struct __mutex *)*mutex;
|
||||||
|
|
||||||
|
/* try to release the mutex */
|
||||||
|
nErrCode = NtReleaseMutant(pmMutex->handle, NULL);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
return (__status_to_errno(nErrCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mutex attributes routines */
|
||||||
|
|
||||||
|
int pthread_mutexattr_init(pthread_mutexattr_t *attr)
|
||||||
|
{
|
||||||
|
struct __mutexattr * pmaMutexAttrs;
|
||||||
|
|
||||||
|
/* invalid return pointer */
|
||||||
|
if(!attr)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* allocate internal structure for mutex attributes */
|
||||||
|
pmaMutexAttrs = (struct __mutexattr *)malloc(sizeof(struct __mutexattr));
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(pmaMutexAttrs == 0)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
/* attribute defaults */
|
||||||
|
pmaMutexAttrs->pshared = PTHREAD_PROCESS_PRIVATE;
|
||||||
|
pmaMutexAttrs->type = PTHREAD_MUTEX_DEFAULT;
|
||||||
|
|
||||||
|
/* return the pointer to the attributes object */
|
||||||
|
*attr = (pthread_mutexattr_t)pmaMutexAttrs;
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
|
||||||
|
{
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(attr == NULL || !__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* deallocate internal structure */
|
||||||
|
free(*attr);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PTHREAD_MUTEXATTR_GET(PATTR,PVAR,FIELD) \
|
||||||
|
if( \
|
||||||
|
(PATTR) == NULL || \
|
||||||
|
(PVAR) == NULL || \
|
||||||
|
!__safeobj_validate(*(PATTR), __PTHREAD_MUTEX_ATTR_MAGIC) \
|
||||||
|
) \
|
||||||
|
return (EINVAL); \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
(*(PVAR)) = ((struct __mutexattr *)*(PATTR))->FIELD; \
|
||||||
|
return (0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr,
|
||||||
|
int *pshared)
|
||||||
|
{
|
||||||
|
PTHREAD_MUTEXATTR_GET(attr, pshared, pshared)
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
|
||||||
|
{
|
||||||
|
PTHREAD_MUTEXATTR_GET(attr, type, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
|
||||||
|
int pshared)
|
||||||
|
{
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(attr == NULL || !__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* validate value */
|
||||||
|
switch(pshared)
|
||||||
|
{
|
||||||
|
case PTHREAD_PROCESS_SHARED: break;
|
||||||
|
case PTHREAD_PROCESS_PRIVATE: break;
|
||||||
|
default: return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
((struct __mutexattr *)*attr)->pshared = pshared;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
|
||||||
|
{
|
||||||
|
/* invalid pointer or pointer to invalid object */
|
||||||
|
if(attr == NULL || !__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* validate value */
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case PTHREAD_MUTEX_NORMAL: break;
|
||||||
|
case PTHREAD_MUTEX_ERRORCHECK: break;
|
||||||
|
case PTHREAD_MUTEX_RECURSIVE: break;
|
||||||
|
default: return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
((struct __mutexattr *)*attr)->type = type;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STUBS */
|
||||||
|
|
||||||
|
int pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
|
||||||
|
int prioceiling, int *old_ceiling)
|
||||||
|
{
|
||||||
|
TODO("realtime threads not currently implemented");
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,
|
||||||
|
int *prioceiling)
|
||||||
|
{
|
||||||
|
TODO("realtime threads not currently implemented");
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,
|
||||||
|
int *protocol)
|
||||||
|
{
|
||||||
|
TODO("realtime threads not currently implemented");
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
|
||||||
|
int protocol)
|
||||||
|
{
|
||||||
|
TODO("realtime threads not currently implemented");
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr,
|
||||||
|
int prioceiling)
|
||||||
|
{
|
||||||
|
TODO("realtime threads not currently implemented");
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr,
|
||||||
|
int *prioceiling)
|
||||||
|
{
|
||||||
|
TODO("realtime threads not currently implemented");
|
||||||
|
return (ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
23
posix/lib/psxdll/pthread/self.c
Normal file
23
posix/lib/psxdll/pthread/self.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/pthread/self.c
|
||||||
|
* PURPOSE: get calling thread's ID
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
pthread_t pthread_self(void)
|
||||||
|
{
|
||||||
|
return ((pthread_t)(NtCurrentTeb()->Cid).UniqueThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
33
posix/lib/psxdll/sched/yield.c
Normal file
33
posix/lib/psxdll/sched/yield.c
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/sched/yield.c
|
||||||
|
* PURPOSE: Yield processor
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
int sched_yield(void)
|
||||||
|
{
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
nErrCode = NtYieldExecution();
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
25
posix/lib/psxdll/signal/raise.c
Normal file
25
posix/lib/psxdll/signal/raise.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/signal/raise.c
|
||||||
|
* PURPOSE: Send a signal to the executing process
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int raise(int sig)
|
||||||
|
{
|
||||||
|
/* returns zero if pthread_kill() returned zero, non-zero otherwise */
|
||||||
|
/* pthread_kill() returns the error number and doesn't set errno */
|
||||||
|
return (((errno = pthread_kill(pthread_self(), sig))) == 0 ? (0) : (1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
22
posix/lib/psxdll/stdlib/abort.c
Normal file
22
posix/lib/psxdll/stdlib/abort.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/stdlib/abort.c
|
||||||
|
* PURPOSE: Generate an abnormal process abort
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
void abort(void)
|
||||||
|
{
|
||||||
|
raise(SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
51
posix/lib/psxdll/stdlib/exit.c
Normal file
51
posix/lib/psxdll/stdlib/exit.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/stdlib/exit.c
|
||||||
|
* PURPOSE: Terminate a process
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
void exit(int status)
|
||||||
|
{
|
||||||
|
TODO("call all functions registered with atexit()");
|
||||||
|
|
||||||
|
TODO("flush all output streams, close all open streams");
|
||||||
|
TODO("remove all files created by tmpfile()");
|
||||||
|
|
||||||
|
TODO("close all of the file descriptors, directory streams, conversion \
|
||||||
|
descriptors and message catalogue descriptors");
|
||||||
|
TODO("send SIGCHILD to the parent process");
|
||||||
|
TODO("set parent pid of children to pid of psxss");
|
||||||
|
TODO("detach each attached shared-memory segment");
|
||||||
|
TODO("for each semaphore for which the calling process has set a semadj \
|
||||||
|
value(), add the value to the semval of the semaphore.");
|
||||||
|
TODO("if the process is a controlling process, send SIGHUP to each process \
|
||||||
|
in the foreground process group...");
|
||||||
|
TODO("... and disassociate the terminal from the session");
|
||||||
|
TODO("if the exit causes a process group to become orphaned, and if any \
|
||||||
|
member of the newly-orphaned process group is stopped, send SIGHUP and \
|
||||||
|
SIGCONT to each process in the newly-orphaned process group");
|
||||||
|
TODO("all open named semaphores in the calling process are closed");
|
||||||
|
TODO("remove any memory locks");
|
||||||
|
TODO("destroy memory mappings");
|
||||||
|
TODO("close all open message queue descriptors");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ExitProcess(status);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NtTerminateProcess(NtCurrentProcess(), status);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
55
posix/lib/psxdll/stdlib/malloc.c
Normal file
55
posix/lib/psxdll/stdlib/malloc.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/stdlib/malloc.c
|
||||||
|
* PURPOSE: Memory allocator
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 27/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
|
||||||
|
void * malloc(size_t size)
|
||||||
|
{
|
||||||
|
void * pTemp = __malloc(size);
|
||||||
|
|
||||||
|
if(!pTemp)
|
||||||
|
errno = ENOMEM;
|
||||||
|
|
||||||
|
return (pTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void * ptr)
|
||||||
|
{
|
||||||
|
__free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void * calloc(size_t nelem, size_t elsize)
|
||||||
|
{
|
||||||
|
return (__malloc(nelem * elsize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void * realloc(void * ptr, size_t size)
|
||||||
|
{
|
||||||
|
void * pTemp;
|
||||||
|
|
||||||
|
if(size == 0)
|
||||||
|
__free(ptr);
|
||||||
|
|
||||||
|
if(ptr == 0)
|
||||||
|
return __malloc(size);
|
||||||
|
|
||||||
|
pTemp = __realloc(ptr, size);
|
||||||
|
|
||||||
|
if(pTemp == 0)
|
||||||
|
errno = ENOMEM;
|
||||||
|
|
||||||
|
return (pTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
23
posix/lib/psxdll/string/strcoll.c
Normal file
23
posix/lib/psxdll/string/strcoll.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/string/strcoll.c
|
||||||
|
* PURPOSE: string comparison using collating information
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 20/01/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
int strcoll(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
TODO("locale semantics currently unimplemented");
|
||||||
|
return (strcmp(s1, s2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
44
posix/lib/psxdll/string/strdup.c
Normal file
44
posix/lib/psxdll/string/strdup.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/string/strdup.c
|
||||||
|
* PURPOSE: duplicate a string
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 21/01/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
char *strdup(const char *s1)
|
||||||
|
{
|
||||||
|
char *pchRetBuf;
|
||||||
|
int nStrLen;
|
||||||
|
|
||||||
|
HINT("strdup() is inefficient - consider dropping zero-terminated strings");
|
||||||
|
|
||||||
|
if (s1 == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nStrLen = strlen(s1);
|
||||||
|
|
||||||
|
/* allocate enough buffer space for s1 and the null terminator */
|
||||||
|
pchRetBuf = (char *) malloc(nStrLen + 1);
|
||||||
|
|
||||||
|
if (pchRetBuf == 0)
|
||||||
|
/* memory allocation failed */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* copy the string */
|
||||||
|
strcpy(pchRetBuf, s1);
|
||||||
|
|
||||||
|
return pchRetBuf;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
27
posix/lib/psxdll/string/strerror.c
Normal file
27
posix/lib/psxdll/string/strerror.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/string/strerror.c
|
||||||
|
* PURPOSE: Get error message string
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 20/01/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
|
||||||
|
static char *__errstr = "<strerror() unsupported>";
|
||||||
|
char *strerror(int errnum)
|
||||||
|
{
|
||||||
|
INFO("errnum %#x", errnum);
|
||||||
|
TODO("getting error string not currently implemented");
|
||||||
|
errno = EINVAL;
|
||||||
|
return (__errstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
178
posix/lib/psxdll/sys/utsname/uname.c
Normal file
178
posix/lib/psxdll/sys/utsname/uname.c
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: lib/psxdll/sys/utsname/uname.c
|
||||||
|
* PURPOSE: Get name of current system
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 19/12/2001: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/debug.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
int uname(struct utsname *name)
|
||||||
|
{
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
OBJECT_ATTRIBUTES oaKeyAttribs;
|
||||||
|
UNICODE_STRING wstrKeyPath;
|
||||||
|
UNICODE_STRING wstrValueName;
|
||||||
|
UNICODE_STRING wstrValueData;
|
||||||
|
ANSI_STRING strValueData;
|
||||||
|
PKEY_VALUE_PARTIAL_INFORMATION pkvpiKeyValue;
|
||||||
|
ULONG nKeyValueSize;
|
||||||
|
HANDLE hKey;
|
||||||
|
|
||||||
|
/* system name and version info are fixed strings, at the moment */ /* FIXME? */
|
||||||
|
strncpy(name->sysname, "ReactOS" , 255);
|
||||||
|
strncpy(name->release, "0.0" , 255);
|
||||||
|
strncpy(name->version, "pre-alpha", 255);
|
||||||
|
|
||||||
|
/* hardware identifier */
|
||||||
|
/* FIXME: this should definitely be determined programmatically */
|
||||||
|
strncpy(name->machine, "i386" , 255);
|
||||||
|
|
||||||
|
/* we use the active computer's name as the node name */
|
||||||
|
/* TODO: POSIX-style registry functions */
|
||||||
|
|
||||||
|
/* initialize the registry key path */
|
||||||
|
RtlInitUnicodeString(
|
||||||
|
&wstrKeyPath,
|
||||||
|
L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* initialize object attributes */
|
||||||
|
oaKeyAttribs.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||||
|
oaKeyAttribs.RootDirectory = NULL;
|
||||||
|
oaKeyAttribs.ObjectName = &wstrKeyPath;
|
||||||
|
oaKeyAttribs.Attributes = OBJ_CASE_INSENSITIVE /* | OBJ_OPENLINK | OBJ_OPENIF */ /* FIXME? */;
|
||||||
|
oaKeyAttribs.SecurityDescriptor = NULL;
|
||||||
|
oaKeyAttribs.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
/* open the key object */
|
||||||
|
nErrCode = NtOpenKey
|
||||||
|
(
|
||||||
|
&hKey,
|
||||||
|
KEY_QUERY_VALUE,
|
||||||
|
&oaKeyAttribs
|
||||||
|
);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
|
||||||
|
ERR("NtOpenKey() failed with status 0x%08X", nErrCode);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize the registry value name */
|
||||||
|
RtlInitUnicodeString(&wstrValueName, L"ComputerName");
|
||||||
|
|
||||||
|
/* fake query - null buffer and zero length to pre-fetch the appropriate buffer size */
|
||||||
|
nErrCode = NtQueryValueKey
|
||||||
|
(
|
||||||
|
hKey,
|
||||||
|
&wstrValueName,
|
||||||
|
KeyValuePartialInformation,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&nKeyValueSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
if(nErrCode == (NTSTATUS)STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* allocate the appropriate buffer size */
|
||||||
|
if(nKeyValueSize < sizeof(KEY_VALUE_PARTIAL_INFORMATION)) /* just to be sure */
|
||||||
|
nKeyValueSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
|
||||||
|
|
||||||
|
pkvpiKeyValue = __malloc(nKeyValueSize);
|
||||||
|
|
||||||
|
}
|
||||||
|
/* failure */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
ERR("NtQueryValueKey() failed with status 0x%08X", nErrCode);
|
||||||
|
NtClose(hKey);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the value */
|
||||||
|
nErrCode = NtQueryValueKey
|
||||||
|
(
|
||||||
|
hKey,
|
||||||
|
&wstrValueName,
|
||||||
|
KeyValuePartialInformation,
|
||||||
|
pkvpiKeyValue,
|
||||||
|
nKeyValueSize,
|
||||||
|
&nKeyValueSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/* close the key handle (not needed anymore) */
|
||||||
|
NtClose(hKey);
|
||||||
|
|
||||||
|
/* failure */
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
ERR("NtQueryValueKey() failed with status 0x%08X", nErrCode);
|
||||||
|
__free(pkvpiKeyValue);
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make wstrValueData refer to the Data field of the key value information */
|
||||||
|
wstrValueData.Length = pkvpiKeyValue->DataLength;
|
||||||
|
wstrValueData.MaximumLength = wstrValueData.Length;
|
||||||
|
wstrValueData.Buffer = (PWCHAR)&(pkvpiKeyValue->Data[0]);
|
||||||
|
|
||||||
|
/* make strValueData refer to the nodename buffer */
|
||||||
|
strValueData.Length = 0;
|
||||||
|
strValueData.MaximumLength = 254;
|
||||||
|
strValueData.Buffer = name->nodename;
|
||||||
|
|
||||||
|
RtlUnicodeStringToAnsiString
|
||||||
|
(
|
||||||
|
&strValueData,
|
||||||
|
&wstrValueData,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* free the key value buffer */
|
||||||
|
__free(pkvpiKeyValue);
|
||||||
|
|
||||||
|
/* null-terminate the returned string */
|
||||||
|
name->nodename[strValueData.Length] = '0';
|
||||||
|
|
||||||
|
INFO
|
||||||
|
(
|
||||||
|
" \
|
||||||
|
name->sysname = \"%s\"\n\
|
||||||
|
tname->nodename = \"%s\"\n\
|
||||||
|
tname->release = \"%s\"\n\
|
||||||
|
tname->version = \"%s\"\n\
|
||||||
|
tname->machine = \"%s\"",
|
||||||
|
name->sysname,
|
||||||
|
name->nodename,
|
||||||
|
name->release,
|
||||||
|
name->version,
|
||||||
|
name->machine
|
||||||
|
);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
42
posix/lib/psxdll/unistd/close.c
Normal file
42
posix/lib/psxdll/unistd/close.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/close.c
|
||||||
|
* PURPOSE: Close a file descriptor
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 13/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/fdtable.h>
|
||||||
|
|
||||||
|
int close(int fildes)
|
||||||
|
{
|
||||||
|
__fildes_t fdDescriptor;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
if(fcntl(fildes, F_DELFD, &fdDescriptor) == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
__free(fdDescriptor.ExtraData);
|
||||||
|
|
||||||
|
nErrCode = NtClose(fdDescriptor.FileHandle);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
41
posix/lib/psxdll/unistd/dup.c
Normal file
41
posix/lib/psxdll/unistd/dup.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/dup.c
|
||||||
|
* PURPOSE: Duplicate an open file descriptor
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 13/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
int dup(int fildes)
|
||||||
|
{
|
||||||
|
return (fcntl(fildes, F_DUPFD, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dup2(int fildes, int fildes2)
|
||||||
|
{
|
||||||
|
if(fildes < 0 || fildes >= OPEN_MAX)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: check if fildes is valid */
|
||||||
|
|
||||||
|
if(fildes == fildes2)
|
||||||
|
return fildes2;
|
||||||
|
|
||||||
|
close(fildes2);
|
||||||
|
return (fcntl(fildes, F_DUPFD, fildes2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
89
posix/lib/psxdll/unistd/getcwd.c
Normal file
89
posix/lib/psxdll/unistd/getcwd.c
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/getcwd.c
|
||||||
|
* PURPOSE: Get the pathname of the current working directory
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 01/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
#include <psx/stdlib.h>
|
||||||
|
#include <psx/pdata.h>
|
||||||
|
|
||||||
|
wchar_t *_Wgetcwd(wchar_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
PUNICODE_STRING pwstrCurDir;
|
||||||
|
|
||||||
|
__PdxAcquirePdataLock();
|
||||||
|
|
||||||
|
pwstrCurDir = __PdxGetCurDir();
|
||||||
|
|
||||||
|
if(size < (pwstrCurDir->Length / sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
errno = ERANGE;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wcsncpy(buf, pwstrCurDir->Buffer, pwstrCurDir->Length);
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getcwd(char *buf, size_t size)
|
||||||
|
{
|
||||||
|
PUNICODE_STRING pwstrCurDir;
|
||||||
|
|
||||||
|
__PdxAcquirePdataLock();
|
||||||
|
|
||||||
|
pwstrCurDir = __PdxGetCurDir();
|
||||||
|
|
||||||
|
if(size < (pwstrCurDir->Length / sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
errno = ERANGE;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ANSI_STRING strBuffer;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
strBuffer.Length = 0;
|
||||||
|
strBuffer.MaximumLength = size;
|
||||||
|
strBuffer.Buffer = buf;
|
||||||
|
|
||||||
|
nErrCode = RtlUnicodeStringToAnsiString
|
||||||
|
(
|
||||||
|
&strBuffer,
|
||||||
|
pwstrCurDir,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
__PdxReleasePdataLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
23
posix/lib/psxdll/unistd/getpid.c
Normal file
23
posix/lib/psxdll/unistd/getpid.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/getpid.c
|
||||||
|
* PURPOSE: Get the process ID
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
pid_t getpid(void)
|
||||||
|
{
|
||||||
|
return ((pid_t)NtCurrentTeb()->Cid.UniqueThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
42
posix/lib/psxdll/unistd/getppid.c
Normal file
42
posix/lib/psxdll/unistd/getppid.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/getppid.c
|
||||||
|
* PURPOSE: Get the parent process ID
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <psx/errno.h>
|
||||||
|
|
||||||
|
pid_t getppid(void)
|
||||||
|
{
|
||||||
|
PROCESS_BASIC_INFORMATION pbiInfo;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
|
||||||
|
nErrCode = NtQueryInformationProcess
|
||||||
|
(
|
||||||
|
NtCurrentProcess(),
|
||||||
|
ProcessBasicInformation,
|
||||||
|
&pbiInfo,
|
||||||
|
sizeof(pbiInfo),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(nErrCode))
|
||||||
|
{
|
||||||
|
errno = __status_to_errno(nErrCode);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pbiInfo.InheritedFromUniqueProcessId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
49
posix/lib/psxdll/unistd/read.c
Normal file
49
posix/lib/psxdll/unistd/read.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS POSIX+ Subsystem
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/read.c
|
||||||
|
* PURPOSE: Read from a file
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
ssize_t read(int fildes, void *buf, size_t nbyte)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
|
||||||
|
{
|
||||||
|
HANDLE hFile;
|
||||||
|
NTSTATUS nErrCode;
|
||||||
|
IO_STATUS_BLOCK isbStatus;
|
||||||
|
|
||||||
|
/* get the file handle for the specified file descriptor */
|
||||||
|
if(fcntl(fildes, F_GETFH, &hFile) == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/* read data from file */
|
||||||
|
nErrCode = NtReadFile
|
||||||
|
(
|
||||||
|
hFile,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&isbStatus,
|
||||||
|
buf,
|
||||||
|
nbyte,
|
||||||
|
(PLARGE_INTEGER)&off_t,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
return ((ssize_t)isbStatus.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
15
posix/lib/psxdll/unistd/write.c
Normal file
15
posix/lib/psxdll/unistd/write.c
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/* $Id:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS POSIX+ Subsystem
|
||||||
|
* FILE: subsys/psx/lib/psxdll/unistd/write.c
|
||||||
|
* PURPOSE: Write on a file
|
||||||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* 15/02/2002: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue