diff options
-rw-r--r-- | include/tar.h | 1 | ||||
-rw-r--r-- | lib/tar/read_header.c | 19 | ||||
-rw-r--r-- | tests/tar_sparse_gnu.c | 2 |
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); |