]> Dogcows Code - chaz/tar/blobdiff - src/misc.c
Update
[chaz/tar] / src / misc.c
index 55bedd2b2c901669ff4025feadbb2fd338984831..951449eb0c0b035246b02fc50f27d7a7c7e1a49f 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 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>
+
+#if HAVE_STROPTS_H
+# include <stropts.h>
+#endif
+#if HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
 
 \f
 /* Handling strings.  */
 
 \f
 /* Handling strings.  */
@@ -239,6 +248,27 @@ code_ns_fraction (int ns, char *p)
        }
     }
 }
        }
     }
 }
+
+char const *
+code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
+{
+  time_t s = t.tv_sec;
+  int ns = t.tv_nsec;
+  char *np;
+  bool negative = s < 0;
+
+  if (negative && ns != 0)
+    {
+      s++;
+      ns = BILLION - ns;
+    }
+
+  np = umaxtostr (negative ? - (uintmax_t) s : (uintmax_t) s, sbuf + 1);
+  if (negative)
+    *--np = '-';
+  code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND);
+  return np;
+}
 \f
 /* File handling.  */
 
 \f
 /* File handling.  */
 
@@ -383,7 +413,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
    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;
 
@@ -469,6 +499,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
 {
@@ -493,8 +543,14 @@ chdir_arg (char const *dir)
 {
   if (wds == wd_alloc)
     {
 {
   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 = ".";
       if (! wds)
        {
          wd[wds].name = ".";
@@ -533,9 +589,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.023458 seconds and 4 git commands to generate.