summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-10-24 04:01:31 +0000
committerkientzle <kientzle@FreeBSD.org>2007-10-24 04:01:31 +0000
commit9bc0f4c6a443721979818bca4ed522cc2dcb24f3 (patch)
treeba01a085d3a3ef352e66b78f332e2c5578188226 /lib
parent2b44eb1afe7b7a4139e16f9faf1a0937db4de771 (diff)
downloadFreeBSD-src-9bc0f4c6a443721979818bca4ed522cc2dcb24f3.zip
FreeBSD-src-9bc0f4c6a443721979818bca4ed522cc2dcb24f3.tar.gz
Fix reading of files that use pax 'size' attribute to store size.
In particular, bsdtar uses the pax 'size' attribute for any file over 8G. MFC after: 3 days
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/archive_read_support_format_tar.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c
index 9d2aef0..72d2e85 100644
--- a/lib/libarchive/archive_read_support_format_tar.c
+++ b/lib/libarchive/archive_read_support_format_tar.c
@@ -164,6 +164,7 @@ struct tar {
struct sparse_block *sparse_last;
int64_t sparse_offset;
int64_t sparse_numbytes;
+ int64_t sparse_realsize;
int sparse_gnu_major;
int sparse_gnu_minor;
char sparse_gnu_pending;
@@ -440,6 +441,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
free(sp);
}
tar->sparse_last = NULL;
+ tar->sparse_realsize = -1; /* Mark this as "unset" */
r = tar_read_header(a, tar, entry);
@@ -1388,9 +1390,10 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
}
if (wcscmp(key, L"GNU.sparse.name") == 0)
archive_entry_copy_pathname_w(entry, value);
- if (wcscmp(key, L"GNU.sparse.realsize") == 0)
- archive_entry_set_size(entry,
- tar_atol10(value, wcslen(value)));
+ if (wcscmp(key, L"GNU.sparse.realsize") == 0) {
+ tar->sparse_realsize = tar_atol10(value, wcslen(value));
+ archive_entry_set_size(entry, tar->sparse_realsize);
+ }
break;
case 'L':
/* Our extensions */
@@ -1471,11 +1474,22 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
/* POSIX has reserved 'security.*' */
/* Someday: if (wcscmp(key, L"security.acl")==0) { ... } */
if (wcscmp(key, L"size")==0) {
- tar->entry_bytes_remaining = tar_atol10(value, wcslen(value));
- archive_entry_set_size(entry, tar->entry_bytes_remaining);
+ /* "size" is the size of the data in the entry. */
+ tar->entry_bytes_remaining
+ = tar_atol10(value, wcslen(value));
+ /*
+ * But, "size" is not necessarily the size of
+ * the file on disk; if this is a sparse file,
+ * the disk size may have already been set from
+ * GNU.sparse.realsize.
+ */
+ if (tar->sparse_realsize < 0) {
+ archive_entry_set_size(entry,
+ tar->entry_bytes_remaining);
+ tar->sparse_realsize
+ = tar->entry_bytes_remaining;
+ }
}
- tar->entry_bytes_remaining = 0;
-
break;
case 'u':
if (wcscmp(key, L"uid")==0)
OpenPOWER on IntegriCloud