]> 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,
 /* 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
 
    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
    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>
    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 <rmt.h>
 #include "common.h"
 #include <quotearg.h>
@@ -27,6 +25,7 @@
 #include <xgetcwd.h>
 #include <unlinkdir.h>
 #include <utimens.h>
 #include <xgetcwd.h>
 #include <unlinkdir.h>
 #include <utimens.h>
+#include <canonicalize.h>
 
 #if HAVE_STROPTS_H
 # include <stropts.h>
 
 #if HAVE_STROPTS_H
 # include <stropts.h>
@@ -216,6 +215,27 @@ unquote_string (char *string)
     *destination = '\0';
   return result;
 }
     *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.  */
 
 \f
 /* Handling numbers.  */
 
@@ -419,6 +439,15 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
 {
   struct stat file_stat;
 
 {
   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))
   /* 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;
 
       && (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 ();
   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
 
     }
 #endif
 
-  return futimens (fd, file, timespec);
+  return gl_futimens (fd, file, timespec);
 }
 
 /* A description of a working directory.  */
 }
 
 /* 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 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;
 
 
 /* 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)
 {
 /* 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)
        {
     {
       if (wd_alloc == 0)
        {
@@ -553,11 +582,11 @@ chdir_arg (char const *dir)
       else
        wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
 
       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] == '.'])
        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;
 /* 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];
   if (previous != i)
     {
       struct wd *prev = &wd[previous];
@@ -619,17 +620,30 @@ chdir_do (int i)
 
       if (! prev->saved)
        {
 
       if (! prev->saved)
        {
+         int err = 0;
          prev->saved = 1;
          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)
        }
 
       if (curr->saved)
This page took 0.027481 seconds and 4 git commands to generate.