tar/tar-1.28-big-sparse-listing.patch
2014-07-28 10:10:16 +02:00

124 lines
4.1 KiB
Diff

From 6400976234810f4de138ee692756072f5beaa64d Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <praiskup@redhat.com>
Date: Mon, 28 Jul 2014 08:18:53 +0200
Subject: [PATCH 9/9] --posix & big (effective) sparse files can not be listed
Upstram bugreports (still downstream):
http://www.mail-archive.com/bug-tar%40gnu.org/msg03909.html
http://www.mail-archive.com/bug-tar@gnu.org/msg04489.html
Related: #916995
---
src/list.c | 1 -
src/sparse.c | 4 ++--
src/tar.h | 4 ++++
src/xheader.c | 28 +++++++++++++++++++++++++++-
4 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/src/list.c b/src/list.c
index 0c7a740..ce9ce4b 100644
--- a/src/list.c
+++ b/src/list.c
@@ -700,7 +700,6 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
}
}
- stat_info->archive_file_size = stat_info->stat.st_size;
xheader_decode (stat_info);
if (sparse_member_p (stat_info))
diff --git a/src/sparse.c b/src/sparse.c
index 53c1868..c8bec6b 100644
--- a/src/sparse.c
+++ b/src/sparse.c
@@ -892,7 +892,7 @@ static struct tar_sparse_optab const star_optab = {
* 1.0
Starting from this version, the exact sparse format version is specified
- explicitely in the header using the following variables:
+ explicitly in the header using the following variables:
GNU.sparse.major Major version
GNU.sparse.minor Minor version
@@ -921,7 +921,7 @@ static struct tar_sparse_optab const star_optab = {
directory. Then, using a simple program it would be possible to expand the
file to its original form even without GNU tar.
- Bu default, v.1.0 archives are created. To use other formats,
+ By default, v.1.0 archives are created. To use other formats,
--sparse-version option is provided. Additionally, v.0.0 can be obtained
by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
--pax-option delete=GNU.sparse.map
diff --git a/src/tar.h b/src/tar.h
index 3d69399..73cd11e 100644
--- a/src/tar.h
+++ b/src/tar.h
@@ -327,6 +327,10 @@ struct tar_stat_info
size_t sparse_map_size; /* Size of the sparse map */
struct sp_array *sparse_map;
+ off_t real_size; /* The real size of sparse file */
+ int real_size_set; /* True when GNU.sparse.realsize is set in
+ archived file */
+
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 c94c6d3..0be83a4 100644
--- a/src/xheader.c
+++ b/src/xheader.c
@@ -742,6 +742,20 @@ decx (void *data, char const *keyword, char const *value, size_t size)
keyword));
}
+static void
+xheader_fixup_file_size (struct tar_stat_info *st)
+{
+ /* The effective size is in st_size, regardless of whether the file is sparse
+ * or not. */
+ st->archive_file_size = st->stat.st_size;
+
+ /* For non-sparse files we are done (effective size == real size). But for
+ sparse files we must take the GNU.sparse.realsize header into account (if
+ present, its content was parsed by sparse_size_decoder already. */
+ if (st->real_size_set)
+ st->stat.st_size = st->real_size;
+}
+
void
xheader_decode (struct tar_stat_info *st)
{
@@ -755,6 +769,11 @@ xheader_decode (struct tar_stat_info *st)
continue;
}
run_override_list (keyword_override_list, st);
+
+ /* Here we know for sure that we have "effective" size stored into
+ st->stat->st_size (this may be set by read_header directly from regular pax
+ header, or overwritten by size_decoder() from extended pax header). */
+ xheader_fixup_file_size (st);
}
static void
@@ -1360,7 +1379,14 @@ sparse_size_decoder (struct tar_stat_info *st,
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
- st->stat.st_size = u;
+ {
+ /* do not set the st->stat.st_size here immediately because there may be
+ the 'size' extended header following 'GNU.sparse.realsize' which would
+ override our setup. We must handle size (and real size) of sparse
+ files once whole xheader is read */
+ st->real_size_set = 1;
+ st->real_size = u;
+ }
}
static void
--
1.9.3