archive_read_support_format_ar.c revision 228753
1107120Sjulian/*- 2107120Sjulian * Copyright (c) 2007 Kai Wang 3139823Simp * Copyright (c) 2007 Tim Kientzle 4139823Simp * All rights reserved. 5139823Simp * 6107120Sjulian * Redistribution and use in source and binary forms, with or without 7107120Sjulian * modification, are permitted provided that the following conditions 8107120Sjulian * are met: 9107120Sjulian * 1. Redistributions of source code must retain the above copyright 10107120Sjulian * notice, this list of conditions and the following disclaimer 11107120Sjulian * in this position and unchanged. 12107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer in the 14107120Sjulian * documentation and/or other materials provided with the distribution. 15107120Sjulian * 16107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17107120Sjulian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18107120Sjulian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19107120Sjulian * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20107120Sjulian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21107120Sjulian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22107120Sjulian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23107120Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24107120Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25107120Sjulian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26107120Sjulian */ 27107120Sjulian 28107120Sjulian#include "archive_platform.h" 29107120Sjulian__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_ar.c 201101 2009-12-28 03:06:27Z kientzle $"); 30121054Semax 31107120Sjulian#ifdef HAVE_SYS_STAT_H 32107120Sjulian#include <sys/stat.h> 33107120Sjulian#endif 34107120Sjulian#ifdef HAVE_ERRNO_H 35107120Sjulian#include <errno.h> 36107120Sjulian#endif 37107120Sjulian#ifdef HAVE_STDLIB_H 38107120Sjulian#include <stdlib.h> 39107120Sjulian#endif 40107120Sjulian#ifdef HAVE_STRING_H 41107120Sjulian#include <string.h> 42107120Sjulian#endif 43128688Semax#ifdef HAVE_LIMITS_H 44128688Semax#include <limits.h> 45128688Semax#endif 46128688Semax 47128688Semax#include "archive.h" 48128688Semax#include "archive_entry.h" 49128688Semax#include "archive_private.h" 50107120Sjulian#include "archive_read_private.h" 51107120Sjulian 52107120Sjulianstruct ar { 53107120Sjulian off_t entry_bytes_remaining; 54107120Sjulian off_t entry_offset; 55107120Sjulian off_t entry_padding; 56107120Sjulian char *strtab; 57107120Sjulian size_t strtab_size; 58107120Sjulian}; 59107120Sjulian 60107120Sjulian/* 61107120Sjulian * Define structure of the "ar" header. 62107120Sjulian */ 63107120Sjulian#define AR_name_offset 0 64107120Sjulian#define AR_name_size 16 65107120Sjulian#define AR_date_offset 16 66107120Sjulian#define AR_date_size 12 67107120Sjulian#define AR_uid_offset 28 68107120Sjulian#define AR_uid_size 6 69107120Sjulian#define AR_gid_offset 34 70107120Sjulian#define AR_gid_size 6 71107120Sjulian#define AR_mode_offset 40 72107120Sjulian#define AR_mode_size 8 73107120Sjulian#define AR_size_offset 48 74107120Sjulian#define AR_size_size 10 75107120Sjulian#define AR_fmag_offset 58 76107120Sjulian#define AR_fmag_size 2 77107120Sjulian 78107120Sjulianstatic int archive_read_format_ar_bid(struct archive_read *a); 79107120Sjulianstatic int archive_read_format_ar_cleanup(struct archive_read *a); 80107120Sjulianstatic int archive_read_format_ar_read_data(struct archive_read *a, 81107120Sjulian const void **buff, size_t *size, off_t *offset); 82107120Sjulianstatic int archive_read_format_ar_skip(struct archive_read *a); 83107120Sjulianstatic int archive_read_format_ar_read_header(struct archive_read *a, 84107120Sjulian struct archive_entry *e); 85107120Sjulianstatic uint64_t ar_atol8(const char *p, unsigned char_cnt); 86107120Sjulianstatic uint64_t ar_atol10(const char *p, unsigned char_cnt); 87107120Sjulianstatic int ar_parse_gnu_filename_table(struct archive_read *a); 88107120Sjulianstatic int ar_parse_common_header(struct ar *ar, struct archive_entry *, 89107120Sjulian const char *h); 90107120Sjulian 91107120Sjulianint 92107120Sjulianarchive_read_support_format_ar(struct archive *_a) 93107120Sjulian{ 94107120Sjulian struct archive_read *a = (struct archive_read *)_a; 95107120Sjulian struct ar *ar; 96107120Sjulian int r; 97107120Sjulian 98107120Sjulian ar = (struct ar *)malloc(sizeof(*ar)); 99107120Sjulian if (ar == NULL) { 100107120Sjulian archive_set_error(&a->archive, ENOMEM, 101107120Sjulian "Can't allocate ar data"); 102107120Sjulian return (ARCHIVE_FATAL); 103107120Sjulian } 104107120Sjulian memset(ar, 0, sizeof(*ar)); 105107120Sjulian ar->strtab = NULL; 106107120Sjulian 107107120Sjulian r = __archive_read_register_format(a, 108107120Sjulian ar, 109107120Sjulian "ar", 110107120Sjulian archive_read_format_ar_bid, 111107120Sjulian NULL, 112107120Sjulian archive_read_format_ar_read_header, 113107120Sjulian archive_read_format_ar_read_data, 114107120Sjulian archive_read_format_ar_skip, 115107120Sjulian archive_read_format_ar_cleanup); 116107120Sjulian 117107120Sjulian if (r != ARCHIVE_OK) { 118107120Sjulian free(ar); 119107120Sjulian return (r); 120107120Sjulian } 121107120Sjulian return (ARCHIVE_OK); 122107120Sjulian} 123107120Sjulian 124107120Sjulianstatic int 125107120Sjulianarchive_read_format_ar_cleanup(struct archive_read *a) 126107120Sjulian{ 127107120Sjulian struct ar *ar; 128107120Sjulian 129107120Sjulian ar = (struct ar *)(a->format->data); 130107120Sjulian if (ar->strtab) 131107120Sjulian free(ar->strtab); 132107120Sjulian free(ar); 133107120Sjulian (a->format->data) = NULL; 134107120Sjulian return (ARCHIVE_OK); 135107120Sjulian} 136107120Sjulian 137114878Sjulianstatic int 138107120Sjulianarchive_read_format_ar_bid(struct archive_read *a) 139107120Sjulian{ 140107120Sjulian const void *h; 141114878Sjulian 142107120Sjulian if (a->archive.archive_format != 0 && 143107120Sjulian (a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) != 144107120Sjulian ARCHIVE_FORMAT_AR) 145107120Sjulian return(0); 146114878Sjulian 147107120Sjulian /* 148107120Sjulian * Verify the 8-byte file signature. 149107120Sjulian * TODO: Do we need to check more than this? 150107120Sjulian */ 151107120Sjulian if ((h = __archive_read_ahead(a, 8, NULL)) == NULL) 152107120Sjulian return (-1); 153107120Sjulian if (strncmp((const char*)h, "!<arch>\n", 8) == 0) { 154107120Sjulian return (64); 155107120Sjulian } 156107120Sjulian return (-1); 157107120Sjulian} 158107120Sjulian 159107120Sjulianstatic int 160107120Sjulianarchive_read_format_ar_read_header(struct archive_read *a, 161107120Sjulian struct archive_entry *entry) 162107120Sjulian{ 163107120Sjulian char filename[AR_name_size + 1]; 164107120Sjulian struct ar *ar; 165107120Sjulian uint64_t number; /* Used to hold parsed numbers before validation. */ 166107120Sjulian ssize_t bytes_read; 167107120Sjulian size_t bsd_name_length, entry_size; 168107120Sjulian char *p, *st; 169107120Sjulian const void *b; 170107120Sjulian const char *h; 171107120Sjulian int r; 172107120Sjulian 173107120Sjulian ar = (struct ar*)(a->format->data); 174107120Sjulian 175107120Sjulian if (a->archive.file_position == 0) { 176107120Sjulian /* 177107120Sjulian * We are now at the beginning of the archive, 178107120Sjulian * so we need first consume the ar global header. 179107120Sjulian */ 180107120Sjulian __archive_read_consume(a, 8); 181107120Sjulian /* Set a default format code for now. */ 182107120Sjulian a->archive.archive_format = ARCHIVE_FORMAT_AR; 183107120Sjulian } 184107120Sjulian 185107120Sjulian /* Read the header for the next file entry. */ 186107120Sjulian if ((b = __archive_read_ahead(a, 60, &bytes_read)) == NULL) 187107120Sjulian /* Broken header. */ 188107120Sjulian return (ARCHIVE_EOF); 189107120Sjulian __archive_read_consume(a, 60); 190107120Sjulian h = (const char *)b; 191107120Sjulian 192107120Sjulian /* Verify the magic signature on the file header. */ 193107120Sjulian if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) { 194107120Sjulian archive_set_error(&a->archive, EINVAL, 195107120Sjulian "Incorrect file header signature"); 196107120Sjulian return (ARCHIVE_WARN); 197107120Sjulian } 198107120Sjulian 199107120Sjulian /* Copy filename into work buffer. */ 200121054Semax strncpy(filename, h + AR_name_offset, AR_name_size); 201121054Semax filename[AR_name_size] = '\0'; 202121054Semax 203107120Sjulian /* 204107120Sjulian * Guess the format variant based on the filename. 205107120Sjulian */ 206107120Sjulian if (a->archive.archive_format == ARCHIVE_FORMAT_AR) { 207107120Sjulian /* We don't already know the variant, so let's guess. */ 208107120Sjulian /* 209107120Sjulian * Biggest clue is presence of '/': GNU starts special 210107120Sjulian * filenames with '/', appends '/' as terminator to 211107120Sjulian * non-special names, so anything with '/' should be 212107120Sjulian * GNU except for BSD long filenames. 213107120Sjulian */ 214107120Sjulian if (strncmp(filename, "#1/", 3) == 0) 215107120Sjulian a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 216107120Sjulian else if (strchr(filename, '/') != NULL) 217107120Sjulian a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; 218107120Sjulian else if (strncmp(filename, "__.SYMDEF", 9) == 0) 219107120Sjulian a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 220107120Sjulian /* 221107120Sjulian * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/' 222107120Sjulian * if name exactly fills 16-byte field? If so, we 223107120Sjulian * can't assume entries without '/' are BSD. XXX 224107120Sjulian */ 225107120Sjulian } 226107120Sjulian 227243882Sglebius /* Update format name from the code. */ 228107120Sjulian if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) 229107120Sjulian a->archive.archive_format_name = "ar (GNU/SVR4)"; 230107120Sjulian else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) 231107120Sjulian a->archive.archive_format_name = "ar (BSD)"; 232107120Sjulian else 233107120Sjulian a->archive.archive_format_name = "ar"; 234107120Sjulian 235107120Sjulian /* 236107120Sjulian * Remove trailing spaces from the filename. GNU and BSD 237107120Sjulian * variants both pad filename area out with spaces. 238107120Sjulian * This will only be wrong if GNU/SVR4 'ar' implementations 239107120Sjulian * omit trailing '/' for 16-char filenames and we have 240107120Sjulian * a 16-char filename that ends in ' '. 241107120Sjulian */ 242107120Sjulian p = filename + AR_name_size - 1; 243107120Sjulian while (p >= filename && *p == ' ') { 244107120Sjulian *p = '\0'; 245107120Sjulian p--; 246107120Sjulian } 247107120Sjulian 248107120Sjulian /* 249107120Sjulian * Remove trailing slash unless first character is '/'. 250114878Sjulian * (BSD entries never end in '/', so this will only trim 251114878Sjulian * GNU-format entries. GNU special entries start with '/' 252114878Sjulian * and are not terminated in '/', so we don't trim anything 253107120Sjulian * that starts with '/'.) 254107120Sjulian */ 255107120Sjulian if (filename[0] != '/' && *p == '/') 256107120Sjulian *p = '\0'; 257114878Sjulian 258107120Sjulian /* 259107120Sjulian * '//' is the GNU filename table. 260107120Sjulian * Later entries can refer to names in this table. 261107120Sjulian */ 262107120Sjulian if (strcmp(filename, "//") == 0) { 263107120Sjulian /* This must come before any call to _read_ahead. */ 264107120Sjulian ar_parse_common_header(ar, entry, h); 265107120Sjulian archive_entry_copy_pathname(entry, filename); 266107120Sjulian archive_entry_set_filetype(entry, AE_IFREG); 267107120Sjulian /* Get the size of the filename table. */ 268107120Sjulian number = ar_atol10(h + AR_size_offset, AR_size_size); 269107120Sjulian if (number > SIZE_MAX) { 270107120Sjulian archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 271107120Sjulian "Filename table too large"); 272107120Sjulian return (ARCHIVE_FATAL); 273107120Sjulian } 274107120Sjulian entry_size = (size_t)number; 275107120Sjulian if (entry_size == 0) { 276107120Sjulian archive_set_error(&a->archive, EINVAL, 277107120Sjulian "Invalid string table"); 278107120Sjulian return (ARCHIVE_WARN); 279107120Sjulian } 280107120Sjulian if (ar->strtab != NULL) { 281107120Sjulian archive_set_error(&a->archive, EINVAL, 282107120Sjulian "More than one string tables exist"); 283107120Sjulian return (ARCHIVE_WARN); 284107120Sjulian } 285107120Sjulian 286107120Sjulian /* Read the filename table into memory. */ 287107120Sjulian st = malloc(entry_size); 288107120Sjulian if (st == NULL) { 289107120Sjulian archive_set_error(&a->archive, ENOMEM, 290107120Sjulian "Can't allocate filename table buffer"); 291107120Sjulian return (ARCHIVE_FATAL); 292107120Sjulian } 293107120Sjulian ar->strtab = st; 294107120Sjulian ar->strtab_size = entry_size; 295107120Sjulian if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL) 296107120Sjulian return (ARCHIVE_FATAL); 297107120Sjulian memcpy(st, b, entry_size); 298107120Sjulian __archive_read_consume(a, entry_size); 299107120Sjulian /* All contents are consumed. */ 300107120Sjulian ar->entry_bytes_remaining = 0; 301107120Sjulian archive_entry_set_size(entry, ar->entry_bytes_remaining); 302107120Sjulian 303107120Sjulian /* Parse the filename table. */ 304107120Sjulian return (ar_parse_gnu_filename_table(a)); 305107120Sjulian } 306107120Sjulian 307107120Sjulian /* 308107120Sjulian * GNU variant handles long filenames by storing /<number> 309107120Sjulian * to indicate a name stored in the filename table. 310107120Sjulian * XXX TODO: Verify that it's all digits... Don't be fooled 311107120Sjulian * by "/9xyz" XXX 312107120Sjulian */ 313107120Sjulian if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') { 314107120Sjulian number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); 315107120Sjulian /* 316107120Sjulian * If we can't look up the real name, warn and return 317107120Sjulian * the entry with the wrong name. 318107120Sjulian */ 319107120Sjulian if (ar->strtab == NULL || number > ar->strtab_size) { 320107120Sjulian archive_set_error(&a->archive, EINVAL, 321107120Sjulian "Can't find long filename for entry"); 322107120Sjulian archive_entry_copy_pathname(entry, filename); 323107120Sjulian /* Parse the time, owner, mode, size fields. */ 324107120Sjulian ar_parse_common_header(ar, entry, h); 325107120Sjulian return (ARCHIVE_WARN); 326107120Sjulian } 327107120Sjulian 328107120Sjulian archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]); 329107120Sjulian /* Parse the time, owner, mode, size fields. */ 330107120Sjulian return (ar_parse_common_header(ar, entry, h)); 331107120Sjulian } 332107120Sjulian 333107120Sjulian /* 334107120Sjulian * BSD handles long filenames by storing "#1/" followed by the 335107120Sjulian * length of filename as a decimal number, then prepends the 336107120Sjulian * the filename to the file contents. 337107120Sjulian */ 338107120Sjulian if (strncmp(filename, "#1/", 3) == 0) { 339107120Sjulian /* Parse the time, owner, mode, size fields. */ 340107120Sjulian /* This must occur before _read_ahead is called again. */ 341107120Sjulian ar_parse_common_header(ar, entry, h); 342107120Sjulian 343107120Sjulian /* Parse the size of the name, adjust the file size. */ 344107120Sjulian number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); 345107120Sjulian bsd_name_length = (size_t)number; 346107120Sjulian /* Guard against the filename + trailing NUL 347107120Sjulian * overflowing a size_t and against the filename size 348107120Sjulian * being larger than the entire entry. */ 349107120Sjulian if (number > (uint64_t)(bsd_name_length + 1) 350107120Sjulian || (off_t)bsd_name_length > ar->entry_bytes_remaining) { 351107120Sjulian archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 352107120Sjulian "Bad input file size"); 353107120Sjulian return (ARCHIVE_FATAL); 354107120Sjulian } 355107120Sjulian ar->entry_bytes_remaining -= bsd_name_length; 356107120Sjulian /* Adjust file size reported to client. */ 357107120Sjulian archive_entry_set_size(entry, ar->entry_bytes_remaining); 358107120Sjulian 359107120Sjulian /* Read the long name into memory. */ 360107120Sjulian if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) { 361107120Sjulian archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 362107120Sjulian "Truncated input file"); 363107120Sjulian return (ARCHIVE_FATAL); 364107120Sjulian } 365107120Sjulian __archive_read_consume(a, bsd_name_length); 366107120Sjulian 367107120Sjulian /* Store it in the entry. */ 368107120Sjulian p = (char *)malloc(bsd_name_length + 1); 369107120Sjulian if (p == NULL) { 370107120Sjulian archive_set_error(&a->archive, ENOMEM, 371107120Sjulian "Can't allocate fname buffer"); 372107120Sjulian return (ARCHIVE_FATAL); 373107120Sjulian } 374107120Sjulian strncpy(p, b, bsd_name_length); 375107120Sjulian p[bsd_name_length] = '\0'; 376107120Sjulian archive_entry_copy_pathname(entry, p); 377107120Sjulian free(p); 378107120Sjulian return (ARCHIVE_OK); 379107120Sjulian } 380107120Sjulian 381107120Sjulian /* 382107120Sjulian * "/" is the SVR4/GNU archive symbol table. 383107120Sjulian */ 384107120Sjulian if (strcmp(filename, "/") == 0) { 385107120Sjulian archive_entry_copy_pathname(entry, "/"); 386107120Sjulian /* Parse the time, owner, mode, size fields. */ 387107120Sjulian r = ar_parse_common_header(ar, entry, h); 388107120Sjulian /* Force the file type to a regular file. */ 389107120Sjulian archive_entry_set_filetype(entry, AE_IFREG); 390107120Sjulian return (r); 391107120Sjulian } 392107120Sjulian 393121054Semax /* 394250576Seadler * "__.SYMDEF" is a BSD archive symbol table. 395107120Sjulian */ 396121054Semax if (strcmp(filename, "__.SYMDEF") == 0) { 397107120Sjulian archive_entry_copy_pathname(entry, filename); 398107120Sjulian /* Parse the time, owner, mode, size fields. */ 399107120Sjulian return (ar_parse_common_header(ar, entry, h)); 400107120Sjulian } 401107120Sjulian 402107120Sjulian /* 403107120Sjulian * Otherwise, this is a standard entry. The filename 404107120Sjulian * has already been trimmed as much as possible, based 405107120Sjulian * on our current knowledge of the format. 406107120Sjulian */ 407107120Sjulian archive_entry_copy_pathname(entry, filename); 408107120Sjulian return (ar_parse_common_header(ar, entry, h)); 409107120Sjulian} 410107120Sjulian 411107120Sjulianstatic int 412107120Sjulianar_parse_common_header(struct ar *ar, struct archive_entry *entry, 413107120Sjulian const char *h) 414107120Sjulian{ 415107120Sjulian uint64_t n; 416107120Sjulian 417107120Sjulian /* Copy remaining header */ 418107120Sjulian archive_entry_set_mtime(entry, 419107120Sjulian (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L); 420243882Sglebius archive_entry_set_uid(entry, 421107120Sjulian (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size)); 422107120Sjulian archive_entry_set_gid(entry, 423107120Sjulian (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size)); 424107120Sjulian archive_entry_set_mode(entry, 425107120Sjulian (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size)); 426107120Sjulian n = ar_atol10(h + AR_size_offset, AR_size_size); 427107120Sjulian 428107120Sjulian ar->entry_offset = 0; 429107120Sjulian ar->entry_padding = n % 2; 430107120Sjulian archive_entry_set_size(entry, n); 431107120Sjulian ar->entry_bytes_remaining = n; 432107120Sjulian return (ARCHIVE_OK); 433107120Sjulian} 434107120Sjulian 435107120Sjulianstatic int 436107120Sjulianarchive_read_format_ar_read_data(struct archive_read *a, 437107120Sjulian const void **buff, size_t *size, off_t *offset) 438107120Sjulian{ 439107120Sjulian ssize_t bytes_read; 440107120Sjulian struct ar *ar; 441107120Sjulian 442107120Sjulian ar = (struct ar *)(a->format->data); 443114878Sjulian 444114878Sjulian if (ar->entry_bytes_remaining > 0) { 445114878Sjulian *buff = __archive_read_ahead(a, 1, &bytes_read); 446107120Sjulian if (bytes_read == 0) { 447107120Sjulian archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 448107120Sjulian "Truncated ar archive"); 449107120Sjulian return (ARCHIVE_FATAL); 450107120Sjulian } 451107120Sjulian if (bytes_read < 0) 452107120Sjulian return (ARCHIVE_FATAL); 453107120Sjulian if (bytes_read > ar->entry_bytes_remaining) 454107120Sjulian bytes_read = (ssize_t)ar->entry_bytes_remaining; 455107120Sjulian *size = bytes_read; 456107120Sjulian *offset = ar->entry_offset; 457107120Sjulian ar->entry_offset += bytes_read; 458107120Sjulian ar->entry_bytes_remaining -= bytes_read; 459107120Sjulian __archive_read_consume(a, (size_t)bytes_read); 460107120Sjulian return (ARCHIVE_OK); 461107120Sjulian } else { 462107120Sjulian while (ar->entry_padding > 0) { 463107120Sjulian *buff = __archive_read_ahead(a, 1, &bytes_read); 464107120Sjulian if (bytes_read <= 0) 465107120Sjulian return (ARCHIVE_FATAL); 466107120Sjulian if (bytes_read > ar->entry_padding) 467107120Sjulian bytes_read = (ssize_t)ar->entry_padding; 468107120Sjulian __archive_read_consume(a, (size_t)bytes_read); 469107120Sjulian ar->entry_padding -= bytes_read; 470107120Sjulian } 471107120Sjulian *buff = NULL; 472107120Sjulian *size = 0; 473107120Sjulian *offset = ar->entry_offset; 474107120Sjulian return (ARCHIVE_EOF); 475107120Sjulian } 476107120Sjulian} 477107120Sjulian 478107120Sjulianstatic int 479107120Sjulianarchive_read_format_ar_skip(struct archive_read *a) 480107120Sjulian{ 481107120Sjulian off_t bytes_skipped; 482107120Sjulian struct ar* ar; 483107120Sjulian 484107120Sjulian ar = (struct ar *)(a->format->data); 485107120Sjulian 486107120Sjulian bytes_skipped = __archive_read_skip(a, 487107120Sjulian ar->entry_bytes_remaining + ar->entry_padding); 488107120Sjulian if (bytes_skipped < 0) 489107120Sjulian return (ARCHIVE_FATAL); 490107120Sjulian 491107120Sjulian ar->entry_bytes_remaining = 0; 492107120Sjulian ar->entry_padding = 0; 493107120Sjulian 494107120Sjulian return (ARCHIVE_OK); 495107120Sjulian} 496107120Sjulian 497107120Sjulianstatic int 498107120Sjulianar_parse_gnu_filename_table(struct archive_read *a) 499107120Sjulian{ 500107120Sjulian struct ar *ar; 501107120Sjulian char *p; 502107120Sjulian size_t size; 503107120Sjulian 504107120Sjulian ar = (struct ar*)(a->format->data); 505107120Sjulian size = ar->strtab_size; 506107120Sjulian 507107120Sjulian for (p = ar->strtab; p < ar->strtab + size - 1; ++p) { 508107120Sjulian if (*p == '/') { 509107120Sjulian *p++ = '\0'; 510107120Sjulian if (*p != '\n') 511107120Sjulian goto bad_string_table; 512107120Sjulian *p = '\0'; 513107120Sjulian } 514107120Sjulian } 515107120Sjulian /* 516107120Sjulian * GNU ar always pads the table to an even size. 517107120Sjulian * The pad character is either '\n' or '`'. 518107120Sjulian */ 519107120Sjulian if (p != ar->strtab + size && *p != '\n' && *p != '`') 520107120Sjulian goto bad_string_table; 521107120Sjulian 522107120Sjulian /* Enforce zero termination. */ 523107120Sjulian ar->strtab[size - 1] = '\0'; 524107120Sjulian 525107120Sjulian return (ARCHIVE_OK); 526107120Sjulian 527107120Sjulianbad_string_table: 528107120Sjulian archive_set_error(&a->archive, EINVAL, 529107120Sjulian "Invalid string table"); 530107120Sjulian free(ar->strtab); 531107120Sjulian ar->strtab = NULL; 532107120Sjulian return (ARCHIVE_WARN); 533107120Sjulian} 534243882Sglebius 535107120Sjulianstatic uint64_t 536107120Sjulianar_atol8(const char *p, unsigned char_cnt) 537107120Sjulian{ 538107120Sjulian uint64_t l, limit, last_digit_limit; 539107120Sjulian unsigned int digit, base; 540107120Sjulian 541107120Sjulian base = 8; 542107120Sjulian limit = UINT64_MAX / base; 543107120Sjulian last_digit_limit = UINT64_MAX % base; 544107120Sjulian 545107120Sjulian while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 546107120Sjulian p++; 547107120Sjulian 548107120Sjulian l = 0; 549107120Sjulian digit = *p - '0'; 550107120Sjulian while (*p >= '0' && digit < base && char_cnt-- > 0) { 551107120Sjulian if (l>limit || (l == limit && digit > last_digit_limit)) { 552107120Sjulian l = UINT64_MAX; /* Truncate on overflow. */ 553107120Sjulian break; 554107120Sjulian } 555107120Sjulian l = (l * base) + digit; 556107120Sjulian digit = *++p - '0'; 557107120Sjulian } 558107120Sjulian return (l); 559107120Sjulian} 560107120Sjulian 561107120Sjulianstatic uint64_t 562107120Sjulianar_atol10(const char *p, unsigned char_cnt) 563107120Sjulian{ 564107120Sjulian uint64_t l, limit, last_digit_limit; 565107120Sjulian unsigned int base, digit; 566107120Sjulian 567107120Sjulian base = 10; 568107120Sjulian limit = UINT64_MAX / base; 569107120Sjulian last_digit_limit = UINT64_MAX % base; 570107120Sjulian 571107120Sjulian while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 572107120Sjulian p++; 573107120Sjulian l = 0; 574107120Sjulian digit = *p - '0'; 575107120Sjulian while (*p >= '0' && digit < base && char_cnt-- > 0) { 576107120Sjulian if (l > limit || (l == limit && digit > last_digit_limit)) { 577107120Sjulian l = UINT64_MAX; /* Truncate on overflow. */ 578107120Sjulian break; 579107120Sjulian } 580107120Sjulian l = (l * base) + digit; 581107120Sjulian digit = *++p - '0'; 582107120Sjulian } 583107120Sjulian return (l); 584107120Sjulian} 585107120Sjulian