* NEWS, configure.ac: Version 1.20.91

* doc/tar.texi: Document transformation scope flags.
* src/common.h (transform_symlinks_option): Remove in favor of
transformation scope flags.
(XFORM_REGFILE, XFORM_LINK, XFORM_SYMLINK, XFORM_ALL): New macros.
(transform_name, transform_member_name, transform_name_fp): Take
an additional argument, specifying scope flags.
* src/create.c: Reflect changes to transform_name.
* src/extract.c (extract_link, extract_symlink): Remove calls to
transform_member_name. It is done in read_header.
* src/list.c (decode_xform): Reflect change in data type of 2nd
argument.
(transform_member_name): 2nd arg is int.
(decode_header): Transform file name and link target names.
* src/tar.c: Remove --transform-symlinks.
* src/transform.c (struct transform): New member `flags'.
(transform_flags): New variable.
(parse_transform_expr): Parse transformation scope flags. Allow to
set global flags using `flags=' syntax.
(_transform_name_to_obstack, transform_name_fp)
(transform_name): Take an additional argument, specifying scope
flags.
This commit is contained in:
Sergey Poznyakoff 2008-10-30 14:13:01 +00:00
parent 5354888e40
commit b4ec8aedf9
11 changed files with 242 additions and 124 deletions

View File

@ -1,3 +1,28 @@
2008-10-30 Sergey Poznyakoff <gray@gnu.org.ua>
* NEWS, configure.ac: Version 1.20.91
* doc/tar.texi: Document transformation scope flags.
* src/common.h (transform_symlinks_option): Remove in favor of
transformation scope flags.
(XFORM_REGFILE, XFORM_LINK, XFORM_SYMLINK, XFORM_ALL): New macros.
(transform_name, transform_member_name, transform_name_fp): Take
an additional argument, specifying scope flags.
* src/create.c: Reflect changes to transform_name.
* src/extract.c (extract_link, extract_symlink): Remove calls to
transform_member_name. It is done in read_header.
* src/list.c (decode_xform): Reflect change in data type of 2nd
argument.
(transform_member_name): 2nd arg is int.
(decode_header): Transform file name and link target names.
* src/tar.c: Remove --transform-symlinks.
* src/transform.c (struct transform): New member `flags'.
(transform_flags): New variable.
(parse_transform_expr): Parse transformation scope flags. Allow to
set global flags using `flags=' syntax.
(_transform_name_to_obstack, transform_name_fp)
(transform_name): Take an additional argument, specifying scope
flags.
2008-10-19 Sergey Poznyakoff <gray@gnu.org.ua>
* THANKS: Add Ed Leaver.

41
NEWS
View File

@ -1,8 +1,8 @@
GNU tar NEWS - User visible changes. 2008-10-22
GNU tar NEWS - User visible changes. 2008-10-30
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.20.90 (CVS)
version 1.20.91 (CVS)
* New short option -J
@ -28,21 +28,40 @@ 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.
* Transformation scope flags
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.
Name transformation expressions understand additional flags that
control type of archive members affected by them. The flags are:
- r
Apply transformation to regular archive members.
- s
Apply transformation to symbolic link targets.
- h
Apply transformation to hard link targets.
Corresponding upper-case letters negate the flag meaning, so that
`H' means ``do not apply transformation to hard link targets.''
The scope flags are listed in the third part of an `s' expression,
e.g.:
tar --transform 's|^|/usr/local/|S'
Default is `rsh', which means that transformations are applied to
both regular archive members and to the targets of symbolic and hard
links. If several transform expressions are used, the default flags
can be changed using `flags=' statement before the expressions, e.g.:
tar --transform 'flags=S;s|^|/usr/local/|S'
* Bugfixes
** The --null option disabled handling of tar options in list files. This
is fixed.
** Fixed record size autodetection. If the detected record size differs from
** Fixed record size autodetection. If detected record size differs from
the expected value (either default, or set on the command line), tar
always prints a warning if verbosity level is set to 1 or greater,
i.e. if either -t or -v option is given.

View File

@ -18,7 +18,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
AC_INIT([GNU tar], [1.20.90], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.20.91], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h:config.hin])

View File

