瀏覽代碼

* gnulib.modules: Add closeout, exitfial.
* lib/.cvsignore: Add __fpending.c, __fpending.h, closeout.c,
closeout.h.
* src/buffer.c: Incluse closeout.h.
(_open_archive): Use freopen rather than fopen, so
that stdlis is always either stdout or stderr. Use
close_stdout_set_file_name to report its name.
* src/tar.c: Include closeout.h and exitfail.h.
(parse_opt, usage): Call close_stdout as appropriate, to check for
write errors.
(decode_options): Exit with status TAREXIT_FAILURE, not 1.
(main): Set exit_failure, to exit with proper status on memory
allocation failure and the like.
Use close_stdout rather than rolling our own test.

Paul Eggert 19 年之前
父節點
當前提交
84378fa99a
共有 5 個文件被更改,包括 76 次插入46 次删除
  1. 15 0
      ChangeLog
  2. 2 0
      gnulib.modules
  3. 4 0
      lib/.cvsignore
  4. 40 39
      src/buffer.c
  5. 15 7
      src/tar.c

+ 15 - 0
ChangeLog

@@ -1,5 +1,20 @@
 2006-02-07  Paul Eggert  <eggert@cs.ucla.edu>
 
+	* gnulib.modules: Add closeout, exitfial.
+	* lib/.cvsignore: Add __fpending.c, __fpending.h, closeout.c,
+	closeout.h.
+	* src/buffer.c: Incluse closeout.h.
+	(_open_archive): Use freopen rather than fopen, so
+	that stdlis is always either stdout or stderr.  Use
+	close_stdout_set_file_name to report its name.
+	* src/tar.c: Include closeout.h and exitfail.h.
+	(parse_opt, usage): Call close_stdout as appropriate, to check for
+	write errors.
+	(decode_options): Exit with status TAREXIT_FAILURE, not 1.
+	(main): Set exit_failure, to exit with proper status on memory
+	allocation failure and the like.
+	Use close_stdout rather than rolling our own test.
+
 	* NEWS: --version now outputs copyright etc., to conform to the
 	GNU coding standards.  Remove --license.
 	* gnulib.modules: Add version-etc-fsf.

+ 2 - 0
gnulib.modules

@@ -5,9 +5,11 @@ alloca
 argmatch
 argp
 backupfile
+closeout
 dirname
 error
 exclude
+exitfail
 fileblocks
 fnmatch-gnu
 ftruncate

+ 4 - 0
lib/.cvsignore

@@ -1,4 +1,8 @@
 .deps
+__fpending.c
+__fpending.h
+closeout.c
+closeout.h
 Makefile
 Makefile.am
 Makefile.in

+ 40 - 39
src/buffer.c

@@ -1,7 +1,7 @@
 /* Buffer management for tar.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
@@ -23,6 +23,7 @@
 
 #include <signal.h>
 
+#include <closeout.h>
 #include <fnmatch.h>
 #include <human.h>
 #include <quotearg.h>
@@ -368,7 +369,7 @@ init_buffer ()
 {
   if (!record_buffer[record_index])
     page_aligned_alloc (&record_buffer[record_index], record_size);
-      
+
   record_start = record_buffer[record_index];
   current_block = record_start;
   record_end = record_start + blocking_factor;
@@ -383,9 +384,10 @@ _open_archive (enum access_mode wanted_access)
 
   if (index_file_name)
     {
-      stdlis = fopen (index_file_name, "w");
+      stdlis = freopen (index_file_name, "w", stdout);
       if (! stdlis)
 	open_error (index_file_name);
+      close_stdout_set_file_name (index_file_name);
     }
   else
     stdlis = to_stdout_option ? stderr : stdout;
@@ -402,7 +404,7 @@ _open_archive (enum access_mode wanted_access)
 
   record_index = 0;
   init_buffer ();
-  
+
   /* When updating the archive, we start with reading.  */
   access_mode = wanted_access == ACCESS_UPDATE ? ACCESS_READ : wanted_access;
 
@@ -876,19 +878,19 @@ change_tape_menu (FILE *read_file)
 	       _("Prepare volume #%d for %s and hit return: "),
 	       global_volno + 1, quote (*archive_name_cursor));
       fflush (stderr);
-      
+
       if (getline (&input_buffer, &size, read_file) <= 0)
 	{
 	  WARN ((0, 0, _("EOF where user reply was expected")));
-	  
+
 	  if (subcommand_option != EXTRACT_SUBCOMMAND
 	      && subcommand_option != LIST_SUBCOMMAND
 	      && subcommand_option != DIFF_SUBCOMMAND)
 	    WARN ((0, 0, _("WARNING: Archive is incomplete")));
-	  
+
 	  fatal_exit ();
 	}
