archive_read.c revision 349901
1310490Scy/*- 251292Sobrien * Copyright (c) 2003-2011 Tim Kientzle 3310490Scy * All rights reserved. 4310490Scy * 5310490Scy * Redistribution and use in source and binary forms, with or without 6310490Scy * modification, are permitted provided that the following conditions 7310490Scy * are met: 8310490Scy * 1. Redistributions of source code must retain the above copyright 9310490Scy * notice, this list of conditions and the following disclaimer. 10310490Scy * 2. Redistributions in binary form must reproduce the above copyright 11310490Scy * notice, this list of conditions and the following disclaimer in the 12310490Scy * documentation and/or other materials provided with the distribution. 13310490Scy * 14310490Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15310490Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16310490Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17310490Scy * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18310490Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19310490Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20310490Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21310490Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22310490Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23310490Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24310490Scy */ 25310490Scy 26310490Scy/* 27310490Scy * This file contains the "essential" portions of the read API, that 28310490Scy * is, stuff that will probably always be used by any client that 29310490Scy * actually needs to read an archive. Optional pieces have been, as 30310490Scy * far as possible, separated out into separate files to avoid 31310490Scy * needlessly bloating statically-linked clients. 32310490Scy */ 33310490Scy 34310490Scy#include "archive_platform.h" 35310490Scy__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_read.c 349901 2019-07-11 00:22:10Z mm $"); 36310490Scy 37310490Scy#ifdef HAVE_ERRNO_H 38310490Scy#include <errno.h> 39310490Scy#endif 40310490Scy#include <stdio.h> 41310490Scy#ifdef HAVE_STDLIB_H 42310490Scy#include <stdlib.h> 43174294Sobrien#endif 44174294Sobrien#ifdef HAVE_STRING_H 45174294Sobrien#include <string.h> 46174294Sobrien#endif 47174294Sobrien#ifdef HAVE_UNISTD_H 48174294Sobrien#include <unistd.h> 49174294Sobrien#endif 50174294Sobrien 51174294Sobrien#include "archive.h" 52174294Sobrien#include "archive_entry.h" 53174294Sobrien#include "archive_private.h" 54174294Sobrien#include "archive_read_private.h" 55174294Sobrien 56174294Sobrien#define minimum(a, b) (a < b ? a : b) 57174294Sobrien 58174294Sobrienstatic int choose_filters(struct archive_read *); 59174294Sobrienstatic int choose_format(struct archive_read *); 60174294Sobrienstatic int close_filters(struct archive_read *); 61174294Sobrienstatic struct archive_vtable *archive_read_vtable(void); 62174294Sobrienstatic int64_t _archive_filter_bytes(struct archive *, int); 63174294Sobrienstatic int _archive_filter_code(struct archive *, int); 64174294Sobrienstatic const char *_archive_filter_name(struct archive *, int); 65174294Sobrienstatic int _archive_filter_count(struct archive *); 66174294Sobrienstatic int _archive_read_close(struct archive *); 67174294Sobrienstatic int _archive_read_data_block(struct archive *, 68174294Sobrien const void **, size_t *, int64_t *); 69310490Scystatic int _archive_read_free(struct archive *); 70174294Sobrienstatic int _archive_read_next_header(struct archive *, 71174294Sobrien struct archive_entry **); 72174294Sobrienstatic int _archive_read_next_header2(struct archive *, 73310490Scy struct archive_entry *); 74174294Sobrienstatic int64_t advance_file_pointer(struct archive_read_filter *, int64_t); 75310490Scy 76174294Sobrienstatic struct archive_vtable * 77174294Sobrienarchive_read_vtable(void) 78174294Sobrien{ 79174294Sobrien static struct archive_vtable av; 80174294Sobrien static int inited = 0; 81174294Sobrien 82310490Scy if (!inited) { 83310490Scy av.archive_filter_bytes = _archive_filter_bytes; 84174294Sobrien av.archive_filter_code = _archive_filter_code; 85310490Scy av.archive_filter_name = _archive_filter_name; 86310490Scy av.archive_filter_count = _archive_filter_count; 87310490Scy av.archive_read_data_block = _archive_read_data_block; 88310490Scy av.archive_read_next_header = _archive_read_next_header; 89174294Sobrien av.archive_read_next_header2 = _archive_read_next_header2; 90310490Scy av.archive_free = _archive_read_free; 91174294Sobrien av.archive_close = _archive_read_close; 92174294Sobrien inited = 1; 93174294Sobrien } 94174294Sobrien return (&av); 95174294Sobrien} 96174294Sobrien 97174294Sobrien/* 98174294Sobrien * Allocate, initialize and return a struct archive object. 99174294Sobrien */ 100174294Sobrienstruct archive * 101174294Sobrienarchive_read_new(void) 102174294Sobrien{ 103174294Sobrien struct archive_read *a; 104174294Sobrien 105174294Sobrien a = (struct archive_read *)calloc(1, sizeof(*a)); 106174294Sobrien if (a == NULL) 107174294Sobrien return (NULL); 108174294Sobrien a->archive.magic = ARCHIVE_READ_MAGIC; 109174294Sobrien 110174294Sobrien a->archive.state = ARCHIVE_STATE_NEW; 111174294Sobrien a->entry = archive_entry_new2(&a->archive); 112174294Sobrien a->archive.vtable = archive_read_vtable(); 113174294Sobrien 114174294Sobrien a->passphrases.last = &a->passphrases.first; 115174294Sobrien 116174294Sobrien return (&a->archive); 117174294Sobrien} 118174294Sobrien 119174294Sobrien/* 120174294Sobrien * Record the do-not-extract-to file. This belongs in archive_read_extract.c. 121174294Sobrien */ 122174294Sobrienvoid 123174294Sobrienarchive_read_extract_set_skip_file(struct archive *_a, la_int64_t d, 124174294Sobrien la_int64_t i) 125174294Sobrien{ 126310490Scy struct archive_read *a = (struct archive_read *)_a; 127310490Scy 128310490Scy if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC, 129310490Scy ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file")) 130310490Scy return; 131310490Scy a->skip_file_set = 1; 132310490Scy a->skip_file_dev = d; 133310490Scy a->skip_file_ino = i; 134310490Scy} 135310490Scy 136310490Scy/* 137310490Scy * Open the archive 138310490Scy */ 139310490Scyint 140310490Scyarchive_read_open(struct archive *a, void *client_data, 141310490Scy archive_open_callback *client_opener, archive_read_callback *client_reader, 142310490Scy archive_close_callback *client_closer) 143310490Scy{ 144310490Scy /* Old archive_read_open() is just a thin shell around 145310490Scy * archive_read_open1. */ 146310490Scy archive_read_set_open_callback(a, client_opener); 147310490Scy archive_read_set_read_callback(a, client_reader); 148310490Scy archive_read_set_close_callback(a, client_closer); 149310490Scy archive_read_set_callback_data(a, client_data); 150310490Scy return archive_read_open1(a); 151310490Scy} 152310490Scy 153310490Scy 154310490Scyint 155310490Scyarchive_read_open2(struct archive *a, void *client_data, 156310490Scy archive_open_callback *client_opener, 157310490Scy archive_read_callback *client_reader, 158310490Scy archive_skip_callback *client_skipper, 159310490Scy archive_close_callback *client_closer) 160310490Scy{ 161310490Scy /* Old archive_read_open2() is just a thin shell around 162310490Scy * archive_read_open1. */ 163310490Scy archive_read_set_callback_data(a, client_data); 164310490Scy archive_read_set_open_callback(a, client_opener); 165310490Scy archive_read_set_read_callback(a, client_reader); 166310490Scy archive_read_set_skip_callback(a, client_skipper); 167310490Scy archive_read_set_close_callback(a, client_closer); 168310490Scy return archive_read_open1(a); 169310490Scy} 170310490Scy 171310490Scystatic ssize_t 172310490Scyclient_read_proxy(struct archive_read_filter *self, const void **buff) 173310490Scy{ 174310490Scy ssize_t r; 175310490Scy r = (self->archive->client.reader)(&self->archive->archive, 176310490Scy self->data, buff); 177310490Scy return (r); 178310490Scy} 179310490Scy 180310490Scystatic int64_t 181310490Scyclient_skip_proxy(struct archive_read_filter *self, int64_t request) 182310490Scy{ 183310490Scy if (request < 0) 184310490Scy __archive_errx(1, "Negative skip requested."); 185174294Sobrien if (request == 0) 186174294Sobrien return 0; 187310490Scy 188174294Sobrien if (self->archive->client.skipper != NULL) { 189174294Sobrien /* Seek requests over 1GiB are broken down into 190310490Scy * multiple seeks. This avoids overflows when the 191310490Scy * requests get passed through 32-bit arguments. */ 192310490Scy int64_t skip_limit = (int64_t)1 << 30; 193310490Scy int64_t total = 0; 194310490Scy for (;;) { 195310490Scy int64_t get, ask = request; 196310490Scy if (ask > skip_limit) 197310490Scy ask = skip_limit; 198310490Scy get = (self->archive->client.skipper) 199310490Scy (&self->archive->archive, self->data, ask); 200310490Scy total += get; 201310490Scy if (get == 0 || get == request) 202174294Sobrien return (total); 203174294Sobrien if (get > request) 204174294Sobrien return ARCHIVE_FATAL; 205174294Sobrien request -= get; 206174294Sobrien } 207174294Sobrien } else if (self->archive->client.seeker != NULL 208174294Sobrien && request > 64 * 1024) { 209174294Sobrien /* If the client provided a seeker but not a skipper, 210174294Sobrien * we can use the seeker to skip forward. 211174294Sobrien * 212174294Sobrien * Note: This isn't always a good idea. The client 213174294Sobrien * skipper is allowed to skip by less than requested 214174294Sobrien * if it needs to maintain block alignment. The 215174294Sobrien * seeker is not allowed to play such games, so using 216174294Sobrien * the seeker here may be a performance loss compared 217174294Sobrien * to just reading and discarding. That's why we 218174294Sobrien * only do this for skips of over 64k. 219174294Sobrien */ 220174294Sobrien int64_t before = self->position; 221174294Sobrien int64_t after = (self->archive->client.seeker) 222174294Sobrien (&self->archive->archive, self->data, request, SEEK_CUR); 223174294Sobrien if (after != before + request) 224174294Sobrien return ARCHIVE_FATAL; 225174294Sobrien return after - before; 226174294Sobrien } 227174294Sobrien return 0; 228174294Sobrien} 229174294Sobrien 230174294Sobrienstatic int64_t 231174294Sobrienclient_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence) 232174294Sobrien{ 233174294Sobrien /* DO NOT use the skipper here! If we transparently handled 234174294Sobrien * forward seek here by using the skipper, that will break 235174294Sobrien * other libarchive code that assumes a successful forward 236174294Sobrien * seek means it can also seek backwards. 237174294Sobrien */ 238174294Sobrien if (self->archive->client.seeker == NULL) { 239174294Sobrien archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 240174294Sobrien "Current client reader does not support seeking a device"); 241174294Sobrien return (ARCHIVE_FAILED); 242174294Sobrien } 243174294Sobrien return (self->archive->client.seeker)(&self->archive->archive, 244174294Sobrien self->data, offset, whence); 245174294Sobrien} 246174294Sobrien 247174294Sobrienstatic int 248174294Sobrienclient_close_proxy(struct archive_read_filter *self) 249174294Sobrien{ 250174294Sobrien int r = ARCHIVE_OK, r2; 251174294Sobrien unsigned int i; 252174294Sobrien 253174294Sobrien if (self->archive->client.closer == NULL) 254174294Sobrien return (r); 255174294Sobrien for (i = 0; i < self->archive->client.nodes; i++) 256174294Sobrien { 257174294Sobrien r2 = (self->archive->client.closer) 258174294Sobrien ((struct archive *)self->archive, 259174294Sobrien self->archive->client.dataset[i].data); 260174294Sobrien if (r > r2) 261174294Sobrien r = r2; 262174294Sobrien } 263174294Sobrien return (r); 264174294Sobrien} 265174294Sobrien 266174294Sobrienstatic int 267174294Sobrienclient_open_proxy(struct archive_read_filter *self) 268174294Sobrien{ 269174294Sobrien int r = ARCHIVE_OK; 270174294Sobrien if (self->archive->client.opener != NULL) 271174294Sobrien r = (self->archive->client.opener)( 272174294Sobrien (struct archive *)self->archive, self->data); 273174294Sobrien return (r); 274174294Sobrien} 275174294Sobrien 276174294Sobrienstatic int 277174294Sobrienclient_switch_proxy(struct archive_read_filter *self, unsigned int iindex) 278174294Sobrien{ 279174294Sobrien int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; 280174294Sobrien void *data2 = NULL; 281174294Sobrien 282174294Sobrien /* Don't do anything if already in the specified data node */ 283174294Sobrien if (self->archive->client.cursor == iindex) 284174294Sobrien return (ARCHIVE_OK); 285174294Sobrien 286174294Sobrien self->archive->client.cursor = iindex; 287174294Sobrien data2 = self->archive->client.dataset[self->archive->client.cursor].data; 288174294Sobrien if (self->archive->client.switcher != NULL) 289174294Sobrien { 290174294Sobrien r1 = r2 = (self->archive->client.switcher) 291174294Sobrien ((struct archive *)self->archive, self->data, data2); 292174294Sobrien self->data = data2; 293174294Sobrien } 294174294Sobrien else 295174294Sobrien { 296174294Sobrien /* Attempt to call close and open instead */ 297174294Sobrien if (self->archive->client.closer != NULL) 298174294Sobrien r1 = (self->archive->client.closer) 299174294Sobrien ((struct archive *)self->archive, self->data); 300174294Sobrien self->data = data2; 301174294Sobrien if (self->archive->client.opener != NULL) 302174294Sobrien r2 = (self->archive->client.opener) 303174294Sobrien ((struct archive *)self->archive, self->data); 304174294Sobrien } 305174294Sobrien return (r1 < r2) ? r1 : r2; 306174294Sobrien} 307174294Sobrien 308174294Sobrienint 309174294Sobrienarchive_read_set_open_callback(struct archive *_a, 310174294Sobrien archive_open_callback *client_opener) 311174294Sobrien{ 312174294Sobrien struct archive_read *a = (struct archive_read *)_a; 313174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 314174294Sobrien "archive_read_set_open_callback"); 315174294Sobrien a->client.opener = client_opener; 316174294Sobrien return ARCHIVE_OK; 317174294Sobrien} 318174294Sobrien 319174294Sobrienint 320174294Sobrienarchive_read_set_read_callback(struct archive *_a, 321174294Sobrien archive_read_callback *client_reader) 322174294Sobrien{ 323174294Sobrien struct archive_read *a = (struct archive_read *)_a; 324174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 325174294Sobrien "archive_read_set_read_callback"); 326174294Sobrien a->client.reader = client_reader; 327174294Sobrien return ARCHIVE_OK; 328174294Sobrien} 329174294Sobrien 330174294Sobrienint 331174294Sobrienarchive_read_set_skip_callback(struct archive *_a, 332174294Sobrien archive_skip_callback *client_skipper) 333174294Sobrien{ 334174294Sobrien struct archive_read *a = (struct archive_read *)_a; 335174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 336174294Sobrien "archive_read_set_skip_callback"); 337174294Sobrien a->client.skipper = client_skipper; 338174294Sobrien return ARCHIVE_OK; 339174294Sobrien} 340174294Sobrien 341174294Sobrienint 342174294Sobrienarchive_read_set_seek_callback(struct archive *_a, 343174294Sobrien archive_seek_callback *client_seeker) 344131702Smbr{ 345174294Sobrien struct archive_read *a = (struct archive_read *)_a; 346174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 347174294Sobrien "archive_read_set_seek_callback"); 348131702Smbr a->client.seeker = client_seeker; 349174294Sobrien return ARCHIVE_OK; 350174294Sobrien} 351174294Sobrien 352174294Sobrienint 353174294Sobrienarchive_read_set_close_callback(struct archive *_a, 354174294Sobrien archive_close_callback *client_closer) 355174294Sobrien{ 356174294Sobrien struct archive_read *a = (struct archive_read *)_a; 357174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 358174294Sobrien "archive_read_set_close_callback"); 359174294Sobrien a->client.closer = client_closer; 360174294Sobrien return ARCHIVE_OK; 361174294Sobrien} 362174294Sobrien 363174294Sobrienint 364174294Sobrienarchive_read_set_switch_callback(struct archive *_a, 365174294Sobrien archive_switch_callback *client_switcher) 366119679Smbr{ 367174294Sobrien struct archive_read *a = (struct archive_read *)_a; 368174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 369174294Sobrien "archive_read_set_switch_callback"); 370174294Sobrien a->client.switcher = client_switcher; 371174294Sobrien return ARCHIVE_OK; 372174294Sobrien} 373174294Sobrien 374174294Sobrienint 375131702Smbrarchive_read_set_callback_data(struct archive *_a, void *client_data) 376131702Smbr{ 377131702Smbr return archive_read_set_callback_data2(_a, client_data, 0); 378174294Sobrien} 379174294Sobrien 380174294Sobrienint 381119679Smbrarchive_read_set_callback_data2(struct archive *_a, void *client_data, 382174294Sobrien unsigned int iindex) 383174294Sobrien{ 384174294Sobrien struct archive_read *a = (struct archive_read *)_a; 385174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 386119679Smbr "archive_read_set_callback_data2"); 387174294Sobrien 388174294Sobrien if (a->client.nodes == 0) 389174294Sobrien { 390174294Sobrien a->client.dataset = (struct archive_read_data_node *) 391174294Sobrien calloc(1, sizeof(*a->client.dataset)); 392174294Sobrien if (a->client.dataset == NULL) 393174294Sobrien { 394174294Sobrien archive_set_error(&a->archive, ENOMEM, 395174294Sobrien "No memory."); 396174294Sobrien return ARCHIVE_FATAL; 397174294Sobrien } 398174294Sobrien a->client.nodes = 1; 399174294Sobrien } 400174294Sobrien 401174294Sobrien if (iindex > a->client.nodes - 1) 402174294Sobrien { 403174294Sobrien archive_set_error(&a->archive, EINVAL, 404174294Sobrien "Invalid index specified."); 405174294Sobrien return ARCHIVE_FATAL; 406174294Sobrien } 407174294Sobrien a->client.dataset[iindex].data = client_data; 408174294Sobrien a->client.dataset[iindex].begin_position = -1; 409310490Scy a->client.dataset[iindex].total_size = -1; 410174294Sobrien return ARCHIVE_OK; 411174294Sobrien} 412174294Sobrien 413174294Sobrienint 414174294Sobrienarchive_read_add_callback_data(struct archive *_a, void *client_data, 415174294Sobrien unsigned int iindex) 416174294Sobrien{ 417174294Sobrien struct archive_read *a = (struct archive_read *)_a; 418174294Sobrien void *p; 419174294Sobrien unsigned int i; 420174294Sobrien 421174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 422174294Sobrien "archive_read_add_callback_data"); 423174294Sobrien if (iindex > a->client.nodes) { 424174294Sobrien archive_set_error(&a->archive, EINVAL, 425174294Sobrien "Invalid index specified."); 426174294Sobrien return ARCHIVE_FATAL; 427174294Sobrien } 428174294Sobrien p = realloc(a->client.dataset, sizeof(*a->client.dataset) 429174294Sobrien * (++(a->client.nodes))); 430174294Sobrien if (p == NULL) { 431174294Sobrien archive_set_error(&a->archive, ENOMEM, 432174294Sobrien "No memory."); 433174294Sobrien return ARCHIVE_FATAL; 434174294Sobrien } 435174294Sobrien a->client.dataset = (struct archive_read_data_node *)p; 436174294Sobrien for (i = a->client.nodes - 1; i > iindex && i > 0; i--) { 437174294Sobrien a->client.dataset[i].data = a->client.dataset[i-1].data; 438174294Sobrien a->client.dataset[i].begin_position = -1; 439174294Sobrien a->client.dataset[i].total_size = -1; 440174294Sobrien } 441174294Sobrien a->client.dataset[iindex].data = client_data; 442174294Sobrien a->client.dataset[iindex].begin_position = -1; 443174294Sobrien a->client.dataset[iindex].total_size = -1; 444174294Sobrien return ARCHIVE_OK; 445174294Sobrien} 446174294Sobrien 447174294Sobrienint 448174294Sobrienarchive_read_append_callback_data(struct archive *_a, void *client_data) 449174294Sobrien{ 450174294Sobrien struct archive_read *a = (struct archive_read *)_a; 451174294Sobrien return archive_read_add_callback_data(_a, client_data, a->client.nodes); 452174294Sobrien} 453174294Sobrien 454174294Sobrienint 455174294Sobrienarchive_read_prepend_callback_data(struct archive *_a, void *client_data) 456174294Sobrien{ 457174294Sobrien return archive_read_add_callback_data(_a, client_data, 0); 458174294Sobrien} 459174294Sobrien 460174294Sobrienint 461174294Sobrienarchive_read_open1(struct archive *_a) 462174294Sobrien{ 463174294Sobrien struct archive_read *a = (struct archive_read *)_a; 464174294Sobrien struct archive_read_filter *filter, *tmp; 465174294Sobrien int slot, e = ARCHIVE_OK; 466174294Sobrien unsigned int i; 467174294Sobrien 468174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 469174294Sobrien "archive_read_open"); 470174294Sobrien archive_clear_error(&a->archive); 471174294Sobrien 472174294Sobrien if (a->client.reader == NULL) { 473174294Sobrien archive_set_error(&a->archive, EINVAL, 474174294Sobrien "No reader function provided to archive_read_open"); 475174294Sobrien a->archive.state = ARCHIVE_STATE_FATAL; 476174294Sobrien return (ARCHIVE_FATAL); 477174294Sobrien } 478174294Sobrien 479174294Sobrien /* Open data source. */ 480174294Sobrien if (a->client.opener != NULL) { 481174294Sobrien e = (a->client.opener)(&a->archive, a->client.dataset[0].data); 482174294Sobrien if (e != 0) { 483174294Sobrien /* If the open failed, call the closer to clean up. */ 484174294Sobrien if (a->client.closer) { 485174294Sobrien for (i = 0; i < a->client.nodes; i++) 486174294Sobrien (a->client.closer)(&a->archive, 487174294Sobrien a->client.dataset[i].data); 488174294Sobrien } 489174294Sobrien return (e); 490174294Sobrien } 491174294Sobrien } 492174294Sobrien 493174294Sobrien filter = calloc(1, sizeof(*filter)); 494174294Sobrien if (filter == NULL) 495174294Sobrien return (ARCHIVE_FATAL); 496174294Sobrien filter->bidder = NULL; 497174294Sobrien filter->upstream = NULL; 498174294Sobrien filter->archive = a; 499174294Sobrien filter->data = a->client.dataset[0].data; 500174294Sobrien filter->open = client_open_proxy; 501174294Sobrien filter->read = client_read_proxy; 502174294Sobrien filter->skip = client_skip_proxy; 503174294Sobrien filter->seek = client_seek_proxy; 504174294Sobrien filter->close = client_close_proxy; 505174294Sobrien filter->sswitch = client_switch_proxy; 506174294Sobrien filter->name = "none"; 507174294Sobrien filter->code = ARCHIVE_FILTER_NONE; 508174294Sobrien 509174294Sobrien a->client.dataset[0].begin_position = 0; 510174294Sobrien if (!a->filter || !a->bypass_filter_bidding) 511174294Sobrien { 512174294Sobrien a->filter = filter; 513174294Sobrien /* Build out the input pipeline. */ 514174294Sobrien e = choose_filters(a); 515174294Sobrien if (e < ARCHIVE_WARN) { 516174294Sobrien a->archive.state = ARCHIVE_STATE_FATAL; 517174294Sobrien return (ARCHIVE_FATAL); 518174294Sobrien } 519174294Sobrien } 520174294Sobrien else 521174294Sobrien { 522174294Sobrien /* Need to add "NONE" type filter at the end of the filter chain */ 523174294Sobrien tmp = a->filter; 524174294Sobrien while (tmp->upstream) 525174294Sobrien tmp = tmp->upstream; 526174294Sobrien tmp->upstream = filter; 527174294Sobrien } 528174294Sobrien 529174294Sobrien if (!a->format) 530174294Sobrien { 531174294Sobrien slot = choose_format(a); 532174294Sobrien if (slot < 0) { 533174294Sobrien close_filters(a); 534174294Sobrien a->archive.state = ARCHIVE_STATE_FATAL; 535174294Sobrien return (ARCHIVE_FATAL); 536174294Sobrien } 537174294Sobrien a->format = &(a->formats[slot]); 538174294Sobrien } 539174294Sobrien 540174294Sobrien a->archive.state = ARCHIVE_STATE_HEADER; 541174294Sobrien 542174294Sobrien /* Ensure libarchive starts from the first node in a multivolume set */ 543174294Sobrien client_switch_proxy(a->filter, 0); 544174294Sobrien return (e); 545174294Sobrien} 546174294Sobrien 547174294Sobrien/* 548174294Sobrien * Allow each registered stream transform to bid on whether 549174294Sobrien * it wants to handle this stream. Repeat until we've finished 550174294Sobrien * building the pipeline. 551174294Sobrien */ 552174294Sobrien 553174294Sobrien/* We won't build a filter pipeline with more stages than this. */ 554174294Sobrien#define MAX_NUMBER_FILTERS 25 555174294Sobrien 556174294Sobrienstatic int 557174294Sobrienchoose_filters(struct archive_read *a) 558174294Sobrien{ 559174294Sobrien int number_bidders, i, bid, best_bid, number_filters; 560174294Sobrien struct archive_read_filter_bidder *bidder, *best_bidder; 561174294Sobrien struct archive_read_filter *filter; 562174294Sobrien ssize_t avail; 563174294Sobrien int r; 564174294Sobrien 565174294Sobrien for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) { 566174294Sobrien number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 567174294Sobrien 568174294Sobrien best_bid = 0; 569174294Sobrien best_bidder = NULL; 570174294Sobrien 571174294Sobrien bidder = a->bidders; 572174294Sobrien for (i = 0; i < number_bidders; i++, bidder++) { 573174294Sobrien if (bidder->bid != NULL) { 574174294Sobrien bid = (bidder->bid)(bidder, a->filter); 575174294Sobrien if (bid > best_bid) { 576174294Sobrien best_bid = bid; 577174294Sobrien best_bidder = bidder; 578174294Sobrien } 579174294Sobrien } 580174294Sobrien } 581174294Sobrien 582174294Sobrien /* If no bidder, we're done. */ 583174294Sobrien if (best_bidder == NULL) { 584174294Sobrien /* Verify the filter by asking it for some data. */ 585174294Sobrien __archive_read_filter_ahead(a->filter, 1, &avail); 586174294Sobrien if (avail < 0) { 587174294Sobrien __archive_read_free_filters(a); 588174294Sobrien return (ARCHIVE_FATAL); 589174294Sobrien } 590174294Sobrien a->archive.compression_name = a->filter->name; 591174294Sobrien a->archive.compression_code = a->filter->code; 592174294Sobrien return (ARCHIVE_OK); 593174294Sobrien } 594174294Sobrien 595174294Sobrien filter 596174294Sobrien = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 597174294Sobrien if (filter == NULL) 598119679Smbr return (ARCHIVE_FATAL); 599174294Sobrien filter->bidder = best_bidder; 600174294Sobrien filter->archive = a; 601119679Smbr filter->upstream = a->filter; 602119679Smbr a->filter = filter; 603174294Sobrien r = (best_bidder->init)(a->filter); 604174294Sobrien if (r != ARCHIVE_OK) { 605174294Sobrien __archive_read_free_filters(a); 606174294Sobrien return (ARCHIVE_FATAL); 607174294Sobrien } 608174294Sobrien } 609119679Smbr archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 610119679Smbr "Input requires too many filters for decoding"); 611174294Sobrien return (ARCHIVE_FATAL); 612174294Sobrien} 613174294Sobrien 614174294Sobrienint 615174294Sobrien__archive_read_header(struct archive_read *a, struct archive_entry *entry) 616174294Sobrien{ 617174294Sobrien if (a->filter->read_header) 618119679Smbr return a->filter->read_header(a->filter, entry); 619119679Smbr else 620119679Smbr return (ARCHIVE_OK); 621119679Smbr} 622174294Sobrien 623119679Smbr/* 624174294Sobrien * Read header of next entry. 625119679Smbr */ 626174294Sobrienstatic int 627174294Sobrien_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) 628174294Sobrien{ 629174294Sobrien struct archive_read *a = (struct archive_read *)_a; 630174294Sobrien int r1 = ARCHIVE_OK, r2; 631174294Sobrien 632174294Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, 633119679Smbr ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 634119679Smbr "archive_read_next_header"); 635174294Sobrien 636119679Smbr archive_entry_clear(entry); 637119679Smbr archive_clear_error(&a->archive); 638119679Smbr 639174294Sobrien /* 640174294Sobrien * If client didn't consume entire data, skip any remainder 641174294Sobrien * (This is especially important for GNU incremental directories.) 642119679Smbr */ 643174294Sobrien if (a->archive.state == ARCHIVE_STATE_DATA) { 644119679Smbr r1 = archive_read_data_skip(&a->archive); 645174294Sobrien if (r1 == ARCHIVE_EOF) 646119679Smbr archive_set_error(&a->archive, EIO, 647174294Sobrien "Premature end-of-file."); 648174294Sobrien if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) { 649174294Sobrien a->archive.state = ARCHIVE_STATE_FATAL; 650174294Sobrien return (ARCHIVE_FATAL); 651174294Sobrien } 652174294Sobrien } 653174294Sobrien 654119679Smbr /* Record start-of-header offset in uncompressed stream. */ 655174294Sobrien a->header_position = a->filter->position; 656119679Smbr 657174294Sobrien ++_a->file_count; 658174294Sobrien r2 = (a->format->read_header)(a, entry); 659174294Sobrien 660174294Sobrien /* 661174294Sobrien * EOF and FATAL are persistent at this layer. By 662174294Sobrien * modifying the state, we guarantee that future calls to 663174294Sobrien * read a header or read data will fail. 664174294Sobrien */ 665174294Sobrien switch (r2) { 666174294Sobrien case ARCHIVE_EOF: 667174294Sobrien a->archive.state = ARCHIVE_STATE_EOF; 668174294Sobrien --_a->file_count;/* Revert a file counter. */ 669174294Sobrien break; 670119679Smbr case ARCHIVE_OK: 671119679Smbr a->archive.state = ARCHIVE_STATE_DATA; 672174294Sobrien break; 673119679Smbr case ARCHIVE_WARN: 674119679Smbr a->archive.state = ARCHIVE_STATE_DATA; 675119679Smbr break; 676119679Smbr case ARCHIVE_RETRY: 677119679Smbr break; 678174294Sobrien case ARCHIVE_FATAL: 679174294Sobrien a->archive.state = ARCHIVE_STATE_FATAL; 680174294Sobrien break; 681174294Sobrien } 682174294Sobrien 683174294Sobrien __archive_reset_read_data(&a->archive); 684174294Sobrien 685174294Sobrien a->data_start_node = a->client.cursor; 686119679Smbr /* EOF always wins; otherwise return the worst error. */ 687174294Sobrien return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1; 68882794Sobrien} 689174294Sobrien 690174294Sobrienstatic int 69182794Sobrien_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) 692174294Sobrien{ 69382794Sobrien int ret; 694174294Sobrien struct archive_read *a = (struct archive_read *)_a; 69582794Sobrien *entryp = NULL; 696174294Sobrien ret = _archive_read_next_header2(_a, a->entry); 69782794Sobrien *entryp = a->entry; 698174294Sobrien return ret; 69982794Sobrien} 700174294Sobrien 701174294Sobrien/* 70282794Sobrien * Allow each registered format to bid on whether it wants to handle 703174294Sobrien * the next entry. Return index of winning bidder. 70482794Sobrien */ 705174294Sobrienstatic int 70682794Sobrienchoose_format(struct archive_read *a) 707174294Sobrien{ 70882794Sobrien int slots; 709174294Sobrien int i; 710174294Sobrien int bid, best_bid; 711174294Sobrien int best_bid_slot; 712174294Sobrien 71382794Sobrien slots = sizeof(a->formats) / sizeof(a->formats[0]); 714174294Sobrien best_bid = -1; 71582794Sobrien best_bid_slot = -1; 716174294Sobrien 71782794Sobrien /* Set up a->format for convenience of bidders. */ 718174294Sobrien a->format = &(a->formats[0]); 71982794Sobrien for (i = 0; i < slots; i++, a->format++) { 720174294Sobrien if (a->format->bid) { 72182794Sobrien bid = (a->format->bid)(a, best_bid); 722174294Sobrien if (bid == ARCHIVE_FATAL) 723174294Sobrien return (ARCHIVE_FATAL); 724174294Sobrien if (a->filter->position != 0) 725174294Sobrien __archive_read_seek(a, 0, SEEK_SET); 726174294Sobrien if ((bid > best_bid) || (best_bid_slot < 0)) { 72782794Sobrien best_bid = bid; 728174294Sobrien best_bid_slot = i; 72982794Sobrien } 730174294Sobrien } 73182794Sobrien } 732174294Sobrien 73382794Sobrien /* 734174294Sobrien * There were no bidders; this is a serious programmer error 735174294Sobrien * and demands a quick and definitive abort. 73682794Sobrien */ 737174294Sobrien if (best_bid_slot < 0) { 738174294Sobrien archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 739174294Sobrien "No formats registered"); 74082794Sobrien return (ARCHIVE_FATAL); 74182794Sobrien } 74282794Sobrien 74382794Sobrien /* 74482794Sobrien * There were bidders, but no non-zero bids; this means we 74582794Sobrien * can't support this stream. 74682794Sobrien */ 74782794Sobrien if (best_bid < 1) { 74882794Sobrien archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 74982794Sobrien "Unrecognized archive format"); 75082794Sobrien return (ARCHIVE_FATAL); 75182794Sobrien } 75282794Sobrien 75382794Sobrien return (best_bid_slot); 75482794Sobrien} 75582794Sobrien 75682794Sobrien/* 75782794Sobrien * Return the file offset (within the uncompressed data stream) where 75882794Sobrien * the last header started. 75982794Sobrien */ 76082794Sobrienla_int64_t 76182794Sobrienarchive_read_header_position(struct archive *_a) 76282794Sobrien{ 76382794Sobrien struct archive_read *a = (struct archive_read *)_a; 76482794Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, 76582794Sobrien ARCHIVE_STATE_ANY, "archive_read_header_position"); 76682794Sobrien return (a->header_position); 76782794Sobrien} 76882794Sobrien 76982794Sobrien/* 77082794Sobrien * Returns 1 if the archive contains at least one encrypted entry. 77182794Sobrien * If the archive format not support encryption at all 77282794Sobrien * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. 77382794Sobrien * If for any other reason (e.g. not enough data read so far) 77482794Sobrien * we cannot say whether there are encrypted entries, then 77582794Sobrien * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. 77682794Sobrien * In general, this function will return values below zero when the 77782794Sobrien * reader is uncertain or totally incapable of encryption support. 77882794Sobrien * When this function returns 0 you can be sure that the reader 77982794Sobrien * supports encryption detection but no encrypted entries have 78082794Sobrien * been found yet. 78182794Sobrien * 78282794Sobrien * NOTE: If the metadata/header of an archive is also encrypted, you 78382794Sobrien * cannot rely on the number of encrypted entries. That is why this 78482794Sobrien * function does not return the number of encrypted entries but# 78582794Sobrien * just shows that there are some. 78682794Sobrien */ 78782794Sobrienint 78882794Sobrienarchive_read_has_encrypted_entries(struct archive *_a) 78982794Sobrien{ 79082794Sobrien struct archive_read *a = (struct archive_read *)_a; 79182794Sobrien int format_supports_encryption = archive_read_format_capabilities(_a) 79282794Sobrien & (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); 79382794Sobrien 79482794Sobrien if (!_a || !format_supports_encryption) { 79582794Sobrien /* Format in general doesn't support encryption */ 79682794Sobrien return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED; 79782794Sobrien } 79882794Sobrien 79982794Sobrien /* A reader potentially has read enough data now. */ 80082794Sobrien if (a->format && a->format->has_encrypted_entries) { 80182794Sobrien return (a->format->has_encrypted_entries)(a); 80282794Sobrien } 80382794Sobrien 80482794Sobrien /* For any other reason we cannot say how many entries are there. */ 80582794Sobrien return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; 80682794Sobrien} 80782794Sobrien 80852894Sobrien/* 80952894Sobrien * Returns a bitmask of capabilities that are supported by the archive format reader. 81052894Sobrien * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. 81152894Sobrien */ 81252894Sobrienint 81352894Sobrienarchive_read_format_capabilities(struct archive *_a) 81452894Sobrien{ 81552894Sobrien struct archive_read *a = (struct archive_read *)_a; 81652894Sobrien if (a && a->format && a->format->format_capabilties) { 81752894Sobrien return (a->format->format_capabilties)(a); 81852894Sobrien } 81952894Sobrien return ARCHIVE_READ_FORMAT_CAPS_NONE; 82052894Sobrien} 82152894Sobrien 82252894Sobrien/* 82352894Sobrien * Read data from an archive entry, using a read(2)-style interface. 82452894Sobrien * This is a convenience routine that just calls 82552894Sobrien * archive_read_data_block and copies the results into the client 82652894Sobrien * buffer, filling any gaps with zero bytes. Clients using this 82752894Sobrien * API can be completely ignorant of sparse-file issues; sparse files 82852894Sobrien * will simply be padded with nulls. 82952894Sobrien * 83052894Sobrien * DO NOT intermingle calls to this function and archive_read_data_block 83152894Sobrien * to read a single entry body. 83252894Sobrien */ 83352894Sobrienla_ssize_t 83451292Sobrienarchive_read_data(struct archive *_a, void *buff, size_t s) 83551292Sobrien{ 83651292Sobrien struct archive *a = (struct archive *)_a; 83751292Sobrien char *dest; 83851292Sobrien const void *read_buf; 83951292Sobrien size_t bytes_read; 84051292Sobrien size_t len; 84151292Sobrien int r; 84251292Sobrien 84351292Sobrien bytes_read = 0; 84451292Sobrien dest = (char *)buff; 84551292Sobrien 84651292Sobrien while (s > 0) { 84751292Sobrien if (a->read_data_offset == a->read_data_output_offset && 84851292Sobrien a->read_data_remaining == 0) { 84951292Sobrien read_buf = a->read_data_block; 85051292Sobrien a->read_data_is_posix_read = 1; 85151292Sobrien a->read_data_requested = s; 85251292Sobrien r = archive_read_data_block(a, &read_buf, 85351292Sobrien &a->read_data_remaining, &a->read_data_offset); 85451292Sobrien a->read_data_block = read_buf; 85551292Sobrien if (r == ARCHIVE_EOF) 85651292Sobrien return (bytes_read); 85751292Sobrien /* 85851292Sobrien * Error codes are all negative, so the status 85951292Sobrien * return here cannot be confused with a valid 86051292Sobrien * byte count. (ARCHIVE_OK is zero.) 86151292Sobrien */ 86251292Sobrien if (r < ARCHIVE_OK) 86351292Sobrien return (r); 86451292Sobrien } 86551292Sobrien 86651292Sobrien if (a->read_data_offset < a->read_data_output_offset) { 86751292Sobrien archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, 86851292Sobrien "Encountered out-of-order sparse blocks"); 86951292Sobrien return (ARCHIVE_RETRY); 87051292Sobrien } 87151292Sobrien 87251292Sobrien /* Compute the amount of zero padding needed. */ 87351292Sobrien if (a->read_data_output_offset + (int64_t)s < 87451292Sobrien a->read_data_offset) { 87551292Sobrien len = s; 87651292Sobrien } else if (a->read_data_output_offset < 87751292Sobrien a->read_data_offset) { 87851292Sobrien len = (size_t)(a->read_data_offset - 87951292Sobrien a->read_data_output_offset); 88051292Sobrien } else 88151292Sobrien len = 0; 88251292Sobrien 88351292Sobrien /* Add zeroes. */ 88451292Sobrien memset(dest, 0, len); 88551292Sobrien s -= len; 88651292Sobrien a->read_data_output_offset += len; 88751292Sobrien dest += len; 88851292Sobrien bytes_read += len; 88951292Sobrien 89051292Sobrien /* Copy data if there is any space left. */ 89151292Sobrien if (s > 0) { 89242629Sobrien len = a->read_data_remaining; 89342629Sobrien if (len > s) 89442629Sobrien len = s; 89542629Sobrien if (len) 89642629Sobrien memcpy(dest, a->read_data_block, len); 89742629Sobrien s -= len; 89842629Sobrien a->read_data_block += len; 89942629Sobrien a->read_data_remaining -= len; 90042629Sobrien a->read_data_output_offset += len; 90142629Sobrien a->read_data_offset += len; 90242629Sobrien dest += len; 90342629Sobrien bytes_read += len; 90442629Sobrien } 90542629Sobrien } 90642629Sobrien a->read_data_is_posix_read = 0; 90742629Sobrien a->read_data_requested = 0; 90842629Sobrien return (bytes_read); 90942629Sobrien} 91042629Sobrien 91142629Sobrien/* 91242629Sobrien * Reset the read_data_* variables, used for starting a new entry. 91342629Sobrien */ 91442629Sobrienvoid __archive_reset_read_data(struct archive * a) 91542629Sobrien{ 91642629Sobrien a->read_data_output_offset = 0; 91742629Sobrien a->read_data_remaining = 0; 91842629Sobrien a->read_data_is_posix_read = 0; 91942629Sobrien a->read_data_requested = 0; 92042629Sobrien 92142629Sobrien /* extra resets, from rar.c */ 92242629Sobrien a->read_data_block = NULL; 92342629Sobrien a->read_data_offset = 0; 92441142Sobrien} 92541142Sobrien 92641142Sobrien/* 92741142Sobrien * Skip over all remaining data in this entry. 92841142Sobrien */ 92941142Sobrienint 93041142Sobrienarchive_read_data_skip(struct archive *_a) 93141142Sobrien{ 93241142Sobrien struct archive_read *a = (struct archive_read *)_a; 93341142Sobrien int r; 93441142Sobrien const void *buff; 93541142Sobrien size_t size; 93641142Sobrien int64_t offset; 93741142Sobrien 93841142Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 93941142Sobrien "archive_read_data_skip"); 94038494Sobrien 94138494Sobrien if (a->format->read_data_skip != NULL) 94238494Sobrien r = (a->format->read_data_skip)(a); 94338494Sobrien else { 94438494Sobrien while ((r = archive_read_data_block(&a->archive, 94538494Sobrien &buff, &size, &offset)) 94638494Sobrien == ARCHIVE_OK) 94738494Sobrien ; 94838494Sobrien } 94938494Sobrien 95038494Sobrien if (r == ARCHIVE_EOF) 95138494Sobrien r = ARCHIVE_OK; 95238494Sobrien 95338494Sobrien a->archive.state = ARCHIVE_STATE_HEADER; 95438494Sobrien return (r); 95538494Sobrien} 95638494Sobrien 95738494Sobrienla_int64_t 95838494Sobrienarchive_seek_data(struct archive *_a, int64_t offset, int whence) 95938494Sobrien{ 96038494Sobrien struct archive_read *a = (struct archive_read *)_a; 96138494Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 96238494Sobrien "archive_seek_data_block"); 96338494Sobrien 96438494Sobrien if (a->format->seek_data == NULL) { 96538494Sobrien archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 96638494Sobrien "Internal error: " 96738494Sobrien "No format_seek_data_block function registered"); 96838494Sobrien return (ARCHIVE_FATAL); 96938494Sobrien } 97038494Sobrien 97138494Sobrien return (a->format->seek_data)(a, offset, whence); 97238494Sobrien} 97338494Sobrien 97438494Sobrien/* 97538494Sobrien * Read the next block of entry data from the archive. 97638494Sobrien * This is a zero-copy interface; the client receives a pointer, 97738494Sobrien * size, and file offset of the next available block of data. 97838494Sobrien * 97938494Sobrien * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if 98038494Sobrien * the end of entry is encountered. 98138494Sobrien */ 98238494Sobrienstatic int 98338494Sobrien_archive_read_data_block(struct archive *_a, 98438494Sobrien const void **buff, size_t *size, int64_t *offset) 98538494Sobrien{ 98638494Sobrien struct archive_read *a = (struct archive_read *)_a; 98738494Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 98838494Sobrien "archive_read_data_block"); 98938494Sobrien 99038494Sobrien if (a->format->read_data == NULL) { 99138494Sobrien archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 99238494Sobrien "Internal error: " 99338494Sobrien "No format->read_data function registered"); 99438494Sobrien return (ARCHIVE_FATAL); 99538494Sobrien } 99638494Sobrien 99738494Sobrien return (a->format->read_data)(a, buff, size, offset); 99838494Sobrien} 99938494Sobrien 100038494Sobrienstatic int 100138494Sobrienclose_filters(struct archive_read *a) 100238494Sobrien{ 100338494Sobrien struct archive_read_filter *f = a->filter; 100438494Sobrien int r = ARCHIVE_OK; 100538494Sobrien /* Close each filter in the pipeline. */ 100638494Sobrien while (f != NULL) { 100738494Sobrien struct archive_read_filter *t = f->upstream; 100838494Sobrien if (!f->closed && f->close != NULL) { 100938494Sobrien int r1 = (f->close)(f); 101038494Sobrien f->closed = 1; 101138494Sobrien if (r1 < r) 101238494Sobrien r = r1; 101338494Sobrien } 101438494Sobrien free(f->buffer); 101538494Sobrien f->buffer = NULL; 101638494Sobrien f = t; 101738494Sobrien } 101838494Sobrien return r; 101938494Sobrien} 102038494Sobrien 102138494Sobrienvoid 102238494Sobrien__archive_read_free_filters(struct archive_read *a) 102338494Sobrien{ 102438494Sobrien /* Make sure filters are closed and their buffers are freed */ 102538494Sobrien close_filters(a); 102638494Sobrien 102738494Sobrien while (a->filter != NULL) { 102838494Sobrien struct archive_read_filter *t = a->filter->upstream; 102938494Sobrien free(a->filter); 103038494Sobrien a->filter = t; 103138494Sobrien } 103238494Sobrien} 103338494Sobrien 103438494Sobrien/* 103538494Sobrien * return the count of # of filters in use 103638494Sobrien */ 103738494Sobrienstatic int 103838494Sobrien_archive_filter_count(struct archive *_a) 103938494Sobrien{ 104038494Sobrien struct archive_read *a = (struct archive_read *)_a; 104138494Sobrien struct archive_read_filter *p = a->filter; 104238494Sobrien int count = 0; 104338494Sobrien while(p) { 104438494Sobrien count++; 104538494Sobrien p = p->upstream; 104638494Sobrien } 104738494Sobrien return count; 104838494Sobrien} 104938494Sobrien 105038494Sobrien/* 105138494Sobrien * Close the file and all I/O. 105238494Sobrien */ 105338494Sobrienstatic int 105438494Sobrien_archive_read_close(struct archive *_a) 105538494Sobrien{ 105638494Sobrien struct archive_read *a = (struct archive_read *)_a; 105738494Sobrien int r = ARCHIVE_OK, r1 = ARCHIVE_OK; 105838494Sobrien 105938494Sobrien archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, 106038494Sobrien ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); 106138494Sobrien if (a->archive.state == ARCHIVE_STATE_CLOSED) 106238494Sobrien return (ARCHIVE_OK); 106338494Sobrien archive_clear_error(&a->archive); 106438494Sobrien a->archive.state = ARCHIVE_STATE_CLOSED; 106538494Sobrien 106638494Sobrien /* TODO: Clean up the formatters. */ 106738494Sobrien 106838494Sobrien /* Release the filter objects. */ 106938494Sobrien r1 = close_filters(a); 107038494Sobrien if (r1 < r) 107138494Sobrien r = r1; 107238494Sobrien 107338494Sobrien return (r); 107438494Sobrien} 107538494Sobrien 107638494Sobrien/* 107738494Sobrien * Release memory and other resources. 107838494Sobrien */ 107938494Sobrienstatic int 108038494Sobrien_archive_read_free(struct archive *_a) 108138494Sobrien{ 108238494Sobrien struct archive_read *a = (struct archive_read *)_a; 108338494Sobrien struct archive_read_passphrase *p; 108438494Sobrien int i, n; 108538494Sobrien int slots; 108638494Sobrien int r = ARCHIVE_OK; 108738494Sobrien 108838494Sobrien if (_a == NULL) 108938494Sobrien return (ARCHIVE_OK); 109038494Sobrien archive_check_magic(_a, ARCHIVE_READ_MAGIC, 109138494Sobrien ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); 109238494Sobrien if (a->archive.state != ARCHIVE_STATE_CLOSED 109338494Sobrien && a->archive.state != ARCHIVE_STATE_FATAL) 109438494Sobrien r = archive_read_close(&a->archive); 109538494Sobrien 109638494Sobrien /* Call cleanup functions registered by optional components. */ 109738494Sobrien if (a->cleanup_archive_extract != NULL) 109838494Sobrien r = (a->cleanup_archive_extract)(a); 109938494Sobrien 110038494Sobrien /* Cleanup format-specific data. */ 110138494Sobrien slots = sizeof(a->formats) / sizeof(a->formats[0]); 110238494Sobrien for (i = 0; i < slots; i++) { 110338494Sobrien a->format = &(a->formats[i]); 110438494Sobrien if (a->formats[i].cleanup) 110538494Sobrien (a->formats[i].cleanup)(a); 110638494Sobrien } 110738494Sobrien 110838494Sobrien /* Free the filters */ 110938494Sobrien __archive_read_free_filters(a); 111038494Sobrien 1111174294Sobrien /* Release the bidder objects. */ 111238494Sobrien n = sizeof(a->bidders)/sizeof(a->bidders[0]); 111338494Sobrien for (i = 0; i < n; i++) { 111438494Sobrien if (a->bidders[i].free != NULL) { 111538494Sobrien int r1 = (a->bidders[i].free)(&a->bidders[i]); 111638494Sobrien if (r1 < r) 111738494Sobrien r = r1; 111838494Sobrien } 111938494Sobrien } 112038494Sobrien 112138494Sobrien /* Release passphrase list. */ 112238494Sobrien p = a->passphrases.first; 112338494Sobrien while (p != NULL) { 112438494Sobrien struct archive_read_passphrase *np = p->next; 112538494Sobrien 112638494Sobrien /* A passphrase should be cleaned. */ 112738494Sobrien memset(p->passphrase, 0, strlen(p->passphrase)); 112838494Sobrien free(p->passphrase); 112938494Sobrien free(p); 113038494Sobrien p = np; 113138494Sobrien } 113238494Sobrien 113338494Sobrien archive_string_free(&a->archive.error_string); 113438494Sobrien archive_entry_free(a->entry); 113538494Sobrien a->archive.magic = 0; 113638494Sobrien __archive_clean(&a->archive); 113738494Sobrien free(a->client.dataset); 113838494Sobrien free(a); 113938494Sobrien return (r); 114038494Sobrien} 114138494Sobrien 114238494Sobrienstatic struct archive_read_filter * 114338494Sobrienget_filter(struct archive *_a, int n) 114438494Sobrien{ 114538494Sobrien struct archive_read *a = (struct archive_read *)_a; 114638494Sobrien struct archive_read_filter *f = a->filter; 114738494Sobrien /* We use n == -1 for 'the last filter', which is always the 114882794Sobrien * client proxy. */ 114938494Sobrien if (n == -1 && f != NULL) { 115038494Sobrien struct archive_read_filter *last = f; 115138494Sobrien f = f->upstream; 115238494Sobrien while (f != NULL) { 115338494Sobrien last = f; 115438494Sobrien f = f->upstream; 115538494Sobrien } 115638494Sobrien return (last); 115738494Sobrien } 115838494Sobrien if (n < 0) 115938494Sobrien return NULL; 116038494Sobrien while (n > 0 && f != NULL) { 116138494Sobrien f = f->upstream; 116238494Sobrien --n; 116338494Sobrien } 116438494Sobrien return (f); 116538494Sobrien} 116638494Sobrien 116738494Sobrienstatic int 116838494Sobrien_archive_filter_code(struct archive *_a, int n) 116938494Sobrien{ 117038494Sobrien struct archive_read_filter *f = get_filter(_a, n); 117138494Sobrien return f == NULL ? -1 : f->code; 117238494Sobrien} 117338494Sobrien 117438494Sobrienstatic const char * 117538494Sobrien_archive_filter_name(struct archive *_a, int n) 117638494Sobrien{ 117738494Sobrien struct archive_read_filter *f = get_filter(_a, n); 117838494Sobrien return f != NULL ? f->name : NULL; 117938494Sobrien} 118038494Sobrien 118138494Sobrienstatic int64_t 118238494Sobrien_archive_filter_bytes(struct archive *_a, int n) 118338494Sobrien{ 118438494Sobrien struct archive_read_filter *f = get_filter(_a, n); 118538494Sobrien return f == NULL ? -1 : f->position; 118638494Sobrien} 118738494Sobrien 118838494Sobrien/* 118938494Sobrien * Used internally by read format handlers to register their bid and 119038494Sobrien * initialization functions. 119138494Sobrien */ 119238494Sobrienint 119338494Sobrien__archive_read_register_format(struct archive_read *a, 119438494Sobrien void *format_data, 119538494Sobrien const char *name, 119638494Sobrien int (*bid)(struct archive_read *, int), 119738494Sobrien int (*options)(struct archive_read *, const char *, const char *), 119838494Sobrien int (*read_header)(struct archive_read *, struct archive_entry *), 119938494Sobrien int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), 120038494Sobrien int (*read_data_skip)(struct archive_read *), 120138494Sobrien int64_t (*seek_data)(struct archive_read *, int64_t, int), 120238494Sobrien int (*cleanup)(struct archive_read *), 120338494Sobrien int (*format_capabilities)(struct archive_read *), 120438494Sobrien int (*has_encrypted_entries)(struct archive_read *)) 120538494Sobrien{ 120638494Sobrien int i, number_slots; 120738494Sobrien 120838494Sobrien archive_check_magic(&a->archive, 120938494Sobrien ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 121038494Sobrien "__archive_read_register_format"); 121138494Sobrien 121238494Sobrien number_slots = sizeof(a->formats) / sizeof(a->formats[0]); 121338494Sobrien 121438494Sobrien for (i = 0; i < number_slots; i++) { 121538494Sobrien if (a->formats[i].bid == bid) 121638494Sobrien return (ARCHIVE_WARN); /* We've already installed */ 121738494Sobrien if (a->formats[i].bid == NULL) { 121838494Sobrien a->formats[i].bid = bid; 121938494Sobrien a->formats[i].options = options; 122038494Sobrien a->formats[i].read_header = read_header; 122138494Sobrien a->formats[i].read_data = read_data; 122238494Sobrien a->formats[i].read_data_skip = read_data_skip; 122338494Sobrien a->formats[i].seek_data = seek_data; 122438494Sobrien a->formats[i].cleanup = cleanup; 122538494Sobrien a->formats[i].data = format_data; 122638494Sobrien a->formats[i].name = name; 122738494Sobrien a->formats[i].format_capabilties = format_capabilities; 122838494Sobrien a->formats[i].has_encrypted_entries = has_encrypted_entries; 122938494Sobrien return (ARCHIVE_OK); 123038494Sobrien } 123138494Sobrien } 123238494Sobrien 123338494Sobrien archive_set_error(&a->archive, ENOMEM, 123438494Sobrien "Not enough slots for format registration"); 123538494Sobrien return (ARCHIVE_FATAL); 123638494Sobrien} 123738494Sobrien 123838494Sobrien/* 123938494Sobrien * Used internally by decompression routines to register their bid and 124038494Sobrien * initialization functions. 124138494Sobrien */ 124238494Sobrienint 124338494Sobrien__archive_read_get_bidder(struct archive_read *a, 124438494Sobrien struct archive_read_filter_bidder **bidder) 124538494Sobrien{ 124638494Sobrien int i, number_slots; 124738494Sobrien 124838494Sobrien number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]); 124938494Sobrien 125038494Sobrien for (i = 0; i < number_slots; i++) { 125138494Sobrien if (a->bidders[i].bid == NULL) { 125238494Sobrien memset(a->bidders + i, 0, sizeof(a->bidders[0])); 125338494Sobrien *bidder = (a->bidders + i); 125438494Sobrien return (ARCHIVE_OK); 125538494Sobrien } 125638494Sobrien } 125738494Sobrien 125838494Sobrien archive_set_error(&a->archive, ENOMEM, 125938494Sobrien "Not enough slots for filter registration"); 126038494Sobrien return (ARCHIVE_FATAL); 126138494Sobrien} 126238494Sobrien 126338494Sobrien/* 126438494Sobrien * The next section implements the peek/consume internal I/O 126538494Sobrien * system used by archive readers. This system allows simple 126638494Sobrien * read-ahead for consumers while preserving zero-copy operation 126738494Sobrien * most of the time. 126838494Sobrien * 126938494Sobrien * The two key operations: 127038494Sobrien * * The read-ahead function returns a pointer to a block of data 127138494Sobrien * that satisfies a minimum request. 127238494Sobrien * * The consume function advances the file pointer. 127338494Sobrien * 127438494Sobrien * In the ideal case, filters generate blocks of data 127538494Sobrien * and __archive_read_ahead() just returns pointers directly into 127638494Sobrien * those blocks. Then __archive_read_consume() just bumps those 127738494Sobrien * pointers. Only if your request would span blocks does the I/O 127838494Sobrien * layer use a copy buffer to provide you with a contiguous block of 127938494Sobrien * data. 128038494Sobrien * 128138494Sobrien * A couple of useful idioms: 128238494Sobrien * * "I just want some data." Ask for 1 byte and pay attention to 128338494Sobrien * the "number of bytes available" from __archive_read_ahead(). 128438494Sobrien * Consume whatever you actually use. 128538494Sobrien * * "I want to output a large block of data." As above, ask for 1 byte, 128638494Sobrien * emit all that's available (up to whatever limit you have), consume 128738494Sobrien * it all, then repeat until you're done. This effectively means that 128838494Sobrien * you're passing along the blocks that came from your provider. 128938494Sobrien * * "I want to peek ahead by a large amount." Ask for 4k or so, then 129038494Sobrien * double and repeat until you get an error or have enough. Note 129138494Sobrien * that the I/O layer will likely end up expanding its copy buffer 129238494Sobrien * to fit your request, so use this technique cautiously. This 129338494Sobrien * technique is used, for example, by some of the format tasting 129438494Sobrien * code that has uncertain look-ahead needs. 129538494Sobrien */ 129638494Sobrien 129738494Sobrien/* 129838494Sobrien * Looks ahead in the input stream: 129938494Sobrien * * If 'avail' pointer is provided, that returns number of bytes available 130038494Sobrien * in the current buffer, which may be much larger than requested. 130138494Sobrien * * If end-of-file, *avail gets set to zero. 130238494Sobrien * * If error, *avail gets error code. 130338494Sobrien * * If request can be met, returns pointer to data. 130438494Sobrien * * If minimum request cannot be met, returns NULL. 130538494Sobrien * 130638494Sobrien * Note: If you just want "some data", ask for 1 byte and pay attention 130738494Sobrien * to *avail, which will have the actual amount available. If you 130838494Sobrien * know exactly how many bytes you need, just ask for that and treat 130938494Sobrien * a NULL return as an error. 131038494Sobrien * 131138494Sobrien * Important: This does NOT move the file pointer. See 131238494Sobrien * __archive_read_consume() below. 131338494Sobrien */ 131438494Sobrienconst void * 131538494Sobrien__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) 131638494Sobrien{ 131738494Sobrien return (__archive_read_filter_ahead(a->filter, min, avail)); 131838494Sobrien} 131938494Sobrien 132038494Sobrienconst void * 132138494Sobrien__archive_read_filter_ahead(struct archive_read_filter *filter, 132238494Sobrien size_t min, ssize_t *avail) 132338494Sobrien{ 132438494Sobrien ssize_t bytes_read; 132538494Sobrien size_t tocopy; 132638494Sobrien 132738494Sobrien if (filter->fatal) { 132838494Sobrien if (avail) 132938494Sobrien *avail = ARCHIVE_FATAL; 133038494Sobrien return (NULL); 133138494Sobrien } 133238494Sobrien 133338494Sobrien /* 133438494Sobrien * Keep pulling more data until we can satisfy the request. 133538494Sobrien */ 133638494Sobrien for (;;) { 133738494Sobrien 133838494Sobrien /* 133938494Sobrien * If we can satisfy from the copy buffer (and the 134038494Sobrien * copy buffer isn't empty), we're done. In particular, 134138494Sobrien * note that min == 0 is a perfectly well-defined 134238494Sobrien * request. 134338494Sobrien */ 134438494Sobrien if (filter->avail >= min && filter->avail > 0) { 134538494Sobrien if (avail != NULL) 134638494Sobrien *avail = filter->avail; 134738494Sobrien return (filter->next); 134838494Sobrien } 134938494Sobrien 135038494Sobrien /* 135138494Sobrien * We can satisfy directly from client buffer if everything 135238494Sobrien * currently in the copy buffer is still in the client buffer. 135338494Sobrien */ 135438494Sobrien if (filter->client_total >= filter->client_avail + filter->avail 135538494Sobrien && filter->client_avail + filter->avail >= min) { 135638494Sobrien /* "Roll back" to client buffer. */ 135738494Sobrien filter->client_avail += filter->avail; 135838494Sobrien filter->client_next -= filter->avail; 135938494Sobrien /* Copy buffer is now empty. */ 136038494Sobrien filter->avail = 0; 136138494Sobrien filter->next = filter->buffer; 136238494Sobrien /* Return data from client buffer. */ 136338494Sobrien if (avail != NULL) 136438494Sobrien *avail = filter->client_avail; 136538494Sobrien return (filter->client_next); 136638494Sobrien } 136738494Sobrien 136838494Sobrien /* Move data forward in copy buffer if necessary. */ 136938494Sobrien if (filter->next > filter->buffer && 137038494Sobrien filter->next + min > filter->buffer + filter->buffer_size) { 137138494Sobrien if (filter->avail > 0) 137238494Sobrien memmove(filter->buffer, filter->next, 137338494Sobrien filter->avail); 137438494Sobrien filter->next = filter->buffer; 137538494Sobrien } 137638494Sobrien 137738494Sobrien /* If we've used up the client data, get more. */ 137838494Sobrien if (filter->client_avail <= 0) { 137938494Sobrien if (filter->end_of_file) { 138038494Sobrien if (avail != NULL) 138138494Sobrien *avail = 0; 138238494Sobrien return (NULL); 138338494Sobrien } 138438494Sobrien bytes_read = (filter->read)(filter, 138538494Sobrien &filter->client_buff); 138638494Sobrien if (bytes_read < 0) { /* Read error. */ 138738494Sobrien filter->client_total = filter->client_avail = 0; 138838494Sobrien filter->client_next = 138938494Sobrien filter->client_buff = NULL; 139038494Sobrien filter->fatal = 1; 139138494Sobrien if (avail != NULL) 139238494Sobrien *avail = ARCHIVE_FATAL; 139338494Sobrien return (NULL); 139438494Sobrien } 139538494Sobrien if (bytes_read == 0) { 139638494Sobrien /* Check for another client object first */ 139738494Sobrien if (filter->archive->client.cursor != 139838494Sobrien filter->archive->client.nodes - 1) { 139938494Sobrien if (client_switch_proxy(filter, 140038494Sobrien filter->archive->client.cursor + 1) 140138494Sobrien == ARCHIVE_OK) 140238494Sobrien continue; 140338494Sobrien } 140438494Sobrien /* Premature end-of-file. */ 140538494Sobrien filter->client_total = filter->client_avail = 0; 140638494Sobrien filter->client_next = 140738494Sobrien filter->client_buff = NULL; 140838494Sobrien filter->end_of_file = 1; 140938494Sobrien /* Return whatever we do have. */ 141038494Sobrien if (avail != NULL) 141138494Sobrien *avail = filter->avail; 141238494Sobrien return (NULL); 141338494Sobrien } 141438494Sobrien filter->client_total = bytes_read; 141538494Sobrien filter->client_avail = filter->client_total; 141638494Sobrien filter->client_next = filter->client_buff; 141738494Sobrien } else { 141838494Sobrien /* 141938494Sobrien * We can't satisfy the request from the copy 142038494Sobrien * buffer or the existing client data, so we 142138494Sobrien * need to copy more client data over to the 142238494Sobrien * copy buffer. 142338494Sobrien */ 142438494Sobrien 142538494Sobrien /* Ensure the buffer is big enough. */ 142638494Sobrien if (min > filter->buffer_size) { 142738494Sobrien size_t s, t; 142838494Sobrien char *p; 142938494Sobrien 143038494Sobrien /* Double the buffer; watch for overflow. */ 143138494Sobrien s = t = filter->buffer_size; 143238494Sobrien if (s == 0) 143338494Sobrien s = min; 143438494Sobrien while (s < min) { 143538494Sobrien t *= 2; 143638494Sobrien if (t <= s) { /* Integer overflow! */ 143738494Sobrien archive_set_error( 143838494Sobrien &filter->archive->archive, 143938494Sobrien ENOMEM, 144038494Sobrien "Unable to allocate copy" 144138494Sobrien " buffer"); 144238494Sobrien filter->fatal = 1; 144338494Sobrien if (avail != NULL) 144438494Sobrien *avail = ARCHIVE_FATAL; 144538494Sobrien return (NULL); 144638494Sobrien } 144738494Sobrien s = t; 144838494Sobrien } 144938494Sobrien /* Now s >= min, so allocate a new buffer. */ 145038494Sobrien p = (char *)malloc(s); 145138494Sobrien if (p == NULL) { 145238494Sobrien archive_set_error( 145338494Sobrien &filter->archive->archive, 145438494Sobrien ENOMEM, 145538494Sobrien "Unable to allocate copy buffer"); 145638494Sobrien filter->fatal = 1; 145738494Sobrien if (avail != NULL) 145838494Sobrien *avail = ARCHIVE_FATAL; 145938494Sobrien return (NULL); 146038494Sobrien } 146138494Sobrien /* Move data into newly-enlarged buffer. */ 146238494Sobrien if (filter->avail > 0) 146338494Sobrien memmove(p, filter->next, filter->avail); 146438494Sobrien free(filter->buffer); 146538494Sobrien filter->next = filter->buffer = p; 146638494Sobrien filter->buffer_size = s; 146738494Sobrien } 146838494Sobrien 146938494Sobrien /* We can add client data to copy buffer. */ 147038494Sobrien /* First estimate: copy to fill rest of buffer. */ 147138494Sobrien tocopy = (filter->buffer + filter->buffer_size) 147238494Sobrien - (filter->next + filter->avail); 147338494Sobrien /* Don't waste time buffering more than we need to. */ 147438494Sobrien if (tocopy + filter->avail > min) 147538494Sobrien tocopy = min - filter->avail; 147638494Sobrien /* Don't copy more than is available. */ 147738494Sobrien if (tocopy > filter->client_avail) 147838494Sobrien tocopy = filter->client_avail; 147938494Sobrien 148038494Sobrien memcpy(filter->next + filter->avail, 148138494Sobrien filter->client_next, tocopy); 148238494Sobrien /* Remove this data from client buffer. */ 148338494Sobrien filter->client_next += tocopy; 148438494Sobrien filter->client_avail -= tocopy; 148538494Sobrien /* add it to copy buffer. */ 148638494Sobrien filter->avail += tocopy; 148738494Sobrien } 148838494Sobrien } 148938494Sobrien} 149038494Sobrien 149138494Sobrien/* 149238494Sobrien * Move the file pointer forward. 149338494Sobrien */ 149438494Sobrienint64_t 149538494Sobrien__archive_read_consume(struct archive_read *a, int64_t request) 149638494Sobrien{ 149738494Sobrien return (__archive_read_filter_consume(a->filter, request)); 149838494Sobrien} 149938494Sobrien 150038494Sobrienint64_t 150138494Sobrien__archive_read_filter_consume(struct archive_read_filter * filter, 150238494Sobrien int64_t request) 150338494Sobrien{ 150438494Sobrien int64_t skipped; 150538494Sobrien 150638494Sobrien if (request < 0) 150738494Sobrien return ARCHIVE_FATAL; 150838494Sobrien if (request == 0) 150938494Sobrien return 0; 151038494Sobrien 151138494Sobrien skipped = advance_file_pointer(filter, request); 151238494Sobrien if (skipped == request) 151338494Sobrien return (skipped); 151438494Sobrien /* We hit EOF before we satisfied the skip request. */ 151538494Sobrien if (skipped < 0) /* Map error code to 0 for error message below. */ 151638494Sobrien skipped = 0; 151738494Sobrien archive_set_error(&filter->archive->archive, 151838494Sobrien ARCHIVE_ERRNO_MISC, 151938494Sobrien "Truncated input file (needed %jd bytes, only %jd available)", 152038494Sobrien (intmax_t)request, (intmax_t)skipped); 152138494Sobrien return (ARCHIVE_FATAL); 152238494Sobrien} 152338494Sobrien 152438494Sobrien/* 152538494Sobrien * Advance the file pointer by the amount requested. 152638494Sobrien * Returns the amount actually advanced, which may be less than the 152738494Sobrien * request if EOF is encountered first. 1528174294Sobrien * Returns a negative value if there's an I/O error. 152938494Sobrien */ 153038494Sobrienstatic int64_t 153138494Sobrienadvance_file_pointer(struct archive_read_filter *filter, int64_t request) 1532174294Sobrien{ 153338494Sobrien int64_t bytes_skipped, total_bytes_skipped = 0; 153438494Sobrien ssize_t bytes_read; 153538494Sobrien size_t min; 153638494Sobrien 153738494Sobrien if (filter->fatal) 153838494Sobrien return (-1); 153938494Sobrien 154038494Sobrien /* Use up the copy buffer first. */ 154138494Sobrien if (filter->avail > 0) { 154238494Sobrien min = (size_t)minimum(request, (int64_t)filter->avail); 154338494Sobrien filter->next += min; 154438494Sobrien filter->avail -= min; 154538494Sobrien request -= min; 154638494Sobrien filter->position += min; 154738494Sobrien total_bytes_skipped += min; 154838494Sobrien } 154938494Sobrien 155038494Sobrien /* Then use up the client buffer. */ 155138494Sobrien if (filter->client_avail > 0) { 155238494Sobrien min = (size_t)minimum(request, (int64_t)filter->client_avail); 155338494Sobrien filter->client_next += min; 155438494Sobrien filter->client_avail -= min; 155538494Sobrien request -= min; 155638494Sobrien filter->position += min; 155738494Sobrien total_bytes_skipped += min; 155838494Sobrien } 155938494Sobrien if (request == 0) 156038494Sobrien return (total_bytes_skipped); 156138494Sobrien 156238494Sobrien /* If there's an optimized skip function, use it. */ 156338494Sobrien if (filter->skip != NULL) { 156438494Sobrien bytes_skipped = (filter->skip)(filter, request); 156538494Sobrien if (bytes_skipped < 0) { /* error */ 156638494Sobrien filter->fatal = 1; 156738494Sobrien return (bytes_skipped); 1568 } 1569 filter->position += bytes_skipped; 1570 total_bytes_skipped += bytes_skipped; 1571 request -= bytes_skipped; 1572 if (request == 0) 1573 return (total_bytes_skipped); 1574 } 1575 1576 /* Use ordinary reads as necessary to complete the request. */ 1577 for (;;) { 1578 bytes_read = (filter->read)(filter, &filter->client_buff); 1579 if (bytes_read < 0) { 1580 filter->client_buff = NULL; 1581 filter->fatal = 1; 1582 return (bytes_read); 1583 } 1584 1585 if (bytes_read == 0) { 1586 if (filter->archive->client.cursor != 1587 filter->archive->client.nodes - 1) { 1588 if (client_switch_proxy(filter, 1589 filter->archive->client.cursor + 1) 1590 == ARCHIVE_OK) 1591 continue; 1592 } 1593 filter->client_buff = NULL; 1594 filter->end_of_file = 1; 1595 return (total_bytes_skipped); 1596 } 1597 1598 if (bytes_read >= request) { 1599 filter->client_next = 1600 ((const char *)filter->client_buff) + request; 1601 filter->client_avail = (size_t)(bytes_read - request); 1602 filter->client_total = bytes_read; 1603 total_bytes_skipped += request; 1604 filter->position += request; 1605 return (total_bytes_skipped); 1606 } 1607 1608 filter->position += bytes_read; 1609 total_bytes_skipped += bytes_read; 1610 request -= bytes_read; 1611 } 1612} 1613 1614/** 1615 * Returns ARCHIVE_FAILED if seeking isn't supported. 1616 */ 1617int64_t 1618__archive_read_seek(struct archive_read *a, int64_t offset, int whence) 1619{ 1620 return __archive_read_filter_seek(a->filter, offset, whence); 1621} 1622 1623int64_t 1624__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, 1625 int whence) 1626{ 1627 struct archive_read_client *client; 1628 int64_t r; 1629 unsigned int cursor; 1630 1631 if (filter->closed || filter->fatal) 1632 return (ARCHIVE_FATAL); 1633 if (filter->seek == NULL) 1634 return (ARCHIVE_FAILED); 1635 1636 client = &(filter->archive->client); 1637 switch (whence) { 1638 case SEEK_CUR: 1639 /* Adjust the offset and use SEEK_SET instead */ 1640 offset += filter->position; 1641 __LA_FALLTHROUGH; 1642 case SEEK_SET: 1643 cursor = 0; 1644 while (1) 1645 { 1646 if (client->dataset[cursor].begin_position < 0 || 1647 client->dataset[cursor].total_size < 0 || 1648 client->dataset[cursor].begin_position + 1649 client->dataset[cursor].total_size - 1 > offset || 1650 cursor + 1 >= client->nodes) 1651 break; 1652 r = client->dataset[cursor].begin_position + 1653 client->dataset[cursor].total_size; 1654 client->dataset[++cursor].begin_position = r; 1655 } 1656 while (1) { 1657 r = client_switch_proxy(filter, cursor); 1658 if (r != ARCHIVE_OK) 1659 return r; 1660 if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) 1661 return r; 1662 client->dataset[cursor].total_size = r; 1663 if (client->dataset[cursor].begin_position + 1664 client->dataset[cursor].total_size - 1 > offset || 1665 cursor + 1 >= client->nodes) 1666 break; 1667 r = client->dataset[cursor].begin_position + 1668 client->dataset[cursor].total_size; 1669 client->dataset[++cursor].begin_position = r; 1670 } 1671 offset -= client->dataset[cursor].begin_position; 1672 if (offset < 0 1673 || offset > client->dataset[cursor].total_size) 1674 return ARCHIVE_FATAL; 1675 if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0) 1676 return r; 1677 break; 1678 1679 case SEEK_END: 1680 cursor = 0; 1681 while (1) { 1682 if (client->dataset[cursor].begin_position < 0 || 1683 client->dataset[cursor].total_size < 0 || 1684 cursor + 1 >= client->nodes) 1685 break; 1686 r = client->dataset[cursor].begin_position + 1687 client->dataset[cursor].total_size; 1688 client->dataset[++cursor].begin_position = r; 1689 } 1690 while (1) { 1691 r = client_switch_proxy(filter, cursor); 1692 if (r != ARCHIVE_OK) 1693 return r; 1694 if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) 1695 return r; 1696 client->dataset[cursor].total_size = r; 1697 r = client->dataset[cursor].begin_position + 1698 client->dataset[cursor].total_size; 1699 if (cursor + 1 >= client->nodes) 1700 break; 1701 client->dataset[++cursor].begin_position = r; 1702 } 1703 while (1) { 1704 if (r + offset >= 1705 client->dataset[cursor].begin_position) 1706 break; 1707 offset += client->dataset[cursor].total_size; 1708 if (cursor == 0) 1709 break; 1710 cursor--; 1711 r = client->dataset[cursor].begin_position + 1712 client->dataset[cursor].total_size; 1713 } 1714 offset = (r + offset) - client->dataset[cursor].begin_position; 1715 if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK) 1716 return r; 1717 r = client_seek_proxy(filter, offset, SEEK_SET); 1718 if (r < ARCHIVE_OK) 1719 return r; 1720 break; 1721 1722 default: 1723 return (ARCHIVE_FATAL); 1724 } 1725 r += client->dataset[cursor].begin_position; 1726 1727 if (r >= 0) { 1728 /* 1729 * Ouch. Clearing the buffer like this hurts, especially 1730 * at bid time. A lot of our efficiency at bid time comes 1731 * from having bidders reuse the data we've already read. 1732 * 1733 * TODO: If the seek request is in data we already 1734 * have, then don't call the seek callback. 1735 * 1736 * TODO: Zip seeks to end-of-file at bid time. If 1737 * other formats also start doing this, we may need to 1738 * find a way for clients to fudge the seek offset to 1739 * a block boundary. 1740 * 1741 * Hmmm... If whence was SEEK_END, we know the file 1742 * size is (r - offset). Can we use that to simplify 1743 * the TODO items above? 1744 */ 1745 filter->avail = filter->client_avail = 0; 1746 filter->next = filter->buffer; 1747 filter->position = r; 1748 filter->end_of_file = 0; 1749 } 1750 return r; 1751} 1752