2001-06-18 Roland McGrath <roland@frob.com>
[kopensolaris-gnu/glibc.git] / hurd / alloc-fd.c
index 370a822..16b0da7 100644 (file)
@@ -1,26 +1,26 @@
-/* Copyright (C) 1994 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-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.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include <hurd.h>
 #include <hurd/fd.h>
+#include <hurd/resource.h>
 #include <stdlib.h>
-
-int _hurd_dtable_rlimit;       /* Resource limit on open descriptors.  */
+#include "hurdmalloc.h"                /* XXX */
 
 /* 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,
@@ -32,6 +32,7 @@ _hurd_alloc_fd (int *fd, int first_fd)
 {
   int i;
   void *crit;
+  long int rlimit;
 
   if (first_fd < 0)
     {
@@ -75,42 +76,64 @@ _hurd_alloc_fd (int *fd, int first_fd)
        __spin_unlock (&d->port.lock);
     }
 
-  if (first_fd < _hurd_dtablesize)
+  __mutex_lock (&_hurd_rlimit_lock);
+  rlimit = _hurd_rlimits[RLIMIT_OFILE].rlim_cur;
+  __mutex_unlock (&_hurd_rlimit_lock);
+
+  if (first_fd < rlimit)
     {
       /* The descriptor table is full.  Check if we have reached the
         resource limit, or only the allocated size.  */
-      if (_hurd_dtablesize < _hurd_dtable_rlimit)
+      if (_hurd_dtablesize < rlimit)
        {
          /* Enlarge the table.  */
          int save = errno;
          struct hurd_fd **new;
-         /* Try to double the table size (but don't exceed the limit).  */
+         /* Try to double the table size, but don't exceed the limit,
+            and make sure it exceeds FIRST_FD.  */
          int size = _hurd_dtablesize * 2;
-         if (size > _hurd_dtable_rlimit)
-           size = _hurd_dtable_rlimit;
+         if (size > rlimit)
+           size = rlimit;
+         else if (size <= first_fd)
+           size = first_fd + 1;
+
+         if (size * sizeof (*_hurd_dtable) < size)
+           {
+             /* Integer overflow! */
+             errno = ENOMEM;
+             goto out;
+           }
+
          /* If we fail to allocate that, decrement the desired size
             until we succeed in allocating it.  */
          do
            new = realloc (_hurd_dtable, size * sizeof (*_hurd_dtable));
-         while (new == NULL && size-- > _hurd_dtablesize);
+         while (new == NULL && size-- > first_fd);
+
          if (new != NULL)
            {
              /* We managed to allocate a new table.  Now install it.  */
              errno = save;
-             first_fd = _hurd_dtablesize;
+             if (first_fd < _hurd_dtablesize)
+               first_fd = _hurd_dtablesize;
              /* Initialize the new slots.  */
-             for (i = first_fd; i < size; ++i)
+             for (i = _hurd_dtablesize; i < size; ++i)
                new[i] = NULL;
              _hurd_dtablesize = size;
              _hurd_dtable = new;
              /* Go back to the loop to initialize the first new slot.  */
              goto search;
            }
+         else
+           errno = ENOMEM;
        }
+      else
+       errno = EMFILE;
     }
   else
     errno = EINVAL;            /* Bogus FIRST_FD value.  */
 
+ out:
   __mutex_unlock (&_hurd_dtable_lock);
   _hurd_critical_section_unlock (crit);