@ -2905,13 +2905,6 @@ 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
@ -3292,11 +3285,6 @@ 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
@ -7605,8 +7593,8 @@ The option @option{--strip=2} instructs @command{tar} to strip the
two leading components (@file{usr/} and @file{include/}) off the file
name.
If you add to the above invocation @option{--verbose} (@option{-v})
option, you will note that the verbose listing still contains the
If you add the @option{--verbose} (@option{-v}) option to the invocation
above, you will note that the verbose listing still contains the
full file name, with the two removed components still in place. This
can be inconvenient, so @command{tar} provides a special option for
altering this behavior:
@ -7631,7 +7619,7 @@ stdlib.h
@end group
@end smallexample
Notice that in both cases the file is @file{stdlib.h} extracted to the
Notice that in both cases the file @file{stdlib.h} is extracted to the
current working directory, @option{--show-transformed-names} affects
only the way its name is displayed.
@ -7677,6 +7665,21 @@ replacement for each file name part that matches @var{regexp}. Both
@var{regexp} and @var{replace} are described in detail in
@ref{The "s" Command, The "s" Command, The `s' Command, sed, GNU sed}.
Any delimiter can be used in lieue of @samp{/}, the only requirement being
that it be used consistently throughout the expression. For example,
the following two expressions are equivalent:
@smallexample
@group
s/one/two/
s,one,two,
@end group
@end smallexample
Changing delimiters is often useful when the @var{regex} contains
slashes. For example, it is more convenient to write @code{s,/,-,} than
@code{s/\//-/}.
As in @command{sed}, you can give several replace expressions,
separated by a semicolon.
@ -7707,21 +7710,41 @@ the interaction is defined to be: ignore matches before the
@end table
Any delimiter can be used in lieue of @samp{/}, the only requirement being
that it be used consistently throughout the expression. For example,
the following two expressions are equivalent:
In addition, several @dfn{transformation scope} flags are supported,
that control to what files transformations apply. These are:
@table @samp
@item r
Apply transformation to regular archive members.
@item R
Do not apply transformation to regular archive members.
@item s
Apply transformation to symbolic link targets.
@item S
Do not apply transformation to symbolic link targets.
@item h
Apply transformation to hard link targets.
@item H
Do not apply transformation to hard link targets.
@end table
Default is @samp{rsh}, which means to apply tranformations to both archive
members and targets of symbolic and hard links.
Default scope flags can also be changed using @samp{flags=} statement
in the transform expression. The flags set this way remain in force
until next @samp{flags=} statement or end of expression, whichever
occurs first. For example:
@smallexample
@group
s/one/two/
s,one,two,
@end group
--transform 'flags=S;s|^|/usr/local/|'
@end smallexample
Changing delimiters is often useful when the @var{regex} contains
slashes. For example, it is more convenient to write @code{s,/,-,} than
@code{s/\//-/}.
Here are several examples of @option{--transform} usage:
@enumerate
@ -7738,61 +7761,59 @@ $ @kbd{tar --transform='s,usr/,usr/local/,' -x -f arch.tar}
$ @kbd{tar --transform='s,/*[^/]*/[^/]*/,,' -x -f arch.tar}
@end smallexample
@item Prepend @file{/prefix/} to each file name:
@smallexample
$ @kbd{tar --transform 's,^,/prefix/,' -x -f arch.tar}
@end smallexample
@item Convert each file name to lower case:
@smallexample
$ @kbd{tar --transform 's/.*/\L&/' -x -f arch.tar}
@end smallexample
@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:
@item Prepend @file{/prefix/} to each file name:
@smallexample
$ @kbd{tar -vv -c -f archive /lib}
tar: Removing leading `/' from member names
$ @kbd{tar --transform 's,^,/prefix/,' -x -f arch.tar}
@end smallexample
@item Archive the @file{/lib} directory, prepending @samp{/usr/local}
to each archive member:
@smallexample
$ @kbd{tar --transform 's,^,/usr/local/,S' -c -f arch.tar /lib}
@end smallexample
@end enumerate
Notice the use of flags in the last example. The @file{/lib}
directory often contains many symbolic links to files within it.
It may look, for example, like this:
@smallexample
$ @kbd{ls -l}
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}:
Using the expression @samp{s,^,/usr/local/,} would mean adding
@samp{/usr/local} to both regular archive members and to link
targets. In this case, @file{/lib/libc.so.6} would become:
@smallexample
$ @kbd{tar --transform 's,^,/usr/local/,' \
--show-transformed -v -x -f archive}
/usr/local/lib/libc.so.6 -> /usr/local/libc-2.3.2.so
@end smallexample
This is definitely not desired. To avoid this, the @samp{S} flag
are used, which excludes symbolic link targets from filename
transformations. The result is:
@smallexample
$ @kbd{tar --transform 's,^,/usr/local/,S', -c -v -f arch.tar \
--show-transformed /lib}
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/}

View File

@ -35,6 +35,7 @@ chdir-long.h
chown.c
close-stream.c
close-stream.h
close.c
closeout.c
closeout.h
config.charset
@ -59,6 +60,7 @@ fchdir.c
fchmodat.c
fchown-stub.c
fchownat.c
fclose.c
fcntl--.h
fcntl-safer.h
fcntl.h

View File

@ -346,9 +346,6 @@ 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 */
@ -738,17 +735,16 @@ bool string_ascii_p (const char *str);
bool utf8_convert (bool to_utf, char const *input, char **output);
/* Module transform.c */
typedef enum
{
xform_regfile,
xform_link,
xform_symlink
} xform_type;
#define XFORM_REGFILE 0x01
#define XFORM_LINK 0x02
#define XFORM_SYMLINK 0x04
#define XFORM_ALL (XFORM_REGFILE|XFORM_LINK|XFORM_SYMLINK)
void set_transform_expr (const char *expr);
bool transform_name (char **pinput);
bool transform_member_name (char **pinput, xform_type type);
bool transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *);
bool transform_name (char **pinput, int type);
bool transform_member_name (char **pinput, int type);
bool transform_name_fp (char **pinput, int type,
char *(*fun)(char *, void *), void *);
/* Module suffix.c */
void set_comression_program_by_suffix (const char *name, const char *defprog);

View File

@ -1495,7 +1495,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
assign_string (&st->file_name,
safer_name_suffix (p, false, absolute_names_option));
transform_name (&st->file_name);
transform_name (&st->file_name, XFORM_REGFILE);
if (deref_stat (dereference_option, p, &st->stat) != 0)
{
@ -1705,8 +1705,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
}
buffer[size] = '\0';
assign_string (&st->link_name, buffer);
if (transform_symlinks_option)
transform_name (&st->link_name);
transform_name (&st->link_name, XFORM_SYMLINK);
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
write_long_link (st);

View File

@ -917,7 +917,6 @@ extract_link (char *file_name, int typeflag)
int interdir_made = 0;
char const *link_name;
transform_member_name (&current_stat_info.link_name, xform_link);
link_name = current_stat_info.link_name;
if (! absolute_names_option && contains_dot_dot (link_name))
@ -974,8 +973,6 @@ extract_symlink (char *file_name, int typeflag)
int status;
int interdir_made = 0;
transform_member_name (&current_stat_info.link_name, xform_symlink);
if (! absolute_names_option
&& (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
|| contains_dot_dot (current_stat_info.link_name)))

View File

@ -472,11 +472,11 @@ read_header (bool raw_extended_headers)
static char *
decode_xform (char *file_name, void *data)
{
xform_type type = *(xform_type*)data;
int type = *(int*)data;
switch (type)
{
case xform_symlink:
case XFORM_SYMLINK:
/* FIXME: It is not quite clear how and to which extent are the symbolic
links subject to filename transformation. In the absence of another
solution, symbolic links are exempt from component stripping and
@ -484,11 +484,11 @@ decode_xform (char *file_name, void *data)
proper. */
return file_name;
case xform_link:
case XFORM_LINK:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case xform_regfile:
case XFORM_REGFILE:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
@ -505,9 +505,9 @@ decode_xform (char *file_name, void *data)
}
bool
transform_member_name (char **pinput, xform_type type)
transform_member_name (char **pinput, int type)
{
return transform_name_fp (pinput, decode_xform, &type);
return transform_name_fp (pinput, type, decode_xform, &type);
}
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
@ -628,7 +628,16 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
stat_info->is_dumpdir = true;
}
transform_member_name (&stat_info->file_name, xform_regfile);
transform_member_name (&stat_info->file_name, XFORM_REGFILE);
switch (header->header.typeflag)
{
case SYMTYPE:
transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
break;
case LNKTYPE:
transform_member_name (&stat_info->link_name, XFORM_LINK);
}
}
/* Convert buffer at WHERE0 of size DIGS from external format to

View File

@ -287,7 +287,6 @@ 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,
@ -322,7 +321,6 @@ enum
TOTALS_OPTION,
TO_COMMAND_OPTION,
TRANSFORM_OPTION,
TRANSFORM_SYMLINKS_OPTION,
UNQUOTE_OPTION,
USAGE_OPTION,
USE_COMPRESS_PROGRAM_OPTION,
@ -689,10 +687,6 @@ static struct argp_option options[] = {
{"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
@ -1911,14 +1905,6 @@ 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;

View File

@ -61,6 +61,7 @@ struct transform
{
struct transform *next;
enum transform_type transform_type;
int flags;
unsigned match_number;
regex_t regex;
/* Compiled replacement expression */
@ -69,6 +70,8 @@ struct transform
};
int transform_flags = XFORM_ALL;
static struct transform *transform_head, *transform_tail;
static struct transform *
@ -131,6 +134,41 @@ add_backref_segment (struct transform *tf, size_t ref)
segm->v.ref = ref;
}
static int
parse_xform_flags (int *pflags, int c)
{
switch (c)
{
case 'r':
*pflags |= XFORM_REGFILE;
break;
case 'R':
*pflags &= ~XFORM_REGFILE;
break;
case 'h':
*pflags |= XFORM_LINK;
break;
case 'H':
*pflags &= ~XFORM_LINK;
break;
case 's':
*pflags |= XFORM_SYMLINK;
break;
case 'S':
*pflags &= ~XFORM_SYMLINK;
break;
default:
return 1;
}
return 0;
}
static void
add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
{
@ -150,8 +188,26 @@ parse_transform_expr (const char *expr)
struct transform *tf = new_transform ();
if (expr[0] != 's')
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
{
if (strncmp (expr, "flags=", 6) == 0)
{
transform_flags = 0;
for (expr += 6; *expr; expr++)
{
if (*expr == ';')
{
expr++;
break;
}
if (parse_xform_flags (&transform_flags, *expr))
USAGE_ERROR ((0, 0, _("Unknown transform flag: %c"),
*expr));
}
return expr;
}
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
}
delim = expr[1];
/* Scan regular expression */
@ -172,6 +228,7 @@ parse_transform_expr (const char *expr)
/* Check flags */
tf->transform_type = transform_first;
tf->flags = transform_flags;
for (p = expr + j + 1; *p && *p != ';'; p++)
switch (*p)
{
@ -186,7 +243,7 @@ parse_transform_expr (const char *expr)
case 'x':
cflags |= REG_EXTENDED;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
tf->match_number = strtoul (p, (char**) &p, 0);
@ -194,8 +251,9 @@ parse_transform_expr (const char *expr)
break;
default:
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression: %c"),
*p));
if (parse_xform_flags (&tf->flags, *p))
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression: %c"),
*p));
}
if (*p == ';')
@ -520,10 +578,11 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
}
bool
_transform_name_to_obstack (char *input, char **output)
_transform_name_to_obstack (int flags, char *input, char **output)
{
struct transform *tf;
bool alloced = false;
if (!stk_init)
{
obstack_init (&stk);
@ -532,18 +591,23 @@ _transform_name_to_obstack (char *input, char **output)
for (tf = transform_head; tf; tf = tf->next)
{
_single_transform_name_to_obstack (tf, input);
input = obstack_finish (&stk);
if (tf->flags & flags)
{
_single_transform_name_to_obstack (tf, input);
input = obstack_finish (&stk);
alloced = true;
}
}
*output = input;
return transform_head != NULL;
return alloced;
}
bool
transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
transform_name_fp (char **pinput, int flags,
char *(*fun)(char *, void *), void *dat)
{
char *str;
bool ret = _transform_name_to_obstack (*pinput, &str);
bool ret = _transform_name_to_obstack (flags, *pinput, &str);
if (ret)
{
assign_string (pinput, fun ? fun (str, dat) : str);
@ -560,8 +624,8 @@ transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
}
bool
transform_name (char **pinput)
transform_name (char **pinput, int type)
{
return transform_name_fp (pinput, NULL, NULL);
return transform_name_fp (pinput, type, NULL, NULL);
}