浏览代码

maint: port to Fedora 33

Fedora 33 uses GCC 10.2.1, which is a bit pickier.
* configure.ac: Do not use -Wsystem-headers, as this
runs afoul of netdb.h on Fedora 33.
* gnulib.modules: Add ‘attribute’.
* lib/wordsplit.c (wsnode_new): Return the newly allocated
pointer instead of a boolean, to pacify GCC 10.2.1 which otherwise
complains about use of possibly-null pointers.  All uses changed.
* src/buffer.c (try_new_volume): Don’t assume find_next_block succeeds.
(_write_volume_label): Pacify GCC 10.2.1 with an ‘assume’, since
LABEL must be nonnull here.
* src/common.h (FALLTHROUGH): Remove; now in attribute.h.
Include attribute.h, for ATTRIBUTE_NONNULL.
* src/misc.c (assign_string_or_null): New function,
taking over the old role of assign_string.
(assign_string): Assume VALUE is non-null.
(assign_null): New function, taking over the old
role of assign_string when its VALUE was nonnull.
All callers of assign_string changed to use these functions.
(assign_string_n): Clear *STRING if VALUE is null,
to fix a potential double-free.
Paul Eggert 4 年之前
父节点
当前提交
8378991cba
共有 7 个文件被更改,包括 124 次插入100 次删除
  1. 4 3
      configure.ac
  2. 1 0
      gnulib.modules
  3. 72 69
      lib/wordsplit.c
  4. 5 3
      src/buffer.c
  5. 5 7
      src/common.h
  6. 11 11
      src/extract.c
  7. 26 7
      src/misc.c

+ 4 - 3
configure.ac

@@ -112,7 +112,7 @@ if test $ac_cv_lib_error_at_line = no; then
   AC_DEFINE([ENABLE_ERROR_PRINT_PROGNAME],[1],
             [Enable the use of error_print_progname to print program name with error messages.
 	     See comment to function tar_print_progname in src/tar.c])
-fi  
+fi
 
 # paxutils modules
 tar_PAXUTILS
@@ -162,6 +162,7 @@ if test "$gl_gcc_warnings" = yes; then
   nw="$nw -Winline"                 # It's OK to not inline.
   nw="$nw -Wstrict-overflow"	    # It's OK to optimize strictly.
   nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now.
+  nw="$nw -Wsystem-headers"         # Don't let system headers trigger warnings
   nw="$nw -Wstack-protector"
 
   gl_MANYWARN_ALL_GCC([ws])
@@ -173,10 +174,10 @@ if test "$gl_gcc_warnings" = yes; then
   gl_WARN_ADD([-Wno-type-limits])      # It's OK to optimize based on types.
   gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
   gl_WARN_ADD([-Wno-format-nonliteral])
-  
+
   gl_WARN_ADD([-fdiagnostics-show-option])
   gl_WARN_ADD([-funit-at-a-time])
-  
+
 
   AC_SUBST([WARN_CFLAGS])
 

+ 1 - 0
gnulib.modules

@@ -23,6 +23,7 @@ areadlinkat-with-size
 argmatch
 argp
 argp-version-etc
+attribute
 backupfile
 closeout
 configmake

+ 72 - 69
lib/wordsplit.c

@@ -95,7 +95,7 @@ _wsplt_seterr (struct wordsplit *wsp, int ec)
     wordsplit_perror (wsp);
   return ec;
 }
-  
+
 static int
 _wsplt_nomem (struct wordsplit *wsp)
 {
@@ -126,7 +126,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
 		 unsigned flags, int finalize)
 {
   int rc;
-  
+
   wss->ws_delim = wsp->ws_delim;
   wss->ws_debug = wsp->ws_debug;
   wss->ws_error = wsp->ws_error;
@@ -150,7 +150,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
     }
 
   wss->ws_options = wsp->ws_options;
-  
+
   flags |= WRDSF_DELIM
          | WRDSF_ALLOC_DIE
          | WRDSF_ERROR
@@ -209,7 +209,7 @@ wordsplit_init0 (struct wordsplit *wsp)
 }
 
 char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
-  
+
 static int
 wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 		unsigned flags)
@@ -282,7 +282,7 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 	{
 	  wsp->ws_escape[WRDSX_WORD] = wordsplit_c_escape_tab;
 	  wsp->ws_escape[WRDSX_QUOTE] = wordsplit_c_escape_tab;
-	  wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD       
+	  wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD
 	                     | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD;
 	}
       else
@@ -292,16 +292,16 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 	  wsp->ws_options |= WRDSO_BSKEEP_QUOTE;
 	}
     }
-  
+
   wsp->ws_endp = 0;
   wsp->ws_wordi = 0;
 
   if (wsp->ws_flags & WRDSF_REUSE)
     wordsplit_free_nodes (wsp);
   wsp->ws_head = wsp->ws_tail = NULL;
-  
+
   wordsplit_init0 (wsp);
-  
+
   return 0;
 }
 
@@ -424,14 +424,13 @@ wsnode_len (struct wordsplit_node *p)
     return p->v.segm.end - p->v.segm.beg;
 }
 
-static int
-wsnode_new (struct wordsplit *wsp, struct wordsplit_node **pnode)
+static struct wordsplit_node *
+wsnode_new (struct wordsplit *wsp)
 {
   struct wordsplit_node *node = calloc (1, sizeof (*node));
   if (!node)
-    return _wsplt_nomem (wsp);
-  *pnode = node;
-  return 0;
+    _wsplt_nomem (wsp);
+  return node;
 }
 
 static void
@@ -527,14 +526,11 @@ wsnode_insert (struct wordsplit *wsp, struct wordsplit_node *node,
 static int
 wordsplit_add_segm (struct wordsplit *wsp, size_t beg, size_t end, int flg)
 {
-  struct wordsplit_node *node;
-  int rc;
-
   if (end == beg && !(flg & _WSNF_EMPTYOK))
     return 0;
-  rc = wsnode_new (wsp, &node);
-  if (rc)
-    return rc;
+  struct wordsplit_node *node = wsnode_new (wsp);
+  if (!node)
+    return 1;
   node->flags = flg & ~(_WSNF_WORD | _WSNF_EMPTYOK);
   node->v.segm.beg = beg;
   node->v.segm.end = end;
@@ -587,7 +583,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
 
   if (!(node->flags & _WSNF_JOIN))
     return 0;
-  
+
   for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next)
     {
       len += wsnode_len (p);
@@ -717,7 +713,7 @@ wordsplit_finish (struct wordsplit *wsp)
 
      Nodes of type _WSNF_DELIM get inserted to the node list if either
      WRDSF_RETURN_DELIMS flag or WRDSO_MAXWORDS option is set.
-     
+
      The following cases should be distinguished:
 
      1. If both WRDSF_SQUEEZE_DELIMS and WRDSF_RETURN_DELIMS are set, compress
@@ -781,7 +777,7 @@ wordsplit_finish (struct wordsplit *wsp)
 	      continue;
 	    }
 	}
-      else 
+      else
 	{
 	  if (delim)
 	    {
@@ -900,11 +896,11 @@ node_split_prefix (struct wordsplit *wsp,
 		   struct wordsplit_node *node,
 		   size_t beg, size_t len, int flg)
 {
-  struct wordsplit_node *newnode;
 
   if (len == 0)
     return 0;
-  if (wsnode_new (wsp, &newnode))
+  struct wordsplit_node *newnode = wsnode_new (wsp);
+  if (!newnode)
     return 1;
   wsnode_insert (wsp, newnode, *ptail, 0);
   if (node->flags & _WSNF_WORD)
@@ -958,7 +954,7 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff,
 		  break;
 		}
 	      break;
-	      
+
 	    case '"':
 	      state = st_dquote;
 	      break;
@@ -1038,7 +1034,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 {
   int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
   char *v;
-  
+
   if (wsp->ws_envidx + n >= wsp->ws_envsiz)
     {
       size_t sz;
@@ -1055,7 +1051,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 		  for (; wsp->ws_env[i]; i++)
 		    ;
 		}
-	      
+
 	      sz = i + n + 1;
 
 	      newenv = calloc (sz, sizeof(newenv[0]));
@@ -1075,7 +1071,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 		    }
 		}
 	      newenv[j] = NULL;
-	      
+
 	      wsp->ws_envbuf = newenv;
 	      wsp->ws_envidx = i;
 	      wsp->ws_envsiz = sz;
@@ -1104,7 +1100,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 	  wsp->ws_env = (const char**) wsp->ws_envbuf;
 	}
     }
-  
+
   if (wsp->ws_flags & WRDSF_ENV_KV)
     {
       /* A key-value pair environment */
@@ -1149,7 +1145,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
   const char *start = str - 1;
   int rc;
   struct wordsplit ws;
-  
+
   if (ISVARBEG (str[0]))
     {
       for (i = 1; i < len; i++)
@@ -1166,7 +1162,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  if (str[i] == ':')
 	    {
 	      size_t j;
-	      
+
 	      defstr = str + i + 1;
 	      if (find_closing_paren (str, i + 1, len, &j, "{}"))
 		return _wsplt_seterr (wsp, WRDSE_CBRACE);
@@ -1182,7 +1178,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  else if (strchr ("-+?=", str[i]))
 	    {
 	      size_t j;
-	      
+
 	      defstr = str + i;
 	      if (find_closing_paren (str, i, len, &j, "{}"))
 		return _wsplt_seterr (wsp, WRDSE_CBRACE);
@@ -1195,7 +1191,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     }
   else
     {
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
@@ -1247,7 +1244,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  rc = WRDSE_UNDEF;
 	}
     }
-  
+
   switch (rc)
     {
     case WRDSE_OK:
@@ -1267,7 +1264,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  wordsplit_free (&ws);
 	}
       break;
-      
+
     case WRDSE_UNDEF:
       if (defstr)
 	{
@@ -1287,11 +1284,11 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	      value = ws.ws_wordv[0];
 	      ws.ws_wordv[0] = NULL;
 	      wordsplit_free (&ws);
-	      
+
 	      if (defstr[-1] == '=')
 		wsplt_assign_var (wsp, str, i, value);
 	    }
-	  else 
+	  else
 	    {
 	      if (*defstr == '?')
 		{
@@ -1339,7 +1336,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	    }
 	}
       break;
-      
+
     case WRDSE_NOSPACE:
       return _wsplt_nomem (wsp);
 
@@ -1357,7 +1354,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     {
       if (flg & _WSNF_QUOTE)
 	{
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    {
 	      free (value);
 	      return 1;
@@ -1371,7 +1369,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	{
 	  free (value);
 	  /* Empty string is a special case */
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    return 1;
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  *ptail = newnode;
@@ -1381,7 +1380,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	{
 	  struct wordsplit ws;
 	  int rc;
-	  
+
 	  rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
 				WRDSF_NOVAR | WRDSF_NOCMD |
 				WRDSF_QUOTE
@@ -1404,7 +1403,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     {
       size_t size = *pend - start + 1;
 
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
@@ -1417,7 +1417,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     }
   else
     {
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
@@ -1486,7 +1487,7 @@ node_expand (struct wordsplit *wsp, struct wordsplit_node *node,
     }
   return 0;
 }
-  
+
 /* Remove NULL nodes from the list */
 static void
 wsnode_nullelim (struct wordsplit *wsp)
@@ -1539,7 +1540,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
   size_t j;
   char *value;
   struct wordsplit_node *newnode;
-  
+
   str++;
   len--;
 
@@ -1566,7 +1567,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
     }
   else
     rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure);
-  
+
   if (rc == WRDSE_NOSPACE)
     return _wsplt_nomem (wsp);
   else if (rc)
@@ -1585,7 +1586,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
     {
       if (flg & _WSNF_QUOTE)
 	{
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    return 1;
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  *ptail = newnode;
@@ -1596,7 +1598,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
 	{
 	  free (value);
 	  /* Empty string is a special case */
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    return 1;
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  *ptail = newnode;
@@ -1627,7 +1630,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
     }
   else
     {
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
@@ -1674,13 +1678,13 @@ wordsplit_trimws (struct wordsplit *wsp)
 	    ;
 	  p->v.segm.beg = n;
 	}
-      
+
       while (p->next && (p->flags & _WSNF_JOIN))
 	p = p->next;
-      
+
       if (p->flags & _WSNF_QUOTE)
 	continue;
-      
+
       /* Trim trailing whitespace */
       for (n = p->v.segm.end;
 	   n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--);
@@ -1699,7 +1703,7 @@ wordsplit_tildexpand (struct wordsplit *wsp)
   struct wordsplit_node *p;
   char *uname = NULL;
   size_t usize = 0;
-  
+
   for (p = wsp->ws_head; p; p = p->next)
     {
       const char *str;
@@ -1714,7 +1718,7 @@ wordsplit_tildexpand (struct wordsplit *wsp)
 	  size_t slen = wsnode_len (p);
 	  struct passwd *pw;
 	  char *newstr;
-	  
+
 	  for (i = 1; i < slen && str[i] != '/'; i++)
 	    ;
 	  if (i == slen)
@@ -1788,7 +1792,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
   if (wsp->ws_options & WRDSO_DOTGLOB)
     flags = GLOB_PERIOD;
 #endif
-  
+
   for (p = wsp->ws_head; p; p = next)
     {
       const char *str;
@@ -1807,23 +1811,23 @@ wordsplit_pathexpand (struct wordsplit *wsp)
 	  glob_t g;
 	  struct wordsplit_node *prev;
 	  char *pattern;
-	  
+
 	  pattern = malloc (slen + 1);
 	  if (!pattern)
 	    return _wsplt_nomem (wsp);
 	  memcpy (pattern, str, slen);
 	  pattern[slen] = 0;
-      
+
 	  switch (glob (pattern, flags, NULL, &g))
 	    {
 	    case 0:
 	      free (pattern);
 	      break;
-	      
+
 	    case GLOB_NOSPACE:
 	      free (pattern);
 	      return _wsplt_nomem (wsp);
-	      
+
 	    case GLOB_NOMATCH:
 	      if (wsp->ws_options & WRDSO_NULLGLOB)
 		{
@@ -1846,7 +1850,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
 		}
 	      free (pattern);
 	      continue;
-	      
+
 	    default:
 	      free (pattern);
 	      return _wsplt_seterr (wsp, WRDSE_GLOBERR);
@@ -1855,10 +1859,10 @@ wordsplit_pathexpand (struct wordsplit *wsp)
 	  prev = p;
 	  for (i = 0; i < g.gl_pathc; i++)
 	    {
-	      struct wordsplit_node *newnode;
+	      struct wordsplit_node *newnode = wsnode_new (wsp);
 	      char *newstr;
-	      
-	      if (wsnode_new (wsp, &newnode))
+
+	      if (!newnode)
 		return 1;
 	      newstr = strdup (g.gl_pathv[i]);
 	      if (!newstr)
@@ -1975,7 +1979,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
   int join = 0;
   unsigned flags = 0;
   struct wordsplit_node *np = wsp->ws_tail;
-  
+
   size_t i = start;
 
   if (i >= len)
@@ -2064,7 +2068,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
   wsp->ws_endp = i;
   if (wsp->ws_flags & WRDSF_INCREMENTAL)
     return _WRDS_EOF;
-  
+
   if (consume_all)
     {
       if (!np)
@@ -2075,7 +2079,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
 	  np = np->next;
 	}
     }
-  
+
   return _WRDS_OK;
 }
 
@@ -2342,7 +2346,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
   if (wsp->ws_flags & WRDSF_SHOWDBG)
     wsp->ws_debug (_("(%02d) Input:%.*s;"),
 		   wsp->ws_lvl, (int) wsp->ws_len, wsp->ws_input);
-  
+
   if ((wsp->ws_flags & WRDSF_NOSPLIT)
       || ((wsp->ws_options & WRDSO_MAXWORDS)
 	  && wsp->ws_wordi + 1 == wsp->ws_maxwords))
@@ -2438,7 +2442,7 @@ wordsplit_run (const char *command, size_t length, struct wordsplit *wsp,
 }
 
 int
-wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, 
+wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
                unsigned flags)
 {
   return wordsplit_run (command, length, wsp, flags, 0);
@@ -2559,4 +2563,3 @@ wordsplit_perror (struct wordsplit *wsp)
       wsp->ws_error ("%s", wordsplit_strerror (wsp));
     }
 }
-

+ 5 - 3
src/buffer.c

@@ -28,6 +28,7 @@
 #include <fnmatch.h>
 #include <human.h>
 #include <quotearg.h>
+#include <verify.h>
 
 #include "common.h"
 #include <rmt.h>
@@ -1325,8 +1326,8 @@ new_volume (enum access_mode mode)
   if (verify_option)
     verify_volume ();
 
-  assign_string (&volume_label, NULL);
-  assign_string (&continued_file_name, NULL);
+  assign_null (&volume_label);
+  assign_null (&continued_file_name);
   continued_file_size = continued_file_offset = 0;
   current_block = record_start;
 
@@ -1505,7 +1506,7 @@ try_new_volume (void)
       ASSIGN_STRING_N (&volume_label, current_header->header.name);
       set_next_block_after (header);
       header = find_next_block ();
-      if (header->header.typeflag != GNUTYPE_MULTIVOL)
+      if (! (header && header->header.typeflag == GNUTYPE_MULTIVOL))
         break;
       FALLTHROUGH;
     case GNUTYPE_MULTIVOL:
@@ -1688,6 +1689,7 @@ _write_volume_label (const char *str)
     {
       union block *label = find_next_block ();
 
+      assume (label);
       memset (label, 0, BLOCKSIZE);
 
       strcpy (label->header.name, str);

+ 5 - 7
src/common.h

@@ -43,18 +43,13 @@
 # define GLOBAL extern
 #endif
 
-#if 7 <= __GNUC__
-# define FALLTHROUGH __attribute__ ((__fallthrough__))
-#else
-# define FALLTHROUGH ((void) 0)
-#endif
-
 #define TAREXIT_SUCCESS PAXEXIT_SUCCESS
 #define TAREXIT_DIFFERS PAXEXIT_DIFFERS
 #define TAREXIT_FAILURE PAXEXIT_FAILURE
 
 
 #include "arith.h"
+#include <attribute.h>
 #include <backupfile.h>
 #include <exclude.h>
 #include <full-write.h>
@@ -633,7 +628,10 @@ void skip_member (void);
 #define max(a, b) ((a) < (b) ? (b) : (a))
 
 char const *quote_n_colon (int n, char const *arg);
-void assign_string (char **dest, const char *src);
+void assign_string_or_null (char **dest, const char *src)
+  ATTRIBUTE_NONNULL ((1));
+void assign_string (char **dest, const char *src) ATTRIBUTE_NONNULL ((1, 2));
+void assign_null (char **dest) ATTRIBUTE_NONNULL ((1));
 void assign_string_n (char **string, const char *value, size_t n);
 #define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v))
 int unquote_string (char *str);

+ 11 - 11
src/extract.c

@@ -520,7 +520,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
   data->change_dir = chdir_current;
   data->cntx_name = NULL;
   if (st)
-    assign_string (&data->cntx_name, st->cntx_name);
+    assign_string_or_null (&data->cntx_name, st->cntx_name);
   if (st && st->acls_a_ptr)
     {
       data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
@@ -1329,7 +1329,7 @@ extract_file (char *file_name, int typeflag)
    first. If it doesn't exist, there is no matching entry in the list.
    Otherwise, look for the entry in list which has the matching dev
    and ino numbers.
-   
+
    This approach avoids scanning the singly-linked list in obvious cases
    and does not rely on comparing file names, which may differ for
    various reasons (e.g. relative vs. absolute file names).
@@ -1342,14 +1342,14 @@ find_delayed_link_source (char const *name)
 
   if (!delayed_link_head)
     return NULL;
-  
+
   if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW))
     {
       if (errno != ENOENT)
 	stat_error (name);
       return NULL;
     }
-  
+
   for (dl = delayed_link_head; dl; dl = dl->next)
     {
       if (dl->dev == st.st_dev && dl->ino == st.st_ino)
@@ -1357,7 +1357,7 @@ find_delayed_link_source (char const *name)
     }
   return dl;
 }
-  
+
 /* Create a placeholder file with name FILE_NAME, which will be
    replaced after other extraction is done by a symbolic link if
    IS_SYMLINK is true, and by a hard link otherwise.  Set
@@ -1385,7 +1385,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made,
 	   */
 	  return 0;
 	}
-      
+
       switch (maybe_recoverable (file_name, false, interdir_made))
 	{
 	case RECOVER_OK:
@@ -1442,7 +1442,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made,
       p->sources->next = 0;
       strcpy (p->sources->string, file_name);
       p->cntx_name = NULL;
-      assign_string (&p->cntx_name, current_stat_info.cntx_name);
+      assign_string_or_null (&p->cntx_name, current_stat_info.cntx_name);
       p->acls_a_ptr = NULL;
       p->acls_a_len = 0;
       p->acls_d_ptr = NULL;
@@ -1467,7 +1467,7 @@ extract_link (char *file_name, int typeflag)
   char const *link_name;
   int rc;
   struct delayed_link *dl;
-  
+
   link_name = current_stat_info.link_name;
 
   if (! absolute_names_option && contains_dot_dot (link_name))
@@ -1475,7 +1475,7 @@ extract_link (char *file_name, int typeflag)
   dl = find_delayed_link_source (link_name);
   if (dl)
     return create_placeholder_file (file_name, false, &interdir_made, dl);
-  
+
   do
     {
       struct stat st1, st2;
@@ -1697,7 +1697,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 
     case GNUTYPE_VOLHDR:
       return false;
-      
+
     case GNUTYPE_MULTIVOL:
       ERROR ((0, 0,
 	      _("%s: Cannot extract -- file is continued from another volume"),
@@ -1753,7 +1753,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 	}
     }
   *fun = extractor;
-  
+
   return true;
 }
 

+ 26 - 7
src/misc.c

@@ -42,11 +42,28 @@ quote_n_colon (int n, char const *arg)
 
 /* Assign STRING to a copy of VALUE if not zero, or to zero.  If
    STRING was nonzero, it is freed first.  */
+void
+assign_string_or_null (char **string, const char *value)
+{
+  if (value)
+    assign_string (string, value);
+  else
+    assign_null (string);
+}
+
 void
 assign_string (char **string, const char *value)
 {
   free (*string);
-  *string = value ? xstrdup (value) : 0;
+  *string = xstrdup (value);
+}
+
+void
+assign_null (char **string)
+{
+  char *old = *string;
+  *string = NULL;
+  free (old);
 }
 
 void
@@ -61,6 +78,8 @@ assign_string_n (char **string, const char *value, size_t n)
       p[l] = 0;
       *string = p;
     }
+  else
+    *string = NULL;
 }
 
 #if 0
@@ -715,7 +734,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
      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);
+  assign_null (&after_backup_name);
 
   /* Check if we really need to backup the file.  */
 
@@ -758,7 +777,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
       ERROR ((0, e, _("%s: Cannot rename to %s"),
 	      quotearg_colon (before_backup_name),
 	      quote_n (1, after_backup_name)));
-      assign_string (&after_backup_name, 0);
+      assign_null (&after_backup_name);
       return false;
     }
 }
@@ -782,7 +801,7 @@ undo_last_backup (void)
 	fprintf (stdlis, _("Renaming %s back to %s\n"),
 		 quote_n (0, after_backup_name),
 		 quote_n (1, before_backup_name));
-      assign_string (&after_backup_name, 0);
+      assign_null (&after_backup_name);
     }
 }
 
@@ -1041,11 +1060,11 @@ tar_getcdpath (int idx)
     {
       int i;
       int save_cwdi = chdir_current;
-      
+
       for (i = idx; i >= 0; i--)
 	if (wd[i].abspath)
 	  break;
-      
+
       while (++i <= idx)
 	{
 	  chdir_do (i);
@@ -1069,7 +1088,7 @@ tar_getcdpath (int idx)
 
       chdir_do (save_cwdi);
     }
-	   
+
   return wd[idx].abspath;
 }