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