re-mark 1.29b-2 as not yet uploaded (merge madness!)
[debian/tar] / src / misc.c
index 0424ea7cc2f9a582805a99e6463ce042cf68d626..071cf2a105240f1dba3ff665bdc0ac3180c27edc 100644 (file)
@@ -1,7 +1,7 @@
 /* Miscellaneous functions, not really specific to GNU tar.
 
    Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010,
 /* Miscellaneous functions, not really specific to GNU tar.
 
    Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010,
-   2012-2013 Free Software Foundation, Inc.
+   2012-2014, 2016 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
 # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
 #endif
 
 # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
 #endif
 
+static void namebuf_add_dir (namebuf_t, char const *);
+static char *namebuf_finish (namebuf_t);
+static const char *tar_getcdpath (int);
+
 \f
 /* Handling strings.  */
 
 \f
 /* Handling strings.  */
 
@@ -230,7 +234,7 @@ zap_slashes (char *name)
 
 /* Normalize FILE_NAME by removing redundant slashes and "."
    components, including redundant trailing slashes.
 
 /* Normalize FILE_NAME by removing redundant slashes and "."
    components, including redundant trailing slashes.
-   Leave ".." alone, as it may be significant in the presence 
+   Leave ".." alone, as it may be significant in the presence
    of symlinks and on platforms where "/.." != "/".
 
    Destructive version: modifies its argument. */
    of symlinks and on platforms where "/.." != "/".
 
    Destructive version: modifies its argument. */
@@ -286,11 +290,14 @@ normalize_filename (int cdidx, const char *name)
          this following approach may lead to situations where the same
          file or directory is processed twice under different absolute
          paths without that duplication being detected.  Perhaps we
          this following approach may lead to situations where the same
          file or directory is processed twice under different absolute
          paths without that duplication being detected.  Perhaps we
-         should use dev+ino pairs instead of names?  */
+         should use dev+ino pairs instead of names?  (See listed03.at for
+         a related test case.) */
       const char *cdpath = tar_getcdpath (cdidx);
       size_t copylen;
       bool need_separator;
       const char *cdpath = tar_getcdpath (cdidx);
       size_t copylen;
       bool need_separator;
-      
+
+      if (!cdpath)
+       call_arg_fatal ("getcwd", ".");
       copylen = strlen (cdpath);
       need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
                          && copylen == 2 && ISSLASH (cdpath[1]));
       copylen = strlen (cdpath);
       need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
                          && copylen == 2 && ISSLASH (cdpath[1]));
@@ -581,7 +588,12 @@ safer_rmdir (const char *file_name)
       return -1;
     }
 
       return -1;
     }
 
-  return unlinkat (chdir_fd, file_name, AT_REMOVEDIR);
+  if (unlinkat (chdir_fd, file_name, AT_REMOVEDIR) == 0)
+    {
+      remove_delayed_set_stat (file_name);
+      return 0;
+    }
+  return -1;
 }
 
 /* Remove FILE_NAME, returning 1 on success.  If FILE_NAME is a directory,
 }
 
 /* Remove FILE_NAME, returning 1 on success.  If FILE_NAME is a directory,
@@ -645,7 +657,7 @@ remove_any_file (const char *file_name, enum remove_option option)
                 (entrylen = strlen (entry)) != 0;
                 entry += entrylen + 1)
              {
                 (entrylen = strlen (entry)) != 0;
                 entry += entrylen + 1)
              {
-               char *file_name_buffer = new_name (file_name, entry);
+               char *file_name_buffer = make_file_name (file_name, entry);
                int r = remove_any_file (file_name_buffer,
                                          RECURSIVE_REMOVE_OPTION);
                int e = errno;
                int r = remove_any_file (file_name_buffer,
                                          RECURSIVE_REMOVE_OPTION);
                int e = errno;
@@ -834,10 +846,11 @@ struct wd
 {
   /* The directory's name.  */
   char const *name;
 {
   /* The directory's name.  */
   char const *name;
-  /* "absolute" path representing this directory; in the contrast to
+  /* "Absolute" path representing this directory; in the contrast to
      the real absolute pathname, it can contain /../ components (see
      the real absolute pathname, it can contain /../ components (see
-     normalize_filename_x for the reason of it). */
-  char *abspath; 
+     normalize_filename_x for the reason of it).  It is NULL if the
+     absolute path could not be determined.  */
+  char *abspath;
   /* If nonzero, the file descriptor of the directory, or AT_FDCWD if
      the working directory.  If zero, the directory needs to be opened
      to be used.  */
   /* If nonzero, the file descriptor of the directory, or AT_FDCWD if
      the working directory.  If zero, the directory needs to be opened
      to be used.  */
