Пример #1
0
/*
 * 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);
		}
	}
}
Пример #2
0
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;
	}
}
Пример #3
0
/*
 * 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);
}
Пример #4
0
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);
}
Пример #5
0
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);
}