X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=inline;f=src%2Fcreate.c;h=a46b1162cc571109bab0c051d1cb033e09b38f9e;hb=be48ff0699a4ea9229ebe9e32eab39d125ecf39b;hp=b6a4f52624291baf03cb996a39b3b2d3d8471536;hpb=f7ce5a4ec57028be0bdea6d45dce8fe1c23ec668;p=chaz%2Ftar diff --git a/src/create.c b/src/create.c index b6a4f52..a46b116 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; @@ -517,7 +519,16 @@ write_long_name (struct tar_stat_info *st) 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); @@ -532,9 +543,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,35 +555,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 ("././@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; @@ -581,7 +567,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); @@ -686,7 +677,7 @@ start_header (struct tar_stat_info *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); @@ -725,13 +716,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); @@ -740,35 +733,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; @@ -791,6 +762,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 @@ -981,11 +983,13 @@ dump_dir0 (char *directory, return; } } - else if (!recursion_option) + + if (!recursion_option) return; - else if (one_file_system_option - && !top_level - && parent_device != stat->stat.st_dev) + + if (one_file_system_option + && !top_level + && parent_device != stat->stat.st_dev) { if (verbose_option) WARN ((0, 0, @@ -1064,7 +1068,8 @@ create_archive (void) char *p; open_archive (ACCESS_WRITE); - + xheader_write_global (); + if (incremental_option) { size_t buffer_size = 1000; @@ -1179,7 +1184,7 @@ dump_hard_link (struct tar_stat_info *stat) if ((dup = hash_lookup (link_table, &lp))) { /* We found a link. */ - char const *link_name = safer_name_suffix (dup->name, 1); + char const *link_name = safer_name_suffix (dup->name, true); dup->nlink--; @@ -1275,7 +1280,7 @@ dump_file0 (struct tar_stat_info *stat, char *p, return; assign_string (&stat->orig_file_name, p); - assign_string (&stat->file_name, safer_name_suffix (p, 0)); + assign_string (&stat->file_name, safer_name_suffix (p, false)); if (deref_stat (dereference_option, p, &stat->stat) != 0) { @@ -1304,12 +1309,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. */