On Thursday, June 23, 2016 3:35:51 PM CEST Dominique Martinet wrote: > Does anyone have an opinion on this ?
It is a bug in sparse and --posix (--xatts implies --posix). Have a look at the attached patch which should resolve this. Pavel
>From d2d97a795ab1b5b04f19e9f60d39301e01f7218d Mon Sep 17 00:00:00 2001 From: Pavel Raiskup <prais...@redhat.com> Date: Thu, 30 Jun 2016 15:47:41 +0200 Subject: [PATCH] sparse: fix pax extraction for unicode filenames Make sure that 'GNU.sparse.name' header has higher priority than (for sparse-purposes artificially modified) 'path' pax header. Historically, the 'GNU.sparse.name' header comes before 'path'; this caused that modified 'path' header won and that is not what we want in sparse "capable" tar implementation. * src/tar.h (tar_stat_info): New argument sparse_name_done. * src/xheader.c (raw_path_decoder): Move here the unconditional code from path_decoder. (path_decoder): Apply raw_path_decoder only if sparse_path_decoder was not yet called. (sparse_path_decoder): New wrapper around raw_path_decoder. --- src/tar.h | 4 ++++ src/xheader.c | 28 +++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/tar.h b/src/tar.h index 07b5bc1..f3e2c43 100644 --- a/src/tar.h +++ b/src/tar.h @@ -331,6 +331,10 @@ struct tar_stat_info int real_size_set; /* True when GNU.sparse.realsize is set in archived file */ + bool sparse_name_done; /* Set to true if 'GNU.sparse.name' header was + processed pax header parsing. Following 'path' + header (lower priority) will be ignored. */ + size_t xattr_map_size; /* Size of the xattr map */ struct xattr_array *xattr_map; diff --git a/src/xheader.c b/src/xheader.c index 8dda580..335ddaf 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -1291,16 +1291,34 @@ path_coder (struct tar_stat_info const *st, char const *keyword, } static void -path_decoder (struct tar_stat_info *st, - char const *keyword __attribute__((unused)), - char const *arg, - size_t size __attribute__((unused))) +raw_path_decoder (struct tar_stat_info *st, char const *arg) { decode_string (&st->orig_file_name, arg); decode_string (&st->file_name, arg); st->had_trailing_slash = strip_trailing_slashes (st->file_name); } + +static void +path_decoder (struct tar_stat_info *st, + char const *keyword __attribute__((unused)), + char const *arg, + size_t size __attribute__((unused))) +{ + if (! st->sparse_name_done) + raw_path_decoder (st, arg); +} + +static void +sparse_path_decoder (struct tar_stat_info *st, + char const *keyword __attribute__((unused)), + char const *arg, + size_t size __attribute__((unused))) +{ + st->sparse_name_done = true; + raw_path_decoder (st, arg); +} + static void size_coder (struct tar_stat_info const *st, char const *keyword, struct xheader *xhdr, void const *data __attribute__ ((unused))) @@ -1730,7 +1748,7 @@ struct xhdr_tab const xhdr_tab[] = { { "uname", uname_coder, uname_decoder, 0, false }, /* Sparse file handling */ - { "GNU.sparse.name", path_coder, path_decoder, + { "GNU.sparse.name", path_coder, sparse_path_decoder, XHDR_PROTECTED, false }, { "GNU.sparse.major", sparse_major_coder, sparse_major_decoder, XHDR_PROTECTED, false }, -- 2.7.4