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: stable/11/contrib/libarchive/libarchive/archive_read.c 358926 2020-03-13 01:05:55Z mm $"); 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 *); 60311041Smmstatic int close_filters(struct archive_read *); 61228753Smmstatic struct archive_vtable *archive_read_vtable(void); 62232153Smmstatic int64_t _archive_filter_bytes(struct archive *, int); 63232153Smmstatic int _archive_filter_code(struct archive *, int); 64232153Smmstatic const char *_archive_filter_name(struct archive *, int); 65232153Smmstatic int _archive_filter_count(struct archive *); 66228753Smmstatic int _archive_read_close(struct archive *); 67232153Smmstatic int _archive_read_data_block(struct archive *, 68232153Smm const void **, size_t *, int64_t *); 69228773Smmstatic int _archive_read_free(struct archive *); 70232153Smmstatic int _archive_read_next_header(struct archive *, 71232153Smm struct archive_entry **); 72232153Smmstatic int _archive_read_next_header2(struct archive *, 73232153Smm struct archive_entry *); 74232153Smmstatic int64_t advance_file_pointer(struct archive_read_filter *, int64_t); 75228753Smm 76228753Smmstatic struct archive_vtable * 77228753Smmarchive_read_vtable(void) 78228753Smm{ 79228753Smm static struct archive_vtable av; 80228753Smm static int inited = 0; 81228753Smm 82228753Smm if (!inited) { 83232153Smm av.archive_filter_bytes = _archive_filter_bytes; 84232153Smm av.archive_filter_code = _archive_filter_code; 85232153Smm av.archive_filter_name = _archive_filter_name; 86232153Smm av.archive_filter_count = _archive_filter_count; 87232153Smm av.archive_read_data_block = _archive_read_data_block; 88232153Smm av.archive_read_next_header = _archive_read_next_header; 89232153Smm av.archive_read_next_header2 = _archive_read_next_header2; 90228773Smm av.archive_free = _archive_read_free; 91228753Smm av.archive_close = _archive_read_close; 92232153Smm inited = 1; 93228753Smm } 94228753Smm return (&av); 95228753Smm} 96228753Smm 97228753Smm/* 98228753Smm * Allocate, initialize and return a struct archive object. 99228753Smm */ 100228753Smmstruct archive * 101228753Smmarchive_read_new(void) 102228753Smm{ 103228753Smm struct archive_read *a; 104228753Smm 105299529Smm a = (struct archive_read *)calloc(1, sizeof(*a)); 106228753Smm if (a == NULL) 107228753Smm return (NULL); 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 114299529Smm a->passphrases.last = &a->passphrases.first; 115299529Smm 116228753Smm return (&a->archive); 117228753Smm} 118228753Smm 119228753Smm/* 120228753Smm * Record the do-not-extract-to file. This belongs in archive_read_extract.c. 121228753Smm */ 122228753Smmvoid 123328827Smmarchive_read_extract_set_skip_file(struct archive *_a, la_int64_t d, 124328827Smm la_int64_t i) 125228753Smm{ 126228753Smm struct archive_read *a = (struct archive_read *)_a; 127232153Smm 128232153Smm if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC, 129232153Smm ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file")) 130232153Smm return; 131232153Smm a->skip_file_set = 1; 132228753Smm a->skip_file_dev = d; 133228753Smm a->skip_file_ino = i; 134228753Smm} 135228753Smm 136228753Smm/* 137232153Smm * Open the archive 138228753Smm */ 139228753Smmint 140232153Smmarchive_read_open(struct archive *a, void *client_data, 141232153Smm archive_open_callback *client_opener, archive_read_callback *client_reader, 142232153Smm archive_close_callback *client_closer) 143228753Smm{ 144232153Smm /* Old archive_read_open() is just a thin shell around 145232153Smm * archive_read_open1. */ 146232153Smm archive_read_set_open_callback(a, client_opener); 147232153Smm archive_read_set_read_callback(a, client_reader); 148232153Smm archive_read_set_close_callback(a, client_closer); 149232153Smm archive_read_set_callback_data(a, client_data); 150232153Smm return archive_read_open1(a); 151228753Smm} 152228753Smm 153228753Smm 154228753Smmint 155232153Smmarchive_read_open2(struct archive *a, void *client_data, 156232153Smm archive_open_callback *client_opener, 157232153Smm archive_read_callback *client_reader, 158232153Smm archive_skip_callback *client_skipper, 159228753Smm archive_close_callback *client_closer) 160228753Smm{ 161232153Smm /* Old archive_read_open2() is just a thin shell around 162232153Smm * archive_read_open1. */ 163232153Smm archive_read_set_callback_data(a, client_data); 164232153Smm archive_read_set_open_callback(a, client_opener); 165232153Smm archive_read_set_read_callback(a, client_reader); 166232153Smm archive_read_set_skip_callback(a, client_skipper); 167232153Smm archive_read_set_close_callback(a, client_closer); 168232153Smm return archive_read_open1(a); 169228753Smm} 170228753Smm 171228753Smmstatic ssize_t 172228753Smmclient_read_proxy(struct archive_read_filter *self, const void **buff) 173228753Smm{ 174228753Smm ssize_t r; 175228753Smm r = (self->archive->client.reader)(&self->archive->archive, 176228753Smm self->data, buff); 177228753Smm return (r); 178228753Smm} 179228753Smm 180228753Smmstatic int64_t 181228753Smmclient_skip_proxy(struct archive_read_filter *self, int64_t request) 182228753Smm{ 183232153Smm if (request < 0) 184232153Smm __archive_errx(1, "Negative skip requested."); 185232153Smm if (request == 0) 186232153Smm return 0; 187228753Smm 188232153Smm if (self->archive->client.skipper != NULL) { 189232153Smm /* Seek requests over 1GiB are broken down into 190232153Smm * multiple seeks. This avoids overflows when the 191232153Smm * requests get passed through 32-bit arguments. */ 192232153Smm int64_t skip_limit = (int64_t)1 << 30; 193232153Smm int64_t total = 0; 194232153Smm for (;;) { 195232153Smm int64_t get, ask = request; 196232153Smm if (ask > skip_limit) 197232153Smm ask = skip_limit; 198248616Smm get = (self->archive->client.skipper) 199248616Smm (&self->archive->archive, self->data, ask); 200299529Smm total += get; 201299529Smm if (get == 0 || get == request) 202232153Smm return (total); 203299529Smm if (get > request) 204299529Smm return ARCHIVE_FATAL; 205232153Smm request -= get; 206232153Smm } 207232153Smm } else if (self->archive->client.seeker != NULL 208232153Smm && request > 64 * 1024) { 209232153Smm /* If the client provided a seeker but not a skipper, 210232153Smm * we can use the seeker to skip forward. 211232153Smm * 212232153Smm * Note: This isn't always a good idea. The client 213232153Smm * skipper is allowed to skip by less than requested 214232153Smm * if it needs to maintain block alignment. The 215232153Smm * seeker is not allowed to play such games, so using 216232153Smm * the seeker here may be a performance loss compared 217232153Smm * to just reading and discarding. That's why we 218232153Smm * only do this for skips of over 64k. 219232153Smm */ 220232153Smm int64_t before = self->position; 221248616Smm int64_t after = (self->archive->client.seeker) 222248616Smm (&self->archive->archive, self->data, request, SEEK_CUR); 223232153Smm if (after != before + request) 224232153Smm return ARCHIVE_FATAL; 225232153Smm return after - before; 226228753Smm } 227232153Smm return 0; 228228753Smm} 229228753Smm 230232153Smmstatic int64_t 231232153Smmclient_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence) 232232153Smm{ 233232153Smm /* DO NOT use the skipper here! If we transparently handled 234232153Smm * forward seek here by using the skipper, that will break 235232153Smm * other libarchive code that assumes a successful forward 236232153Smm * seek means it can also seek backwards. 237232153Smm */ 238299529Smm if (self->archive->client.seeker == NULL) { 239299529Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 240299529Smm "Current client reader does not support seeking a device"); 241232153Smm return (ARCHIVE_FAILED); 242299529Smm } 243232153Smm return (self->archive->client.seeker)(&self->archive->archive, 244232153Smm self->data, offset, whence); 245232153Smm} 246232153Smm 247228753Smmstatic int 248228753Smmclient_close_proxy(struct archive_read_filter *self) 249228753Smm{ 250248616Smm int r = ARCHIVE_OK, r2; 251248616Smm unsigned int i; 252228753Smm 253248616Smm if (self->archive->client.closer == NULL) 254248616Smm return (r); 255248616Smm for (i = 0; i < self->archive->client.nodes; i++) 256248616Smm { 257248616Smm r2 = (self->archive->client.closer) 258248616Smm ((struct archive *)self->archive, 259248616Smm self->archive->client.dataset[i].data); 260248616Smm if (r > r2) 261248616Smm r = r2; 262248616Smm } 263228753Smm return (r); 264228753Smm} 265228753Smm 266248616Smmstatic int 267248616Smmclient_open_proxy(struct archive_read_filter *self) 268248616Smm{ 269248616Smm int r = ARCHIVE_OK; 270248616Smm if (self->archive->client.opener != NULL) 271248616Smm r = (self->archive->client.opener)( 272248616Smm (struct archive *)self->archive, self->data); 273248616Smm return (r); 274248616Smm} 275248616Smm 276248616Smmstatic int 277248616Smmclient_switch_proxy(struct archive_read_filter *self, unsigned int iindex) 278248616Smm{ 279248616Smm int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; 280248616Smm void *data2 = NULL; 281248616Smm 282248616Smm /* Don't do anything if already in the specified data node */ 283248616Smm if (self->archive->client.cursor == iindex) 284248616Smm return (ARCHIVE_OK); 285248616Smm 286248616Smm self->archive->client.cursor = iindex; 287248616Smm data2 = self->archive->client.dataset[self->archive->client.cursor].data; 288248616Smm if (self->archive->client.switcher != NULL) 289248616Smm { 290248616Smm r1 = r2 = (self->archive->client.switcher) 291248616Smm ((struct archive *)self->archive, self->data, data2); 292248616Smm self->data = data2; 293248616Smm } 294248616Smm else 295248616Smm { 296248616Smm /* Attempt to call close and open instead */ 297248616Smm if (self->archive->client.closer != NULL) 298248616Smm r1 = (self->archive->client.closer) 299248616Smm ((struct archive *)self->archive, self->data); 300248616Smm self->data = data2; 301248616Smm if (self->archive->client.opener != NULL) 302248616Smm r2 = (self->archive->client.opener) 303248616Smm ((struct archive *)self->archive, self->data); 304248616Smm } 305248616Smm return (r1 < r2) ? r1 : r2; 306248616Smm} 307248616Smm 308232153Smmint 309232153Smmarchive_read_set_open_callback(struct archive *_a, 310232153Smm archive_open_callback *client_opener) 311232153Smm{ 312232153Smm struct archive_read *a = (struct archive_read *)_a; 313232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 314232153Smm "archive_read_set_open_callback"); 315232153Smm a->client.opener = client_opener; 316232153Smm return ARCHIVE_OK; 317232153Smm} 318228753Smm 319228753Smmint 320232153Smmarchive_read_set_read_callback(struct archive *_a, 321232153Smm archive_read_callback *client_reader) 322232153Smm{ 323232153Smm struct archive_read *a = (struct archive_read *)_a; 324232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 325232153Smm "archive_read_set_read_callback"); 326232153Smm a->client.reader = client_reader; 327232153Smm return ARCHIVE_OK; 328232153Smm} 329232153Smm 330232153Smmint 331232153Smmarchive_read_set_skip_callback(struct archive *_a, 332232153Smm archive_skip_callback *client_skipper) 333232153Smm{ 334232153Smm struct archive_read *a = (struct archive_read *)_a; 335232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 336232153Smm "archive_read_set_skip_callback"); 337232153Smm a->client.skipper = client_skipper; 338232153Smm return ARCHIVE_OK; 339232153Smm} 340232153Smm 341232153Smmint 342232153Smmarchive_read_set_seek_callback(struct archive *_a, 343232153Smm archive_seek_callback *client_seeker) 344232153Smm{ 345232153Smm struct archive_read *a = (struct archive_read *)_a; 346232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 347232153Smm "archive_read_set_seek_callback"); 348232153Smm a->client.seeker = client_seeker; 349232153Smm return ARCHIVE_OK; 350232153Smm} 351232153Smm 352232153Smmint 353232153Smmarchive_read_set_close_callback(struct archive *_a, 354228753Smm archive_close_callback *client_closer) 355228753Smm{ 356228753Smm struct archive_read *a = (struct archive_read *)_a; 357232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 358232153Smm "archive_read_set_close_callback"); 359232153Smm a->client.closer = client_closer; 360232153Smm return ARCHIVE_OK; 361232153Smm} 362232153Smm 363232153Smmint 364248616Smmarchive_read_set_switch_callback(struct archive *_a, 365248616Smm archive_switch_callback *client_switcher) 366248616Smm{ 367248616Smm struct archive_read *a = (struct archive_read *)_a; 368248616Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 369248616Smm "archive_read_set_switch_callback"); 370248616Smm a->client.switcher = client_switcher; 371248616Smm return ARCHIVE_OK; 372248616Smm} 373248616Smm 374248616Smmint 375232153Smmarchive_read_set_callback_data(struct archive *_a, void *client_data) 376232153Smm{ 377248616Smm return archive_read_set_callback_data2(_a, client_data, 0); 378248616Smm} 379248616Smm 380248616Smmint 381248616Smmarchive_read_set_callback_data2(struct archive *_a, void *client_data, 382248616Smm unsigned int iindex) 383248616Smm{ 384232153Smm struct archive_read *a = (struct archive_read *)_a; 385232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 386248616Smm "archive_read_set_callback_data2"); 387248616Smm 388248616Smm if (a->client.nodes == 0) 389248616Smm { 390248616Smm a->client.dataset = (struct archive_read_data_node *) 391248616Smm calloc(1, sizeof(*a->client.dataset)); 392248616Smm if (a->client.dataset == NULL) 393248616Smm { 394248616Smm archive_set_error(&a->archive, ENOMEM, 395248616Smm "No memory."); 396248616Smm return ARCHIVE_FATAL; 397248616Smm } 398248616Smm a->client.nodes = 1; 399248616Smm } 400248616Smm 401248616Smm if (iindex > a->client.nodes - 1) 402248616Smm { 403248616Smm archive_set_error(&a->archive, EINVAL, 404248616Smm "Invalid index specified."); 405248616Smm return ARCHIVE_FATAL; 406248616Smm } 407248616Smm a->client.dataset[iindex].data = client_data; 408248616Smm a->client.dataset[iindex].begin_position = -1; 409248616Smm a->client.dataset[iindex].total_size = -1; 410232153Smm return ARCHIVE_OK; 411232153Smm} 412232153Smm 413232153Smmint 414248616Smmarchive_read_add_callback_data(struct archive *_a, void *client_data, 415248616Smm unsigned int iindex) 416248616Smm{ 417248616Smm struct archive_read *a = (struct archive_read *)_a; 418248616Smm void *p; 419248616Smm unsigned int i; 420248616Smm 421248616Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 422248616Smm "archive_read_add_callback_data"); 423248616Smm if (iindex > a->client.nodes) { 424248616Smm archive_set_error(&a->archive, EINVAL, 425248616Smm "Invalid index specified."); 426248616Smm return ARCHIVE_FATAL; 427248616Smm } 428248616Smm p = realloc(a->client.dataset, sizeof(*a->client.dataset) 429248616Smm * (++(a->client.nodes))); 430248616Smm if (p == NULL) { 431248616Smm archive_set_error(&a->archive, ENOMEM, 432248616Smm "No memory."); 433248616Smm return ARCHIVE_FATAL; 434248616Smm } 435248616Smm a->client.dataset = (struct archive_read_data_node *)p; 436358088Smm for (i = a->client.nodes - 1; i > iindex; i--) { 437248616Smm a->client.dataset[i].data = a->client.dataset[i-1].data; 438248616Smm a->client.dataset[i].begin_position = -1; 439248616Smm a->client.dataset[i].total_size = -1; 440248616Smm } 441248616Smm a->client.dataset[iindex].data = client_data; 442248616Smm a->client.dataset[iindex].begin_position = -1; 443248616Smm a->client.dataset[iindex].total_size = -1; 444248616Smm return ARCHIVE_OK; 445248616Smm} 446248616Smm 447248616Smmint 448248616Smmarchive_read_append_callback_data(struct archive *_a, void *client_data) 449248616Smm{ 450248616Smm struct archive_read *a = (struct archive_read *)_a; 451248616Smm return archive_read_add_callback_data(_a, client_data, a->client.nodes); 452248616Smm} 453248616Smm 454248616Smmint 455248616Smmarchive_read_prepend_callback_data(struct archive *_a, void *client_data) 456248616Smm{ 457248616Smm return archive_read_add_callback_data(_a, client_data, 0); 458248616Smm} 459248616Smm 460248616Smmint 461232153Smmarchive_read_open1(struct archive *_a) 462232153Smm{ 463232153Smm struct archive_read *a = (struct archive_read *)_a; 464248616Smm struct archive_read_filter *filter, *tmp; 465299529Smm int slot, e = ARCHIVE_OK; 466248616Smm unsigned int i; 467228753Smm 468232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 469228753Smm "archive_read_open"); 470228753Smm archive_clear_error(&a->archive); 471228753Smm 472232153Smm if (a->client.reader == NULL) { 473232153Smm archive_set_error(&a->archive, EINVAL, 474228753Smm "No reader function provided to archive_read_open"); 475232153Smm a->archive.state = ARCHIVE_STATE_FATAL; 476232153Smm return (ARCHIVE_FATAL); 477232153Smm } 478228753Smm 479228753Smm /* Open data source. */ 480232153Smm if (a->client.opener != NULL) { 481248616Smm e = (a->client.opener)(&a->archive, a->client.dataset[0].data); 482228753Smm if (e != 0) { 483228753Smm /* If the open failed, call the closer to clean up. */ 484248616Smm if (a->client.closer) { 485248616Smm for (i = 0; i < a->client.nodes; i++) 486248616Smm (a->client.closer)(&a->archive, 487248616Smm a->client.dataset[i].data); 488248616Smm } 489228753Smm return (e); 490228753Smm } 491228753Smm } 492228753Smm 493228753Smm filter = calloc(1, sizeof(*filter)); 494228753Smm if (filter == NULL) 495228753Smm return (ARCHIVE_FATAL); 496228753Smm filter->bidder = NULL; 497228753Smm filter->upstream = NULL; 498228753Smm filter->archive = a; 499248616Smm filter->data = a->client.dataset[0].data; 500248616Smm filter->open = client_open_proxy; 501228753Smm filter->read = client_read_proxy; 502228753Smm filter->skip = client_skip_proxy; 503232153Smm filter->seek = client_seek_proxy; 504228753Smm filter->close = client_close_proxy; 505248616Smm filter->sswitch = client_switch_proxy; 506228753Smm filter->name = "none"; 507248616Smm filter->code = ARCHIVE_FILTER_NONE; 508228753Smm 509248616Smm a->client.dataset[0].begin_position = 0; 510248616Smm if (!a->filter || !a->bypass_filter_bidding) 511248616Smm { 512248616Smm a->filter = filter; 513248616Smm /* Build out the input pipeline. */ 514248616Smm e = choose_filters(a); 515248616Smm if (e < ARCHIVE_WARN) { 516248616Smm a->archive.state = ARCHIVE_STATE_FATAL; 517248616Smm return (ARCHIVE_FATAL); 518248616Smm } 519232153Smm } 520248616Smm else 521248616Smm { 522248616Smm /* Need to add "NONE" type filter at the end of the filter chain */ 523248616Smm tmp = a->filter; 524248616Smm while (tmp->upstream) 525248616Smm tmp = tmp->upstream; 526248616Smm tmp->upstream = filter; 527248616Smm } 528228753Smm 529248616Smm if (!a->format) 530248616Smm { 531248616Smm slot = choose_format(a); 532248616Smm if (slot < 0) { 533311041Smm close_filters(a); 534248616Smm a->archive.state = ARCHIVE_STATE_FATAL; 535248616Smm return (ARCHIVE_FATAL); 536248616Smm } 537248616Smm a->format = &(a->formats[slot]); 538232153Smm } 539232153Smm 540232153Smm a->archive.state = ARCHIVE_STATE_HEADER; 541248616Smm 542248616Smm /* Ensure libarchive starts from the first node in a multivolume set */ 543248616Smm client_switch_proxy(a->filter, 0); 544228753Smm return (e); 545228753Smm} 546228753Smm 547228753Smm/* 548228753Smm * Allow each registered stream transform to bid on whether 549228753Smm * it wants to handle this stream. Repeat until we've finished 550228753Smm * building the pipeline. 551228753Smm */ 552299529Smm 553299529Smm/* We won't build a filter pipeline with more stages than this. */ 554299529Smm#define MAX_NUMBER_FILTERS 25 555299529Smm 556228753Smmstatic int 557232153Smmchoose_filters(struct archive_read *a) 558228753Smm{ 559299529Smm int number_bidders, i, bid, best_bid, number_filters; 560228753Smm struct archive_read_filter_bidder *bidder, *best_bidder; 561228753Smm struct archive_read_filter *filter; 562228753Smm ssize_t avail; 563228753Smm int r; 564228753Smm 565299529Smm for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) { 566228753Smm number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 567228753Smm 568228753Smm best_bid = 0; 569228753Smm best_bidder = NULL; 570228753Smm 571228753Smm bidder = a->bidders; 572228753Smm for (i = 0; i < number_bidders; i++, bidder++) { 573228753Smm if (bidder->bid != NULL) { 574228753Smm bid = (bidder->bid)(bidder, a->filter); 575228753Smm if (bid > best_bid) { 576228753Smm best_bid = bid; 577228753Smm best_bidder = bidder; 578228753Smm } 579228753Smm } 580228753Smm } 581228753Smm 582228753Smm /* If no bidder, we're done. */ 583228753Smm if (best_bidder == NULL) { 584232153Smm /* Verify the filter by asking it for some data. */ 585228753Smm __archive_read_filter_ahead(a->filter, 1, &avail); 586228753Smm if (avail < 0) { 587248616Smm __archive_read_free_filters(a); 588228753Smm return (ARCHIVE_FATAL); 589228753Smm } 590228753Smm a->archive.compression_name = a->filter->name; 591228753Smm a->archive.compression_code = a->filter->code; 592228753Smm return (ARCHIVE_OK); 593228753Smm } 594228753Smm 595228753Smm filter 596228753Smm = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 597228753Smm if (filter == NULL) 598228753Smm return (ARCHIVE_FATAL); 599228753Smm filter->bidder = best_bidder; 600228753Smm filter->archive = a; 601228753Smm filter->upstream = a->filter; 602228753Smm a->filter = filter; 603228753Smm r = (best_bidder->init)(a->filter); 604228753Smm if (r != ARCHIVE_OK) { 605248616Smm __archive_read_free_filters(a); 606232153Smm return (ARCHIVE_FATAL); 607228753Smm } 608228753Smm } 609295914Sdelphij archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 610295914Sdelphij "Input requires too many filters for decoding"); 611295914Sdelphij return (ARCHIVE_FATAL); 612228753Smm} 613228753Smm 614348607Smmint 615348607Smm__archive_read_header(struct archive_read *a, struct archive_entry *entry) 616348607Smm{ 617348607Smm if (a->filter->read_header) 618348607Smm return a->filter->read_header(a->filter, entry); 619348607Smm else 620348607Smm return (ARCHIVE_OK); 621348607Smm} 622348607Smm 623228753Smm/* 624228753Smm * Read header of next entry. 625228753Smm */ 626232153Smmstatic int 627232153Smm_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) 628228753Smm{ 629228753Smm struct archive_read *a = (struct archive_read *)_a; 630232153Smm int r1 = ARCHIVE_OK, r2; 631228753Smm 632232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 633228753Smm ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 634228753Smm "archive_read_next_header"); 635228753Smm 636228753Smm archive_entry_clear(entry); 637228753Smm archive_clear_error(&a->archive); 638228753Smm 639228753Smm /* 640228753Smm * If client didn't consume entire data, skip any remainder 641228753Smm * (This is especially important for GNU incremental directories.) 642228753Smm */ 643228753Smm if (a->archive.state == ARCHIVE_STATE_DATA) { 644232153Smm r1 = archive_read_data_skip(&a->archive); 645232153Smm if (r1 == ARCHIVE_EOF) 646232153Smm archive_set_error(&a->archive, EIO, 647232153Smm "Premature end-of-file."); 648232153Smm if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) { 649228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 650228753Smm return (ARCHIVE_FATAL); 651228753Smm } 652228753Smm } 653228753Smm 654232153Smm /* Record start-of-header offset in uncompressed stream. */ 655232153Smm a->header_position = a->filter->position; 656228753Smm 657232153Smm ++_a->file_count; 658232153Smm r2 = (a->format->read_header)(a, entry); 659228753Smm 660228753Smm /* 661228753Smm * EOF and FATAL are persistent at this layer. By 662228753Smm * modifying the state, we guarantee that future calls to 663228753Smm * read a header or read data will fail. 664228753Smm */ 665232153Smm switch (r2) { 666228753Smm case ARCHIVE_EOF: 667228753Smm a->archive.state = ARCHIVE_STATE_EOF; 668232153Smm --_a->file_count;/* Revert a file counter. */ 669228753Smm break; 670228753Smm case ARCHIVE_OK: 671228753Smm a->archive.state = ARCHIVE_STATE_DATA; 672228753Smm break; 673228753Smm case ARCHIVE_WARN: 674228753Smm a->archive.state = ARCHIVE_STATE_DATA; 675228753Smm break; 676228753Smm case ARCHIVE_RETRY: 677228753Smm break; 678228753Smm case ARCHIVE_FATAL: 679228753Smm a->archive.state = ARCHIVE_STATE_FATAL; 680228753Smm break; 681228753Smm } 682228753Smm 683299529Smm __archive_reset_read_data(&a->archive); 684299529Smm 685248616Smm a->data_start_node = a->client.cursor; 686232153Smm /* EOF always wins; otherwise return the worst error. */ 687232153Smm return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1; 688228753Smm} 689228753Smm 690299529Smmstatic int 691232153Smm_archive_read_next_header(struct archive *_a, struct archive_entry **entryp) 692228753Smm{ 693228753Smm int ret; 694228753Smm struct archive_read *a = (struct archive_read *)_a; 695228753Smm *entryp = NULL; 696232153Smm ret = _archive_read_next_header2(_a, a->entry); 697228753Smm *entryp = a->entry; 698228753Smm return ret; 699228753Smm} 700228753Smm 701228753Smm/* 702228753Smm * Allow each registered format to bid on whether it wants to handle 703228753Smm * the next entry. Return index of winning bidder. 704228753Smm */ 705228753Smmstatic int 706228753Smmchoose_format(struct archive_read *a) 707228753Smm{ 708228753Smm int slots; 709228753Smm int i; 710228753Smm int bid, best_bid; 711228753Smm int best_bid_slot; 712228753Smm 713228753Smm slots = sizeof(a->formats) / sizeof(a->formats[0]); 714228753Smm best_bid = -1; 715228753Smm best_bid_slot = -1; 716228753Smm 717232153Smm /* Set up a->format for convenience of bidders. */ 718228753Smm a->format = &(a->formats[0]); 719228753Smm for (i = 0; i < slots; i++, a->format++) { 720228753Smm if (a->format->bid) { 721232153Smm bid = (a->format->bid)(a, best_bid); 722228753Smm if (bid == ARCHIVE_FATAL) 723228753Smm return (ARCHIVE_FATAL); 724232153Smm if (a->filter->position != 0) 725232153Smm __archive_read_seek(a, 0, SEEK_SET); 726228753Smm if ((bid > best_bid) || (best_bid_slot < 0)) { 727228753Smm best_bid = bid; 728228753Smm best_bid_slot = i; 729228753Smm } 730228753Smm } 731228753Smm } 732228753Smm 733228753Smm /* 734228753Smm * There were no bidders; this is a serious programmer error 735228753Smm * and demands a quick and definitive abort. 736228753Smm */ 737232153Smm if (best_bid_slot < 0) { 738232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 739232153Smm "No formats registered"); 740232153Smm return (ARCHIVE_FATAL); 741232153Smm } 742228753Smm 743228753Smm /* 744228753Smm * There were bidders, but no non-zero bids; this means we 745228753Smm * can't support this stream. 746228753Smm */ 747228753Smm if (best_bid < 1) { 748228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 749228753Smm "Unrecognized archive format"); 750228753Smm return (ARCHIVE_FATAL); 751228753Smm } 752228753Smm 753228753Smm return (best_bid_slot); 754228753Smm} 755228753Smm 756228753Smm/* 757228753Smm * Return the file offset (within the uncompressed data stream) where 758228753Smm * the last header started. 759228753Smm */ 760328827Smmla_int64_t 761228753Smmarchive_read_header_position(struct archive *_a) 762228753Smm{ 763228753Smm struct archive_read *a = (struct archive_read *)_a; 764232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 765228753Smm ARCHIVE_STATE_ANY, "archive_read_header_position"); 766228753Smm return (a->header_position); 767228753Smm} 768228753Smm 769228753Smm/* 770299529Smm * Returns 1 if the archive contains at least one encrypted entry. 771299529Smm * If the archive format not support encryption at all 772299529Smm * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. 773299529Smm * If for any other reason (e.g. not enough data read so far) 774299529Smm * we cannot say whether there are encrypted entries, then 775299529Smm * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. 776299529Smm * In general, this function will return values below zero when the 777311041Smm * reader is uncertain or totally incapable of encryption support. 778299529Smm * When this function returns 0 you can be sure that the reader 779299529Smm * supports encryption detection but no encrypted entries have 780299529Smm * been found yet. 781299529Smm * 782299529Smm * NOTE: If the metadata/header of an archive is also encrypted, you 783299529Smm * cannot rely on the number of encrypted entries. That is why this 784299529Smm * function does not return the number of encrypted entries but# 785299529Smm * just shows that there are some. 786299529Smm */ 787299529Smmint 788299529Smmarchive_read_has_encrypted_entries(struct archive *_a) 789299529Smm{ 790299529Smm struct archive_read *a = (struct archive_read *)_a; 791299529Smm int format_supports_encryption = archive_read_format_capabilities(_a) 792299529Smm & (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); 793299529Smm 794299529Smm if (!_a || !format_supports_encryption) { 795299529Smm /* Format in general doesn't support encryption */ 796299529Smm return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED; 797299529Smm } 798299529Smm 799299529Smm /* A reader potentially has read enough data now. */ 800299529Smm if (a->format && a->format->has_encrypted_entries) { 801299529Smm return (a->format->has_encrypted_entries)(a); 802299529Smm } 803299529Smm 804299529Smm /* For any other reason we cannot say how many entries are there. */ 805299529Smm return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; 806299529Smm} 807299529Smm 808299529Smm/* 809299529Smm * Returns a bitmask of capabilities that are supported by the archive format reader. 810299529Smm * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. 811299529Smm */ 812299529Smmint 813299529Smmarchive_read_format_capabilities(struct archive *_a) 814299529Smm{ 815299529Smm struct archive_read *a = (struct archive_read *)_a; 816299529Smm if (a && a->format && a->format->format_capabilties) { 817299529Smm return (a->format->format_capabilties)(a); 818299529Smm } 819299529Smm return ARCHIVE_READ_FORMAT_CAPS_NONE; 820299529Smm} 821299529Smm 822299529Smm/* 823228753Smm * Read data from an archive entry, using a read(2)-style interface. 824228753Smm * This is a convenience routine that just calls 825228753Smm * archive_read_data_block and copies the results into the client 826228753Smm * buffer, filling any gaps with zero bytes. Clients using this 827228753Smm * API can be completely ignorant of sparse-file issues; sparse files 828228753Smm * will simply be padded with nulls. 829228753Smm * 830228753Smm * DO NOT intermingle calls to this function and archive_read_data_block 831228753Smm * to read a single entry body. 832228753Smm */ 833337351Smmla_ssize_t 834228753Smmarchive_read_data(struct archive *_a, void *buff, size_t s) 835228753Smm{ 836299529Smm struct archive *a = (struct archive *)_a; 837228753Smm char *dest; 838228753Smm const void *read_buf; 839228753Smm size_t bytes_read; 840228753Smm size_t len; 841228753Smm int r; 842228753Smm 843228753Smm bytes_read = 0; 844228753Smm dest = (char *)buff; 845228753Smm 846228753Smm while (s > 0) { 847349900Smm if (a->read_data_offset == a->read_data_output_offset && 848349900Smm a->read_data_remaining == 0) { 849228753Smm read_buf = a->read_data_block; 850248616Smm a->read_data_is_posix_read = 1; 851248616Smm a->read_data_requested = s; 852299529Smm r = archive_read_data_block(a, &read_buf, 853228753Smm &a->read_data_remaining, &a->read_data_offset); 854228753Smm a->read_data_block = read_buf; 855228753Smm if (r == ARCHIVE_EOF) 856228753Smm return (bytes_read); 857228753Smm /* 858228753Smm * Error codes are all negative, so the status 859228753Smm * return here cannot be confused with a valid 860228753Smm * byte count. (ARCHIVE_OK is zero.) 861228753Smm */ 862228753Smm if (r < ARCHIVE_OK) 863228753Smm return (r); 864228753Smm } 865228753Smm 866228753Smm if (a->read_data_offset < a->read_data_output_offset) { 867299529Smm archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, 868228753Smm "Encountered out-of-order sparse blocks"); 869228753Smm return (ARCHIVE_RETRY); 870228753Smm } 871228753Smm 872228753Smm /* Compute the amount of zero padding needed. */ 873232153Smm if (a->read_data_output_offset + (int64_t)s < 874228753Smm a->read_data_offset) { 875228753Smm len = s; 876228753Smm } else if (a->read_data_output_offset < 877228753Smm a->read_data_offset) { 878238856Smm len = (size_t)(a->read_data_offset - 879238856Smm a->read_data_output_offset); 880228753Smm } else 881228753Smm len = 0; 882228753Smm 883228753Smm /* Add zeroes. */ 884228753Smm memset(dest, 0, len); 885228753Smm s -= len; 886228753Smm a->read_data_output_offset += len; 887228753Smm dest += len; 888228753Smm bytes_read += len; 889228753Smm 890228753Smm /* Copy data if there is any space left. */ 891228753Smm if (s > 0) { 892228753Smm len = a->read_data_remaining; 893228753Smm if (len > s) 894228753Smm len = s; 895358926Smm if (len) { 896318482Smm memcpy(dest, a->read_data_block, len); 897358926Smm s -= len; 898358926Smm a->read_data_block += len; 899358926Smm a->read_data_remaining -= len; 900358926Smm a->read_data_output_offset += len; 901358926Smm a->read_data_offset += len; 902358926Smm dest += len; 903358926Smm bytes_read += len; 904358926Smm } 905228753Smm } 906228753Smm } 907248616Smm a->read_data_is_posix_read = 0; 908248616Smm a->read_data_requested = 0; 909228753Smm return (bytes_read); 910228753Smm} 911228753Smm 912228753Smm/* 913299529Smm * Reset the read_data_* variables, used for starting a new entry. 914299529Smm */ 915299529Smmvoid __archive_reset_read_data(struct archive * a) 916299529Smm{ 917299529Smm a->read_data_output_offset = 0; 918299529Smm a->read_data_remaining = 0; 919299529Smm a->read_data_is_posix_read = 0; 920299529Smm a->read_data_requested = 0; 921299529Smm 922299529Smm /* extra resets, from rar.c */ 923299529Smm a->read_data_block = NULL; 924299529Smm a->read_data_offset = 0; 925299529Smm} 926299529Smm 927299529Smm/* 928228753Smm * Skip over all remaining data in this entry. 929228753Smm */ 930228753Smmint 931228753Smmarchive_read_data_skip(struct archive *_a) 932228753Smm{ 933228753Smm struct archive_read *a = (struct archive_read *)_a; 934228753Smm int r; 935228753Smm const void *buff; 936228753Smm size_t size; 937232153Smm int64_t offset; 938228753Smm 939232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 940228753Smm "archive_read_data_skip"); 941228753Smm 942228753Smm if (a->format->read_data_skip != NULL) 943228753Smm r = (a->format->read_data_skip)(a); 944228753Smm else { 945228753Smm while ((r = archive_read_data_block(&a->archive, 946228753Smm &buff, &size, &offset)) 947228753Smm == ARCHIVE_OK) 948228753Smm ; 949228753Smm } 950228753Smm 951228753Smm if (r == ARCHIVE_EOF) 952228753Smm r = ARCHIVE_OK; 953228753Smm 954228753Smm a->archive.state = ARCHIVE_STATE_HEADER; 955228753Smm return (r); 956228753Smm} 957228753Smm 958328827Smmla_int64_t 959248616Smmarchive_seek_data(struct archive *_a, int64_t offset, int whence) 960248616Smm{ 961248616Smm struct archive_read *a = (struct archive_read *)_a; 962248616Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 963248616Smm "archive_seek_data_block"); 964248616Smm 965248616Smm if (a->format->seek_data == NULL) { 966248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 967248616Smm "Internal error: " 968248616Smm "No format_seek_data_block function registered"); 969248616Smm return (ARCHIVE_FATAL); 970248616Smm } 971248616Smm 972248616Smm return (a->format->seek_data)(a, offset, whence); 973248616Smm} 974248616Smm 975228753Smm/* 976228753Smm * Read the next block of entry data from the archive. 977228753Smm * This is a zero-copy interface; the client receives a pointer, 978228753Smm * size, and file offset of the next available block of data. 979228753Smm * 980228753Smm * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if 981228753Smm * the end of entry is encountered. 982228753Smm */ 983232153Smmstatic int 984232153Smm_archive_read_data_block(struct archive *_a, 985232153Smm const void **buff, size_t *size, int64_t *offset) 986228753Smm{ 987228753Smm struct archive_read *a = (struct archive_read *)_a; 988232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, 989228753Smm "archive_read_data_block"); 990228753Smm 991228753Smm if (a->format->read_data == NULL) { 992228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 993228753Smm "Internal error: " 994299529Smm "No format->read_data function registered"); 995228753Smm return (ARCHIVE_FATAL); 996228753Smm } 997228753Smm 998228753Smm return (a->format->read_data)(a, buff, size, offset); 999228753Smm} 1000228753Smm 1001311041Smmstatic int 1002311041Smmclose_filters(struct archive_read *a) 1003232153Smm{ 1004232153Smm struct archive_read_filter *f = a->filter; 1005232153Smm int r = ARCHIVE_OK; 1006232153Smm /* Close each filter in the pipeline. */ 1007232153Smm while (f != NULL) { 1008232153Smm struct archive_read_filter *t = f->upstream; 1009232153Smm if (!f->closed && f->close != NULL) { 1010232153Smm int r1 = (f->close)(f); 1011232153Smm f->closed = 1; 1012232153Smm if (r1 < r) 1013232153Smm r = r1; 1014232153Smm } 1015232153Smm free(f->buffer); 1016232153Smm f->buffer = NULL; 1017232153Smm f = t; 1018232153Smm } 1019232153Smm return r; 1020232153Smm} 1021232153Smm 1022248616Smmvoid 1023248616Smm__archive_read_free_filters(struct archive_read *a) 1024232153Smm{ 1025311041Smm /* Make sure filters are closed and their buffers are freed */ 1026311041Smm close_filters(a); 1027311041Smm 1028232153Smm while (a->filter != NULL) { 1029232153Smm struct archive_read_filter *t = a->filter->upstream; 1030232153Smm free(a->filter); 1031232153Smm a->filter = t; 1032232153Smm } 1033232153Smm} 1034232153Smm 1035228753Smm/* 1036232153Smm * return the count of # of filters in use 1037228753Smm */ 1038228753Smmstatic int 1039232153Smm_archive_filter_count(struct archive *_a) 1040232153Smm{ 1041232153Smm struct archive_read *a = (struct archive_read *)_a; 1042232153Smm struct archive_read_filter *p = a->filter; 1043232153Smm int count = 0; 1044232153Smm while(p) { 1045232153Smm count++; 1046232153Smm p = p->upstream; 1047232153Smm } 1048232153Smm return count; 1049232153Smm} 1050232153Smm 1051232153Smm/* 1052232153Smm * Close the file and all I/O. 1053232153Smm */ 1054232153Smmstatic int 1055228753Smm_archive_read_close(struct archive *_a) 1056228753Smm{ 1057228753Smm struct archive_read *a = (struct archive_read *)_a; 1058228753Smm int r = ARCHIVE_OK, r1 = ARCHIVE_OK; 1059228753Smm 1060232153Smm archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, 1061232153Smm ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); 1062232153Smm if (a->archive.state == ARCHIVE_STATE_CLOSED) 1063232153Smm return (ARCHIVE_OK); 1064228753Smm archive_clear_error(&a->archive); 1065228753Smm a->archive.state = ARCHIVE_STATE_CLOSED; 1066228753Smm 1067228753Smm /* TODO: Clean up the formatters. */ 1068228753Smm 1069228753Smm /* Release the filter objects. */ 1070311041Smm r1 = close_filters(a); 1071228753Smm if (r1 < r) 1072228753Smm r = r1; 1073228753Smm 1074228753Smm return (r); 1075228753Smm} 1076228753Smm 1077228753Smm/* 1078228753Smm * Release memory and other resources. 1079228753Smm */ 1080228753Smmstatic int 1081228773Smm_archive_read_free(struct archive *_a) 1082228753Smm{ 1083228753Smm struct archive_read *a = (struct archive_read *)_a; 1084299529Smm struct archive_read_passphrase *p; 1085232153Smm int i, n; 1086228753Smm int slots; 1087228753Smm int r = ARCHIVE_OK; 1088228753Smm 1089232153Smm if (_a == NULL) 1090232153Smm return (ARCHIVE_OK); 1091232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 1092232153Smm ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); 1093232153Smm if (a->archive.state != ARCHIVE_STATE_CLOSED 1094232153Smm && a->archive.state != ARCHIVE_STATE_FATAL) 1095228753Smm r = archive_read_close(&a->archive); 1096228753Smm 1097232153Smm /* Call cleanup functions registered by optional components. */ 1098232153Smm if (a->cleanup_archive_extract != NULL) 1099232153Smm r = (a->cleanup_archive_extract)(a); 1100232153Smm 1101228753Smm /* Cleanup format-specific data. */ 1102228753Smm slots = sizeof(a->formats) / sizeof(a->formats[0]); 1103228753Smm for (i = 0; i < slots; i++) { 1104228753Smm a->format = &(a->formats[i]); 1105228753Smm if (a->formats[i].cleanup) 1106228753Smm (a->formats[i].cleanup)(a); 1107228753Smm } 1108228753Smm 1109232153Smm /* Free the filters */ 1110248616Smm __archive_read_free_filters(a); 1111232153Smm 1112232153Smm /* Release the bidder objects. */ 1113232153Smm n = sizeof(a->bidders)/sizeof(a->bidders[0]); 1114232153Smm for (i = 0; i < n; i++) { 1115232153Smm if (a->bidders[i].free != NULL) { 1116232153Smm int r1 = (a->bidders[i].free)(&a->bidders[i]); 1117232153Smm if (r1 < r) 1118232153Smm r = r1; 1119232153Smm } 1120232153Smm } 1121232153Smm 1122299529Smm /* Release passphrase list. */ 1123299529Smm p = a->passphrases.first; 1124299529Smm while (p != NULL) { 1125299529Smm struct archive_read_passphrase *np = p->next; 1126299529Smm 1127299529Smm /* A passphrase should be cleaned. */ 1128299529Smm memset(p->passphrase, 0, strlen(p->passphrase)); 1129299529Smm free(p->passphrase); 1130299529Smm free(p); 1131299529Smm p = np; 1132299529Smm } 1133299529Smm 1134228753Smm archive_string_free(&a->archive.error_string); 1135299529Smm archive_entry_free(a->entry); 1136228753Smm a->archive.magic = 0; 1137232153Smm __archive_clean(&a->archive); 1138248616Smm free(a->client.dataset); 1139228753Smm free(a); 1140228753Smm return (r); 1141228753Smm} 1142228753Smm 1143232153Smmstatic struct archive_read_filter * 1144232153Smmget_filter(struct archive *_a, int n) 1145232153Smm{ 1146232153Smm struct archive_read *a = (struct archive_read *)_a; 1147232153Smm struct archive_read_filter *f = a->filter; 1148248616Smm /* We use n == -1 for 'the last filter', which is always the 1149248616Smm * client proxy. */ 1150232153Smm if (n == -1 && f != NULL) { 1151232153Smm struct archive_read_filter *last = f; 1152232153Smm f = f->upstream; 1153232153Smm while (f != NULL) { 1154232153Smm last = f; 1155232153Smm f = f->upstream; 1156232153Smm } 1157232153Smm return (last); 1158232153Smm } 1159232153Smm if (n < 0) 1160232153Smm return NULL; 1161232153Smm while (n > 0 && f != NULL) { 1162232153Smm f = f->upstream; 1163232153Smm --n; 1164232153Smm } 1165232153Smm return (f); 1166232153Smm} 1167232153Smm 1168232153Smmstatic int 1169232153Smm_archive_filter_code(struct archive *_a, int n) 1170232153Smm{ 1171232153Smm struct archive_read_filter *f = get_filter(_a, n); 1172232153Smm return f == NULL ? -1 : f->code; 1173232153Smm} 1174232153Smm 1175232153Smmstatic const char * 1176232153Smm_archive_filter_name(struct archive *_a, int n) 1177232153Smm{ 1178232153Smm struct archive_read_filter *f = get_filter(_a, n); 1179299529Smm return f != NULL ? f->name : NULL; 1180232153Smm} 1181232153Smm 1182232153Smmstatic int64_t 1183232153Smm_archive_filter_bytes(struct archive *_a, int n) 1184232153Smm{ 1185232153Smm struct archive_read_filter *f = get_filter(_a, n); 1186232153Smm return f == NULL ? -1 : f->position; 1187232153Smm} 1188232153Smm 1189228753Smm/* 1190228753Smm * Used internally by read format handlers to register their bid and 1191228753Smm * initialization functions. 1192228753Smm */ 1193228753Smmint 1194228753Smm__archive_read_register_format(struct archive_read *a, 1195228753Smm void *format_data, 1196228753Smm const char *name, 1197232153Smm int (*bid)(struct archive_read *, int), 1198228753Smm int (*options)(struct archive_read *, const char *, const char *), 1199228753Smm int (*read_header)(struct archive_read *, struct archive_entry *), 1200232153Smm int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), 1201228753Smm int (*read_data_skip)(struct archive_read *), 1202248616Smm int64_t (*seek_data)(struct archive_read *, int64_t, int), 1203299529Smm int (*cleanup)(struct archive_read *), 1204299529Smm int (*format_capabilities)(struct archive_read *), 1205299529Smm int (*has_encrypted_entries)(struct archive_read *)) 1206228753Smm{ 1207228753Smm int i, number_slots; 1208228753Smm 1209232153Smm archive_check_magic(&a->archive, 1210228753Smm ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 1211228753Smm "__archive_read_register_format"); 1212228753Smm 1213228753Smm number_slots = sizeof(a->formats) / sizeof(a->formats[0]); 1214228753Smm 1215228753Smm for (i = 0; i < number_slots; i++) { 1216228753Smm if (a->formats[i].bid == bid) 1217228753Smm return (ARCHIVE_WARN); /* We've already installed */ 1218228753Smm if (a->formats[i].bid == NULL) { 1219228753Smm a->formats[i].bid = bid; 1220228753Smm a->formats[i].options = options; 1221228753Smm a->formats[i].read_header = read_header; 1222228753Smm a->formats[i].read_data = read_data; 1223228753Smm a->formats[i].read_data_skip = read_data_skip; 1224248616Smm a->formats[i].seek_data = seek_data; 1225228753Smm a->formats[i].cleanup = cleanup; 1226228753Smm a->formats[i].data = format_data; 1227228753Smm a->formats[i].name = name; 1228299529Smm a->formats[i].format_capabilties = format_capabilities; 1229299529Smm a->formats[i].has_encrypted_entries = has_encrypted_entries; 1230228753Smm return (ARCHIVE_OK); 1231228753Smm } 1232228753Smm } 1233228753Smm 1234232153Smm archive_set_error(&a->archive, ENOMEM, 1235232153Smm "Not enough slots for format registration"); 1236232153Smm return (ARCHIVE_FATAL); 1237228753Smm} 1238228753Smm 1239228753Smm/* 1240228753Smm * Used internally by decompression routines to register their bid and 1241228753Smm * initialization functions. 1242228753Smm */ 1243232153Smmint 1244232153Smm__archive_read_get_bidder(struct archive_read *a, 1245232153Smm struct archive_read_filter_bidder **bidder) 1246228753Smm{ 1247228753Smm int i, number_slots; 1248228753Smm 1249228753Smm number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]); 1250228753Smm 1251228753Smm for (i = 0; i < number_slots; i++) { 1252228753Smm if (a->bidders[i].bid == NULL) { 1253228753Smm memset(a->bidders + i, 0, sizeof(a->bidders[0])); 1254232153Smm *bidder = (a->bidders + i); 1255232153Smm return (ARCHIVE_OK); 1256228753Smm } 1257228753Smm } 1258228753Smm 1259232153Smm archive_set_error(&a->archive, ENOMEM, 1260232153Smm "Not enough slots for filter registration"); 1261232153Smm return (ARCHIVE_FATAL); 1262228753Smm} 1263228753Smm 1264228753Smm/* 1265232153Smm * The next section implements the peek/consume internal I/O 1266232153Smm * system used by archive readers. This system allows simple 1267232153Smm * read-ahead for consumers while preserving zero-copy operation 1268232153Smm * most of the time. 1269228753Smm * 1270232153Smm * The two key operations: 1271232153Smm * * The read-ahead function returns a pointer to a block of data 1272232153Smm * that satisfies a minimum request. 1273232153Smm * * The consume function advances the file pointer. 1274232153Smm * 1275228753Smm * In the ideal case, filters generate blocks of data 1276228753Smm * and __archive_read_ahead() just returns pointers directly into 1277228753Smm * those blocks. Then __archive_read_consume() just bumps those 1278228753Smm * pointers. Only if your request would span blocks does the I/O 1279228753Smm * layer use a copy buffer to provide you with a contiguous block of 1280232153Smm * data. 1281228753Smm * 1282228753Smm * A couple of useful idioms: 1283228753Smm * * "I just want some data." Ask for 1 byte and pay attention to 1284228753Smm * the "number of bytes available" from __archive_read_ahead(). 1285232153Smm * Consume whatever you actually use. 1286228753Smm * * "I want to output a large block of data." As above, ask for 1 byte, 1287232153Smm * emit all that's available (up to whatever limit you have), consume 1288232153Smm * it all, then repeat until you're done. This effectively means that 1289232153Smm * you're passing along the blocks that came from your provider. 1290228753Smm * * "I want to peek ahead by a large amount." Ask for 4k or so, then 1291228753Smm * double and repeat until you get an error or have enough. Note 1292228753Smm * that the I/O layer will likely end up expanding its copy buffer 1293228753Smm * to fit your request, so use this technique cautiously. This 1294228753Smm * technique is used, for example, by some of the format tasting 1295228753Smm * code that has uncertain look-ahead needs. 1296228753Smm */ 1297228753Smm 1298228753Smm/* 1299228753Smm * Looks ahead in the input stream: 1300228753Smm * * If 'avail' pointer is provided, that returns number of bytes available 1301228753Smm * in the current buffer, which may be much larger than requested. 1302228753Smm * * If end-of-file, *avail gets set to zero. 1303228753Smm * * If error, *avail gets error code. 1304232153Smm * * If request can be met, returns pointer to data. 1305232153Smm * * If minimum request cannot be met, returns NULL. 1306228753Smm * 1307228753Smm * Note: If you just want "some data", ask for 1 byte and pay attention 1308228753Smm * to *avail, which will have the actual amount available. If you 1309228753Smm * know exactly how many bytes you need, just ask for that and treat 1310228753Smm * a NULL return as an error. 1311228753Smm * 1312228753Smm * Important: This does NOT move the file pointer. See 1313228753Smm * __archive_read_consume() below. 1314228753Smm */ 1315228753Smmconst void * 1316228753Smm__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) 1317228753Smm{ 1318228753Smm return (__archive_read_filter_ahead(a->filter, min, avail)); 1319228753Smm} 1320228753Smm 1321228753Smmconst void * 1322228753Smm__archive_read_filter_ahead(struct archive_read_filter *filter, 1323228753Smm size_t min, ssize_t *avail) 1324228753Smm{ 1325228753Smm ssize_t bytes_read; 1326228753Smm size_t tocopy; 1327228753Smm 1328228753Smm if (filter->fatal) { 1329228753Smm if (avail) 1330228753Smm *avail = ARCHIVE_FATAL; 1331228753Smm return (NULL); 1332228753Smm } 1333228753Smm 1334228753Smm /* 1335228753Smm * Keep pulling more data until we can satisfy the request. 1336228753Smm */ 1337228753Smm for (;;) { 1338228753Smm 1339228753Smm /* 1340228753Smm * If we can satisfy from the copy buffer (and the 1341228753Smm * copy buffer isn't empty), we're done. In particular, 1342228753Smm * note that min == 0 is a perfectly well-defined 1343228753Smm * request. 1344228753Smm */ 1345228753Smm if (filter->avail >= min && filter->avail > 0) { 1346228753Smm if (avail != NULL) 1347228753Smm *avail = filter->avail; 1348228753Smm return (filter->next); 1349228753Smm } 1350228753Smm 1351228753Smm /* 1352228753Smm * We can satisfy directly from client buffer if everything 1353228753Smm * currently in the copy buffer is still in the client buffer. 1354228753Smm */ 1355228753Smm if (filter->client_total >= filter->client_avail + filter->avail 1356228753Smm && filter->client_avail + filter->avail >= min) { 1357228753Smm /* "Roll back" to client buffer. */ 1358228753Smm filter->client_avail += filter->avail; 1359228753Smm filter->client_next -= filter->avail; 1360228753Smm /* Copy buffer is now empty. */ 1361228753Smm filter->avail = 0; 1362228753Smm filter->next = filter->buffer; 1363228753Smm /* Return data from client buffer. */ 1364228753Smm if (avail != NULL) 1365228753Smm *avail = filter->client_avail; 1366228753Smm return (filter->client_next); 1367228753Smm } 1368228753Smm 1369228753Smm /* Move data forward in copy buffer if necessary. */ 1370228753Smm if (filter->next > filter->buffer && 1371228753Smm filter->next + min > filter->buffer + filter->buffer_size) { 1372228753Smm if (filter->avail > 0) 1373248616Smm memmove(filter->buffer, filter->next, 1374248616Smm filter->avail); 1375228753Smm filter->next = filter->buffer; 1376228753Smm } 1377228753Smm 1378228753Smm /* If we've used up the client data, get more. */ 1379228753Smm if (filter->client_avail <= 0) { 1380228753Smm if (filter->end_of_file) { 1381228753Smm if (avail != NULL) 1382228753Smm *avail = 0; 1383228753Smm return (NULL); 1384228753Smm } 1385228753Smm bytes_read = (filter->read)(filter, 1386228753Smm &filter->client_buff); 1387228753Smm if (bytes_read < 0) { /* Read error. */ 1388228753Smm filter->client_total = filter->client_avail = 0; 1389248616Smm filter->client_next = 1390248616Smm filter->client_buff = NULL; 1391228753Smm filter->fatal = 1; 1392228753Smm if (avail != NULL) 1393228753Smm *avail = ARCHIVE_FATAL; 1394228753Smm return (NULL); 1395228753Smm } 1396248616Smm if (bytes_read == 0) { 1397248616Smm /* Check for another client object first */ 1398248616Smm if (filter->archive->client.cursor != 1399248616Smm filter->archive->client.nodes - 1) { 1400248616Smm if (client_switch_proxy(filter, 1401248616Smm filter->archive->client.cursor + 1) 1402248616Smm == ARCHIVE_OK) 1403248616Smm continue; 1404248616Smm } 1405248616Smm /* Premature end-of-file. */ 1406228753Smm filter->client_total = filter->client_avail = 0; 1407248616Smm filter->client_next = 1408248616Smm filter->client_buff = NULL; 1409228753Smm filter->end_of_file = 1; 1410228753Smm /* Return whatever we do have. */ 1411228753Smm if (avail != NULL) 1412228753Smm *avail = filter->avail; 1413228753Smm return (NULL); 1414228753Smm } 1415228753Smm filter->client_total = bytes_read; 1416228753Smm filter->client_avail = filter->client_total; 1417228753Smm filter->client_next = filter->client_buff; 1418248616Smm } else { 1419228753Smm /* 1420228753Smm * We can't satisfy the request from the copy 1421228753Smm * buffer or the existing client data, so we 1422228753Smm * need to copy more client data over to the 1423228753Smm * copy buffer. 1424228753Smm */ 1425228753Smm 1426228753Smm /* Ensure the buffer is big enough. */ 1427228753Smm if (min > filter->buffer_size) { 1428228753Smm size_t s, t; 1429228753Smm char *p; 1430228753Smm 1431228753Smm /* Double the buffer; watch for overflow. */ 1432228753Smm s = t = filter->buffer_size; 1433228753Smm if (s == 0) 1434228753Smm s = min; 1435228753Smm while (s < min) { 1436228753Smm t *= 2; 1437228753Smm if (t <= s) { /* Integer overflow! */ 1438228753Smm archive_set_error( 1439248616Smm &filter->archive->archive, 1440248616Smm ENOMEM, 1441248616Smm "Unable to allocate copy" 1442248616Smm " buffer"); 1443228753Smm filter->fatal = 1; 1444228753Smm if (avail != NULL) 1445228753Smm *avail = ARCHIVE_FATAL; 1446228753Smm return (NULL); 1447228753Smm } 1448228753Smm s = t; 1449228753Smm } 1450228753Smm /* Now s >= min, so allocate a new buffer. */ 1451228753Smm p = (char *)malloc(s); 1452228753Smm if (p == NULL) { 1453228753Smm archive_set_error( 1454228753Smm &filter->archive->archive, 1455228753Smm ENOMEM, 1456228753Smm "Unable to allocate copy buffer"); 1457228753Smm filter->fatal = 1; 1458228753Smm if (avail != NULL) 1459228753Smm *avail = ARCHIVE_FATAL; 1460228753Smm return (NULL); 1461228753Smm } 1462228753Smm /* Move data into newly-enlarged buffer. */ 1463228753Smm if (filter->avail > 0) 1464228753Smm memmove(p, filter->next, filter->avail); 1465228753Smm free(filter->buffer); 1466228753Smm filter->next = filter->buffer = p; 1467228753Smm filter->buffer_size = s; 1468228753Smm } 1469228753Smm 1470228753Smm /* We can add client data to copy buffer. */ 1471228753Smm /* First estimate: copy to fill rest of buffer. */ 1472228753Smm tocopy = (filter->buffer + filter->buffer_size) 1473228753Smm - (filter->next + filter->avail); 1474228753Smm /* Don't waste time buffering more than we need to. */ 1475228753Smm if (tocopy + filter->avail > min) 1476228753Smm tocopy = min - filter->avail; 1477228753Smm /* Don't copy more than is available. */ 1478228753Smm if (tocopy > filter->client_avail) 1479228753Smm tocopy = filter->client_avail; 1480228753Smm 1481248616Smm memcpy(filter->next + filter->avail, 1482248616Smm filter->client_next, tocopy); 1483228753Smm /* Remove this data from client buffer. */ 1484228753Smm filter->client_next += tocopy; 1485228753Smm filter->client_avail -= tocopy; 1486228753Smm /* add it to copy buffer. */ 1487228753Smm filter->avail += tocopy; 1488228753Smm } 1489228753Smm } 1490228753Smm} 1491228753Smm 1492228753Smm/* 1493232153Smm * Move the file pointer forward. 1494228753Smm */ 1495232153Smmint64_t 1496232153Smm__archive_read_consume(struct archive_read *a, int64_t request) 1497228753Smm{ 1498232153Smm return (__archive_read_filter_consume(a->filter, request)); 1499228753Smm} 1500228753Smm 1501232153Smmint64_t 1502228753Smm__archive_read_filter_consume(struct archive_read_filter * filter, 1503232153Smm int64_t request) 1504228753Smm{ 1505232153Smm int64_t skipped; 1506228753Smm 1507282932Sdelphij if (request < 0) 1508282932Sdelphij return ARCHIVE_FATAL; 1509232153Smm if (request == 0) 1510232153Smm return 0; 1511232153Smm 1512232153Smm skipped = advance_file_pointer(filter, request); 1513228753Smm if (skipped == request) 1514228753Smm return (skipped); 1515228753Smm /* We hit EOF before we satisfied the skip request. */ 1516232153Smm if (skipped < 0) /* Map error code to 0 for error message below. */ 1517228753Smm skipped = 0; 1518232153Smm archive_set_error(&filter->archive->archive, 1519228753Smm ARCHIVE_ERRNO_MISC, 1520228753Smm "Truncated input file (needed %jd bytes, only %jd available)", 1521228753Smm (intmax_t)request, (intmax_t)skipped); 1522228753Smm return (ARCHIVE_FATAL); 1523228753Smm} 1524228753Smm 1525232153Smm/* 1526232153Smm * Advance the file pointer by the amount requested. 1527232153Smm * Returns the amount actually advanced, which may be less than the 1528232153Smm * request if EOF is encountered first. 1529232153Smm * Returns a negative value if there's an I/O error. 1530232153Smm */ 1531232153Smmstatic int64_t 1532232153Smmadvance_file_pointer(struct archive_read_filter *filter, int64_t request) 1533228753Smm{ 1534228753Smm int64_t bytes_skipped, total_bytes_skipped = 0; 1535232153Smm ssize_t bytes_read; 1536228753Smm size_t min; 1537228753Smm 1538228753Smm if (filter->fatal) 1539228753Smm return (-1); 1540232153Smm 1541232153Smm /* Use up the copy buffer first. */ 1542228753Smm if (filter->avail > 0) { 1543238856Smm min = (size_t)minimum(request, (int64_t)filter->avail); 1544232153Smm filter->next += min; 1545232153Smm filter->avail -= min; 1546232153Smm request -= min; 1547232153Smm filter->position += min; 1548232153Smm total_bytes_skipped += min; 1549228753Smm } 1550232153Smm 1551232153Smm /* Then use up the client buffer. */ 1552228753Smm if (filter->client_avail > 0) { 1553238856Smm min = (size_t)minimum(request, (int64_t)filter->client_avail); 1554232153Smm filter->client_next += min; 1555232153Smm filter->client_avail -= min; 1556232153Smm request -= min; 1557232153Smm filter->position += min; 1558232153Smm total_bytes_skipped += min; 1559228753Smm } 1560228753Smm if (request == 0) 1561228753Smm return (total_bytes_skipped); 1562232153Smm 1563232153Smm /* If there's an optimized skip function, use it. */ 1564228753Smm if (filter->skip != NULL) { 1565228753Smm bytes_skipped = (filter->skip)(filter, request); 1566228753Smm if (bytes_skipped < 0) { /* error */ 1567228753Smm filter->fatal = 1; 1568228753Smm return (bytes_skipped); 1569228753Smm } 1570232153Smm filter->position += bytes_skipped; 1571228753Smm total_bytes_skipped += bytes_skipped; 1572228753Smm request -= bytes_skipped; 1573232153Smm if (request == 0) 1574232153Smm return (total_bytes_skipped); 1575228753Smm } 1576232153Smm 1577232153Smm /* Use ordinary reads as necessary to complete the request. */ 1578232153Smm for (;;) { 1579232153Smm bytes_read = (filter->read)(filter, &filter->client_buff); 1580232153Smm if (bytes_read < 0) { 1581232153Smm filter->client_buff = NULL; 1582232153Smm filter->fatal = 1; 1583228753Smm return (bytes_read); 1584232153Smm } 1585232153Smm 1586228753Smm if (bytes_read == 0) { 1587248616Smm if (filter->archive->client.cursor != 1588248616Smm filter->archive->client.nodes - 1) { 1589248616Smm if (client_switch_proxy(filter, 1590248616Smm filter->archive->client.cursor + 1) 1591248616Smm == ARCHIVE_OK) 1592248616Smm continue; 1593248616Smm } 1594232153Smm filter->client_buff = NULL; 1595232153Smm filter->end_of_file = 1; 1596228753Smm return (total_bytes_skipped); 1597228753Smm } 1598232153Smm 1599232153Smm if (bytes_read >= request) { 1600232153Smm filter->client_next = 1601232153Smm ((const char *)filter->client_buff) + request; 1602238856Smm filter->client_avail = (size_t)(bytes_read - request); 1603232153Smm filter->client_total = bytes_read; 1604232153Smm total_bytes_skipped += request; 1605232153Smm filter->position += request; 1606232153Smm return (total_bytes_skipped); 1607232153Smm } 1608232153Smm 1609232153Smm filter->position += bytes_read; 1610228753Smm total_bytes_skipped += bytes_read; 1611228753Smm request -= bytes_read; 1612228753Smm } 1613228753Smm} 1614232153Smm 1615232153Smm/** 1616232153Smm * Returns ARCHIVE_FAILED if seeking isn't supported. 1617232153Smm */ 1618232153Smmint64_t 1619232153Smm__archive_read_seek(struct archive_read *a, int64_t offset, int whence) 1620232153Smm{ 1621232153Smm return __archive_read_filter_seek(a->filter, offset, whence); 1622232153Smm} 1623232153Smm 1624232153Smmint64_t 1625248616Smm__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, 1626248616Smm int whence) 1627232153Smm{ 1628248616Smm struct archive_read_client *client; 1629232153Smm int64_t r; 1630248616Smm unsigned int cursor; 1631232153Smm 1632232153Smm if (filter->closed || filter->fatal) 1633232153Smm return (ARCHIVE_FATAL); 1634232153Smm if (filter->seek == NULL) 1635232153Smm return (ARCHIVE_FAILED); 1636248616Smm 1637248616Smm client = &(filter->archive->client); 1638248616Smm switch (whence) { 1639248616Smm case SEEK_CUR: 1640248616Smm /* Adjust the offset and use SEEK_SET instead */ 1641328827Smm offset += filter->position; 1642328827Smm __LA_FALLTHROUGH; 1643248616Smm case SEEK_SET: 1644248616Smm cursor = 0; 1645248616Smm while (1) 1646248616Smm { 1647248616Smm if (client->dataset[cursor].begin_position < 0 || 1648248616Smm client->dataset[cursor].total_size < 0 || 1649248616Smm client->dataset[cursor].begin_position + 1650248616Smm client->dataset[cursor].total_size - 1 > offset || 1651248616Smm cursor + 1 >= client->nodes) 1652248616Smm break; 1653248616Smm r = client->dataset[cursor].begin_position + 1654248616Smm client->dataset[cursor].total_size; 1655248616Smm client->dataset[++cursor].begin_position = r; 1656248616Smm } 1657248616Smm while (1) { 1658248616Smm r = client_switch_proxy(filter, cursor); 1659248616Smm if (r != ARCHIVE_OK) 1660248616Smm return r; 1661248616Smm if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) 1662248616Smm return r; 1663248616Smm client->dataset[cursor].total_size = r; 1664248616Smm if (client->dataset[cursor].begin_position + 1665248616Smm client->dataset[cursor].total_size - 1 > offset || 1666248616Smm cursor + 1 >= client->nodes) 1667248616Smm break; 1668248616Smm r = client->dataset[cursor].begin_position + 1669248616Smm client->dataset[cursor].total_size; 1670248616Smm client->dataset[++cursor].begin_position = r; 1671248616Smm } 1672248616Smm offset -= client->dataset[cursor].begin_position; 1673299529Smm if (offset < 0 1674299529Smm || offset > client->dataset[cursor].total_size) 1675299529Smm return ARCHIVE_FATAL; 1676248616Smm if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0) 1677248616Smm return r; 1678248616Smm break; 1679248616Smm 1680248616Smm case SEEK_END: 1681248616Smm cursor = 0; 1682248616Smm while (1) { 1683248616Smm if (client->dataset[cursor].begin_position < 0 || 1684248616Smm client->dataset[cursor].total_size < 0 || 1685248616Smm cursor + 1 >= client->nodes) 1686248616Smm break; 1687248616Smm r = client->dataset[cursor].begin_position + 1688248616Smm client->dataset[cursor].total_size; 1689248616Smm client->dataset[++cursor].begin_position = r; 1690248616Smm } 1691248616Smm while (1) { 1692248616Smm r = client_switch_proxy(filter, cursor); 1693248616Smm if (r != ARCHIVE_OK) 1694248616Smm return r; 1695248616Smm if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) 1696248616Smm return r; 1697248616Smm client->dataset[cursor].total_size = r; 1698248616Smm r = client->dataset[cursor].begin_position + 1699248616Smm client->dataset[cursor].total_size; 1700248616Smm if (cursor + 1 >= client->nodes) 1701248616Smm break; 1702248616Smm client->dataset[++cursor].begin_position = r; 1703248616Smm } 1704248616Smm while (1) { 1705248616Smm if (r + offset >= 1706248616Smm client->dataset[cursor].begin_position) 1707248616Smm break; 1708248616Smm offset += client->dataset[cursor].total_size; 1709248616Smm if (cursor == 0) 1710248616Smm break; 1711248616Smm cursor--; 1712248616Smm r = client->dataset[cursor].begin_position + 1713248616Smm client->dataset[cursor].total_size; 1714248616Smm } 1715248616Smm offset = (r + offset) - client->dataset[cursor].begin_position; 1716248616Smm if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK) 1717248616Smm return r; 1718248616Smm r = client_seek_proxy(filter, offset, SEEK_SET); 1719248616Smm if (r < ARCHIVE_OK) 1720248616Smm return r; 1721248616Smm break; 1722248616Smm 1723248616Smm default: 1724248616Smm return (ARCHIVE_FATAL); 1725248616Smm } 1726248616Smm r += client->dataset[cursor].begin_position; 1727248616Smm 1728232153Smm if (r >= 0) { 1729232153Smm /* 1730232153Smm * Ouch. Clearing the buffer like this hurts, especially 1731232153Smm * at bid time. A lot of our efficiency at bid time comes 1732232153Smm * from having bidders reuse the data we've already read. 1733232153Smm * 1734232153Smm * TODO: If the seek request is in data we already 1735232153Smm * have, then don't call the seek callback. 1736232153Smm * 1737232153Smm * TODO: Zip seeks to end-of-file at bid time. If 1738232153Smm * other formats also start doing this, we may need to 1739232153Smm * find a way for clients to fudge the seek offset to 1740232153Smm * a block boundary. 1741232153Smm * 1742232153Smm * Hmmm... If whence was SEEK_END, we know the file 1743232153Smm * size is (r - offset). Can we use that to simplify 1744232153Smm * the TODO items above? 1745232153Smm */ 1746232153Smm filter->avail = filter->client_avail = 0; 1747232153Smm filter->next = filter->buffer; 1748232153Smm filter->position = r; 1749232153Smm filter->end_of_file = 0; 1750232153Smm } 1751232153Smm return r; 1752232153Smm} 1753