archive_read_support_format_ar.c revision 311042
1238825Smm/*- 2238825Smm * Copyright (c) 2007 Kai Wang 3238825Smm * Copyright (c) 2007 Tim Kientzle 4238825Smm * All rights reserved. 5238825Smm * 6238825Smm * Redistribution and use in source and binary forms, with or without 7238825Smm * modification, are permitted provided that the following conditions 8238825Smm * are met: 9238825Smm * 1. Redistributions of source code must retain the above copyright 10238825Smm * notice, this list of conditions and the following disclaimer 11238825Smm * in this position and unchanged. 12238825Smm * 2. Redistributions in binary form must reproduce the above copyright 13238825Smm * notice, this list of conditions and the following disclaimer in the 14238825Smm * documentation and/or other materials provided with the distribution. 15238825Smm * 16238825Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17238825Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18238825Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19238825Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20238825Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21238825Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22238825Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23238825Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24238825Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25238825Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26238825Smm */ 27238825Smm 28238825Smm#include "archive_platform.h" 29238825Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_read_support_format_ar.c 311042 2017-01-02 01:43:11Z mm $"); 30238825Smm 31238825Smm#ifdef HAVE_SYS_STAT_H 32238825Smm#include <sys/stat.h> 33238825Smm#endif 34238825Smm#ifdef HAVE_ERRNO_H 35238825Smm#include <errno.h> 36238825Smm#endif 37238825Smm#ifdef HAVE_STDLIB_H 38238825Smm#include <stdlib.h> 39238825Smm#endif 40238825Smm#ifdef HAVE_STRING_H 41238825Smm#include <string.h> 42238825Smm#endif 43302001Smm#ifdef HAVE_LIMITS_H 44238825Smm#include <limits.h> 45238825Smm#endif 46238825Smm 47238825Smm#include "archive.h" 48238825Smm#include "archive_entry.h" 49238825Smm#include "archive_private.h" 50238825Smm#include "archive_read_private.h" 51238825Smm 52238825Smmstruct ar { 53238825Smm int64_t entry_bytes_remaining; 54238825Smm /* unconsumed is purely to track data we've gotten from readahead, 55238825Smm * but haven't yet marked as consumed. Must be paired with 56238825Smm * entry_bytes_remaining usage/modification. 57238825Smm */ 58238825Smm size_t entry_bytes_unconsumed; 59238825Smm int64_t entry_offset; 60238825Smm int64_t entry_padding; 61238825Smm char *strtab; 62238825Smm size_t strtab_size; 63238825Smm char read_global_header; 64238825Smm}; 65238825Smm 66238825Smm/* 67238825Smm * Define structure of the "ar" header. 68238825Smm */ 69238825Smm#define AR_name_offset 0 70238825Smm#define AR_name_size 16 71238825Smm#define AR_date_offset 16 72238825Smm#define AR_date_size 12 73238825Smm#define AR_uid_offset 28 74238825Smm#define AR_uid_size 6 75238825Smm#define AR_gid_offset 34 76238825Smm#define AR_gid_size 6 77238825Smm#define AR_mode_offset 40 78238825Smm#define AR_mode_size 8 79238825Smm#define AR_size_offset 48 80238825Smm#define AR_size_size 10 81238825Smm#define AR_fmag_offset 58 82238825Smm#define AR_fmag_size 2 83238825Smm 84238825Smmstatic int archive_read_format_ar_bid(struct archive_read *a, int); 85238825Smmstatic int archive_read_format_ar_cleanup(struct archive_read *a); 86238825Smmstatic int archive_read_format_ar_read_data(struct archive_read *a, 87238825Smm const void **buff, size_t *size, int64_t *offset); 88238825Smmstatic int archive_read_format_ar_skip(struct archive_read *a); 89238825Smmstatic int archive_read_format_ar_read_header(struct archive_read *a, 90238825Smm struct archive_entry *e); 91238825Smmstatic uint64_t ar_atol8(const char *p, unsigned char_cnt); 92238825Smmstatic uint64_t ar_atol10(const char *p, unsigned char_cnt); 93238825Smmstatic int ar_parse_gnu_filename_table(struct archive_read *a); 94238825Smmstatic int ar_parse_common_header(struct ar *ar, struct archive_entry *, 95238825Smm const char *h); 96348608Smm 97348608Smmint 98348608Smmarchive_read_support_format_ar(struct archive *_a) 99238825Smm{ 100238825Smm struct archive_read *a = (struct archive_read *)_a; 101238825Smm struct ar *ar; 102238825Smm int r; 103238825Smm 104238825Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 105238825Smm ARCHIVE_STATE_NEW, "archive_read_support_format_ar"); 106238825Smm 107238825Smm ar = (struct ar *)calloc(1, sizeof(*ar)); 108238825Smm if (ar == NULL) { 109238825Smm archive_set_error(&a->archive, ENOMEM, 110238825Smm "Can't allocate ar data"); 111238825Smm return (ARCHIVE_FATAL); 112238825Smm } 113238825Smm ar->strtab = NULL; 114238825Smm 115238825Smm r = __archive_read_register_format(a, 116238825Smm ar, 117238825Smm "ar", 118238825Smm archive_read_format_ar_bid, 119238825Smm NULL, 120238825Smm archive_read_format_ar_read_header, 121238825Smm archive_read_format_ar_read_data, 122238825Smm archive_read_format_ar_skip, 123238825Smm NULL, 124238825Smm archive_read_format_ar_cleanup, 125238825Smm NULL, 126238825Smm NULL); 127238825Smm 128238825Smm if (r != ARCHIVE_OK) { 129238825Smm free(ar); 130238825Smm return (r); 131238825Smm } 132238825Smm return (ARCHIVE_OK); 133238825Smm} 134238825Smm 135238825Smmstatic int 136238825Smmarchive_read_format_ar_cleanup(struct archive_read *a) 137238825Smm{ 138238825Smm struct ar *ar; 139238825Smm 140238825Smm ar = (struct ar *)(a->format->data); 141238825Smm if (ar->strtab) 142238825Smm free(ar->strtab); 143238825Smm free(ar); 144238825Smm (a->format->data) = NULL; 145238825Smm return (ARCHIVE_OK); 146238825Smm} 147238825Smm 148238825Smmstatic int 149238825Smmarchive_read_format_ar_bid(struct archive_read *a, int best_bid) 150238825Smm{ 151238825Smm const void *h; 152238825Smm 153238825Smm (void)best_bid; /* UNUSED */ 154238825Smm 155238825Smm /* 156238825Smm * Verify the 8-byte file signature. 157238825Smm * TODO: Do we need to check more than this? 158238825Smm */ 159238825Smm if ((h = __archive_read_ahead(a, 8, NULL)) == NULL) 160238825Smm return (-1); 161238825Smm if (memcmp(h, "!<arch>\n", 8) == 0) { 162238825Smm return (64); 163238825Smm } 164238825Smm return (-1); 165238825Smm} 166238825Smm 167238825Smmstatic int 168238825Smm_ar_read_header(struct archive_read *a, struct archive_entry *entry, 169238825Smm struct ar *ar, const char *h, size_t *unconsumed) 170238825Smm{ 171238825Smm char filename[AR_name_size + 1]; 172238825Smm uint64_t number; /* Used to hold parsed numbers before validation. */ 173238825Smm size_t bsd_name_length, entry_size; 174238825Smm char *p, *st; 175238825Smm const void *b; 176238825Smm int r; 177238825Smm 178238825Smm /* Verify the magic signature on the file header. */ 179238825Smm if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) { 180238825Smm archive_set_error(&a->archive, EINVAL, 181238825Smm "Incorrect file header signature"); 182238825Smm return (ARCHIVE_FATAL); 183238825Smm } 184238825Smm 185238825Smm /* Copy filename into work buffer. */ 186238825Smm strncpy(filename, h + AR_name_offset, AR_name_size); 187238825Smm filename[AR_name_size] = '\0'; 188238825Smm 189238825Smm /* 190238825Smm * Guess the format variant based on the filename. 191238825Smm */ 192238825Smm if (a->archive.archive_format == ARCHIVE_FORMAT_AR) { 193238825Smm /* We don't already know the variant, so let's guess. */ 194238825Smm /* 195238825Smm * Biggest clue is presence of '/': GNU starts special 196238825Smm * filenames with '/', appends '/' as terminator to 197238825Smm * non-special names, so anything with '/' should be 198238825Smm * GNU except for BSD long filenames. 199238825Smm */ 200238825Smm if (strncmp(filename, "#1/", 3) == 0) 201238825Smm a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 202238825Smm else if (strchr(filename, '/') != NULL) 203238825Smm a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; 204238825Smm else if (strncmp(filename, "__.SYMDEF", 9) == 0) 205238825Smm a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 206238825Smm /* 207238825Smm * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/' 208238825Smm * if name exactly fills 16-byte field? If so, we 209238825Smm * can't assume entries without '/' are BSD. XXX 210238825Smm */ 211238825Smm } 212238825Smm 213238825Smm /* Update format name from the code. */ 214238825Smm if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) 215238825Smm a->archive.archive_format_name = "ar (GNU/SVR4)"; 216238825Smm else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) 217238825Smm a->archive.archive_format_name = "ar (BSD)"; 218238825Smm else 219238825Smm a->archive.archive_format_name = "ar"; 220238825Smm 221238825Smm /* 222238825Smm * Remove trailing spaces from the filename. GNU and BSD 223238825Smm * variants both pad filename area out with spaces. 224238825Smm * This will only be wrong if GNU/SVR4 'ar' implementations 225238825Smm * omit trailing '/' for 16-char filenames and we have 226238825Smm * a 16-char filename that ends in ' '. 227238825Smm */ 228238825Smm p = filename + AR_name_size - 1; 229348608Smm while (p >= filename && *p == ' ') { 230238825Smm *p = '\0'; 231238825Smm p--; 232238825Smm } 233238825Smm 234238825Smm /* 235238825Smm * Remove trailing slash unless first character is '/'. 236238825Smm * (BSD entries never end in '/', so this will only trim 237238825Smm * GNU-format entries. GNU special entries start with '/' 238238825Smm * and are not terminated in '/', so we don't trim anything 239238825Smm * that starts with '/'.) 240238825Smm */ 241238825Smm if (filename[0] != '/' && p > filename && *p == '/') { 242238825Smm *p = '\0'; 243238825Smm } 244238825Smm 245238825Smm if (p < filename) { 246238825Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 247238825Smm "Found entry with empty filename"); 248238825Smm return (ARCHIVE_FATAL); 249238825Smm } 250238825Smm 251238825Smm /* 252238825Smm * '//' is the GNU filename table. 253238825Smm * Later entries can refer to names in this table. 254238825Smm */ 255238825Smm if (strcmp(filename, "//") == 0) { 256238825Smm /* This must come before any call to _read_ahead. */ 257238825Smm ar_parse_common_header(ar, entry, h); 258238825Smm archive_entry_copy_pathname(entry, filename); 259238825Smm archive_entry_set_filetype(entry, AE_IFREG); 260238825Smm /* Get the size of the filename table. */ 261238825Smm number = ar_atol10(h + AR_size_offset, AR_size_size); 262238825Smm if (number > SIZE_MAX || number > 1024 * 1024 * 1024) { 263238825Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 264238825Smm "Filename table too large"); 265238825Smm return (ARCHIVE_FATAL); 266238825Smm } 267238825Smm entry_size = (size_t)number; 268238825Smm if (entry_size == 0) { 269238825Smm archive_set_error(&a->archive, EINVAL, 270238825Smm "Invalid string table"); 271238825Smm return (ARCHIVE_FATAL); 272238825Smm } 273238825Smm if (ar->strtab != NULL) { 274238825Smm archive_set_error(&a->archive, EINVAL, 275238825Smm "More than one string tables exist"); 276238825Smm return (ARCHIVE_FATAL); 277238825Smm } 278238825Smm 279238825Smm /* Read the filename table into memory. */ 280238825Smm st = malloc(entry_size); 281238825Smm if (st == NULL) { 282238825Smm archive_set_error(&a->archive, ENOMEM, 283238825Smm "Can't allocate filename table buffer"); 284238825Smm return (ARCHIVE_FATAL); 285238825Smm } 286238825Smm ar->strtab = st; 287238825Smm ar->strtab_size = entry_size; 288238825Smm 289238825Smm if (*unconsumed) { 290238825Smm __archive_read_consume(a, *unconsumed); 291238825Smm *unconsumed = 0; 292238825Smm } 293238825Smm 294238825Smm if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL) 295238825Smm return (ARCHIVE_FATAL); 296238825Smm memcpy(st, b, entry_size); 297238825Smm __archive_read_consume(a, entry_size); 298238825Smm /* All contents are consumed. */ 299238825Smm ar->entry_bytes_remaining = 0; 300238825Smm archive_entry_set_size(entry, ar->entry_bytes_remaining); 301238825Smm 302238825Smm /* Parse the filename table. */ 303238825Smm return (ar_parse_gnu_filename_table(a)); 304238825Smm } 305238825Smm 306238825Smm /* 307238825Smm * GNU variant handles long filenames by storing /<number> 308238825Smm * to indicate a name stored in the filename table. 309238825Smm * XXX TODO: Verify that it's all digits... Don't be fooled 310238825Smm * by "/9xyz" XXX 311238825Smm */ 312238825Smm if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') { 313238825Smm number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); 314238825Smm /* 315238825Smm * If we can't look up the real name, warn and return 316238825Smm * the entry with the wrong name. 317238825Smm */ 318238825Smm if (ar->strtab == NULL || number >= ar->strtab_size) { 319238825Smm archive_set_error(&a->archive, EINVAL, 320238825Smm "Can't find long filename for GNU/SVR4 archive entry"); 321238825Smm archive_entry_copy_pathname(entry, filename); 322238825Smm /* Parse the time, owner, mode, size fields. */ 323238825Smm ar_parse_common_header(ar, entry, h); 324238825Smm return (ARCHIVE_FATAL); 325238825Smm } 326238825Smm 327238825Smm archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]); 328238825Smm /* Parse the time, owner, mode, size fields. */ 329238825Smm return (ar_parse_common_header(ar, entry, h)); 330238825Smm } 331238825Smm 332238825Smm /* 333238825Smm * BSD handles long filenames by storing "#1/" followed by the 334238825Smm * length of filename as a decimal number, then prepends the 335238825Smm * the filename to the file contents. 336238825Smm */ 337238825Smm if (strncmp(filename, "#1/", 3) == 0) { 338238825Smm /* Parse the time, owner, mode, size fields. */ 339238825Smm /* This must occur before _read_ahead is called again. */ 340238825Smm ar_parse_common_header(ar, entry, h); 341238825Smm 342238825Smm /* Parse the size of the name, adjust the file size. */ 343238825Smm number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); 344238825Smm /* Sanity check the filename length: 345238825Smm * = Must be <= SIZE_MAX - 1 346238825Smm * = Must be <= 1MB 347238825Smm * = Cannot be bigger than the entire entry 348238825Smm */ 349238825Smm if (number > SIZE_MAX - 1 350238825Smm || number > 1024 * 1024 351238825Smm || (int64_t)number > ar->entry_bytes_remaining) { 352238825Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 353238825Smm "Bad input file size"); 354238825Smm return (ARCHIVE_FATAL); 355238825Smm } 356238825Smm bsd_name_length = (size_t)number; 357238825Smm ar->entry_bytes_remaining -= bsd_name_length; 358238825Smm /* Adjust file size reported to client. */ 359238825Smm archive_entry_set_size(entry, ar->entry_bytes_remaining); 360238825Smm 361238825Smm if (*unconsumed) { 362238825Smm __archive_read_consume(a, *unconsumed); 363238825Smm *unconsumed = 0; 364238825Smm } 365238825Smm 366238825Smm /* Read the long name into memory. */ 367238825Smm if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) { 368238825Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 369238825Smm "Truncated input file"); 370238825Smm return (ARCHIVE_FATAL); 371238825Smm } 372238825Smm /* Store it in the entry. */ 373238825Smm p = (char *)malloc(bsd_name_length + 1); 374238825Smm if (p == NULL) { 375238825Smm archive_set_error(&a->archive, ENOMEM, 376238825Smm "Can't allocate fname buffer"); 377238825Smm return (ARCHIVE_FATAL); 378238825Smm } 379238825Smm strncpy(p, b, bsd_name_length); 380238825Smm p[bsd_name_length] = '\0'; 381238825Smm 382238825Smm __archive_read_consume(a, bsd_name_length); 383238825Smm 384238825Smm archive_entry_copy_pathname(entry, p); 385238825Smm free(p); 386238825Smm return (ARCHIVE_OK); 387238825Smm } 388238825Smm 389238825Smm /* 390238825Smm * "/" is the SVR4/GNU archive symbol table. 391238825Smm */ 392238825Smm if (strcmp(filename, "/") == 0) { 393238825Smm archive_entry_copy_pathname(entry, "/"); 394238825Smm /* Parse the time, owner, mode, size fields. */ 395238825Smm r = ar_parse_common_header(ar, entry, h); 396238825Smm /* Force the file type to a regular file. */ 397238825Smm archive_entry_set_filetype(entry, AE_IFREG); 398238825Smm return (r); 399238825Smm } 400238825Smm 401238825Smm /* 402238825Smm * "__.SYMDEF" is a BSD archive symbol table. 403238825Smm */ 404238825Smm if (strcmp(filename, "__.SYMDEF") == 0) { 405238825Smm archive_entry_copy_pathname(entry, filename); 406238825Smm /* Parse the time, owner, mode, size fields. */ 407238825Smm return (ar_parse_common_header(ar, entry, h)); 408238825Smm } 409238825Smm 410238825Smm /* 411238825Smm * Otherwise, this is a standard entry. The filename 412238825Smm * has already been trimmed as much as possible, based 413238825Smm * on our current knowledge of the format. 414238825Smm */ 415238825Smm archive_entry_copy_pathname(entry, filename); 416238825Smm return (ar_parse_common_header(ar, entry, h)); 417238825Smm} 418238825Smm 419238825Smmstatic int 420238825Smmarchive_read_format_ar_read_header(struct archive_read *a, 421238825Smm struct archive_entry *entry) 422238825Smm{ 423238825Smm struct ar *ar = (struct ar*)(a->format->data); 424238825Smm size_t unconsumed; 425238825Smm const void *header_data; 426238825Smm int ret; 427238825Smm 428238825Smm if (!ar->read_global_header) { 429238825Smm /* 430238825Smm * We are now at the beginning of the archive, 431238825Smm * so we need first consume the ar global header. 432238825Smm */ 433238825Smm __archive_read_consume(a, 8); 434238825Smm ar->read_global_header = 1; 435238825Smm /* Set a default format code for now. */ 436238825Smm a->archive.archive_format = ARCHIVE_FORMAT_AR; 437238825Smm } 438238825Smm 439238825Smm /* Read the header for the next file entry. */ 440238825Smm if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL) 441238825Smm /* Broken header. */ 442238825Smm return (ARCHIVE_EOF); 443238825Smm 444238825Smm unconsumed = 60; 445238825Smm 446238825Smm ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed); 447238825Smm 448238825Smm if (unconsumed) 449238825Smm __archive_read_consume(a, unconsumed); 450238825Smm 451238825Smm return ret; 452238825Smm} 453238825Smm 454238825Smm 455238825Smmstatic int 456238825Smmar_parse_common_header(struct ar *ar, struct archive_entry *entry, 457238825Smm const char *h) 458238825Smm{ 459238825Smm uint64_t n; 460238825Smm 461238825Smm /* Copy remaining header */ 462238825Smm archive_entry_set_mtime(entry, 463238825Smm (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L); 464238825Smm archive_entry_set_uid(entry, 465238825Smm (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size)); 466238825Smm archive_entry_set_gid(entry, 467238825Smm (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size)); 468238825Smm archive_entry_set_mode(entry, 469238825Smm (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size)); 470238825Smm n = ar_atol10(h + AR_size_offset, AR_size_size); 471238825Smm 472238825Smm ar->entry_offset = 0; 473238825Smm ar->entry_padding = n % 2; 474238825Smm archive_entry_set_size(entry, n); 475238825Smm ar->entry_bytes_remaining = n; 476238825Smm return (ARCHIVE_OK); 477238825Smm} 478348608Smm 479348608Smmstatic int 480348608Smmarchive_read_format_ar_read_data(struct archive_read *a, 481348608Smm const void **buff, size_t *size, int64_t *offset) 482348608Smm{ 483348608Smm ssize_t bytes_read; 484348608Smm struct ar *ar; 485348608Smm 486348608Smm ar = (struct ar *)(a->format->data); 487348608Smm 488348608Smm if (ar->entry_bytes_unconsumed) { 489348608Smm __archive_read_consume(a, ar->entry_bytes_unconsumed); 490348608Smm ar->entry_bytes_unconsumed = 0; 491348608Smm } 492348608Smm 493348608Smm if (ar->entry_bytes_remaining > 0) { 494348608Smm *buff = __archive_read_ahead(a, 1, &bytes_read); 495348608Smm if (bytes_read == 0) { 496348608Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 497348608Smm "Truncated ar archive"); 498348608Smm return (ARCHIVE_FATAL); 499348608Smm } 500313571Smm if (bytes_read < 0) 501238825Smm return (ARCHIVE_FATAL); 502238825Smm if (bytes_read > ar->entry_bytes_remaining) 503238825Smm bytes_read = (ssize_t)ar->entry_bytes_remaining; 504238825Smm *size = bytes_read; 505238825Smm ar->entry_bytes_unconsumed = bytes_read; 506238825Smm *offset = ar->entry_offset; 507238825Smm ar->entry_offset += bytes_read; 508238825Smm ar->entry_bytes_remaining -= bytes_read; 509238825Smm return (ARCHIVE_OK); 510238825Smm } else { 511238825Smm int64_t skipped = __archive_read_consume(a, ar->entry_padding); 512238825Smm if (skipped >= 0) { 513238825Smm ar->entry_padding -= skipped; 514238825Smm } 515238825Smm if (ar->entry_padding) { 516238825Smm if (skipped >= 0) { 517238825Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 518238825Smm "Truncated ar archive- failed consuming padding"); 519238825Smm } 520238825Smm return (ARCHIVE_FATAL); 521238825Smm } 522238825Smm *buff = NULL; 523238825Smm *size = 0; 524238825Smm *offset = ar->entry_offset; 525238825Smm return (ARCHIVE_EOF); 526238825Smm } 527238825Smm} 528238825Smm 529238825Smmstatic int 530238825Smmarchive_read_format_ar_skip(struct archive_read *a) 531238825Smm{ 532238825Smm int64_t bytes_skipped; 533238825Smm struct ar* ar; 534238825Smm 535238825Smm ar = (struct ar *)(a->format->data); 536238825Smm 537238825Smm bytes_skipped = __archive_read_consume(a, 538238825Smm ar->entry_bytes_remaining + ar->entry_padding 539238825Smm + ar->entry_bytes_unconsumed); 540238825Smm if (bytes_skipped < 0) 541238825Smm return (ARCHIVE_FATAL); 542238825Smm 543238825Smm ar->entry_bytes_remaining = 0; 544238825Smm ar->entry_bytes_unconsumed = 0; 545238825Smm ar->entry_padding = 0; 546238825Smm 547238825Smm return (ARCHIVE_OK); 548238825Smm} 549238825Smm 550238825Smmstatic int 551238825Smmar_parse_gnu_filename_table(struct archive_read *a) 552238825Smm{ 553238825Smm struct ar *ar; 554238825Smm char *p; 555238825Smm size_t size; 556238825Smm 557238825Smm ar = (struct ar*)(a->format->data); 558238825Smm size = ar->strtab_size; 559238825Smm 560238825Smm for (p = ar->strtab; p < ar->strtab + size - 1; ++p) { 561238825Smm if (*p == '/') { 562238825Smm *p++ = '\0'; 563238825Smm if (*p != '\n') 564238825Smm goto bad_string_table; 565238825Smm *p = '\0'; 566238825Smm } 567238825Smm } 568238825Smm /* 569238825Smm * GNU ar always pads the table to an even size. 570238825Smm * The pad character is either '\n' or '`'. 571238825Smm */ 572238825Smm if (p != ar->strtab + size && *p != '\n' && *p != '`') 573238825Smm goto bad_string_table; 574238825Smm 575238825Smm /* Enforce zero termination. */ 576238825Smm ar->strtab[size - 1] = '\0'; 577238825Smm 578238825Smm return (ARCHIVE_OK); 579238825Smm 580238825Smmbad_string_table: 581238825Smm archive_set_error(&a->archive, EINVAL, 582238825Smm "Invalid string table"); 583238825Smm free(ar->strtab); 584238825Smm ar->strtab = NULL; 585238825Smm return (ARCHIVE_FATAL); 586238825Smm} 587238825Smm 588238825Smmstatic uint64_t 589238825Smmar_atol8(const char *p, unsigned char_cnt) 590238825Smm{ 591238825Smm uint64_t l, limit, last_digit_limit; 592238825Smm unsigned int digit, base; 593238825Smm 594238825Smm base = 8; 595238825Smm limit = UINT64_MAX / base; 596238825Smm last_digit_limit = UINT64_MAX % base; 597238825Smm 598238825Smm while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 599238825Smm p++; 600238825Smm 601238825Smm l = 0; 602238825Smm digit = *p - '0'; 603238825Smm while (*p >= '0' && digit < base && char_cnt-- > 0) { 604238825Smm if (l>limit || (l == limit && digit > last_digit_limit)) { 605238825Smm l = UINT64_MAX; /* Truncate on overflow. */ 606238825Smm break; 607238825Smm } 608238825Smm l = (l * base) + digit; 609302001Smm digit = *++p - '0'; 610238825Smm } 611238825Smm return (l); 612238825Smm} 613238825Smm 614238825Smmstatic uint64_t 615238825Smmar_atol10(const char *p, unsigned char_cnt) 616238825Smm{ 617238825Smm uint64_t l, limit, last_digit_limit; 618238825Smm unsigned int base, digit; 619238825Smm 620238825Smm base = 10; 621238825Smm limit = UINT64_MAX / base; 622238825Smm last_digit_limit = UINT64_MAX % base; 623238825Smm 624238825Smm while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 625238825Smm p++; 626238825Smm l = 0; 627302001Smm digit = *p - '0'; 628302001Smm while (*p >= '0' && digit < base && char_cnt-- > 0) { 629302001Smm if (l > limit || (l == limit && digit > last_digit_limit)) { 630302001Smm l = UINT64_MAX; /* Truncate on overflow. */ 631302001Smm break; 632302001Smm } 633238825Smm l = (l * base) + digit; 634238825Smm digit = *++p - '0'; 635238825Smm } 636238825Smm return (l); 637238825Smm} 638238825Smm