Use current_stat_info
This commit is contained in:
12
src/buffer.c
12
src/buffer.c
@@ -669,8 +669,7 @@ open_archive (enum access_mode wanted_access)
|
||||
if (archive_names == 0)
|
||||
FATAL_ERROR ((0, 0, _("No archive name given")));
|
||||
|
||||
current_file_name = 0;
|
||||
current_link_name = 0;
|
||||
destroy_stat (¤t_stat_info);
|
||||
save_name = 0;
|
||||
real_s_name = 0;
|
||||
|
||||
@@ -845,8 +844,8 @@ open_archive (enum access_mode wanted_access)
|
||||
else
|
||||
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);
|
||||
assign_string (¤t_stat_info.file_name, record_start->header.name);
|
||||
current_stat_info.had_trailing_slash = strip_trailing_slashes (current_stat_info.file_name);
|
||||
|
||||
record_start->header.typeflag = GNUTYPE_VOLHDR;
|
||||
TIME_TO_CHARS (start_time, record_start->header.mtime);
|
||||
@@ -1362,10 +1361,7 @@ close_archive (void)
|
||||
}
|
||||
#endif /* !MSDOS */
|
||||
|
||||
if (current_file_name)
|
||||
free (current_file_name);
|
||||
if (current_link_name)
|
||||
free (current_link_name);
|
||||
destroy_stat (¤t_stat_info);
|
||||
if (save_name)
|
||||
free (save_name);
|
||||
if (real_s_name)
|
||||
|
||||
573
src/compare.c
573
src/compare.c
@@ -1,5 +1,8 @@
|
||||
/* Diff files from a tar archive.
|
||||
Copyright (C) 1988, 92, 93, 94, 96, 97 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 1987-04-30.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
@@ -14,14 +17,26 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#if HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#else
|
||||
struct utimbuf
|
||||
{
|
||||
long actime;
|
||||
long modtime;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if HAVE_LINUX_FD_H
|
||||
# include <linux/fd.h>
|
||||
#endif
|
||||
|
||||
#include <quotearg.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "rmt.h"
|
||||
|
||||
@@ -29,105 +44,85 @@
|
||||
#define MESSAGE_BUFFER_SIZE 100
|
||||
|
||||
/* Nonzero if we are verifying at the moment. */
|
||||
int now_verifying = 0;
|
||||
bool now_verifying;
|
||||
|
||||
/* File descriptor for the file we are diffing. */
|
||||
static int diff_handle;
|
||||
|
||||
/* Area for reading file contents into. */
|
||||
static char *diff_buffer = NULL;
|
||||
|
||||
/*--------------------------------.
|
||||
| Initialize for a diff operation |
|
||||
`--------------------------------*/
|
||||
static char *diff_buffer;
|
||||
|
||||
/* Initialize for a diff operation. */
|
||||
void
|
||||
diff_init (void)
|
||||
{
|
||||
diff_buffer = (char *) valloc ((unsigned) record_size);
|
||||
diff_buffer = valloc (record_size);
|
||||
if (!diff_buffer)
|
||||
FATAL_ERROR ((0, 0,
|
||||
_("Could not allocate memory for diff buffer of %d bytes"),
|
||||
record_size));
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------.
|
||||
| Sigh about something that differs by writing a MESSAGE to stdlis, given |
|
||||
| MESSAGE is not NULL. Also set the exit status if not already. |
|
||||
`------------------------------------------------------------------------*/
|
||||
|
||||
/* Sigh about something that differs by writing a MESSAGE to stdlis,
|
||||
given MESSAGE is nonzero. Also set the exit status if not already. */
|
||||
static void
|
||||
report_difference (const char *message)
|
||||
{
|
||||
if (message)
|
||||
fprintf (stdlis, "%s: %s\n", current_file_name, message);
|
||||
fprintf (stdlis, "%s: %s\n", quotearg_colon (current_stat_info.file_name), message);
|
||||
|
||||
if (exit_status == TAREXIT_SUCCESS)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------.
|
||||
| Takes a buffer returned by read_and_process and does nothing with it. |
|
||||
`-----------------------------------------------------------------------*/
|
||||
|
||||
/* Yes, I know. SIZE and DATA are unused in this function. Some compilers
|
||||
may even report it. That's OK, just relax! */
|
||||
|
||||
/* Take a buffer returned by read_and_process and do nothing with it. */
|
||||
static int
|
||||
process_noop (long size, char *data)
|
||||
process_noop (size_t size, char *data)
|
||||
{
|
||||
/* Yes, I know. SIZE and DATA are unused in this function. Some
|
||||
compilers may even report it. That's OK, just relax! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
|
||||
static int
|
||||
process_rawdata (long bytes, char *buffer)
|
||||
process_rawdata (size_t bytes, char *buffer)
|
||||
{
|
||||
int status = read (diff_handle, diff_buffer, (size_t) bytes);
|
||||
ssize_t status = safe_read (diff_handle, diff_buffer, bytes);
|
||||
char message[MESSAGE_BUFFER_SIZE];
|
||||
|
||||
if (status != bytes)
|
||||
{
|
||||
if (status < 0)
|
||||
{
|
||||
WARN ((0, errno, _("Cannot read %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
read_error (current_stat_info.file_name);
|
||||
report_difference (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (message, _("Could only read %d of %ld bytes"),
|
||||
status, bytes);
|
||||
sprintf (message, _("Could only read %lu of %lu bytes"),
|
||||
(unsigned long) status, (unsigned long) bytes);
|
||||
report_difference (message);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp (buffer, diff_buffer, (size_t) bytes))
|
||||
if (memcmp (buffer, diff_buffer, bytes))
|
||||
{
|
||||
report_difference (_("Data differs"));
|
||||
report_difference (_("Contents differ"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
|
||||
/* Directory contents, only for GNUTYPE_DUMPDIR. */
|
||||
|
||||
static char *dumpdir_cursor;
|
||||
|
||||
static int
|
||||
process_dumpdir (long bytes, char *buffer)
|
||||
process_dumpdir (size_t bytes, char *buffer)
|
||||
{
|
||||
if (memcmp (buffer, dumpdir_cursor, (size_t) bytes))
|
||||
if (memcmp (buffer, dumpdir_cursor, bytes))
|
||||
{
|
||||
report_difference (_("Data differs"));
|
||||
report_difference (_("Contents differ"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -135,28 +130,25 @@ process_dumpdir (long bytes, char *buffer)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------.
|
||||
| Some other routine wants SIZE bytes in the archive. For each chunk of |
|
||||
| the archive, call PROCESSOR with the size of the chunk, and the address |
|
||||
| of the chunk it can work with. The PROCESSOR should return nonzero for |
|
||||
| success. It it return error once, continue skipping without calling |
|
||||
| PROCESSOR anymore. |
|
||||
`------------------------------------------------------------------------*/
|
||||
|
||||
/* Some other routine wants SIZE bytes in the archive. For each chunk
|
||||
of the archive, call PROCESSOR with the size of the chunk, and the
|
||||
address of the chunk it can work with. The PROCESSOR should return
|
||||
nonzero for success. It it return error once, continue skipping
|
||||
without calling PROCESSOR anymore. */
|
||||
static void
|
||||
read_and_process (long size, int (*processor) (long, char *))
|
||||
read_and_process (off_t size, int (*processor) (size_t, char *))
|
||||
{
|
||||
union block *data_block;
|
||||
long data_size;
|
||||
size_t data_size;
|
||||
|
||||
if (multi_volume_option)
|
||||
save_sizeleft = size;
|
||||
while (size)
|
||||
{
|
||||
data_block = find_next_block ();
|
||||
if (data_block == NULL)
|
||||
if (! data_block)
|
||||
{
|
||||
ERROR ((0, 0, _("Unexpected EOF on archive file")));
|
||||
ERROR ((0, 0, _("Unexpected EOF in archive")));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -173,98 +165,9 @@ read_and_process (long size, int (*processor) (long, char *))
|
||||
}
|
||||
}
|
||||
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
|
||||
/* JK This routine should be used more often than it is ... look into
|
||||
that. Anyhow, what it does is translate the sparse information on the
|
||||
header, and in any subsequent extended headers, into an array of
|
||||
structures with true numbers, as opposed to character strings. It
|
||||
simply makes our life much easier, doing so many comparisong and such.
|
||||
*/
|
||||
|
||||
static void
|
||||
fill_in_sparse_array (void)
|
||||
{
|
||||
int counter;
|
||||
|
||||
/* Allocate space for our scratch space; it's initially 10 elements
|
||||
long, but can change in this routine if necessary. */
|
||||
|
||||
sp_array_size = 10;
|
||||
sparsearray = (struct sp_array *) xmalloc (sp_array_size * sizeof (struct sp_array));
|
||||
|
||||
/* There are at most five of these structures in the header itself;
|
||||
read these in first. */
|
||||
|
||||
for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
|
||||
{
|
||||
/* Compare to 0, or use !(int)..., for Pyramid's dumb compiler. */
|
||||
if (current_header->oldgnu_header.sp[counter].numbytes == 0)
|
||||
break;
|
||||
|
||||
sparsearray[counter].offset =
|
||||
from_oct (1 + 12, current_header->oldgnu_header.sp[counter].offset);
|
||||
sparsearray[counter].numbytes =
|
||||
from_oct (1 + 12, current_header->oldgnu_header.sp[counter].numbytes);
|
||||
}
|
||||
|
||||
/* If the header's extended, we gotta read in exhdr's till we're done. */
|
||||
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
{
|
||||
/* How far into the sparsearray we are `so far'. */
|
||||
static int so_far_ind = SPARSES_IN_OLDGNU_HEADER;
|
||||
union block *exhdr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
exhdr = find_next_block ();
|
||||
for (counter = 0; counter < SPARSES_IN_SPARSE_HEADER; counter++)
|
||||
{
|
||||
if (counter + so_far_ind > sp_array_size - 1)
|
||||
{
|
||||
/* We just ran out of room in our scratch area -
|
||||
realloc it. */
|
||||
|
||||
sp_array_size *= 2;
|
||||
sparsearray = (struct sp_array *)
|
||||
xrealloc (sparsearray,
|
||||
sp_array_size * sizeof (struct sp_array));
|
||||
}
|
||||
|
||||
/* Convert the character strings into longs. */
|
||||
|
||||
sparsearray[counter + so_far_ind].offset =
|
||||
from_oct (1 + 12, exhdr->sparse_header.sp[counter].offset);
|
||||
sparsearray[counter + so_far_ind].numbytes =
|
||||
from_oct (1 + 12, exhdr->sparse_header.sp[counter].numbytes);
|
||||
}
|
||||
|
||||
/* If this is the last extended header for this file, we can
|
||||
stop. */
|
||||
|
||||
if (!exhdr->sparse_header.isextended)
|
||||
break;
|
||||
|
||||
so_far_ind += SPARSES_IN_SPARSE_HEADER;
|
||||
set_next_block_after (exhdr);
|
||||
}
|
||||
|
||||
/* Be sure to skip past the last one. */
|
||||
|
||||
set_next_block_after (exhdr);
|
||||
}
|
||||
}
|
||||
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
|
||||
/* JK Diff'ing a sparse file with its counterpart on the tar file is a
|
||||
bit of a different story than a normal file. First, we must know what
|
||||
areas of the file to skip through, i.e., we need to contruct a
|
||||
areas of the file to skip through, i.e., we need to construct a
|
||||
sparsearray, which will hold all the information we need. We must
|
||||
compare small amounts of data at a time as we find it. */
|
||||
|
||||
@@ -273,56 +176,68 @@ fill_in_sparse_array (void)
|
||||
I'm not sure overall identical sparsity is verified. */
|
||||
|
||||
static void
|
||||
diff_sparse_files (int size_of_file)
|
||||
diff_sparse_files (void)
|
||||
{
|
||||
int remaining_size = size_of_file;
|
||||
char *buffer = (char *) xmalloc (BLOCKSIZE * sizeof (char));
|
||||
int buffer_size = BLOCKSIZE;
|
||||
union block *data_block = NULL;
|
||||
off_t remaining_size = current_stat_info.stat.st_size;
|
||||
char *buffer = xmalloc (BLOCKSIZE * sizeof (char));
|
||||
size_t buffer_size = BLOCKSIZE;
|
||||
union block *data_block = 0;
|
||||
int counter = 0;
|
||||
int different = 0;
|
||||
|
||||
fill_in_sparse_array ();
|
||||
if (! fill_in_sparse_array ())
|
||||
fatal_exit ();
|
||||
|
||||
while (remaining_size > 0)
|
||||
{
|
||||
int status;
|
||||
long chunk_size;
|
||||
ssize_t status;
|
||||
size_t chunk_size;
|
||||
off_t offset;
|
||||
|
||||
#if 0
|
||||
int amount_read = 0;
|
||||
off_t amount_read = 0;
|
||||
#endif
|
||||
|
||||
data_block = find_next_block ();
|
||||
if (!data_block)
|
||||
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
|
||||
chunk_size = sparsearray[counter].numbytes;
|
||||
if (!chunk_size)
|
||||
break;
|
||||
|
||||
lseek (diff_handle, sparsearray[counter].offset, 0);
|
||||
offset = sparsearray[counter].offset;
|
||||
if (lseek (diff_handle, offset, SEEK_SET) < 0)
|
||||
{
|
||||
seek_error_details (current_stat_info.file_name, offset);
|
||||
report_difference (0);
|
||||
}
|
||||
|
||||
/* Take care to not run out of room in our buffer. */
|
||||
|
||||
while (buffer_size < chunk_size)
|
||||
{
|
||||
if (buffer_size * 2 < buffer_size)
|
||||
xalloc_die ();
|
||||
buffer_size *= 2;
|
||||
buffer = (char *) xrealloc (buffer, buffer_size * sizeof (char));
|
||||
buffer = xrealloc (buffer, buffer_size * sizeof (char));
|
||||
}
|
||||
|
||||
while (chunk_size > BLOCKSIZE)
|
||||
{
|
||||
if (status = read (diff_handle, buffer, BLOCKSIZE),
|
||||
if (status = safe_read (diff_handle, buffer, BLOCKSIZE),
|
||||
status != BLOCKSIZE)
|
||||
{
|
||||
if (status < 0)
|
||||
{
|
||||
WARN ((0, errno, _("Cannot read %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
read_error (current_stat_info.file_name);
|
||||
report_difference (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
char message[MESSAGE_BUFFER_SIZE];
|
||||
|
||||
sprintf (message, _("Could only read %d of %ld bytes"),
|
||||
status, chunk_size);
|
||||
sprintf (message, _("Could only read %lu of %lu bytes"),
|
||||
(unsigned long) status, (unsigned long) chunk_size);
|
||||
report_difference (message);
|
||||
}
|
||||
break;
|
||||
@@ -338,27 +253,29 @@ diff_sparse_files (int size_of_file)
|
||||
remaining_size -= status;
|
||||
set_next_block_after (data_block);
|
||||
data_block = find_next_block ();
|
||||
if (!data_block)
|
||||
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
|
||||
}
|
||||
if (status = read (diff_handle, buffer, (size_t) chunk_size),
|
||||
if (status = safe_read (diff_handle, buffer, chunk_size),
|
||||
status != chunk_size)
|
||||
{
|
||||
if (status < 0)
|
||||
{
|
||||
WARN ((0, errno, _("Cannot read %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
read_error (current_stat_info.file_name);
|
||||
report_difference (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
char message[MESSAGE_BUFFER_SIZE];
|
||||
|
||||
sprintf (message, _("Could only read %d of %ld bytes"),
|
||||
status, chunk_size);
|
||||
sprintf (message, _("Could only read %lu of %lu bytes"),
|
||||
(unsigned long) status, (unsigned long) chunk_size);
|
||||
report_difference (message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp (buffer, data_block->buffer, (size_t) chunk_size))
|
||||
if (memcmp (buffer, data_block->buffer, chunk_size))
|
||||
{
|
||||
different = 1;
|
||||
break;
|
||||
@@ -370,6 +287,8 @@ diff_sparse_files (int size_of_file)
|
||||
amount_read = 0;
|
||||
set_next_block_after (data_block);
|
||||
data_block = find_next_block ();
|
||||
if (!data_block)
|
||||
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
|
||||
}
|
||||
#endif
|
||||
set_next_block_after (data_block);
|
||||
@@ -381,7 +300,7 @@ diff_sparse_files (int size_of_file)
|
||||
/* If the number of bytes read isn't the number of bytes supposedly in
|
||||
the file, they're different. */
|
||||
|
||||
if (amount_read != size_of_file)
|
||||
if (amount_read != current_stat_info.stat.st_size)
|
||||
different = 1;
|
||||
#endif
|
||||
|
||||
@@ -389,71 +308,56 @@ diff_sparse_files (int size_of_file)
|
||||
free (sparsearray);
|
||||
|
||||
if (different)
|
||||
report_difference (_("Data differs"));
|
||||
report_difference (_("Contents differ"));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------.
|
||||
| Call either stat or lstat over STAT_DATA, depending on --dereference |
|
||||
| (-h), for a file which should exist. Diagnose any problem. Return |
|
||||
| nonzero for success, zero otherwise. |
|
||||
`---------------------------------------------------------------------*/
|
||||
|
||||
/* Call either stat or lstat over STAT_DATA, depending on
|
||||
--dereference (-h), for a file which should exist. Diagnose any
|
||||
problem. Return nonzero for success, zero otherwise. */
|
||||
static int
|
||||
get_stat_data (struct stat *stat_data)
|
||||
get_stat_data (char const *file_name, struct stat *stat_data)
|
||||
{
|
||||
int status = (dereference_option
|
||||
? stat (current_file_name, stat_data)
|
||||
: lstat (current_file_name, stat_data));
|
||||
int status = deref_stat (dereference_option, file_name, stat_data);
|
||||
|
||||
if (status < 0)
|
||||
if (status != 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
report_difference (_("File does not exist"));
|
||||
stat_warn (file_name);
|
||||
else
|
||||
{
|
||||
ERROR ((0, errno, _("Cannot stat file %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
}
|
||||
#if 0
|
||||
skip_file ((long) current_stat.st_size);
|
||||
#endif
|
||||
stat_error (file_name);
|
||||
report_difference (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------.
|
||||
| Diff a file against the archive. |
|
||||
`----------------------------------*/
|
||||
|
||||
/* Diff a file against the archive. */
|
||||
void
|
||||
diff_archive (void)
|
||||
{
|
||||
struct stat stat_data;
|
||||
int name_length;
|
||||
int status;
|
||||
|
||||
errno = EPIPE; /* FIXME: errno should be read-only */
|
||||
/* FIXME: remove perrors */
|
||||
struct utimbuf restore_times;
|
||||
|
||||
set_next_block_after (current_header);
|
||||
decode_header (current_header, ¤t_stat, ¤t_format, 1);
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
||||
|
||||
/* Print the block from `current_header' and `current_stat'. */
|
||||
/* Print the block from current_header and current_stat_info. */
|
||||
|
||||
if (verbose_option)
|
||||
{
|
||||
if (now_verifying)
|
||||
fprintf (stdlis, _("Verify "));
|
||||
print_header ();
|
||||
print_header (-1);
|
||||
}
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
{
|
||||
default:
|
||||
WARN ((0, 0, _("Unknown file type '%c' for %s, diffed as normal file"),
|
||||
current_header->header.typeflag, current_file_name));
|
||||
ERROR ((0, 0, _("%s: Unknown file type '%c', diffed as normal file"),
|
||||
quotearg_colon (current_stat_info.file_name),
|
||||
current_header->header.typeflag));
|
||||
/* Fall through. */
|
||||
|
||||
case AREGTYPE:
|
||||
@@ -463,92 +367,83 @@ diff_archive (void)
|
||||
|
||||
/* Appears to be a file. See if it's really a directory. */
|
||||
|
||||
name_length = strlen (current_file_name) - 1;
|
||||
if (current_file_name[name_length] == '/')
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
goto really_dir;
|
||||
|
||||
if (!get_stat_data (&stat_data))
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
{
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) current_stat.st_size);
|
||||
skip_member ();
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (!S_ISREG (stat_data.st_mode))
|
||||
{
|
||||
report_difference (_("Not a regular file"));
|
||||
skip_file ((long) current_stat.st_size);
|
||||
report_difference (_("File type differs"));
|
||||
skip_member ();
|
||||
goto quit;
|
||||
}
|
||||
|
||||
stat_data.st_mode &= 07777;
|
||||
if (stat_data.st_mode != current_stat.st_mode)
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
|
||||
report_difference (_("Mode differs"));
|
||||
|
||||
#if !MSDOS
|
||||
/* stat() in djgpp's C library gives a constant number of 42 as the
|
||||
uid and gid of a file. So, comparing an FTP'ed archive just after
|
||||
unpack would fail on MSDOS. */
|
||||
if (stat_data.st_uid != current_stat.st_uid)
|
||||
if (stat_data.st_uid != current_stat_info.stat.st_uid)
|
||||
report_difference (_("Uid differs"));
|
||||
if (stat_data.st_gid != current_stat.st_gid)
|
||||
if (stat_data.st_gid != current_stat_info.stat.st_gid)
|
||||
report_difference (_("Gid differs"));
|
||||
#endif
|
||||
|
||||
if (stat_data.st_mtime != current_stat.st_mtime)
|
||||
if (stat_data.st_mtime != current_stat_info.stat.st_mtime)
|
||||
report_difference (_("Mod time differs"));
|
||||
if (current_header->header.typeflag != GNUTYPE_SPARSE &&
|
||||
stat_data.st_size != current_stat.st_size)
|
||||
stat_data.st_size != current_stat_info.stat.st_size)
|
||||
{
|
||||
report_difference (_("Size differs"));
|
||||
skip_file ((long) current_stat.st_size);
|
||||
skip_member ();
|
||||
goto quit;
|
||||
}
|
||||
|
||||
diff_handle = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
|
||||
diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_handle < 0 && !absolute_names_option)
|
||||
{
|
||||
char *tmpbuf = xmalloc (strlen (current_file_name) + 2);
|
||||
|
||||
*tmpbuf = '/';
|
||||
strcpy (tmpbuf + 1, current_file_name);
|
||||
diff_handle = open (tmpbuf, O_NDELAY | O_RDONLY);
|
||||
free (tmpbuf);
|
||||
}
|
||||
if (diff_handle < 0)
|
||||
{
|
||||
ERROR ((0, errno, _("Cannot open %s"), current_file_name));
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) current_stat.st_size);
|
||||
report_difference (NULL);
|
||||
open_error (current_stat_info.file_name);
|
||||
skip_member ();
|
||||
report_difference (0);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
restore_times.actime = stat_data.st_atime;
|
||||
restore_times.modtime = stat_data.st_mtime;
|
||||
|
||||
/* Need to treat sparse files completely differently here. */
|
||||
|
||||
if (current_header->header.typeflag == GNUTYPE_SPARSE)
|
||||
diff_sparse_files (current_stat.st_size);
|
||||
diff_sparse_files ();
|
||||
else
|
||||
{
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_file_name);
|
||||
save_totsize = current_stat.st_size;
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = current_stat_info.stat.st_size;
|
||||
/* save_sizeleft is set in read_and_process. */
|
||||
}
|
||||
|
||||
read_and_process ((long) (current_stat.st_size), process_rawdata);
|
||||
read_and_process (current_stat_info.stat.st_size, process_rawdata);
|
||||
|
||||
if (multi_volume_option)
|
||||
assign_string (&save_name, NULL);
|
||||
assign_string (&save_name, 0);
|
||||
}
|
||||
|
||||
status = close (diff_handle);
|
||||
if (status < 0)
|
||||
ERROR ((0, errno, _("Error while closing %s"), current_file_name));
|
||||
if (status != 0)
|
||||
close_error (current_stat_info.file_name);
|
||||
|
||||
if (atime_preserve_option)
|
||||
utime (current_stat_info.file_name, &restore_times);
|
||||
|
||||
quit:
|
||||
break;
|
||||
@@ -556,33 +451,21 @@ diff_archive (void)
|
||||
#if !MSDOS
|
||||
case LNKTYPE:
|
||||
{
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
struct stat link_data;
|
||||
|
||||
if (!get_stat_data (&stat_data))
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
if (!get_stat_data (current_stat_info.link_name, &link_data))
|
||||
break;
|
||||
|
||||
dev = stat_data.st_dev;
|
||||
ino = stat_data.st_ino;
|
||||
status = stat (current_link_name, &stat_data);
|
||||
if (status < 0)
|
||||
if (stat_data.st_dev != link_data.st_dev
|
||||
|| stat_data.st_ino != link_data.st_ino)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
report_difference (_("Does not exist"));
|
||||
else
|
||||
{
|
||||
WARN ((0, errno, _("Cannot stat file %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
char *message =
|
||||
xmalloc (MESSAGE_BUFFER_SIZE + 4 * strlen (current_stat_info.link_name));
|
||||
|
||||
if (stat_data.st_dev != dev || stat_data.st_ino != ino)
|
||||
{
|
||||
char *message = (char *)
|
||||
xmalloc (MESSAGE_BUFFER_SIZE + strlen (current_link_name));
|
||||
|
||||
sprintf (message, _("Not linked to %s"), current_link_name);
|
||||
sprintf (message, _("Not linked to %s"),
|
||||
quote (current_stat_info.link_name));
|
||||
report_difference (message);
|
||||
free (message);
|
||||
break;
|
||||
@@ -592,80 +475,61 @@ diff_archive (void)
|
||||
}
|
||||
#endif /* not MSDOS */
|
||||
|
||||
#ifdef S_ISLNK
|
||||
#ifdef HAVE_READLINK
|
||||
case SYMTYPE:
|
||||
{
|
||||
char linkbuf[NAME_FIELD_SIZE + 3]; /* FIXME: may be too short. */
|
||||
size_t len = strlen (current_stat_info.link_name);
|
||||
char *linkbuf = alloca (len + 1);
|
||||
|
||||
status = readlink (current_file_name, linkbuf, (sizeof linkbuf) - 1);
|
||||
status = readlink (current_stat_info.file_name, linkbuf, len + 1);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
report_difference (_("No such file or directory"));
|
||||
readlink_warn (current_stat_info.file_name);
|
||||
else
|
||||
{
|
||||
WARN ((0, errno, _("Cannot read link %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
}
|
||||
break;
|
||||
readlink_error (current_stat_info.file_name);
|
||||
report_difference (0);
|
||||
}
|
||||
|
||||
linkbuf[status] = '\0'; /* null-terminate it */
|
||||
if (strncmp (current_link_name, linkbuf, (size_t) status) != 0)
|
||||
else if (status != len
|
||||
|| strncmp (current_stat_info.link_name, linkbuf, len) != 0)
|
||||
report_difference (_("Symlink differs"));
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* not S_ISLNK */
|
||||
#endif
|
||||
|
||||
#ifdef S_IFCHR
|
||||
case CHRTYPE:
|
||||
current_stat.st_mode |= S_IFCHR;
|
||||
goto check_node;
|
||||
#endif /* not S_IFCHR */
|
||||
|
||||
#ifdef S_IFBLK
|
||||
/* If local system doesn't support block devices, use default case. */
|
||||
|
||||
case BLKTYPE:
|
||||
current_stat.st_mode |= S_IFBLK;
|
||||
goto check_node;
|
||||
#endif /* not S_IFBLK */
|
||||
|
||||
#ifdef S_ISFIFO
|
||||
/* If local system doesn't support FIFOs, use default case. */
|
||||
|
||||
case FIFOTYPE:
|
||||
# ifdef S_IFIFO
|
||||
current_stat.st_mode |= S_IFIFO;
|
||||
# endif
|
||||
current_stat.st_rdev = 0; /* FIXME: do we need this? */
|
||||
goto check_node;
|
||||
#endif /* S_ISFIFO */
|
||||
|
||||
check_node:
|
||||
/* FIXME: deal with umask. */
|
||||
|
||||
if (!get_stat_data (&stat_data))
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
|
||||
if (current_stat.st_rdev != stat_data.st_rdev)
|
||||
if (current_header->header.typeflag == CHRTYPE
|
||||
? !S_ISCHR (stat_data.st_mode)
|
||||
: current_header->header.typeflag == BLKTYPE
|
||||
? !S_ISBLK (stat_data.st_mode)
|
||||
: /* current_header->header.typeflag == FIFOTYPE */
|
||||
!S_ISFIFO (stat_data.st_mode))
|
||||
{
|
||||
report_difference (_("Device numbers changed"));
|
||||
report_difference (_("File type differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
#ifdef S_IFMT
|
||||
current_stat.st_mode != stat_data.st_mode
|
||||
#else
|
||||
/* POSIX lossage. */
|
||||
(current_stat.st_mode & 07777) != (stat_data.st_mode & 07777)
|
||||
#endif
|
||||
)
|
||||
if ((current_header->header.typeflag == CHRTYPE
|
||||
|| current_header->header.typeflag == BLKTYPE)
|
||||
&& current_stat_info.stat.st_rdev != stat_data.st_rdev)
|
||||
{
|
||||
report_difference (_("Mode or device-type changed"));
|
||||
report_difference (_("Device number differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
|
||||
{
|
||||
report_difference (_("Mode differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -673,49 +537,46 @@ diff_archive (void)
|
||||
|
||||
case GNUTYPE_DUMPDIR:
|
||||
{
|
||||
char *dumpdir_buffer = get_directory_contents (current_file_name, 0);
|
||||
char *dumpdir_buffer = get_directory_contents (current_stat_info.file_name, 0);
|
||||
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_file_name);
|
||||
save_totsize = current_stat.st_size;
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = current_stat_info.stat.st_size;
|
||||
/* save_sizeleft is set in read_and_process. */
|
||||
}
|
||||
|
||||
if (dumpdir_buffer)
|
||||
{
|
||||
dumpdir_cursor = dumpdir_buffer;
|
||||
read_and_process ((long) (current_stat.st_size), process_dumpdir);
|
||||
read_and_process (current_stat_info.stat.st_size, process_dumpdir);
|
||||
free (dumpdir_buffer);
|
||||
}
|
||||
else
|
||||
read_and_process ((long) (current_stat.st_size), process_noop);
|
||||
read_and_process (current_stat_info.stat.st_size, process_noop);
|
||||
|
||||
if (multi_volume_option)
|
||||
assign_string (&save_name, NULL);
|
||||
assign_string (&save_name, 0);
|
||||
/* Fall through. */
|
||||
}
|
||||
|
||||
case DIRTYPE:
|
||||
/* Check for trailing /. */
|
||||
|
||||
name_length = strlen (current_file_name) - 1;
|
||||
|
||||
really_dir:
|
||||
while (name_length && current_file_name[name_length] == '/')
|
||||
current_file_name[name_length--] = '\0'; /* zap / */
|
||||
|
||||
if (!get_stat_data (&stat_data))
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
|
||||
if (!S_ISDIR (stat_data.st_mode))
|
||||
{
|
||||
report_difference (_("No longer a directory"));
|
||||
report_difference (_("File type differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
|
||||
{
|
||||
report_difference (_("Mode differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((stat_data.st_mode & 07777) != (current_stat.st_mode & 07777))
|
||||
report_difference (_("Mode differs"));
|
||||
break;
|
||||
|
||||
case GNUTYPE_VOLHDR:
|
||||
@@ -725,73 +586,65 @@ diff_archive (void)
|
||||
{
|
||||
off_t offset;
|
||||
|
||||
name_length = strlen (current_file_name) - 1;
|
||||
if (current_file_name[name_length] == '/')
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
goto really_dir;
|
||||
|
||||
if (!get_stat_data (&stat_data))
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
|
||||
if (!S_ISREG (stat_data.st_mode))
|
||||
{
|
||||
report_difference (_("Not a regular file"));
|
||||
skip_file ((long) current_stat.st_size);
|
||||
report_difference (_("File type differs"));
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
stat_data.st_mode &= 07777;
|
||||
offset = from_oct (1 + 12, current_header->oldgnu_header.offset);
|
||||
if (stat_data.st_size != current_stat.st_size + offset)
|
||||
offset = OFF_FROM_HEADER (current_header->oldgnu_header.offset);
|
||||
if (stat_data.st_size != current_stat_info.stat.st_size + offset)
|
||||
{
|
||||
report_difference (_("Size differs"));
|
||||
skip_file ((long) current_stat.st_size);
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
diff_handle = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
|
||||
diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_handle < 0)
|
||||
{
|
||||
WARN ((0, errno, _("Cannot open file %s"), current_file_name));
|
||||
report_difference (NULL);
|
||||
skip_file ((long) current_stat.st_size);
|
||||
open_error (current_stat_info.file_name);
|
||||
report_difference (0);
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
status = lseek (diff_handle, offset, 0);
|
||||
if (status != offset)
|
||||
if (lseek (diff_handle, offset, SEEK_SET) < 0)
|
||||
{
|
||||
WARN ((0, errno, _("Cannot seek to %ld in file %s"),
|
||||
offset, current_file_name));
|
||||
report_difference (NULL);
|
||||
seek_error_details (current_stat_info.file_name, offset);
|
||||
report_difference (0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_file_name);
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = stat_data.st_size;
|
||||
/* save_sizeleft is set in read_and_process. */
|
||||
}
|
||||
|
||||
read_and_process ((long) (current_stat.st_size), process_rawdata);
|
||||
read_and_process (current_stat_info.stat.st_size, process_rawdata);
|
||||
|
||||
if (multi_volume_option)
|
||||
assign_string (&save_name, NULL);
|
||||
assign_string (&save_name, 0);
|
||||
|
||||
status = close (diff_handle);
|
||||
if (status < 0)
|
||||
ERROR ((0, errno, _("Error while closing %s"), current_file_name));
|
||||
if (status != 0)
|
||||
close_error (current_stat_info.file_name);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
|
||||
void
|
||||
verify_volume (void)
|
||||
{
|
||||
@@ -829,12 +682,10 @@ verify_volume (void)
|
||||
status < 0))
|
||||
{
|
||||
#endif
|
||||
if (rmtlseek (archive, 0L, 0) != 0)
|
||||
if (rmtlseek (archive, (off_t) 0, SEEK_SET) != 0)
|
||||
{
|
||||
/* Lseek failed. Try a different method. */
|
||||
|
||||
WARN ((0, errno,
|
||||
_("Could not rewind archive file for verify")));
|
||||
seek_warn (archive_name_array[0]);
|
||||
return;
|
||||
}
|
||||
#ifdef MTIOCTOP
|
||||
@@ -849,17 +700,19 @@ verify_volume (void)
|
||||
flush_read ();
|
||||
while (1)
|
||||
{
|
||||
enum read_header status = read_header ();
|
||||
enum read_header status = read_header (0);
|
||||
|
||||
if (status == HEADER_FAILURE)
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
while (status == HEADER_FAILURE);
|
||||
do
|
||||
{
|
||||
counter++;
|
||||
status = read_header ();
|
||||
status = read_header (0);
|
||||
}
|
||||
while (status == HEADER_FAILURE);
|
||||
|
||||
ERROR ((0, 0,
|
||||
_("VERIFY FAILURE: %d invalid header(s) detected"), counter));
|
||||
}
|
||||
|
||||
154
src/create.c
154
src/create.c
@@ -359,7 +359,7 @@ write_eot (void)
|
||||
|
||||
/* FIXME: Cross recursion between start_header and write_long! */
|
||||
|
||||
static union block *start_header (const char *, struct stat *);
|
||||
static union block *start_header (const char *, struct tar_stat_info *);
|
||||
|
||||
static void
|
||||
write_long (const char *p, char type)
|
||||
@@ -367,10 +367,10 @@ write_long (const char *p, char type)
|
||||
size_t size = strlen (p) + 1;
|
||||
size_t bufsize;
|
||||
union block *header;
|
||||
struct stat foo;
|
||||
struct tar_stat_info foo;
|
||||
|
||||
memset (&foo, 0, sizeof foo);
|
||||
foo.st_size = size;
|
||||
foo.stat.st_size = size;
|
||||
|
||||
header = start_header ("././@LongLink", &foo);
|
||||
header->header.typeflag = type;
|
||||
@@ -400,7 +400,7 @@ write_long (const char *p, char type)
|
||||
and return its address. */
|
||||
|
||||
static union block *
|
||||
start_header (const char *name, struct stat *st)
|
||||
start_header (const char *name, struct tar_stat_info *st)
|
||||
{
|
||||
union block *header;
|
||||
|
||||
@@ -411,7 +411,7 @@ start_header (const char *name, struct stat *st)
|
||||
header = find_next_block ();
|
||||
memset (header->buffer, 0, sizeof (union block));
|
||||
|
||||
assign_string (¤t_file_name, name);
|
||||
assign_string (¤t_stat_info.file_name, name);
|
||||
|
||||
strncpy (header->header.name, name, NAME_FIELD_SIZE);
|
||||
header->header.name[NAME_FIELD_SIZE - 1] = '\0';
|
||||
@@ -419,12 +419,12 @@ start_header (const char *name, struct stat *st)
|
||||
/* Override some stat fields, if requested to do so. */
|
||||
|
||||
if (owner_option != (uid_t) -1)
|
||||
st->st_uid = owner_option;
|
||||
st->stat.st_uid = owner_option;
|
||||
if (group_option != (gid_t) -1)
|
||||
st->st_gid = group_option;
|
||||
st->stat.st_gid = group_option;
|
||||
if (mode_option)
|
||||
st->st_mode = ((st->st_mode & ~MODE_ALL)
|
||||
| mode_adjust (st->st_mode, mode_option));
|
||||
st->stat.st_mode = ((st->stat.st_mode & ~MODE_ALL)
|
||||
| mode_adjust (st->stat.st_mode, mode_option));
|
||||
|
||||
/* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
|
||||
for a few tars and came up with the following interoperability
|
||||
@@ -450,22 +450,22 @@ start_header (const char *name, struct stat *st)
|
||||
acceptor for Paul's test. */
|
||||
|
||||
if (archive_format == V7_FORMAT)
|
||||
MODE_TO_CHARS (st->st_mode & MODE_ALL, header->header.mode);
|
||||
MODE_TO_CHARS (st->stat.st_mode & MODE_ALL, header->header.mode);
|
||||
else
|
||||
MODE_TO_CHARS (st->st_mode, header->header.mode);
|
||||
MODE_TO_CHARS (st->stat.st_mode, header->header.mode);
|
||||
|
||||
UID_TO_CHARS (st->st_uid, header->header.uid);
|
||||
GID_TO_CHARS (st->st_gid, header->header.gid);
|
||||
OFF_TO_CHARS (st->st_size, header->header.size);
|
||||
TIME_TO_CHARS (st->st_mtime, header->header.mtime);
|
||||
UID_TO_CHARS (st->stat.st_uid, header->header.uid);
|
||||
GID_TO_CHARS (st->stat.st_gid, header->header.gid);
|
||||
OFF_TO_CHARS (st->stat.st_size, header->header.size);
|
||||
TIME_TO_CHARS (st->stat.st_mtime, header->header.mtime);
|
||||
MAJOR_TO_CHARS (0, header->header.devmajor);
|
||||
MINOR_TO_CHARS (0, header->header.devminor);
|
||||
|
||||
if (incremental_option)
|
||||
if (archive_format == OLDGNU_FORMAT)
|
||||
{
|
||||
TIME_TO_CHARS (st->st_atime, header->oldgnu_header.atime);
|
||||
TIME_TO_CHARS (st->st_ctime, header->oldgnu_header.ctime);
|
||||
TIME_TO_CHARS (st->stat.st_atime, header->oldgnu_header.atime);
|
||||
TIME_TO_CHARS (st->stat.st_ctime, header->oldgnu_header.ctime);
|
||||
}
|
||||
|
||||
header->header.typeflag = archive_format == V7_FORMAT ? AREGTYPE : REGTYPE;
|
||||
@@ -496,8 +496,8 @@ start_header (const char *name, struct stat *st)
|
||||
}
|
||||
else
|
||||
{
|
||||
uid_to_uname (st->st_uid, header->header.uname);
|
||||
gid_to_gname (st->st_gid, header->header.gname);
|
||||
uid_to_uname (st->stat.st_uid, header->header.uname);
|
||||
gid_to_gname (st->stat.st_gid, header->header.gname);
|
||||
}
|
||||
|
||||
return header;
|
||||
@@ -541,7 +541,7 @@ finish_header (union block *header, off_t block_ordinal)
|
||||
/* These globals are parameters to print_header, sigh. */
|
||||
|
||||
current_header = header;
|
||||
/* current_stat is already set up. */
|
||||
/* current_stat_info is already set up. */
|
||||
current_format = archive_format;
|
||||
print_header (block_ordinal);
|
||||
}
|
||||
@@ -859,7 +859,7 @@ static Hash_table *link_table;
|
||||
of an incremental dump. PARENT_DEVICE is the device of P's
|
||||
parent directory; it is examined only if TOP_LEVEL is zero.
|
||||
|
||||
Set global CURRENT_STAT to stat output for this file. */
|
||||
Set global CURRENT_STAT_INFO to stat output for this file. */
|
||||
|
||||
/* FIXME: One should make sure that for *every* path leading to setting
|
||||
exit_status to failure, a clear diagnostic has been issued. */
|
||||
@@ -881,7 +881,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
if (interactive_option && !confirm ("add", p))
|
||||
return;
|
||||
|
||||
if (deref_stat (dereference_option, p, ¤t_stat) != 0)
|
||||
if (deref_stat (dereference_option, p, ¤t_stat_info.stat) != 0)
|
||||
{
|
||||
if (ignore_failed_read_option)
|
||||
stat_warn (p);
|
||||
@@ -890,12 +890,12 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
return;
|
||||
}
|
||||
|
||||
original_ctime = current_stat.st_ctime;
|
||||
restore_times.actime = current_stat.st_atime;
|
||||
restore_times.modtime = current_stat.st_mtime;
|
||||
original_ctime = current_stat_info.stat.st_ctime;
|
||||
restore_times.actime = current_stat_info.stat.st_atime;
|
||||
restore_times.modtime = current_stat_info.stat.st_mtime;
|
||||
|
||||
#ifdef S_ISHIDDEN
|
||||
if (S_ISHIDDEN (current_stat.st_mode))
|
||||
if (S_ISHIDDEN (current_stat_info.stat.st_mode))
|
||||
{
|
||||
char *new = (char *) alloca (strlen (p) + 2);
|
||||
if (new)
|
||||
@@ -911,9 +911,9 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
put in the archive. */
|
||||
|
||||
if ((0 < top_level || !incremental_option)
|
||||
&& !S_ISDIR (current_stat.st_mode)
|
||||
&& current_stat.st_mtime < newer_mtime_option
|
||||
&& (!after_date_option || current_stat.st_ctime < newer_ctime_option))
|
||||
&& !S_ISDIR (current_stat_info.stat.st_mode)
|
||||
&& current_stat_info.stat.st_mtime < newer_mtime_option
|
||||
&& (!after_date_option || current_stat_info.stat.st_ctime < newer_ctime_option))
|
||||
{
|
||||
if (0 < top_level)
|
||||
WARN ((0, 0, _("%s: file is unchanged; not dumped"),
|
||||
@@ -925,7 +925,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
#if !MSDOS
|
||||
/* See if we are trying to dump the archive. */
|
||||
|
||||
if (ar_dev && current_stat.st_dev == ar_dev && current_stat.st_ino == ar_ino)
|
||||
if (ar_dev && current_stat_info.stat.st_dev == ar_dev && current_stat_info.stat.st_ino == ar_ino)
|
||||
{
|
||||
WARN ((0, 0, _("%s: file is the archive; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
@@ -933,7 +933,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (S_ISDIR (current_stat.st_mode))
|
||||
if (S_ISDIR (current_stat_info.stat.st_mode))
|
||||
{
|
||||
char *directory;
|
||||
char const *entry;
|
||||
@@ -941,7 +941,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
char *namebuf;
|
||||
size_t buflen;
|
||||
size_t len;
|
||||
dev_t our_device = current_stat.st_dev;
|
||||
dev_t our_device = current_stat_info.stat.st_dev;
|
||||
|
||||
errno = 0;
|
||||
|
||||
@@ -979,18 +979,18 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
directory blocks to be written even with old archives. */
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
current_stat.st_size = 0; /* force 0 size on dir */
|
||||
current_stat_info.stat.st_size = 0; /* force 0 size on dir */
|
||||
|
||||
/* FIXME: If people could really read standard archives, this
|
||||
should be:
|
||||
|
||||
header
|
||||
= start_header (standard_option ? p : namebuf, ¤t_stat);
|
||||
= start_header (standard_option ? p : namebuf, ¤t_stat_info);
|
||||
|
||||
but since they'd interpret DIRTYPE blocks as regular
|
||||
files, we'd better put the / on the name. */
|
||||
|
||||
header = start_header (namebuf, ¤t_stat);
|
||||
header = start_header (namebuf, ¤t_stat_info);
|
||||
|
||||
if (incremental_option)
|
||||
header->header.typeflag = GNUTYPE_DUMPDIR;
|
||||
@@ -1063,7 +1063,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
avoid doing so if the user only wants to dump one file system. */
|
||||
|
||||
if (one_file_system_option && !top_level
|
||||
&& parent_device != current_stat.st_dev)
|
||||
&& parent_device != current_stat_info.stat.st_dev)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
@@ -1104,12 +1104,12 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
{
|
||||
/* Check for multiple links. */
|
||||
|
||||
if (1 < current_stat.st_nlink && link_table)
|
||||
if (1 < current_stat_info.stat.st_nlink && link_table)
|
||||
{
|
||||
struct link lp;
|
||||
struct link *dup;
|
||||
lp.ino = current_stat.st_ino;
|
||||
lp.dev = current_stat.st_dev;
|
||||
lp.ino = current_stat_info.stat.st_ino;
|
||||
lp.dev = current_stat_info.stat.st_dev;
|
||||
|
||||
if ((dup = hash_lookup (link_table, &lp)))
|
||||
{
|
||||
@@ -1121,10 +1121,10 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
block_ordinal = current_block_ordinal ();
|
||||
if (NAME_FIELD_SIZE <= strlen (link_name))
|
||||
write_long (link_name, GNUTYPE_LONGLINK);
|
||||
assign_string (¤t_link_name, link_name);
|
||||
assign_string (¤t_stat_info.link_name, link_name);
|
||||
|
||||
current_stat.st_size = 0;
|
||||
header = start_header (p, ¤t_stat);
|
||||
current_stat_info.stat.st_size = 0;
|
||||
header = start_header (p, ¤t_stat_info);
|
||||
strncpy (header->header.linkname, link_name, NAME_FIELD_SIZE);
|
||||
|
||||
/* Force null termination. */
|
||||
@@ -1146,8 +1146,8 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
|
||||
/* This is not a link to a previously dumped file, so dump it. */
|
||||
|
||||
if (S_ISREG (current_stat.st_mode)
|
||||
|| S_ISCTG (current_stat.st_mode))
|
||||
if (S_ISREG (current_stat_info.stat.st_mode)
|
||||
|| S_ISCTG (current_stat_info.stat.st_mode))
|
||||
{
|
||||
int f; /* file descriptor */
|
||||
size_t bufsize;
|
||||
@@ -1193,14 +1193,14 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
st_blocks, so `du' and `ls -s' give wrong results. So, the
|
||||
--sparse option would not work on a minix filesystem. */
|
||||
|
||||
if (ST_NBLOCKS (current_stat)
|
||||
< (current_stat.st_size / ST_NBLOCKSIZE
|
||||
+ (current_stat.st_size % ST_NBLOCKSIZE != 0)))
|
||||
if (ST_NBLOCKS (current_stat_info.stat)
|
||||
< (current_stat_info.stat.st_size / ST_NBLOCKSIZE
|
||||
+ (current_stat_info.stat.st_size % ST_NBLOCKSIZE != 0)))
|
||||
{
|
||||
int counter;
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
header = start_header (p, ¤t_stat);
|
||||
header = start_header (p, ¤t_stat_info);
|
||||
header->header.typeflag = GNUTYPE_SPARSE;
|
||||
header_moved = 1;
|
||||
|
||||
@@ -1221,15 +1221,15 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
<file>. It might be kind of disconcerting if the
|
||||
shrunken file size was the one that showed up. */
|
||||
|
||||
OFF_TO_CHARS (current_stat.st_size,
|
||||
OFF_TO_CHARS (current_stat_info.stat.st_size,
|
||||
header->oldgnu_header.realsize);
|
||||
|
||||
/* This will be the new "size" of the file, i.e., the size
|
||||
of the file minus the blocks of holes that we're
|
||||
skipping over. */
|
||||
|
||||
current_stat.st_size = find_new_file_size (sparses);
|
||||
OFF_TO_CHARS (current_stat.st_size, header->header.size);
|
||||
current_stat_info.stat.st_size = find_new_file_size (sparses);
|
||||
OFF_TO_CHARS (current_stat_info.stat.st_size, header->header.size);
|
||||
|
||||
for (counter = 0;
|
||||
counter < sparses && counter < SPARSES_IN_OLDGNU_HEADER;
|
||||
@@ -1243,14 +1243,14 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
}
|
||||
}
|
||||
|
||||
sizeleft = current_stat.st_size;
|
||||
sizeleft = current_stat_info.stat.st_size;
|
||||
|
||||
/* Don't bother opening empty, world readable files. Also do not open
|
||||
files when archive is meant for /dev/null. */
|
||||
|
||||
if (dev_null_output
|
||||
|| (sizeleft == 0
|
||||
&& MODE_R == (MODE_R & current_stat.st_mode)))
|
||||
&& MODE_R == (MODE_R & current_stat_info.stat.st_mode)))
|
||||
f = -1;
|
||||
else
|
||||
{
|
||||
@@ -1271,12 +1271,12 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
if (!header_moved)
|
||||
{
|
||||
block_ordinal = current_block_ordinal ();
|
||||
header = start_header (p, ¤t_stat);
|
||||
header = start_header (p, ¤t_stat_info);
|
||||
}
|
||||
|
||||
/* Mark contiguous files, if we support them. */
|
||||
|
||||
if (archive_format != V7_FORMAT && S_ISCTG (current_stat.st_mode))
|
||||
if (archive_format != V7_FORMAT && S_ISCTG (current_stat_info.stat.st_mode))
|
||||
header->header.typeflag = CONTTYPE;
|
||||
|
||||
isextended = header->oldgnu_header.isextended;
|
||||
@@ -1312,7 +1312,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
{
|
||||
if (f < 0
|
||||
|| finish_sparse_file (f, &sizeleft,
|
||||
current_stat.st_size, p))
|
||||
current_stat_info.stat.st_size, p))
|
||||
goto padit;
|
||||
}
|
||||
else
|
||||
@@ -1322,7 +1322,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
{
|
||||
assign_string (&save_name, p);
|
||||
save_sizeleft = sizeleft;
|
||||
save_totsize = current_stat.st_size;
|
||||
save_totsize = current_stat_info.stat.st_size;
|
||||
}
|
||||
start = find_next_block ();
|
||||
|
||||
@@ -1346,7 +1346,7 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
(ignore_failed_read_option
|
||||
? read_warn_details
|
||||
: read_error_details)
|
||||
(p, current_stat.st_size - sizeleft, bufsize);
|
||||
(p, current_stat_info.stat.st_size - sizeleft, bufsize);
|
||||
goto padit;
|
||||
}
|
||||
sizeleft -= count;
|
||||
@@ -1428,12 +1428,12 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
goto file_was_dumped;
|
||||
}
|
||||
#ifdef HAVE_READLINK
|
||||
else if (S_ISLNK (current_stat.st_mode))
|
||||
else if (S_ISLNK (current_stat_info.stat.st_mode))
|
||||
{
|
||||
char *buffer;
|
||||
int size;
|
||||
size_t linklen = current_stat.st_size;
|
||||
if (linklen != current_stat.st_size || linklen + 1 == 0)
|
||||
size_t linklen = current_stat_info.stat.st_size;
|
||||
if (linklen != current_stat_info.stat.st_size || linklen + 1 == 0)
|
||||
xalloc_die ();
|
||||
buffer = (char *) alloca (linklen + 1);
|
||||
size = readlink (p, buffer, linklen + 1);
|
||||
@@ -1448,11 +1448,11 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
buffer[size] = '\0';
|
||||
if (size >= NAME_FIELD_SIZE)
|
||||
write_long (buffer, GNUTYPE_LONGLINK);
|
||||
assign_string (¤t_link_name, buffer);
|
||||
assign_string (¤t_stat_info.link_name, buffer);
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
current_stat.st_size = 0; /* force 0 size on symlink */
|
||||
header = start_header (p, ¤t_stat);
|
||||
current_stat_info.stat.st_size = 0; /* force 0 size on symlink */
|
||||
header = start_header (p, ¤t_stat_info);
|
||||
strncpy (header->header.linkname, buffer, NAME_FIELD_SIZE);
|
||||
header->header.linkname[NAME_FIELD_SIZE - 1] = '\0';
|
||||
header->header.typeflag = SYMTYPE;
|
||||
@@ -1467,18 +1467,18 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
goto file_was_dumped;
|
||||
}
|
||||
#endif
|
||||
else if (S_ISCHR (current_stat.st_mode))
|
||||
else if (S_ISCHR (current_stat_info.stat.st_mode))
|
||||
type = CHRTYPE;
|
||||
else if (S_ISBLK (current_stat.st_mode))
|
||||
else if (S_ISBLK (current_stat_info.stat.st_mode))
|
||||
type = BLKTYPE;
|
||||
else if (S_ISFIFO (current_stat.st_mode))
|
||||
else if (S_ISFIFO (current_stat_info.stat.st_mode))
|
||||
type = FIFOTYPE;
|
||||
else if (S_ISSOCK (current_stat.st_mode))
|
||||
else if (S_ISSOCK (current_stat_info.stat.st_mode))
|
||||
{
|
||||
WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
else if (S_ISDOOR (current_stat.st_mode))
|
||||
else if (S_ISDOOR (current_stat_info.stat.st_mode))
|
||||
{
|
||||
WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
|
||||
return;
|
||||
@@ -1491,14 +1491,14 @@ dump_file (char *p, int top_level, dev_t parent_device)
|
||||
goto unknown;
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
current_stat.st_size = 0; /* force 0 size */
|
||||
header = start_header (p, ¤t_stat);
|
||||
current_stat_info.stat.st_size = 0; /* force 0 size */
|
||||
header = start_header (p, ¤t_stat_info);
|
||||
header->header.typeflag = type;
|
||||
|
||||
if (type != FIFOTYPE)
|
||||
{
|
||||
MAJOR_TO_CHARS (major (current_stat.st_rdev), header->header.devmajor);
|
||||
MINOR_TO_CHARS (minor (current_stat.st_rdev), header->header.devminor);
|
||||
MAJOR_TO_CHARS (major (current_stat_info.stat.st_rdev), header->header.devmajor);
|
||||
MINOR_TO_CHARS (minor (current_stat_info.stat.st_rdev), header->header.devminor);
|
||||
}
|
||||
|
||||
finish_header (header, block_ordinal);
|
||||
@@ -1517,14 +1517,14 @@ unknown:
|
||||
return;
|
||||
|
||||
file_was_dumped:
|
||||
if (1 < current_stat.st_nlink)
|
||||
if (1 < current_stat_info.stat.st_nlink)
|
||||
{
|
||||
struct link *dup;
|
||||
struct link *lp = xmalloc (offsetof (struct link, name)
|
||||
+ strlen (p) + 1);
|
||||
lp->ino = current_stat.st_ino;
|
||||
lp->dev = current_stat.st_dev;
|
||||
lp->nlink = current_stat.st_nlink;
|
||||
lp->ino = current_stat_info.stat.st_ino;
|
||||
lp->dev = current_stat_info.stat.st_dev;
|
||||
lp->nlink = current_stat_info.stat.st_nlink;
|
||||
strcpy (lp->name, p);
|
||||
|
||||
if (! ((link_table
|
||||
|
||||
402
src/delete.c
402
src/delete.c
@@ -1,5 +1,7 @@
|
||||
/* Delete entries from a tar archive.
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -13,97 +15,95 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
|
||||
#include "common.h"
|
||||
#include "rmt.h"
|
||||
|
||||
static union block *new_record = NULL;
|
||||
static union block *save_record = NULL;
|
||||
static int records_read = 0;
|
||||
static int new_blocks = 0;
|
||||
static int blocks_needed = 0;
|
||||
static union block *new_record;
|
||||
static int new_blocks;
|
||||
static bool acting_as_filter;
|
||||
|
||||
/* FIXME: This module should not directly handle the following three
|
||||
variables, instead, this should be done in buffer.c only. */
|
||||
/* FIXME: This module should not directly handle the following
|
||||
variables, instead, the interface should be cleaned up. */
|
||||
extern union block *record_start;
|
||||
extern union block *record_end;
|
||||
extern union block *current_block;
|
||||
extern union block *recent_long_name;
|
||||
extern union block *recent_long_link;
|
||||
extern off_t records_read;
|
||||
extern off_t records_written;
|
||||
|
||||
/*-------------------------------------------------------------------------.
|
||||
| Move archive descriptor by COUNT records worth. If COUNT is positive we |
|
||||
| move forward, else we move negative. If its a tape, MTIOCTOP had better |
|
||||
| work. If its something else, we try to seek on it. If we can't seek, |
|
||||
| we loose! |
|
||||
`-------------------------------------------------------------------------*/
|
||||
/* The number of records skipped at the start of the archive, when
|
||||
passing over members that are not deleted. */
|
||||
static off_t records_skipped;
|
||||
|
||||
/* Move archive descriptor by COUNT records worth. If COUNT is
|
||||
positive we move forward, else we move negative. If it's a tape,
|
||||
MTIOCTOP had better work. If it's something else, we try to seek
|
||||
on it. If we can't seek, we lose! */
|
||||
static void
|
||||
move_archive (int count)
|
||||
move_archive (off_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
{
|
||||
struct mtop operation;
|
||||
int status;
|
||||
|
||||
if (count > 0)
|
||||
if (count < 0
|
||||
? (operation.mt_op = MTBSR,
|
||||
operation.mt_count = -count,
|
||||
operation.mt_count == -count)
|
||||
: (operation.mt_op = MTFSR,
|
||||
operation.mt_count = count,
|
||||
operation.mt_count == count))
|
||||
{
|
||||
operation.mt_op = MTFSR;
|
||||
operation.mt_count = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
operation.mt_op = MTBSR;
|
||||
operation.mt_count = -count;
|
||||
}
|
||||
if (0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
|
||||
return;
|
||||
|
||||
if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
|
||||
status >= 0)
|
||||
return;
|
||||
|
||||
if (errno == EIO)
|
||||
if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
|
||||
status >= 0)
|
||||
return;
|
||||
if (errno == EIO
|
||||
&& 0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* MTIOCTOP */
|
||||
|
||||
{
|
||||
off_t position = rmtlseek (archive, 0L, 1);
|
||||
off_t position0 = rmtlseek (archive, (off_t) 0, SEEK_CUR);
|
||||
off_t increment = record_size * (off_t) count;
|
||||
off_t position = position0 + increment;
|
||||
|
||||
position += record_size * count;
|
||||
|
||||
if (rmtlseek (archive, position, 0) != position)
|
||||
FATAL_ERROR ((0, 0, _("Could not re-position archive file")));
|
||||
if (increment / count != record_size
|
||||
|| (position < position0) != (increment < 0)
|
||||
|| (position = position < 0 ? 0 : position,
|
||||
rmtlseek (archive, position, SEEK_SET) != position))
|
||||
seek_error_details (archive_name_array[0], position);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------.
|
||||
| Write out the record which has been filled. If MOVE_BACK_FLAG, |
|
||||
| backspace to where we started. |
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
/* Write out the record which has been filled. If MOVE_BACK_FLAG,
|
||||
backspace to where we started. */
|
||||
static void
|
||||
write_record (int move_back_flag)
|
||||
{
|
||||
save_record = record_start;
|
||||
union block *save_record = record_start;
|
||||
record_start = new_record;
|
||||
|
||||
if (archive == STDIN)
|
||||
if (acting_as_filter)
|
||||
{
|
||||
archive = STDOUT;
|
||||
archive = STDOUT_FILENO;
|
||||
flush_write ();
|
||||
archive = STDIN;
|
||||
archive = STDIN_FILENO;
|
||||
}
|
||||
else
|
||||
{
|
||||
move_archive (-(records_read + 1));
|
||||
move_archive ((records_written + records_skipped) - records_read);
|
||||
flush_write ();
|
||||
}
|
||||
|
||||
@@ -113,19 +113,24 @@ write_record (int move_back_flag)
|
||||
{
|
||||
/* Move the tape head back to where we were. */
|
||||
|
||||
if (archive != STDIN)
|
||||
move_archive (records_read);
|
||||
|
||||
records_read--;
|
||||
if (! acting_as_filter)
|
||||
move_archive (records_read - (records_written + records_skipped));
|
||||
}
|
||||
|
||||
blocks_needed = blocking_factor;
|
||||
new_blocks = 0;
|
||||
}
|
||||
|
||||
/*---.
|
||||
| ? |
|
||||
`---*/
|
||||
static void
|
||||
write_recent_blocks (union block *h, size_t blocks)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < blocks; i++)
|
||||
{
|
||||
new_record[new_blocks++] = h[i];
|
||||
if (new_blocks == blocking_factor)
|
||||
write_record (1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
delete_archive_members (void)
|
||||
@@ -135,16 +140,17 @@ delete_archive_members (void)
|
||||
|
||||
/* FIXME: Should clean the routine before cleaning these variables :-( */
|
||||
struct name *name;
|
||||
int blocks_to_skip = 0;
|
||||
int blocks_to_keep = 0;
|
||||
off_t blocks_to_skip = 0;
|
||||
off_t blocks_to_keep = 0;
|
||||
int kept_blocks_in_record;
|
||||
|
||||
name_gather ();
|
||||
open_archive (ACCESS_UPDATE);
|
||||
acting_as_filter = strcmp (archive_name_array[0], "-") == 0;
|
||||
|
||||
while (logical_status == HEADER_STILL_UNREAD)
|
||||
do
|
||||
{
|
||||
enum read_header status = read_header ();
|
||||
enum read_header status = read_header (1);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -152,19 +158,24 @@ delete_archive_members (void)
|
||||
abort ();
|
||||
|
||||
case HEADER_SUCCESS:
|
||||
if (name = name_scan (current_file_name), !name)
|
||||
if (name = name_scan (current_stat_info.file_name), !name)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) (current_stat.st_size));
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
name->found = 1;
|
||||
logical_status = HEADER_SUCCESS;
|
||||
/* Fall through. */
|
||||
case HEADER_SUCCESS_EXTENDED:
|
||||
logical_status = status;
|
||||
break;
|
||||
|
||||
case HEADER_ZERO_BLOCK:
|
||||
if (ignore_zeros_option)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case HEADER_END_OF_FILE:
|
||||
logical_status = HEADER_END_OF_FILE;
|
||||
break;
|
||||
@@ -193,144 +204,159 @@ delete_archive_members (void)
|
||||
|
||||
previous_status = status;
|
||||
}
|
||||
while (logical_status == HEADER_STILL_UNREAD);
|
||||
|
||||
if (logical_status != HEADER_SUCCESS)
|
||||
records_skipped = records_read - 1;
|
||||
new_record = xmalloc (record_size);
|
||||
|
||||
if (logical_status == HEADER_SUCCESS
|
||||
|| logical_status == HEADER_SUCCESS_EXTENDED)
|
||||
{
|
||||
write_eot ();
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
return;
|
||||
}
|
||||
write_archive_to_stdout = 0;
|
||||
|
||||
write_archive_to_stdout = 0;
|
||||
new_record = (union block *) xmalloc ((size_t) record_size);
|
||||
/* Save away blocks before this one in this record. */
|
||||
|
||||
/* Save away blocks before this one in this record. */
|
||||
new_blocks = current_block - record_start;
|
||||
if (new_blocks)
|
||||
memcpy (new_record, record_start, new_blocks * BLOCKSIZE);
|
||||
|
||||
new_blocks = current_block - record_start;
|
||||
blocks_needed = blocking_factor - new_blocks;
|
||||
if (new_blocks)
|
||||
memcpy ((void *) new_record, (void *) record_start,
|
||||
(size_t) (new_blocks * BLOCKSIZE));
|
||||
|
||||
#if 0
|
||||
/* FIXME: Old code, before the goto was inserted. To be redesigned. */
|
||||
set_next_block_after (current_header);
|
||||
if (current_header->oldgnu_header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) (current_stat.st_size));
|
||||
#endif
|
||||
logical_status = HEADER_STILL_UNREAD;
|
||||
goto flush_file;
|
||||
|
||||
/* FIXME: Solaris 2.4 Sun cc (the ANSI one, not the old K&R) says:
|
||||
"delete.c", line 223: warning: loop not entered at top
|
||||
Reported by Bruno Haible. */
|
||||
while (1)
|
||||
{
|
||||
enum read_header status;
|
||||
|
||||
/* Fill in a record. */
|
||||
|
||||
if (current_block == record_end)
|
||||
if (logical_status == HEADER_SUCCESS)
|
||||
{
|
||||
flush_archive ();
|
||||
records_read++;
|
||||
}
|
||||
status = read_header ();
|
||||
|
||||
if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
if (status == HEADER_END_OF_FILE || status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
logical_status = HEADER_END_OF_FILE;
|
||||
memset (new_record[new_blocks].buffer, 0,
|
||||
(size_t) (BLOCKSIZE * blocks_needed));
|
||||
new_blocks += blocks_needed;
|
||||
blocks_needed = 0;
|
||||
write_record (0);
|
||||
break;
|
||||
/* FIXME: Pheew! This is crufty code! */
|
||||
logical_status = HEADER_STILL_UNREAD;
|
||||
goto flush_file;
|
||||
}
|
||||
|
||||
if (status == HEADER_FAILURE)
|
||||
/* FIXME: Solaris 2.4 Sun cc (the ANSI one, not the old K&R) says:
|
||||
"delete.c", line 223: warning: loop not entered at top
|
||||
Reported by Bruno Haible. */
|
||||
while (1)
|
||||
{
|
||||
ERROR ((0, 0, _("Deleting non-header from archive")));
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
enum read_header status;
|
||||
|
||||
/* Found another header. */
|
||||
|
||||
if (name = name_scan (current_file_name), name)
|
||||
{
|
||||
name->found = 1;
|
||||
flush_file:
|
||||
set_next_block_after (current_header);
|
||||
blocks_to_skip = (current_stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
|
||||
while (record_end - current_block <= blocks_to_skip)
|
||||
{
|
||||
blocks_to_skip -= (record_end - current_block);
|
||||
flush_archive ();
|
||||
records_read++;
|
||||
}
|
||||
current_block += blocks_to_skip;
|
||||
blocks_to_skip = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Copy header. */
|
||||
|
||||
new_record[new_blocks] = *current_header;
|
||||
new_blocks++;
|
||||
blocks_needed--;
|
||||
blocks_to_keep
|
||||
= (current_stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
set_next_block_after (current_header);
|
||||
if (blocks_needed == 0)
|
||||
write_record (1);
|
||||
|
||||
/* Copy data. */
|
||||
|
||||
kept_blocks_in_record = record_end - current_block;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
|
||||
while (blocks_to_keep)
|
||||
{
|
||||
int count;
|
||||
/* Fill in a record. */
|
||||
|
||||
if (current_block == record_end)
|
||||
flush_archive ();
|
||||
status = read_header (0);
|
||||
|
||||
if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
|
||||
{
|
||||
flush_read ();
|
||||
records_read++;
|
||||
current_block = record_start;
|
||||
kept_blocks_in_record = blocking_factor;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
if (status == HEADER_END_OF_FILE || status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
logical_status = HEADER_END_OF_FILE;
|
||||
break;
|
||||
}
|
||||
count = kept_blocks_in_record;
|
||||
if (count > blocks_needed)
|
||||
count = blocks_needed;
|
||||
|
||||
memcpy ((void *) (new_record + new_blocks),
|
||||
(void *) current_block,
|
||||
(size_t) (count * BLOCKSIZE));
|
||||
new_blocks += count;
|
||||
blocks_needed -= count;
|
||||
current_block += count;
|
||||
blocks_to_keep -= count;
|
||||
kept_blocks_in_record -= count;
|
||||
if (status == HEADER_FAILURE)
|
||||
{
|
||||
ERROR ((0, 0, _("Deleting non-header from archive")));
|
||||
set_next_block_after (current_header);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (blocks_needed == 0)
|
||||
/* Found another header. */
|
||||
|
||||
if (name = name_scan (current_stat_info.file_name), name)
|
||||
{
|
||||
name->found = 1;
|
||||
flush_file:
|
||||
set_next_block_after (current_header);
|
||||
blocks_to_skip = (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
|
||||
while (record_end - current_block <= blocks_to_skip)
|
||||
{
|
||||
blocks_to_skip -= (record_end - current_block);
|
||||
flush_archive ();
|
||||
}
|
||||
current_block += blocks_to_skip;
|
||||
blocks_to_skip = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Copy header. */
|
||||
|
||||
write_recent_blocks (recent_long_name, recent_long_name_blocks);
|
||||
write_recent_blocks (recent_long_link, recent_long_link_blocks);
|
||||
new_record[new_blocks] = *current_header;
|
||||
new_blocks++;
|
||||
blocks_to_keep
|
||||
= (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
set_next_block_after (current_header);
|
||||
if (new_blocks == blocking_factor)
|
||||
write_record (1);
|
||||
|
||||
/* Copy data. */
|
||||
|
||||
kept_blocks_in_record = record_end - current_block;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
|
||||
while (blocks_to_keep)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (current_block == record_end)
|
||||
{
|
||||
flush_read ();
|
||||
current_block = record_start;
|
||||
kept_blocks_in_record = blocking_factor;
|
||||
if (kept_blocks_in_record > blocks_to_keep)
|
||||
kept_blocks_in_record = blocks_to_keep;
|
||||
}
|
||||
count = kept_blocks_in_record;
|
||||
if (blocking_factor - new_blocks < count)
|
||||
count = blocking_factor - new_blocks;
|
||||
|
||||
if (! count)
|
||||
abort ();
|
||||
|
||||
memcpy (new_record + new_blocks, current_block, count * BLOCKSIZE);
|
||||
new_blocks += count;
|
||||
current_block += count;
|
||||
blocks_to_keep -= count;
|
||||
kept_blocks_in_record -= count;
|
||||
|
||||
if (new_blocks == blocking_factor)
|
||||
write_record (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_eot ();
|
||||
if (logical_status == HEADER_END_OF_FILE)
|
||||
{
|
||||
/* Write the end of tape. FIXME: we can't use write_eot here,
|
||||
as it gets confused when the input is at end of file. */
|
||||
|
||||
int total_zero_blocks = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int zero_blocks = blocking_factor - new_blocks;
|
||||
memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
|
||||
total_zero_blocks += zero_blocks;
|
||||
write_record (total_zero_blocks < 2);
|
||||
}
|
||||
while (total_zero_blocks < 2);
|
||||
}
|
||||
|
||||
free (new_record);
|
||||
|
||||
if (! acting_as_filter && ! _isrmt (archive))
|
||||
{
|
||||
#if MSDOS
|
||||
int status = write (archive, "", 0);
|
||||
#else
|
||||
off_t pos = lseek (archive, (off_t) 0, SEEK_CUR);
|
||||
int status = pos < 0 ? -1 : ftruncate (archive, pos);
|
||||
#endif
|
||||
if (status != 0)
|
||||
truncate_warn (archive_name_array[0]);
|
||||
}
|
||||
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
}
|
||||
|
||||
125
src/extract.c
125
src/extract.c
@@ -129,14 +129,15 @@ extr_init (void)
|
||||
}
|
||||
|
||||
/* If restoring permissions, restore the mode for FILE_NAME from
|
||||
information given in *STAT_INFO (where *CURRENT_STAT_INFO gives
|
||||
the current status if CURRENT_STAT_INFO is nonzero); otherwise invert the
|
||||
information given in *STAT_INFO (where *CUR_INFO gives
|
||||
the current status if CUR_INFO is nonzero); otherwise invert the
|
||||
INVERT_PERMISSIONS bits from the file's current permissions.
|
||||
PERMSTATUS specifies the status of the file's permissions.
|
||||
TYPEFLAG specifies the type of the file. */
|
||||
static void
|
||||
set_mode (char const *file_name, struct stat const *stat_info,
|
||||
struct stat const *current_stat_info,
|
||||
set_mode (char const *file_name,
|
||||
struct stat const *stat_info,
|
||||
struct stat const *cur_info,
|
||||
mode_t invert_permissions, enum permstatus permstatus,
|
||||
char typeflag)
|
||||
{
|
||||
@@ -168,16 +169,16 @@ set_mode (char const *file_name, struct stat const *stat_info,
|
||||
that we created, so there's no point optimizing this code for
|
||||
other cases. */
|
||||
struct stat st;
|
||||
if (! current_stat_info)
|
||||
if (! cur_info)
|
||||
{
|
||||
if (stat (file_name, &st) != 0)
|
||||
{
|
||||
stat_error (file_name);
|
||||
return;
|
||||
}
|
||||
current_stat_info = &st;
|
||||
cur_info = &st;
|
||||
}
|
||||
mode = current_stat_info->st_mode ^ invert_permissions;
|
||||
mode = cur_info->st_mode ^ invert_permissions;
|
||||
}
|
||||
|
||||
if (chmod (file_name, mode) != 0)
|
||||
@@ -199,7 +200,7 @@ check_time (char const *file_name, time_t t)
|
||||
|
||||
/* Restore stat attributes (owner, group, mode and times) for
|
||||
FILE_NAME, using information given in *STAT_INFO.
|
||||
If CURRENT_STAT_INFO is nonzero, *CURRENT_STAT_INFO is the
|
||||
If CUR_INFO is nonzero, *CUR_INFO is the
|
||||
file's currernt status.
|
||||
If not restoring permissions, invert the
|
||||
INVERT_PERMISSIONS bits from the file's current permissions.
|
||||
@@ -212,8 +213,9 @@ check_time (char const *file_name, time_t t)
|
||||
punt for the rest. Sigh! */
|
||||
|
||||
static void
|
||||
set_stat (char const *file_name, struct stat const *stat_info,
|
||||
struct stat const *current_stat_info,
|
||||
set_stat (char const *file_name,
|
||||
struct stat const *stat_info,
|
||||
struct stat const *cur_info,
|
||||
mode_t invert_permissions, enum permstatus permstatus,
|
||||
char typeflag)
|
||||
{
|
||||
@@ -252,7 +254,7 @@ set_stat (char const *file_name, struct stat const *stat_info,
|
||||
done, it is not possible anymore to change file permissions, so we
|
||||
have to set permissions prior to possibly giving files away. */
|
||||
|
||||
set_mode (file_name, stat_info, current_stat_info,
|
||||
set_mode (file_name, stat_info, cur_info,
|
||||
invert_permissions, permstatus, typeflag);
|
||||
}
|
||||
|
||||
@@ -332,9 +334,9 @@ repair_delayed_set_stat (char const *dir_name,
|
||||
if (st.st_dev == dir_stat_info->st_dev
|
||||
&& st.st_ino == dir_stat_info->st_ino)
|
||||
{
|
||||
data->stat_info = current_stat;
|
||||
data->invert_permissions = (MODE_RWX
|
||||
& (current_stat.st_mode ^ st.st_mode));
|
||||
data->stat_info = current_stat_info.stat;
|
||||
data->invert_permissions =
|
||||
(MODE_RWX & (current_stat_info.stat.st_mode ^ st.st_mode));
|
||||
data->permstatus = ARCHIVED_PERMSTATUS;
|
||||
return;
|
||||
}
|
||||
@@ -388,7 +390,7 @@ make_directories (char *file_name)
|
||||
invert_permissions is zero, because
|
||||
repair_delayed_set_stat may need to update the struct. */
|
||||
delay_set_stat (file_name,
|
||||
¤t_stat /* ignored */,
|
||||
¤t_stat_info.stat /* ignored */,
|
||||
invert_permissions, INTERDIR_PERMSTATUS);
|
||||
|
||||
print_for_mkdir (file_name, cursor - file_name, mode);
|
||||
@@ -400,13 +402,16 @@ make_directories (char *file_name)
|
||||
|
||||
*cursor = '/';
|
||||
|
||||
if (errno == EEXIST
|
||||
if (errno == EEXIST)
|
||||
continue; /* Directory already exists. */
|
||||
else if ((errno == ENOSYS /* Automounted dirs on Solaris return
|
||||
this. Reported by Warren Hyde
|
||||
<Warren.Hyde@motorola.com> */
|
||||
#if MSDOS
|
||||
/* Turbo C mkdir gives a funny errno. */
|
||||
|| errno == EACCES
|
||||
|| errno == EACCES /* Turbo C mkdir gives a funny errno. */
|
||||
#endif
|
||||
)
|
||||
/* Directory already exists. */
|
||||
)
|
||||
&& access (file_name, W_OK) == 0)
|
||||
continue;
|
||||
|
||||
/* Some other error in the mkdir. We return to the caller. */
|
||||
@@ -493,7 +498,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
bool
|
||||
fill_in_sparse_array (void)
|
||||
{
|
||||
off_t sparse_data_size = current_stat.st_size;
|
||||
off_t sparse_data_size = current_stat_info.stat.st_size;
|
||||
off_t file_size = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
|
||||
int sparses;
|
||||
int counter;
|
||||
@@ -560,7 +565,8 @@ fill_in_sparse_array (void)
|
||||
return 1;
|
||||
|
||||
invalid_member:
|
||||
ERROR ((0, 0, "%s: invalid sparse archive member", current_file_name));
|
||||
ERROR ((0, 0, _("%s: invalid sparse archive member"),
|
||||
current_stat_info.file_name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -640,7 +646,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_symlinks)
|
||||
struct delayed_set_stat *data = delayed_set_stat_head;
|
||||
bool skip_this_one = 0;
|
||||
struct stat st;
|
||||
struct stat const *current_stat_info = 0;
|
||||
struct stat const *cur_info = 0;
|
||||
|
||||
check_for_renamed_directories |= data->after_symlinks;
|
||||
|
||||
@@ -654,7 +660,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_symlinks)
|
||||
|
||||
if (check_for_renamed_directories)
|
||||
{
|
||||
current_stat_info = &st;
|
||||
cur_info = &st;
|
||||
if (stat (data->file_name, &st) != 0)
|
||||
{
|
||||
stat_error (data->file_name);
|
||||
@@ -671,7 +677,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_symlinks)
|
||||
}
|
||||
|
||||
if (! skip_this_one)
|
||||
set_stat (data->file_name, &data->stat_info, current_stat_info,
|
||||
set_stat (data->file_name, &data->stat_info, cur_info,
|
||||
data->invert_permissions, data->permstatus, DIRTYPE);
|
||||
|
||||
delayed_set_stat_head = data->next;
|
||||
@@ -694,13 +700,12 @@ extract_archive (void)
|
||||
off_t file_size;
|
||||
int interdir_made = 0;
|
||||
char typeflag;
|
||||
union block *exhdr;
|
||||
char *file_name;
|
||||
|
||||
set_next_block_after (current_header);
|
||||
decode_header (current_header, ¤t_stat, ¤t_format, 1);
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
||||
|
||||
if (interactive_option && !confirm ("extract", current_file_name))
|
||||
if (interactive_option && !confirm ("extract", current_stat_info.file_name))
|
||||
{
|
||||
skip_member ();
|
||||
return;
|
||||
@@ -711,7 +716,7 @@ extract_archive (void)
|
||||
if (verbose_option)
|
||||
print_header (-1);
|
||||
|
||||
file_name = safer_name_suffix (current_file_name, 0);
|
||||
file_name = safer_name_suffix (current_stat_info.file_name, 0);
|
||||
|
||||
apply_nonancestor_delayed_set_stat (file_name, 0);
|
||||
|
||||
@@ -745,7 +750,7 @@ extract_archive (void)
|
||||
/* Appears to be a file. But BSD tar uses the convention that a slash
|
||||
suffix means a directory. */
|
||||
|
||||
if (current_trailing_slash)
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
goto really_dir;
|
||||
|
||||
/* FIXME: deal with protection issues. */
|
||||
@@ -755,7 +760,7 @@ extract_archive (void)
|
||||
| (old_files_option == OVERWRITE_OLD_FILES
|
||||
? O_TRUNC
|
||||
: O_EXCL));
|
||||
mode = current_stat.st_mode & MODE_RWX & ~ current_umask;
|
||||
mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
|
||||
|
||||
if (to_stdout_option)
|
||||
{
|
||||
@@ -776,7 +781,7 @@ extract_archive (void)
|
||||
the open call that creates them. */
|
||||
|
||||
if (typeflag == CONTTYPE)
|
||||
fd = open (file_name, openflag | O_CTG, mode, current_stat.st_size);
|
||||
fd = open (file_name, openflag | O_CTG, mode, current_stat_info.stat.st_size);
|
||||
else
|
||||
fd = open (file_name, openflag, mode);
|
||||
|
||||
@@ -823,16 +828,16 @@ extract_archive (void)
|
||||
name = xmalloc (name_length_bis);
|
||||
memcpy (name, file_name, name_length_bis);
|
||||
size = extract_sparse_file (fd, name,
|
||||
current_stat.st_size, file_size);
|
||||
current_stat_info.stat.st_size, file_size);
|
||||
free (sparsearray);
|
||||
}
|
||||
else
|
||||
for (size = current_stat.st_size; size > 0; )
|
||||
for (size = current_stat_info.stat.st_size; size > 0; )
|
||||
{
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_file_name);
|
||||
save_totsize = current_stat.st_size;
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = current_stat_info.stat.st_size;
|
||||
save_sizeleft = size;
|
||||
}
|
||||
|
||||
@@ -883,7 +888,7 @@ extract_archive (void)
|
||||
undo_last_backup ();
|
||||
}
|
||||
|
||||
set_stat (file_name, ¤t_stat, 0, 0,
|
||||
set_stat (file_name, ¤t_stat_info.stat, 0, 0,
|
||||
(old_files_option == OVERWRITE_OLD_FILES
|
||||
? UNKNOWN_PERMSTATUS
|
||||
: ARCHIVED_PERMSTATUS),
|
||||
@@ -896,19 +901,19 @@ extract_archive (void)
|
||||
break;
|
||||
|
||||
if (absolute_names_option
|
||||
|| ! (ISSLASH (current_link_name
|
||||
[FILESYSTEM_PREFIX_LEN (current_link_name)])
|
||||
|| contains_dot_dot (current_link_name)))
|
||||
|| ! (ISSLASH (current_stat_info.link_name
|
||||
[FILESYSTEM_PREFIX_LEN (current_stat_info.link_name)])
|
||||
|| contains_dot_dot (current_stat_info.link_name)))
|
||||
{
|
||||
while (status = symlink (current_link_name, file_name),
|
||||
while (status = symlink (current_stat_info.link_name, file_name),
|
||||
status != 0)
|
||||
if (!maybe_recoverable (file_name, &interdir_made))
|
||||
break;
|
||||
|
||||
if (status == 0)
|
||||
set_stat (file_name, ¤t_stat, 0, 0, 0, SYMTYPE);
|
||||
set_stat (file_name, ¤t_stat_info.stat, 0, 0, 0, SYMTYPE);
|
||||
else
|
||||
symlink_error (current_link_name, file_name);
|
||||
symlink_error (current_stat_info.link_name, file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -937,19 +942,19 @@ extract_archive (void)
|
||||
struct delayed_set_stat *h;
|
||||
struct delayed_symlink *p =
|
||||
xmalloc (offsetof (struct delayed_symlink, target)
|
||||
+ strlen (current_link_name) + 1);
|
||||
+ strlen (current_stat_info.link_name) + 1);
|
||||
p->next = delayed_symlink_head;
|
||||
delayed_symlink_head = p;
|
||||
p->dev = st.st_dev;
|
||||
p->ino = st.st_ino;
|
||||
p->mtime = st.st_mtime;
|
||||
p->uid = current_stat.st_uid;
|
||||
p->gid = current_stat.st_gid;
|
||||
p->uid = current_stat_info.stat.st_uid;
|
||||
p->gid = current_stat_info.stat.st_gid;
|
||||
p->sources = xmalloc (offsetof (struct string_list, string)
|
||||
+ strlen (file_name) + 1);
|
||||
p->sources->next = 0;
|
||||
strcpy (p->sources->string, file_name);
|
||||
strcpy (p->target, current_link_name);
|
||||
strcpy (p->target, current_stat_info.link_name);
|
||||
|
||||
h = delayed_set_stat_head;
|
||||
if (h && ! h->after_symlinks
|
||||
@@ -1002,7 +1007,7 @@ extract_archive (void)
|
||||
|
||||
again_link:
|
||||
{
|
||||
char const *link_name = safer_name_suffix (current_link_name, 1);
|
||||
char const *link_name = safer_name_suffix (current_stat_info.link_name, 1);
|
||||
struct stat st1, st2;
|
||||
int e;
|
||||
|
||||
@@ -1049,13 +1054,13 @@ extract_archive (void)
|
||||
|
||||
#if S_IFCHR
|
||||
case CHRTYPE:
|
||||
current_stat.st_mode |= S_IFCHR;
|
||||
current_stat_info.stat.st_mode |= S_IFCHR;
|
||||
goto make_node;
|
||||
#endif
|
||||
|
||||
#if S_IFBLK
|
||||
case BLKTYPE:
|
||||
current_stat.st_mode |= S_IFBLK;
|
||||
current_stat_info.stat.st_mode |= S_IFBLK;
|
||||
#endif
|
||||
|
||||
#if S_IFCHR || S_IFBLK
|
||||
@@ -1063,8 +1068,8 @@ extract_archive (void)
|
||||
if (! prepare_to_extract (file_name, 0))
|
||||
break;
|
||||
|
||||
status = mknod (file_name, current_stat.st_mode,
|
||||
current_stat.st_rdev);
|
||||
status = mknod (file_name, current_stat_info.stat.st_mode,
|
||||
current_stat_info.stat.st_rdev);
|
||||
if (status != 0)
|
||||
{
|
||||
if (maybe_recoverable (file_name, &interdir_made))
|
||||
@@ -1074,7 +1079,7 @@ extract_archive (void)
|
||||
undo_last_backup ();
|
||||
break;
|
||||
};
|
||||
set_stat (file_name, ¤t_stat, 0, 0,
|
||||
set_stat (file_name, ¤t_stat_info.stat, 0, 0,
|
||||
ARCHIVED_PERMSTATUS, typeflag);
|
||||
break;
|
||||
#endif
|
||||
@@ -1084,13 +1089,13 @@ extract_archive (void)
|
||||
if (! prepare_to_extract (file_name, 0))
|
||||
break;
|
||||
|
||||
while (status = mkfifo (file_name, current_stat.st_mode),
|
||||
while (status = mkfifo (file_name, current_stat_info.stat.st_mode),
|
||||
status != 0)
|
||||
if (!maybe_recoverable (file_name, &interdir_made))
|
||||
break;
|
||||
|
||||
if (status == 0)
|
||||
set_stat (file_name, ¤t_stat, 0, 0,
|
||||
set_stat (file_name, ¤t_stat_info.stat, NULL, 0,
|
||||
ARCHIVED_PERMSTATUS, typeflag);
|
||||
else
|
||||
{
|
||||
@@ -1114,7 +1119,7 @@ extract_archive (void)
|
||||
else if (typeflag == GNUTYPE_DUMPDIR)
|
||||
skip_member ();
|
||||
|
||||
mode = ((current_stat.st_mode
|
||||
mode = ((current_stat_info.stat.st_mode
|
||||
| (we_are_root ? 0 : MODE_WXUSR))
|
||||
& MODE_RWX);
|
||||
|
||||
@@ -1167,8 +1172,8 @@ extract_archive (void)
|
||||
if (status == 0
|
||||
|| old_files_option == DEFAULT_OLD_FILES
|
||||
|| old_files_option == OVERWRITE_OLD_FILES)
|
||||
delay_set_stat (file_name, ¤t_stat,
|
||||
MODE_RWX & (mode ^ current_stat.st_mode),
|
||||
delay_set_stat (file_name, ¤t_stat_info.stat,
|
||||
MODE_RWX & (mode ^ current_stat_info.stat.st_mode),
|
||||
(status == 0
|
||||
? ARCHIVED_PERMSTATUS
|
||||
: UNKNOWN_PERMSTATUS));
|
||||
@@ -1176,7 +1181,7 @@ extract_archive (void)
|
||||
|
||||
case GNUTYPE_VOLHDR:
|
||||
if (verbose_option)
|
||||
fprintf (stdlis, _("Reading %s\n"), quote (current_file_name));
|
||||
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
|
||||
break;
|
||||
|
||||
case GNUTYPE_NAMES:
|
||||
@@ -1186,7 +1191,7 @@ extract_archive (void)
|
||||
case GNUTYPE_MULTIVOL:
|
||||
ERROR ((0, 0,
|
||||
_("%s: Cannot extract -- file is continued from another volume"),
|
||||
quotearg_colon (current_file_name)));
|
||||
quotearg_colon (current_stat_info.file_name)));
|
||||
skip_member ();
|
||||
if (backup_option)
|
||||
undo_last_backup ();
|
||||
|
||||
825
src/incremen.c
825
src/incremen.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user