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 
28 #ifdef HAVE_ERRNO_H
29 #include <errno.h>
30 #endif
31 
32 #include "archive.h"
33 #include "archive_private.h"
34 #include "archive_read_private.h"
35 
36 int
37 archive_read_append_filter(struct archive *_a, int code)
38 {
39   int r1, r2, number_bidders, i;
40   char str[20];
41   struct archive_read_filter_bidder *bidder;
42   struct archive_read_filter *filter;
43   struct archive_read *a = (struct archive_read *)_a;
44 
45   r2 = (ARCHIVE_OK);
46   switch (code)
47   {
48     case ARCHIVE_FILTER_NONE:
49       /* No filter to add, so do nothing.
50        * NOTE: An initial "NONE" type filter is always set at the end of the
51        * filter chain.
52        */
53       r1 = (ARCHIVE_OK);
54       break;
55     case ARCHIVE_FILTER_GZIP:
56       strcpy(str, "gzip");
57       r1 = archive_read_support_filter_gzip(_a);
58       break;
59     case ARCHIVE_FILTER_BZIP2:
60       strcpy(str, "bzip2");
61       r1 = archive_read_support_filter_bzip2(_a);
62       break;
63     case ARCHIVE_FILTER_COMPRESS:
64       strcpy(str, "compress (.Z)");
65       r1 = archive_read_support_filter_compress(_a);
66       break;
67     case ARCHIVE_FILTER_PROGRAM:
68       archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
69           "Cannot append program filter using archive_read_append_filter");
70       return (ARCHIVE_FATAL);
71     case ARCHIVE_FILTER_LZMA:
72       strcpy(str, "lzma");
73       r1 = archive_read_support_filter_lzma(_a);
74       break;
75     case ARCHIVE_FILTER_XZ:
76       strcpy(str, "xz");
77       r1 = archive_read_support_filter_xz(_a);
78       break;
79     case ARCHIVE_FILTER_UU:
80       strcpy(str, "uu");
81       r1 = archive_read_support_filter_uu(_a);
82       break;
83     case ARCHIVE_FILTER_RPM:
84       strcpy(str, "rpm");
85       r1 = archive_read_support_filter_rpm(_a);
86       break;
87     case ARCHIVE_FILTER_LZ4:
88       strcpy(str, "lz4");
89       r1 = archive_read_support_filter_lz4(_a);
90       break;
91     case ARCHIVE_FILTER_ZSTD:
92       strcpy(str, "zstd");
93       r1 = archive_read_support_filter_zstd(_a);
94       break;
95     case ARCHIVE_FILTER_LZIP:
96       strcpy(str, "lzip");
97       r1 = archive_read_support_filter_lzip(_a);
98       break;
99     case ARCHIVE_FILTER_LRZIP:
100       strcpy(str, "lrzip");
101       r1 = archive_read_support_filter_lrzip(_a);
102       break;
103     default:
104       archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
105           "Invalid filter code specified");
106       return (ARCHIVE_FATAL);
107   }
108 
109   if (code != ARCHIVE_FILTER_NONE)
110   {
111     number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
112 
113     bidder = a->bidders;
114     for (i = 0; i < number_bidders; i++, bidder++)
115     {
116       if (!bidder->name || !strcmp(bidder->name, str))
117         break;
118     }
119     if (!bidder->name || strcmp(bidder->name, str))
120     {
121       archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
122           "Internal error: Unable to append filter");
123       return (ARCHIVE_FATAL);
124     }
125 
126     filter
127         = (struct archive_read_filter *)calloc(1, sizeof(*filter));
128     if (filter == NULL)
129     {
130       archive_set_error(&a->archive, ENOMEM, "Out of memory");
131       return (ARCHIVE_FATAL);
132     }
133     filter->bidder = bidder;
134     filter->archive = a;
135     filter->upstream = a->filter;
136     a->filter = filter;
137     r2 = (bidder->vtable->init)(a->filter);
138     if (r2 != ARCHIVE_OK) {
139       __archive_read_free_filters(a);
140       return (ARCHIVE_FATAL);
141     }
142   }
143 
144   a->bypass_filter_bidding = 1;
145   return (r1 < r2) ? r1 : r2;
146 }
147 
148 int
149 archive_read_append_filter_program(struct archive *_a, const char *cmd)
150 {
151   return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
152 }
153 
154 int
155 archive_read_append_filter_program_signature(struct archive *_a,
156   const char *cmd, const void *signature, size_t signature_len)
157 {
158   int r, number_bidders, i;
159   struct archive_read_filter_bidder *bidder;
160   struct archive_read_filter *filter;
161   struct archive_read *a = (struct archive_read *)_a;
162 
163   if (archive_read_support_filter_program_signature(_a, cmd, signature,
164     signature_len) != (ARCHIVE_OK))
165     return (ARCHIVE_FATAL);
166 
167   number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
168 
169   bidder = a->bidders;
170   for (i = 0; i < number_bidders; i++, bidder++)
171   {
172     /* Program bidder name set to filter name after initialization */
173     if (bidder->data && !bidder->name)
174       break;
175   }
176   if (!bidder->data)
177   {
178     archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
179         "Internal error: Unable to append program filter");
180     return (ARCHIVE_FATAL);
181   }
182 
183   filter
184       = (struct archive_read_filter *)calloc(1, sizeof(*filter));
185   if (filter == NULL)
186   {
187     archive_set_error(&a->archive, ENOMEM, "Out of memory");
188     return (ARCHIVE_FATAL);
189   }
190   filter->bidder = bidder;
191   filter->archive = a;
192   filter->upstream = a->filter;
193   a->filter = filter;
194   r = (bidder->vtable->init)(a->filter);
195   if (r != ARCHIVE_OK) {
196     __archive_read_free_filters(a);
197     return (ARCHIVE_FATAL);
198   }
199   bidder->name = a->filter->name;
200 
201   a->bypass_filter_bidding = 1;
202   return r;
203 }
204