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:
parent
dff2641a67
commit
936d273c3a
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user