A number of minor corrections to the support for external compression

programs:
  * Support platforms that have fork() but not vfork()
  * Don't write(), select(), or poll() against closed file descriptors
This commit is contained in:
Tim Kientzle 2008-06-15 10:45:57 +00:00
parent dff2641a67
commit 936d273c3a
3 changed files with 45 additions and 13 deletions

View File

@ -28,7 +28,8 @@ __FBSDID("$FreeBSD$");
/* This capability is only available on POSIX systems. */
#if !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL)
#if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
!(defined(HAVE_FORK) || defined(HAVE_VFORK))
/*
* On non-Posix systems, allow the program to build, but choke if
@ -177,6 +178,12 @@ child_read(struct archive_read *a, char *buf, size_t buf_len)
state->child_in_buf_avail = ret;
}
if (state->child_stdin == -1) {
fcntl(state->child_stdout, F_SETFL, 0);
__archive_check_child(state->child_stdin, state->child_stdout);
goto restart_read;
}
do {
ret = write(state->child_stdin, state->child_in_buf,
state->child_in_buf_avail);
@ -191,7 +198,7 @@ child_read(struct archive_read *a, char *buf, size_t buf_len)
goto restart_read;
} else if (ret == 0 || (ret == -1 && errno == EPIPE)) {
close(state->child_stdin);
state->child_stdout = -1;
state->child_stdin = -1;
fcntl(state->child_stdout, F_SETFL, 0);
goto restart_read;
} else {

View File

@ -28,7 +28,9 @@
__FBSDID("$FreeBSD$");
/* This capability is only available on POSIX systems. */
#if !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL)
#if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
!(defined(HAVE_FORK) || defined(HAVE_VFORK))
#include "archive.h"
/*
* On non-Posix systems, allow the program to build, but choke if
@ -180,6 +182,12 @@ child_write(struct archive_write *a, const char *buf, size_t buf_len)
if (ret == -1 && errno != EAGAIN)
return (-1);
if (state->child_stdout == -1) {
fcntl(state->child_stdin, F_SETFL, 0);
__archive_check_child(state->child_stdin, state->child_stdout);
goto restart_write;
}
do {
ret = read(state->child_stdout,
state->child_buf + state->child_buf_avail,

View File

@ -26,7 +26,8 @@
#include "archive_platform.h"
/* This capability is only available on POSIX systems. */
#if defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL)
#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \
(defined(HAVE_FORK) || defined(HAVE_VFORK))
__FBSDID("$FreeBSD$");
@ -75,7 +76,11 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
stdout_pipe[1] = tmp;
}
#if HAVE_VFORK
switch ((child = vfork())) {
#else
switch ((child = fork())) {
#endif
case -1:
goto stdout_opened;
case 0:
@ -118,23 +123,35 @@ __archive_check_child(int in, int out)
{
#if defined(HAVE_POLL)
struct pollfd fds[2];
int idx;
fds[0].fd = in;
fds[0].events = POLLOUT;
fds[1].fd = out;
fds[1].events = POLLIN;
idx = 0;
if (in != -1) {
fds[idx].fd = in;
fds[idx].events = POLLOUT;
++idx;
}
if (out != -1) {
fds[idx].fd = out;
fds[idx].events = POLLIN;
++idx;
}
poll(fds, 2, -1); /* -1 == INFTIM, wait forever */
poll(fds, idx, -1); /* -1 == INFTIM, wait forever */
#elif defined(HAVE_SELECT)
fd_set fds_in, fds_out, fds_error;
FD_ZERO(&fds_in);
FD_SET(out, &fds_in);
FD_ZERO(&fds_out);
FD_SET(in, &fds_out);
FD_ZERO(&fds_error);
FD_SET(in, &fds_error);
FD_SET(out, &fds_error);
if (out != -1) {
FD_SET(out, &fds_in);
FD_SET(out, &fds_error);
}
if (in != -1) {
FD_SET(in, &fds_out);
FD_SET(in, &fds_error);
}
select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL);
#else
sleep(1);