1 /*- 2 * Copyright (c) 2003-2012 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "archive_platform.h" 27 __FBSDID("$FreeBSD$"); 28 29 #ifdef HAVE_ERRNO_H 30 #include <errno.h> 31 #endif 32 33 #include "archive.h" 34 #include "archive_private.h" 35 #include "archive_read_private.h" 36 37 int 38 archive_read_append_filter(struct archive *_a, int code) 39 { 40 int r1, r2, number_bidders, i; 41 char str[20]; 42 struct archive_read_filter_bidder *bidder; 43 struct archive_read_filter *filter; 44 struct archive_read *a = (struct archive_read *)_a; 45 46 r2 = (ARCHIVE_OK); 47 switch (code) 48 { 49 case ARCHIVE_FILTER_NONE: 50 /* No filter to add, so do nothing. 51 * NOTE: An initial "NONE" type filter is always set at the end of the 52 * filter chain. 53 */ 54 r1 = (ARCHIVE_OK); 55 break; 56 case ARCHIVE_FILTER_GZIP: 57 strcpy(str, "gzip"); 58 r1 = archive_read_support_filter_gzip(_a); 59 break; 60 case ARCHIVE_FILTER_BZIP2: 61 strcpy(str, "bzip2"); 62 r1 = archive_read_support_filter_bzip2(_a); 63 break; 64 case ARCHIVE_FILTER_COMPRESS: 65 strcpy(str, "compress (.Z)"); 66 r1 = archive_read_support_filter_compress(_a); 67 break; 68 case ARCHIVE_FILTER_PROGRAM: 69 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 70 "Cannot append program filter using archive_read_append_filter"); 71 return (ARCHIVE_FATAL); 72 case ARCHIVE_FILTER_LZMA: 73 strcpy(str, "lzma"); 74 r1 = archive_read_support_filter_lzma(_a); 75 break; 76 case ARCHIVE_FILTER_XZ: 77 strcpy(str, "xz"); 78 r1 = archive_read_support_filter_xz(_a); 79 break; 80 case ARCHIVE_FILTER_UU: 81 strcpy(str, "uu"); 82 r1 = archive_read_support_filter_uu(_a); 83 break; 84 case ARCHIVE_FILTER_RPM: 85 strcpy(str, "rpm"); 86 r1 = archive_read_support_filter_rpm(_a); 87 break; 88 case ARCHIVE_FILTER_LZ4: 89 strcpy(str, "lz4"); 90 r1 = archive_read_support_filter_lz4(_a); 91 break; 92 case ARCHIVE_FILTER_LZIP: 93 strcpy(str, "lzip"); 94 r1 = archive_read_support_filter_lzip(_a); 95 break; 96 case ARCHIVE_FILTER_LRZIP: 97 strcpy(str, "lrzip"); 98 r1 = archive_read_support_filter_lrzip(_a); 99 break; 100 default: 101 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 102 "Invalid filter code specified"); 103 return (ARCHIVE_FATAL); 104 } 105 106 if (code != ARCHIVE_FILTER_NONE) 107 { 108 number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 109 110 bidder = a->bidders; 111 for (i = 0; i < number_bidders; i++, bidder++) 112 { 113 if (!bidder->name || !strcmp(bidder->name, str)) 114 break; 115 } 116 if (!bidder->name || strcmp(bidder->name, str)) 117 { 118 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 119 "Internal error: Unable to append filter"); 120 return (ARCHIVE_FATAL); 121 } 122 123 filter 124 = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 125 if (filter == NULL) 126 { 127 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 128 return (ARCHIVE_FATAL); 129 } 130 filter->bidder = bidder; 131 filter->archive = a; 132 filter->upstream = a->filter; 133 a->filter = filter; 134 r2 = (bidder->init)(a->filter); 135 if (r2 != ARCHIVE_OK) { 136 __archive_read_close_filters(a); 137 __archive_read_free_filters(a); 138 return (ARCHIVE_FATAL); 139 } 140 } 141 142 a->bypass_filter_bidding = 1; 143 return (r1 < r2) ? r1 : r2; 144 } 145 146 int 147 archive_read_append_filter_program(struct archive *_a, const char *cmd) 148 { 149 return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0)); 150 } 151 152 int 153 archive_read_append_filter_program_signature(struct archive *_a, 154 const char *cmd, const void *signature, size_t signature_len) 155 { 156 int r, number_bidders, i; 157 struct archive_read_filter_bidder *bidder; 158 struct archive_read_filter *filter; 159 struct archive_read *a = (struct archive_read *)_a; 160 161 if (archive_read_support_filter_program_signature(_a, cmd, signature, 162 signature_len) != (ARCHIVE_OK)) 163 return (ARCHIVE_FATAL); 164 165 number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 166 167 bidder = a->bidders; 168 for (i = 0; i < number_bidders; i++, bidder++) 169 { 170 /* Program bidder name set to filter name after initialization */ 171 if (bidder->data && !bidder->name) 172 break; 173 } 174 if (!bidder->data) 175 { 176 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 177 "Internal error: Unable to append program filter"); 178 return (ARCHIVE_FATAL); 179 } 180 181 filter 182 = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 183 if (filter == NULL) 184 { 185 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 186 return (ARCHIVE_FATAL); 187 } 188 filter->bidder = bidder; 189 filter->archive = a; 190 filter->upstream = a->filter; 191 a->filter = filter; 192 r = (bidder->init)(a->filter); 193 if (r != ARCHIVE_OK) { 194 __archive_read_close_filters(a); 195 __archive_read_free_filters(a); 196 return (ARCHIVE_FATAL); 197 } 198 bidder->name = a->filter->name; 199 200 a->bypass_filter_bidding = 1; 201 return r; 202 } 203