X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fcreate.c;h=065e6fafd511fcb454b891cef56c43a91b4d7bba;hb=7add6e4274e340257433bfba38018b97c32c5321;hp=01324d353bf62d082ab8599f6e5c36b0f6121f9a;hpb=434f2a22ba7a7cbe319aa19026c1f603f3794662;p=chaz%2Ftar diff --git a/src/create.c b/src/create.c index 01324d3..065e6fa 100644 --- a/src/create.c +++ b/src/create.c @@ -1,7 +1,7 @@ /* 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. @@ -186,6 +186,8 @@ to_chars (int negative, uintmax_t value, size_t valsize, { 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); @@ -369,7 +371,7 @@ tar_copy_str (char *dst, const char *src, size_t len) } /* Write a "private" header */ -static union block * +union block * start_private_header (const char *name, size_t size) { time_t t; @@ -532,9 +534,9 @@ write_long_name (struct tar_stat_info *st) } 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; @@ -544,36 +546,10 @@ write_extended (struct tar_stat_info *st, union block *old_header, char type) return old_header; xheader_finish (&extended_header); - size = extended_header.size; - memcpy (hp.buffer, old_header, sizeof (hp)); - - header = start_private_header (p = xheader_xhdr_name (st), size); + p = xheader_xhdr_name (st); + xheader_write (XHDTYPE, p, &extended_header); free (p); - 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); header = find_next_block (); memcpy (header, &hp.buffer, sizeof (hp.buffer)); return header; @@ -582,7 +558,12 @@ write_extended (struct tar_stat_info *st, union block *old_header, char type) 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); @@ -726,13 +707,15 @@ start_header (struct tar_stat_info *st) 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); @@ -741,35 +724,13 @@ start_header (struct tar_stat_info *st) 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; @@ -792,6 +753,37 @@ finish_header (struct tar_stat_info *st, 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) +{ + 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); + simple_finish_header (header); +} void @@ -987,8 +979,8 @@ dump_dir0 (char *directory, 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, @@ -1067,7 +1059,8 @@ create_archive (void) char *p; open_archive (ACCESS_WRITE); - + xheader_write_global (); + if (incremental_option) { size_t buffer_size = 1000; @@ -1307,12 +1300,11 @@ dump_file0 (struct tar_stat_info *stat, char *p, /* 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. */