From 57bfbbde90dfcc18ee6b1e27c01ba915ecc56312 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Thu, 16 Oct 2008 11:07:19 +0000 Subject: [PATCH] * src/common.h (transform_symlinks_option): New global. * src/create.c (dump_file0): Transform symlink targets only if explicitly required. Thanks Cyril Strejc for reporting the problem. * src/tar.c (parse_opt): New options --transform-symlinks and --no-transform-symlinks. New alias --xform to the --transform option. * doc/tar.texi: Document --transform-symlinks * NEWS: Update. * THANKS: Update. * src/names.c (name_gather): Use xzalloc. * src/buffer.c (short_read): Move record size detection before the loop. --- ChangeLog | 17 ++++++++++++++ NEWS | 12 +++++++++- THANKS | 1 + doc/tar.texi | 64 ++++++++++++++++++++++++++++++++++++++++++++++---- lib/.cvsignore | 6 +++++ src/buffer.c | 28 ++++++++++------------ src/common.h | 3 +++ src/create.c | 3 ++- src/names.c | 4 +--- src/tar.c | 21 +++++++++++++++++ 10 files changed, 134 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index e74930b..4e74e8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2008-10-16 Sergey Poznyakoff + + * src/common.h (transform_symlinks_option): New global. + * src/create.c (dump_file0): Transform symlink targets only if + explicitly required. Thanks Cyril Strejc for reporting the + problem. + * src/tar.c (parse_opt): New options --transform-symlinks and + --no-transform-symlinks. New alias --xform to the --transform + option. + * doc/tar.texi: Document --transform-symlinks + * NEWS: Update. + * THANKS: Update. + + * src/names.c (name_gather): Use xzalloc. + * src/buffer.c (short_read): Move record size detection before + the loop. + 2008-10-07 Sergey Poznyakoff * src/tar.c (options): Add --lzop option. diff --git a/NEWS b/NEWS index 5767601..a55eb34 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -GNU tar NEWS - User visible changes. 2008-09-24 +GNU tar NEWS - User visible changes. 2008-10-16 Please send GNU tar bug reports to @@ -28,6 +28,16 @@ back to using archive suffix to determine it. Using --exclude-vcs handles also files used internally by Bazaar, Mercurial and Darcs. +* The --transform-symlink option. + +The effect of the --transform option on the symbolic links targets is +controlled by --transform-symlink and --no-transform-symlink options. +By default, transformations do not apply to symlink targets, +which corresponds to the behavior of version 1.19. To apply +transformations to symlink targets as well, use --transform-symlink +option. The --no-transform-symlink option cancels the effect of any +prior --transform-symlink. + * Bugfixes ** The --null option disabled handling of tar options in list files. This diff --git a/THANKS b/THANKS index 0c2495c..986b1af 100644 --- a/THANKS +++ b/THANKS @@ -102,6 +102,7 @@ Clinton Carr clint@netcom.com Conrad Hughes chughes@maths.tcd.ie Constantin Belous const@cris.net Coranth Gryphon gryphon@bur.visidyne.com +Cyril Strejc strejc@unicontrols.cz Dale R. Worley worley@world.std.com Dale Wiles wiles@geordi.calspan.com Dan Bloch dan@transarc.com diff --git a/doc/tar.texi b/doc/tar.texi index f86f077..43970ad 100644 --- a/doc/tar.texi +++ b/doc/tar.texi @@ -2905,6 +2905,13 @@ characters set by the previous @option{--quote-chars} option With this option, @command{tar} will not recurse into directories. @xref{recurse}. +@opsummary{no-transform-symlinks} +@item --no-transform-symlinks +Cancel the effect of any prior @command{--transform-symlinks} option +(see below) and return to the default behavior of applying name +transformation expression only to the names of files (archive +members), not to target of symbolic links. + @opsummary{no-same-owner} @item --no-same-owner @itemx -o @@ -3266,8 +3273,9 @@ rather than the data modification time stored in the archive. @xref{Data Modification Times}. @opsummary{transform} +@opsummary{xform} @item --transform=@var{sed-expr} - +@itemx --xform=@var{sed-expr} Transform file or member names using @command{sed} replacement expression @var{sed-expr}. For example, @@ -3284,6 +3292,11 @@ To see transformed member names in verbose listings, use @option{--show-transformed-names} option (@pxref{show-transformed-names}). +@opsummary{transform-symlinks} +@item --transform-symlinks +Apply @command{--transform} option to symbolic link targets +(@pxref{transform}). + @opsummary{uncompress} @item --uncompress @@ -7553,7 +7566,7 @@ characters that are quoted by default in the selected quoting style. @command{Tar} archives contain detailed information about files stored in them and full file names are part of that information. When -storing file to an archive, its file name is recorded in the archive +storing file to an archive, its file name is recorded in it, along with the actual file contents. When restoring from an archive, a file is created on disk with exactly the same name as that stored in the archive. In the majority of cases this is the desired behavior @@ -7570,7 +7583,7 @@ directory components, or with otherwise modified names. In other cases it is desirable to store files under differing names in the archive. -@GNUTAR{} provides two options for these needs. +@GNUTAR{} provides several options for these needs. @table @option @opindex strip-components @@ -7644,7 +7657,9 @@ In case you need to apply more complex modifications to the file name, @table @option @opindex transform +@opindex xform @item --transform=@var{expression} +@itemx --xform=@var{expression} Modify file names using supplied @var{expression}. @end table @@ -7683,7 +7698,7 @@ sed, GNU sed}). @item @var{number} Only replace the @var{number}th match of the @var{regexp}. -Note: the @var{posix} standard does not specify what should happen +Note: the @acronym{POSIX} standard does not specify what should happen when you mix the @samp{g} and @var{number} modifiers. @GNUTAR{} follows the GNU @command{sed} implementation in this regard, so the interaction is defined to be: ignore matches before the @@ -7737,6 +7752,47 @@ $ @kbd{tar --transform 's/.*/\L&/' -x -f arch.tar} @end enumerate +The @option{--transform} option applies only to member names. It does +not apply to symbolic link targets. In many cases, this is the +desired behavior. Consider for example, archiving the @file{/lib} +directory: + +@smallexample +$ @kbd{tar -vv -c -f archive /lib} +tar: Removing leading `/' from member names +drwxr-xr-x root/root 0 2008-07-08 16:20 /lib/ +-rwxr-xr-x root/root 1250840 2008-05-25 07:44 /lib/libc-2.3.2.so +lrwxrwxrwx root/root 0 2008-06-24 17:12 /lib/libc.so.6 -> libc-2.3.2.so +... +@end smallexample + +Now, you can use our example above to extract it into @file{/usr/local}: + +@smallexample +$ @kbd{tar --transform 's,^,/usr/local/,' \ + --show-transformed -v -x -f archive} +drwxr-xr-x root/root 0 2008-07-08 16:20 /usr/local/lib/ +-rwxr-xr-x root/root 1250840 2008-05-25 07:44 /usr/local/lib/libc-2.3.2.so +lrwxrwxrwx root/root 0 2008-06-24 17:12 /usr/local/lib/libc.so.6 -> +libc-2.3.2.so +@end smallexample + +As you see, it correctly extracts @file{libc.so.6} as a symbolic link +to @file{libc-2.3.2.so}. + +However, sometimes you may need to transform symbolic link targets as +well. To do so, @GNUTAR provides an additional option: + +@table @option +@opindex transform-symlinks +@item --transform-symlinks +Apply @command{--transform} option to symbolic link targets. + +@opindex no-transform-symlinks +@itemx --no-transform-symlinks +Cancel the effect of the previous @option{--transform-symlinks} option. +@end table + Unlike @option{--strip-components}, @option{--transform} can be used in any @GNUTAR{} operation mode. For example, the following command adds files to the archive while replacing the leading @file{usr/} diff --git a/lib/.cvsignore b/lib/.cvsignore index eb46334..9173507 100644 --- a/lib/.cvsignore +++ b/lib/.cvsignore @@ -25,6 +25,8 @@ at-func.c backupfile.c backupfile.h basename.c +c-ctype.c +c-ctype.h canonicalize-lgpl.c canonicalize.h charset.alias @@ -46,6 +48,7 @@ dirname.c dirname.h dup-safer.c dup2.c +errno.in.h error.c error.h exclude.c @@ -130,6 +133,7 @@ obstack.c obstack.h offtostr.c open-safer.c +open.c openat-die.c openat-priv.h openat-proc.c @@ -189,6 +193,7 @@ stdbool.in.h stdint.h stdint.in.h stdio-impl.h +stdio-write.c stdio.h stdio.in.h stdlib.h @@ -258,6 +263,7 @@ wchar.in.h wctype.h wctype.in.h wcwidth.c +write.c xalloc-die.c xalloc.h xgetcwd.c diff --git a/src/buffer.c b/src/buffer.c index c544ee0..79bb7d6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -686,6 +686,18 @@ short_read (size_t status) more = record_start->buffer + status; left = record_size - status; + if (left && left % BLOCKSIZE == 0 + && !read_full_records && verbose_option > 1 + && record_start_block == 0 && status != 0) + { + unsigned long rsize = status / BLOCKSIZE; + WARN ((0, 0, + ngettext ("Record size = %lu block", + "Record size = %lu blocks", + rsize), + rsize)); + } + while (left % BLOCKSIZE != 0 || (left && status && read_full_records)) { @@ -707,26 +719,10 @@ short_read (size_t status) rest)); } - /* User warned us about this. Fix up. */ - left -= status; more += status; } - /* FIXME: for size=0, multi-volume support. On the first record, warn - about the problem. */ - - if (!read_full_records && verbose_option > 1 - && record_start_block == 0 && status != 0) - { - unsigned long rsize = (record_size - left) / BLOCKSIZE; - WARN ((0, 0, - ngettext ("Record size = %lu block", - "Record size = %lu blocks", - rsize), - rsize)); - } - record_end = record_start + (record_size - left) / BLOCKSIZE; records_read++; } diff --git a/src/common.h b/src/common.h index 91ae10c..947546a 100644 --- a/src/common.h +++ b/src/common.h @@ -346,6 +346,9 @@ GLOBAL bool unquote_option; GLOBAL bool test_label_option; /* Test archive volume label and exit */ +/* Apply transformations to symlink targets as well. */ +GLOBAL bool transform_symlinks_option; + /* Show file or archive names after transformation. In particular, when creating archive in verbose mode, list member names as stored in the archive */ diff --git a/src/create.c b/src/create.c index fc26f1e..7b20c02 100644 --- a/src/create.c +++ b/src/create.c @@ -1705,7 +1705,8 @@ dump_file0 (struct tar_stat_info *st, const char *p, } buffer[size] = '\0'; assign_string (&st->link_name, buffer); - transform_name (&st->link_name); + if (transform_symlinks_option) + transform_name (&st->link_name); if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size) write_long_link (st); diff --git a/src/names.c b/src/names.c index 0c3aebf..05f89b1 100644 --- a/src/names.c +++ b/src/names.c @@ -388,9 +388,7 @@ name_gather (void) if (allocated_size == 0) { allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1; - buffer = xmalloc (allocated_size); - /* FIXME: This memset is overkill, and ugly... */ - memset (buffer, 0, allocated_size); + buffer = xzalloc (allocated_size); } while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR) diff --git a/src/tar.c b/src/tar.c index c2ead13..1b9ffce 100644 --- a/src/tar.c +++ b/src/tar.c @@ -287,6 +287,7 @@ enum NO_RECURSION_OPTION, NO_SAME_OWNER_OPTION, NO_SAME_PERMISSIONS_OPTION, + NO_TRANSFORM_SYMLINKS_OPTION, NO_UNQUOTE_OPTION, NO_WILDCARDS_MATCH_SLASH_OPTION, NO_WILDCARDS_OPTION, @@ -321,6 +322,7 @@ enum TOTALS_OPTION, TO_COMMAND_OPTION, TRANSFORM_OPTION, + TRANSFORM_SYMLINKS_OPTION, UNQUOTE_OPTION, USAGE_OPTION, USE_COMPRESS_PROGRAM_OPTION, @@ -686,6 +688,11 @@ static struct argp_option options[] = { GRID+1 }, {"transform", TRANSFORM_OPTION, N_("EXPRESSION"), 0, N_("use sed replace EXPRESSION to transform file names"), GRID+1 }, + {"xform", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, + {"transform-symlinks", TRANSFORM_SYMLINKS_OPTION, NULL, 0, + N_("apply transformations to symlink targets"), GRID+1 }, + {"no-transform-symlinks", NO_TRANSFORM_SYMLINKS_OPTION, NULL, 0, + N_("cancel effect of the previous --transform-symlinks option"), GRID+1 }, #undef GRID #define GRID 120 @@ -1819,6 +1826,8 @@ parse_opt (int key, char *arg, struct argp_state *state) /* FIXME: What it is good for? */ same_permissions_option = true; same_order_option = true; + WARN ((0, 0, _("The --preserve option is deprecated, " + "use --preserve-permissions --preserve-order instead"))); break; case RECORD_SIZE_OPTION: @@ -1902,6 +1911,14 @@ parse_opt (int key, char *arg, struct argp_state *state) set_transform_expr (arg); break; + case TRANSFORM_SYMLINKS_OPTION: + transform_symlinks_option = true; + break; + + case NO_TRANSFORM_SYMLINKS_OPTION: + transform_symlinks_option = false; + break; + case USE_COMPRESS_PROGRAM_OPTION: set_use_compress_program_option (arg); break; @@ -2345,6 +2362,10 @@ decode_options (int argc, char **argv) if (tape_length_option && tape_length_option < record_size) USAGE_ERROR ((0, 0, _("Volume length cannot be less than record size"))); + + if (same_order_option && listed_incremental_option) + USAGE_ERROR ((0, 0, _("--preserve-order is not compatible with " + "--listed-incremental"))); /* Forbid using -c with no input files whatsoever. Check that `-f -', explicit or implied, is used correctly. */ -- 2.44.0