1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm/* 27228753Smm * This file contains the "essential" portions of the read API, that 28228753Smm * is, stuff that will probably always be used by any client that 29228753Smm * actually needs to read an archive. Optional pieces have been, as 30228753Smm * far as possible, separated out into separate files to avoid 31228753Smm * needlessly bloating statically-linked clients. 32228753Smm */ 33228753Smm 34228753Smm#include "archive_platform.h" 35229592Smm__FBSDID("$FreeBSD$"); 36228753Smm 37228753Smm#ifdef HAVE_ERRNO_H 38228753Smm#include <errno.h> 39228753Smm#endif 40228753Smm#include <stdio.h> 41228753Smm#ifdef HAVE_STDLIB_H 42228753Smm#include <stdlib.h> 43228753Smm#endif 44228753Smm#ifdef HAVE_STRING_H 45228753Smm#include <string.h> 46228753Smm#endif 47228753Smm#ifdef HAVE_UNISTD_H 48228753Smm#include <unistd.h> 49228753Smm#endif 50228753Smm 51228753Smm#include "archive.h" 52228753Smm#include "archive_entry.h" 53228753Smm#include "archive_private.h" 54228753Smm#include "archive_read_private.h" 55228753Smm 56228753Smm#define minimum(a, b) (a < b ? a : b) 57228753Smm 58228753Smmstatic int build_stream(struct archive_read *); 59228753Smmstatic int choose_format(struct archive_read *); 60228753Smmstatic int cleanup_filters(struct archive_read *); 61228753Smmstatic struct archive_vtable *archive_read_vtable(void); 62228753Smmstatic int _archive_read_close(struct archive *); 63229592Smmstatic int _archive_read_free(struct archive *); 64228753Smm 65228753Smmstatic struct archive_vtable * 66228753Smmarchive_read_vtable(void) 67228753Smm{ 68228753Smm static struct archive_vtable av; 69228753Smm static int inited = 0; 70228753Smm 71228753Smm if (!inited) { 72229592Smm av.archive_free = _archive_read_free; 73228753Smm av.archive_close = _archive_read_close; 74228753Smm } 75228753Smm return (&av); 76228753Smm} 77228753Smm 78228753Smm/* 79228753Smm * Allocate, initialize and return a struct archive object. 80228753Smm */ 81228753Smmstruct archive * 82228753Smmarchive_read_new(void) 83228753Smm{ 84228753Smm struct archive_read *a; 85228753Smm 86228753Smm a = (struct archive_read *)malloc(sizeof(*a)); 87228753Smm if (a == NULL) 88228753Smm return (NULL); 89228753Smm memset(a, 0, sizeof(*a)); 90228753Smm a->archive.magic = ARCHIVE_READ_MAGIC; 91228753Smm 92228753Smm a->archive.state = ARCHIVE_STATE_NEW; 93228753Smm a->entry = archive_entry_new(); 94228753Smm a->archive.vtable = archive_read_vtable(); 95228753Smm 96228753Smm return (&a->archive); 97228753Smm} 98228753Smm 99228753Smm/* 100228753Smm * Record the do-not-extract-to file. This belongs in archive_read_extract.c. 101228753Smm */ 102228753Smmvoid 103228753Smmarchive_read_extract_set_skip_file(struct archive *_a, dev_t d, ino_t i) 104228753Smm{ 105228753Smm struct archive_read *a = (struct archive_read *)_a; 106228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, 107228753Smm "archive_read_extract_set_skip_file"); 108228753Smm a->skip_file_dev = d; 109228753Smm a->skip_file_ino = i; 110228753Smm} 111228753Smm 112228753Smm/* 113228753Smm * Set read options for the format. 114228753Smm */ 115228753Smmint 116228753Smmarchive_read_set_format_options(struct archive *_a, const char *s) 117228753Smm{ 118228753Smm struct archive_read *a; 119228753Smm struct archive_format_descriptor *format; 120228753Smm char key[64], val[64]; 121228753Smm char *valp; 122228753Smm size_t i; 123228753Smm int len, r; 124228753Smm 125228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 126228753Smm "archive_read_set_format_options"); 127228753Smm 128228753Smm if (s == NULL || *s == '\0') 129228753Smm return (ARCHIVE_OK); 130228753Smm a = (struct archive_read *)_a; 131228753Smm __archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, 132228753Smm ARCHIVE_STATE_NEW, "archive_read_set_format_options"); 133228753Smm len = 0; 134228753Smm for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) { 135228753Smm format = &a->formats[i]; 136228753Smm if (format == NULL || format->options == NULL || 137228753Smm format->name == NULL) 138228753Smm /* This format does not support option. */ 139228753Smm continue; 140228753Smm 141228753Smm while ((len = __archive_parse_options(s, format->name, 142228753Smm sizeof(key), key, sizeof(val), val)) > 0) { 143228753Smm valp = val[0] == '\0' ? NULL : val; 144228753Smm a->format = format; 145228753Smm r = format->options(a, key, valp); 146228753Smm a->format = NULL; 147228753Smm if (r == ARCHIVE_FATAL) 148228753Smm return (r); 149228753Smm s += len; 150228753Smm } 151228753Smm } 152228753Smm if (len < 0) { 153228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 154228753Smm "Illegal format options."); 155228753Smm return (ARCHIVE_WARN); 156228753Smm } 157228753Smm return (ARCHIVE_OK); 158228753Smm} 159228753Smm 160228753Smm/* 161228753Smm * Set read options for the filter. 162228753Smm */ 163228753Smmint 164228753Smmarchive_read_set_filter_options(struct archive *_a, const char *s) 165228753Smm{ 166228753Smm struct archive_read *a; 167228753Smm struct archive_read_filter *filter; 168228753Smm struct archive_read_filter_bidder *bidder; 169228753Smm char key[64], val[64]; 170228753Smm int len, r; 171228753Smm 172228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 173228753Smm "archive_read_set_filter_options"); 174228753Smm 175228753Smm if (s == NULL || *s == '\0') 176228753Smm return (ARCHIVE_OK); 177228753Smm a = (struct archive_read *)_a; 178228753Smm __archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, 179228753Smm ARCHIVE_STATE_NEW, "archive_read_set_filter_options"); 180228753Smm len = 0; 181228753Smm for (filter = a->filter; filter != NULL; filter = filter->upstream) { 182228753Smm bidder = filter->bidder; 183228753Smm if (bidder == NULL) 184228753Smm continue; 185228753Smm if (bidder->options == NULL) 186228753Smm /* This bidder does not support option */ 187228753Smm continue; 188228753Smm while ((len = __archive_parse_options(s, filter->name, 189228753Smm sizeof(key), key, sizeof(val), val)) > 0) { 190228753Smm if (val[0] == '\0') 191228753Smm r = bidder->options(bidder, key, NULL); 192228753Smm else 193228753Smm r = bidder->options(bidder, key, val); 194228753Smm if (r == ARCHIVE_FATAL) 195228753Smm return (r); 196228753Smm s += len; 197228753Smm } 198228753Smm } 199228753Smm if (len < 0) { 200228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 201228753Smm "Illegal format options."); 202228753Smm return (ARCHIVE_WARN); 203228753Smm } 204228753Smm return (ARCHIVE_OK); 205228753Smm} 206228753Smm 207228753Smm/* 208228753Smm * Set read options for the format and the filter. 209228753Smm */ 210228753Smmint 211228753Smmarchive_read_set_options(struct archive *_a, const char *s) 212228753Smm{ 213228753Smm int r; 214228753Smm 215228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 216228753Smm "archive_read_set_options"); 217228753Smm archive_clear_error(_a); 218228753Smm 219228753Smm r = archive_read_set_format_options(_a, s); 220228753Smm if (r != ARCHIVE_OK) 221228753Smm return (r); 222228753Smm r = archive_read_set_filter_options(_a, s); 223228753Smm if (r != ARCHIVE_OK) 224228753Smm return (r); 225228753Smm return (ARCHIVE_OK); 226228753Smm} 227228753Smm 228228753Smm/* 229228753Smm * Open the archive 230228753Smm */ 231228753Smmint 232228753Smmarchive_read_open(struct archive *a, void *client_data, 233228753Smm archive_open_callback *client_opener, archive_read_callback *client_reader, 234228753Smm archive_close_callback *client_closer) 235228753Smm{ 236228753Smm /* Old archive_read_open() is just a thin shell around 237228753Smm * archive_read_open2. */ 238228753Smm return archive_read_open2(a, client_data, client_opener, 239228753Smm client_reader, NULL, client_closer); 240228753Smm} 241228753Smm 242228753Smmstatic ssize_t 243228753Smmclient_read_proxy(struct archive_read_filter *self, const void **buff) 244228753Smm{ 245228753Smm ssize_t r; 246228753Smm r = (self->archive->client.reader)(&self->archive->archive, 247228753Smm self->data, buff); 248228753Smm self->archive->archive.raw_position += r; 249228753Smm return (r); 250228753Smm} 251228753Smm 252228753Smmstatic int64_t 253228753Smmclient_skip_proxy(struct archive_read_filter *self, int64_t request) 254228753Smm{ 255228753Smm int64_t ask, get, total; 256228753Smm /* Limit our maximum seek request to 1GB on platforms 257228753Smm * with 32-bit off_t (such as Windows). */ 258228753Smm int64_t skip_limit = ((int64_t)1) << (sizeof(off_t) * 8 - 2); 259228753Smm 260228753Smm if (self->archive->client.skipper == NULL) 261228753Smm return (0); 262228753Smm total = 0; 263228753Smm for (;;) { 264228753Smm ask = request; 265228753Smm if (ask > skip_limit) 266228753Smm ask = skip_limit; 267228753Smm get = (self->archive->client.skipper)(&self->archive->archive, 268228753Smm self->data, ask); 269228753Smm if (get == 0) 270228753Smm return (total); 271228753Smm request -= get; 272228753Smm self->archive->archive.raw_position += get; 273228753Smm total += get; 274228753Smm } 275228753Smm} 276228753Smm 277228753Smmstatic int 278228753Smmclient_close_proxy(struct archive_read_filter *self) 279228753Smm{ 280228753Smm int r = ARCHIVE_OK; 281228753Smm 282228753Smm if (self->archive->client.closer != NULL) 283228753Smm r = (self->archive->client.closer)((struct archive *)self->archive, 284228753Smm self->data); 285228753Smm self->data = NULL; 286228753Smm return (r); 287228753Smm} 288228753Smm 289228753Smm 290228753Smmint 291228753Smmarchive_read_open2(struct archive *_a, void *client_data, 292228753Smm archive_open_callback *client_opener, 293228753Smm archive_read_callback *client_reader, 294228753Smm archive_skip_callback *client_skipper, 295228753Smm archive_close_callback *client_closer) 296228753Smm{ 297228753Smm struct archive_read *a = (struct archive_read *)_a; 298228753Smm struct archive_read_filter *filter; 299228753Smm int e; 300228753Smm 301228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 302228753Smm "archive_read_open"); 303228753Smm archive_clear_error(&a->archive); 304228753Smm 305228753Smm if (client_reader == NULL) 306228753Smm __archive_errx(1, 307228753Smm "No reader function provided to archive_read_open"); 308228753Smm 309228753Smm /* Open data source. */ 310228753Smm if (client_opener != NULL) { 311228753Smm e =(client_opener)(&a->archive, client_data); 312228753Smm if (e != 0) { 313228753Smm /* If the open failed, call the closer to clean up. */ 314228753Smm if (client_closer) 315228753Smm (client_closer)(&a->archive, client_data); 316228753Smm return (e); 317228753Smm } 318228753Smm } 319228753Smm 320228753Smm /* Save the client functions and mock up the initial source. */ 321228753Smm a->client.reader = client_reader; 322228753Smm a->client.skipper = client_skipper; 323228753Smm a->client.closer = client_closer; 324228753Smm 325228753Smm filter = calloc(1, sizeof(*filter)); 326228753Smm if (filter == NULL) 327228753Smm return (ARCHIVE_FATAL); 328228753Smm filter->bidder = NULL; 329228753Smm filter->upstream = NULL; 330228753Smm filter->archive = a; 331228753Smm filter->data = client_data; 332228753Smm filter->read = client_read_proxy; 333228753Smm filter->skip = client_skip_proxy; 334228753Smm filter->close = client_close_proxy; 335228753Smm filter->name = "none"; 336228753Smm filter->code = ARCHIVE_COMPRESSION_NONE; 337228753Smm a->filter = filter; 338228753Smm 339228753Smm /* Build out the input pipeline. */ 340228753Smm e = build_stream(a); 341228753Smm if (e == ARCHIVE_OK) 342228753Smm a->archive.state = ARCHIVE_STATE_HEADER; 343228753Smm 344228753Smm return (e); 345228753Smm} 346228753Smm 347228753Smm/* 348228753Smm * Allow each registered stream transform to bid on whether 349228753Smm * it wants to handle this stream. Repeat until we've finished 350228753Smm * building the pipeline. 351228753Smm */ 352228753Smmstatic int 353228753Smmbuild_stream(struct archive_read *a) 354228753Smm{ 355228753Smm int number_bidders, i, bid, best_bid; 356228753Smm struct archive_read_filter_bidder *bidder, *best_bidder; 357228753Smm struct archive_read_filter *filter; 358228753Smm ssize_t avail; 359228753Smm int r; 360228753Smm 361228753Smm for (;;) { 362228753Smm number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 363228753Smm 364228753Smm best_bid = 0; 365228753Smm best_bidder = NULL; 366228753Smm 367228753Smm bidder = a->bidders; 368228753Smm for (i = 0; i < number_bidders; i++, bidder++) { 369228753Smm if (bidder->bid != NULL) { 370228753Smm bid = (bidder->bid)(bidder, a->filter); 371228753Smm if (bid > best_bid) { 372228753Smm best_bid = bid; 373228753Smm best_bidder = bidder; 374228753Smm } 375228753Smm } 376228753Smm } 377228753Smm 378228753Smm /* If no bidder, we're done. */ 379228753Smm if (best_bidder == NULL) { 380228753Smm /* Verify the final pipelin by asking it for some data. */ 381228753Smm __archive_read_filter_ahead(a->filter, 1, &avail); 382228753Smm if (avail < 0) { 383228753Smm cleanup_filters(a); 384228753Smm return (ARCHIVE_FATAL); 385228753Smm } 386228753Smm a->archive.compression_name = a->filter->name; 387228753Smm a->archive.compression_code = a->filter->code; 388228753Smm return (ARCHIVE_OK); 389228753Smm } 390228753Smm 391228753Smm filter 392228753Smm = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 393228753Smm if (filter == NULL) 394228753Smm return (ARCHIVE_FATAL); 395228753Smm filter->bidder = best_bidder; 396228753Smm filter->archive = a; 397228753Smm filter->upstream = a->filter; 398228753Smm a->filter = filter; 399228753Smm r = (best_bidder->init)(a->filter); 400228753Smm if (r != ARCHIVE_OK) { 401228753Smm cleanup_filters(a); 402228753Smm return (r); 403228753Smm } 404228753Smm } 405228753Smm} 406228753Smm 407228753Smm/* 408228753Smm * Read header of next entry. 409228753Smm */ 410228753Smmint 411228753Smmarchive_read_next_header2(struct archive *_a, struct archive_entry *entry) 412228753Smm{ 413228753Smm struct archive_read *a = (struct archive_read *)_a; 414228753Smm int slot, ret; 415228753Smm 416228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, 417228753Smm ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 418228753Smm "archive_read_next_header"); 419228753Smm 420228753Smm ++_a->file_count; 421228753Smm archive_entry_clear(entry); 422228753Smm archive_clear_error(&a->archive); 423228753Smm 424228753Smm /* 425228753Smm * If no format has yet been chosen, choose one. 426228753Smm */ 427228753Smm if (a->format == NULL) { 428228753Smm slot = choose_format(a); 429228753Smm if (slot < 0) { 430228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 431228753Smm return (ARCHIVE_FATAL); 432228753Smm } 433228753Smm a->format = &(a->formats[slot]); 434228753Smm } 435228753Smm 436228753Smm /* 437228753Smm * If client didn't consume entire data, skip any remainder 438228753Smm * (This is especially important for GNU incremental directories.) 439228753Smm */ 440228753Smm if (a->archive.state == ARCHIVE_STATE_DATA) { 441228753Smm ret = archive_read_data_skip(&a->archive); 442228753Smm if (ret == ARCHIVE_EOF) { 443228753Smm archive_set_error(&a->archive, EIO, "Premature end-of-file."); 444228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 445228753Smm return (ARCHIVE_FATAL); 446228753Smm } 447228753Smm if (ret != ARCHIVE_OK) 448228753Smm return (ret); 449228753Smm } 450228753Smm 451228753Smm /* Record start-of-header. */ 452228753Smm a->header_position = a->archive.file_position; 453228753Smm 454228753Smm ret = (a->format->read_header)(a, entry); 455228753Smm 456228753Smm /* 457228753Smm * EOF and FATAL are persistent at this layer. By 458228753Smm * modifying the state, we guarantee that future calls to 459228753Smm * read a header or read data will fail. 460228753Smm */ 461228753Smm switch (ret) { 462228753Smm case ARCHIVE_EOF: 463228753Smm a->archive.state = ARCHIVE_STATE_EOF; 464228753Smm break; 465228753Smm case ARCHIVE_OK: 466228753Smm a->archive.state = ARCHIVE_STATE_DATA; 467228753Smm break; 468228753Smm case ARCHIVE_WARN: 469228753Smm a->archive.state = ARCHIVE_STATE_DATA; 470228753Smm break; 471228753Smm case ARCHIVE_RETRY: 472228753Smm break; 473228753Smm case ARCHIVE_FATAL: 474228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 475228753Smm break; 476228753Smm } 477228753Smm 478228753Smm a->read_data_output_offset = 0; 479228753Smm a->read_data_remaining = 0; 480228753Smm return (ret); 481228753Smm} 482228753Smm 483228753Smmint 484228753Smmarchive_read_next_header(struct archive *_a, struct archive_entry **entryp) 485228753Smm{ 486228753Smm int ret; 487228753Smm struct archive_read *a = (struct archive_read *)_a; 488228753Smm *entryp = NULL; 489228753Smm ret = archive_read_next_header2(_a, a->entry); 490228753Smm *entryp = a->entry; 491228753Smm return ret; 492228753Smm} 493228753Smm 494228753Smm/* 495228753Smm * Allow each registered format to bid on whether it wants to handle 496228753Smm * the next entry. Return index of winning bidder. 497228753Smm */ 498228753Smmstatic int 499228753Smmchoose_format(struct archive_read *a) 500228753Smm{ 501228753Smm int slots; 502228753Smm int i; 503228753Smm int bid, best_bid; 504228753Smm int best_bid_slot; 505228753Smm 506228753Smm slots = sizeof(a->formats) / sizeof(a->formats[0]); 507228753Smm best_bid = -1; 508228753Smm best_bid_slot = -1; 509228753Smm 510228753Smm /* Set up a->format and a->pformat_data for convenience of bidders. */ 511228753Smm a->format = &(a->formats[0]); 512228753Smm for (i = 0; i < slots; i++, a->format++) { 513228753Smm if (a->format->bid) { 514228753Smm bid = (a->format->bid)(a); 515228753Smm if (bid == ARCHIVE_FATAL) 516228753Smm return (ARCHIVE_FATAL); 517228753Smm if ((bid > best_bid) || (best_bid_slot < 0)) { 518228753Smm best_bid = bid; 519228753Smm best_bid_slot = i; 520228753Smm } 521228753Smm } 522228753Smm } 523228753Smm 524228753Smm /* 525228753Smm * There were no bidders; this is a serious programmer error 526228753Smm * and demands a quick and definitive abort. 527228753Smm */ 528228753Smm if (best_bid_slot < 0) 529228753Smm __archive_errx(1, "No formats were registered; you must " 530228753Smm "invoke at least one archive_read_support_format_XXX " 531228753Smm "function in order to successfully read an archive."); 532228753Smm 533228753Smm /* 534228753Smm * There were bidders, but no non-zero bids; this means we 535228753Smm * can't support this stream. 536228753Smm */ 537228753Smm if (best_bid < 1) { 538228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 539228753Smm "Unrecognized archive format"); 540228753Smm return (ARCHIVE_FATAL); 541228753Smm } 542228753Smm 543228753Smm return (best_bid_slot); 544228753Smm} 545228753Smm 546228753Smm/* 547228753Smm * Return the file offset (within the uncompressed data stream) where 548228753Smm * the last header started. 549228753Smm */ 550228753Smmint64_t 551228753Smmarchive_read_header_position(struct archive *_a) 552228753Smm{ 553228753Smm struct archive_read *a = (struct archive_read *)_a; 554228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, 555228753Smm ARCHIVE_STATE_ANY, "archive_read_header_position"); 556228753Smm return (a->header_position); 557228753Smm} 558228753Smm 559228753Smm/* 560228753Smm * Read data from an archive entry, using a read(2)-style interface. 561228753Smm * This is a convenience routine that just calls 562228753Smm * archive_read_data_block and copies the results into the client 563228753Smm * buffer, filling any gaps with zero bytes. Clients using this 564228753Smm * API can be completely ignorant of sparse-file issues; sparse files 565228753Smm * will simply be padded with nulls. 566228753Smm * 567228753Smm * DO NOT intermingle calls to this function and archive_read_data_block 568228753Smm * to read a single entry body. 569228753Smm */ 570228753Smmssize_t 571228753Smmarchive_read_data(struct archive *_a, void *buff, size_t s) 572228753Smm{ 573228753Smm struct archive_read *a = (struct archive_read *)_a; 574228753Smm char *dest; 575228753Smm const void *read_buf; 576228753Smm size_t bytes_read; 577228753Smm size_t len; 578228753Smm int r; 579228753Smm 580228753Smm bytes_read = 0; 581228753Smm dest = (char *)buff; 582228753Smm 583228753Smm while (s > 0) { 584228753Smm if (a->read_data_remaining == 0) { 585228753Smm read_buf = a->read_data_block; 586228753Smm r = archive_read_data_block(&a->archive, &read_buf, 587228753Smm &a->read_data_remaining, &a->read_data_offset); 588228753Smm a->read_data_block = read_buf; 589228753Smm if (r == ARCHIVE_EOF) 590228753Smm return (bytes_read); 591228753Smm /* 592228753Smm * Error codes are all negative, so the status 593228753Smm * return here cannot be confused with a valid 594228753Smm * byte count. (ARCHIVE_OK is zero.) 595228753Smm */ 596228753Smm if (r < ARCHIVE_OK) 597228753Smm return (r); 598228753Smm } 599228753Smm 600228753Smm if (a->read_data_offset < a->read_data_output_offset) { 601228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 602228753Smm "Encountered out-of-order sparse blocks"); 603228753Smm return (ARCHIVE_RETRY); 604228753Smm } 605228753Smm 606228753Smm /* Compute the amount of zero padding needed. */ 607228753Smm if (a->read_data_output_offset + (off_t)s < 608228753Smm a->read_data_offset) { 609228753Smm len = s; 610228753Smm } else if (a->read_data_output_offset < 611228753Smm a->read_data_offset) { 612228753Smm len = a->read_data_offset - 613228753Smm a->read_data_output_offset; 614228753Smm } else 615228753Smm len = 0; 616228753Smm 617228753Smm /* Add zeroes. */ 618228753Smm memset(dest, 0, len); 619228753Smm s -= len; 620228753Smm a->read_data_output_offset += len; 621228753Smm dest += len; 622228753Smm bytes_read += len; 623228753Smm 624228753Smm /* Copy data if there is any space left. */ 625228753Smm if (s > 0) { 626228753Smm len = a->read_data_remaining; 627228753Smm if (len > s) 628228753Smm len = s; 629228753Smm memcpy(dest, a->read_data_block, len); 630228753Smm s -= len; 631228753Smm a->read_data_block += len; 632228753Smm a->read_data_remaining -= len; 633228753Smm a->read_data_output_offset += len; 634228753Smm a->read_data_offset += len; 635228753Smm dest += len; 636228753Smm bytes_read += len; 637228753Smm } 638228753Smm } 639228753Smm return (bytes_read); 640228753Smm} 641228753Smm 642228753Smm#if ARCHIVE_API_VERSION < 3 643228753Smm/* 644228753Smm * Obsolete function provided for compatibility only. Note that the API 645228753Smm * of this function doesn't allow the caller to detect if the remaining 646228753Smm * data from the archive entry is shorter than the buffer provided, or 647228753Smm * even if an error occurred while reading data. 648228753Smm */ 649228753Smmint 650228753Smmarchive_read_data_into_buffer(struct archive *a, void *d, ssize_t len) 651228753Smm{ 652228753Smm 653228753Smm archive_read_data(a, d, len); 654228753Smm return (ARCHIVE_OK); 655228753Smm} 656228753Smm#endif 657228753Smm 658228753Smm/* 659228753Smm * Skip over all remaining data in this entry. 660228753Smm */ 661228753Smmint 662228753Smmarchive_read_data_skip(struct archive *_a) 663228753Smm{ 664228753Smm struct archive_read *a = (struct archive_read *)_a; 665228753Smm int r; 666228753Smm const void *buff; 667228753Smm size_t size; 668228753Smm off_t offset; 669228753Smm 670228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 671228753Smm "archive_read_data_skip"); 672228753Smm 673228753Smm if (a->format->read_data_skip != NULL) 674228753Smm r = (a->format->read_data_skip)(a); 675228753Smm else { 676228753Smm while ((r = archive_read_data_block(&a->archive, 677228753Smm &buff, &size, &offset)) 678228753Smm == ARCHIVE_OK) 679228753Smm ; 680228753Smm } 681228753Smm 682228753Smm if (r == ARCHIVE_EOF) 683228753Smm r = ARCHIVE_OK; 684228753Smm 685228753Smm a->archive.state = ARCHIVE_STATE_HEADER; 686228753Smm return (r); 687228753Smm} 688228753Smm 689228753Smm/* 690228753Smm * Read the next block of entry data from the archive. 691228753Smm * This is a zero-copy interface; the client receives a pointer, 692228753Smm * size, and file offset of the next available block of data. 693228753Smm * 694228753Smm * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if 695228753Smm * the end of entry is encountered. 696228753Smm */ 697228753Smmint 698228753Smmarchive_read_data_block(struct archive *_a, 699228753Smm const void **buff, size_t *size, off_t *offset) 700228753Smm{ 701228753Smm struct archive_read *a = (struct archive_read *)_a; 702228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 703228753Smm "archive_read_data_block"); 704228753Smm 705228753Smm if (a->format->read_data == NULL) { 706228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 707228753Smm "Internal error: " 708228753Smm "No format_read_data_block function registered"); 709228753Smm return (ARCHIVE_FATAL); 710228753Smm } 711228753Smm 712228753Smm return (a->format->read_data)(a, buff, size, offset); 713228753Smm} 714228753Smm 715228753Smm/* 716228753Smm * Close the file and release most resources. 717228753Smm * 718228753Smm * Be careful: client might just call read_new and then read_finish. 719228753Smm * Don't assume we actually read anything or performed any non-trivial 720228753Smm * initialization. 721228753Smm */ 722228753Smmstatic int 723228753Smm_archive_read_close(struct archive *_a) 724228753Smm{ 725228753Smm struct archive_read *a = (struct archive_read *)_a; 726228753Smm int r = ARCHIVE_OK, r1 = ARCHIVE_OK; 727228753Smm size_t i, n; 728228753Smm 729228753Smm __archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, 730228753Smm ARCHIVE_STATE_ANY, "archive_read_close"); 731228753Smm archive_clear_error(&a->archive); 732228753Smm a->archive.state = ARCHIVE_STATE_CLOSED; 733228753Smm 734228753Smm 735228753Smm /* Call cleanup functions registered by optional components. */ 736228753Smm if (a->cleanup_archive_extract != NULL) 737228753Smm r = (a->cleanup_archive_extract)(a); 738228753Smm 739228753Smm /* TODO: Clean up the formatters. */ 740228753Smm 741228753Smm /* Release the filter objects. */ 742228753Smm r1 = cleanup_filters(a); 743228753Smm if (r1 < r) 744228753Smm r = r1; 745228753Smm 746228753Smm /* Release the bidder objects. */ 747228753Smm n = sizeof(a->bidders)/sizeof(a->bidders[0]); 748228753Smm for (i = 0; i < n; i++) { 749228753Smm if (a->bidders[i].free != NULL) { 750228753Smm r1 = (a->bidders[i].free)(&a->bidders[i]); 751228753Smm if (r1 < r) 752228753Smm r = r1; 753228753Smm } 754228753Smm } 755228753Smm 756228753Smm return (r); 757228753Smm} 758228753Smm 759228753Smmstatic int 760228753Smmcleanup_filters(struct archive_read *a) 761228753Smm{ 762228753Smm int r = ARCHIVE_OK; 763228753Smm /* Clean up the filter pipeline. */ 764228753Smm while (a->filter != NULL) { 765228753Smm struct archive_read_filter *t = a->filter->upstream; 766228753Smm if (a->filter->close != NULL) { 767228753Smm int r1 = (a->filter->close)(a->filter); 768228753Smm if (r1 < r) 769228753Smm r = r1; 770228753Smm } 771228753Smm free(a->filter->buffer); 772228753Smm free(a->filter); 773228753Smm a->filter = t; 774228753Smm } 775228753Smm return r; 776228753Smm} 777228753Smm 778228753Smm/* 779228753Smm * Release memory and other resources. 780228753Smm */ 781228753Smmstatic int 782229592Smm_archive_read_free(struct archive *_a) 783228753Smm{ 784228753Smm struct archive_read *a = (struct archive_read *)_a; 785228753Smm int i; 786228753Smm int slots; 787228753Smm int r = ARCHIVE_OK; 788228753Smm 789228753Smm __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, 790229592Smm "archive_read_free"); 791228753Smm if (a->archive.state != ARCHIVE_STATE_CLOSED) 792228753Smm r = archive_read_close(&a->archive); 793228753Smm 794228753Smm /* Cleanup format-specific data. */ 795228753Smm slots = sizeof(a->formats) / sizeof(a->formats[0]); 796228753Smm for (i = 0; i < slots; i++) { 797228753Smm a->format = &(a->formats[i]); 798228753Smm if (a->formats[i].cleanup) 799228753Smm (a->formats[i].cleanup)(a); 800228753Smm } 801228753Smm 802228753Smm archive_string_free(&a->archive.error_string); 803228753Smm if (a->entry) 804228753Smm archive_entry_free(a->entry); 805228753Smm a->archive.magic = 0; 806228753Smm free(a); 807228753Smm#if ARCHIVE_API_VERSION > 1 808228753Smm return (r); 809228753Smm#endif 810228753Smm} 811228753Smm 812228753Smm/* 813228753Smm * Used internally by read format handlers to register their bid and 814228753Smm * initialization functions. 815228753Smm */ 816228753Smmint 817228753Smm__archive_read_register_format(struct archive_read *a, 818228753Smm void *format_data, 819228753Smm const char *name, 820228753Smm int (*bid)(struct archive_read *), 821228753Smm int (*options)(struct archive_read *, const char *, const char *), 822228753Smm int (*read_header)(struct archive_read *, struct archive_entry *), 823228753Smm int (*read_data)(struct archive_read *, const void **, size_t *, off_t *), 824228753Smm int (*read_data_skip)(struct archive_read *), 825228753Smm int (*cleanup)(struct archive_read *)) 826228753Smm{ 827228753Smm int i, number_slots; 828228753Smm 829228753Smm __archive_check_magic(&a->archive, 830228753Smm ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 831228753Smm "__archive_read_register_format"); 832228753Smm 833228753Smm number_slots = sizeof(a->formats) / sizeof(a->formats[0]); 834228753Smm 835228753Smm for (i = 0; i < number_slots; i++) { 836228753Smm if (a->formats[i].bid == bid) 837228753Smm return (ARCHIVE_WARN); /* We've already installed */ 838228753Smm if (a->formats[i].bid == NULL) { 839228753Smm a->formats[i].bid = bid; 840228753Smm a->formats[i].options = options; 841228753Smm a->formats[i].read_header = read_header; 842228753Smm a->formats[i].read_data = read_data; 843228753Smm a->formats[i].read_data_skip = read_data_skip; 844228753Smm a->formats[i].cleanup = cleanup; 845228753Smm a->formats[i].data = format_data; 846228753Smm a->formats[i].name = name; 847228753Smm return (ARCHIVE_OK); 848228753Smm } 849228753Smm } 850228753Smm 851228753Smm __archive_errx(1, "Not enough slots for format registration"); 852228753Smm return (ARCHIVE_FATAL); /* Never actually called. */ 853228753Smm} 854228753Smm 855228753Smm/* 856228753Smm * Used internally by decompression routines to register their bid and 857228753Smm * initialization functions. 858228753Smm */ 859228753Smmstruct archive_read_filter_bidder * 860228753Smm__archive_read_get_bidder(struct archive_read *a) 861228753Smm{ 862228753Smm int i, number_slots; 863228753Smm 864228753Smm __archive_check_magic(&a->archive, 865228753Smm ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 866228753Smm "__archive_read_get_bidder"); 867228753Smm 868228753Smm number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]); 869228753Smm 870228753Smm for (i = 0; i < number_slots; i++) { 871228753Smm if (a->bidders[i].bid == NULL) { 872228753Smm memset(a->bidders + i, 0, sizeof(a->bidders[0])); 873228753Smm return (a->bidders + i); 874228753Smm } 875228753Smm } 876228753Smm 877228753Smm __archive_errx(1, "Not enough slots for compression registration"); 878228753Smm return (NULL); /* Never actually executed. */ 879228753Smm} 880228753Smm 881228753Smm/* 882228753Smm * The next three functions comprise the peek/consume internal I/O 883228753Smm * system used by archive format readers. This system allows fairly 884228753Smm * flexible read-ahead and allows the I/O code to operate in a 885228753Smm * zero-copy manner most of the time. 886228753Smm * 887228753Smm * In the ideal case, filters generate blocks of data 888228753Smm * and __archive_read_ahead() just returns pointers directly into 889228753Smm * those blocks. Then __archive_read_consume() just bumps those 890228753Smm * pointers. Only if your request would span blocks does the I/O 891228753Smm * layer use a copy buffer to provide you with a contiguous block of 892228753Smm * data. The __archive_read_skip() is an optimization; it scans ahead 893228753Smm * very quickly (it usually translates into a seek() operation if 894228753Smm * you're reading uncompressed disk files). 895228753Smm * 896228753Smm * A couple of useful idioms: 897228753Smm * * "I just want some data." Ask for 1 byte and pay attention to 898228753Smm * the "number of bytes available" from __archive_read_ahead(). 899228753Smm * You can consume more than you asked for; you just can't consume 900228753Smm * more than is available. If you consume everything that's 901228753Smm * immediately available, the next read_ahead() call will pull 902228753Smm * the next block. 903228753Smm * * "I want to output a large block of data." As above, ask for 1 byte, 904228753Smm * emit all that's available (up to whatever limit you have), then 905228753Smm * repeat until you're done. 906228753Smm * * "I want to peek ahead by a large amount." Ask for 4k or so, then 907228753Smm * double and repeat until you get an error or have enough. Note 908228753Smm * that the I/O layer will likely end up expanding its copy buffer 909228753Smm * to fit your request, so use this technique cautiously. This 910228753Smm * technique is used, for example, by some of the format tasting 911228753Smm * code that has uncertain look-ahead needs. 912228753Smm * 913228753Smm * TODO: Someday, provide a more generic __archive_read_seek() for 914228753Smm * those cases where it's useful. This is tricky because there are lots 915228753Smm * of cases where seek() is not available (reading gzip data from a 916228753Smm * network socket, for instance), so there needs to be a good way to 917228753Smm * communicate whether seek() is available and users of that interface 918228753Smm * need to use non-seeking strategies whenever seek() is not available. 919228753Smm */ 920228753Smm 921228753Smm/* 922228753Smm * Looks ahead in the input stream: 923228753Smm * * If 'avail' pointer is provided, that returns number of bytes available 924228753Smm * in the current buffer, which may be much larger than requested. 925228753Smm * * If end-of-file, *avail gets set to zero. 926228753Smm * * If error, *avail gets error code. 927228753Smm * * If request can be met, returns pointer to data, returns NULL 928228753Smm * if request is not met. 929228753Smm * 930228753Smm * Note: If you just want "some data", ask for 1 byte and pay attention 931228753Smm * to *avail, which will have the actual amount available. If you 932228753Smm * know exactly how many bytes you need, just ask for that and treat 933228753Smm * a NULL return as an error. 934228753Smm * 935228753Smm * Important: This does NOT move the file pointer. See 936228753Smm * __archive_read_consume() below. 937228753Smm */ 938228753Smm 939228753Smm/* 940228753Smm * This is tricky. We need to provide our clients with pointers to 941228753Smm * contiguous blocks of memory but we want to avoid copying whenever 942228753Smm * possible. 943228753Smm * 944228753Smm * Mostly, this code returns pointers directly into the block of data 945228753Smm * provided by the client_read routine. It can do this unless the 946228753Smm * request would split across blocks. In that case, we have to copy 947228753Smm * into an internal buffer to combine reads. 948228753Smm */ 949228753Smmconst void * 950228753Smm__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) 951228753Smm{ 952228753Smm return (__archive_read_filter_ahead(a->filter, min, avail)); 953228753Smm} 954228753Smm 955228753Smmconst void * 956228753Smm__archive_read_filter_ahead(struct archive_read_filter *filter, 957228753Smm size_t min, ssize_t *avail) 958228753Smm{ 959228753Smm ssize_t bytes_read; 960228753Smm size_t tocopy; 961228753Smm 962228753Smm if (filter->fatal) { 963228753Smm if (avail) 964228753Smm *avail = ARCHIVE_FATAL; 965228753Smm return (NULL); 966228753Smm } 967228753Smm 968228753Smm /* 969228753Smm * Keep pulling more data until we can satisfy the request. 970228753Smm */ 971228753Smm for (;;) { 972228753Smm 973228753Smm /* 974228753Smm * If we can satisfy from the copy buffer (and the 975228753Smm * copy buffer isn't empty), we're done. In particular, 976228753Smm * note that min == 0 is a perfectly well-defined 977228753Smm * request. 978228753Smm */ 979228753Smm if (filter->avail >= min && filter->avail > 0) { 980228753Smm if (avail != NULL) 981228753Smm *avail = filter->avail; 982228753Smm return (filter->next); 983228753Smm } 984228753Smm 985228753Smm /* 986228753Smm * We can satisfy directly from client buffer if everything 987228753Smm * currently in the copy buffer is still in the client buffer. 988228753Smm */ 989228753Smm if (filter->client_total >= filter->client_avail + filter->avail 990228753Smm && filter->client_avail + filter->avail >= min) { 991228753Smm /* "Roll back" to client buffer. */ 992228753Smm filter->client_avail += filter->avail; 993228753Smm filter->client_next -= filter->avail; 994228753Smm /* Copy buffer is now empty. */ 995228753Smm filter->avail = 0; 996228753Smm filter->next = filter->buffer; 997228753Smm /* Return data from client buffer. */ 998228753Smm if (avail != NULL) 999228753Smm *avail = filter->client_avail; 1000228753Smm return (filter->client_next); 1001228753Smm } 1002228753Smm 1003228753Smm /* Move data forward in copy buffer if necessary. */ 1004228753Smm if (filter->next > filter->buffer && 1005228753Smm filter->next + min > filter->buffer + filter->buffer_size) { 1006228753Smm if (filter->avail > 0) 1007228753Smm memmove(filter->buffer, filter->next, filter->avail); 1008228753Smm filter->next = filter->buffer; 1009228753Smm } 1010228753Smm 1011228753Smm /* If we've used up the client data, get more. */ 1012228753Smm if (filter->client_avail <= 0) { 1013228753Smm if (filter->end_of_file) { 1014228753Smm if (avail != NULL) 1015228753Smm *avail = 0; 1016228753Smm return (NULL); 1017228753Smm } 1018228753Smm bytes_read = (filter->read)(filter, 1019228753Smm &filter->client_buff); 1020228753Smm if (bytes_read < 0) { /* Read error. */ 1021228753Smm filter->client_total = filter->client_avail = 0; 1022228753Smm filter->client_next = filter->client_buff = NULL; 1023228753Smm filter->fatal = 1; 1024228753Smm if (avail != NULL) 1025228753Smm *avail = ARCHIVE_FATAL; 1026228753Smm return (NULL); 1027228753Smm } 1028228753Smm if (bytes_read == 0) { /* Premature end-of-file. */ 1029228753Smm filter->client_total = filter->client_avail = 0; 1030228753Smm filter->client_next = filter->client_buff = NULL; 1031228753Smm filter->end_of_file = 1; 1032228753Smm /* Return whatever we do have. */ 1033228753Smm if (avail != NULL) 1034228753Smm *avail = filter->avail; 1035228753Smm return (NULL); 1036228753Smm } 1037228753Smm filter->position += bytes_read; 1038228753Smm filter->client_total = bytes_read; 1039228753Smm filter->client_avail = filter->client_total; 1040228753Smm filter->client_next = filter->client_buff; 1041228753Smm } 1042228753Smm else 1043228753Smm { 1044228753Smm /* 1045228753Smm * We can't satisfy the request from the copy 1046228753Smm * buffer or the existing client data, so we 1047228753Smm * need to copy more client data over to the 1048228753Smm * copy buffer. 1049228753Smm */ 1050228753Smm 1051228753Smm /* Ensure the buffer is big enough. */ 1052228753Smm if (min > filter->buffer_size) { 1053228753Smm size_t s, t; 1054228753Smm char *p; 1055228753Smm 1056228753Smm /* Double the buffer; watch for overflow. */ 1057228753Smm s = t = filter->buffer_size; 1058228753Smm if (s == 0) 1059228753Smm s = min; 1060228753Smm while (s < min) { 1061228753Smm t *= 2; 1062228753Smm if (t <= s) { /* Integer overflow! */ 1063228753Smm archive_set_error( 1064228753Smm &filter->archive->archive, 1065228753Smm ENOMEM, 1066228753Smm "Unable to allocate copy buffer"); 1067228753Smm filter->fatal = 1; 1068228753Smm if (avail != NULL) 1069228753Smm *avail = ARCHIVE_FATAL; 1070228753Smm return (NULL); 1071228753Smm } 1072228753Smm s = t; 1073228753Smm } 1074228753Smm /* Now s >= min, so allocate a new buffer. */ 1075228753Smm p = (char *)malloc(s); 1076228753Smm if (p == NULL) { 1077228753Smm archive_set_error( 1078228753Smm &filter->archive->archive, 1079228753Smm ENOMEM, 1080228753Smm "Unable to allocate copy buffer"); 1081228753Smm filter->fatal = 1; 1082228753Smm if (avail != NULL) 1083228753Smm *avail = ARCHIVE_FATAL; 1084228753Smm return (NULL); 1085228753Smm } 1086228753Smm /* Move data into newly-enlarged buffer. */ 1087228753Smm if (filter->avail > 0) 1088228753Smm memmove(p, filter->next, filter->avail); 1089228753Smm free(filter->buffer); 1090228753Smm filter->next = filter->buffer = p; 1091228753Smm filter->buffer_size = s; 1092228753Smm } 1093228753Smm 1094228753Smm /* We can add client data to copy buffer. */ 1095228753Smm /* First estimate: copy to fill rest of buffer. */ 1096228753Smm tocopy = (filter->buffer + filter->buffer_size) 1097228753Smm - (filter->next + filter->avail); 1098228753Smm /* Don't waste time buffering more than we need to. */ 1099228753Smm if (tocopy + filter->avail > min) 1100228753Smm tocopy = min - filter->avail; 1101228753Smm /* Don't copy more than is available. */ 1102228753Smm if (tocopy > filter->client_avail) 1103228753Smm tocopy = filter->client_avail; 1104228753Smm 1105228753Smm memcpy(filter->next + filter->avail, filter->client_next, 1106228753Smm tocopy); 1107228753Smm /* Remove this data from client buffer. */ 1108228753Smm filter->client_next += tocopy; 1109228753Smm filter->client_avail -= tocopy; 1110228753Smm /* add it to copy buffer. */ 1111228753Smm filter->avail += tocopy; 1112228753Smm } 1113228753Smm } 1114228753Smm} 1115228753Smm 1116228753Smm/* 1117228753Smm * Move the file pointer forward. This should be called after 1118228753Smm * __archive_read_ahead() returns data to you. Don't try to move 1119228753Smm * ahead by more than the amount of data available according to 1120228753Smm * __archive_read_ahead(). 1121228753Smm */ 1122228753Smm/* 1123228753Smm * Mark the appropriate data as used. Note that the request here will 1124228753Smm * often be much smaller than the size of the previous read_ahead 1125228753Smm * request. 1126228753Smm */ 1127228753Smmssize_t 1128228753Smm__archive_read_consume(struct archive_read *a, size_t request) 1129228753Smm{ 1130228753Smm ssize_t r; 1131228753Smm r = __archive_read_filter_consume(a->filter, request); 1132228753Smm a->archive.file_position += r; 1133228753Smm return (r); 1134228753Smm} 1135228753Smm 1136228753Smmssize_t 1137228753Smm__archive_read_filter_consume(struct archive_read_filter * filter, 1138228753Smm size_t request) 1139228753Smm{ 1140228753Smm if (filter->avail > 0) { 1141228753Smm /* Read came from copy buffer. */ 1142228753Smm filter->next += request; 1143228753Smm filter->avail -= request; 1144228753Smm } else { 1145228753Smm /* Read came from client buffer. */ 1146228753Smm filter->client_next += request; 1147228753Smm filter->client_avail -= request; 1148228753Smm } 1149228753Smm return (request); 1150228753Smm} 1151228753Smm 1152228753Smm/* 1153228753Smm * Move the file pointer ahead by an arbitrary amount. If you're 1154228753Smm * reading uncompressed data from a disk file, this will actually 1155228753Smm * translate into a seek() operation. Even in cases where seek() 1156228753Smm * isn't feasible, this at least pushes the read-and-discard loop 1157228753Smm * down closer to the data source. 1158228753Smm */ 1159228753Smmint64_t 1160228753Smm__archive_read_skip(struct archive_read *a, int64_t request) 1161228753Smm{ 1162228753Smm int64_t skipped = __archive_read_skip_lenient(a, request); 1163228753Smm if (skipped == request) 1164228753Smm return (skipped); 1165228753Smm /* We hit EOF before we satisfied the skip request. */ 1166228753Smm if (skipped < 0) // Map error code to 0 for error message below. 1167228753Smm skipped = 0; 1168228753Smm archive_set_error(&a->archive, 1169228753Smm ARCHIVE_ERRNO_MISC, 1170228753Smm "Truncated input file (needed %jd bytes, only %jd available)", 1171228753Smm (intmax_t)request, (intmax_t)skipped); 1172228753Smm return (ARCHIVE_FATAL); 1173228753Smm} 1174228753Smm 1175228753Smmint64_t 1176228753Smm__archive_read_skip_lenient(struct archive_read *a, int64_t request) 1177228753Smm{ 1178228753Smm int64_t skipped = __archive_read_filter_skip(a->filter, request); 1179228753Smm if (skipped > 0) 1180228753Smm a->archive.file_position += skipped; 1181228753Smm return (skipped); 1182228753Smm} 1183228753Smm 1184228753Smmint64_t 1185228753Smm__archive_read_filter_skip(struct archive_read_filter *filter, int64_t request) 1186228753Smm{ 1187228753Smm int64_t bytes_skipped, total_bytes_skipped = 0; 1188228753Smm size_t min; 1189228753Smm 1190228753Smm if (filter->fatal) 1191228753Smm return (-1); 1192228753Smm /* 1193228753Smm * If there is data in the buffers already, use that first. 1194228753Smm */ 1195228753Smm if (filter->avail > 0) { 1196228753Smm min = minimum(request, (off_t)filter->avail); 1197228753Smm bytes_skipped = __archive_read_filter_consume(filter, min); 1198228753Smm request -= bytes_skipped; 1199228753Smm total_bytes_skipped += bytes_skipped; 1200228753Smm } 1201228753Smm if (filter->client_avail > 0) { 1202228753Smm min = minimum(request, (int64_t)filter->client_avail); 1203228753Smm bytes_skipped = __archive_read_filter_consume(filter, min); 1204228753Smm request -= bytes_skipped; 1205228753Smm total_bytes_skipped += bytes_skipped; 1206228753Smm } 1207228753Smm if (request == 0) 1208228753Smm return (total_bytes_skipped); 1209228753Smm /* 1210228753Smm * If a client_skipper was provided, try that first. 1211228753Smm */ 1212228753Smm#if ARCHIVE_API_VERSION < 2 1213228753Smm if ((filter->skip != NULL) && (request < SSIZE_MAX)) { 1214228753Smm#else 1215228753Smm if (filter->skip != NULL) { 1216228753Smm#endif 1217228753Smm bytes_skipped = (filter->skip)(filter, request); 1218228753Smm if (bytes_skipped < 0) { /* error */ 1219228753Smm filter->client_total = filter->client_avail = 0; 1220228753Smm filter->client_next = filter->client_buff = NULL; 1221228753Smm filter->fatal = 1; 1222228753Smm return (bytes_skipped); 1223228753Smm } 1224228753Smm total_bytes_skipped += bytes_skipped; 1225228753Smm request -= bytes_skipped; 1226228753Smm filter->client_next = filter->client_buff; 1227228753Smm filter->client_avail = filter->client_total = 0; 1228228753Smm } 1229228753Smm /* 1230228753Smm * Note that client_skipper will usually not satisfy the 1231228753Smm * full request (due to low-level blocking concerns), 1232228753Smm * so even if client_skipper is provided, we may still 1233228753Smm * have to use ordinary reads to finish out the request. 1234228753Smm */ 1235228753Smm while (request > 0) { 1236228753Smm ssize_t bytes_read; 1237228753Smm (void)__archive_read_filter_ahead(filter, 1, &bytes_read); 1238228753Smm if (bytes_read < 0) 1239228753Smm return (bytes_read); 1240228753Smm if (bytes_read == 0) { 1241228753Smm return (total_bytes_skipped); 1242228753Smm } 1243228753Smm min = (size_t)(minimum(bytes_read, request)); 1244228753Smm bytes_read = __archive_read_filter_consume(filter, min); 1245228753Smm total_bytes_skipped += bytes_read; 1246228753Smm request -= bytes_read; 1247228753Smm } 1248228753Smm return (total_bytes_skipped); 1249228753Smm} 1250