1167346Sbms/*- 2189340Sbms * Copyright (c) 2007 Kai Wang 3167346Sbms * Copyright (c) 2007 Tim Kientzle 4167346Sbms * All rights reserved. 520529Sfenner * 6167346Sbms * Redistribution and use in source and binary forms, with or without 7167346Sbms * modification, are permitted provided that the following conditions 8167346Sbms * are met: 9167346Sbms * 1. Redistributions of source code must retain the above copyright 10167346Sbms * notice, this list of conditions and the following disclaimer 11167346Sbms * in this position and unchanged. 12167346Sbms * 2. Redistributions in binary form must reproduce the above copyright 13167346Sbms * notice, this list of conditions and the following disclaimer in the 14167346Sbms * documentation and/or other materials provided with the distribution. 15167346Sbms * 16167346Sbms * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17167346Sbms * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18167346Sbms * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19167346Sbms * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20167346Sbms * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21167346Sbms * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22167346Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23167346Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24167346Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25167346Sbms * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26167346Sbms */ 27167346Sbms 28167346Sbms#include "archive_platform.h" 2920529Sfenner__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/archive_read_support_format_ar.c 344673 2019-02-28 22:56:15Z mm $"); 3020529Sfenner 31167346Sbms#ifdef HAVE_SYS_STAT_H 32191651Sbms#include <sys/stat.h> 33191651Sbms#endif 34191651Sbms#ifdef HAVE_ERRNO_H 35191651Sbms#include <errno.h> 36191651Sbms#endif 37167346Sbms#ifdef HAVE_STDLIB_H 38167346Sbms#include <stdlib.h> 39117280Scharnier#endif 40117280Scharnier#ifdef HAVE_STRING_H 4178720Sdd#include <string.h> 4220529Sfenner#endif 43191651Sbms#ifdef HAVE_LIMITS_H 44167346Sbms#include <limits.h> 4520529Sfenner#endif 4620531Sfenner 47167346Sbms#include "archive.h" 48167346Sbms#include "archive_entry.h" 4920529Sfenner#include "archive_private.h" 5036440Sjulian#include "archive_read_private.h" 51167346Sbms 52191651Sbmsstruct ar { 5320529Sfenner int64_t entry_bytes_remaining; 54191651Sbms /* unconsumed is purely to track data we've gotten from readahead, 55191651Sbms * but haven't yet marked as consumed. Must be paired with 56191651Sbms * entry_bytes_remaining usage/modification. 57191651Sbms */ 58191651Sbms size_t entry_bytes_unconsumed; 59191651Sbms int64_t entry_offset; 60191651Sbms int64_t entry_padding; 61191651Sbms char *strtab; 6220529Sfenner size_t strtab_size; 63191651Sbms char read_global_header; 64167346Sbms}; 65167346Sbms 66167346Sbms/* 67167346Sbms * Define structure of the "ar" header. 68191651Sbms */ 69167346Sbms#define AR_name_offset 0 70167346Sbms#define AR_name_size 16 71167346Sbms#define AR_date_offset 16 72191651Sbms#define AR_date_size 12 73191651Sbms#define AR_uid_offset 28 74191651Sbms#define AR_uid_size 6 75167346Sbms#define AR_gid_offset 34 76191651Sbms#define AR_gid_size 6 77191651Sbms#define AR_mode_offset 40 78191651Sbms#define AR_mode_size 8 79191651Sbms#define AR_size_offset 48 80191651Sbms#define AR_size_size 10 81191651Sbms#define AR_fmag_offset 58 82191651Sbms#define AR_fmag_size 2 83191651Sbms 84191651Sbmsstatic int archive_read_format_ar_bid(struct archive_read *a, int); 85191651Sbmsstatic int archive_read_format_ar_cleanup(struct archive_read *a); 86191651Sbmsstatic int archive_read_format_ar_read_data(struct archive_read *a, 87191651Sbms const void **buff, size_t *size, int64_t *offset); 88191651Sbmsstatic int archive_read_format_ar_skip(struct archive_read *a); 89191651Sbmsstatic int archive_read_format_ar_read_header(struct archive_read *a, 90191651Sbms struct archive_entry *e); 91191651Sbmsstatic uint64_t ar_atol8(const char *p, unsigned char_cnt); 92191651Sbmsstatic uint64_t ar_atol10(const char *p, unsigned char_cnt); 93191651Sbmsstatic int ar_parse_gnu_filename_table(struct archive_read *a); 94191651Sbmsstatic int ar_parse_common_header(struct ar *ar, struct archive_entry *, 95191651Sbms const char *h); 96191651Sbms 97191651Sbmsint 98191651Sbmsarchive_read_support_format_ar(struct archive *_a) 99191651Sbms{ 100191651Sbms struct archive_read *a = (struct archive_read *)_a; 101167346Sbms struct ar *ar; 102167346Sbms int r; 103167346Sbms 104167346Sbms archive_check_magic(_a, ARCHIVE_READ_MAGIC, 105191651Sbms ARCHIVE_STATE_NEW, "archive_read_support_format_ar"); 106191651Sbms 107191651Sbms ar = (struct ar *)calloc(1, sizeof(*ar)); 108191651Sbms if (ar == NULL) { 109191651Sbms archive_set_error(&a->archive, ENOMEM, 110191651Sbms "Can't allocate ar data"); 111191651Sbms return (ARCHIVE_FATAL); 112191651Sbms } 113191651Sbms ar->strtab = NULL; 114191651Sbms 115191651Sbms r = __archive_read_register_format(a, 116191651Sbms ar, 117191651Sbms "ar", 118189340Sbms archive_read_format_ar_bid, 119191651Sbms NULL, 120189340Sbms archive_read_format_ar_read_header, 121191651Sbms archive_read_format_ar_read_data, 122191651Sbms archive_read_format_ar_skip, 123191651Sbms NULL, 124191651Sbms archive_read_format_ar_cleanup, 125191651Sbms NULL, 126191651Sbms NULL); 127191651Sbms 128191651Sbms if (r != ARCHIVE_OK) { 129191651Sbms free(ar); 130191651Sbms return (r); 131191651Sbms } 132191651Sbms return (ARCHIVE_OK); 133191651Sbms} 134191651Sbms 135191651Sbmsstatic int 136191651Sbmsarchive_read_format_ar_cleanup(struct archive_read *a) 137191651Sbms{ 138191651Sbms struct ar *ar; 139191651Sbms 140191651Sbms ar = (struct ar *)(a->format->data); 141191651Sbms free(ar->strtab); 142191651Sbms free(ar); 143191651Sbms (a->format->data) = NULL; 144191651Sbms return (ARCHIVE_OK); 145189340Sbms} 146189340Sbms 147191651Sbmsstatic int 148191651Sbmsarchive_read_format_ar_bid(struct archive_read *a, int best_bid) 149191651Sbms{ 150191651Sbms const void *h; 151191651Sbms 152191651Sbms (void)best_bid; /* UNUSED */ 153191651Sbms 154191651Sbms /* 155191651Sbms * Verify the 8-byte file signature. 156191651Sbms * TODO: Do we need to check more than this? 157191651Sbms */ 158191651Sbms if ((h = __archive_read_ahead(a, 8, NULL)) == NULL) 159191651Sbms return (-1); 160191651Sbms if (memcmp(h, "!<arch>\n", 8) == 0) { 161191651Sbms return (64); 162191651Sbms } 163191651Sbms return (-1); 164191651Sbms} 165191651Sbms 166191651Sbmsstatic int 167191651Sbms_ar_read_header(struct archive_read *a, struct archive_entry *entry, 168191651Sbms struct ar *ar, const char *h, size_t *unconsumed) 169191651Sbms{ 170191651Sbms char filename[AR_name_size + 1]; 171191651Sbms uint64_t number; /* Used to hold parsed numbers before validation. */ 172191651Sbms size_t bsd_name_length, entry_size; 173191651Sbms char *p, *st; 174191651Sbms const void *b; 175191651Sbms int r; 176191651Sbms 177191651Sbms /* Verify the magic signature on the file header. */ 178191651Sbms if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) { 179191651Sbms archive_set_error(&a->archive, EINVAL, 180191651Sbms "Incorrect file header signature"); 181191651Sbms return (ARCHIVE_FATAL); 182191651Sbms } 183191651Sbms 184191651Sbms /* Copy filename into work buffer. */ 185191651Sbms strncpy(filename, h + AR_name_offset, AR_name_size); 186191651Sbms filename[AR_name_size] = '\0'; 187191651Sbms 188191651Sbms /* 189191651Sbms * Guess the format variant based on the filename. 190191651Sbms */ 191191651Sbms if (a->archive.archive_format == ARCHIVE_FORMAT_AR) { 192191651Sbms /* We don't already know the variant, so let's guess. */ 193191651Sbms /* 194191651Sbms * Biggest clue is presence of '/': GNU starts special 195191651Sbms * filenames with '/', appends '/' as terminator to 19630026Scharnier * non-special names, so anything with '/' should be 197167346Sbms * GNU except for BSD long filenames. 198167346Sbms */ 199167346Sbms if (strncmp(filename, "#1/", 3) == 0) 200167346Sbms a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 201191651Sbms else if (strchr(filename, '/') != NULL) 20220529Sfenner a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; 203191651Sbms else if (strncmp(filename, "__.SYMDEF", 9) == 0) 204191651Sbms a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 205191651Sbms /* 206167346Sbms * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/' 207244538Skevlo * if name exactly fills 16-byte field? If so, we 208191651Sbms * can't assume entries without '/' are BSD. XXX 209191651Sbms */ 210191651Sbms } 211191651Sbms 212244538Skevlo /* Update format name from the code. */ 213191651Sbms if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) 214191651Sbms a->archive.archive_format_name = "ar (GNU/SVR4)"; 215223510Sjhb else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) 216223510Sjhb a->archive.archive_format_name = "ar (BSD)"; 21720529Sfenner else 218167346Sbms a->archive.archive_format_name = "ar"; 219167346Sbms 220167346Sbms /* 221167346Sbms * Remove trailing spaces from the filename. GNU and BSD 222167346Sbms * variants both pad filename area out with spaces. 223167346Sbms * This will only be wrong if GNU/SVR4 'ar' implementations 224167346Sbms * omit trailing '/' for 16-char filenames and we have 225167346Sbms * a 16-char filename that ends in ' '. 226191651Sbms */ 227167346Sbms p = filename + AR_name_size - 1; 228167346Sbms while (p >= filename && *p == ' ') { 229167346Sbms *p = '\0'; 230167346Sbms p--; 231167346Sbms } 232167346Sbms 233191651Sbms /* 234167346Sbms * Remove trailing slash unless first character is '/'. 235167346Sbms * (BSD entries never end in '/', so this will only trim 236167346Sbms * GNU-format entries. GNU special entries start with '/' 237167346Sbms * and are not terminated in '/', so we don't trim anything 238167346Sbms * that starts with '/'.) 239191651Sbms */ 240167346Sbms if (filename[0] != '/' && p > filename && *p == '/') { 241167346Sbms *p = '\0'; 24220529Sfenner } 243191651Sbms 244191651Sbms if (p < filename) { 245191651Sbms archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 246191651Sbms "Found entry with empty filename"); 247191651Sbms return (ARCHIVE_FATAL); 248167346Sbms } 249167346Sbms 250167346Sbms /* 251167346Sbms * '//' is the GNU filename table. 252191651Sbms * Later entries can refer to names in this table. 253167346Sbms */ 254167346Sbms if (strcmp(filename, "//") == 0) { 255167346Sbms /* This must come before any call to _read_ahead. */ 256167346Sbms ar_parse_common_header(ar, entry, h); 257167346Sbms archive_entry_copy_pathname(entry, filename); 258167346Sbms archive_entry_set_filetype(entry, AE_IFREG); 259167346Sbms /* Get the size of the filename table. */ 260167346Sbms number = ar_atol10(h + AR_size_offset, AR_size_size); 261167346Sbms if (number > SIZE_MAX || number > 1024 * 1024 * 1024) { 262167346Sbms archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 263167346Sbms "Filename table too large"); 264167346Sbms return (ARCHIVE_FATAL); 265167346Sbms } 266167346Sbms entry_size = (size_t)number; 267167346Sbms if (entry_size == 0) { 268167346Sbms archive_set_error(&a->archive, EINVAL, 269167346Sbms "Invalid string table"); 270191651Sbms return (ARCHIVE_FATAL); 271167346Sbms } 272167346Sbms if (ar->strtab != NULL) { 273167346Sbms archive_set_error(&a->archive, EINVAL, 274167346Sbms "More than one string tables exist"); 275167346Sbms return (ARCHIVE_FATAL); 276191651Sbms } 277191651Sbms 278191651Sbms /* Read the filename table into memory. */ 279191651Sbms st = malloc(entry_size); 280191651Sbms if (st == NULL) { 281191651Sbms archive_set_error(&a->archive, ENOMEM, 282191651Sbms "Can't allocate filename table buffer"); 283191651Sbms return (ARCHIVE_FATAL); 284191651Sbms } 285191651Sbms ar->strtab = st; 286191651Sbms ar->strtab_size = entry_size; 287191651Sbms 288191651Sbms if (*unconsumed) { 289191651Sbms __archive_read_consume(a, *unconsumed); 290191651Sbms *unconsumed = 0; 291191651Sbms } 292191651Sbms 293191651Sbms if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL) 294191651Sbms return (ARCHIVE_FATAL); 295191651Sbms memcpy(st, b, entry_size); 296191651Sbms __archive_read_consume(a, entry_size); 297191651Sbms /* All contents are consumed. */ 298191651Sbms ar->entry_bytes_remaining = 0; 299191651Sbms archive_entry_set_size(entry, ar->entry_bytes_remaining); 300191651Sbms 301191651Sbms /* Parse the filename table. */ 302191651Sbms return (ar_parse_gnu_filename_table(a)); 303191651Sbms } 304191651Sbms 305191651Sbms /* 306191651Sbms * GNU variant handles long filenames by storing /<number> 307191651Sbms * to indicate a name stored in the filename table. 308191651Sbms * XXX TODO: Verify that it's all digits... Don't be fooled 309191651Sbms * by "/9xyz" XXX 310191651Sbms */ 311191651Sbms if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') { 312191651Sbms number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); 313191651Sbms /* 314191651Sbms * If we can't look up the real name, warn and return 315191651Sbms * the entry with the wrong name. 316191651Sbms */ 317191651Sbms if (ar->strtab == NULL || number >= ar->strtab_size) { 318191651Sbms archive_set_error(&a->archive, EINVAL, 319191651Sbms "Can't find long filename for GNU/SVR4 archive entry"); 320191651Sbms archive_entry_copy_pathname(entry, filename); 321191651Sbms /* Parse the time, owner, mode, size fields. */ 322191651Sbms ar_parse_common_header(ar, entry, h); 323191651Sbms return (ARCHIVE_FATAL); 324191651Sbms } 325191651Sbms 326191651Sbms archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]); 327191651Sbms /* Parse the time, owner, mode, size fields. */ 328191651Sbms return (ar_parse_common_header(ar, entry, h)); 329191651Sbms } 330191651Sbms 331191651Sbms /* 332191651Sbms * BSD handles long filenames by storing "#1/" followed by the 333191651Sbms * length of filename as a decimal number, then prepends the 334191651Sbms * the filename to the file contents. 335191651Sbms */ 336191651Sbms if (strncmp(filename, "#1/", 3) == 0) { 337191651Sbms /* Parse the time, owner, mode, size fields. */ 338191651Sbms /* This must occur before _read_ahead is called again. */ 339191651Sbms ar_parse_common_header(ar, entry, h); 340191651Sbms 341191651Sbms /* Parse the size of the name, adjust the file size. */ 342191651Sbms number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); 343191651Sbms /* Sanity check the filename length: 344191651Sbms * = Must be <= SIZE_MAX - 1 345191651Sbms * = Must be <= 1MB 346191651Sbms * = Cannot be bigger than the entire entry 347191651Sbms */ 348191651Sbms if (number > SIZE_MAX - 1 349191651Sbms || number > 1024 * 1024 350191651Sbms || (int64_t)number > ar->entry_bytes_remaining) { 351191651Sbms archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 352191651Sbms "Bad input file size"); 353191651Sbms return (ARCHIVE_FATAL); 354191651Sbms } 355191651Sbms bsd_name_length = (size_t)number; 356191651Sbms ar->entry_bytes_remaining -= bsd_name_length; 357191651Sbms /* Adjust file size reported to client. */ 358191651Sbms archive_entry_set_size(entry, ar->entry_bytes_remaining); 359191651Sbms 360191651Sbms if (*unconsumed) { 361191651Sbms __archive_read_consume(a, *unconsumed); 362191651Sbms *unconsumed = 0; 363191651Sbms } 364191651Sbms 365191651Sbms /* Read the long name into memory. */ 366191651Sbms if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) { 367191651Sbms archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 368191651Sbms "Truncated input file"); 369191651Sbms return (ARCHIVE_FATAL); 370191651Sbms } 371191651Sbms /* Store it in the entry. */ 372191651Sbms p = (char *)malloc(bsd_name_length + 1); 373191651Sbms if (p == NULL) { 374191651Sbms archive_set_error(&a->archive, ENOMEM, 375167346Sbms "Can't allocate fname buffer"); 376223510Sjhb return (ARCHIVE_FATAL); 377167346Sbms } 378167346Sbms strncpy(p, b, bsd_name_length); 379167346Sbms p[bsd_name_length] = '\0'; 380170613Sbms 381191651Sbms __archive_read_consume(a, bsd_name_length); 382191651Sbms 383167346Sbms archive_entry_copy_pathname(entry, p); 384167346Sbms free(p); 385191651Sbms return (ARCHIVE_OK); 386191651Sbms } 387191651Sbms 388191651Sbms /* 389191651Sbms * "/" is the SVR4/GNU archive symbol table. 390167346Sbms * "/SYM64/" is the SVR4/GNU 64-bit variant archive symbol table. 391191651Sbms */ 392191651Sbms if (strcmp(filename, "/") == 0 || strcmp(filename, "/SYM64/") == 0) { 393191651Sbms archive_entry_copy_pathname(entry, filename); 394191651Sbms /* Parse the time, owner, mode, size fields. */ 395167346Sbms r = ar_parse_common_header(ar, entry, h); 396167346Sbms /* Force the file type to a regular file. */ 397167346Sbms archive_entry_set_filetype(entry, AE_IFREG); 398167346Sbms return (r); 399167346Sbms } 400167346Sbms 401167346Sbms /* 40220529Sfenner * "__.SYMDEF" is a BSD archive symbol table. 40320529Sfenner */ 404167346Sbms if (strcmp(filename, "__.SYMDEF") == 0) { 405167346Sbms archive_entry_copy_pathname(entry, filename); 406167346Sbms /* Parse the time, owner, mode, size fields. */ 407167346Sbms return (ar_parse_common_header(ar, entry, h)); 408167346Sbms } 409167346Sbms 410167346Sbms /* 411167346Sbms * Otherwise, this is a standard entry. The filename 412167346Sbms * has already been trimmed as much as possible, based 413167346Sbms * on our current knowledge of the format. 414167346Sbms */ 41520529Sfenner archive_entry_copy_pathname(entry, filename); 41620529Sfenner return (ar_parse_common_header(ar, entry, h)); 417167346Sbms} 418167346Sbms 419189340Sbmsstatic int 420191651Sbmsarchive_read_format_ar_read_header(struct archive_read *a, 421189340Sbms struct archive_entry *entry) 422191651Sbms{ 423191651Sbms struct ar *ar = (struct ar*)(a->format->data); 424191651Sbms size_t unconsumed; 425191651Sbms const void *header_data; 426191651Sbms int ret; 427191651Sbms 428191651Sbms if (!ar->read_global_header) { 429191651Sbms /* 430191651Sbms * We are now at the beginning of the archive, 431191651Sbms * so we need first consume the ar global header. 432191651Sbms */ 433191651Sbms __archive_read_consume(a, 8); 434191651Sbms ar->read_global_header = 1; 435189340Sbms /* Set a default format code for now. */ 436189340Sbms a->archive.archive_format = ARCHIVE_FORMAT_AR; 437189340Sbms } 438191651Sbms 439191651Sbms /* Read the header for the next file entry. */ 440191651Sbms if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL) 441191651Sbms /* Broken header. */ 442191651Sbms return (ARCHIVE_EOF); 443191651Sbms 444191651Sbms unconsumed = 60; 445191651Sbms 446191651Sbms ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed); 447191651Sbms 448189340Sbms if (unconsumed) 449191651Sbms __archive_read_consume(a, unconsumed); 450191651Sbms 451191651Sbms return ret; 452189340Sbms} 453191651Sbms 454191651Sbms 455191651Sbmsstatic int 456191651Sbmsar_parse_common_header(struct ar *ar, struct archive_entry *entry, 457191651Sbms const char *h) 458191651Sbms{ 459191651Sbms uint64_t n; 460191651Sbms 461191651Sbms /* Copy remaining header */ 462223510Sjhb archive_entry_set_filetype(entry, AE_IFREG); 463223510Sjhb archive_entry_set_mtime(entry, 464223510Sjhb (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L); 465223510Sjhb archive_entry_set_uid(entry, 466191651Sbms (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size)); 467189340Sbms archive_entry_set_gid(entry, 468191651Sbms (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size)); 469191651Sbms archive_entry_set_mode(entry, 470191651Sbms (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size)); 471189340Sbms n = ar_atol10(h + AR_size_offset, AR_size_size); 472191651Sbms 473191651Sbms ar->entry_offset = 0; 474191651Sbms ar->entry_padding = n % 2; 475191651Sbms archive_entry_set_size(entry, n); 476191651Sbms ar->entry_bytes_remaining = n; 477191651Sbms return (ARCHIVE_OK); 478191651Sbms} 479191651Sbms 480191651Sbmsstatic int 481191651Sbmsarchive_read_format_ar_read_data(struct archive_read *a, 482191651Sbms const void **buff, size_t *size, int64_t *offset) 483191651Sbms{ 484191651Sbms ssize_t bytes_read; 485191651Sbms struct ar *ar; 486191651Sbms 487191651Sbms ar = (struct ar *)(a->format->data); 488191651Sbms 489191651Sbms if (ar->entry_bytes_unconsumed) { 490191651Sbms __archive_read_consume(a, ar->entry_bytes_unconsumed); 491191651Sbms ar->entry_bytes_unconsumed = 0; 492191651Sbms } 493191651Sbms 494191651Sbms if (ar->entry_bytes_remaining > 0) { 495191651Sbms *buff = __archive_read_ahead(a, 1, &bytes_read); 496191651Sbms if (bytes_read == 0) { 497191651Sbms archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 498191651Sbms "Truncated ar archive"); 499191651Sbms return (ARCHIVE_FATAL); 500191651Sbms } 501191651Sbms if (bytes_read < 0) 502191651Sbms return (ARCHIVE_FATAL); 503191651Sbms if (bytes_read > ar->entry_bytes_remaining) 504223510Sjhb bytes_read = (ssize_t)ar->entry_bytes_remaining; 505223510Sjhb *size = bytes_read; 506223510Sjhb ar->entry_bytes_unconsumed = bytes_read; 507223510Sjhb *offset = ar->entry_offset; 508191651Sbms ar->entry_offset += bytes_read; 509191651Sbms ar->entry_bytes_remaining -= bytes_read; 510191651Sbms return (ARCHIVE_OK); 511191651Sbms } else { 512191651Sbms int64_t skipped = __archive_read_consume(a, ar->entry_padding); 513191651Sbms if (skipped >= 0) { 514191651Sbms ar->entry_padding -= skipped; 515191651Sbms } 516191651Sbms if (ar->entry_padding) { 517191651Sbms if (skipped >= 0) { 518191651Sbms archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 519191651Sbms "Truncated ar archive- failed consuming padding"); 520191651Sbms } 521191651Sbms return (ARCHIVE_FATAL); 522191651Sbms } 523191651Sbms *buff = NULL; 524191651Sbms *size = 0; 525191651Sbms *offset = ar->entry_offset; 526191651Sbms return (ARCHIVE_EOF); 527191651Sbms } 528191651Sbms} 529191651Sbms 530191651Sbmsstatic int 531191651Sbmsarchive_read_format_ar_skip(struct archive_read *a) 532191651Sbms{ 533191651Sbms int64_t bytes_skipped; 534191651Sbms struct ar* ar; 535191651Sbms 536191651Sbms ar = (struct ar *)(a->format->data); 537191651Sbms 538191651Sbms bytes_skipped = __archive_read_consume(a, 539191651Sbms ar->entry_bytes_remaining + ar->entry_padding 540191651Sbms + ar->entry_bytes_unconsumed); 541191651Sbms if (bytes_skipped < 0) 542191651Sbms return (ARCHIVE_FATAL); 543191651Sbms 544191651Sbms ar->entry_bytes_remaining = 0; 545223510Sjhb ar->entry_bytes_unconsumed = 0; 546223510Sjhb ar->entry_padding = 0; 547223510Sjhb 548223510Sjhb return (ARCHIVE_OK); 549191651Sbms} 550191651Sbms 551191651Sbmsstatic int 552191651Sbmsar_parse_gnu_filename_table(struct archive_read *a) 553191651Sbms{ 554191651Sbms struct ar *ar; 555191651Sbms char *p; 556191651Sbms size_t size; 557191651Sbms 558191651Sbms ar = (struct ar*)(a->format->data); 559191651Sbms size = ar->strtab_size; 560191651Sbms 561191651Sbms for (p = ar->strtab; p < ar->strtab + size - 1; ++p) { 562191651Sbms if (*p == '/') { 563191651Sbms *p++ = '\0'; 564191651Sbms if (*p != '\n') 565191651Sbms goto bad_string_table; 566191651Sbms *p = '\0'; 567191651Sbms } 568191651Sbms } 569191651Sbms /* 570191651Sbms * GNU ar always pads the table to an even size. 571191651Sbms * The pad character is either '\n' or '`'. 572191651Sbms */ 573191651Sbms if (p != ar->strtab + size && *p != '\n' && *p != '`') 574191651Sbms goto bad_string_table; 575191651Sbms 576191651Sbms /* Enforce zero termination. */ 577191651Sbms ar->strtab[size - 1] = '\0'; 578191651Sbms 579191651Sbms return (ARCHIVE_OK); 580191651Sbms 581191651Sbmsbad_string_table: 582191651Sbms archive_set_error(&a->archive, EINVAL, 583191651Sbms "Invalid string table"); 584191651Sbms free(ar->strtab); 585191651Sbms ar->strtab = NULL; 586191651Sbms return (ARCHIVE_FATAL); 587191651Sbms} 588191651Sbms 589191651Sbmsstatic uint64_t 590191651Sbmsar_atol8(const char *p, unsigned char_cnt) 591191651Sbms{ 592191651Sbms uint64_t l, limit, last_digit_limit; 593191651Sbms unsigned int digit, base; 594191651Sbms 595191651Sbms base = 8; 596191651Sbms limit = UINT64_MAX / base; 597191651Sbms last_digit_limit = UINT64_MAX % base; 598191651Sbms 599191651Sbms while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 600191651Sbms p++; 601191651Sbms 602191651Sbms l = 0; 603191651Sbms digit = *p - '0'; 604191651Sbms while (*p >= '0' && digit < base && char_cnt-- > 0) { 605191651Sbms if (l>limit || (l == limit && digit > last_digit_limit)) { 606191651Sbms l = UINT64_MAX; /* Truncate on overflow. */ 607191651Sbms break; 608223510Sjhb } 609223510Sjhb l = (l * base) + digit; 610223510Sjhb digit = *++p - '0'; 611223510Sjhb } 612191651Sbms return (l); 613191651Sbms} 614191651Sbms 615191651Sbmsstatic uint64_t 616191651Sbmsar_atol10(const char *p, unsigned char_cnt) 617191651Sbms{ 618191651Sbms uint64_t l, limit, last_digit_limit; 619191651Sbms unsigned int base, digit; 620191651Sbms 621191651Sbms base = 10; 622191651Sbms limit = UINT64_MAX / base; 623191651Sbms last_digit_limit = UINT64_MAX % base; 624191651Sbms 625191651Sbms while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 626191651Sbms p++; 627189340Sbms l = 0; 628189340Sbms digit = *p - '0'; 629189340Sbms while (*p >= '0' && digit < base && char_cnt-- > 0) { 630191651Sbms if (l > limit || (l == limit && digit > last_digit_limit)) { 631191651Sbms l = UINT64_MAX; /* Truncate on overflow. */ 632191651Sbms break; 633191651Sbms } 634191651Sbms l = (l * base) + digit; 635191651Sbms digit = *++p - '0'; 636191651Sbms } 637191651Sbms return (l); 638191651Sbms} 639191651Sbms