archive_read.c revision 282932
1228753Smm/*- 2232153Smm * Copyright (c) 2003-2011 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" 35228763Smm__FBSDID("$FreeBSD: head/contrib/libarchive/libarchive/archive_read.c 282932 2015-05-14 22:35:26Z delphij $"); 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 58232153Smmstatic int choose_filters(struct archive_read *); 59228753Smmstatic int choose_format(struct archive_read *); 60228753Smmstatic struct archive_vtable *archive_read_vtable(void); 61232153Smmstatic int64_t _archive_filter_bytes(struct archive *, int); 62232153Smmstatic int _archive_filter_code(struct archive *, int); 63232153Smmstatic const char *_archive_filter_name(struct archive *, int); 64232153Smmstatic int _archive_filter_count(struct archive *); 65228753Smmstatic int _archive_read_close(struct archive *); 66232153Smmstatic int _archive_read_data_block(struct archive *, 67232153Smm const void **, size_t *, int64_t *); 68228773Smmstatic int _archive_read_free(struct archive *); 69232153Smmstatic int _archive_read_next_header(struct archive *, 70232153Smm struct archive_entry **); 71232153Smmstatic int _archive_read_next_header2(struct archive *, 72232153Smm struct archive_entry *); 73232153Smmstatic int64_t advance_file_pointer(struct archive_read_filter *, int64_t); 74228753Smm 75228753Smmstatic struct archive_vtable * 76228753Smmarchive_read_vtable(void) 77228753Smm{ 78228753Smm static struct archive_vtable av; 79228753Smm static int inited = 0; 80228753Smm 81228753Smm if (!inited) { 82232153Smm av.archive_filter_bytes = _archive_filter_bytes; 83232153Smm av.archive_filter_code = _archive_filter_code; 84232153Smm av.archive_filter_name = _archive_filter_name; 85232153Smm av.archive_filter_count = _archive_filter_count; 86232153Smm av.archive_read_data_block = _archive_read_data_block; 87232153Smm av.archive_read_next_header = _archive_read_next_header; 88232153Smm av.archive_read_next_header2 = _archive_read_next_header2; 89228773Smm av.archive_free = _archive_read_free; 90228753Smm av.archive_close = _archive_read_close; 91232153Smm inited = 1; 92228753Smm } 93228753Smm return (&av); 94228753Smm} 95228753Smm 96228753Smm/* 97228753Smm * Allocate, initialize and return a struct archive object. 98228753Smm */ 99228753Smmstruct archive * 100228753Smmarchive_read_new(void) 101228753Smm{ 102228753Smm struct archive_read *a; 103228753Smm 104228753Smm a = (struct archive_read *)malloc(sizeof(*a)); 105228753Smm if (a == NULL) 106228753Smm return (NULL); 107228753Smm memset(a, 0, sizeof(*a)); 108228753Smm a->archive.magic = ARCHIVE_READ_MAGIC; 109228753Smm 110228753Smm a->archive.state = ARCHIVE_STATE_NEW; 111232153Smm a->entry = archive_entry_new2(&a->archive); 112228753Smm a->archive.vtable = archive_read_vtable(); 113228753Smm 114228753Smm return (&a->archive); 115228753Smm} 116228753Smm 117228753Smm/* 118228753Smm * Record the do-not-extract-to file. This belongs in archive_read_extract.c. 119228753Smm */ 120228753Smmvoid 121232153Smmarchive_read_extract_set_skip_file(struct archive *_a, int64_t d, int64_t i) 122228753Smm{ 123228753Smm struct archive_read *a = (struct archive_read *)_a; 124232153Smm 125232153Smm if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC, 126232153Smm ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file")) 127232153Smm return; 128232153Smm a->skip_file_set = 1; 129228753Smm a->skip_file_dev = d; 130228753Smm a->skip_file_ino = i; 131228753Smm} 132228753Smm 133228753Smm/* 134232153Smm * Open the archive 135228753Smm */ 136228753Smmint 137232153Smmarchive_read_open(struct archive *a, void *client_data, 138232153Smm archive_open_callback *client_opener, archive_read_callback *client_reader, 139232153Smm archive_close_callback *client_closer) 140228753Smm{ 141232153Smm /* Old archive_read_open() is just a thin shell around 142232153Smm * archive_read_open1. */ 143232153Smm archive_read_set_open_callback(a, client_opener); 144232153Smm archive_read_set_read_callback(a, client_reader); 145232153Smm archive_read_set_close_callback(a, client_closer); 146232153Smm archive_read_set_callback_data(a, client_data); 147232153Smm return archive_read_open1(a); 148228753Smm} 149228753Smm 150228753Smm 151228753Smmint 152232153Smmarchive_read_open2(struct archive *a, void *client_data, 153232153Smm archive_open_callback *client_opener, 154232153Smm archive_read_callback *client_reader, 155232153Smm archive_skip_callback *client_skipper, 156228753Smm archive_close_callback *client_closer) 157228753Smm{ 158232153Smm /* Old archive_read_open2() is just a thin shell around 159232153Smm * archive_read_open1. */ 160232153Smm archive_read_set_callback_data(a, client_data); 161232153Smm archive_read_set_open_callback(a, client_opener); 162232153Smm archive_read_set_read_callback(a, client_reader); 163232153Smm archive_read_set_skip_callback(a, client_skipper); 164232153Smm archive_read_set_close_callback(a, client_closer); 165232153Smm return archive_read_open1(a); 166228753Smm} 167228753Smm 168228753Smmstatic ssize_t 169228753Smmclient_read_proxy(struct archive_read_filter *self, const void **buff) 170228753Smm{ 171228753Smm ssize_t r; 172228753Smm r = (self->archive->client.reader)(&self->archive->archive, 173228753Smm self->data, buff); 174228753Smm return (r); 175228753Smm} 176228753Smm 177228753Smmstatic int64_t 178228753Smmclient_skip_proxy(struct archive_read_filter *self, int64_t request) 179228753Smm{ 180232153Smm if (request < 0) 181232153Smm __archive_errx(1, "Negative skip requested."); 182232153Smm if (request == 0) 183232153Smm return 0; 184228753Smm 185232153Smm if (self->archive->client.skipper != NULL) { 186232153Smm /* Seek requests over 1GiB are broken down into 187232153Smm * multiple seeks. This avoids overflows when the 188232153Smm * requests get passed through 32-bit arguments. */ 189232153Smm int64_t skip_limit = (int64_t)1 << 30; 190232153Smm int64_t total = 0; 191232153Smm for (;;) { 192232153Smm int64_t get, ask = request; 193232153Smm if (ask > skip_limit) 194232153Smm ask = skip_limit; 195248616Smm get = (self->archive->client.skipper) 196248616Smm (&self->archive->archive, self->data, ask); 197232153Smm if (get == 0) 198232153Smm return (total); 199232153Smm request -= get; 200232153Smm total += get; 201232153Smm } 202232153Smm } else if (self->archive->client.seeker != NULL 203232153Smm && request > 64 * 1024) { 204232153Smm /* If the client provided a seeker but not a skipper, 205232153Smm * we can use the seeker to skip forward. 206232153Smm * 207232153Smm * Note: This isn't always a good idea. The client 208232153Smm * skipper is allowed to skip by less than requested 209232153Smm * if it needs to maintain block alignment. The 210232153Smm * seeker is not allowed to play such games, so using 211232153Smm * the seeker here may be a performance loss compared 212232153Smm * to just reading and discarding. That's why we 213232153Smm * only do this for skips of over 64k. 214232153Smm */ 215232153Smm int64_t before = self->position; 216248616Smm int64_t after = (self->archive->client.seeker) 217248616Smm (&self->archive->archive, self->data, request, SEEK_CUR); 218232153Smm if (after != before + request) 219232153Smm return ARCHIVE_FATAL; 220232153Smm return after - before; 221228753Smm } 222232153Smm return 0; 223228753Smm} 224228753Smm 225232153Smmstatic int64_t 226232153Smmclient_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence) 227232153Smm{ 228232153Smm /* DO NOT use the skipper here! If we transparently handled 229232153Smm * forward seek here by using the skipper, that will break 230232153Smm * other libarchive code that assumes a successful forward 231232153Smm * seek means it can also seek backwards. 232232153Smm */ 233232153Smm if (self->archive->client.seeker == NULL) 234232153Smm return (ARCHIVE_FAILED); 235232153Smm return (self->archive->client.seeker)(&self->archive->archive, 236232153Smm self->data, offset, whence); 237232153Smm} 238232153Smm 239228753Smmstatic int 240228753Smmclient_close_proxy(struct archive_read_filter *self) 241228753Smm{ 242248616Smm int r = ARCHIVE_OK, r2; 243248616Smm unsigned int i; 244228753Smm 245248616Smm if (self->archive->client.closer == NULL) 246248616Smm return (r); 247248616Smm for (i = 0; i < self->archive->client.nodes; i++) 248248616Smm { 249248616Smm r2 = (self->archive->client.closer) 250248616Smm ((struct archive *)self->archive, 251248616Smm self->archive->client.dataset[i].data); 252248616Smm if (r > r2) 253248616Smm r = r2; 254248616Smm } 255228753Smm return (r); 256228753Smm} 257228753Smm 258248616Smmstatic int 259248616Smmclient_open_proxy(struct archive_read_filter *self) 260248616Smm{ 261248616Smm int r = ARCHIVE_OK; 262248616Smm if (self->archive->client.opener != NULL) 263248616Smm r = (self->archive->client.opener)( 264248616Smm (struct archive *)self->archive, self->data); 265248616Smm return (r); 266248616Smm} 267248616Smm 268248616Smmstatic int 269248616Smmclient_switch_proxy(struct archive_read_filter *self, unsigned int iindex) 270248616Smm{ 271248616Smm int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; 272248616Smm void *data2 = NULL; 273248616Smm 274248616Smm /* Don't do anything if already in the specified data node */ 275248616Smm if (self->archive->client.cursor == iindex) 276248616Smm return (ARCHIVE_OK); 277248616Smm 278248616Smm self->archive->client.cursor = iindex; 279248616Smm data2 = self->archive->client.dataset[self->archive->client.cursor].data; 280248616Smm if (self->archive->client.switcher != NULL) 281248616Smm { 282248616Smm r1 = r2 = (self->archive->client.switcher) 283248616Smm ((struct archive *)self->archive, self->data, data2); 284248616Smm self->data = data2; 285248616Smm } 286248616Smm else 287248616Smm { 288248616Smm /* Attempt to call close and open instead */ 289248616Smm if (self->archive->client.closer != NULL) 290248616Smm r1 = (self->archive->client.closer) 291248616Smm ((struct archive *)self->archive, self->data); 292248616Smm self->data = data2; 293248616Smm if (self->archive->client.opener != NULL) 294248616Smm r2 = (self->archive->client.opener) 295248616Smm ((struct archive *)self->archive, self->data); 296248616Smm } 297248616Smm return (r1 < r2) ? r1 : r2; 298248616Smm} 299248616Smm 300232153Smmint 301232153Smmarchive_read_set_open_callback(struct archive *_a, 302232153Smm archive_open_callback *client_opener) 303232153Smm{ 304232153Smm struct archive_read *a = (struct archive_read *)_a; 305232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 306232153Smm "archive_read_set_open_callback"); 307232153Smm a->client.opener = client_opener; 308232153Smm return ARCHIVE_OK; 309232153Smm} 310228753Smm 311228753Smmint 312232153Smmarchive_read_set_read_callback(struct archive *_a, 313232153Smm archive_read_callback *client_reader) 314232153Smm{ 315232153Smm struct archive_read *a = (struct archive_read *)_a; 316232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 317232153Smm "archive_read_set_read_callback"); 318232153Smm a->client.reader = client_reader; 319232153Smm return ARCHIVE_OK; 320232153Smm} 321232153Smm 322232153Smmint 323232153Smmarchive_read_set_skip_callback(struct archive *_a, 324232153Smm archive_skip_callback *client_skipper) 325232153Smm{ 326232153Smm struct archive_read *a = (struct archive_read *)_a; 327232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 328232153Smm "archive_read_set_skip_callback"); 329232153Smm a->client.skipper = client_skipper; 330232153Smm return ARCHIVE_OK; 331232153Smm} 332232153Smm 333232153Smmint 334232153Smmarchive_read_set_seek_callback(struct archive *_a, 335232153Smm archive_seek_callback *client_seeker) 336232153Smm{ 337232153Smm struct archive_read *a = (struct archive_read *)_a; 338232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 339232153Smm "archive_read_set_seek_callback"); 340232153Smm a->client.seeker = client_seeker; 341232153Smm return ARCHIVE_OK; 342232153Smm} 343232153Smm 344232153Smmint 345232153Smmarchive_read_set_close_callback(struct archive *_a, 346228753Smm archive_close_callback *client_closer) 347228753Smm{ 348228753Smm struct archive_read *a = (struct archive_read *)_a; 349232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 350232153Smm "archive_read_set_close_callback"); 351232153Smm a->client.closer = client_closer; 352232153Smm return ARCHIVE_OK; 353232153Smm} 354232153Smm 355232153Smmint 356248616Smmarchive_read_set_switch_callback(struct archive *_a, 357248616Smm archive_switch_callback *client_switcher) 358248616Smm{ 359248616Smm struct archive_read *a = (struct archive_read *)_a; 360248616Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 361248616Smm "archive_read_set_switch_callback"); 362248616Smm a->client.switcher = client_switcher; 363248616Smm return ARCHIVE_OK; 364248616Smm} 365248616Smm 366248616Smmint 367232153Smmarchive_read_set_callback_data(struct archive *_a, void *client_data) 368232153Smm{ 369248616Smm return archive_read_set_callback_data2(_a, client_data, 0); 370248616Smm} 371248616Smm 372248616Smmint 373248616Smmarchive_read_set_callback_data2(struct archive *_a, void *client_data, 374248616Smm unsigned int iindex) 375248616Smm{ 376232153Smm struct archive_read *a = (struct archive_read *)_a; 377232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 378248616Smm "archive_read_set_callback_data2"); 379248616Smm 380248616Smm if (a->client.nodes == 0) 381248616Smm { 382248616Smm a->client.dataset = (struct archive_read_data_node *) 383248616Smm calloc(1, sizeof(*a->client.dataset)); 384248616Smm if (a->client.dataset == NULL) 385248616Smm { 386248616Smm archive_set_error(&a->archive, ENOMEM, 387248616Smm "No memory."); 388248616Smm return ARCHIVE_FATAL; 389248616Smm } 390248616Smm a->client.nodes = 1; 391248616Smm } 392248616Smm 393248616Smm if (iindex > a->client.nodes - 1) 394248616Smm { 395248616Smm archive_set_error(&a->archive, EINVAL, 396248616Smm "Invalid index specified."); 397248616Smm return ARCHIVE_FATAL; 398248616Smm } 399248616Smm a->client.dataset[iindex].data = client_data; 400248616Smm a->client.dataset[iindex].begin_position = -1; 401248616Smm a->client.dataset[iindex].total_size = -1; 402232153Smm return ARCHIVE_OK; 403232153Smm} 404232153Smm 405232153Smmint 406248616Smmarchive_read_add_callback_data(struct archive *_a, void *client_data, 407248616Smm unsigned int iindex) 408248616Smm{ 409248616Smm struct archive_read *a = (struct archive_read *)_a; 410248616Smm void *p; 411248616Smm unsigned int i; 412248616Smm 413248616Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 414248616Smm "archive_read_add_callback_data"); 415248616Smm if (iindex > a->client.nodes) { 416248616Smm archive_set_error(&a->archive, EINVAL, 417248616Smm "Invalid index specified."); 418248616Smm return ARCHIVE_FATAL; 419248616Smm } 420248616Smm p = realloc(a->client.dataset, sizeof(*a->client.dataset) 421248616Smm * (++(a->client.nodes))); 422248616Smm if (p == NULL) { 423248616Smm archive_set_error(&a->archive, ENOMEM, 424248616Smm "No memory."); 425248616Smm return ARCHIVE_FATAL; 426248616Smm } 427248616Smm a->client.dataset = (struct archive_read_data_node *)p; 428248616Smm for (i = a->client.nodes - 1; i > iindex && i > 0; i--) { 429248616Smm a->client.dataset[i].data = a->client.dataset[i-1].data; 430248616Smm a->client.dataset[i].begin_position = -1; 431248616Smm a->client.dataset[i].total_size = -1; 432248616Smm } 433248616Smm a->client.dataset[iindex].data = client_data; 434248616Smm a->client.dataset[iindex].begin_position = -1; 435248616Smm a->client.dataset[iindex].total_size = -1; 436248616Smm return ARCHIVE_OK; 437248616Smm} 438248616Smm 439248616Smmint 440248616Smmarchive_read_append_callback_data(struct archive *_a, void *client_data) 441248616Smm{ 442248616Smm struct archive_read *a = (struct archive_read *)_a; 443248616Smm return archive_read_add_callback_data(_a, client_data, a->client.nodes); 444248616Smm} 445248616Smm 446248616Smmint 447248616Smmarchive_read_prepend_callback_data(struct archive *_a, void *client_data) 448248616Smm{ 449248616Smm return archive_read_add_callback_data(_a, client_data, 0); 450248616Smm} 451248616Smm 452248616Smmint 453232153Smmarchive_read_open1(struct archive *_a) 454232153Smm{ 455232153Smm struct archive_read *a = (struct archive_read *)_a; 456248616Smm struct archive_read_filter *filter, *tmp; 457248616Smm int slot; 458248616Smm int e = 0; 459248616Smm unsigned int i; 460228753Smm 461232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 462228753Smm "archive_read_open"); 463228753Smm archive_clear_error(&a->archive); 464228753Smm 465232153Smm if (a->client.reader == NULL) { 466232153Smm archive_set_error(&a->archive, EINVAL, 467228753Smm "No reader function provided to archive_read_open"); 468232153Smm a->archive.state = ARCHIVE_STATE_FATAL; 469232153Smm return (ARCHIVE_FATAL); 470232153Smm } 471228753Smm 472228753Smm /* Open data source. */ 473232153Smm if (a->client.opener != NULL) { 474248616Smm e = (a->client.opener)(&a->archive, a->client.dataset[0].data); 475228753Smm if (e != 0) { 476228753Smm /* If the open failed, call the closer to clean up. */ 477248616Smm if (a->client.closer) { 478248616Smm for (i = 0; i < a->client.nodes; i++) 479248616Smm (a->client.closer)(&a->archive, 480248616Smm a->client.dataset[i].data); 481248616Smm } 482228753Smm return (e); 483228753Smm } 484228753Smm } 485228753Smm 486228753Smm filter = calloc(1, sizeof(*filter)); 487228753Smm if (filter == NULL) 488228753Smm return (ARCHIVE_FATAL); 489228753Smm filter->bidder = NULL; 490228753Smm filter->upstream = NULL; 491228753Smm filter->archive = a; 492248616Smm filter->data = a->client.dataset[0].data; 493248616Smm filter->open = client_open_proxy; 494228753Smm filter->read = client_read_proxy; 495228753Smm filter->skip = client_skip_proxy; 496232153Smm filter->seek = client_seek_proxy; 497228753Smm filter->close = client_close_proxy; 498248616Smm filter->sswitch = client_switch_proxy; 499228753Smm filter->name = "none"; 500248616Smm filter->code = ARCHIVE_FILTER_NONE; 501228753Smm 502248616Smm a->client.dataset[0].begin_position = 0; 503248616Smm if (!a->filter || !a->bypass_filter_bidding) 504248616Smm { 505248616Smm a->filter = filter; 506248616Smm /* Build out the input pipeline. */ 507248616Smm e = choose_filters(a); 508248616Smm if (e < ARCHIVE_WARN) { 509248616Smm a->archive.state = ARCHIVE_STATE_FATAL; 510248616Smm return (ARCHIVE_FATAL); 511248616Smm } 512232153Smm } 513248616Smm else 514248616Smm { 515248616Smm /* Need to add "NONE" type filter at the end of the filter chain */ 516248616Smm tmp = a->filter; 517248616Smm while (tmp->upstream) 518248616Smm tmp = tmp->upstream; 519248616Smm tmp->upstream = filter; 520248616Smm } 521228753Smm 522248616Smm if (!a->format) 523248616Smm { 524248616Smm slot = choose_format(a); 525248616Smm if (slot < 0) { 526248616Smm __archive_read_close_filters(a); 527248616Smm a->archive.state = ARCHIVE_STATE_FATAL; 528248616Smm return (ARCHIVE_FATAL); 529248616Smm } 530248616Smm a->format = &(a->formats[slot]); 531232153Smm } 532232153Smm 533232153Smm a->archive.state = ARCHIVE_STATE_HEADER; 534248616Smm 535248616Smm /* Ensure libarchive starts from the first node in a multivolume set */ 536248616Smm client_switch_proxy(a->filter, 0); 537228753Smm return (e); 538228753Smm} 539228753Smm 540228753Smm/* 541228753Smm * Allow each registered stream transform to bid on whether 542228753Smm * it wants to handle this stream. Repeat until we've finished 543228753Smm * building the pipeline. 544228753Smm */ 545228753Smmstatic int 546232153Smmchoose_filters(struct archive_read *a) 547228753Smm{ 548228753Smm int number_bidders, i, bid, best_bid; 549228753Smm struct archive_read_filter_bidder *bidder, *best_bidder; 550228753Smm struct archive_read_filter *filter; 551228753Smm ssize_t avail; 552228753Smm int r; 553228753Smm 554228753Smm for (;;) { 555228753Smm number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 556228753Smm 557228753Smm best_bid = 0; 558228753Smm best_bidder = NULL; 559228753Smm 560228753Smm bidder = a->bidders; 561228753Smm for (i = 0; i < number_bidders; i++, bidder++) { 562228753Smm if (bidder->bid != NULL) { 563228753Smm bid = (bidder->bid)(bidder, a->filter); 564228753Smm if (bid > best_bid) { 565228753Smm best_bid = bid; 566228753Smm best_bidder = bidder; 567228753Smm } 568228753Smm } 569228753Smm } 570228753Smm 571228753Smm /* If no bidder, we're done. */ 572228753Smm if (best_bidder == NULL) { 573232153Smm /* Verify the filter by asking it for some data. */ 574228753Smm __archive_read_filter_ahead(a->filter, 1, &avail); 575228753Smm if (avail < 0) { 576248616Smm __archive_read_close_filters(a); 577248616Smm __archive_read_free_filters(a); 578228753Smm return (ARCHIVE_FATAL); 579228753Smm } 580228753Smm a->archive.compression_name = a->filter->name; 581228753Smm a->archive.compression_code = a->filter->code; 582228753Smm return (ARCHIVE_OK); 583228753Smm } 584228753Smm 585228753Smm filter 586228753Smm = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 587228753Smm if (filter == NULL) 588228753Smm return (ARCHIVE_FATAL); 589228753Smm filter->bidder = best_bidder; 590228753Smm filter->archive = a; 591228753Smm filter->upstream = a->filter; 592228753Smm a->filter = filter; 593228753Smm r = (best_bidder->init)(a->filter); 594228753Smm if (r != ARCHIVE_OK) { 595248616Smm __archive_read_close_filters(a); 596248616Smm __archive_read_free_filters(a); 597232153Smm return (ARCHIVE_FATAL); 598228753Smm } 599228753Smm } 600228753Smm} 601228753Smm 602228753Smm/* 603228753Smm * Read header of next entry. 604228753Smm */ 605232153Smmstatic int 606232153Smm_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) 607228753Smm{ 608228753Smm struct archive_read *a = (struct archive_read *)_a; 609232153Smm int r1 = ARCHIVE_OK, r2; 610228753Smm 611232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 612228753Smm ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 613228753Smm "archive_read_next_header"); 614228753Smm 615228753Smm archive_entry_clear(entry); 616228753Smm archive_clear_error(&a->archive); 617228753Smm 618228753Smm /* 619228753Smm * If client didn't consume entire data, skip any remainder 620228753Smm * (This is especially important for GNU incremental directories.) 621228753Smm */ 622228753Smm if (a->archive.state == ARCHIVE_STATE_DATA) { 623232153Smm r1 = archive_read_data_skip(&a->archive); 624232153Smm if (r1 == ARCHIVE_EOF) 625232153Smm archive_set_error(&a->archive, EIO, 626232153Smm "Premature end-of-file."); 627232153Smm if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) { 628228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 629228753Smm return (ARCHIVE_FATAL); 630228753Smm } 631228753Smm } 632228753Smm 633232153Smm /* Record start-of-header offset in uncompressed stream. */ 634232153Smm a->header_position = a->filter->position; 635228753Smm 636232153Smm ++_a->file_count; 637232153Smm r2 = (a->format->read_header)(a, entry); 638228753Smm 639228753Smm /* 640228753Smm * EOF and FATAL are persistent at this layer. By 641228753Smm * modifying the state, we guarantee that future calls to 642228753Smm * read a header or read data will fail. 643228753Smm */ 644232153Smm switch (r2) { 645228753Smm case ARCHIVE_EOF: 646228753Smm a->archive.state = ARCHIVE_STATE_EOF; 647232153Smm --_a->file_count;/* Revert a file counter. */ 648228753Smm break; 649228753Smm case ARCHIVE_OK: 650228753Smm a->archive.state = ARCHIVE_STATE_DATA; 651228753Smm break; 652228753Smm case ARCHIVE_WARN: 653228753Smm a->archive.state = ARCHIVE_STATE_DATA; 654228753Smm break; 655228753Smm case ARCHIVE_RETRY: 656228753Smm break; 657228753Smm case ARCHIVE_FATAL: 658228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 659228753Smm break; 660228753Smm } 661228753Smm 662228753Smm a->read_data_output_offset = 0; 663228753Smm a->read_data_remaining = 0; 664248616Smm a->read_data_is_posix_read = 0; 665248616Smm a->read_data_requested = 0; 666248616Smm a->data_start_node = a->client.cursor; 667232153Smm /* EOF always wins; otherwise return the worst error. */ 668232153Smm return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1; 669228753Smm} 670228753Smm 671228753Smmint 672232153Smm_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) 673228753Smm{ 674228753Smm int ret; 675228753Smm struct archive_read *a = (struct archive_read *)_a; 676228753Smm *entryp = NULL; 677232153Smm ret = _archive_read_next_header2(_a, a->entry); 678228753Smm *entryp = a->entry; 679228753Smm return ret; 680228753Smm} 681228753Smm 682228753Smm/* 683228753Smm * Allow each registered format to bid on whether it wants to handle 684228753Smm * the next entry. Return index of winning bidder. 685228753Smm */ 686228753Smmstatic int 687228753Smmchoose_format(struct archive_read *a) 688228753Smm{ 689228753Smm int slots; 690228753Smm int i; 691228753Smm int bid, best_bid; 692228753Smm int best_bid_slot; 693228753Smm 694228753Smm slots = sizeof(a->formats) / sizeof(a->formats[0]); 695228753Smm best_bid = -1; 696228753Smm best_bid_slot = -1; 697228753Smm 698232153Smm /* Set up a->format for convenience of bidders. */ 699228753Smm a->format = &(a->formats[0]); 700228753Smm for (i = 0; i < slots; i++, a->format++) { 701228753Smm if (a->format->bid) { 702232153Smm bid = (a->format->bid)(a, best_bid); 703228753Smm if (bid == ARCHIVE_FATAL) 704228753Smm return (ARCHIVE_FATAL); 705232153Smm if (a->filter->position != 0) 706232153Smm __archive_read_seek(a, 0, SEEK_SET); 707228753Smm if ((bid > best_bid) || (best_bid_slot < 0)) { 708228753Smm best_bid = bid; 709228753Smm best_bid_slot = i; 710228753Smm } 711228753Smm } 712228753Smm } 713228753Smm 714228753Smm /* 715228753Smm * There were no bidders; this is a serious programmer error 716228753Smm * and demands a quick and definitive abort. 717228753Smm */ 718232153Smm if (best_bid_slot < 0) { 719232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 720232153Smm "No formats registered"); 721232153Smm return (ARCHIVE_FATAL); 722232153Smm } 723228753Smm 724228753Smm /* 725228753Smm * There were bidders, but no non-zero bids; this means we 726228753Smm * can't support this stream. 727228753Smm */ 728228753Smm if (best_bid < 1) { 729228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 730228753Smm "Unrecognized archive format"); 731228753Smm return (ARCHIVE_FATAL); 732228753Smm } 733228753Smm 734228753Smm return (best_bid_slot); 735228753Smm} 736228753Smm 737228753Smm/* 738228753Smm * Return the file offset (within the uncompressed data stream) where 739228753Smm * the last header started. 740228753Smm */ 741228753Smmint64_t 742228753Smmarchive_read_header_position(struct archive *_a) 743228753Smm{ 744228753Smm struct archive_read *a = (struct archive_read *)_a; 745232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 746228753Smm ARCHIVE_STATE_ANY, "archive_read_header_position"); 747228753Smm return (a->header_position); 748228753Smm} 749228753Smm 750228753Smm/* 751228753Smm * Read data from an archive entry, using a read(2)-style interface. 752228753Smm * This is a convenience routine that just calls 753228753Smm * archive_read_data_block and copies the results into the client 754228753Smm * buffer, filling any gaps with zero bytes. Clients using this 755228753Smm * API can be completely ignorant of sparse-file issues; sparse files 756228753Smm * will simply be padded with nulls. 757228753Smm * 758228753Smm * DO NOT intermingle calls to this function and archive_read_data_block 759228753Smm * to read a single entry body. 760228753Smm */ 761228753Smmssize_t 762228753Smmarchive_read_data(struct archive *_a, void *buff, size_t s) 763228753Smm{ 764228753Smm struct archive_read *a = (struct archive_read *)_a; 765228753Smm char *dest; 766228753Smm const void *read_buf; 767228753Smm size_t bytes_read; 768228753Smm size_t len; 769228753Smm int r; 770228753Smm 771228753Smm bytes_read = 0; 772228753Smm dest = (char *)buff; 773228753Smm 774228753Smm while (s > 0) { 775228753Smm if (a->read_data_remaining == 0) { 776228753Smm read_buf = a->read_data_block; 777248616Smm a->read_data_is_posix_read = 1; 778248616Smm a->read_data_requested = s; 779232153Smm r = _archive_read_data_block(&a->archive, &read_buf, 780228753Smm &a->read_data_remaining, &a->read_data_offset); 781228753Smm a->read_data_block = read_buf; 782228753Smm if (r == ARCHIVE_EOF) 783228753Smm return (bytes_read); 784228753Smm /* 785228753Smm * Error codes are all negative, so the status 786228753Smm * return here cannot be confused with a valid 787228753Smm * byte count. (ARCHIVE_OK is zero.) 788228753Smm */ 789228753Smm if (r < ARCHIVE_OK) 790228753Smm return (r); 791228753Smm } 792228753Smm 793228753Smm if (a->read_data_offset < a->read_data_output_offset) { 794228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 795228753Smm "Encountered out-of-order sparse blocks"); 796228753Smm return (ARCHIVE_RETRY); 797228753Smm } 798228753Smm 799228753Smm /* Compute the amount of zero padding needed. */ 800232153Smm if (a->read_data_output_offset + (int64_t)s < 801228753Smm a->read_data_offset) { 802228753Smm len = s; 803228753Smm } else if (a->read_data_output_offset < 804228753Smm a->read_data_offset) { 805238856Smm len = (size_t)(a->read_data_offset - 806238856Smm a->read_data_output_offset); 807228753Smm } else 808228753Smm len = 0; 809228753Smm 810228753Smm /* Add zeroes. */ 811228753Smm memset(dest, 0, len); 812228753Smm s -= len; 813228753Smm a->read_data_output_offset += len; 814228753Smm dest += len; 815228753Smm bytes_read += len; 816228753Smm 817228753Smm /* Copy data if there is any space left. */ 818228753Smm if (s > 0) { 819228753Smm len = a->read_data_remaining; 820228753Smm if (len > s) 821228753Smm len = s; 822228753Smm memcpy(dest, a->read_data_block, len); 823228753Smm s -= len; 824228753Smm a->read_data_block += len; 825228753Smm a->read_data_remaining -= len; 826228753Smm a->read_data_output_offset += len; 827228753Smm a->read_data_offset += len; 828228753Smm dest += len; 829228753Smm bytes_read += len; 830228753Smm } 831228753Smm } 832248616Smm a->read_data_is_posix_read = 0; 833248616Smm a->read_data_requested = 0; 834228753Smm return (bytes_read); 835228753Smm} 836228753Smm 837228753Smm/* 838228753Smm * Skip over all remaining data in this entry. 839228753Smm */ 840228753Smmint 841228753Smmarchive_read_data_skip(struct archive *_a) 842228753Smm{ 843228753Smm struct archive_read *a = (struct archive_read *)_a; 844228753Smm int r; 845228753Smm const void *buff; 846228753Smm size_t size; 847232153Smm int64_t offset; 848228753Smm 849232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 850228753Smm "archive_read_data_skip"); 851228753Smm 852228753Smm if (a->format->read_data_skip != NULL) 853228753Smm r = (a->format->read_data_skip)(a); 854228753Smm else { 855228753Smm while ((r = archive_read_data_block(&a->archive, 856228753Smm &buff, &size, &offset)) 857228753Smm == ARCHIVE_OK) 858228753Smm ; 859228753Smm } 860228753Smm 861228753Smm if (r == ARCHIVE_EOF) 862228753Smm r = ARCHIVE_OK; 863228753Smm 864228753Smm a->archive.state = ARCHIVE_STATE_HEADER; 865228753Smm return (r); 866228753Smm} 867228753Smm 868248616Smmint64_t 869248616Smmarchive_seek_data(struct archive *_a, int64_t offset, int whence) 870248616Smm{ 871248616Smm struct archive_read *a = (struct archive_read *)_a; 872248616Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 873248616Smm "archive_seek_data_block"); 874248616Smm 875248616Smm if (a->format->seek_data == NULL) { 876248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 877248616Smm "Internal error: " 878248616Smm "No format_seek_data_block function registered"); 879248616Smm return (ARCHIVE_FATAL); 880248616Smm } 881248616Smm 882248616Smm return (a->format->seek_data)(a, offset, whence); 883248616Smm} 884248616Smm 885228753Smm/* 886228753Smm * Read the next block of entry data from the archive. 887228753Smm * This is a zero-copy interface; the client receives a pointer, 888228753Smm * size, and file offset of the next available block of data. 889228753Smm * 890228753Smm * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if 891228753Smm * the end of entry is encountered. 892228753Smm */ 893232153Smmstatic int 894232153Smm_archive_read_data_block(struct archive *_a, 895232153Smm const void **buff, size_t *size, int64_t *offset) 896228753Smm{ 897228753Smm struct archive_read *a = (struct archive_read *)_a; 898232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 899228753Smm "archive_read_data_block"); 900228753Smm 901228753Smm if (a->format->read_data == NULL) { 902228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 903228753Smm "Internal error: " 904228753Smm "No format_read_data_block function registered"); 905228753Smm return (ARCHIVE_FATAL); 906228753Smm } 907228753Smm 908228753Smm return (a->format->read_data)(a, buff, size, offset); 909228753Smm} 910228753Smm 911248616Smmint 912248616Smm__archive_read_close_filters(struct archive_read *a) 913232153Smm{ 914232153Smm struct archive_read_filter *f = a->filter; 915232153Smm int r = ARCHIVE_OK; 916232153Smm /* Close each filter in the pipeline. */ 917232153Smm while (f != NULL) { 918232153Smm struct archive_read_filter *t = f->upstream; 919232153Smm if (!f->closed && f->close != NULL) { 920232153Smm int r1 = (f->close)(f); 921232153Smm f->closed = 1; 922232153Smm if (r1 < r) 923232153Smm r = r1; 924232153Smm } 925232153Smm free(f->buffer); 926232153Smm f->buffer = NULL; 927232153Smm f = t; 928232153Smm } 929232153Smm return r; 930232153Smm} 931232153Smm 932248616Smmvoid 933248616Smm__archive_read_free_filters(struct archive_read *a) 934232153Smm{ 935232153Smm while (a->filter != NULL) { 936232153Smm struct archive_read_filter *t = a->filter->upstream; 937232153Smm free(a->filter); 938232153Smm a->filter = t; 939232153Smm } 940232153Smm} 941232153Smm 942228753Smm/* 943232153Smm * return the count of # of filters in use 944228753Smm */ 945228753Smmstatic int 946232153Smm_archive_filter_count(struct archive *_a) 947232153Smm{ 948232153Smm struct archive_read *a = (struct archive_read *)_a; 949232153Smm struct archive_read_filter *p = a->filter; 950232153Smm int count = 0; 951232153Smm while(p) { 952232153Smm count++; 953232153Smm p = p->upstream; 954232153Smm } 955232153Smm return count; 956232153Smm} 957232153Smm 958232153Smm/* 959232153Smm * Close the file and all I/O. 960232153Smm */ 961232153Smmstatic int 962228753Smm_archive_read_close(struct archive *_a) 963228753Smm{ 964228753Smm struct archive_read *a = (struct archive_read *)_a; 965228753Smm int r = ARCHIVE_OK, r1 = ARCHIVE_OK; 966228753Smm 967232153Smm archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, 968232153Smm ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); 969232153Smm if (a->archive.state == ARCHIVE_STATE_CLOSED) 970232153Smm return (ARCHIVE_OK); 971228753Smm archive_clear_error(&a->archive); 972228753Smm a->archive.state = ARCHIVE_STATE_CLOSED; 973228753Smm 974228753Smm /* TODO: Clean up the formatters. */ 975228753Smm 976228753Smm /* Release the filter objects. */ 977248616Smm r1 = __archive_read_close_filters(a); 978228753Smm if (r1 < r) 979228753Smm r = r1; 980228753Smm 981228753Smm return (r); 982228753Smm} 983228753Smm 984228753Smm/* 985228753Smm * Release memory and other resources. 986228753Smm */ 987228753Smmstatic int 988228773Smm_archive_read_free(struct archive *_a) 989228753Smm{ 990228753Smm struct archive_read *a = (struct archive_read *)_a; 991232153Smm int i, n; 992228753Smm int slots; 993228753Smm int r = ARCHIVE_OK; 994228753Smm 995232153Smm if (_a == NULL) 996232153Smm return (ARCHIVE_OK); 997232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 998232153Smm ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); 999232153Smm if (a->archive.state != ARCHIVE_STATE_CLOSED 1000232153Smm && a->archive.state != ARCHIVE_STATE_FATAL) 1001228753Smm r = archive_read_close(&a->archive); 1002228753Smm 1003232153Smm /* Call cleanup functions registered by optional components. */ 1004232153Smm if (a->cleanup_archive_extract != NULL) 1005232153Smm r = (a->cleanup_archive_extract)(a); 1006232153Smm 1007228753Smm /* Cleanup format-specific data. */ 1008228753Smm slots = sizeof(a->formats) / sizeof(a->formats[0]); 1009228753Smm for (i = 0; i < slots; i++) { 1010228753Smm a->format = &(a->formats[i]); 1011228753Smm if (a->formats[i].cleanup) 1012228753Smm (a->formats[i].cleanup)(a); 1013228753Smm } 1014228753Smm 1015232153Smm /* Free the filters */ 1016248616Smm __archive_read_free_filters(a); 1017232153Smm 1018232153Smm /* Release the bidder objects. */ 1019232153Smm n = sizeof(a->bidders)/sizeof(a->bidders[0]); 1020232153Smm for (i = 0; i < n; i++) { 1021232153Smm if (a->bidders[i].free != NULL) { 1022232153Smm int r1 = (a->bidders[i].free)(&a->bidders[i]); 1023232153Smm if (r1 < r) 1024232153Smm r = r1; 1025232153Smm } 1026232153Smm } 1027232153Smm 1028228753Smm archive_string_free(&a->archive.error_string); 1029228753Smm if (a->entry) 1030228753Smm archive_entry_free(a->entry); 1031228753Smm a->archive.magic = 0; 1032232153Smm __archive_clean(&a->archive); 1033248616Smm free(a->client.dataset); 1034228753Smm free(a); 1035228753Smm return (r); 1036228753Smm} 1037228753Smm 1038232153Smmstatic struct archive_read_filter * 1039232153Smmget_filter(struct archive *_a, int n) 1040232153Smm{ 1041232153Smm struct archive_read *a = (struct archive_read *)_a; 1042232153Smm struct archive_read_filter *f = a->filter; 1043248616Smm /* We use n == -1 for 'the last filter', which is always the 1044248616Smm * client proxy. */ 1045232153Smm if (n == -1 && f != NULL) { 1046232153Smm struct archive_read_filter *last = f; 1047232153Smm f = f->upstream; 1048232153Smm while (f != NULL) { 1049232153Smm last = f; 1050232153Smm f = f->upstream; 1051232153Smm } 1052232153Smm return (last); 1053232153Smm } 1054232153Smm if (n < 0) 1055232153Smm return NULL; 1056232153Smm while (n > 0 && f != NULL) { 1057232153Smm f = f->upstream; 1058232153Smm --n; 1059232153Smm } 1060232153Smm return (f); 1061232153Smm} 1062232153Smm 1063232153Smmstatic int 1064232153Smm_archive_filter_code(struct archive *_a, int n) 1065232153Smm{ 1066232153Smm struct archive_read_filter *f = get_filter(_a, n); 1067232153Smm return f == NULL ? -1 : f->code; 1068232153Smm} 1069232153Smm 1070232153Smmstatic const char * 1071232153Smm_archive_filter_name(struct archive *_a, int n) 1072232153Smm{ 1073232153Smm struct archive_read_filter *f = get_filter(_a, n); 1074232153Smm return f == NULL ? NULL : f->name; 1075232153Smm} 1076232153Smm 1077232153Smmstatic int64_t 1078232153Smm_archive_filter_bytes(struct archive *_a, int n) 1079232153Smm{ 1080232153Smm struct archive_read_filter *f = get_filter(_a, n); 1081232153Smm return f == NULL ? -1 : f->position; 1082232153Smm} 1083232153Smm 1084228753Smm/* 1085228753Smm * Used internally by read format handlers to register their bid and 1086228753Smm * initialization functions. 1087228753Smm */ 1088228753Smmint 1089228753Smm__archive_read_register_format(struct archive_read *a, 1090228753Smm void *format_data, 1091228753Smm const char *name, 1092232153Smm int (*bid)(struct archive_read *, int), 1093228753Smm int (*options)(struct archive_read *, const char *, const char *), 1094228753Smm int (*read_header)(struct archive_read *, struct archive_entry *), 1095232153Smm int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), 1096228753Smm int (*read_data_skip)(struct archive_read *), 1097248616Smm int64_t (*seek_data)(struct archive_read *, int64_t, int), 1098228753Smm int (*cleanup)(struct archive_read *)) 1099228753Smm{ 1100228753Smm int i, number_slots; 1101228753Smm 1102232153Smm archive_check_magic(&a->archive, 1103228753Smm ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 1104228753Smm "__archive_read_register_format"); 1105228753Smm 1106228753Smm number_slots = sizeof(a->formats) / sizeof(a->formats[0]); 1107228753Smm 1108228753Smm for (i = 0; i < number_slots; i++) { 1109228753Smm if (a->formats[i].bid == bid) 1110228753Smm return (ARCHIVE_WARN); /* We've already installed */ 1111228753Smm if (a->formats[i].bid == NULL) { 1112228753Smm a->formats[i].bid = bid; 1113228753Smm a->formats[i].options = options; 1114228753Smm a->formats[i].read_header = read_header; 1115228753Smm a->formats[i].read_data = read_data; 1116228753Smm a->formats[i].read_data_skip = read_data_skip; 1117248616Smm a->formats[i].seek_data = seek_data; 1118228753Smm a->formats[i].cleanup = cleanup; 1119228753Smm a->formats[i].data = format_data; 1120228753Smm a->formats[i].name = name; 1121228753Smm return (ARCHIVE_OK); 1122228753Smm } 1123228753Smm } 1124228753Smm 1125232153Smm archive_set_error(&a->archive, ENOMEM, 1126232153Smm "Not enough slots for format registration"); 1127232153Smm return (ARCHIVE_FATAL); 1128228753Smm} 1129228753Smm 1130228753Smm/* 1131228753Smm * Used internally by decompression routines to register their bid and 1132228753Smm * initialization functions. 1133228753Smm */ 1134232153Smmint 1135232153Smm__archive_read_get_bidder(struct archive_read *a, 1136232153Smm struct archive_read_filter_bidder **bidder) 1137228753Smm{ 1138228753Smm int i, number_slots; 1139228753Smm 1140228753Smm number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]); 1141228753Smm 1142228753Smm for (i = 0; i < number_slots; i++) { 1143228753Smm if (a->bidders[i].bid == NULL) { 1144228753Smm memset(a->bidders + i, 0, sizeof(a->bidders[0])); 1145232153Smm *bidder = (a->bidders + i); 1146232153Smm return (ARCHIVE_OK); 1147228753Smm } 1148228753Smm } 1149228753Smm 1150232153Smm archive_set_error(&a->archive, ENOMEM, 1151232153Smm "Not enough slots for filter registration"); 1152232153Smm return (ARCHIVE_FATAL); 1153228753Smm} 1154228753Smm 1155228753Smm/* 1156232153Smm * The next section implements the peek/consume internal I/O 1157232153Smm * system used by archive readers. This system allows simple 1158232153Smm * read-ahead for consumers while preserving zero-copy operation 1159232153Smm * most of the time. 1160228753Smm * 1161232153Smm * The two key operations: 1162232153Smm * * The read-ahead function returns a pointer to a block of data 1163232153Smm * that satisfies a minimum request. 1164232153Smm * * The consume function advances the file pointer. 1165232153Smm * 1166228753Smm * In the ideal case, filters generate blocks of data 1167228753Smm * and __archive_read_ahead() just returns pointers directly into 1168228753Smm * those blocks. Then __archive_read_consume() just bumps those 1169228753Smm * pointers. Only if your request would span blocks does the I/O 1170228753Smm * layer use a copy buffer to provide you with a contiguous block of 1171232153Smm * data. 1172228753Smm * 1173228753Smm * A couple of useful idioms: 1174228753Smm * * "I just want some data." Ask for 1 byte and pay attention to 1175228753Smm * the "number of bytes available" from __archive_read_ahead(). 1176232153Smm * Consume whatever you actually use. 1177228753Smm * * "I want to output a large block of data." As above, ask for 1 byte, 1178232153Smm * emit all that's available (up to whatever limit you have), consume 1179232153Smm * it all, then repeat until you're done. This effectively means that 1180232153Smm * you're passing along the blocks that came from your provider. 1181228753Smm * * "I want to peek ahead by a large amount." Ask for 4k or so, then 1182228753Smm * double and repeat until you get an error or have enough. Note 1183228753Smm * that the I/O layer will likely end up expanding its copy buffer 1184228753Smm * to fit your request, so use this technique cautiously. This 1185228753Smm * technique is used, for example, by some of the format tasting 1186228753Smm * code that has uncertain look-ahead needs. 1187228753Smm */ 1188228753Smm 1189228753Smm/* 1190228753Smm * Looks ahead in the input stream: 1191228753Smm * * If 'avail' pointer is provided, that returns number of bytes available 1192228753Smm * in the current buffer, which may be much larger than requested. 1193228753Smm * * If end-of-file, *avail gets set to zero. 1194228753Smm * * If error, *avail gets error code. 1195232153Smm * * If request can be met, returns pointer to data. 1196232153Smm * * If minimum request cannot be met, returns NULL. 1197228753Smm * 1198228753Smm * Note: If you just want "some data", ask for 1 byte and pay attention 1199228753Smm * to *avail, which will have the actual amount available. If you 1200228753Smm * know exactly how many bytes you need, just ask for that and treat 1201228753Smm * a NULL return as an error. 1202228753Smm * 1203228753Smm * Important: This does NOT move the file pointer. See 1204228753Smm * __archive_read_consume() below. 1205228753Smm */ 1206228753Smmconst void * 1207228753Smm__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) 1208228753Smm{ 1209228753Smm return (__archive_read_filter_ahead(a->filter, min, avail)); 1210228753Smm} 1211228753Smm 1212228753Smmconst void * 1213228753Smm__archive_read_filter_ahead(struct archive_read_filter *filter, 1214228753Smm size_t min, ssize_t *avail) 1215228753Smm{ 1216228753Smm ssize_t bytes_read; 1217228753Smm size_t tocopy; 1218228753Smm 1219228753Smm if (filter->fatal) { 1220228753Smm if (avail) 1221228753Smm *avail = ARCHIVE_FATAL; 1222228753Smm return (NULL); 1223228753Smm } 1224228753Smm 1225228753Smm /* 1226228753Smm * Keep pulling more data until we can satisfy the request. 1227228753Smm */ 1228228753Smm for (;;) { 1229228753Smm 1230228753Smm /* 1231228753Smm * If we can satisfy from the copy buffer (and the 1232228753Smm * copy buffer isn't empty), we're done. In particular, 1233228753Smm * note that min == 0 is a perfectly well-defined 1234228753Smm * request. 1235228753Smm */ 1236228753Smm if (filter->avail >= min && filter->avail > 0) { 1237228753Smm if (avail != NULL) 1238228753Smm *avail = filter->avail; 1239228753Smm return (filter->next); 1240228753Smm } 1241228753Smm 1242228753Smm /* 1243228753Smm * We can satisfy directly from client buffer if everything 1244228753Smm * currently in the copy buffer is still in the client buffer. 1245228753Smm */ 1246228753Smm if (filter->client_total >= filter->client_avail + filter->avail 1247228753Smm && filter->client_avail + filter->avail >= min) { 1248228753Smm /* "Roll back" to client buffer. */ 1249228753Smm filter->client_avail += filter->avail; 1250228753Smm filter->client_next -= filter->avail; 1251228753Smm /* Copy buffer is now empty. */ 1252228753Smm filter->avail = 0; 1253228753Smm filter->next = filter->buffer; 1254228753Smm /* Return data from client buffer. */ 1255228753Smm if (avail != NULL) 1256228753Smm *avail = filter->client_avail; 1257228753Smm return (filter->client_next); 1258228753Smm } 1259228753Smm 1260228753Smm /* Move data forward in copy buffer if necessary. */ 1261228753Smm if (filter->next > filter->buffer && 1262228753Smm filter->next + min > filter->buffer + filter->buffer_size) { 1263228753Smm if (filter->avail > 0) 1264248616Smm memmove(filter->buffer, filter->next, 1265248616Smm filter->avail); 1266228753Smm filter->next = filter->buffer; 1267228753Smm } 1268228753Smm 1269228753Smm /* If we've used up the client data, get more. */ 1270228753Smm if (filter->client_avail <= 0) { 1271228753Smm if (filter->end_of_file) { 1272228753Smm if (avail != NULL) 1273228753Smm *avail = 0; 1274228753Smm return (NULL); 1275228753Smm } 1276228753Smm bytes_read = (filter->read)(filter, 1277228753Smm &filter->client_buff); 1278228753Smm if (bytes_read < 0) { /* Read error. */ 1279228753Smm filter->client_total = filter->client_avail = 0; 1280248616Smm filter->client_next = 1281248616Smm filter->client_buff = NULL; 1282228753Smm filter->fatal = 1; 1283228753Smm if (avail != NULL) 1284228753Smm *avail = ARCHIVE_FATAL; 1285228753Smm return (NULL); 1286228753Smm } 1287248616Smm if (bytes_read == 0) { 1288248616Smm /* Check for another client object first */ 1289248616Smm if (filter->archive->client.cursor != 1290248616Smm filter->archive->client.nodes - 1) { 1291248616Smm if (client_switch_proxy(filter, 1292248616Smm filter->archive->client.cursor + 1) 1293248616Smm == ARCHIVE_OK) 1294248616Smm continue; 1295248616Smm } 1296248616Smm /* Premature end-of-file. */ 1297228753Smm filter->client_total = filter->client_avail = 0; 1298248616Smm filter->client_next = 1299248616Smm filter->client_buff = NULL; 1300228753Smm filter->end_of_file = 1; 1301228753Smm /* Return whatever we do have. */ 1302228753Smm if (avail != NULL) 1303228753Smm *avail = filter->avail; 1304228753Smm return (NULL); 1305228753Smm } 1306228753Smm filter->client_total = bytes_read; 1307228753Smm filter->client_avail = filter->client_total; 1308228753Smm filter->client_next = filter->client_buff; 1309248616Smm } else { 1310228753Smm /* 1311228753Smm * We can't satisfy the request from the copy 1312228753Smm * buffer or the existing client data, so we 1313228753Smm * need to copy more client data over to the 1314228753Smm * copy buffer. 1315228753Smm */ 1316228753Smm 1317228753Smm /* Ensure the buffer is big enough. */ 1318228753Smm if (min > filter->buffer_size) { 1319228753Smm size_t s, t; 1320228753Smm char *p; 1321228753Smm 1322228753Smm /* Double the buffer; watch for overflow. */ 1323228753Smm s = t = filter->buffer_size; 1324228753Smm if (s == 0) 1325228753Smm s = min; 1326228753Smm while (s < min) { 1327228753Smm t *= 2; 1328228753Smm if (t <= s) { /* Integer overflow! */ 1329228753Smm archive_set_error( 1330248616Smm &filter->archive->archive, 1331248616Smm ENOMEM, 1332248616Smm "Unable to allocate copy" 1333248616Smm " buffer"); 1334228753Smm filter->fatal = 1; 1335228753Smm if (avail != NULL) 1336228753Smm *avail = ARCHIVE_FATAL; 1337228753Smm return (NULL); 1338228753Smm } 1339228753Smm s = t; 1340228753Smm } 1341228753Smm /* Now s >= min, so allocate a new buffer. */ 1342228753Smm p = (char *)malloc(s); 1343228753Smm if (p == NULL) { 1344228753Smm archive_set_error( 1345228753Smm &filter->archive->archive, 1346228753Smm ENOMEM, 1347228753Smm "Unable to allocate copy buffer"); 1348228753Smm filter->fatal = 1; 1349228753Smm if (avail != NULL) 1350228753Smm *avail = ARCHIVE_FATAL; 1351228753Smm return (NULL); 1352228753Smm } 1353228753Smm /* Move data into newly-enlarged buffer. */ 1354228753Smm if (filter->avail > 0) 1355228753Smm memmove(p, filter->next, filter->avail); 1356228753Smm free(filter->buffer); 1357228753Smm filter->next = filter->buffer = p; 1358228753Smm filter->buffer_size = s; 1359228753Smm } 1360228753Smm 1361228753Smm /* We can add client data to copy buffer. */ 1362228753Smm /* First estimate: copy to fill rest of buffer. */ 1363228753Smm tocopy = (filter->buffer + filter->buffer_size) 1364228753Smm - (filter->next + filter->avail); 1365228753Smm /* Don't waste time buffering more than we need to. */ 1366228753Smm if (tocopy + filter->avail > min) 1367228753Smm tocopy = min - filter->avail; 1368228753Smm /* Don't copy more than is available. */ 1369228753Smm if (tocopy > filter->client_avail) 1370228753Smm tocopy = filter->client_avail; 1371228753Smm 1372248616Smm memcpy(filter->next + filter->avail, 1373248616Smm filter->client_next, tocopy); 1374228753Smm /* Remove this data from client buffer. */ 1375228753Smm filter->client_next += tocopy; 1376228753Smm filter->client_avail -= tocopy; 1377228753Smm /* add it to copy buffer. */ 1378228753Smm filter->avail += tocopy; 1379228753Smm } 1380228753Smm } 1381228753Smm} 1382228753Smm 1383228753Smm/* 1384232153Smm * Move the file pointer forward. 1385228753Smm */ 1386232153Smmint64_t 1387232153Smm__archive_read_consume(struct archive_read *a, int64_t request) 1388228753Smm{ 1389232153Smm return (__archive_read_filter_consume(a->filter, request)); 1390228753Smm} 1391228753Smm 1392232153Smmint64_t 1393228753Smm__archive_read_filter_consume(struct archive_read_filter * filter, 1394232153Smm int64_t request) 1395228753Smm{ 1396232153Smm int64_t skipped; 1397228753Smm 1398282932Sdelphij if (request < 0) 1399282932Sdelphij return ARCHIVE_FATAL; 1400232153Smm if (request == 0) 1401232153Smm return 0; 1402232153Smm 1403232153Smm skipped = advance_file_pointer(filter, request); 1404228753Smm if (skipped == request) 1405228753Smm return (skipped); 1406228753Smm /* We hit EOF before we satisfied the skip request. */ 1407232153Smm if (skipped < 0) /* Map error code to 0 for error message below. */ 1408228753Smm skipped = 0; 1409232153Smm archive_set_error(&filter->archive->archive, 1410228753Smm ARCHIVE_ERRNO_MISC, 1411228753Smm "Truncated input file (needed %jd bytes, only %jd available)", 1412228753Smm (intmax_t)request, (intmax_t)skipped); 1413228753Smm return (ARCHIVE_FATAL); 1414228753Smm} 1415228753Smm 1416232153Smm/* 1417232153Smm * Advance the file pointer by the amount requested. 1418232153Smm * Returns the amount actually advanced, which may be less than the 1419232153Smm * request if EOF is encountered first. 1420232153Smm * Returns a negative value if there's an I/O error. 1421232153Smm */ 1422232153Smmstatic int64_t 1423232153Smmadvance_file_pointer(struct archive_read_filter *filter, int64_t request) 1424228753Smm{ 1425228753Smm int64_t bytes_skipped, total_bytes_skipped = 0; 1426232153Smm ssize_t bytes_read; 1427228753Smm size_t min; 1428228753Smm 1429228753Smm if (filter->fatal) 1430228753Smm return (-1); 1431232153Smm 1432232153Smm /* Use up the copy buffer first. */ 1433228753Smm if (filter->avail > 0) { 1434238856Smm min = (size_t)minimum(request, (int64_t)filter->avail); 1435232153Smm filter->next += min; 1436232153Smm filter->avail -= min; 1437232153Smm request -= min; 1438232153Smm filter->position += min; 1439232153Smm total_bytes_skipped += min; 1440228753Smm } 1441232153Smm 1442232153Smm /* Then use up the client buffer. */ 1443228753Smm if (filter->client_avail > 0) { 1444238856Smm min = (size_t)minimum(request, (int64_t)filter->client_avail); 1445232153Smm filter->client_next += min; 1446232153Smm filter->client_avail -= min; 1447232153Smm request -= min; 1448232153Smm filter->position += min; 1449232153Smm total_bytes_skipped += min; 1450228753Smm } 1451228753Smm if (request == 0) 1452228753Smm return (total_bytes_skipped); 1453232153Smm 1454232153Smm /* If there's an optimized skip function, use it. */ 1455228753Smm if (filter->skip != NULL) { 1456228753Smm bytes_skipped = (filter->skip)(filter, request); 1457228753Smm if (bytes_skipped < 0) { /* error */ 1458228753Smm filter->fatal = 1; 1459228753Smm return (bytes_skipped); 1460228753Smm } 1461232153Smm filter->position += bytes_skipped; 1462228753Smm total_bytes_skipped += bytes_skipped; 1463228753Smm request -= bytes_skipped; 1464232153Smm if (request == 0) 1465232153Smm return (total_bytes_skipped); 1466228753Smm } 1467232153Smm 1468232153Smm /* Use ordinary reads as necessary to complete the request. */ 1469232153Smm for (;;) { 1470232153Smm bytes_read = (filter->read)(filter, &filter->client_buff); 1471232153Smm if (bytes_read < 0) { 1472232153Smm filter->client_buff = NULL; 1473232153Smm filter->fatal = 1; 1474228753Smm return (bytes_read); 1475232153Smm } 1476232153Smm 1477228753Smm if (bytes_read == 0) { 1478248616Smm if (filter->archive->client.cursor != 1479248616Smm filter->archive->client.nodes - 1) { 1480248616Smm if (client_switch_proxy(filter, 1481248616Smm filter->archive->client.cursor + 1) 1482248616Smm == ARCHIVE_OK) 1483248616Smm continue; 1484248616Smm } 1485232153Smm filter->client_buff = NULL; 1486232153Smm filter->end_of_file = 1; 1487228753Smm return (total_bytes_skipped); 1488228753Smm } 1489232153Smm 1490232153Smm if (bytes_read >= request) { 1491232153Smm filter->client_next = 1492232153Smm ((const char *)filter->client_buff) + request; 1493238856Smm filter->client_avail = (size_t)(bytes_read - request); 1494232153Smm filter->client_total = bytes_read; 1495232153Smm total_bytes_skipped += request; 1496232153Smm filter->position += request; 1497232153Smm return (total_bytes_skipped); 1498232153Smm } 1499232153Smm 1500232153Smm filter->position += bytes_read; 1501228753Smm total_bytes_skipped += bytes_read; 1502228753Smm request -= bytes_read; 1503228753Smm } 1504228753Smm} 1505232153Smm 1506232153Smm/** 1507232153Smm * Returns ARCHIVE_FAILED if seeking isn't supported. 1508232153Smm */ 1509232153Smmint64_t 1510232153Smm__archive_read_seek(struct archive_read *a, int64_t offset, int whence) 1511232153Smm{ 1512232153Smm return __archive_read_filter_seek(a->filter, offset, whence); 1513232153Smm} 1514232153Smm 1515232153Smmint64_t 1516248616Smm__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, 1517248616Smm int whence) 1518232153Smm{ 1519248616Smm struct archive_read_client *client; 1520232153Smm int64_t r; 1521248616Smm unsigned int cursor; 1522232153Smm 1523232153Smm if (filter->closed || filter->fatal) 1524232153Smm return (ARCHIVE_FATAL); 1525232153Smm if (filter->seek == NULL) 1526232153Smm return (ARCHIVE_FAILED); 1527248616Smm 1528248616Smm client = &(filter->archive->client); 1529248616Smm switch (whence) { 1530248616Smm case SEEK_CUR: 1531248616Smm /* Adjust the offset and use SEEK_SET instead */ 1532248616Smm offset += filter->position; 1533248616Smm case SEEK_SET: 1534248616Smm cursor = 0; 1535248616Smm while (1) 1536248616Smm { 1537248616Smm if (client->dataset[cursor].begin_position < 0 || 1538248616Smm client->dataset[cursor].total_size < 0 || 1539248616Smm client->dataset[cursor].begin_position + 1540248616Smm client->dataset[cursor].total_size - 1 > offset || 1541248616Smm cursor + 1 >= client->nodes) 1542248616Smm break; 1543248616Smm r = client->dataset[cursor].begin_position + 1544248616Smm client->dataset[cursor].total_size; 1545248616Smm client->dataset[++cursor].begin_position = r; 1546248616Smm } 1547248616Smm while (1) { 1548248616Smm r = client_switch_proxy(filter, cursor); 1549248616Smm if (r != ARCHIVE_OK) 1550248616Smm return r; 1551248616Smm if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) 1552248616Smm return r; 1553248616Smm client->dataset[cursor].total_size = r; 1554248616Smm if (client->dataset[cursor].begin_position + 1555248616Smm client->dataset[cursor].total_size - 1 > offset || 1556248616Smm cursor + 1 >= client->nodes) 1557248616Smm break; 1558248616Smm r = client->dataset[cursor].begin_position + 1559248616Smm client->dataset[cursor].total_size; 1560248616Smm client->dataset[++cursor].begin_position = r; 1561248616Smm } 1562248616Smm offset -= client->dataset[cursor].begin_position; 1563248616Smm if (offset < 0) 1564248616Smm offset = 0; 1565248616Smm else if (offset > client->dataset[cursor].total_size - 1) 1566248616Smm offset = client->dataset[cursor].total_size - 1; 1567248616Smm if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0) 1568248616Smm return r; 1569248616Smm break; 1570248616Smm 1571248616Smm case SEEK_END: 1572248616Smm cursor = 0; 1573248616Smm while (1) { 1574248616Smm if (client->dataset[cursor].begin_position < 0 || 1575248616Smm client->dataset[cursor].total_size < 0 || 1576248616Smm cursor + 1 >= client->nodes) 1577248616Smm break; 1578248616Smm r = client->dataset[cursor].begin_position + 1579248616Smm client->dataset[cursor].total_size; 1580248616Smm client->dataset[++cursor].begin_position = r; 1581248616Smm } 1582248616Smm while (1) { 1583248616Smm r = client_switch_proxy(filter, cursor); 1584248616Smm if (r != ARCHIVE_OK) 1585248616Smm return r; 1586248616Smm if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) 1587248616Smm return r; 1588248616Smm client->dataset[cursor].total_size = r; 1589248616Smm r = client->dataset[cursor].begin_position + 1590248616Smm client->dataset[cursor].total_size; 1591248616Smm if (cursor + 1 >= client->nodes) 1592248616Smm break; 1593248616Smm client->dataset[++cursor].begin_position = r; 1594248616Smm } 1595248616Smm while (1) { 1596248616Smm if (r + offset >= 1597248616Smm client->dataset[cursor].begin_position) 1598248616Smm break; 1599248616Smm offset += client->dataset[cursor].total_size; 1600248616Smm if (cursor == 0) 1601248616Smm break; 1602248616Smm cursor--; 1603248616Smm r = client->dataset[cursor].begin_position + 1604248616Smm client->dataset[cursor].total_size; 1605248616Smm } 1606248616Smm offset = (r + offset) - client->dataset[cursor].begin_position; 1607248616Smm if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK) 1608248616Smm return r; 1609248616Smm r = client_seek_proxy(filter, offset, SEEK_SET); 1610248616Smm if (r < ARCHIVE_OK) 1611248616Smm return r; 1612248616Smm break; 1613248616Smm 1614248616Smm default: 1615248616Smm return (ARCHIVE_FATAL); 1616248616Smm } 1617248616Smm r += client->dataset[cursor].begin_position; 1618248616Smm 1619232153Smm if (r >= 0) { 1620232153Smm /* 1621232153Smm * Ouch. Clearing the buffer like this hurts, especially 1622232153Smm * at bid time. A lot of our efficiency at bid time comes 1623232153Smm * from having bidders reuse the data we've already read. 1624232153Smm * 1625232153Smm * TODO: If the seek request is in data we already 1626232153Smm * have, then don't call the seek callback. 1627232153Smm * 1628232153Smm * TODO: Zip seeks to end-of-file at bid time. If 1629232153Smm * other formats also start doing this, we may need to 1630232153Smm * find a way for clients to fudge the seek offset to 1631232153Smm * a block boundary. 1632232153Smm * 1633232153Smm * Hmmm... If whence was SEEK_END, we know the file 1634232153Smm * size is (r - offset). Can we use that to simplify 1635232153Smm * the TODO items above? 1636232153Smm */ 1637232153Smm filter->avail = filter->client_avail = 0; 1638232153Smm filter->next = filter->buffer; 1639232153Smm filter->position = r; 1640232153Smm filter->end_of_file = 0; 1641232153Smm } 1642232153Smm return r; 1643232153Smm} 1644