| @@ -165,34 +165,35 @@ struct tar { | | | @@ -165,34 +165,35 @@ struct tar { |
165 | int64_t realsize; | | 165 | int64_t realsize; |
166 | struct sparse_block *sparse_list; | | 166 | struct sparse_block *sparse_list; |
167 | struct sparse_block *sparse_last; | | 167 | struct sparse_block *sparse_last; |
168 | int64_t sparse_offset; | | 168 | int64_t sparse_offset; |
169 | int64_t sparse_numbytes; | | 169 | int64_t sparse_numbytes; |
170 | int sparse_gnu_major; | | 170 | int sparse_gnu_major; |
171 | int sparse_gnu_minor; | | 171 | int sparse_gnu_minor; |
172 | char sparse_gnu_pending; | | 172 | char sparse_gnu_pending; |
173 | }; | | 173 | }; |
174 | | | 174 | |
175 | static ssize_t UTF8_mbrtowc(wchar_t *pwc, const char *s, size_t n); | | 175 | static ssize_t UTF8_mbrtowc(wchar_t *pwc, const char *s, size_t n); |
176 | static int archive_block_is_null(const unsigned char *p); | | 176 | static int archive_block_is_null(const unsigned char *p); |
177 | static char *base64_decode(const char *, size_t, size_t *); | | 177 | static char *base64_decode(const char *, size_t, size_t *); |
178 | static void gnu_add_sparse_entry(struct tar *, | | 178 | static int gnu_add_sparse_entry(struct archive_read *, struct tar *, |
179 | off_t offset, off_t remaining); | | 179 | off_t offset, off_t remaining); |
180 | static void gnu_clear_sparse_list(struct tar *); | | 180 | static void gnu_clear_sparse_list(struct tar *); |
181 | static int gnu_sparse_old_read(struct archive_read *, struct tar *, | | 181 | static int gnu_sparse_old_read(struct archive_read *, struct tar *, |
182 | const struct archive_entry_header_gnutar *header); | | 182 | const struct archive_entry_header_gnutar *header); |
183 | static void gnu_sparse_old_parse(struct tar *, | | 183 | static int gnu_sparse_old_parse(struct archive_read *, struct tar *, |
184 | const struct gnu_sparse *sparse, int length); | | 184 | const struct gnu_sparse *sparse, int length); |
185 | static int gnu_sparse_01_parse(struct tar *, const char *); | | 185 | static int gnu_sparse_01_parse(struct archive_read *, struct tar *, |
| | | 186 | const char *); |
186 | static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *); | | 187 | static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *); |
187 | static int header_Solaris_ACL(struct archive_read *, struct tar *, | | 188 | static int header_Solaris_ACL(struct archive_read *, struct tar *, |
188 | struct archive_entry *, const void *); | | 189 | struct archive_entry *, const void *); |
189 | static int header_common(struct archive_read *, struct tar *, | | 190 | static int header_common(struct archive_read *, struct tar *, |
190 | struct archive_entry *, const void *); | | 191 | struct archive_entry *, const void *); |
191 | static int header_old_tar(struct archive_read *, struct tar *, | | 192 | static int header_old_tar(struct archive_read *, struct tar *, |
192 | struct archive_entry *, const void *); | | 193 | struct archive_entry *, const void *); |
193 | static int header_pax_extensions(struct archive_read *, struct tar *, | | 194 | static int header_pax_extensions(struct archive_read *, struct tar *, |
194 | struct archive_entry *, const void *); | | 195 | struct archive_entry *, const void *); |
195 | static int header_pax_global(struct archive_read *, struct tar *, | | 196 | static int header_pax_global(struct archive_read *, struct tar *, |
196 | struct archive_entry *, const void *h); | | 197 | struct archive_entry *, const void *h); |
197 | static int header_longlink(struct archive_read *, struct tar *, | | 198 | static int header_longlink(struct archive_read *, struct tar *, |
198 | struct archive_entry *, const void *h); | | 199 | struct archive_entry *, const void *h); |
| @@ -202,28 +203,28 @@ static int header_volume(struct archive_ | | | @@ -202,28 +203,28 @@ static int header_volume(struct archive_ |
202 | struct archive_entry *, const void *h); | | 203 | struct archive_entry *, const void *h); |
203 | static int header_ustar(struct archive_read *, struct tar *, | | 204 | static int header_ustar(struct archive_read *, struct tar *, |
204 | struct archive_entry *, const void *h); | | 205 | struct archive_entry *, const void *h); |
205 | static int header_gnutar(struct archive_read *, struct tar *, | | 206 | static int header_gnutar(struct archive_read *, struct tar *, |
206 | struct archive_entry *, const void *h); | | 207 | struct archive_entry *, const void *h); |
207 | static int archive_read_format_tar_bid(struct archive_read *); | | 208 | static int archive_read_format_tar_bid(struct archive_read *); |
208 | static int archive_read_format_tar_cleanup(struct archive_read *); | | 209 | static int archive_read_format_tar_cleanup(struct archive_read *); |
209 | static int archive_read_format_tar_read_data(struct archive_read *a, | | 210 | static int archive_read_format_tar_read_data(struct archive_read *a, |
210 | const void **buff, size_t *size, off_t *offset); | | 211 | const void **buff, size_t *size, off_t *offset); |
211 | static int archive_read_format_tar_skip(struct archive_read *a); | | 212 | static int archive_read_format_tar_skip(struct archive_read *a); |
212 | static int archive_read_format_tar_read_header(struct archive_read *, | | 213 | static int archive_read_format_tar_read_header(struct archive_read *, |
213 | struct archive_entry *); | | 214 | struct archive_entry *); |
214 | static int checksum(struct archive_read *, const void *); | | 215 | static int checksum(struct archive_read *, const void *); |
215 | static int pax_attribute(struct tar *, struct archive_entry *, | | 216 | static int pax_attribute(struct archive_read *, struct tar *, |
216 | char *key, char *value); | | 217 | struct archive_entry *, char *key, char *value); |
217 | static int pax_header(struct archive_read *, struct tar *, | | 218 | static int pax_header(struct archive_read *, struct tar *, |
218 | struct archive_entry *, char *attr); | | 219 | struct archive_entry *, char *attr); |
219 | static void pax_time(const char *, int64_t *sec, long *nanos); | | 220 | static void pax_time(const char *, int64_t *sec, long *nanos); |
220 | static ssize_t readline(struct archive_read *, struct tar *, const char **, | | 221 | static ssize_t readline(struct archive_read *, struct tar *, const char **, |
221 | ssize_t limit); | | 222 | ssize_t limit); |
222 | static int read_body_to_string(struct archive_read *, struct tar *, | | 223 | static int read_body_to_string(struct archive_read *, struct tar *, |
223 | struct archive_string *, const void *h); | | 224 | struct archive_string *, const void *h); |
224 | static int64_t tar_atol(const char *, unsigned); | | 225 | static int64_t tar_atol(const char *, unsigned); |
225 | static int64_t tar_atol10(const char *, unsigned); | | 226 | static int64_t tar_atol10(const char *, unsigned); |
226 | static int64_t tar_atol256(const char *, unsigned); | | 227 | static int64_t tar_atol256(const char *, unsigned); |
227 | static int64_t tar_atol8(const char *, unsigned); | | 228 | static int64_t tar_atol8(const char *, unsigned); |
228 | static int tar_read_header(struct archive_read *, struct tar *, | | 229 | static int tar_read_header(struct archive_read *, struct tar *, |
229 | struct archive_entry *); | | 230 | struct archive_entry *); |
| @@ -409,27 +410,29 @@ archive_read_format_tar_read_header(stru | | | @@ -409,27 +410,29 @@ archive_read_format_tar_read_header(stru |
409 | tar->sparse_list = sp->next; | | 410 | tar->sparse_list = sp->next; |
410 | free(sp); | | 411 | free(sp); |
411 | } | | 412 | } |
412 | tar->sparse_last = NULL; | | 413 | tar->sparse_last = NULL; |
413 | tar->realsize = -1; /* Mark this as "unset" */ | | 414 | tar->realsize = -1; /* Mark this as "unset" */ |
414 | | | 415 | |
415 | r = tar_read_header(a, tar, entry); | | 416 | r = tar_read_header(a, tar, entry); |
416 | | | 417 | |
417 | /* | | 418 | /* |
418 | * "non-sparse" files are really just sparse files with | | 419 | * "non-sparse" files are really just sparse files with |
419 | * a single block. | | 420 | * a single block. |
420 | */ | | 421 | */ |
421 | if (tar->sparse_list == NULL) | | 422 | if (tar->sparse_list == NULL) |
422 | gnu_add_sparse_entry(tar, 0, tar->entry_bytes_remaining); | | 423 | if (gnu_add_sparse_entry(a, tar, 0, tar->entry_bytes_remaining) |
| | | 424 | != ARCHIVE_OK) |
| | | 425 | return (ARCHIVE_FATAL); |
423 | | | 426 | |
424 | if (r == ARCHIVE_OK) { | | 427 | if (r == ARCHIVE_OK) { |
425 | /* | | 428 | /* |
426 | * "Regular" entry with trailing '/' is really | | 429 | * "Regular" entry with trailing '/' is really |
427 | * directory: This is needed for certain old tar | | 430 | * directory: This is needed for certain old tar |
428 | * variants and even for some broken newer ones. | | 431 | * variants and even for some broken newer ones. |
429 | */ | | 432 | */ |
430 | p = archive_entry_pathname(entry); | | 433 | p = archive_entry_pathname(entry); |
431 | l = strlen(p); | | 434 | l = strlen(p); |
432 | if (archive_entry_filetype(entry) == AE_IFREG | | 435 | if (archive_entry_filetype(entry) == AE_IFREG |
433 | && p[l-1] == '/') | | 436 | && p[l-1] == '/') |
434 | archive_entry_set_filetype(entry, AE_IFDIR); | | 437 | archive_entry_set_filetype(entry, AE_IFDIR); |
435 | } | | 438 | } |
| @@ -1259,27 +1262,27 @@ pax_header(struct archive_read *a, struc | | | @@ -1259,27 +1262,27 @@ pax_header(struct archive_read *a, struc |
1259 | while (*p && *p != '=') | | 1262 | while (*p && *p != '=') |
1260 | ++p; | | 1263 | ++p; |
1261 | if (*p == '\0') { | | 1264 | if (*p == '\0') { |
1262 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, | | 1265 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
1263 | "Invalid pax extended attributes"); | | 1266 | "Invalid pax extended attributes"); |
1264 | return (ARCHIVE_WARN); | | 1267 | return (ARCHIVE_WARN); |
1265 | } | | 1268 | } |
1266 | *p = '\0'; | | 1269 | *p = '\0'; |
1267 | | | 1270 | |
1268 | /* Identify null-terminated 'value' portion. */ | | 1271 | /* Identify null-terminated 'value' portion. */ |
1269 | value = p + 1; | | 1272 | value = p + 1; |
1270 | | | 1273 | |
1271 | /* Identify this attribute and set it in the entry. */ | | 1274 | /* Identify this attribute and set it in the entry. */ |
1272 | err2 = pax_attribute(tar, entry, key, value); | | 1275 | err2 = pax_attribute(a, tar, entry, key, value); |
1273 | err = err_combine(err, err2); | | 1276 | err = err_combine(err, err2); |
1274 | | | 1277 | |
1275 | /* Skip to next line */ | | 1278 | /* Skip to next line */ |
1276 | attr += line_length; | | 1279 | attr += line_length; |
1277 | attr_length -= line_length; | | 1280 | attr_length -= line_length; |
1278 | } | | 1281 | } |
1279 | if (archive_strlen(&(tar->entry_gname)) > 0) { | | 1282 | if (archive_strlen(&(tar->entry_gname)) > 0) { |
1280 | value = tar->entry_gname.s; | | 1283 | value = tar->entry_gname.s; |
1281 | if (tar->pax_hdrcharset_binary) | | 1284 | if (tar->pax_hdrcharset_binary) |
1282 | archive_entry_copy_gname(entry, value); | | 1285 | archive_entry_copy_gname(entry, value); |
1283 | else { | | 1286 | else { |
1284 | if (!archive_entry_update_gname_utf8(entry, value)) { | | 1287 | if (!archive_entry_update_gname_utf8(entry, value)) { |
1285 | err = ARCHIVE_WARN; | | 1288 | err = ARCHIVE_WARN; |
| @@ -1385,70 +1388,74 @@ pax_attribute_xattr(struct archive_entry | | | @@ -1385,70 +1388,74 @@ pax_attribute_xattr(struct archive_entry |
1385 | * Parse a single key=value attribute. key/value pointers are | | 1388 | * Parse a single key=value attribute. key/value pointers are |
1386 | * assumed to point into reasonably long-lived storage. | | 1389 | * assumed to point into reasonably long-lived storage. |
1387 | * | | 1390 | * |
1388 | * Note that POSIX reserves all-lowercase keywords. Vendor-specific | | 1391 | * Note that POSIX reserves all-lowercase keywords. Vendor-specific |
1389 | * extensions should always have keywords of the form "VENDOR.attribute" | | 1392 | * extensions should always have keywords of the form "VENDOR.attribute" |
1390 | * In particular, it's quite feasible to support many different | | 1393 | * In particular, it's quite feasible to support many different |
1391 | * vendor extensions here. I'm using "LIBARCHIVE" for extensions | | 1394 | * vendor extensions here. I'm using "LIBARCHIVE" for extensions |
1392 | * unique to this library. | | 1395 | * unique to this library. |
1393 | * | | 1396 | * |
1394 | * Investigate other vendor-specific extensions and see if | | 1397 | * Investigate other vendor-specific extensions and see if |
1395 | * any of them look useful. | | 1398 | * any of them look useful. |
1396 | */ | | 1399 | */ |
1397 | static int | | 1400 | static int |
1398 | pax_attribute(struct tar *tar, struct archive_entry *entry, | | 1401 | pax_attribute(struct archive_read *a, struct tar *tar, |
1399 | char *key, char *value) | | 1402 | struct archive_entry *entry, char *key, char *value) |
1400 | { | | 1403 | { |
1401 | int64_t s; | | 1404 | int64_t s; |
1402 | long n; | | 1405 | long n; |
1403 | wchar_t *wp; | | 1406 | wchar_t *wp; |
1404 | | | 1407 | |
1405 | switch (key[0]) { | | 1408 | switch (key[0]) { |
1406 | case 'G': | | 1409 | case 'G': |
1407 | /* GNU "0.0" sparse pax format. */ | | 1410 | /* GNU "0.0" sparse pax format. */ |
1408 | if (strcmp(key, "GNU.sparse.numblocks") == 0) { | | 1411 | if (strcmp(key, "GNU.sparse.numblocks") == 0) { |
1409 | tar->sparse_offset = -1; | | 1412 | tar->sparse_offset = -1; |
1410 | tar->sparse_numbytes = -1; | | 1413 | tar->sparse_numbytes = -1; |
1411 | tar->sparse_gnu_major = 0; | | 1414 | tar->sparse_gnu_major = 0; |
1412 | tar->sparse_gnu_minor = 0; | | 1415 | tar->sparse_gnu_minor = 0; |
1413 | } | | 1416 | } |
1414 | if (strcmp(key, "GNU.sparse.offset") == 0) { | | 1417 | if (strcmp(key, "GNU.sparse.offset") == 0) { |
1415 | tar->sparse_offset = tar_atol10(value, strlen(value)); | | 1418 | tar->sparse_offset = tar_atol10(value, strlen(value)); |
1416 | if (tar->sparse_numbytes != -1) { | | 1419 | if (tar->sparse_numbytes != -1) { |
1417 | gnu_add_sparse_entry(tar, | | 1420 | if (gnu_add_sparse_entry(a, tar, |
1418 | tar->sparse_offset, tar->sparse_numbytes); | | 1421 | tar->sparse_offset, tar->sparse_numbytes) |
| | | 1422 | != ARCHIVE_OK) |
| | | 1423 | return (ARCHIVE_FATAL); |
1419 | tar->sparse_offset = -1; | | 1424 | tar->sparse_offset = -1; |
1420 | tar->sparse_numbytes = -1; | | 1425 | tar->sparse_numbytes = -1; |
1421 | } | | 1426 | } |
1422 | } | | 1427 | } |
1423 | if (strcmp(key, "GNU.sparse.numbytes") == 0) { | | 1428 | if (strcmp(key, "GNU.sparse.numbytes") == 0) { |
1424 | tar->sparse_numbytes = tar_atol10(value, strlen(value)); | | 1429 | tar->sparse_numbytes = tar_atol10(value, strlen(value)); |
1425 | if (tar->sparse_numbytes != -1) { | | 1430 | if (tar->sparse_numbytes != -1) { |
1426 | gnu_add_sparse_entry(tar, | | 1431 | if (gnu_add_sparse_entry(a, tar, |
1427 | tar->sparse_offset, tar->sparse_numbytes); | | 1432 | tar->sparse_offset, tar->sparse_numbytes) |
| | | 1433 | != ARCHIVE_OK) |
| | | 1434 | return (ARCHIVE_FATAL); |
1428 | tar->sparse_offset = -1; | | 1435 | tar->sparse_offset = -1; |
1429 | tar->sparse_numbytes = -1; | | 1436 | tar->sparse_numbytes = -1; |
1430 | } | | 1437 | } |
1431 | } | | 1438 | } |
1432 | if (strcmp(key, "GNU.sparse.size") == 0) { | | 1439 | if (strcmp(key, "GNU.sparse.size") == 0) { |
1433 | tar->realsize = tar_atol10(value, strlen(value)); | | 1440 | tar->realsize = tar_atol10(value, strlen(value)); |
1434 | archive_entry_set_size(entry, tar->realsize); | | 1441 | archive_entry_set_size(entry, tar->realsize); |
1435 | } | | 1442 | } |
1436 | | | 1443 | |
1437 | /* GNU "0.1" sparse pax format. */ | | 1444 | /* GNU "0.1" sparse pax format. */ |
1438 | if (strcmp(key, "GNU.sparse.map") == 0) { | | 1445 | if (strcmp(key, "GNU.sparse.map") == 0) { |
1439 | tar->sparse_gnu_major = 0; | | 1446 | tar->sparse_gnu_major = 0; |
1440 | tar->sparse_gnu_minor = 1; | | 1447 | tar->sparse_gnu_minor = 1; |
1441 | if (gnu_sparse_01_parse(tar, value) != ARCHIVE_OK) | | 1448 | if (gnu_sparse_01_parse(a, tar, value) != ARCHIVE_OK) |
1442 | return (ARCHIVE_WARN); | | 1449 | return (ARCHIVE_WARN); |
1443 | } | | 1450 | } |
1444 | | | 1451 | |
1445 | /* GNU "1.0" sparse pax format */ | | 1452 | /* GNU "1.0" sparse pax format */ |
1446 | if (strcmp(key, "GNU.sparse.major") == 0) { | | 1453 | if (strcmp(key, "GNU.sparse.major") == 0) { |
1447 | tar->sparse_gnu_major = tar_atol10(value, strlen(value)); | | 1454 | tar->sparse_gnu_major = tar_atol10(value, strlen(value)); |
1448 | tar->sparse_gnu_pending = 1; | | 1455 | tar->sparse_gnu_pending = 1; |
1449 | } | | 1456 | } |
1450 | if (strcmp(key, "GNU.sparse.minor") == 0) { | | 1457 | if (strcmp(key, "GNU.sparse.minor") == 0) { |
1451 | tar->sparse_gnu_minor = tar_atol10(value, strlen(value)); | | 1458 | tar->sparse_gnu_minor = tar_atol10(value, strlen(value)); |
1452 | tar->sparse_gnu_pending = 1; | | 1459 | tar->sparse_gnu_pending = 1; |
1453 | } | | 1460 | } |
1454 | if (strcmp(key, "GNU.sparse.name") == 0) { | | 1461 | if (strcmp(key, "GNU.sparse.name") == 0) { |
| @@ -1706,52 +1713,57 @@ header_gnutar(struct archive_read *a, st | | | @@ -1706,52 +1713,57 @@ header_gnutar(struct archive_read *a, st |
1706 | | | 1713 | |
1707 | /* Grab GNU-specific fields. */ | | 1714 | /* Grab GNU-specific fields. */ |
1708 | archive_entry_set_atime(entry, | | 1715 | archive_entry_set_atime(entry, |
1709 | tar_atol(header->atime, sizeof(header->atime)), 0); | | 1716 | tar_atol(header->atime, sizeof(header->atime)), 0); |
1710 | archive_entry_set_ctime(entry, | | 1717 | archive_entry_set_ctime(entry, |
1711 | tar_atol(header->ctime, sizeof(header->ctime)), 0); | | 1718 | tar_atol(header->ctime, sizeof(header->ctime)), 0); |
1712 | if (header->realsize[0] != 0) { | | 1719 | if (header->realsize[0] != 0) { |
1713 | tar->realsize | | 1720 | tar->realsize |
1714 | = tar_atol(header->realsize, sizeof(header->realsize)); | | 1721 | = tar_atol(header->realsize, sizeof(header->realsize)); |
1715 | archive_entry_set_size(entry, tar->realsize); | | 1722 | archive_entry_set_size(entry, tar->realsize); |
1716 | } | | 1723 | } |
1717 | | | 1724 | |
1718 | if (header->sparse[0].offset[0] != 0) { | | 1725 | if (header->sparse[0].offset[0] != 0) { |
1719 | gnu_sparse_old_read(a, tar, header); | | 1726 | if (gnu_sparse_old_read(a, tar, header) != ARCHIVE_OK) |
| | | 1727 | return (ARCHIVE_FATAL); |
1720 | } else { | | 1728 | } else { |
1721 | if (header->isextended[0] != 0) { | | 1729 | if (header->isextended[0] != 0) { |
1722 | /* XXX WTF? XXX */ | | 1730 | /* XXX WTF? XXX */ |
1723 | } | | 1731 | } |
1724 | } | | 1732 | } |
1725 | | | 1733 | |
1726 | return (0); | | 1734 | return (0); |
1727 | } | | 1735 | } |
1728 | | | 1736 | |
1729 | static void | | 1737 | static int |
1730 | gnu_add_sparse_entry(struct tar *tar, off_t offset, off_t remaining) | | 1738 | gnu_add_sparse_entry(struct archive_read *a, struct tar *tar, off_t offset, |
| | | 1739 | off_t remaining) |
1731 | { | | 1740 | { |
1732 | struct sparse_block *p; | | 1741 | struct sparse_block *p; |
1733 | | | 1742 | |
1734 | p = (struct sparse_block *)malloc(sizeof(*p)); | | 1743 | p = (struct sparse_block *)malloc(sizeof(*p)); |
1735 | if (p == NULL) | | 1744 | if (p == NULL) { |
1736 | __archive_errx(1, "Out of memory"); | | 1745 | archive_set_error(&a->archive, ENOMEM, "Out of memory"); |
| | | 1746 | return (ARCHIVE_FATAL); |
| | | 1747 | } |
1737 | memset(p, 0, sizeof(*p)); | | 1748 | memset(p, 0, sizeof(*p)); |
1738 | if (tar->sparse_last != NULL) | | 1749 | if (tar->sparse_last != NULL) |
1739 | tar->sparse_last->next = p; | | 1750 | tar->sparse_last->next = p; |
1740 | else | | 1751 | else |
1741 | tar->sparse_list = p; | | 1752 | tar->sparse_list = p; |
1742 | tar->sparse_last = p; | | 1753 | tar->sparse_last = p; |
1743 | p->offset = offset; | | 1754 | p->offset = offset; |
1744 | p->remaining = remaining; | | 1755 | p->remaining = remaining; |
| | | 1756 | return (ARCHIVE_OK); |
1745 | } | | 1757 | } |
1746 | | | 1758 | |
1747 | static void | | 1759 | static void |
1748 | gnu_clear_sparse_list(struct tar *tar) | | 1760 | gnu_clear_sparse_list(struct tar *tar) |
1749 | { | | 1761 | { |
1750 | struct sparse_block *p; | | 1762 | struct sparse_block *p; |
1751 | | | 1763 | |
1752 | while (tar->sparse_list != NULL) { | | 1764 | while (tar->sparse_list != NULL) { |
1753 | p = tar->sparse_list; | | 1765 | p = tar->sparse_list; |
1754 | tar->sparse_list = p->next; | | 1766 | tar->sparse_list = p->next; |
1755 | free(p); | | 1767 | free(p); |
1756 | } | | 1768 | } |
1757 | tar->sparse_last = NULL; | | 1769 | tar->sparse_last = NULL; |
| @@ -1772,60 +1784,65 @@ gnu_clear_sparse_list(struct tar *tar) | | | @@ -1772,60 +1784,65 @@ gnu_clear_sparse_list(struct tar *tar) |
1772 | static int | | 1784 | static int |
1773 | gnu_sparse_old_read(struct archive_read *a, struct tar *tar, | | 1785 | gnu_sparse_old_read(struct archive_read *a, struct tar *tar, |
1774 | const struct archive_entry_header_gnutar *header) | | 1786 | const struct archive_entry_header_gnutar *header) |
1775 | { | | 1787 | { |
1776 | ssize_t bytes_read; | | 1788 | ssize_t bytes_read; |
1777 | const void *data; | | 1789 | const void *data; |
1778 | struct extended { | | 1790 | struct extended { |
1779 | struct gnu_sparse sparse[21]; | | 1791 | struct gnu_sparse sparse[21]; |
1780 | char isextended[1]; | | 1792 | char isextended[1]; |
1781 | char padding[7]; | | 1793 | char padding[7]; |
1782 | }; | | 1794 | }; |
1783 | const struct extended *ext; | | 1795 | const struct extended *ext; |
1784 | | | 1796 | |
1785 | gnu_sparse_old_parse(tar, header->sparse, 4); | | 1797 | if (gnu_sparse_old_parse(a, tar, header->sparse, 4) != ARCHIVE_OK) |
| | | 1798 | return (ARCHIVE_FATAL); |
1786 | if (header->isextended[0] == 0) | | 1799 | if (header->isextended[0] == 0) |
1787 | return (ARCHIVE_OK); | | 1800 | return (ARCHIVE_OK); |
1788 | | | 1801 | |
1789 | do { | | 1802 | do { |
1790 | data = __archive_read_ahead(a, 512, &bytes_read); | | 1803 | data = __archive_read_ahead(a, 512, &bytes_read); |
1791 | if (bytes_read < 0) | | 1804 | if (bytes_read < 0) |
1792 | return (ARCHIVE_FATAL); | | 1805 | return (ARCHIVE_FATAL); |
1793 | if (bytes_read < 512) { | | 1806 | if (bytes_read < 512) { |
1794 | archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, | | 1807 | archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, |
1795 | "Truncated tar archive " | | 1808 | "Truncated tar archive " |
1796 | "detected while reading sparse file data"); | | 1809 | "detected while reading sparse file data"); |
1797 | return (ARCHIVE_FATAL); | | 1810 | return (ARCHIVE_FATAL); |
1798 | } | | 1811 | } |
1799 | __archive_read_consume(a, 512); | | 1812 | __archive_read_consume(a, 512); |
1800 | ext = (const struct extended *)data; | | 1813 | ext = (const struct extended *)data; |
1801 | gnu_sparse_old_parse(tar, ext->sparse, 21); | | 1814 | if (gnu_sparse_old_parse(a, tar, ext->sparse, 21) != ARCHIVE_OK) |
| | | 1815 | return (ARCHIVE_FATAL); |
1802 | } while (ext->isextended[0] != 0); | | 1816 | } while (ext->isextended[0] != 0); |
1803 | if (tar->sparse_list != NULL) | | 1817 | if (tar->sparse_list != NULL) |
1804 | tar->entry_offset = tar->sparse_list->offset; | | 1818 | tar->entry_offset = tar->sparse_list->offset; |
1805 | return (ARCHIVE_OK); | | 1819 | return (ARCHIVE_OK); |
1806 | } | | 1820 | } |
1807 | | | 1821 | |
1808 | static void | | 1822 | static int |
1809 | gnu_sparse_old_parse(struct tar *tar, | | 1823 | gnu_sparse_old_parse(struct archive_read *a, struct tar *tar, |
1810 | const struct gnu_sparse *sparse, int length) | | 1824 | const struct gnu_sparse *sparse, int length) |
1811 | { | | 1825 | { |
1812 | while (length > 0 && sparse->offset[0] != 0) { | | 1826 | while (length > 0 && sparse->offset[0] != 0) { |
1813 | gnu_add_sparse_entry(tar, | | 1827 | if (gnu_add_sparse_entry(a, tar, |
1814 | tar_atol(sparse->offset, sizeof(sparse->offset)), | | 1828 | tar_atol(sparse->offset, sizeof(sparse->offset)), |
1815 | tar_atol(sparse->numbytes, sizeof(sparse->numbytes))); | | 1829 | tar_atol(sparse->numbytes, sizeof(sparse->numbytes))) |
| | | 1830 | != ARCHIVE_OK) |
| | | 1831 | return (ARCHIVE_FATAL); |
1816 | sparse++; | | 1832 | sparse++; |
1817 | length--; | | 1833 | length--; |
1818 | } | | 1834 | } |
| | | 1835 | return (ARCHIVE_OK); |
1819 | } | | 1836 | } |
1820 | | | 1837 | |
1821 | /* | | 1838 | /* |
1822 | * GNU tar sparse format 0.0 | | 1839 | * GNU tar sparse format 0.0 |
1823 | * | | 1840 | * |
1824 | * Beginning with GNU tar 1.15, sparse files are stored using | | 1841 | * Beginning with GNU tar 1.15, sparse files are stored using |
1825 | * information in the pax extended header. The GNU tar maintainers | | 1842 | * information in the pax extended header. The GNU tar maintainers |
1826 | * have gone through a number of variations in the process of working | | 1843 | * have gone through a number of variations in the process of working |
1827 | * out this scheme; furtunately, they're all numbered. | | 1844 | * out this scheme; furtunately, they're all numbered. |
1828 | * | | 1845 | * |
1829 | * Sparse format 0.0 uses attribute GNU.sparse.numblocks to store the | | 1846 | * Sparse format 0.0 uses attribute GNU.sparse.numblocks to store the |
1830 | * number of blocks, and GNU.sparse.offset/GNU.sparse.numbytes to | | 1847 | * number of blocks, and GNU.sparse.offset/GNU.sparse.numbytes to |
1831 | * store offset/size for each block. The repeated instances of these | | 1848 | * store offset/size for each block. The repeated instances of these |
| @@ -1835,47 +1852,49 @@ gnu_sparse_old_parse(struct tar *tar, | | | @@ -1835,47 +1852,49 @@ gnu_sparse_old_parse(struct tar *tar, |
1835 | | | 1852 | |
1836 | /* | | 1853 | /* |
1837 | * GNU tar sparse format 0.1 | | 1854 | * GNU tar sparse format 0.1 |
1838 | * | | 1855 | * |
1839 | * This version replaced the offset/numbytes attributes with | | 1856 | * This version replaced the offset/numbytes attributes with |
1840 | * a single "map" attribute that stored a list of integers. This | | 1857 | * a single "map" attribute that stored a list of integers. This |
1841 | * format had two problems: First, the "map" attribute could be very | | 1858 | * format had two problems: First, the "map" attribute could be very |
1842 | * long, which caused problems for some implementations. More | | 1859 | * long, which caused problems for some implementations. More |
1843 | * importantly, the sparse data was lost when extracted by archivers | | 1860 | * importantly, the sparse data was lost when extracted by archivers |
1844 | * that didn't recognize this extension. | | 1861 | * that didn't recognize this extension. |
1845 | */ | | 1862 | */ |
1846 | | | 1863 | |
1847 | static int | | 1864 | static int |
1848 | gnu_sparse_01_parse(struct tar *tar, const char *p) | | 1865 | gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p) |
1849 | { | | 1866 | { |
1850 | const char *e; | | 1867 | const char *e; |
1851 | off_t offset = -1, size = -1; | | 1868 | off_t offset = -1, size = -1; |
1852 | | | 1869 | |
1853 | for (;;) { | | 1870 | for (;;) { |
1854 | e = p; | | 1871 | e = p; |
1855 | while (*e != '\0' && *e != ',') { | | 1872 | while (*e != '\0' && *e != ',') { |
1856 | if (*e < '0' || *e > '9') | | 1873 | if (*e < '0' || *e > '9') |
1857 | return (ARCHIVE_WARN); | | 1874 | return (ARCHIVE_WARN); |
1858 | e++; | | 1875 | e++; |
1859 | } | | 1876 | } |
1860 | if (offset < 0) { | | 1877 | if (offset < 0) { |
1861 | offset = tar_atol10(p, e - p); | | 1878 | offset = tar_atol10(p, e - p); |
1862 | if (offset < 0) | | 1879 | if (offset < 0) |
1863 | return (ARCHIVE_WARN); | | 1880 | return (ARCHIVE_WARN); |
1864 | } else { | | 1881 | } else { |
1865 | size = tar_atol10(p, e - p); | | 1882 | size = tar_atol10(p, e - p); |
1866 | if (size < 0) | | 1883 | if (size < 0) |
1867 | return (ARCHIVE_WARN); | | 1884 | return (ARCHIVE_WARN); |
1868 | gnu_add_sparse_entry(tar, offset, size); | | 1885 | if (gnu_add_sparse_entry(a, tar, offset, size) |
| | | 1886 | != ARCHIVE_OK) |
| | | 1887 | return (ARCHIVE_FATAL); |
1869 | offset = -1; | | 1888 | offset = -1; |
1870 | } | | 1889 | } |
1871 | if (*e == '\0') | | 1890 | if (*e == '\0') |
1872 | return (ARCHIVE_OK); | | 1891 | return (ARCHIVE_OK); |
1873 | p = e + 1; | | 1892 | p = e + 1; |
1874 | } | | 1893 | } |
1875 | } | | 1894 | } |
1876 | | | 1895 | |
1877 | /* | | 1896 | /* |
1878 | * GNU tar sparse format 1.0 | | 1897 | * GNU tar sparse format 1.0 |
1879 | * | | 1898 | * |
1880 | * The idea: The offset/size data is stored as a series of base-10 | | 1899 | * The idea: The offset/size data is stored as a series of base-10 |
1881 | * ASCII numbers prepended to the file data, so that dearchivers that | | 1900 | * ASCII numbers prepended to the file data, so that dearchivers that |
| @@ -1959,27 +1978,28 @@ gnu_sparse_10_read(struct archive_read * | | | @@ -1959,27 +1978,28 @@ gnu_sparse_10_read(struct archive_read * |
1959 | entries = gnu_sparse_10_atol(a, tar, &remaining); | | 1978 | entries = gnu_sparse_10_atol(a, tar, &remaining); |
1960 | if (entries < 0) | | 1979 | if (entries < 0) |
1961 | return (ARCHIVE_FATAL); | | 1980 | return (ARCHIVE_FATAL); |
1962 | /* Parse the individual entries. */ | | 1981 | /* Parse the individual entries. */ |
1963 | while (entries-- > 0) { | | 1982 | while (entries-- > 0) { |
1964 | /* Parse offset/size */ | | 1983 | /* Parse offset/size */ |
1965 | offset = gnu_sparse_10_atol(a, tar, &remaining); | | 1984 | offset = gnu_sparse_10_atol(a, tar, &remaining); |
1966 | if (offset < 0) | | 1985 | if (offset < 0) |
1967 | return (ARCHIVE_FATAL); | | 1986 | return (ARCHIVE_FATAL); |
1968 | size = gnu_sparse_10_atol(a, tar, &remaining); | | 1987 | size = gnu_sparse_10_atol(a, tar, &remaining); |
1969 | if (size < 0) | | 1988 | if (size < 0) |
1970 | return (ARCHIVE_FATAL); | | 1989 | return (ARCHIVE_FATAL); |
1971 | /* Add a new sparse entry. */ | | 1990 | /* Add a new sparse entry. */ |
1972 | gnu_add_sparse_entry(tar, offset, size); | | 1991 | if (gnu_add_sparse_entry(a, tar, offset, size) != ARCHIVE_OK) |
| | | 1992 | return (ARCHIVE_FATAL); |
1973 | } | | 1993 | } |
1974 | /* Skip rest of block... */ | | 1994 | /* Skip rest of block... */ |
1975 | bytes_read = tar->entry_bytes_remaining - remaining; | | 1995 | bytes_read = tar->entry_bytes_remaining - remaining; |
1976 | to_skip = 0x1ff & -bytes_read; | | 1996 | to_skip = 0x1ff & -bytes_read; |
1977 | if (to_skip != __archive_read_skip(a, to_skip)) | | 1997 | if (to_skip != __archive_read_skip(a, to_skip)) |
1978 | return (ARCHIVE_FATAL); | | 1998 | return (ARCHIVE_FATAL); |
1979 | return (bytes_read + to_skip); | | 1999 | return (bytes_read + to_skip); |
1980 | } | | 2000 | } |
1981 | | | 2001 | |
1982 | /*- | | 2002 | /*- |
1983 | * Convert text->integer. | | 2003 | * Convert text->integer. |
1984 | * | | 2004 | * |
1985 | * Traditional tar formats (including POSIX) specify base-8 for | | 2005 | * Traditional tar formats (including POSIX) specify base-8 for |