-      
+
       if (input_buffer[0] == '\n'
 	  || input_buffer[0] == 'y'
 	  || input_buffer[0] == 'Y')
@@ -910,37 +912,37 @@ change_tape_menu (FILE *read_file)
 
 	case 'q':
 	  /* Quit.  */
-	  
+
 	  WARN ((0, 0, _("No new volume; exiting.\n")));
-	  
+
 	  if (subcommand_option != EXTRACT_SUBCOMMAND
 	      && subcommand_option != LIST_SUBCOMMAND
 	      && subcommand_option != DIFF_SUBCOMMAND)
 	    WARN ((0, 0, _("WARNING: Archive is incomplete")));
-	  
+
 	  fatal_exit ();
-	  
+
 	case 'n':
 	  /* Get new file name.  */
-	  
+
 	  {
 	    char *name;
 	    char *cursor;
-	    
+
 	    for (name = input_buffer + 1;
 		 *name == ' ' || *name == '\t';
 		 name++)
 	      ;
-	    
+
 	    for (cursor = name; *cursor && *cursor != '\n'; cursor++)
 	      ;
 	    *cursor = '\0';
-	    
+
 	    /* FIXME: the following allocation is never reclaimed.  */
 	    *archive_name_cursor = xstrdup (name);
 	  }
 	  break;
-	  
+
 	case '!':
 	  if (!restrict_option)
 	    {
@@ -977,7 +979,7 @@ new_volume (enum access_mode mode)
   assign_string (&volume_label, NULL);
   assign_string (&continued_file_name, NULL);
   continued_file_size = continued_file_offset = 0;
-  
+
   if (rmtclose (archive) != 0)
     close_warn (*archive_name_cursor);
 
@@ -1111,7 +1113,7 @@ try_new_volume ()
 	  }
 	break;
       }
-      
+
     case GNUTYPE_VOLHDR:
       if (!read_header0 ())
 	return false;
@@ -1121,7 +1123,7 @@ try_new_volume ()
       if (header->header.typeflag != GNUTYPE_MULTIVOL)
 	break;
       /* FALL THROUGH */
-      
+
     case GNUTYPE_MULTIVOL:
       if (!read_header0 ())
 	return false;
@@ -1131,7 +1133,7 @@ try_new_volume ()
       continued_file_offset =
 	UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset);
       break;
-      
+
     default:
       break;
     }
@@ -1139,7 +1141,7 @@ try_new_volume ()
   if (real_s_name)
     {
       uintmax_t s;
-      if (!continued_file_name 
+      if (!continued_file_name
 	  || strcmp (continued_file_name, real_s_name))
 	{
 	  WARN ((0, 0, _("%s is not continued on this volume"),
@@ -1162,7 +1164,7 @@ try_new_volume ()
 		 STRINGIFY_BIGINT (continued_file_offset, s2buf)));
 	  return false;
 	}
-      
+
       if (real_s_totsize - real_s_sizeleft != continued_file_offset)
 	{
 	  WARN ((0, 0, _("This volume is out of sequence")));
@@ -1228,7 +1230,7 @@ _write_volume_label (const char *str)
   else
     {
       union block *label = find_next_block ();
-      
+
       memset (label, 0, BLOCKSIZE);
 
       strcpy (label->header.name, volume_label_option);
@@ -1280,7 +1282,7 @@ add_chunk_header ()
 					       real_s_part_no);
       st.file_name = st.orig_file_name;
       st.archive_file_size = st.stat.st_size = real_s_sizeleft;
-      
+
       block_ordinal = current_block_ordinal ();
       blk = start_header (&st);
       free (st.orig_file_name);
@@ -1307,25 +1309,25 @@ gnu_add_multi_volume_header (void)
 {
   int tmp;
   union block *block = find_next_block ();
-  
+
   if (strlen (real_s_name) > NAME_FIELD_SIZE)
     WARN ((0, 0,
 	   _("%s: file name too long to be stored in a GNU multivolume header, truncated"),
 	   quotearg_colon (real_s_name)));
-  
+
   memset (block, 0, BLOCKSIZE);
-  
+
   /* FIXME: Michael P Urban writes: [a long name file] is being written
      when a new volume rolls around [...]  Looks like the wrong value is
      being preserved in real_s_name, though.  */
-  
+
   strncpy (block->header.name, real_s_name, NAME_FIELD_SIZE);
   block->header.typeflag = GNUTYPE_MULTIVOL;
-  
+
   OFF_TO_CHARS (real_s_sizeleft, block->header.size);
   OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
 		block->oldgnu_header.offset);
-  
+
   tmp = verbose_option;
   verbose_option = 0;
   finish_header (&current_stat_info, block, -1);
@@ -1401,7 +1403,7 @@ simple_flush_read (void)
       if (status != record_size)
 	archive_write_error (status);
     }
-  
+
   for (;;)
     {
       status = rmtread (archive, record_start->buffer, record_size);
@@ -1493,7 +1495,7 @@ _gnu_flush_read (void)
       else if (status == SAFE_READ_ERROR)
 	{
 	  archive_read_error ();
-	  continue; 
+	  continue;
 	}
       break;
     }
@@ -1505,7 +1507,7 @@ gnu_flush_read (void)
 {
   flush_read_ptr = simple_flush_read; /* Avoid recursion */
   _gnu_flush_read ();
-  flush_read_ptr = gnu_flush_read; 
+  flush_read_ptr = gnu_flush_read;
 }
 
 static void
@@ -1516,7 +1518,7 @@ _gnu_flush_write (size_t buffer_level)
   char *copy_ptr;
   size_t copy_size;
   size_t bufsize;
-    
+
   status = _flush_write ();
   if (status != record_size && !multi_volume_option)
     archive_write_error (status);
@@ -1552,7 +1554,7 @@ _gnu_flush_write (size_t buffer_level)
   /* Switch to the next buffer */
   record_index = !record_index;
   init_buffer ();
-  
+
   if (volume_label_option)
     add_volume_label ();
 
@@ -1584,7 +1586,7 @@ gnu_flush_write (size_t buffer_level)
 {
   flush_write_ptr = simple_flush_write; /* Avoid recursion */
   _gnu_flush_write (buffer_level);
-  flush_write_ptr = gnu_flush_write; 
+  flush_write_ptr = gnu_flush_write;
 }
 
 void
@@ -1597,7 +1599,7 @@ void
 flush_write ()
 {
   flush_write_ptr (record_size);
-}    
+}
 
 void
 open_archive (enum access_mode wanted_access)
@@ -1623,4 +1625,3 @@ open_archive (enum access_mode wanted_access)
       break;
     }
 }
-

+ 15 - 7
src/tar.c

@@ -37,6 +37,8 @@
 #include "common.h"
 
 #include <argmatch.h>
+#include <closeout.h>
+#include <exitfail.h>
 #include <getdate.h>
 #include <localedir.h>
 #include <rmt.h>
@@ -1441,7 +1443,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
     case SHOW_DEFAULTS_OPTION:
       show_default_settings (stdout);
-      exit(0);
+      close_stdout ();
+      exit (0);
 
     case STRIP_COMPONENTS_OPTION:
       {
@@ -1605,16 +1608,18 @@ parse_opt (int key, char *arg, struct argp_state *state)
       fprintf (state->out_stream, "\n");
       fprintf (state->out_stream, _("Report bugs to %s.\n"),
 	       argp_program_bug_address);
+      close_stdout ();
       exit (0);
 
     case USAGE_OPTION:
-      argp_state_help (state, state->out_stream,
-		       ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
-      break;
+      argp_state_help (state, state->out_stream, ARGP_HELP_USAGE);
+      close_stdout ();
+      exit (0);
 
     case VERSION_OPTION:
       version_etc (state->out_stream, "tar", PACKAGE_NAME, VERSION,
 		   "John Gilmore", "Jay Fenlason", (char *) NULL);
+      close_stdout ();
       exit (0);
 
     case HANG_OPTION:
@@ -1643,6 +1648,7 @@ void
 usage (int status)
 {
   argp_help (&argp, stderr, ARGP_HELP_SEE, (char*) program_name);
+  close_stdout ();
   exit (status);
 }
 
@@ -1753,7 +1759,7 @@ decode_options (int argc, char **argv)
 
   if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
 		  &index, &args))
-    exit (1);
+    exit (TAREXIT_FAILURE);
 
 
   /* Special handling for 'o' option:
@@ -2003,6 +2009,7 @@ main (int argc, char **argv)
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
+  exit_failure = TAREXIT_FAILURE;
   exit_status = TAREXIT_SUCCESS;
   filename_terminator = '\n';
   set_quoting_style (0, DEFAULT_QUOTING_STYLE);
@@ -2089,8 +2096,9 @@ main (int argc, char **argv)
   free (archive_name_array);
   name_term ();
 
-  if (stdlis != stderr && (ferror (stdlis) || fclose (stdlis) != 0))
-    FATAL_ERROR ((0, 0, _("Error in writing to standard output")));
+  if (stdlis == stdout)
+    close_stdout ();
+
   if (exit_status == TAREXIT_FAILURE)
     error (0, 0, _("Error exit delayed from previous errors"));
   if (ferror (stderr) || fclose (stderr) != 0)