now introducing the POSIX+ client DLL! (my first check-in, hope I don't f*** up somet...
authorKJK::Hyperion <hackbunny@reactos.org>
Wed, 20 Feb 2002 07:06:52 +0000 (07:06 +0000)
committerKJK::Hyperion <hackbunny@reactos.org>
Wed, 20 Feb 2002 07:06:52 +0000 (07:06 +0000)
svn path=/trunk/; revision=2634

43 files changed:
posix/lib/psxdll/Makefile [new file with mode: 0644]
posix/lib/psxdll/dirent/closedir.c [new file with mode: 0644]
posix/lib/psxdll/dirent/opendir.c [new file with mode: 0644]
posix/lib/psxdll/dirent/readdir.c [new file with mode: 0644]
posix/lib/psxdll/dlfcn/dlclose.c [new file with mode: 0644]
posix/lib/psxdll/dlfcn/dlerror.c [new file with mode: 0644]
posix/lib/psxdll/dlfcn/dlopen.c [new file with mode: 0644]
posix/lib/psxdll/dlfcn/dlsym.c [new file with mode: 0644]
posix/lib/psxdll/errno/errno.c [new file with mode: 0644]
posix/lib/psxdll/fcntl/fcntl.c [new file with mode: 0644]
posix/lib/psxdll/fcntl/open.c [new file with mode: 0644]
posix/lib/psxdll/libgen/basename.c [new file with mode: 0644]
posix/lib/psxdll/misc/fdtable.c [new file with mode: 0644]
posix/lib/psxdll/misc/interlock.c [new file with mode: 0644]
posix/lib/psxdll/misc/main.c [new file with mode: 0644]
posix/lib/psxdll/misc/path.c [new file with mode: 0644]
posix/lib/psxdll/misc/safeobj.c [new file with mode: 0644]
posix/lib/psxdll/misc/template.c [new file with mode: 0644]
posix/lib/psxdll/psxdll.def [new file with mode: 0644]
posix/lib/psxdll/psxdll.edf [new file with mode: 0644]
posix/lib/psxdll/psxdll.rc [new file with mode: 0644]
posix/lib/psxdll/pthread/create.c [new file with mode: 0644]
posix/lib/psxdll/pthread/exit.c [new file with mode: 0644]
posix/lib/psxdll/pthread/join.c [new file with mode: 0644]
posix/lib/psxdll/pthread/kill.c [new file with mode: 0644]
posix/lib/psxdll/pthread/mutex.c [new file with mode: 0644]
posix/lib/psxdll/pthread/self.c [new file with mode: 0644]
posix/lib/psxdll/sched/yield.c [new file with mode: 0644]
posix/lib/psxdll/signal/raise.c [new file with mode: 0644]
posix/lib/psxdll/stdlib/abort.c [new file with mode: 0644]
posix/lib/psxdll/stdlib/exit.c [new file with mode: 0644]
posix/lib/psxdll/stdlib/malloc.c [new file with mode: 0644]
posix/lib/psxdll/string/strcoll.c [new file with mode: 0644]
posix/lib/psxdll/string/strdup.c [new file with mode: 0644]
posix/lib/psxdll/string/strerror.c [new file with mode: 0644]
posix/lib/psxdll/sys/utsname/uname.c [new file with mode: 0644]
posix/lib/psxdll/unistd/close.c [new file with mode: 0644]
posix/lib/psxdll/unistd/dup.c [new file with mode: 0644]
posix/lib/psxdll/unistd/getcwd.c [new file with mode: 0644]
posix/lib/psxdll/unistd/getpid.c [new file with mode: 0644]
posix/lib/psxdll/unistd/getppid.c [new file with mode: 0644]
posix/lib/psxdll/unistd/read.c [new file with mode: 0644]
posix/lib/psxdll/unistd/write.c [new file with mode: 0644]

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