From 84378fa99ae3ce256fea9eb25d8ae999d1c91fdf Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 7 Feb 2006 23:51:37 +0000 Subject: [PATCH] * 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. --- ChangeLog | 15 ++++++++++ gnulib.modules | 2 ++ lib/.cvsignore | 4 +++ src/buffer.c | 79 +++++++++++++++++++++++++------------------------- src/tar.c | 22 +++++++++----- 5 files changed, 76 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index e353e52..ce1a7d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2006-02-07 Paul Eggert + * 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. diff --git a/gnulib.modules b/gnulib.modules index 3688a08..44b44e2 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -5,9 +5,11 @@ alloca argmatch argp backupfile +closeout dirname error exclude +exitfail fileblocks fnmatch-gnu ftruncate diff --git a/lib/.cvsignore b/lib/.cvsignore index 900e49e..ac25e8d 100644 --- a/lib/.cvsignore +++ b/lib/.cvsignore @@ -1,4 +1,8 @@ .deps +__fpending.c +__fpending.h +closeout.c +closeout.h Makefile Makefile.am Makefile.in diff --git a/src/buffer.c b/src/buffer.c index 9ed8e88..1b36051 100644 --- a/src/buffer.c +++ b/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 +#include #include #include #include @@ -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 (¤t_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; } } - diff --git a/src/tar.c b/src/tar.c index c8eeaa4..7159e24 100644 --- a/src/tar.c +++ b/src/tar.c @@ -37,6 +37,8 @@ #include "common.h" #include +#include +#include #include #include #include @@ -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) -- 2.45.2