@@ -879,15 +892,13 @@ chdir_count (void)
 int
 chdir_arg (char const *dir)
 {
 int
 chdir_arg (char const *dir)
 {
+  char *absdir;
+
   if (wd_count == wd_alloc)
     {
       if (wd_alloc == 0)
   if (wd_count == wd_alloc)
     {
       if (wd_alloc == 0)
-       {
-         wd_alloc = 2;
-         wd = xmalloc (sizeof *wd * wd_alloc);
-       }
-      else
-       wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
+       wd_alloc = 2;
+      wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
 
       if (! wd_count)
        {
 
       if (! wd_count)
        {
@@ -909,18 +920,22 @@ chdir_arg (char const *dir)
        return wd_count - 1;
     }
 
        return wd_count - 1;
     }
 
-  wd[wd_count].name = dir;
-  /* if the given name is an absolute path, then use that path
-     to represent this working directory; otherwise, construct
-     a path based on the previous -C option's absolute path */
-  if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name))
-    wd[wd_count].abspath = xstrdup (wd[wd_count].name);
-  else
+
+  /* If the given name is absolute, use it to represent this directory;
+     otherwise, construct a name based on the previous -C option.  */
+  if (IS_ABSOLUTE_FILE_NAME (dir))
+    absdir = xstrdup (dir);
+  else if (wd[wd_count - 1].abspath)
     {
       namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
     {
       namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
-      namebuf_add_dir (nbuf, wd[wd_count].name);
-      wd[wd_count].abspath = namebuf_finish (nbuf);
+      namebuf_add_dir (nbuf, dir);
+      absdir = namebuf_finish (nbuf);
     }
     }
+  else
+    absdir = 0;
+
+  wd[wd_count].name = dir;
+  wd[wd_count].abspath = absdir;
   wd[wd_count].fd = 0;
   return wd_count++;
 }
   wd[wd_count].fd = 0;
   return wd_count++;
 }
@@ -1007,7 +1022,7 @@ tar_dirname (void)
    chdir_args() has never been called, so we simply return the
    process's actual cwd.  (Note that in this case IDX is ignored,
    since it should always be 0.) */
    chdir_args() has never been called, so we simply return the
    process's actual cwd.  (Note that in this case IDX is ignored,
    since it should always be 0.) */
-const char *
+static const char *
 tar_getcdpath (int idx)
 {
   if (!wd)
 tar_getcdpath (int idx)
 {
   if (!wd)
@@ -1098,13 +1113,6 @@ file_removed_diag (const char *name, bool top_level,
     diagfn (name);
 }
 
     diagfn (name);
 }
 
-void
-write_fatal_details (char const *name, ssize_t status, size_t size)
-{
-  write_error_details (name, status, size);
-  fatal_exit ();
-}
-
 /* Fork, aborting if unsuccessful.  */
 pid_t
 xfork (void)
 /* Fork, aborting if unsuccessful.  */
 pid_t
 xfork (void)
@@ -1189,7 +1197,7 @@ namebuf_name (namebuf_t buf, const char *name)
   return buf->buffer;
 }
 
   return buf->buffer;
 }
 
-void
+static void
 namebuf_add_dir (namebuf_t buf, const char *name)
 {
   static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
 namebuf_add_dir (namebuf_t buf, const char *name)
 {
   static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
@@ -1202,11 +1210,11 @@ namebuf_add_dir (namebuf_t buf, const char *name)
   buf->dir_length += strlen (name);
 }
 
   buf->dir_length += strlen (name);
 }
 
-char *
+static char *
 namebuf_finish (namebuf_t buf)
 {
   char *res = buf->buffer;
 namebuf_finish (namebuf_t buf)
 {
   char *res = buf->buffer;
-  
+
   if (ISSLASH (buf->buffer[buf->dir_length - 1]))
     buf->buffer[buf->dir_length] = 0;
   free (buf);
   if (ISSLASH (buf->buffer[buf->dir_length - 1]))
     buf->buffer[buf->dir_length] = 0;
   free (buf);
@@ -1232,7 +1240,7 @@ tar_savedir (const char *name, int must_exist)
       open_error (name);
     }
   else if (! ((dir = fdopendir (fd))
       open_error (name);
     }
   else if (! ((dir = fdopendir (fd))
-             && (ret = streamsavedir (dir))))
+             && (ret = streamsavedir (dir, savedir_sort_order))))
     savedir_error (name);
 
   if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
     savedir_error (name);
 
   if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)