/* * Allow each registered stream transform to bid on whether * it wants to handle this stream. Repeat until we've finished * building the pipeline. */ static int choose_filters(struct archive_read *a) { int number_bidders, i, bid, best_bid; struct archive_read_filter_bidder *bidder, *best_bidder; struct archive_read_filter *filter; ssize_t avail; int r; for (;;) { number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); best_bid = 0; best_bidder = NULL; bidder = a->bidders; for (i = 0; i < number_bidders; i++, bidder++) { if (bidder->bid != NULL) { bid = (bidder->bid)(bidder, a->filter); if (bid > best_bid) { best_bid = bid; best_bidder = bidder; } } } /* If no bidder, we're done. */ if (best_bidder == NULL) { /* Verify the filter by asking it for some data. */ __archive_read_filter_ahead(a->filter, 1, &avail); if (avail < 0) { close_filters(a); free_filters(a); return (ARCHIVE_FATAL); } a->archive.compression_name = a->filter->name; a->archive.compression_code = a->filter->code; return (ARCHIVE_OK); } filter = (struct archive_read_filter *)calloc(1, sizeof(*filter)); if (filter == NULL) return (ARCHIVE_FATAL); filter->bidder = best_bidder; filter->archive = a; filter->upstream = a->filter; a->filter = filter; r = (best_bidder->init)(a->filter); if (r != ARCHIVE_OK) { close_filters(a); free_filters(a); return (ARCHIVE_FATAL); } } }
void __archive_read_free_filters(struct archive_read *a) { /* Make sure filters are closed and their buffers are freed */ close_filters(a); while (a->filter != NULL) { struct archive_read_filter *t = a->filter->upstream; free(a->filter); a->filter = t; } }
/* * Close the file and all I/O. */ static int _archive_read_close(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; int r = ARCHIVE_OK, r1 = ARCHIVE_OK; archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close"); if (a->archive.state == ARCHIVE_STATE_CLOSED) return (ARCHIVE_OK); archive_clear_error(&a->archive); a->archive.state = ARCHIVE_STATE_CLOSED; /* TODO: Clean up the formatters. */ /* Release the filter objects. */ r1 = close_filters(a); if (r1 < r) r = r1; return (r); }
int archive_read_open1(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; struct archive_read_filter *filter; int slot, e; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open"); archive_clear_error(&a->archive); if (a->client.reader == NULL) { archive_set_error(&a->archive, EINVAL, "No reader function provided to archive_read_open"); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } /* Open data source. */ if (a->client.opener != NULL) { e =(a->client.opener)(&a->archive, a->client.data); if (e != 0) { /* If the open failed, call the closer to clean up. */ if (a->client.closer) (a->client.closer)(&a->archive, a->client.data); return (e); } } filter = calloc(1, sizeof(*filter)); if (filter == NULL) return (ARCHIVE_FATAL); filter->bidder = NULL; filter->upstream = NULL; filter->archive = a; filter->data = a->client.data; filter->read = client_read_proxy; filter->skip = client_skip_proxy; filter->seek = client_seek_proxy; filter->close = client_close_proxy; filter->name = "none"; filter->code = ARCHIVE_COMPRESSION_NONE; a->filter = filter; /* Build out the input pipeline. */ e = choose_filters(a); if (e < ARCHIVE_WARN) { a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } slot = choose_format(a); if (slot < 0) { close_filters(a); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } a->format = &(a->formats[slot]); a->archive.state = ARCHIVE_STATE_HEADER; return (e); }
int archive_read_open1(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; struct archive_read_filter *filter; int slot, e; unsigned int i; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open"); archive_clear_error(&a->archive); if (a->client.reader == NULL) { archive_set_error(&a->archive, EINVAL, "No reader function provided to archive_read_open"); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } /* Open data source. */ if (a->client.opener != NULL) { e =(a->client.opener)(&a->archive, a->client.dataset[0].data); if (e != 0) { /* If the open failed, call the closer to clean up. */ if (a->client.closer) { for (i = 0; i < a->client.nodes; i++) (a->client.closer)(&a->archive, a->client.dataset[i].data); } return (e); } } filter = calloc(1, sizeof(*filter)); if (filter == NULL) return (ARCHIVE_FATAL); filter->bidder = NULL; filter->upstream = NULL; filter->archive = a; filter->data = a->client.dataset[0].data; filter->open = client_open_proxy; filter->read = client_read_proxy; filter->skip = client_skip_proxy; filter->seek = client_seek_proxy; filter->close = client_close_proxy; filter->sswitch = client_switch_proxy; filter->name = "none"; filter->code = ARCHIVE_FILTER_NONE; a->filter = filter; client_switch_proxy(a->filter, 0); a->client.dataset[0].begin_position = 0; /* Build out the input pipeline. */ e = choose_filters(a); if (e < ARCHIVE_WARN) { a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } slot = choose_format(a); if (slot < 0) { close_filters(a); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } a->format = &(a->formats[slot]); a->archive.state = ARCHIVE_STATE_HEADER; /* Ensure libarchive starts from the first node in a multivolume set */ client_switch_proxy(a->filter, 0); return (e); }