]> Dogcows Code - chaz/tar/blobdiff - src/misc.c
Port to Forte Developer 7 C 5.4 and C99.
[chaz/tar] / src / misc.c
index 78844ffcc8f6ed5adca60b9f6cd9fb9a8bab8c74..1d7e9e1eb7daff061e447029c7756fcbe28e4c27 100644 (file)
@@ -1,7 +1,7 @@
 /* Miscellaneous functions, not really specific to GNU tar.
 
    Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include <system.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <rmt.h>
 #include "common.h"
 #include <quotearg.h>
 #include <save-cwd.h>
+#include <xgetcwd.h>
 #include <unlinkdir.h>
 #include <utimens.h>
 
@@ -412,7 +415,7 @@ remove_any_file (const char *file_name, enum remove_option option)
    so, we do not have to backup block or character devices, nor remote
    entities.  */
 bool
-maybe_backup_file (const char *file_name, int this_is_the_archive)
+maybe_backup_file (const char *file_name, bool this_is_the_archive)
 {
   struct stat file_stat;
 
@@ -542,8 +545,14 @@ chdir_arg (char const *dir)
 {
   if (wds == wd_alloc)
     {
-      wd_alloc = 2 * (wd_alloc + 1);
-      wd = xrealloc (wd, sizeof *wd * wd_alloc);
+      if (wd_alloc == 0)
+       {
+         wd_alloc = 2;
+         wd = xmalloc (sizeof *wd * wd_alloc);
+       }
+      else
+       wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
+
       if (! wds)
        {
          wd[wds].name = ".";
@@ -568,12 +577,42 @@ chdir_arg (char const *dir)
   return wds++;
 }
 
+/* Return maximum number of open files */
+int
+get_max_open_files ()
+{
+#if defined _SC_OPEN_MAX
+  return sysconf (_SC_OPEN_MAX);
+#elif defined RLIMIT_NOFILE
+  struct rlimit rlim;
+
+  if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
+    return rlim.rlim_max;
+  return -1;
+#elif defined HAVE_GETDTABLESIZE
+  return getdtablesize ();
+#else
+  return -1;
+#endif
+}
+
+/* Close all descriptors, except the first three */
+void
+closeopen ()
+{
+  int i;
+
+  for (i = get_max_open_files () - 1; i > 2; i--)
+    close (i);
+}
+
 /* Change to directory I.  If I is 0, change to the initial working
    directory; otherwise, I must be a value returned by chdir_arg.  */
 void
 chdir_do (int i)
 {
   static int previous;
+  static int saved_count;
 
   if (previous != i)
     {
@@ -583,7 +622,15 @@ chdir_do (int i)
       if (! prev->saved)
        {
          prev->saved = 1;
-         if (save_cwd (&prev->saved_cwd) != 0)
+         saved_count++;
+         /* Make sure we still have at least one descriptor available */
+         if (saved_count >= get_max_open_files () - 4)
+           {
+             /* Force restore_cwd to use chdir_long */
+             prev->saved_cwd.desc = -1;
+             prev->saved_cwd.name = xgetcwd ();
+           }
+         else if (save_cwd (&prev->saved_cwd) != 0)
            FATAL_ERROR ((0, 0, _("Cannot save working directory")));
        }
 
This page took 0.024678 seconds and 4 git commands to generate.