mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +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