/* Buffer management for tar.
- Copyright 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001 Free
- Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
+ 2003 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
static tarlong prev_written; /* bytes written on previous volumes */
static tarlong bytes_written; /* bytes written on this volume */
-/* FIXME: The following four variables should ideally be static to this
- module. However, this cannot be done yet, as update.c uses the first
- three a lot, and compare.c uses the fourth. The cleanup continues! */
+/* FIXME: The following variables should ideally be static to this
+ module. However, this cannot be done yet. The cleanup continues! */
union block *record_start; /* start of record of archive */
union block *record_end; /* last+1 block of archive record */
union block *current_block; /* current block of archive */
enum access_mode access_mode; /* how do we handle the archive */
+off_t records_read; /* number of records read from this archive */
+off_t records_written; /* likewise, for records written */
+
static struct stat archive_stat; /* stat block for archive file */
static off_t record_start_block; /* block ordinal at record_start */
-/* Where we write list messages (not errors, not interactions) to. Stdout
- unless we're writing a pipe, in which case stderr. */
+/* Where we write list messages (not errors, not interactions) to. */
FILE *stdlis;
-static void backspace_output PARAMS ((void));
-static int new_volume PARAMS ((enum access_mode));
-static void archive_write_error PARAMS ((ssize_t)) __attribute__ ((noreturn));
-static void archive_read_error PARAMS ((void));
+static void backspace_output (void);
+static int new_volume (enum access_mode);
+static void archive_write_error (ssize_t) __attribute__ ((noreturn));
+static void archive_read_error (void);
#if !MSDOS
/* Obnoxious test to see if dimwit is trying to dump the archive. */
off_t save_sizeleft; /* where we are in the file we are writing,
only valid if save_name is nonzero */
-int write_archive_to_stdout;
+bool write_archive_to_stdout;
/* Used by flush_read and flush_write to store the real info about saved
names. */
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
double seconds;
+ int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
#if HAVE_CLOCK_GETTIME
struct timespec now;
sprintf (bytes, TARLONG_FORMAT, written);
/* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
- fprintf (stderr, _("Total bytes written: %s (%sB, %sB/s)\n"), bytes,
- human_readable ((uintmax_t) written, abbr, 1, -1024),
+ fprintf (stderr, _("Total bytes written: %s (%s, %s/s)\n"), bytes,
+ human_readable (written, abbr, human_opts, 1, 1),
(0 < seconds && written / seconds < (uintmax_t) -1
- ? human_readable ((uintmax_t) (written / seconds), rate, 1, -1024)
+ ? human_readable (written / seconds, rate, human_opts, 1, 1)
: "?"));
}
{
written += status;
if (written == record_size
- || _isrmt (archive) || ! S_ISFIFO (archive_stat.st_mode))
+ || _isrmt (archive)
+ || ! (S_ISFIFO (archive_stat.st_mode)
+ || S_ISSOCK (archive_stat.st_mode)))
break;
}
{
size_t size = record_size - length;
- if (size < BLOCKSIZE)
- size = BLOCKSIZE;
status = safe_read (STDIN_FILENO, cursor, size);
if (status <= 0)
break;
{
int backed_up_flag = 0;
- stdlis = to_stdout_option ? stderr : stdout;
+ if (index_file_name)
+ {
+ stdlis = fopen (index_file_name, "w");
+ if (! stdlis)
+ open_error (index_file_name);
+ }
+ else
+ stdlis = to_stdout_option ? stderr : stdout;
if (record_size == 0)
FATAL_ERROR ((0, 0, _("Invalid value for record_size")));
switch (wanted_access)
{
- case ACCESS_READ:
case ACCESS_UPDATE:
+ records_written = 0;
+ case ACCESS_READ:
+ records_read = 0;
record_end = record_start; /* set up for 1st record = # 0 */
find_next_block (); /* read it in, check for EOF */
break;
case ACCESS_WRITE:
+ records_written = 0;
if (volume_label_option)
{
memset (record_start, 0, BLOCKSIZE);
strcpy (record_start->header.name, volume_label_option);
assign_string (¤t_file_name, record_start->header.name);
+ current_trailing_slash = strip_trailing_slashes (current_file_name);
record_start->header.typeflag = GNUTYPE_VOLHDR;
TIME_TO_CHARS (start_time, record_start->header.mtime);
- finish_header (record_start);
+ finish_header (record_start, -1);
#if 0
current_block++;
#endif
archive_write_error (status);
if (status > 0)
- bytes_written += status;
+ {
+ records_written++;
+ bytes_written += status;
+ }
if (status == record_size)
{
if (multi_volume_option)
{
- char *cursor;
-
- if (!save_name)
+ if (save_name)
+ {
+ assign_string (&real_s_name, safer_name_suffix (save_name, 0));
+ real_s_totsize = save_totsize;
+ real_s_sizeleft = save_sizeleft;
+ }
+ else
{
assign_string (&real_s_name, 0);
real_s_totsize = 0;
real_s_sizeleft = 0;
- return;
}
-
- cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name);
- while (ISSLASH (*cursor))
- cursor++;
-
- assign_string (&real_s_name, cursor);
- real_s_totsize = save_totsize;
- real_s_sizeleft = save_sizeleft;
}
return;
}
volume_label_option, volno);
TIME_TO_CHARS (start_time, record_start->header.mtime);
record_start->header.typeflag = GNUTYPE_VOLHDR;
- finish_header (record_start);
+ finish_header (record_start, -1);
}
if (real_s_name)
record_start->oldgnu_header.offset);
tmp = verbose_option;
verbose_option = 0;
- finish_header (record_start);
+ finish_header (record_start, -1);
verbose_option = tmp;
if (volume_label_option)
assign_string (&real_s_name, 0);
else
{
- char *cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name);
-
- while (ISSLASH (*cursor))
- cursor++;
-
- assign_string (&real_s_name, cursor);
+ assign_string (&real_s_name, safer_name_suffix (save_name, 0));
real_s_sizeleft = save_sizeleft;
real_s_totsize = save_totsize;
}
return;
}
+static void
+short_read (ssize_t status)
+{
+ size_t left; /* bytes left */
+ char *more; /* pointer to next byte to read */
+
+ more = record_start->buffer + status;
+ left = record_size - status;
+
+ while (left % BLOCKSIZE != 0
+ || (left && status && read_full_records_option))
+ {
+ if (status)
+ while ((status = rmtread (archive, more, left)) < 0)
+ archive_read_error ();
+
+ if (status == 0)
+ break;
+
+ if (! read_full_records_option)
+ FATAL_ERROR ((0, 0, _("Unaligned block (%lu bytes) in archive"),
+ (unsigned long) (record_size - left)));
+
+ /* User warned us about this. Fix up. */
+
+ left -= status;
+ more += status;
+ }
+
+ /* FIXME: for size=0, multi-volume support. On the first record, warn
+ about the problem. */
+
+ if (!read_full_records_option && verbose_option
+ && record_start_block == 0 && status > 0)
+ WARN ((0, 0, _("Record size = %lu blocks"),
+ (unsigned long) ((record_size - left) / BLOCKSIZE)));
+
+ record_end = record_start + (record_size - left) / BLOCKSIZE;
+ records_read++;
+}
+
/* Perform a read to flush the buffer. */
void
flush_read (void)
{
ssize_t status; /* result from system call */
- size_t left; /* bytes left */
- char *more; /* pointer to next byte to read */
if (checkpoint_option && !(++checkpoint % 10))
WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
{
if (save_name)
{
- char *cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name);
-
- while (ISSLASH (*cursor))
- cursor++;
-
- assign_string (&real_s_name, cursor);
+ assign_string (&real_s_name, safer_name_suffix (save_name, 0));
real_s_sizeleft = save_sizeleft;
real_s_totsize = save_totsize;
}
error_loop:
status = rmtread (archive, record_start->buffer, record_size);
if (status == record_size)
- return;
+ {
+ records_read++;
+ return;
+ }
if ((status == 0
|| (status < 0 && errno == ENOSPC)
goto vol_error;
}
if (status != record_size)
- goto short_read;
+ short_read (status);
cursor = record_start;
cursor++;
}
current_block = cursor;
+ records_read++;
return;
}
else if (status < 0)
goto error_loop; /* try again */
}
- short_read:
- more = record_start->buffer + status;
- left = record_size - status;
-
- while (left % BLOCKSIZE != 0
- || (left && status && read_full_records_option))
- {
- if (status)
- while ((status = rmtread (archive, more, left)) < 0)
- archive_read_error ();
-
- if (status == 0)
- {
- if (left % BLOCKSIZE != 0)
- ERROR ((0, 0, _("%d garbage bytes ignored at end of archive"),
- (int) ((record_size - left) % BLOCKSIZE)));
- break;
- }
-
- if (! read_full_records_option)
- FATAL_ERROR ((0, 0, _("Unaligned block (%lu bytes) in archive"),
- (unsigned long) (record_size - left)));
-
- /* User warned us about this. Fix up. */
-
- left -= status;
- more += status;
- }
-
- /* FIXME: for size=0, multi-volume support. On the first record, warn
- about the problem. */
-
- if (!read_full_records_option && verbose_option
- && record_start_block == 0 && status > 0)
- WARN ((0, 0, _("Record size = %lu blocks"),
- (unsigned long) ((record_size - left) / BLOCKSIZE)));
-
- record_end = record_start + (record_size - left) / BLOCKSIZE;
+ short_read (status);
}
/* Flush the current buffer to/from the archive. */
if (access_mode == ACCESS_READ
&& ! _isrmt (archive)
- && S_ISFIFO (archive_stat.st_mode))
+ && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
while (rmtread (archive, record_start->buffer, record_size) > 0)
continue;
#endif
}
}
- if (verify_option)
+ if (strcmp (archive_name_cursor[0], "-") == 0)
+ {
+ read_full_records_option = true;
+ archive = STDIN_FILENO;
+ }
+ else if (verify_option)
archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,
rsh_command_option);
else
return 1;
}
+