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$");
30 /* This capability is only available on POSIX systems. */
31 #if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
32 !(defined(HAVE_FORK) || defined(HAVE_VFORK))
37 * On non-Posix systems, allow the program to build, but choke if
38 * this function is actually invoked.
41 archive_read_support_compression_program(struct archive *_a, const char *cmd)
43 archive_set_error(_a, -1,
44 "External compression programs not supported on this platform");
45 return (ARCHIVE_FATAL);
50 #ifdef HAVE_SYS_WAIT_H
51 # include <sys/wait.h>
73 #include "archive_private.h"
74 #include "archive_read_private.h"
76 #include "filter_fork.h"
78 struct program_reader {
83 struct program_source {
86 int child_stdin, child_stdout;
91 const char *child_in_buf;
92 size_t child_in_buf_avail;
95 static int program_reader_bid(struct archive_reader *,
96 const void *, size_t);
97 static struct archive_read_source *program_reader_init(struct archive_read *,
98 struct archive_reader *, struct archive_read_source *,
99 const void *, size_t);
100 static int program_reader_free(struct archive_reader *);
102 static ssize_t program_source_read(struct archive_read_source *,
104 static int program_source_close(struct archive_read_source *);
108 archive_read_support_compression_program(struct archive *_a, const char *cmd)
110 struct archive_read *a = (struct archive_read *)_a;
111 struct archive_reader *reader = __archive_read_get_reader(a);
112 struct program_reader *state;
114 state = (struct program_reader *)calloc(sizeof (*state), 1);
117 return (ARCHIVE_FATAL);
119 return (ARCHIVE_FATAL);
121 state->cmd = strdup(cmd);
122 state->bid = INT_MAX;
124 reader->data = state;
125 reader->bid = program_reader_bid;
126 reader->init = program_reader_init;
127 reader->free = program_reader_free;
132 program_reader_free(struct archive_reader *self)
139 * If the user used us to register, they must really want us to
140 * handle it, so we always bid INT_MAX the first time we're called.
141 * After that, we always return zero, lest we end up instantiating
142 * an infinite pipeline.
145 program_reader_bid(struct archive_reader *self, const void *buff, size_t len)
147 struct program_reader *state = self->data;
148 int bid = state->bid;
150 (void)buff; /* UNUSED */
151 (void)len; /* UNUSED */
153 state->bid = 0; /* Don't bid again on this pipeline. */
155 return (bid); /* Default: We'll take it if we haven't yet bid. */
159 * Use select() to decide whether the child is ready for read or write.
163 child_read(struct archive_read_source *self, char *buf, size_t buf_len)
165 struct program_source *state = self->data;
166 ssize_t ret, requested;
167 const void *child_buf;
169 if (state->child_stdout == -1)
176 requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
179 ret = read(state->child_stdout, buf, requested);
180 } while (ret == -1 && errno == EINTR);
184 if (ret == 0 || (ret == -1 && errno == EPIPE)) {
185 close(state->child_stdout);
186 state->child_stdout = -1;
189 if (ret == -1 && errno != EAGAIN)
192 if (state->child_in_buf_avail == 0) {
193 child_buf = state->child_in_buf;
194 ret = (self->upstream->read)(self->upstream, &child_buf);
195 state->child_in_buf = (const char *)child_buf;
198 close(state->child_stdin);
199 state->child_stdin = -1;
200 fcntl(state->child_stdout, F_SETFL, 0);
204 close(state->child_stdin);
205 state->child_stdin = -1;
206 fcntl(state->child_stdout, F_SETFL, 0);
209 state->child_in_buf_avail = ret;
212 if (state->child_stdin == -1) {
213 fcntl(state->child_stdout, F_SETFL, 0);
214 __archive_check_child(state->child_stdin, state->child_stdout);
219 ret = write(state->child_stdin, state->child_in_buf,
220 state->child_in_buf_avail);
221 } while (ret == -1 && errno == EINTR);
224 state->child_in_buf += ret;
225 state->child_in_buf_avail -= ret;
227 } else if (ret == -1 && errno == EAGAIN) {
228 __archive_check_child(state->child_stdin, state->child_stdout);
230 } else if (ret == 0 || (ret == -1 && errno == EPIPE)) {
231 close(state->child_stdin);
232 state->child_stdin = -1;
233 fcntl(state->child_stdout, F_SETFL, 0);
236 close(state->child_stdin);
237 state->child_stdin = -1;
238 fcntl(state->child_stdout, F_SETFL, 0);
243 static struct archive_read_source *
244 program_reader_init(struct archive_read *a, struct archive_reader *reader,
245 struct archive_read_source *upstream, const void *buff, size_t n)
247 struct program_source *state;
248 struct program_reader *reader_state;
249 struct archive_read_source *self;
250 static const size_t out_buf_len = 65536;
253 const char *prefix = "Program: ";
256 reader_state = (struct program_reader *)reader->data;
258 self = (struct archive_read_source *)malloc(sizeof(*self));
259 state = (struct program_source *)malloc(sizeof(*state));
260 out_buf = (char *)malloc(out_buf_len);
261 description = (char *)malloc(strlen(prefix) + strlen(reader_state->cmd) + 1);
265 || description == NULL)
267 archive_set_error(&a->archive, ENOMEM,
268 "Can't allocate input data");
276 a->archive.compression_code = ARCHIVE_COMPRESSION_PROGRAM;
277 state->description = description;
278 strcpy(state->description, prefix);
279 strcat(state->description, reader_state->cmd);
280 a->archive.compression_name = state->description;
282 state->out_buf = out_buf;
283 state->out_buf_len = out_buf_len;
285 state->child_in_buf = buff;
286 state->child_in_buf_avail = n;
288 if ((state->child = __archive_create_child(reader_state->cmd,
289 &state->child_stdin, &state->child_stdout)) == -1) {
290 free(state->out_buf);
292 archive_set_error(&a->archive, EINVAL,
293 "Can't initialise filter");
298 self->read = program_source_read;
300 self->close = program_source_close;
301 self->upstream = upstream;
304 /* XXX Check that we can read at least one byte? */
309 program_source_read(struct archive_read_source *self, const void **buff)
311 struct program_source *state;
312 ssize_t bytes, total;
315 state = (struct program_source *)self->data;
319 while (state->child_stdout != -1) {
320 bytes = child_read(self, p, state->out_buf_len - total);
326 /* TODO: fix this */ /* a->archive.raw_position += bytes_read; */
329 *buff = state->out_buf;
334 program_source_close(struct archive_read_source *self)
336 struct program_source *state;
339 state = (struct program_source *)self->data;
341 /* Shut down the child. */
342 if (state->child_stdin != -1)
343 close(state->child_stdin);
344 if (state->child_stdout != -1)
345 close(state->child_stdout);
346 while (waitpid(state->child, &status, 0) == -1 && errno == EINTR)
349 /* Release our private data. */
350 free(state->out_buf);
351 free(state->description);
358 #endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */