|  | @@ -1638,12 +1638,15 @@ restore_parent_fd (struct tar_stat_info const *st)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Dump a single file, recursing on directories.  ST is the file's
 | 
	
		
			
				|  |  |     status info, NAME its name relative to the parent directory, and P
 | 
	
		
			
				|  |  | -   its full name (which may be relative to the working directory).  */
 | 
	
		
			
				|  |  | +   its full name (which may be relative to the working directory).
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   Return the address of dynamically allocated storage that the caller
 | 
	
		
			
				|  |  | +   should free, or the null pointer if there is no such storage.  */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* FIXME: One should make sure that for *every* path leading to setting
 | 
	
		
			
				|  |  |     exit_status to failure, a clear diagnostic has been issued.  */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void
 | 
	
		
			
				|  |  | +static void *
 | 
	
		
			
				|  |  |  dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    union block *header;
 | 
	
	
		
			
				|  | @@ -1657,7 +1660,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |    void (*diag) (char const *) = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (interactive_option && !confirm ("add", p))
 | 
	
		
			
				|  |  | -    return;
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    assign_string (&st->orig_file_name, p);
 | 
	
		
			
				|  |  |    assign_string (&st->file_name,
 | 
	
	
		
			
				|  | @@ -1687,7 +1690,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |    if (diag)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        file_removed_diag (p, top_level, diag);
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return NULL;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    struct stat st1 = st->stat;
 | 
	
	
		
			
				|  | @@ -1696,16 +1699,13 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |    st->mtime = get_stat_mtime (&st->stat);
 | 
	
		
			
				|  |  |    st->ctime = get_stat_ctime (&st->stat);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  void *allocated = NULL;
 | 
	
		
			
				|  |  |  #ifdef S_ISHIDDEN
 | 
	
		
			
				|  |  |    if (S_ISHIDDEN (st->stat.st_mode))
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -      char *new = (char *) alloca (strlen (p) + 2);
 | 
	
		
			
				|  |  | -      if (new)
 | 
	
		
			
				|  |  | -	{
 | 
	
		
			
				|  |  | -	  strcpy (new, p);
 | 
	
		
			
				|  |  | -	  strcat (new, "@");
 | 
	
		
			
				|  |  | -	  p = new;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +      allocated = xmalloc (strlen (p) + 2);
 | 
	
		
			
				|  |  | +      strcpy (stpcpy (allocated, p), "@");
 | 
	
		
			
				|  |  | +      p = allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1724,7 +1724,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |  	WARNOPT (WARN_FILE_UNCHANGED,
 | 
	
		
			
				|  |  |  		 (0, 0, _("%s: file is unchanged; not dumped"),
 | 
	
		
			
				|  |  |  		  quotearg_colon (p)));
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* See if we are trying to dump the archive.  */
 | 
	
	
		
			
				|  | @@ -1733,13 +1733,13 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |        WARNOPT (WARN_IGNORE_ARCHIVE,
 | 
	
		
			
				|  |  |  	       (0, 0, _("%s: archive cannot contain itself; not dumped"),
 | 
	
		
			
				|  |  |  		quotearg_colon (p)));
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    is_dir = S_ISDIR (st->stat.st_mode) != 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (!is_dir && dump_hard_link (st))
 | 
	
		
			
				|  |  | -    return;
 | 
	
		
			
				|  |  | +    return allocated;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (is_dir || S_ISREG (st->stat.st_mode) || S_ISCTG (st->stat.st_mode))
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -1760,7 +1760,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |  	    {
 | 
	
		
			
				|  |  |  	      exclusion_tag_warning (st->orig_file_name, tag_file_name,
 | 
	
		
			
				|  |  |  				     _("directory not dumped"));
 | 
	
		
			
				|  |  | -	      return;
 | 
	
		
			
				|  |  | +	      return allocated;
 | 
	
		
			
				|  |  |  	    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  ok = dump_dir (st);
 | 
	
	
		
			
				|  | @@ -1868,7 +1868,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |        if (ok && remove_files_option)
 | 
	
		
			
				|  |  |  	queue_deferred_unlink (p, is_dir);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  #ifdef HAVE_READLINK
 | 
	
		
			
				|  |  |    else if (S_ISLNK (st->stat.st_mode))
 | 
	
	
		
			
				|  | @@ -1879,7 +1879,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |  	  if (errno == ENOMEM)
 | 
	
		
			
				|  |  |  	    xalloc_die ();
 | 
	
		
			
				|  |  |  	  file_removed_diag (p, top_level, readlink_diag);
 | 
	
		
			
				|  |  | -	  return;
 | 
	
		
			
				|  |  | +	  return allocated;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |        transform_name (&st->link_name, XFORM_SYMLINK);
 | 
	
		
			
				|  |  |        if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
 | 
	
	
		
			
				|  | @@ -1893,7 +1893,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |        st->stat.st_size = 0;	/* force 0 size on symlink */
 | 
	
		
			
				|  |  |        header = start_header (st);
 | 
	
		
			
				|  |  |        if (!header)
 | 
	
		
			
				|  |  | -	return;
 | 
	
		
			
				|  |  | +	return allocated;
 | 
	
		
			
				|  |  |        tar_copy_str (header->header.linkname, st->link_name, NAME_FIELD_SIZE);
 | 
	
		
			
				|  |  |        header->header.typeflag = SYMTYPE;
 | 
	
		
			
				|  |  |        finish_header (st, header, block_ordinal);
 | 
	
	
		
			
				|  | @@ -1903,7 +1903,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |  	queue_deferred_unlink (p, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        file_count_links (st);
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |    else if (S_ISCHR (st->stat.st_mode))
 | 
	
	
		
			
				|  | @@ -1931,35 +1931,36 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        WARNOPT (WARN_FILE_IGNORED,
 | 
	
		
			
				|  |  |  	       (0, 0, _("%s: socket ignored"), quotearg_colon (p)));
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    else if (S_ISDOOR (st->stat.st_mode))
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        WARNOPT (WARN_FILE_IGNORED,
 | 
	
		
			
				|  |  |  	       (0, 0, _("%s: door ignored"), quotearg_colon (p)));
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    else
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        unknown_file_error (p);
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (archive_format == V7_FORMAT)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        unknown_file_error (p);
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | +      return allocated;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    block_ordinal = current_block_ordinal ();
 | 
	
		
			
				|  |  |    st->stat.st_size = 0;	/* force 0 size */
 | 
	
		
			
				|  |  |    header = start_header (st);
 | 
	
		
			
				|  |  |    if (!header)
 | 
	
		
			
				|  |  | -    return;
 | 
	
		
			
				|  |  | +    return allocated;
 | 
	
		
			
				|  |  |    header->header.typeflag = type;
 | 
	
		
			
				|  |  |    finish_header (st, header, block_ordinal);
 | 
	
		
			
				|  |  |    if (remove_files_option)
 | 
	
		
			
				|  |  |      queue_deferred_unlink (p, false);
 | 
	
		
			
				|  |  | +  return allocated;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Dump a file, recursively.  PARENT describes the file's parent
 | 
	
	
		
			
				|  | @@ -1974,7 +1975,7 @@ dump_file (struct tar_stat_info *parent, char const *name,
 | 
	
		
			
				|  |  |    struct tar_stat_info st;
 | 
	
		
			
				|  |  |    tar_stat_init (&st);
 | 
	
		
			
				|  |  |    st.parent = parent;
 | 
	
		
			
				|  |  | -  dump_file0 (&st, name, fullname);
 | 
	
		
			
				|  |  | +  free (dump_file0 (&st, name, fullname));
 | 
	
		
			
				|  |  |    if (parent && listed_incremental_option)
 | 
	
		
			
				|  |  |      update_parent_directory (parent);
 | 
	
		
			
				|  |  |    tar_stat_destroy (&st);
 |