From ad8ae0a2f56d7ef8a2348dc07e99b4b31cb46d17 Mon Sep 17 00:00:00 2001 From: "KJK::Hyperion" Date: Wed, 20 Feb 2002 07:06:52 +0000 Subject: [PATCH] now introducing the POSIX+ client DLL! (my first check-in, hope I don't f*** up something) svn path=/trunk/; revision=2634 --- posix/lib/psxdll/Makefile | 117 +++++++ posix/lib/psxdll/dirent/closedir.c | 36 +++ posix/lib/psxdll/dirent/opendir.c | 100 ++++++ posix/lib/psxdll/dirent/readdir.c | 214 ++++++++++++ posix/lib/psxdll/dlfcn/dlclose.c | 60 ++++ posix/lib/psxdll/dlfcn/dlerror.c | 36 +++ posix/lib/psxdll/dlfcn/dlopen.c | 129 ++++++++ posix/lib/psxdll/dlfcn/dlsym.c | 92 ++++++ posix/lib/psxdll/errno/errno.c | 25 ++ posix/lib/psxdll/fcntl/fcntl.c | 311 ++++++++++++++++++ posix/lib/psxdll/fcntl/open.c | 181 +++++++++++ posix/lib/psxdll/libgen/basename.c | 114 +++++++ posix/lib/psxdll/misc/fdtable.c | 234 ++++++++++++++ posix/lib/psxdll/misc/interlock.c | 83 +++++ posix/lib/psxdll/misc/main.c | 19 ++ posix/lib/psxdll/misc/path.c | 460 ++++++++++++++++++++++++++ posix/lib/psxdll/misc/safeobj.c | 45 +++ posix/lib/psxdll/misc/template.c | 15 + posix/lib/psxdll/psxdll.def | 143 ++++++++ posix/lib/psxdll/psxdll.edf | 143 ++++++++ posix/lib/psxdll/psxdll.rc | 39 +++ posix/lib/psxdll/pthread/create.c | 198 ++++++++++++ posix/lib/psxdll/pthread/exit.c | 78 +++++ posix/lib/psxdll/pthread/join.c | 98 ++++++ posix/lib/psxdll/pthread/kill.c | 22 ++ posix/lib/psxdll/pthread/mutex.c | 465 +++++++++++++++++++++++++++ posix/lib/psxdll/pthread/self.c | 23 ++ posix/lib/psxdll/sched/yield.c | 33 ++ posix/lib/psxdll/signal/raise.c | 25 ++ posix/lib/psxdll/stdlib/abort.c | 22 ++ posix/lib/psxdll/stdlib/exit.c | 51 +++ posix/lib/psxdll/stdlib/malloc.c | 55 ++++ posix/lib/psxdll/string/strcoll.c | 23 ++ posix/lib/psxdll/string/strdup.c | 44 +++ posix/lib/psxdll/string/strerror.c | 27 ++ posix/lib/psxdll/sys/utsname/uname.c | 178 ++++++++++ posix/lib/psxdll/unistd/close.c | 42 +++ posix/lib/psxdll/unistd/dup.c | 41 +++ posix/lib/psxdll/unistd/getcwd.c | 89 +++++ posix/lib/psxdll/unistd/getpid.c | 23 ++ posix/lib/psxdll/unistd/getppid.c | 42 +++ posix/lib/psxdll/unistd/read.c | 49 +++ posix/lib/psxdll/unistd/write.c | 15 + 43 files changed, 4239 insertions(+) create mode 100644 posix/lib/psxdll/Makefile create mode 100644 posix/lib/psxdll/dirent/closedir.c create mode 100644 posix/lib/psxdll/dirent/opendir.c create mode 100644 posix/lib/psxdll/dirent/readdir.c create mode 100644 posix/lib/psxdll/dlfcn/dlclose.c create mode 100644 posix/lib/psxdll/dlfcn/dlerror.c create mode 100644 posix/lib/psxdll/dlfcn/dlopen.c create mode 100644 posix/lib/psxdll/dlfcn/dlsym.c create mode 100644 posix/lib/psxdll/errno/errno.c create mode 100644 posix/lib/psxdll/fcntl/fcntl.c create mode 100644 posix/lib/psxdll/fcntl/open.c create mode 100644 posix/lib/psxdll/libgen/basename.c create mode 100644 posix/lib/psxdll/misc/fdtable.c create mode 100644 posix/lib/psxdll/misc/interlock.c create mode 100644 posix/lib/psxdll/misc/main.c create mode 100644 posix/lib/psxdll/misc/path.c create mode 100644 posix/lib/psxdll/misc/safeobj.c create mode 100644 posix/lib/psxdll/misc/template.c create mode 100644 posix/lib/psxdll/psxdll.def create mode 100644 posix/lib/psxdll/psxdll.edf create mode 100644 posix/lib/psxdll/psxdll.rc create mode 100644 posix/lib/psxdll/pthread/create.c create mode 100644 posix/lib/psxdll/pthread/exit.c create mode 100644 posix/lib/psxdll/pthread/join.c create mode 100644 posix/lib/psxdll/pthread/kill.c create mode 100644 posix/lib/psxdll/pthread/mutex.c create mode 100644 posix/lib/psxdll/pthread/self.c create mode 100644 posix/lib/psxdll/sched/yield.c create mode 100644 posix/lib/psxdll/signal/raise.c create mode 100644 posix/lib/psxdll/stdlib/abort.c create mode 100644 posix/lib/psxdll/stdlib/exit.c create mode 100644 posix/lib/psxdll/stdlib/malloc.c create mode 100644 posix/lib/psxdll/string/strcoll.c create mode 100644 posix/lib/psxdll/string/strdup.c create mode 100644 posix/lib/psxdll/string/strerror.c create mode 100644 posix/lib/psxdll/sys/utsname/uname.c create mode 100644 posix/lib/psxdll/unistd/close.c create mode 100644 posix/lib/psxdll/unistd/dup.c create mode 100644 posix/lib/psxdll/unistd/getcwd.c create mode 100644 posix/lib/psxdll/unistd/getpid.c create mode 100644 posix/lib/psxdll/unistd/getppid.c create mode 100644 posix/lib/psxdll/unistd/read.c create mode 100644 posix/lib/psxdll/unistd/write.c diff --git a/posix/lib/psxdll/Makefile b/posix/lib/psxdll/Makefile new file mode 100644 index 00000000000..444f16692ef --- /dev/null +++ b/posix/lib/psxdll/Makefile @@ -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 diff --git a/posix/lib/psxdll/dirent/closedir.c b/posix/lib/psxdll/dirent/closedir.c new file mode 100644 index 00000000000..b3af81c4fdb --- /dev/null +++ b/posix/lib/psxdll/dirent/closedir.c @@ -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 + * UPDATE HISTORY: + * 01/02/2002: Created + * 13/02/2002: KJK::Hyperion: modified to use file descriptors + */ + +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/dirent/opendir.c b/posix/lib/psxdll/dirent/opendir.c new file mode 100644 index 00000000000..bc211655dbb --- /dev/null +++ b/posix/lib/psxdll/dirent/opendir.c @@ -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 + * UPDATE HISTORY: + * 27/01/2002: Created + * 13/02/2002: KJK::Hyperion: modified to use file descriptors + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/dirent/readdir.c b/posix/lib/psxdll/dirent/readdir.c new file mode 100644 index 00000000000..79938c47d33 --- /dev/null +++ b/posix/lib/psxdll/dirent/readdir.c @@ -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 + * UPDATE HISTORY: + * 27/01/2002: Created + * 13/02/2002: KJK::Hyperion: modified to use file descriptors + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/dlfcn/dlclose.c b/posix/lib/psxdll/dlfcn/dlclose.c new file mode 100644 index 00000000000..6241a9f8779 --- /dev/null +++ b/posix/lib/psxdll/dlfcn/dlclose.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/dlfcn/dlerror.c b/posix/lib/psxdll/dlfcn/dlerror.c new file mode 100644 index 00000000000..c23c3d3613b --- /dev/null +++ b/posix/lib/psxdll/dlfcn/dlerror.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/dlfcn/dlopen.c b/posix/lib/psxdll/dlfcn/dlopen.c new file mode 100644 index 00000000000..10563aeb0fe --- /dev/null +++ b/posix/lib/psxdll/dlfcn/dlopen.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/dlfcn/dlsym.c b/posix/lib/psxdll/dlfcn/dlsym.c new file mode 100644 index 00000000000..60140e304eb --- /dev/null +++ b/posix/lib/psxdll/dlfcn/dlsym.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/errno/errno.c b/posix/lib/psxdll/errno/errno.c new file mode 100644 index 00000000000..78a7bded106 --- /dev/null +++ b/posix/lib/psxdll/errno/errno.c @@ -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 + * UPDATE HISTORY: + * 27/12/2001: Created + */ + +#include +#include + +static int __errno_storage = 0; + +int * __PdxGetThreadErrNum(void) +{ + FIXME("errno currently not thread-safe"); + return (&__errno_storage); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/fcntl/fcntl.c b/posix/lib/psxdll/fcntl/fcntl.c new file mode 100644 index 00000000000..4ae854862d3 --- /dev/null +++ b/posix/lib/psxdll/fcntl/fcntl.c @@ -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 + * UPDATE HISTORY: + * 13/02/2002: Created + * 15/02/2002: Implemented fcntl() (KJK::Hyperion) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ \ No newline at end of file diff --git a/posix/lib/psxdll/fcntl/open.c b/posix/lib/psxdll/fcntl/open.c new file mode 100644 index 00000000000..6b745825829 --- /dev/null +++ b/posix/lib/psxdll/fcntl/open.c @@ -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 + * UPDATE HISTORY: + * 04/02/2002: Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/libgen/basename.c b/posix/lib/psxdll/libgen/basename.c new file mode 100644 index 00000000000..6f47dcadfdc --- /dev/null +++ b/posix/lib/psxdll/libgen/basename.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/misc/fdtable.c b/posix/lib/psxdll/misc/fdtable.c new file mode 100644 index 00000000000..5c65f1e8a57 --- /dev/null +++ b/posix/lib/psxdll/misc/fdtable.c @@ -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 + * UPDATE HISTORY: + * 12/02/2002: Created + */ + +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/misc/interlock.c b/posix/lib/psxdll/misc/interlock.c new file mode 100644 index 00000000000..a0ea432abbf --- /dev/null +++ b/posix/lib/psxdll/misc/interlock.c @@ -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 + * 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 + +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 */ + diff --git a/posix/lib/psxdll/misc/main.c b/posix/lib/psxdll/misc/main.c new file mode 100644 index 00000000000..f9b394874de --- /dev/null +++ b/posix/lib/psxdll/misc/main.c @@ -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 + * UPDATE HISTORY: + * 27/12/2001: Created + */ + +int __stdcall DllMain(void *hinstDll, unsigned long int dwReason, void *reserved) +{ + return (1); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/misc/path.c b/posix/lib/psxdll/misc/path.c new file mode 100644 index 00000000000..795a53ae6fc --- /dev/null +++ b/posix/lib/psxdll/misc/path.c @@ -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 + * UPDATE HISTORY: + * 31/01/2002: Created + */ + +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/misc/safeobj.c b/posix/lib/psxdll/misc/safeobj.c new file mode 100644 index 00000000000..697fd937120 --- /dev/null +++ b/posix/lib/psxdll/misc/safeobj.c @@ -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 + * UPDATE HISTORY: + * 09/01/2002: Created + */ + +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/misc/template.c b/posix/lib/psxdll/misc/template.c new file mode 100644 index 00000000000..a3a67618202 --- /dev/null +++ b/posix/lib/psxdll/misc/template.c @@ -0,0 +1,15 @@ +/* $Id: + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS POSIX+ Subsystem + * FILE: + * PURPOSE: + * PROGRAMMER: + * UPDATE HISTORY: + * : Created + */ + + +/* EOF */ + diff --git a/posix/lib/psxdll/psxdll.def b/posix/lib/psxdll/psxdll.def new file mode 100644 index 00000000000..013745727f5 --- /dev/null +++ b/posix/lib/psxdll/psxdll.def @@ -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 diff --git a/posix/lib/psxdll/psxdll.edf b/posix/lib/psxdll/psxdll.edf new file mode 100644 index 00000000000..b3485bc3c3d --- /dev/null +++ b/posix/lib/psxdll/psxdll.edf @@ -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 diff --git a/posix/lib/psxdll/psxdll.rc b/posix/lib/psxdll/psxdll.rc new file mode 100644 index 00000000000..0f9befb9b1c --- /dev/null +++ b/posix/lib/psxdll/psxdll.rc @@ -0,0 +1,39 @@ +/* $Id: psxdll.rc,v 1.1 2002/02/20 07:06:50 hyperion Exp $ +*/ +#include +#include + +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 diff --git a/posix/lib/psxdll/pthread/create.c b/posix/lib/psxdll/pthread/create.c new file mode 100644 index 00000000000..93f53b8e8e1 --- /dev/null +++ b/posix/lib/psxdll/pthread/create.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include + +/* 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 */ + diff --git a/posix/lib/psxdll/pthread/exit.c b/posix/lib/psxdll/pthread/exit.c new file mode 100644 index 00000000000..429822f49e7 --- /dev/null +++ b/posix/lib/psxdll/pthread/exit.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/pthread/join.c b/posix/lib/psxdll/pthread/join.c new file mode 100644 index 00000000000..694a7155f5b --- /dev/null +++ b/posix/lib/psxdll/pthread/join.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/pthread/kill.c b/posix/lib/psxdll/pthread/kill.c new file mode 100644 index 00000000000..783f2959651 --- /dev/null +++ b/posix/lib/psxdll/pthread/kill.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include + +int pthread_kill(pthread_t thread, int sig) +{ + return (ENOSYS); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/pthread/mutex.c b/posix/lib/psxdll/pthread/mutex.c new file mode 100644 index 00000000000..7e89f43b0ed --- /dev/null +++ b/posix/lib/psxdll/pthread/mutex.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/pthread/self.c b/posix/lib/psxdll/pthread/self.c new file mode 100644 index 00000000000..0dea976da65 --- /dev/null +++ b/posix/lib/psxdll/pthread/self.c @@ -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 + * UPDATE HISTORY: + * 27/12/2001: Created + */ + +#include +#include +#include + +pthread_t pthread_self(void) +{ + return ((pthread_t)(NtCurrentTeb()->Cid).UniqueThread); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/sched/yield.c b/posix/lib/psxdll/sched/yield.c new file mode 100644 index 00000000000..8477b393e07 --- /dev/null +++ b/posix/lib/psxdll/sched/yield.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include +#include + +int sched_yield(void) +{ + NTSTATUS nErrCode; + + nErrCode = NtYieldExecution(); + + if(!NT_SUCCESS(nErrCode)) + { + errno = __status_to_errno(nErrCode); + return (-1); + } + + return (0); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/signal/raise.c b/posix/lib/psxdll/signal/raise.c new file mode 100644 index 00000000000..479901dc6a9 --- /dev/null +++ b/posix/lib/psxdll/signal/raise.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/stdlib/abort.c b/posix/lib/psxdll/stdlib/abort.c new file mode 100644 index 00000000000..134ad92f2e8 --- /dev/null +++ b/posix/lib/psxdll/stdlib/abort.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include + +void abort(void) +{ + raise(SIGABRT); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/stdlib/exit.c b/posix/lib/psxdll/stdlib/exit.c new file mode 100644 index 00000000000..d76c580457e --- /dev/null +++ b/posix/lib/psxdll/stdlib/exit.c @@ -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 + * UPDATE HISTORY: + * 27/12/2001: Created + */ + +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/stdlib/malloc.c b/posix/lib/psxdll/stdlib/malloc.c new file mode 100644 index 00000000000..c0b66e7b0ef --- /dev/null +++ b/posix/lib/psxdll/stdlib/malloc.c @@ -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 + * UPDATE HISTORY: + * 27/12/2001: Created + */ + +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/string/strcoll.c b/posix/lib/psxdll/string/strcoll.c new file mode 100644 index 00000000000..ebd42ffa6c4 --- /dev/null +++ b/posix/lib/psxdll/string/strcoll.c @@ -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 + * UPDATE HISTORY: + * 20/01/2002: Created + */ + +#include +#include + +int strcoll(const char *s1, const char *s2) +{ + TODO("locale semantics currently unimplemented"); + return (strcmp(s1, s2)); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/string/strdup.c b/posix/lib/psxdll/string/strdup.c new file mode 100644 index 00000000000..9f5695cdfc9 --- /dev/null +++ b/posix/lib/psxdll/string/strdup.c @@ -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 + * UPDATE HISTORY: + * 21/01/2002: Created + */ + +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/string/strerror.c b/posix/lib/psxdll/string/strerror.c new file mode 100644 index 00000000000..361ff0320f0 --- /dev/null +++ b/posix/lib/psxdll/string/strerror.c @@ -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 + * UPDATE HISTORY: + * 20/01/2002: Created + */ + +#include +#include +#include + +static char *__errstr = ""; +char *strerror(int errnum) +{ + INFO("errnum %#x", errnum); + TODO("getting error string not currently implemented"); + errno = EINVAL; + return (__errstr); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/sys/utsname/uname.c b/posix/lib/psxdll/sys/utsname/uname.c new file mode 100644 index 00000000000..68f1f3fae37 --- /dev/null +++ b/posix/lib/psxdll/sys/utsname/uname.c @@ -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 + * UPDATE HISTORY: + * 19/12/2001: Created + */ + +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/unistd/close.c b/posix/lib/psxdll/unistd/close.c new file mode 100644 index 00000000000..020fe67adf2 --- /dev/null +++ b/posix/lib/psxdll/unistd/close.c @@ -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 + * UPDATE HISTORY: + * 13/02/2002: Created + */ + +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/unistd/dup.c b/posix/lib/psxdll/unistd/dup.c new file mode 100644 index 00000000000..b746563dd77 --- /dev/null +++ b/posix/lib/psxdll/unistd/dup.c @@ -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 + * UPDATE HISTORY: + * 13/02/2002: Created + */ + +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/unistd/getcwd.c b/posix/lib/psxdll/unistd/getcwd.c new file mode 100644 index 00000000000..51771e00a40 --- /dev/null +++ b/posix/lib/psxdll/unistd/getcwd.c @@ -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 + * UPDATE HISTORY: + * 01/02/2002: Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/unistd/getpid.c b/posix/lib/psxdll/unistd/getpid.c new file mode 100644 index 00000000000..2a3ebd33db0 --- /dev/null +++ b/posix/lib/psxdll/unistd/getpid.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include +#include + +pid_t getpid(void) +{ + return ((pid_t)NtCurrentTeb()->Cid.UniqueThread); +} + +/* EOF */ + diff --git a/posix/lib/psxdll/unistd/getppid.c b/posix/lib/psxdll/unistd/getppid.c new file mode 100644 index 00000000000..8d5ed88a070 --- /dev/null +++ b/posix/lib/psxdll/unistd/getppid.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/unistd/read.c b/posix/lib/psxdll/unistd/read.c new file mode 100644 index 00000000000..a3ce7126058 --- /dev/null +++ b/posix/lib/psxdll/unistd/read.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + +#include +#include +#include + +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 */ + diff --git a/posix/lib/psxdll/unistd/write.c b/posix/lib/psxdll/unistd/write.c new file mode 100644 index 00000000000..a234ef37744 --- /dev/null +++ b/posix/lib/psxdll/unistd/write.c @@ -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 + * UPDATE HISTORY: + * 15/02/2002: Created + */ + + +/* EOF */ + -- 2.17.1