Formerly ../hurd/alloc-fd.c.~6~
[kopensolaris-gnu/glibc.git] / hurd / alloc-fd.c
index 5eacc41..f138d52 100644 (file)
@@ -16,20 +16,44 @@ License along with the GNU C Library; see the file COPYING.LIB.  If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
+#include <hurd.h>
 #include <hurd/fd.h>
 #include <hurd/fd.h>
+#include <stdlib.h>
+
+/* Allocate a new file descriptor and return it, locked.  The new
+   descriptor number will be no less than FIRST_FD.  If the table is full,
+   set errno to EMFILE and return NULL.  If FIRST_FD is negative or bigger
+   than the size of the table, set errno to EINVAL and return NULL.  */
 
 
-/* Allocate a new file descriptor and return it, locked.
-   If the table is full, set errno and return NULL.  */
 struct hurd_fd *
 _hurd_alloc_fd (int *fd, const int first_fd)
 {
   int i;
 
 struct hurd_fd *
 _hurd_alloc_fd (int *fd, const int first_fd)
 {
   int i;
 
-  __mutex_lock (&hurd_dtable_lock);
+  if (first_fd < 0)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  __mutex_lock (&_hurd_dtable_lock);
 
   for (i = first_fd; i < _hurd_dtable.size; ++i)
     {
 
   for (i = first_fd; i < _hurd_dtable.size; ++i)
     {
-      struct hurd_fd *d = &_hurd_dtable.d[i];
+      struct hurd_fd *d = _hurd_dtable.d[i];
+      if (d == NULL)
+       {
+         /* Allocate a new descriptor structure for this slot,
+            initializing its port cells to nil.  The test below will catch
+            and return this descriptor cell after locking it.  */
+         d = _hurd_new_fd (MACH_PORT_NULL, MACH_PORT_NULL);
+         if (d == NULL)
+           {
+             __mutex_unlock (&hurd_dtable_lock);
+             return NULL;
+           }
+       }
+
       __spin_lock (&d->port.lock);
       if (d->port.port == MACH_PORT_NULL)
        {
       __spin_lock (&d->port.lock);
       if (d->port.port == MACH_PORT_NULL)
        {
@@ -42,8 +66,9 @@ _hurd_alloc_fd (int *fd, const int first_fd)
        __spin_unlock (&d->port.lock);
     }
 
        __spin_unlock (&d->port.lock);
     }
 
+  errno = first_fd < _hurd_dtable.size ? EMFILE : EINVAL;
+
   __mutex_unlock (&hurd_dtable_lock);
 
   __mutex_unlock (&hurd_dtable_lock);
 
-  errno = EMFILE;
   return NULL;
 }
   return NULL;
 }