2 * Copyright (c) 2007 Joerg Sonnenberger
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
52 #include "archive_private.h"
53 #include "archive_read_private.h"
56 archive_read_support_compression_program(struct archive *a, const char *cmd)
58 return (archive_read_support_compression_program_signature(a, cmd, NULL, 0));
62 /* This capability is only available on POSIX systems. */
63 #if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
64 !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
67 * On non-Posix systems, allow the program to build, but choke if
68 * this function is actually invoked.
71 archive_read_support_compression_program_signature(struct archive *_a,
72 const char *cmd, void *signature, size_t signature_len)
74 (void)_a; /* UNUSED */
75 (void)cmd; /* UNUSED */
76 (void)signature; /* UNUSED */
77 (void)signature_len; /* UNUSED */
79 archive_set_error(_a, -1,
80 "External compression programs not supported on this platform");
81 return (ARCHIVE_FATAL);
85 __archive_read_program(struct archive_read_filter *self, const char *cmd)
87 (void)self; /* UNUSED */
88 (void)cmd; /* UNUSED */
90 archive_set_error(&self->archive->archive, -1,
91 "External compression programs not supported on this platform");
92 return (ARCHIVE_FATAL);
97 #include "filter_fork.h"
100 * The bidder object stores the command and the signature to watch for.
101 * The 'inhibit' entry here is used to ensure that unchecked filters never
102 * bid twice in the same pipeline.
104 struct program_bidder {
107 size_t signature_len;
111 static int program_bidder_bid(struct archive_read_filter_bidder *,
112 struct archive_read_filter *upstream);
113 static int program_bidder_init(struct archive_read_filter *);
114 static int program_bidder_free(struct archive_read_filter_bidder *);
117 * The actual filter needs to track input and output data.
119 struct program_filter {
122 int child_stdin, child_stdout;
128 static ssize_t program_filter_read(struct archive_read_filter *,
130 static int program_filter_close(struct archive_read_filter *);
133 archive_read_support_compression_program_signature(struct archive *_a,
134 const char *cmd, const void *signature, size_t signature_len)
136 struct archive_read *a = (struct archive_read *)_a;
137 struct archive_read_filter_bidder *bidder;
138 struct program_bidder *state;
141 * Get a bidder object from the read core.
143 bidder = __archive_read_get_bidder(a);
145 return (ARCHIVE_FATAL);
148 * Allocate our private state.
150 state = (struct program_bidder *)calloc(sizeof (*state), 1);
152 return (ARCHIVE_FATAL);
153 state->cmd = strdup(cmd);
154 if (signature != NULL && signature_len > 0) {
155 state->signature_len = signature_len;
156 state->signature = malloc(signature_len);
157 memcpy(state->signature, signature, signature_len);
161 * Fill in the bidder object.
163 bidder->data = state;
164 bidder->bid = program_bidder_bid;
165 bidder->init = program_bidder_init;
166 bidder->options = NULL;
167 bidder->free = program_bidder_free;
172 program_bidder_free(struct archive_read_filter_bidder *self)
174 struct program_bidder *state = (struct program_bidder *)self->data;
176 free(state->signature);
182 * If we do have a signature, bid only if that matches.
184 * If there's no signature, we bid INT_MAX the first time
185 * we're called, then never bid again.
188 program_bidder_bid(struct archive_read_filter_bidder *self,
189 struct archive_read_filter *upstream)
191 struct program_bidder *state = self->data;
194 /* If we have a signature, use that to match. */
195 if (state->signature_len > 0) {
196 p = __archive_read_filter_ahead(upstream,
197 state->signature_len, NULL);
200 /* No match, so don't bid. */
201 if (memcmp(p, state->signature, state->signature_len) != 0)
203 return (state->signature_len * 8);
206 /* Otherwise, bid once and then never bid again. */
214 * Use select() to decide whether the child is ready for read or write.
217 child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
219 struct program_filter *state = self->data;
220 ssize_t ret, requested, avail;
223 requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
227 ret = read(state->child_stdout, buf, requested);
228 } while (ret == -1 && errno == EINTR);
232 if (ret == 0 || (ret == -1 && errno == EPIPE)) {
233 close(state->child_stdout);
234 state->child_stdout = -1;
237 if (ret == -1 && errno != EAGAIN)
240 if (state->child_stdin == -1) {
241 /* Block until child has some I/O ready. */
242 __archive_check_child(state->child_stdin,
243 state->child_stdout);
247 /* Get some more data from upstream. */
248 p = __archive_read_filter_ahead(self->upstream, 1, &avail);
250 close(state->child_stdin);
251 state->child_stdin = -1;
252 fcntl(state->child_stdout, F_SETFL, 0);
259 ret = write(state->child_stdin, p, avail);
260 } while (ret == -1 && errno == EINTR);
263 /* Consume whatever we managed to write. */
264 __archive_read_filter_consume(self->upstream, ret);
265 } else if (ret == -1 && errno == EAGAIN) {
266 /* Block until child has some I/O ready. */
267 __archive_check_child(state->child_stdin,
268 state->child_stdout);
271 close(state->child_stdin);
272 state->child_stdin = -1;
273 fcntl(state->child_stdout, F_SETFL, 0);
274 /* If it was a bad error, we're done; otherwise
275 * it was EPIPE or EOF, and we can still read
277 if (ret == -1 && errno != EPIPE)
284 __archive_read_program(struct archive_read_filter *self, const char *cmd)
286 struct program_filter *state;
287 static const size_t out_buf_len = 65536;
290 const char *prefix = "Program: ";
292 state = (struct program_filter *)calloc(1, sizeof(*state));
293 out_buf = (char *)malloc(out_buf_len);
294 description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
295 if (state == NULL || out_buf == NULL || description == NULL) {
296 archive_set_error(&self->archive->archive, ENOMEM,
297 "Can't allocate input data");
301 return (ARCHIVE_FATAL);
304 self->code = ARCHIVE_COMPRESSION_PROGRAM;
305 state->description = description;
306 strcpy(state->description, prefix);
307 strcat(state->description, cmd);
308 self->name = state->description;
310 state->out_buf = out_buf;
311 state->out_buf_len = out_buf_len;
313 if ((state->child = __archive_create_child(cmd,
314 &state->child_stdin, &state->child_stdout)) == -1) {
315 free(state->out_buf);
317 archive_set_error(&self->archive->archive, EINVAL,
318 "Can't initialise filter");
319 return (ARCHIVE_FATAL);
323 self->read = program_filter_read;
325 self->close = program_filter_close;
327 /* XXX Check that we can read at least one byte? */
332 program_bidder_init(struct archive_read_filter *self)
334 struct program_bidder *bidder_state;
336 bidder_state = (struct program_bidder *)self->bidder->data;
337 return (__archive_read_program(self, bidder_state->cmd));
341 program_filter_read(struct archive_read_filter *self, const void **buff)
343 struct program_filter *state;
348 state = (struct program_filter *)self->data;
352 while (state->child_stdout != -1 && total < state->out_buf_len) {
353 bytes = child_read(self, p, state->out_buf_len - total);
362 *buff = state->out_buf;
367 program_filter_close(struct archive_read_filter *self)
369 struct program_filter *state;
372 state = (struct program_filter *)self->data;
374 /* Shut down the child. */
375 if (state->child_stdin != -1)
376 close(state->child_stdin);
377 if (state->child_stdout != -1)
378 close(state->child_stdout);
379 while (waitpid(state->child, &status, 0) == -1 && errno == EINTR)
382 /* Release our private data. */
383 free(state->out_buf);
384 free(state->description);
390 #endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */