/* 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.
#include <signal.h>
+#include <closeout.h>
#include <fnmatch.h>
#include <human.h>
#include <quotearg.h>
{
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;
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;
record_index = 0;
init_buffer ();
-
+
/* When updating the archive, we start with reading. */
access_mode = wanted_access == ACCESS_UPDATE ? ACCESS_READ : wanted_access;
_("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')
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)
{
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);
}
break;
}
-
+
case GNUTYPE_VOLHDR:
if (!read_header0 ())
return false;
if (header->header.typeflag != GNUTYPE_MULTIVOL)
break;
/* FALL THROUGH */
-
+
case GNUTYPE_MULTIVOL:
if (!read_header0 ())
return false;
continued_file_offset =
UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset);
break;
-
+
default:
break;
}
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"),
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")));
else
{
union block *label = find_next_block ();
-
+
memset (label, 0, BLOCKSIZE);
strcpy (label->header.name, volume_label_option);
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);
{
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);
if (status != record_size)
archive_write_error (status);
}
-
+
for (;;)
{
status = rmtread (archive, record_start->buffer, record_size);
else if (status == SAFE_READ_ERROR)
{
archive_read_error ();
- continue;
+ continue;
}
break;
}
{
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
char *copy_ptr;
size_t copy_size;
size_t bufsize;
-
+
status = _flush_write ();
if (status != record_size && !multi_volume_option)
archive_write_error (status);
/* Switch to the next buffer */
record_index = !record_index;
init_buffer ();
-
+
if (volume_label_option)
add_volume_label ();
{
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
flush_write ()
{
flush_write_ptr (record_size);
-}
+}
void
open_archive (enum access_mode wanted_access)
break;
}
}
-
#include "common.h"
#include <argmatch.h>
+#include <closeout.h>
+#include <exitfail.h>
#include <getdate.h>
#include <localedir.h>
#include <rmt.h>
case SHOW_DEFAULTS_OPTION:
show_default_settings (stdout);
- exit(0);
+ close_stdout ();
+ exit (0);
case STRIP_COMPONENTS_OPTION:
{
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:
usage (int status)
{
argp_help (&argp, stderr, ARGP_HELP_SEE, (char*) program_name);
+ close_stdout ();
exit (status);
}
if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
&index, &args))
- exit (1);
+ exit (TAREXIT_FAILURE);
/* Special handling for 'o' option:
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
+ exit_failure = TAREXIT_FAILURE;
exit_status = TAREXIT_SUCCESS;
filename_terminator = '\n';
set_quoting_style (0, DEFAULT_QUOTING_STYLE);
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)