Example #1
0
static int
choose_filters(struct archive_read *a)
{
	int number_bidders, i, bid, best_bid, number_filters;
	struct archive_read_filter_bidder *bidder, *best_bidder;
	struct archive_read_filter *filter;
	ssize_t avail;
	int r;

	for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) {
		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) {
				__archive_read_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) {
			__archive_read_free_filters(a);
			return (ARCHIVE_FATAL);
		}
	}
	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
	    "Input requires too many filters for decoding");
	return (ARCHIVE_FATAL);
}
Example #2
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) {
				__archive_read_close_filters(a);
				__archive_read_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) {
			__archive_read_close_filters(a);
			__archive_read_free_filters(a);
			return (ARCHIVE_FATAL);
		}
	}
}
int
archive_read_append_filter_program_signature(struct archive *_a,
        const char *cmd, const void *signature, size_t signature_len)
{
    int r, number_bidders, i;
    struct archive_read_filter_bidder *bidder;
    struct archive_read_filter *filter;
    struct archive_read *a = (struct archive_read *)_a;

    if (archive_read_support_filter_program_signature(_a, cmd, signature,
            signature_len) != (ARCHIVE_OK))
        return (ARCHIVE_FATAL);

    number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);

    bidder = a->bidders;
    for (i = 0; i < number_bidders; i++, bidder++)
    {
        /* Program bidder name set to filter name after initialization */
        if (bidder->data && !bidder->name)
            break;
    }
    if (!bidder->data)
    {
        archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
                          "Internal error: Unable to append program filter");
        return (ARCHIVE_FATAL);
    }

    filter
        = (struct archive_read_filter *)calloc(1, sizeof(*filter));
    if (filter == NULL)
    {
        archive_set_error(&a->archive, ENOMEM, "Out of memory");
        return (ARCHIVE_FATAL);
    }
    filter->bidder = bidder;
    filter->archive = a;
    filter->upstream = a->filter;
    a->filter = filter;
    r = (bidder->init)(a->filter);
    if (r != ARCHIVE_OK) {
        __archive_read_close_filters(a);
        __archive_read_free_filters(a);
        return (ARCHIVE_FATAL);
    }
    bidder->name = a->filter->name;

    a->bypass_filter_bidding = 1;
    return r;
}
Example #4
0
/*
 * Release memory and other resources.
 */
static int
_archive_read_free(struct archive *_a)
{
	struct archive_read *a = (struct archive_read *)_a;
	int i, n;
	int slots;
	int r = ARCHIVE_OK;

	if (_a == NULL)
		return (ARCHIVE_OK);
	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
	if (a->archive.state != ARCHIVE_STATE_CLOSED
	    && a->archive.state != ARCHIVE_STATE_FATAL)
		r = archive_read_close(&a->archive);

	/* Call cleanup functions registered by optional components. */
	if (a->cleanup_archive_extract != NULL)
		r = (a->cleanup_archive_extract)(a);

	/* Cleanup format-specific data. */
	slots = sizeof(a->formats) / sizeof(a->formats[0]);
	for (i = 0; i < slots; i++) {
		a->format = &(a->formats[i]);
		if (a->formats[i].cleanup)
			(a->formats[i].cleanup)(a);
	}

	/* Free the filters */
	__archive_read_free_filters(a);

	/* Release the bidder objects. */
	n = sizeof(a->bidders)/sizeof(a->bidders[0]);
	for (i = 0; i < n; i++) {
		if (a->bidders[i].free != NULL) {
			int r1 = (a->bidders[i].free)(&a->bidders[i]);
			if (r1 < r)
				r = r1;
		}
	}

	archive_string_free(&a->archive.error_string);
	if (a->entry)
		archive_entry_free(a->entry);
	a->archive.magic = 0;
	__archive_clean(&a->archive);
	free(a->client.dataset);
	free(a);
	return (r);
}
int
archive_read_append_filter(struct archive *_a, int code)
{
    int r1, r2, number_bidders, i;
    char str[20];
    struct archive_read_filter_bidder *bidder;
    struct archive_read_filter *filter;
    struct archive_read *a = (struct archive_read *)_a;

    r1 = r2 = (ARCHIVE_OK);
    switch (code)
    {
    case ARCHIVE_FILTER_NONE:
        /* No filter to add, so do nothing.
         * NOTE: An initial "NONE" type filter is always set at the end of the
         * filter chain.
         */
        r1 = (ARCHIVE_OK);
        break;
    case ARCHIVE_FILTER_GZIP:
        strcpy(str, "gzip");
        r1 = archive_read_support_filter_gzip(_a);
        break;
    case ARCHIVE_FILTER_BZIP2:
        strcpy(str, "bzip2");
        r1 = archive_read_support_filter_bzip2(_a);
        break;
    case ARCHIVE_FILTER_COMPRESS:
        strcpy(str, "compress (.Z)");
        r1 = archive_read_support_filter_compress(_a);
        break;
    case ARCHIVE_FILTER_PROGRAM:
        archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
                          "Cannot append program filter using archive_read_append_filter");
        return (ARCHIVE_FATAL);
    case ARCHIVE_FILTER_LZMA:
        strcpy(str, "lzma");
        r1 = archive_read_support_filter_lzma(_a);
        break;
    case ARCHIVE_FILTER_XZ:
        strcpy(str, "xz");
        r1 = archive_read_support_filter_xz(_a);
        break;
    case ARCHIVE_FILTER_UU:
        strcpy(str, "uu");
        r1 = archive_read_support_filter_uu(_a);
        break;
    case ARCHIVE_FILTER_RPM:
        strcpy(str, "rpm");
        r1 = archive_read_support_filter_rpm(_a);
        break;
    case ARCHIVE_FILTER_LZIP:
        strcpy(str, "lzip");
        r1 = archive_read_support_filter_lzip(_a);
        break;
    case ARCHIVE_FILTER_LRZIP:
        strcpy(str, "lrzip");
        r1 = archive_read_support_filter_lrzip(_a);
        break;
    default:
        archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
                          "Invalid filter code specified");
        return (ARCHIVE_FATAL);
    }

    if (code != ARCHIVE_FILTER_NONE)
    {
        number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);

        bidder = a->bidders;
        for (i = 0; i < number_bidders; i++, bidder++)
        {
            if (!bidder->name || !strcmp(bidder->name, str))
                break;
        }
        if (!bidder->name || strcmp(bidder->name, str))
        {
            archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
                              "Internal error: Unable to append filter");
            return (ARCHIVE_FATAL);
        }

        filter
            = (struct archive_read_filter *)calloc(1, sizeof(*filter));
        if (filter == NULL)
        {
            archive_set_error(&a->archive, ENOMEM, "Out of memory");
            return (ARCHIVE_FATAL);
        }
        filter->bidder = bidder;
        filter->archive = a;
        filter->upstream = a->filter;
        a->filter = filter;
        r2 = (bidder->init)(a->filter);
        if (r2 != ARCHIVE_OK) {
            __archive_read_close_filters(a);
            __archive_read_free_filters(a);
            return (ARCHIVE_FATAL);
        }
    }

    a->bypass_filter_bidding = 1;
    return (r1 < r2) ? r1 : r2;
}