/* Create a tar archive.
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003 Free Software Foundation, Inc.
+ 2003, 2004 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
{
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. */
uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
char subbuf[UINTMAX_STRSIZE_BOUND + 1];
char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
}
/* Write a "private" header */
-static union block *
+union block *
start_private_header (const char *name, size_t size)
{
time_t t;
xheader_store ("path", st, NULL);
break;
- case V7_FORMAT:
+ case V7_FORMAT:
+ if (strlen (st->file_name) > NAME_FIELD_SIZE-1)
+ {
+ WARN ((0, 0, _("%s: file name is too long (max %d); not dumped"),
+ quotearg_colon (st->file_name),
+ NAME_FIELD_SIZE - 1));
+ return NULL;
+ }
+ break;
+
case USTAR_FORMAT:
case STAR_FORMAT:
return write_ustar_long_name (st->file_name);
}
return write_short_name (st);
}
-
+
static union block *
-write_extended (struct tar_stat_info *st, union block *old_header, char type)
+write_extended (struct tar_stat_info *st, union block *old_header)
{
union block *header, hp;
- size_t size;
char *p;
if (extended_header.buffer || extended_header.stk == NULL)
return old_header;
xheader_finish (&extended_header);
- size = extended_header.size;
-
memcpy (hp.buffer, old_header, sizeof (hp));
-
- header = start_private_header ("././@PaxHeader", size);
- header->header.typeflag = type;
-
- finish_header (st, header, -1);
-
- p = extended_header.buffer;
-
- do
- {
- size_t len;
-
- header = find_next_block ();
- len = BLOCKSIZE;
- if (len > size)
- len = size;
- memcpy (header->buffer, p, len);
- if (len < BLOCKSIZE)
- memset (header->buffer + len, 0, BLOCKSIZE - len);
- p += len;
- size -= len;
- set_next_block_after (header);
- }
- while (size > 0);
-
- xheader_destroy (&extended_header);
+ p = xheader_xhdr_name (st);
+ xheader_write (XHDTYPE, p, &extended_header);
+ free (p);
header = find_next_block ();
memcpy (header, &hp.buffer, sizeof (hp.buffer));
return header;
static union block *
write_header_name (struct tar_stat_info *st)
{
- if (NAME_FIELD_SIZE < strlen (st->file_name))
+ if (archive_format == POSIX_FORMAT && !string_ascii_p (st->file_name))
+ {
+ xheader_store ("path", st, NULL);
+ return write_short_name (st);
+ }
+ else if (NAME_FIELD_SIZE < strlen (st->file_name))
return write_long_name (st);
else
return write_short_name (st);
xheader_store ("ctime", st, NULL);
}
else if (incremental_option)
- if (archive_format == OLDGNU_FORMAT)
+ if (archive_format == OLDGNU_FORMAT || archive_format == GNU_FORMAT)
{
TIME_TO_CHARS (st->stat.st_atime, header->oldgnu_header.atime);
TIME_TO_CHARS (st->stat.st_ctime, header->oldgnu_header.ctime);
gid_to_gname (st->stat.st_gid, &st->gname);
if (archive_format == POSIX_FORMAT
- && strlen (st->uname) > UNAME_FIELD_SIZE)
+ && (strlen (st->uname) > UNAME_FIELD_SIZE
+ || !string_ascii_p (st->uname)))
xheader_store ("uname", st, NULL);
else
UNAME_TO_CHARS (st->uname, header->header.uname);
if (archive_format == POSIX_FORMAT
- && strlen (st->gname) > GNAME_FIELD_SIZE)
+ && (strlen (st->gname) > GNAME_FIELD_SIZE
+ || !string_ascii_p (st->gname)))
xheader_store ("gname", st, NULL);
else
GNAME_TO_CHARS (st->gname, header->header.gname);
return header;
}
-/* Finish off a filled-in header block and write it out. We also
- print the file name and/or full info if verbose is on. If BLOCK_ORDINAL
- is not negative, is the block ordinal of the first record for this
- file, which may be a preceding long name or long link record. */
void
-finish_header (struct tar_stat_info *st,
- union block *header, off_t block_ordinal)
+simple_finish_header (union block *header)
{
size_t i;
int sum;
char *p;
- /* Note: It is important to do this before the call to write_extended(),
- so that the actual ustar header is printed */
- if (verbose_option
- && header->header.typeflag != GNUTYPE_LONGLINK
- && header->header.typeflag != GNUTYPE_LONGNAME
- && header->header.typeflag != XHDTYPE
- && header->header.typeflag != XGLTYPE)
- {
- /* These globals are parameters to print_header, sigh. */
-
- current_header = header;
- current_format = archive_format;
- print_header (st, block_ordinal);
- }
-
- header = write_extended (st, header, XHDTYPE);
-
memcpy (header->header.chksum, CHKBLANKS, sizeof header->header.chksum);
sum = 0;
set_next_block_after (header);
}
+
+/* Finish off a filled-in header block and write it out. We also
+ print the file name and/or full info if verbose is on. If BLOCK_ORDINAL
+ is not negative, is the block ordinal of the first record for this
+ file, which may be a preceding long name or long link record. */
+void
+finish_header (struct tar_stat_info *st,
+ union block *header, off_t block_ordinal)
+{
+ /* Note: It is important to do this before the call to write_extended(),
+ so that the actual ustar header is printed */
+ if (verbose_option
+ && header->header.typeflag != GNUTYPE_LONGLINK
+ && header->header.typeflag != GNUTYPE_LONGNAME
+ && header->header.typeflag != XHDTYPE
+ && header->header.typeflag != XGLTYPE)
+ {
+ /* These globals are parameters to print_header, sigh. */
+
+ current_header = header;
+ current_format = archive_format;
+ print_header (st, block_ordinal);
+ }
+
+ header = write_extended (st, header);
+ simple_finish_header (header);
+}
\f
void
return;
if (one_file_system_option
- && !top_level
- && parent_device != stat->stat.st_dev)
+ && !top_level
+ && parent_device != stat->stat.st_dev)
{
if (verbose_option)
WARN ((0, 0,
char *p;
open_archive (ACCESS_WRITE);
-
+ xheader_write_global ();
+
if (incremental_option)
{
size_t buffer_size = 1000;
/* See if we want only new files, and check if this one is too old to
put in the archive. */
- if ((0 < top_level || !incremental_option)
- && !S_ISDIR (stat->stat.st_mode)
+ if (!S_ISDIR (stat->stat.st_mode)
&& stat->stat.st_mtime < newer_mtime_option
&& (!after_date_option || stat->stat.st_ctime < newer_ctime_option))
{
- if (0 < top_level)
+ if (0 < top_level) /* equivalent to !incremental_option */
WARN ((0, 0, _("%s: file is unchanged; not dumped"),
quotearg_colon (p)));
/* FIXME: recheck this return. */