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 */
+extern off_t records_skipped; /* number of records skipped at the start
+ of the archive, defined in delete.c */
static off_t record_start_block; /* block ordinal at record_start */
static bool hit_eof;
/* Checkpointing counter */
-static int checkpoint;
+static unsigned checkpoint;
static bool read_full_records = false;
set_start_time ()
{
gettime (&start_time);
+ volume_start_time = start_time;
+ last_stat_time = start_time;
+}
+
+void
+set_volume_start_time ()
+{
+ gettime (&volume_start_time);
+ last_stat_time = volume_start_time;
}
void
{
struct timespec now;
gettime (&now);
- duration += ((now.tv_sec - start_time.tv_sec)
- + (now.tv_nsec - start_time.tv_nsec) / 1e9);
- set_start_time ();
+ duration += ((now.tv_sec - last_stat_time.tv_sec)
+ + (now.tv_nsec - last_stat_time.tv_nsec) / 1e9);
+ gettime (&last_stat_time);
}
\f
}
\f
-void
-print_total_written (void)
+static void
+print_stats (FILE *fp, const char *text, tarlong numbytes)
{
- tarlong written = prev_written + bytes_written;
char bytes[sizeof (tarlong) * CHAR_BIT];
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
- sprintf (bytes, TARLONG_FORMAT, written);
+ sprintf (bytes, TARLONG_FORMAT, numbytes);
- /* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
- fprintf (stderr, _("Total bytes written: %s (%s, %s/s)\n"), bytes,
- human_readable (written, abbr, human_opts, 1, 1),
- (0 < duration && written / duration < (uintmax_t) -1
- ? human_readable (written / duration, rate, human_opts, 1, 1)
+ fprintf (fp, "%s: %s (%s, %s/s)\n",
+ text, bytes,
+ human_readable (numbytes, abbr, human_opts, 1, 1),
+ (0 < duration && numbytes / duration < (uintmax_t) -1
+ ? human_readable (numbytes / duration, rate, human_opts, 1, 1)
: "?"));
}
+void
+print_total_stats ()
+{
+ switch (subcommand_option)
+ {
+ case CREATE_SUBCOMMAND:
+ case CAT_SUBCOMMAND:
+ case UPDATE_SUBCOMMAND:
+ case APPEND_SUBCOMMAND:
+ /* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
+ print_stats (stderr, _("Total bytes written"),
+ prev_written + bytes_written);
+ break;
+
+ case DELETE_SUBCOMMAND:
+ {
+ char buf[UINTMAX_STRSIZE_BOUND];
+ print_stats (stderr, _("Total bytes read"),
+ records_read * record_size);
+ print_stats (stderr, _("Total bytes written"),
+ prev_written + bytes_written);
+ fprintf (stderr, _("Total bytes deleted: %s\n"),
+ STRINGIFY_BIGINT ((records_read - records_skipped)
+ * record_size
+ - (prev_written + bytes_written), buf));
+ }
+ break;
+
+ case EXTRACT_SUBCOMMAND:
+ case LIST_SUBCOMMAND:
+ case DIFF_SUBCOMMAND:
+ print_stats (stderr, _("Total bytes read"),
+ records_read * record_size);
+ break;
+
+ default:
+ abort ();
+ }
+}
+
/* Compute and return the block ordinal at current_block. */
off_t
current_block_ordinal (void)
{
int backed_up_flag = 0;
- if (index_file_name)
- {
- 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;
-
if (record_size == 0)
FATAL_ERROR ((0, 0, _("Invalid value for record_size")));
abort (); /* Should not happen */
break;
}
-
- if (wanted_access == ACCESS_WRITE
- && strcmp (archive_name_array[0], "-") == 0)
- stdlis = stderr;
}
else if (strcmp (archive_name_array[0], "-") == 0)
{
case ACCESS_WRITE:
archive = STDOUT_FILENO;
- stdlis = stderr;
break;
case ACCESS_UPDATE:
archive = STDIN_FILENO;
- stdlis = stderr;
write_archive_to_stdout = true;
+ record_end = record_start; /* set up for 1st record = # 0 */
break;
}
}
break;
case ACCESS_UPDATE:
- archive = rmtopen (archive_name_array[0], O_RDWR | O_CREAT | O_BINARY,
+ archive = rmtopen (archive_name_array[0],
+ O_RDWR | O_CREAT | O_BINARY,
MODE_RW, rsh_command_option);
+
+ if (check_compressed_archive () != ct_none)
+ FATAL_ERROR ((0, 0,
+ _("Cannot update compressed archives")));
break;
}
switch (wanted_access)
{
- case ACCESS_UPDATE:
- records_written = 0;
- record_end = record_start; /* set up for 1st record = # 0 */
-
case ACCESS_READ:
find_next_block (); /* read it in, check for EOF */
break;
+ case ACCESS_UPDATE:
case ACCESS_WRITE:
records_written = 0;
break;
}
}
+static void
+do_checkpoint (bool write)
+{
+ if (checkpoint_option && !(++checkpoint % checkpoint_option))
+ {
+ switch (checkpoint_style)
+ {
+ case checkpoint_dot:
+ fputc ('.', stdlis);
+ fflush (stdlis);
+ break;
+
+ case checkpoint_text:
+ if (write)
+ /* TRANSLATORS: This is a ``checkpoint of write operation'',
+ *not* ``Writing a checkpoint''.
+ E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
+ *not* ``Escribiendo un punto de comprobaci@'on'' */
+ WARN ((0, 0, _("Write checkpoint %u"), checkpoint));
+ else
+ /* TRANSLATORS: This is a ``checkpoint of read operation'',
+ *not* ``Reading a checkpoint''.
+ E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
+ *not* ``Leyendo un punto de comprobaci@'on'' */
+ WARN ((0, 0, _("Read checkpoint %u"), checkpoint));
+ break;
+ }
+ }
+}
+
/* Perform a write to flush the buffer. */
ssize_t
_flush_write (void)
{
ssize_t status;
- if (checkpoint_option && !(++checkpoint % 10))
- /* TRANSLATORS: This is a ``checkpoint of write operation'',
- *not* ``Writing a checkpoint''.
- E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
- *not* ``Escribiendo un punto de comprobaci@'on'' */
- WARN ((0, 0, _("Write checkpoint %d"), checkpoint));
-
+ do_checkpoint (true);
if (tape_length_option && tape_length_option <= bytes_written)
{
errno = ENOSPC;
if (totals_option)
{
int e = errno;
- print_total_written ();
+ print_total_stats ();
errno = e;
}
records_read++;
}
-/* Perform a read to flush the buffer. */
-size_t
-_flush_read (void)
-{
- size_t status; /* result from system call */
-
- if (checkpoint_option && !(++checkpoint % 10))
- /* TRANSLATORS: This is a ``checkpoint of read operation'',
- *not* ``Reading a checkpoint''.
- E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
- *not* ``Leyendo un punto de comprobaci@'on'' */
- WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
-
- /* Clear the count of errors. This only applies to a single call to
- flush_read. */
-
- read_error_count = 0; /* clear error count */
-
- if (write_archive_to_stdout && record_start_block != 0)
- {
- archive = STDOUT_FILENO;
- status = sys_write_archive_buffer ();
- archive = STDIN_FILENO;
- if (status != record_size)
- archive_write_error (status);
- }
-
- status = rmtread (archive, record_start->buffer, record_size);
- if (status == record_size)
- records_read++;
- return status;
-}
-
/* Flush the current buffer to/from the archive. */
void
flush_archive (void)
{
char *input_buffer = NULL;
size_t size = 0;
-
- while (1)
+ bool stop = false;
+
+ while (!stop)
{
fputc ('\007', stderr);
fprintf (stderr,
case '?':
{
fprintf (stderr, _("\
- n [name] Give a new file name for the next (and subsequent) volume(s)\n\
+ n name Give a new file name for the next (and subsequent) volume(s)\n\
q Abort tar\n\
y or newline Continue operation\n"));
if (!restrict_option)
;
*cursor = '\0';
- /* FIXME: the following allocation is never reclaimed. */
- *archive_name_cursor = xstrdup (name);
+ if (name[0])
+ {
+ /* FIXME: the following allocation is never reclaimed. */
+ *archive_name_cursor = xstrdup (name);
+ stop = true;
+ }
+ else
+ fprintf (stderr, "%s",
+ _("File name not specified. Try again.\n"));
}
break;
{
size_t status; /* result from system call */
- if (checkpoint_option && !(++checkpoint % 10))
- /* TRANSLATORS: This is a ``checkpoint of read operation'',
- *not* ``Reading a checkpoint''.
- E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
- *not* ``Leyendo un punto de comprobaci@'on'' */
- WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
-
+ do_checkpoint (false);
+
/* Clear the count of errors. This only applies to a single call to
flush_read. */
{
size_t status; /* result from system call */
- if (checkpoint_option && !(++checkpoint % 10))
- /* TRANSLATORS: This is a ``checkpoint of read operation'',
- *not* ``Reading a checkpoint''.
- E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
- *not* ``Leyendo un punto de comprobaci@'on'' */
- WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
-
+ do_checkpoint (false);
+
/* Clear the count of errors. This only applies to a single call to
flush_read. */
xheader_destroy (&extended_header);
increase_volume_number ();
- if (totals_option)
- prev_written += bytes_written;
+ prev_written += bytes_written;
bytes_written = 0;
copy_ptr = record_start->buffer + status;
default:
break;
}
+ set_volume_start_time ();
}