]> Dogcows Code - chaz/tar/blobdiff - src/misc.c
Improve listed incremental dumps.
[chaz/tar] / src / misc.c
index 328591ca4b77beb26b216a86499f82687e353282..b56a916b1557a87175c5ea57e308a186c3259b67 100644 (file)
@@ -1,11 +1,11 @@
 /* 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, 2007, 2009 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
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -18,8 +18,6 @@
    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>
@@ -27,6 +25,7 @@
 #include <xgetcwd.h>
 #include <unlinkdir.h>
 #include <utimens.h>
+#include <canonicalize.h>
 
 #if HAVE_STROPTS_H
 # include <stropts.h>
@@ -216,6 +215,27 @@ unquote_string (char *string)
     *destination = '\0';
   return result;
 }
+
+/* Zap trailing slashes.  */
+char *
+zap_slashes (char *name)
+{
+  char *q;
+
+  if (!name || *name == 0)
+    return name;
+  q = name + strlen (name) - 1;
+  while (q > name && ISSLASH (*q))
+    *q-- = '\0';
+  return name;
+}
+
+char *
+normalize_filename (const char *name)
+{
+  return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
+}
+
 \f
 /* Handling numbers.  */
 
@@ -419,6 +439,15 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
 {
   struct stat file_stat;
 
+  assign_string (&before_backup_name, file_name);
+
+  /* A run situation may exist between Emacs or other GNU programs trying to
+     make a backup for the same file simultaneously.  If theoretically
+     possible, real problems are unlikely.  Doing any better would require a
+     convention, GNU-wide, for all programs doing backups.  */
+
+  assign_string (&after_backup_name, 0);
+
   /* Check if we really need to backup the file.  */
 
   if (this_is_the_archive && _remdev (file_name))
@@ -440,14 +469,6 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
       && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
     return true;
 
-  assign_string (&before_backup_name, file_name);
-
-  /* A run situation may exist between Emacs or other GNU programs trying to
-     make a backup for the same file simultaneously.  If theoretically
-     possible, real problems are unlikely.  Doing any better would require a
-     convention, GNU-wide, for all programs doing backups.  */
-
-  assign_string (&after_backup_name, 0);
   after_backup_name = find_backup_file_name (file_name, backup_type);
   if (! after_backup_name)
     xalloc_die ();
@@ -518,7 +539,7 @@ set_file_atime (int fd, char const *file, struct timespec const timespec[2])
     }
 #endif
 
-  return futimens (fd, file, timespec);
+  return gl_futimens (fd, file, timespec);
 }
 
 /* A description of a working directory.  */
@@ -533,17 +554,25 @@ struct wd
 static struct wd *wd;
 
 /* The number of working directories in the vector.  */
-static size_t wds;
+static size_t wd_count;
 
 /* The allocated size of the vector.  */
 static size_t wd_alloc;
 
+int
+chdir_count ()
+{
+  if (wd_count == 0)
+    return wd_count;
+  return wd_count - 1;
+}
+
 /* DIR is the operand of a -C option; add it to vector of chdir targets,
    and return the index of its location.  */
 int
 chdir_arg (char const *dir)
 {
-  if (wds == wd_alloc)
+  if (wd_count == wd_alloc)
     {
       if (wd_alloc == 0)
        {
@@ -553,11 +582,11 @@ chdir_arg (char const *dir)
       else
        wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
 
-      if (! wds)
+      if (! wd_count)
        {
-         wd[wds].name = ".";
-         wd[wds].saved = 0;
-         wds++;
+         wd[wd_count].name = ".";
+         wd[wd_count].saved = 0;
+         wd_count++;
        }
     }
 
@@ -569,49 +598,21 @@ chdir_arg (char const *dir)
        for (dir += 2;  ISSLASH (*dir);  dir++)
          continue;
       if (! dir[dir[0] == '.'])
-       return wds - 1;
+       return wd_count - 1;
     }
 
-  wd[wds].name = dir;
-  wd[wds].saved = 0;
-  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;
-#elif defined HAVE_GETDTABLESIZE
-  return getdtablesize ();
-#endif
-  return -1;
+  wd[wd_count].name = dir;
+  wd[wd_count].saved = 0;
+  return wd_count++;
 }
 
-/* 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)
     {
       struct wd *prev = &wd[previous];
@@ -619,17 +620,30 @@ chdir_do (int i)
 
       if (! prev->saved)
        {
+         int err = 0;
          prev->saved = 1;
-         saved_count++;
-         /* Make sure we still have at least one descriptor available */
-         if (saved_count >= get_max_open_files () - 4)
+         if (save_cwd (&prev->saved_cwd) != 0)
+           err = errno;
+         else if (0 <= prev->saved_cwd.desc)
            {
-             /* Force restore_cwd to use chdir_long */
-             prev->saved_cwd.desc = -1;
-             prev->saved_cwd.name = xgetcwd ();
+             /* Make sure we still have at least one descriptor available.  */
+             int fd1 = prev->saved_cwd.desc;
+             int fd2 = dup (fd1);
+             if (0 <= fd2)
+               close (fd2);
+             else if (errno == EMFILE)
+               {
+                 /* Force restore_cwd to use chdir_long.  */
+                 close (fd1);
+                 prev->saved_cwd.desc = -1;
+                 prev->saved_cwd.name = xgetcwd ();
+               }
+             else
+               err = errno;
            }
-         else if (save_cwd (&prev->saved_cwd) != 0)
-           FATAL_ERROR ((0, 0, _("Cannot save working directory")));
+
+         if (err)
+           FATAL_ERROR ((0, err, _("Cannot save working directory")));
        }
 
       if (curr->saved)
This page took 0.024975 seconds and 4 git commands to generate.