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_ZSTD: 93 strcpy(str, "zstd"); 94 r1 = archive_read_support_filter_zstd(_a); 95 break; 96 case ARCHIVE_FILTER_LZIP: 97 strcpy(str, "lzip"); 98 r1 = archive_read_support_filter_lzip(_a); 99 break; 100 case ARCHIVE_FILTER_LRZIP: 101 strcpy(str, "lrzip"); 102 r1 = archive_read_support_filter_lrzip(_a); 103 break; 104 default: 105 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 106 "Invalid filter code specified"); 107 return (ARCHIVE_FATAL); 108 } 109 110 if (code != ARCHIVE_FILTER_NONE) 111 { 112 number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 113 114 bidder = a->bidders; 115 for (i = 0; i < number_bidders; i++, bidder++) 116 { 117 if (!bidder->name || !strcmp(bidder->name, str)) 118 break; 119 } 120 if (!bidder->name || strcmp(bidder->name, str)) 121 { 122 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 123 "Internal error: Unable to append filter"); 124 return (ARCHIVE_FATAL); 125 } 126 127 filter 128 = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 129 if (filter == NULL) 130 { 131 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 132 return (ARCHIVE_FATAL); 133 } 134 filter->bidder = bidder; 135 filter->archive = a; 136 filter->upstream = a->filter; 137 a->filter = filter; 138 r2 = (bidder->init)(a->filter); 139 if (r2 != ARCHIVE_OK) { 140 __archive_read_free_filters(a); 141 return (ARCHIVE_FATAL); 142 } 143 } 144 145 a->bypass_filter_bidding = 1; 146 return (r1 < r2) ? r1 : r2; 147 } 148 149 int 150 archive_read_append_filter_program(struct archive *_a, const char *cmd) 151 { 152 return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0)); 153 } 154 155 int 156 archive_read_append_filter_program_signature(struct archive *_a, 157 const char *cmd, const void *signature, size_t signature_len) 158 { 159 int r, number_bidders, i; 160 struct archive_read_filter_bidder *bidder; 161 struct archive_read_filter *filter; 162 struct archive_read *a = (struct archive_read *)_a; 163 164 if (archive_read_support_filter_program_signature(_a, cmd, signature, 165 signature_len) != (ARCHIVE_OK)) 166 return (ARCHIVE_FATAL); 167 168 number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); 169 170 bidder = a->bidders; 171 for (i = 0; i < number_bidders; i++, bidder++) 172 { 173 /* Program bidder name set to filter name after initialization */ 174 if (bidder->data && !bidder->name) 175 break; 176 } 177 if (!bidder->data) 178 { 179 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 180 "Internal error: Unable to append program filter"); 181 return (ARCHIVE_FATAL); 182 } 183 184 filter 185 = (struct archive_read_filter *)calloc(1, sizeof(*filter)); 186 if (filter == NULL) 187 { 188 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 189 return (ARCHIVE_FATAL); 190 } 191 filter->bidder = bidder; 192 filter->archive = a; 193 filter->upstream = a->filter; 194 a->filter = filter; 195 r = (bidder->init)(a->filter); 196 if (r != ARCHIVE_OK) { 197 __archive_read_free_filters(a); 198 return (ARCHIVE_FATAL); 199 } 200 bidder->name = a->filter->name; 201 202 a->bypass_filter_bidding = 1; 203 return r; 204 } 205