summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/tar.h1
-rw-r--r--lib/tar/read_header.c19
-rw-r--r--tests/tar_sparse_gnu.c2
3 files changed, 12 insertions, 10 deletions
diff --git a/include/tar.h b/include/tar.h
index 6fdb22d..2819740 100644
--- a/include/tar.h
+++ b/include/tar.h
@@ -72,6 +72,7 @@ typedef struct {
char *name;
char *link_target;
tar_sparse_data_t *sparse;
+ uint64_t sparse_size;
bool unknown_record;
} tar_header_decoded_t;
diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c
index 44a38f9..5d2a808 100644
--- a/lib/tar/read_header.c
+++ b/lib/tar/read_header.c
@@ -613,16 +613,6 @@ int read_header(int fd, tar_header_decoded_t *out)
goto fail;
continue;
case TAR_TYPE_GNU_SPARSE:
- if (!(set_by_pax & PAX_SIZE)) {
- if (read_number(hdr.tail.gnu.realsize,
- sizeof(hdr.tail.gnu.realsize),
- &pax_size))
- goto fail;
-
- out->sb.st_size = pax_size;
- set_by_pax |= PAX_SIZE;
- }
-
free_sparse_list(out->sparse);
out->sparse = read_gnu_old_sparse(fd, &hdr);
if (out->sparse == NULL)
@@ -635,6 +625,15 @@ int read_header(int fd, tar_header_decoded_t *out)
if (decode_header(&hdr, set_by_pax, out, version))
goto fail;
+ if (hdr.typeflag == TAR_TYPE_GNU_SPARSE) {
+ if (read_number(hdr.tail.gnu.realsize,
+ sizeof(hdr.tail.gnu.realsize), &pax_size))
+ goto fail;
+
+ out->sparse_size = out->sb.st_size;
+ out->sb.st_size = pax_size;
+ }
+
return 0;
out_eof:
clear_header(out);
diff --git a/tests/tar_sparse_gnu.c b/tests/tar_sparse_gnu.c
index 2f2e1c5..844f7e3 100644
--- a/tests/tar_sparse_gnu.c
+++ b/tests/tar_sparse_gnu.c
@@ -40,6 +40,7 @@ int main(void)
assert(hdr.sb.st_uid == 01750);
assert(hdr.sb.st_gid == 01750);
assert(hdr.sb.st_size == 524288);
+ assert(hdr.sparse_size == 8192);
assert(strcmp(hdr.name, "input.bin") == 0);
assert(!hdr.unknown_record);
@@ -69,6 +70,7 @@ int main(void)
assert(hdr.sb.st_uid == 01750);
assert(hdr.sb.st_gid == 01750);
assert(hdr.sb.st_size == 2097152);
+ assert(hdr.sparse_size == 32768);
assert(strcmp(hdr.name, "input.bin") == 0);
assert(!hdr.unknown_record);