Resuscitate POSIX subsystem from revision 21378.
[reactos.git] / rossubsys / posix / lib / psxdll / misc / fdtable.c
diff --git a/rossubsys/posix/lib/psxdll/misc/fdtable.c b/rossubsys/posix/lib/psxdll/misc/fdtable.c
new file mode 100644 (file)
index 0000000..76aa0fa
--- /dev/null
@@ -0,0 +1,238 @@
+/* $Id: fdtable.c,v 1.6 2002/10/29 04:45:31 rex Exp $
+ */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS POSIX+ Subsystem
+ * 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 */
+  if(fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors) == 0)
+   pTemp = __malloc((nFileNo + 1) * sizeof(*fdtable->Descriptors));
+  else
+   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);
+
+ /* TODO: check the fileno against the bitmap */
+ return (&fdtable->Descriptors[fileno]);
+}
+
+/* EOF */
+