]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
The "size" pax header keyword overrides tar header's size field.
authorMartin Matuska <martin@matuska.org>
Sun, 5 Mar 2017 22:46:37 +0000 (23:46 +0100)
committerMartin Matuska <martin@matuska.org>
Sun, 5 Mar 2017 22:49:21 +0000 (23:49 +0100)
Fixes #880

libarchive/archive_read_support_format_tar.c

index bd7f13d52eeb7d6918653032a3c7d0115c79c7c4..30d5bc83c3213612ae00fc899a5caf1a9ea40c87 100644 (file)
@@ -155,6 +155,7 @@ struct tar {
        int                      compat_2x;
        int                      process_mac_extensions;
        int                      read_concatenated_archives;
+       int                      realsize_override;
 };
 
 static int     archive_block_is_null(const char *p);
@@ -527,6 +528,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
        tar->entry_offset = 0;
        gnu_clear_sparse_list(tar);
        tar->realsize = -1; /* Mark this as "unset" */
+       tar->realsize_override = 0;
 
        /* Setup default string conversion. */
        tar->sconv = tar->opt_sconv;
@@ -1894,6 +1896,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
                if (strcmp(key, "GNU.sparse.size") == 0) {
                        tar->realsize = tar_atol10(value, strlen(value));
                        archive_entry_set_size(entry, tar->realsize);
+                       tar->realsize_override = 1;
                }
 
                /* GNU "0.1" sparse pax format. */
@@ -1925,6 +1928,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
                if (strcmp(key, "GNU.sparse.realsize") == 0) {
                        tar->realsize = tar_atol10(value, strlen(value));
                        archive_entry_set_size(entry, tar->realsize);
+                       tar->realsize_override = 1;
                }
                break;
        case 'L':
@@ -1977,6 +1981,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
                            tar_atol10(value, strlen(value)));
                } else if (strcmp(key, "SCHILY.realsize") == 0) {
                        tar->realsize = tar_atol10(value, strlen(value));
+                       tar->realsize_override = 1;
                        archive_entry_set_size(entry, tar->realsize);
                } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
                        pax_attribute_schily_xattr(entry, key, value,
@@ -2055,14 +2060,12 @@ pax_attribute(struct archive_read *a, struct tar *tar,
                        tar->entry_bytes_remaining
                            = tar_atol10(value, strlen(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 or GNU.sparse.size or
-                        * an old GNU header field or SCHILY.realsize
-                        * or ....
+                        * The "size" pax header keyword always overrides the
+                        * "size" field in the tar header.
+                        * GNU.sparse.realsize, GNU.sparse.size and
+                        * SCHILY.realsize override this value.
                         */
-                       if (tar->realsize < 0) {
+                       if (!tar->realsize_override) {
                                archive_entry_set_size(entry,
                                    tar->entry_bytes_remaining);
                                tar->realsize
@@ -2206,6 +2209,7 @@ header_gnutar(struct archive_read *a, struct tar *tar,
                tar->realsize
                    = tar_atol(header->realsize, sizeof(header->realsize));
                archive_entry_set_size(entry, tar->realsize);
+               tar->realsize_override = 1;
        }
 
        if (header->sparse[0].offset[0] != 0) {