/* Create a tar archive.
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
char const *minval_string;
char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
char const *value_string;
-
+
if (gnu_format)
{
uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
}
else
minval_string = "0";
-
+
if (negative)
{
char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
}
else
value_string = STRINGIFY_BIGINT (value, valbuf);
-
+
if (substitute)
{
int negsub;
uintmax_t sub = substitute (&negsub) & maxval;
- /* FIXME: This is the only place where GNU_FORMAT differs from
- OLDGNU_FORMAT. Apart from this they are completely identical. */
+ /* NOTE: This is one of the few places where GNU_FORMAT differs from
+ OLDGNU_FORMAT. The actual differences are:
+
+ 1. In OLDGNU_FORMAT all strings in a tar header end in \0
+ 2. Incremental archives use oldgnu_header.
+
+ Apart from this they are completely identical. */
uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
char subbuf[UINTMAX_STRSIZE_BOUND + 1];
char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
}
else
substitute = NULL; /* No substitution for formats, other than GNU */
-
+
return to_chars_subst (negative, gnu_format, value, valsize, substitute,
where, size, type);
}
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
&& archive_format != POSIX_FORMAT
&& archive_format != USTAR_FORMAT
- && archive_format != GNU_FORMAT)
+ && archive_format != GNU_FORMAT
+ && archive_format != OLDGNU_FORMAT)
{
negative = v < 0;
u = v;
file_dumpable_p (struct tar_stat_info *st)
{
if (dev_null_output)
- return totals_option && sparse_option && sparse_file_p (st);
+ return totals_option && sparse_option && ST_IS_SPARSE (st->stat);
return !(st->archive_file_size == 0
&& (st->stat.st_mode & MODE_R) == MODE_R);
}
size_t i;
if (length > PREFIX_FIELD_SIZE)
- length = PREFIX_FIELD_SIZE+2;
+ length = PREFIX_FIELD_SIZE + 1;
for (i = length - 1; i > 0; i--)
if (ISSLASH (name[i]))
break;
if (mode_option)
st->stat.st_mode =
((st->stat.st_mode & ~MODE_ALL)
- | mode_adjust (st->stat.st_mode, mode_option, initial_umask));
+ | mode_adjust (st->stat.st_mode, S_ISDIR (st->stat.st_mode) != 0,
+ initial_umask, mode_option, NULL));
/* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
for a few tars and came up with the following interoperability
}
{
- struct timespec mtime = st->mtime;
+ struct timespec mtime = set_mtime_option ? mtime_option : st->mtime;
if (archive_format == POSIX_FORMAT)
{
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec
void
create_archive (void)
{
- char *p;
+ const char *p;
open_archive (ACCESS_WRITE);
xheader_write_global ();
exit_status to failure, a clear diagnostic has been issued. */
static void
-dump_file0 (struct tar_stat_info *st, char const *p,
+dump_file0 (struct tar_stat_info *st, const char *p,
int top_level, dev_t parent_device)
{
union block *header;
assign_string (&st->file_name,
safer_name_suffix (p, false, absolute_names_option));
+ transform_name (&st->file_name);
+
if (deref_stat (dereference_option, p, &st->stat) != 0)
{
stat_diag (p);
{
enum dump_status status;
- if (fd != -1 && sparse_option && sparse_file_p (st))
+ if (fd != -1 && sparse_option && ST_IS_SPARSE (st->stat))
{
status = sparse_dump_file (fd, st);
if (status == dump_status_not_implemented)
abort ();
}
+ file_count_links (st);
+
ok = status == dump_status_ok;
}
}
void
-dump_file (char *p, int top_level, dev_t parent_device)
+dump_file (const char *p, int top_level, dev_t parent_device)
{
struct tar_stat_info st;
tar_stat_init (&st);