]> Dogcows Code - chaz/tar/blobdiff - src/misc.c
Improve listed incremental dumps.
[chaz/tar] / src / misc.c
index 7322dd2a0f56c89cde3db3d24c14c51bb4ad1a4a..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
 #include "common.h"
 #include <quotearg.h>
 #include <save-cwd.h>
 #include "common.h"
 #include <quotearg.h>
 #include <save-cwd.h>
+#include <xgetcwd.h>
 #include <unlinkdir.h>
 #include <unlinkdir.h>
+#include <utimens.h>
+#include <canonicalize.h>
+
+#if HAVE_STROPTS_H
+# include <stropts.h>
+#endif
+#if HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
 
 \f
 /* Handling strings.  */
 
 \f
 /* Handling strings.  */
@@ -205,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.  */
 
@@ -404,10 +435,19 @@ 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
    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;
 
 {
   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))
@@ -429,14 +469,6 @@ maybe_backup_file (const char *file_name, int 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 ();
@@ -490,6 +522,26 @@ deref_stat (bool deref, char const *name, struct stat *buf)
   return deref ? stat (name, buf) : lstat (name, buf);
 }
 
   return deref ? stat (name, buf) : lstat (name, buf);
 }
 
+/* Set FD's (i.e., FILE's) access time to TIMESPEC[0].  If that's not
+   possible to do by itself, set its access and data modification
+   times to TIMESPEC[0] and TIMESPEC[1], respectively.  */
+int
+set_file_atime (int fd, char const *file, struct timespec const timespec[2])
+{
+#ifdef _FIOSATIME
+  if (0 <= fd)
+    {
+      struct timeval timeval;
+      timeval.tv_sec = timespec[0].tv_sec;
+      timeval.tv_usec = timespec[0].tv_nsec / 1000;
+      if (ioctl (fd, _FIOSATIME, &timeval) == 0)
+       return 0;
+    }
+#endif
+
+  return gl_futimens (fd, file, timespec);
+}
+
 /* A description of a working directory.  */
 struct wd
 {
 /* A description of a working directory.  */
 struct wd
 {
@@ -502,25 +554,39 @@ 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)
     {
     {
-      wd_alloc = 2 * (wd_alloc + 1);
-      wd = xrealloc (wd, sizeof *wd * wd_alloc);
-      if (! wds)
+      if (wd_alloc == 0)
+       {
+         wd_alloc = 2;
+         wd = xmalloc (sizeof *wd * wd_alloc);
+       }
+      else
+       wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
+
+      if (! wd_count)
        {
        {
-         wd[wds].name = ".";
-         wd[wds].saved = 0;
-         wds++;
+         wd[wd_count].name = ".";
+         wd[wd_count].saved = 0;
+         wd_count++;
        }
     }
 
        }
     }
 
@@ -532,12 +598,12 @@ 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++;
+  wd[wd_count].name = dir;
+  wd[wd_count].saved = 0;
+  return wd_count++;
 }
 
 /* Change to directory I.  If I is 0, change to the initial working
 }
 
 /* Change to directory I.  If I is 0, change to the initial working
@@ -554,9 +620,30 @@ chdir_do (int i)
 
       if (! prev->saved)
        {
 
       if (! prev->saved)
        {
+         int err = 0;
          prev->saved = 1;
          if (save_cwd (&prev->saved_cwd) != 0)
          prev->saved = 1;
          if (save_cwd (&prev->saved_cwd) != 0)
-           FATAL_ERROR ((0, 0, _("Cannot save working directory")));
+           err = errno;
+         else if (0 <= prev->saved_cwd.desc)
+           {
+             /* 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;
+           }
+
+         if (err)
+           FATAL_ERROR ((0, err, _("Cannot save working directory")));
        }
 
       if (curr->saved)
        }
 
       if (curr->saved)
This page took 0.02891 seconds and 4 git commands to generate.