@@ -129,7 +129,11 @@ struct tar {
129
129
int64_t entry_offset ;
130
130
int64_t entry_padding ;
131
131
int64_t entry_bytes_unconsumed ;
132
- int64_t realsize ;
132
+ int64_t disk_size ;
133
+ int64_t GNU_sparse_realsize ;
134
+ int64_t GNU_sparse_size ;
135
+ int64_t SCHILY_sparse_realsize ;
136
+ int64_t pax_size ;
133
137
struct sparse_block * sparse_list ;
134
138
struct sparse_block * sparse_last ;
135
139
int64_t sparse_offset ;
@@ -138,6 +142,7 @@ struct tar {
138
142
int sparse_gnu_minor ;
139
143
char sparse_gnu_attributes_seen ;
140
144
char filetype ;
145
+ char size_fields ; /* Bits defined below */
141
146
142
147
struct archive_string localname ;
143
148
struct archive_string_conv * opt_sconv ;
@@ -148,9 +153,15 @@ struct tar {
148
153
int compat_2x ;
149
154
int process_mac_extensions ;
150
155
int read_concatenated_archives ;
151
- int realsize_override ;
152
156
};
153
157
158
+ /* Track which size fields were present in the headers */
159
+ #define TAR_SIZE_PAX_SIZE 1
160
+ #define TAR_SIZE_GNU_SPARSE_REALSIZE 2
161
+ #define TAR_SIZE_GNU_SPARSE_SIZE 4
162
+ #define TAR_SIZE_SCHILY_SPARSE_REALSIZE 8
163
+
164
+
154
165
static int archive_block_is_null (const char * p );
155
166
static char * base64_decode (const char * , size_t , size_t * );
156
167
static int gnu_add_sparse_entry (struct archive_read * , struct tar * ,
@@ -529,8 +540,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
529
540
tar = (struct tar * )(a -> format -> data );
530
541
tar -> entry_offset = 0 ;
531
542
gnu_clear_sparse_list (tar );
532
- tar -> realsize = -1 ; /* Mark this as "unset" */
533
- tar -> realsize_override = 0 ;
543
+ tar -> size_fields = 0 ; /* We don't have any size info yet */
534
544
535
545
/* Setup default string conversion. */
536
546
tar -> sconv = tar -> opt_sconv ;
@@ -622,7 +632,7 @@ archive_read_format_tar_read_data(struct archive_read *a,
622
632
tar -> entry_padding = 0 ;
623
633
* buff = NULL ;
624
634
* size = 0 ;
625
- * offset = tar -> realsize ;
635
+ * offset = tar -> disk_size ;
626
636
return (ARCHIVE_EOF );
627
637
}
628
638
@@ -1290,6 +1300,11 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
1290
1300
* allows header_old_tar and header_ustar
1291
1301
* to handle filenames differently, while still putting most of the
1292
1302
* common parsing into one place.
1303
+ *
1304
+ * This is called _after_ ustar, GNU tar, Schily, etc, special
1305
+ * fields have already been parsed into the `tar` structure.
1306
+ * So we can make final decisions here about how to reconcile
1307
+ * size, mode, etc, information.
1293
1308
*/
1294
1309
static int
1295
1310
header_common (struct archive_read * a , struct tar * tar ,
@@ -1323,28 +1338,60 @@ header_common(struct archive_read *a, struct tar *tar,
1323
1338
archive_entry_set_mtime (entry , tar_atol (header -> mtime , sizeof (header -> mtime )), 0 );
1324
1339
}
1325
1340
1326
- /* Update size information as appropriate */
1327
- if (!archive_entry_size_is_set (entry )) {
1328
- tar -> entry_bytes_remaining = tar_atol (header -> size , sizeof (header -> size ));
1329
- if (tar -> entry_bytes_remaining < 0 ) {
1330
- tar -> entry_bytes_remaining = 0 ;
1331
- archive_set_error (& a -> archive , ARCHIVE_ERRNO_MISC ,
1332
- "Tar entry has negative size" );
1333
- return (ARCHIVE_FATAL );
1334
- }
1335
- if (tar -> entry_bytes_remaining > entry_limit ) {
1336
- tar -> entry_bytes_remaining = 0 ;
1337
- archive_set_error (& a -> archive , ARCHIVE_ERRNO_MISC ,
1338
- "Tar entry size overflow" );
1339
- return (ARCHIVE_FATAL );
1340
- }
1341
- if (!tar -> realsize_override ) {
1342
- tar -> realsize = tar -> entry_bytes_remaining ;
1343
- }
1344
- archive_entry_set_size (entry , tar -> realsize );
1345
- } else if (tar -> realsize_override ) {
1346
- tar -> entry_bytes_remaining = tar -> realsize ;
1347
- archive_entry_set_size (entry , tar -> realsize );
1341
+ /* Reconcile the size info. */
1342
+ /* First, how big is the file on disk? */
1343
+ if ((tar -> size_fields & TAR_SIZE_GNU_SPARSE_REALSIZE ) != 0 ) {
1344
+ /* GNU sparse format 1.0 uses `GNU.sparse.realsize`
1345
+ * to hold the size of the file on disk. */
1346
+ tar -> disk_size = tar -> GNU_sparse_realsize ;
1347
+ } else if ((tar -> size_fields & TAR_SIZE_GNU_SPARSE_SIZE ) != 0
1348
+ && (tar -> sparse_gnu_major == 0 )) {
1349
+ /* GNU sparse format 0.0 and 0.1 use `GNU.sparse.size`
1350
+ * to hold the size of the file on disk. */
1351
+ tar -> disk_size = tar -> GNU_sparse_size ;
1352
+ } else if ((tar -> size_fields & TAR_SIZE_SCHILY_SPARSE_REALSIZE ) != 0 ) {
1353
+ tar -> disk_size = tar -> SCHILY_sparse_realsize ;
1354
+ } else if ((tar -> size_fields & TAR_SIZE_PAX_SIZE ) != 0 ) {
1355
+ tar -> disk_size = tar -> pax_size ;
1356
+ } else {
1357
+ /* There wasn't a suitable pax header, so use the ustar info */
1358
+ tar -> disk_size = tar_atol (header -> size , sizeof (header -> size ));
1359
+ }
1360
+
1361
+ if (tar -> disk_size < 0 ) {
1362
+ archive_set_error (& a -> archive , ARCHIVE_ERRNO_MISC ,
1363
+ "Tar entry has negative file size" );
1364
+ return (ARCHIVE_FATAL );
1365
+ } else if (tar -> disk_size > entry_limit ) {
1366
+ archive_set_error (& a -> archive , ARCHIVE_ERRNO_MISC ,
1367
+ "Tar entry size overflow" );
1368
+ return (ARCHIVE_FATAL );
1369
+ } else {
1370
+ archive_entry_set_size (entry , tar -> disk_size );
1371
+ }
1372
+
1373
+ /* Second, how big is the data in the archive? */
1374
+ if ((tar -> size_fields & TAR_SIZE_GNU_SPARSE_SIZE ) != 0
1375
+ && (tar -> sparse_gnu_major == 1 )) {
1376
+ /* GNU sparse format 1.0 uses `GNU.sparse.size`
1377
+ * to hold the size of the data in the archive. */
1378
+ tar -> entry_bytes_remaining = tar -> GNU_sparse_size ;
1379
+ } else if ((tar -> size_fields & TAR_SIZE_PAX_SIZE ) != 0 ) {
1380
+ tar -> entry_bytes_remaining = tar -> pax_size ;
1381
+ } else {
1382
+ tar -> entry_bytes_remaining
1383
+ = tar_atol (header -> size , sizeof (header -> size ));
1384
+ }
1385
+ if (tar -> entry_bytes_remaining < 0 ) {
1386
+ tar -> entry_bytes_remaining = 0 ;
1387
+ archive_set_error (& a -> archive , ARCHIVE_ERRNO_MISC ,
1388
+ "Tar entry has negative size" );
1389
+ return (ARCHIVE_FATAL );
1390
+ } else if (tar -> entry_bytes_remaining > entry_limit ) {
1391
+ tar -> entry_bytes_remaining = 0 ;
1392
+ archive_set_error (& a -> archive , ARCHIVE_ERRNO_MISC ,
1393
+ "Tar entry size overflow" );
1394
+ return (ARCHIVE_FATAL );
1348
1395
}
1349
1396
1350
1397
/* Handle the tar type flag appropriately. */
@@ -2299,10 +2346,13 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
2299
2346
}
2300
2347
else if (key_length == 4 && memcmp (key , "size" , 4 ) == 0 ) {
2301
2348
/* GNU.sparse.size */
2349
+ /* This is either the size of stored entry OR the size of data on disk,
2350
+ * depending on which GNU sparse format version is in use.
2351
+ * Since pax attributes can be in any order, we may not actually
2352
+ * know at this point how to interpret this. */
2302
2353
if ((err = pax_attribute_read_number (a , value_length , & t )) == ARCHIVE_OK ) {
2303
- tar -> realsize = t ;
2304
- archive_entry_set_size (entry , tar -> realsize );
2305
- tar -> realsize_override = 1 ;
2354
+ tar -> GNU_sparse_size = t ;
2355
+ tar -> size_fields |= TAR_SIZE_GNU_SPARSE_SIZE ;
2306
2356
}
2307
2357
return (err );
2308
2358
}
@@ -2370,11 +2420,10 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
2370
2420
return (err );
2371
2421
}
2372
2422
else if (key_length == 8 && memcmp (key , "realsize" , 8 ) == 0 ) {
2373
- /* GNU.sparse.realsize */
2423
+ /* GNU.sparse.realsize = size of file on disk */
2374
2424
if ((err = pax_attribute_read_number (a , value_length , & t )) == ARCHIVE_OK ) {
2375
- tar -> realsize = t ;
2376
- archive_entry_set_size (entry , tar -> realsize );
2377
- tar -> realsize_override = 1 ;
2425
+ tar -> GNU_sparse_realsize = t ;
2426
+ tar -> size_fields |= TAR_SIZE_GNU_SPARSE_REALSIZE ;
2378
2427
}
2379
2428
return (err );
2380
2429
}
@@ -2555,12 +2604,12 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
2555
2604
}
2556
2605
else if (key_length == 8 && memcmp (key , "realsize" , 8 ) == 0 ) {
2557
2606
if ((err = pax_attribute_read_number (a , value_length , & t )) == ARCHIVE_OK ) {
2558
- tar -> realsize = t ;
2559
- tar -> realsize_override = 1 ;
2560
- archive_entry_set_size (entry , tar -> realsize );
2607
+ tar -> SCHILY_sparse_realsize = t ;
2608
+ tar -> size_fields |= TAR_SIZE_SCHILY_SPARSE_REALSIZE ;
2561
2609
}
2562
2610
return (err );
2563
2611
}
2612
+ /* TODO: Is there a SCHILY.sparse.size similar to GNU.sparse.size ? */
2564
2613
else if (key_length > 6 && memcmp (key , "xattr." , 6 ) == 0 ) {
2565
2614
key_length -= 6 ;
2566
2615
key += 6 ;
@@ -2727,19 +2776,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
2727
2776
if (key_length == 4 && memcmp (key , "size" , 4 ) == 0 ) {
2728
2777
/* "size" is the size of the data in the entry. */
2729
2778
if ((err = pax_attribute_read_number (a , value_length , & t )) == ARCHIVE_OK ) {
2730
- tar -> entry_bytes_remaining = t ;
2731
- /*
2732
- * The "size" pax header keyword always overrides the
2733
- * "size" field in the tar header.
2734
- * GNU.sparse.realsize, GNU.sparse.size and
2735
- * SCHILY.realsize override this value.
2736
- */
2737
- if (!tar -> realsize_override ) {
2738
- archive_entry_set_size (entry ,
2739
- tar -> entry_bytes_remaining );
2740
- tar -> realsize
2741
- = tar -> entry_bytes_remaining ;
2742
- }
2779
+ tar -> pax_size = t ;
2780
+ tar -> size_fields |= TAR_SIZE_PAX_SIZE ;
2743
2781
}
2744
2782
else if (t == INT64_MAX ) {
2745
2783
/* Note: pax_attr_read_number returns INT64_MAX on overflow or < 0 */
@@ -2851,11 +2889,6 @@ header_gnutar(struct archive_read *a, struct tar *tar,
2851
2889
* filename is stored as in old-style archives.
2852
2890
*/
2853
2891
2854
- /* Grab fields common to all tar variants. */
2855
- err = header_common (a , tar , entry , h );
2856
- if (err == ARCHIVE_FATAL )
2857
- return (err );
2858
-
2859
2892
/* Copy filename over (to ensure null termination). */
2860
2893
header = (const struct archive_entry_header_gnutar * )h ;
2861
2894
const char * existing_pathname = archive_entry_pathname (entry );
@@ -2904,8 +2937,6 @@ header_gnutar(struct archive_read *a, struct tar *tar,
2904
2937
archive_entry_set_rdev (entry , 0 );
2905
2938
}
2906
2939
2907
- tar -> entry_padding = 0x1ff & (- tar -> entry_bytes_remaining );
2908
-
2909
2940
/* Grab GNU-specific fields. */
2910
2941
if (!archive_entry_atime_is_set (entry )) {
2911
2942
t = tar_atol (header -> atime , sizeof (header -> atime ));
@@ -2919,10 +2950,10 @@ header_gnutar(struct archive_read *a, struct tar *tar,
2919
2950
}
2920
2951
2921
2952
if (header -> realsize [0 ] != 0 ) {
2922
- tar -> realsize
2953
+ /* Treat as a synonym for the pax GNU.sparse.realsize attr */
2954
+ tar -> GNU_sparse_realsize
2923
2955
= tar_atol (header -> realsize , sizeof (header -> realsize ));
2924
- archive_entry_set_size (entry , tar -> realsize );
2925
- tar -> realsize_override = 1 ;
2956
+ tar -> size_fields |= TAR_SIZE_GNU_SPARSE_REALSIZE ;
2926
2957
}
2927
2958
2928
2959
if (header -> sparse [0 ].offset [0 ] != 0 ) {
@@ -2935,6 +2966,13 @@ header_gnutar(struct archive_read *a, struct tar *tar,
2935
2966
}
2936
2967
}
2937
2968
2969
+ /* Grab fields common to all tar variants. */
2970
+ err = header_common (a , tar , entry , h );
2971
+ if (err == ARCHIVE_FATAL )
2972
+ return (err );
2973
+
2974
+ tar -> entry_padding = 0x1ff & (- tar -> entry_bytes_remaining );
2975
+
2938
2976
return (err );
2939
2977
}
2940
2978
@@ -3114,8 +3152,7 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
3114
3152
* it's not possible to support both variants. This code supports
3115
3153
* the later variant at the expense of not supporting the former.
3116
3154
*
3117
- * This variant also replaced GNU.sparse.size with GNU.sparse.realsize
3118
- * and introduced the GNU.sparse.major/GNU.sparse.minor attributes.
3155
+ * This variant also introduced the GNU.sparse.major/GNU.sparse.minor attributes.
3119
3156
*/
3120
3157
3121
3158
/*
0 commit comments