/* Buffer management for tar.
- Copyright 1988, 92, 93, 94, 96, 97, 99, 2000 Free Software Foundation, Inc.
+
+ Copyright 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001 Free
+ Software Foundation, Inc.
+
Written by John Gilmore, on 1985-08-25.
This program is free software; you can redistribute it and/or modify it
#include "system.h"
#include <signal.h>
-#include <time.h>
-#ifndef time
-time_t time ();
-#endif
#if MSDOS
# include <process.h>
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 */
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. */
{
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;
}
status = write_archive_buffer ();
if (status != record_size)
- archive_write_error (status);
+ archive_write_error (status);
}
#if 0
waitpid_error (use_compress_program_option);
break;
}
-
+
if (WIFSIGNALED (wait_status))
{
kill (child_pid, WTERMSIG (wait_status));
while (maximum)
{
count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
- status = full_write (STDOUT_FILENO, cursor, count);
- if (status < 0)
+ if (full_write (STDOUT_FILENO, cursor, count) != count)
write_error (use_compress_program_option);
-
- if (status != count)
- {
- ERROR ((0, 0, _("Write to compression program short %lu bytes"),
- (unsigned long) (count - status)));
- count = status;
- }
-
cursor += count;
maximum -= count;
}
waitpid_error (use_compress_program_option);
break;
}
-
+
if (WIFSIGNALED (wait_status))
{
kill (child_pid, WTERMSIG (wait_status));
char *string;
int result;
+ if (! memchr (label->header.name, '\0', sizeof label->header.name))
+ return 0;
+
if (fnmatch (volume_label_option, label->header.name, 0) == 0)
return 1;
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);
archive_write_error (status);
if (status > 0)
- bytes_written += status;
+ {
+ records_written++;
+ bytes_written += status;
+ }
if (status == record_size)
{
}
cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name);
- while (*cursor == '/')
+ while (ISSLASH (*cursor))
cursor++;
assign_string (&real_s_name, cursor);
strcpy (record_start->header.name, real_s_name);
record_start->header.typeflag = GNUTYPE_MULTIVOL;
OFF_TO_CHARS (real_s_sizeleft, record_start->header.size);
- OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
+ OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
record_start->oldgnu_header.offset);
tmp = verbose_option;
verbose_option = 0;
{
char *cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name);
- while (*cursor == '/')
+ while (ISSLASH (*cursor))
cursor++;
assign_string (&real_s_name, cursor);
{
char *cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name);
- while (*cursor == '/')
+ while (ISSLASH (*cursor))
cursor++;
assign_string (&real_s_name, cursor);
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)
char totsizebuf[UINTMAX_STRSIZE_BOUND];
char s1buf[UINTMAX_STRSIZE_BOUND];
char s2buf[UINTMAX_STRSIZE_BOUND];
-
+
WARN ((0, 0, _("%s is the wrong size (%s != %s + %s)"),
quote (cursor->header.name),
STRINGIFY_BIGINT (save_totsize, totsizebuf),
cursor++;
}
current_block = cursor;
+ records_read++;
return;
}
else if (status < 0)
more = record_start->buffer + status;
left = record_size - status;
- while (left % BLOCKSIZE != 0)
+ while (left % BLOCKSIZE != 0
+ || (left && status && read_full_records_option))
{
if (status)
while ((status = rmtread (archive, more, left)) < 0)
if (status == 0)
{
- ERROR ((0, 0, _("%d garbage bytes ignored at end of archive"),
- (int) ((record_size - left) % BLOCKSIZE)));
+ 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;
(unsigned long) ((record_size - left) / BLOCKSIZE)));
record_end = record_start + (record_size - left) / BLOCKSIZE;
+ records_read++;
}
/* 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 (file)
{
- fscanf (file, "%d", &global_volno);
+ if (fscanf (file, "%d", &global_volno) != 1
+ || global_volno < 0)
+ FATAL_ERROR ((0, 0, _("%s: contains invalid volume number"),
+ quotearg_colon (volno_file_option)));
if (ferror (file))
read_error (volno_file_option);
if (fclose (file) != 0)
close_warn (*archive_name_cursor);
global_volno++;
+ if (global_volno < 0)
+ FATAL_ERROR ((0, 0, _("Volume number overflow")));
volno++;
archive_name_cursor++;
if (archive_name_cursor == archive_name_array + archive_names)
{
if (volno_file_option)
closeout_volume_number ();
- system (info_script_option);
+ if (system (info_script_option) != 0)
+ FATAL_ERROR ((0, 0, _("`%s' command failed"), info_script_option));
}
else
while (1)