1228753Smm/*-
2228753Smm * Copyright (c) 2007 Joerg Sonnenberger
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24228753Smm */
25228753Smm
26228753Smm#include "archive_platform.h"
27229592Smm__FBSDID("$FreeBSD$");
28228753Smm
29228753Smm#ifdef HAVE_SYS_WAIT_H
30228753Smm#  include <sys/wait.h>
31228753Smm#endif
32228753Smm#ifdef HAVE_ERRNO_H
33228753Smm#  include <errno.h>
34228753Smm#endif
35228753Smm#ifdef HAVE_FCNTL_H
36228753Smm#  include <fcntl.h>
37228753Smm#endif
38228753Smm#ifdef HAVE_LIMITS_H
39228753Smm#  include <limits.h>
40228753Smm#endif
41228753Smm#ifdef HAVE_SIGNAL_H
42228753Smm#  include <signal.h>
43228753Smm#endif
44228753Smm#ifdef HAVE_STDLIB_H
45228753Smm#  include <stdlib.h>
46228753Smm#endif
47228753Smm#ifdef HAVE_STRING_H
48228753Smm#  include <string.h>
49228753Smm#endif
50228753Smm#ifdef HAVE_UNISTD_H
51228753Smm#  include <unistd.h>
52228753Smm#endif
53228753Smm
54228753Smm#include "archive.h"
55228753Smm#include "archive_private.h"
56228753Smm#include "archive_read_private.h"
57228753Smm
58228753Smmint
59228753Smmarchive_read_support_compression_program(struct archive *a, const char *cmd)
60228753Smm{
61228753Smm	return (archive_read_support_compression_program_signature(a, cmd, NULL, 0));
62228753Smm}
63228753Smm
64228753Smm
65228753Smm/* This capability is only available on POSIX systems. */
66228753Smm#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
67228753Smm    !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
68228753Smm
69228753Smm/*
70228753Smm * On non-Posix systems, allow the program to build, but choke if
71228753Smm * this function is actually invoked.
72228753Smm */
73228753Smmint
74228753Smmarchive_read_support_compression_program_signature(struct archive *_a,
75228753Smm    const char *cmd, void *signature, size_t signature_len)
76228753Smm{
77228753Smm	(void)_a; /* UNUSED */
78228753Smm	(void)cmd; /* UNUSED */
79228753Smm	(void)signature; /* UNUSED */
80228753Smm	(void)signature_len; /* UNUSED */
81228753Smm
82228753Smm	archive_set_error(_a, -1,
83228753Smm	    "External compression programs not supported on this platform");
84228753Smm	return (ARCHIVE_FATAL);
85228753Smm}
86228753Smm
87228753Smmint
88228753Smm__archive_read_program(struct archive_read_filter *self, const char *cmd)
89228753Smm{
90228753Smm	(void)self; /* UNUSED */
91228753Smm	(void)cmd; /* UNUSED */
92228753Smm
93228753Smm	archive_set_error(&self->archive->archive, -1,
94228753Smm	    "External compression programs not supported on this platform");
95228753Smm	return (ARCHIVE_FATAL);
96228753Smm}
97228753Smm
98228753Smm#else
99228753Smm
100228753Smm#include "filter_fork.h"
101228753Smm
102228753Smm/*
103228753Smm * The bidder object stores the command and the signature to watch for.
104228753Smm * The 'inhibit' entry here is used to ensure that unchecked filters never
105228753Smm * bid twice in the same pipeline.
106228753Smm */
107228753Smmstruct program_bidder {
108228753Smm	char *cmd;
109228753Smm	void *signature;
110228753Smm	size_t signature_len;
111228753Smm	int inhibit;
112228753Smm};
113228753Smm
114228753Smmstatic int	program_bidder_bid(struct archive_read_filter_bidder *,
115228753Smm		    struct archive_read_filter *upstream);
116228753Smmstatic int	program_bidder_init(struct archive_read_filter *);
117228753Smmstatic int	program_bidder_free(struct archive_read_filter_bidder *);
118228753Smm
119228753Smm/*
120228753Smm * The actual filter needs to track input and output data.
121228753Smm */
122228753Smmstruct program_filter {
123228753Smm	char		*description;
124228753Smm	pid_t		 child;
125228753Smm	int		 exit_status;
126228753Smm	int		 waitpid_return;
127228753Smm	int		 child_stdin, child_stdout;
128228753Smm
129228753Smm	char		*out_buf;
130228753Smm	size_t		 out_buf_len;
131228753Smm};
132228753Smm
133228753Smmstatic ssize_t	program_filter_read(struct archive_read_filter *,
134228753Smm		    const void **);
135228753Smmstatic int	program_filter_close(struct archive_read_filter *);
136228753Smm
137228753Smmint
138228753Smmarchive_read_support_compression_program_signature(struct archive *_a,
139228753Smm    const char *cmd, const void *signature, size_t signature_len)
140228753Smm{
141228753Smm	struct archive_read *a = (struct archive_read *)_a;
142228753Smm	struct archive_read_filter_bidder *bidder;
143228753Smm	struct program_bidder *state;
144228753Smm
145228753Smm	/*
146228753Smm	 * Get a bidder object from the read core.
147228753Smm	 */
148228753Smm	bidder = __archive_read_get_bidder(a);
149228753Smm	if (bidder == NULL)
150228753Smm		return (ARCHIVE_FATAL);
151228753Smm
152228753Smm	/*
153228753Smm	 * Allocate our private state.
154228753Smm	 */
155228753Smm	state = (struct program_bidder *)calloc(sizeof (*state), 1);
156228753Smm	if (state == NULL)
157228753Smm		return (ARCHIVE_FATAL);
158228753Smm	state->cmd = strdup(cmd);
159228753Smm	if (signature != NULL && signature_len > 0) {
160228753Smm		state->signature_len = signature_len;
161228753Smm		state->signature = malloc(signature_len);
162228753Smm		memcpy(state->signature, signature, signature_len);
163228753Smm	}
164228753Smm
165228753Smm	/*
166228753Smm	 * Fill in the bidder object.
167228753Smm	 */
168228753Smm	bidder->data = state;
169228753Smm	bidder->bid = program_bidder_bid;
170228753Smm	bidder->init = program_bidder_init;
171228753Smm	bidder->options = NULL;
172228753Smm	bidder->free = program_bidder_free;
173228753Smm	return (ARCHIVE_OK);
174228753Smm}
175228753Smm
176228753Smmstatic int
177228753Smmprogram_bidder_free(struct archive_read_filter_bidder *self)
178228753Smm{
179228753Smm	struct program_bidder *state = (struct program_bidder *)self->data;
180228753Smm	free(state->cmd);
181228753Smm	free(state->signature);
182228753Smm	free(self->data);
183228753Smm	return (ARCHIVE_OK);
184228753Smm}
185228753Smm
186228753Smm/*
187228753Smm * If we do have a signature, bid only if that matches.
188228753Smm *
189228753Smm * If there's no signature, we bid INT_MAX the first time
190228753Smm * we're called, then never bid again.
191228753Smm */
192228753Smmstatic int
193228753Smmprogram_bidder_bid(struct archive_read_filter_bidder *self,
194228753Smm    struct archive_read_filter *upstream)
195228753Smm{
196228753Smm	struct program_bidder *state = self->data;
197228753Smm	const char *p;
198228753Smm
199228753Smm	/* If we have a signature, use that to match. */
200228753Smm	if (state->signature_len > 0) {
201228753Smm		p = __archive_read_filter_ahead(upstream,
202228753Smm		    state->signature_len, NULL);
203228753Smm		if (p == NULL)
204228753Smm			return (0);
205228753Smm		/* No match, so don't bid. */
206228753Smm		if (memcmp(p, state->signature, state->signature_len) != 0)
207228753Smm			return (0);
208228753Smm		return ((int)state->signature_len * 8);
209228753Smm	}
210228753Smm
211228753Smm	/* Otherwise, bid once and then never bid again. */
212228753Smm	if (state->inhibit)
213228753Smm		return (0);
214228753Smm	state->inhibit = 1;
215228753Smm	return (INT_MAX);
216228753Smm}
217228753Smm
218228753Smm/*
219228753Smm * Shut down the child, return ARCHIVE_OK if it exited normally.
220228753Smm *
221228753Smm * Note that the return value is sticky; if we're called again,
222228753Smm * we won't reap the child again, but we will return the same status
223228753Smm * (including error message if the child came to a bad end).
224228753Smm */
225228753Smmstatic int
226228753Smmchild_stop(struct archive_read_filter *self, struct program_filter *state)
227228753Smm{
228228753Smm	/* Close our side of the I/O with the child. */
229228753Smm	if (state->child_stdin != -1) {
230228753Smm		close(state->child_stdin);
231228753Smm		state->child_stdin = -1;
232228753Smm	}
233228753Smm	if (state->child_stdout != -1) {
234228753Smm		close(state->child_stdout);
235228753Smm		state->child_stdout = -1;
236228753Smm	}
237228753Smm
238228753Smm	if (state->child != 0) {
239228753Smm		/* Reap the child. */
240228753Smm		do {
241228753Smm			state->waitpid_return
242228753Smm			    = waitpid(state->child, &state->exit_status, 0);
243228753Smm		} while (state->waitpid_return == -1 && errno == EINTR);
244228753Smm		state->child = 0;
245228753Smm	}
246228753Smm
247228753Smm	if (state->waitpid_return < 0) {
248228753Smm		/* waitpid() failed?  This is ugly. */
249228753Smm		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
250228753Smm		    "Child process exited badly");
251228753Smm		return (ARCHIVE_WARN);
252228753Smm	}
253228753Smm
254228753Smm#if !defined(_WIN32) || defined(__CYGWIN__)
255228753Smm	if (WIFSIGNALED(state->exit_status)) {
256228753Smm#ifdef SIGPIPE
257228753Smm		/* If the child died because we stopped reading before
258228753Smm		 * it was done, that's okay.  Some archive formats
259228753Smm		 * have padding at the end that we routinely ignore. */
260228753Smm		/* The alternative to this would be to add a step
261228753Smm		 * before close(child_stdout) above to read from the
262228753Smm		 * child until the child has no more to write. */
263228753Smm		if (WTERMSIG(state->exit_status) == SIGPIPE)
264228753Smm			return (ARCHIVE_OK);
265228753Smm#endif
266228753Smm		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
267228753Smm		    "Child process exited with signal %d",
268228753Smm		    WTERMSIG(state->exit_status));
269228753Smm		return (ARCHIVE_WARN);
270228753Smm	}
271228753Smm#endif /* !_WIN32 || __CYGWIN__ */
272228753Smm
273228753Smm	if (WIFEXITED(state->exit_status)) {
274228753Smm		if (WEXITSTATUS(state->exit_status) == 0)
275228753Smm			return (ARCHIVE_OK);
276228753Smm
277228753Smm		archive_set_error(&self->archive->archive,
278228753Smm		    ARCHIVE_ERRNO_MISC,
279228753Smm		    "Child process exited with status %d",
280228753Smm		    WEXITSTATUS(state->exit_status));
281228753Smm		return (ARCHIVE_WARN);
282228753Smm	}
283228753Smm
284228753Smm	return (ARCHIVE_WARN);
285228753Smm}
286228753Smm
287228753Smm/*
288228753Smm * Use select() to decide whether the child is ready for read or write.
289228753Smm */
290228753Smmstatic ssize_t
291228753Smmchild_read(struct archive_read_filter *self, char *buf, size_t buf_len)
292228753Smm{
293228753Smm	struct program_filter *state = self->data;
294228753Smm	ssize_t ret, requested, avail;
295228753Smm	const char *p;
296228753Smm
297228753Smm	requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
298228753Smm
299228753Smm	for (;;) {
300228753Smm		do {
301228753Smm			ret = read(state->child_stdout, buf, requested);
302228753Smm		} while (ret == -1 && errno == EINTR);
303228753Smm
304228753Smm		if (ret > 0)
305228753Smm			return (ret);
306228753Smm		if (ret == 0 || (ret == -1 && errno == EPIPE))
307228753Smm			/* Child has closed its output; reap the child
308228753Smm			 * and return the status. */
309228753Smm			return (child_stop(self, state));
310228753Smm		if (ret == -1 && errno != EAGAIN)
311228753Smm			return (-1);
312228753Smm
313228753Smm		if (state->child_stdin == -1) {
314228753Smm			/* Block until child has some I/O ready. */
315228753Smm			__archive_check_child(state->child_stdin,
316228753Smm			    state->child_stdout);
317228753Smm			continue;
318228753Smm		}
319228753Smm
320228753Smm		/* Get some more data from upstream. */
321228753Smm		p = __archive_read_filter_ahead(self->upstream, 1, &avail);
322228753Smm		if (p == NULL) {
323228753Smm			close(state->child_stdin);
324228753Smm			state->child_stdin = -1;
325228753Smm			fcntl(state->child_stdout, F_SETFL, 0);
326228753Smm			if (avail < 0)
327228753Smm				return (avail);
328228753Smm			continue;
329228753Smm		}
330228753Smm
331228753Smm		do {
332228753Smm			ret = write(state->child_stdin, p, avail);
333228753Smm		} while (ret == -1 && errno == EINTR);
334228753Smm
335228753Smm		if (ret > 0) {
336228753Smm			/* Consume whatever we managed to write. */
337228753Smm			__archive_read_filter_consume(self->upstream, ret);
338228753Smm		} else if (ret == -1 && errno == EAGAIN) {
339228753Smm			/* Block until child has some I/O ready. */
340228753Smm			__archive_check_child(state->child_stdin,
341228753Smm			    state->child_stdout);
342228753Smm		} else {
343228753Smm			/* Write failed. */
344228753Smm			close(state->child_stdin);
345228753Smm			state->child_stdin = -1;
346228753Smm			fcntl(state->child_stdout, F_SETFL, 0);
347228753Smm			/* If it was a bad error, we're done; otherwise
348228753Smm			 * it was EPIPE or EOF, and we can still read
349228753Smm			 * from the child. */
350228753Smm			if (ret == -1 && errno != EPIPE)
351228753Smm				return (-1);
352228753Smm		}
353228753Smm	}
354228753Smm}
355228753Smm
356228753Smmint
357228753Smm__archive_read_program(struct archive_read_filter *self, const char *cmd)
358228753Smm{
359228753Smm	struct program_filter	*state;
360228753Smm	static const size_t out_buf_len = 65536;
361228753Smm	char *out_buf;
362228753Smm	char *description;
363228753Smm	const char *prefix = "Program: ";
364228753Smm
365228753Smm	state = (struct program_filter *)calloc(1, sizeof(*state));
366228753Smm	out_buf = (char *)malloc(out_buf_len);
367228753Smm	description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
368228753Smm	if (state == NULL || out_buf == NULL || description == NULL) {
369228753Smm		archive_set_error(&self->archive->archive, ENOMEM,
370228753Smm		    "Can't allocate input data");
371228753Smm		free(state);
372228753Smm		free(out_buf);
373228753Smm		free(description);
374228753Smm		return (ARCHIVE_FATAL);
375228753Smm	}
376228753Smm
377228753Smm	self->code = ARCHIVE_COMPRESSION_PROGRAM;
378228753Smm	state->description = description;
379228753Smm	strcpy(state->description, prefix);
380228753Smm	strcat(state->description, cmd);
381228753Smm	self->name = state->description;
382228753Smm
383228753Smm	state->out_buf = out_buf;
384228753Smm	state->out_buf_len = out_buf_len;
385228753Smm
386228753Smm	if ((state->child = __archive_create_child(cmd,
387228753Smm		 &state->child_stdin, &state->child_stdout)) == -1) {
388228753Smm		free(state->out_buf);
389228753Smm		free(state);
390228753Smm		archive_set_error(&self->archive->archive, EINVAL,
391228753Smm		    "Can't initialise filter");
392228753Smm		return (ARCHIVE_FATAL);
393228753Smm	}
394228753Smm
395228753Smm	self->data = state;
396228753Smm	self->read = program_filter_read;
397228753Smm	self->skip = NULL;
398228753Smm	self->close = program_filter_close;
399228753Smm
400228753Smm	/* XXX Check that we can read at least one byte? */
401228753Smm	return (ARCHIVE_OK);
402228753Smm}
403228753Smm
404228753Smmstatic int
405228753Smmprogram_bidder_init(struct archive_read_filter *self)
406228753Smm{
407228753Smm	struct program_bidder   *bidder_state;
408228753Smm
409228753Smm	bidder_state = (struct program_bidder *)self->bidder->data;
410228753Smm	return (__archive_read_program(self, bidder_state->cmd));
411228753Smm}
412228753Smm
413228753Smmstatic ssize_t
414228753Smmprogram_filter_read(struct archive_read_filter *self, const void **buff)
415228753Smm{
416228753Smm	struct program_filter *state;
417228753Smm	ssize_t bytes;
418228753Smm	size_t total;
419228753Smm	char *p;
420228753Smm
421228753Smm	state = (struct program_filter *)self->data;
422228753Smm
423228753Smm	total = 0;
424228753Smm	p = state->out_buf;
425228753Smm	while (state->child_stdout != -1 && total < state->out_buf_len) {
426228753Smm		bytes = child_read(self, p, state->out_buf_len - total);
427228753Smm		if (bytes < 0)
428228753Smm			/* No recovery is possible if we can no longer
429228753Smm			 * read from the child. */
430228753Smm			return (ARCHIVE_FATAL);
431228753Smm		if (bytes == 0)
432228753Smm			/* We got EOF from the child. */
433228753Smm			break;
434228753Smm		total += bytes;
435228753Smm		p += bytes;
436228753Smm	}
437228753Smm
438228753Smm	*buff = state->out_buf;
439228753Smm	return (total);
440228753Smm}
441228753Smm
442228753Smmstatic int
443228753Smmprogram_filter_close(struct archive_read_filter *self)
444228753Smm{
445228753Smm	struct program_filter	*state;
446228753Smm	int e;
447228753Smm
448228753Smm	state = (struct program_filter *)self->data;
449228753Smm	e = child_stop(self, state);
450228753Smm
451228753Smm	/* Release our private data. */
452228753Smm	free(state->out_buf);
453228753Smm	free(state->description);
454228753Smm	free(state);
455228753Smm
456228753Smm	return (e);
457228753Smm}
458228753Smm
459228753Smm#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
460