Hello, In the absence of a better solution, I have applied the following patch:
2007-06-02 Sergey Poznyakoff <[EMAIL PROTECTED]> * src/common.h (xform_type): New data type (transform_member_name): Last argument is of xform_type type. All callers updated * src/extract.c: Update calls to transform_member_name * src/list.c (decode_xform): Symbolic links are exempt from component stripping and name suffix normalization but subject to file name transformation proper. This solution satisfies both the test case provided by MrC, and the one submitted by Morten Welinder (http://lists.gnu.org/archive/html/bug-tar/2007-03/msg00011.html). Regards, Sergey Index: src/common.h =================================================================== RCS file: /cvsroot/tar/tar/src/common.h,v retrieving revision 1.97 diff -p -u -r1.97 common.h --- src/common.h 19 May 2007 17:02:13 -0000 1.97 +++ src/common.h 1 Jun 2007 21:21:33 -0000 @@ -725,7 +725,14 @@ 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; + void set_transform_expr (const char *expr); bool transform_name (char **pinput); -bool transform_member_name (char **pinput, bool lnk); +bool transform_member_name (char **pinput, xform_type type); bool transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *); Index: src/extract.c =================================================================== RCS file: /cvsroot/tar/tar/src/extract.c,v retrieving revision 1.101 diff -p -u -r1.101 extract.c --- src/extract.c 30 Mar 2007 19:18:10 -0000 1.101 +++ src/extract.c 1 Jun 2007 21:21:33 -0000 @@ -917,7 +917,7 @@ extract_link (char *file_name, int typef int interdir_made = 0; char const *link_name; - transform_member_name (¤t_stat_info.link_name, true); + transform_member_name (¤t_stat_info.link_name, xform_link); link_name = current_stat_info.link_name; if (! absolute_names_option && contains_dot_dot (link_name)) @@ -974,7 +974,7 @@ extract_symlink (char *file_name, int ty int status; int interdir_made = 0; - transform_member_name (¤t_stat_info.link_name, true); + transform_member_name (¤t_stat_info.link_name, xform_symlink); if (! absolute_names_option && (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name) Index: src/list.c =================================================================== RCS file: /cvsroot/tar/tar/src/list.c,v retrieving revision 1.104 diff -p -u -r1.104 list.c --- src/list.c 19 May 2007 17:03:28 -0000 1.104 +++ src/list.c 1 Jun 2007 21:21:33 -0000 @@ -472,9 +472,27 @@ read_header (bool raw_extended_headers) static char * decode_xform (char *file_name, void *data) { - bool link_target = *(bool*)data; - file_name = safer_name_suffix (file_name, link_target, - absolute_names_option); + xform_type type = *(xform_type*)data; + + switch (type) + { + 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 + name suffix normalization, but subject to filename transformation + proper. */ + return file_name; + + case xform_link: + file_name = safer_name_suffix (file_name, true, absolute_names_option); + break; + + case xform_regfile: + file_name = safer_name_suffix (file_name, false, absolute_names_option); + break; + } + if (strip_name_components) { size_t prefix_len = stripped_prefix_len (file_name, @@ -487,9 +505,9 @@ decode_xform (char *file_name, void *dat } bool -transform_member_name (char **pinput, bool lnk) +transform_member_name (char **pinput, xform_type type) { - return transform_name_fp (pinput, decode_xform, &lnk); + return transform_name_fp (pinput, decode_xform, &type); } #define ISOCTAL(c) ((c)>='0'&&(c)<='7') @@ -610,7 +628,7 @@ decode_header (union block *header, stru stat_info->is_dumpdir = true; } - transform_member_name (&stat_info->file_name, false); + transform_member_name (&stat_info->file_name, xform_regfile); } /* Convert buffer at WHERE0 of size DIGS from external format to