From 30763684b7ff402e8e202a87718d1a3eeab7fef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20D=C3=B8rum?= Date: Sat, 8 Jun 2024 13:30:38 +0200 Subject: [PATCH] add -o/--output option --- po/de.po | 12 ++++++------ po/fr.po | 12 ++++++------ po/pl.po | 12 ++++++------ po/pt.po | 12 ++++++------ src/include/options.h | 3 ++- src/include/pv-internal.h | 2 ++ src/include/pv.h | 1 + src/main/main.c | 14 ++++++++++++++ src/main/options.c | 13 ++++++++++++- src/pv/file.c | 32 +++++++++++++++---------------- src/pv/signal.c | 4 ++-- src/pv/state.c | 28 +++++++++++++++++++++++++++ src/pv/transfer.c | 40 ++++++++++++++++++++------------------- 13 files changed, 122 insertions(+), 63 deletions(-) diff --git a/po/de.po b/po/de.po index 01230d0..228a3df 100644 --- a/po/de.po +++ b/po/de.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2024-04-21 14:15+0100\n" +"POT-Creation-Date: 2024-06-08 12:44+0200\n" "Language: de\n" "Content-Type: text/plain; charset=UTF-8\n" "Date: 1999-06-01 15:18:29+0100\n" @@ -368,7 +368,7 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:750 src/pv/transfer.c:954 +#: src/pv/display.c:750 src/pv/transfer.c:958 msgid "buffer allocation failed" msgstr "Puffer konnte nicht allokiert werden" @@ -424,7 +424,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99 +#: src/pv/loop.c:575 src/pv/loop.c:626 src/pv/loop.c:667 src/pv/watchpid.c:99 #: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128 #: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192 #: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301 @@ -468,15 +468,15 @@ msgstr "" msgid "failed to set interval timer" msgstr "" -#: src/pv/transfer.c:694 +#: src/pv/transfer.c:697 msgid "failed to clear interval timer" msgstr "" -#: src/pv/transfer.c:818 +#: src/pv/transfer.c:822 msgid "write failed" msgstr "write-Aufruf fehlgeschlagen" -#: src/pv/transfer.c:1051 +#: src/pv/transfer.c:1055 msgid "select call failed" msgstr "select-Aufruf fehlgeschlagen" diff --git a/po/fr.po b/po/fr.po index 0bc0eec..a6b67c2 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2024-04-21 14:15+0100\n" +"POT-Creation-Date: 2024-06-08 12:44+0200\n" "Language: fr\n" "Content-Type: text/plain; charset=UTF-8\n" "Date: 1999-06-01 15:18:29+0100\n" @@ -373,7 +373,7 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:750 src/pv/transfer.c:954 +#: src/pv/display.c:750 src/pv/transfer.c:958 msgid "buffer allocation failed" msgstr "échec de l'allocation de mémoire tampon" @@ -429,7 +429,7 @@ msgstr "(aucun)" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99 +#: src/pv/loop.c:575 src/pv/loop.c:626 src/pv/loop.c:667 src/pv/watchpid.c:99 #: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128 #: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192 #: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301 @@ -473,15 +473,15 @@ msgstr "aucun tampon de transfert alloué" msgid "failed to set interval timer" msgstr "" -#: src/pv/transfer.c:694 +#: src/pv/transfer.c:697 msgid "failed to clear interval timer" msgstr "" -#: src/pv/transfer.c:818 +#: src/pv/transfer.c:822 msgid "write failed" msgstr "l'écriture a échoué" -#: src/pv/transfer.c:1051 +#: src/pv/transfer.c:1055 msgid "select call failed" msgstr "l'appel de sélection a échoué" diff --git a/po/pl.po b/po/pl.po index 1741a5d..6a01fc9 100644 --- a/po/pl.po +++ b/po/pl.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2024-04-21 14:15+0100\n" +"POT-Creation-Date: 2024-06-08 12:44+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -357,7 +357,7 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:750 src/pv/transfer.c:954 +#: src/pv/display.c:750 src/pv/transfer.c:958 msgid "buffer allocation failed" msgstr "nie udało się zaalokować bufora" @@ -414,7 +414,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99 +#: src/pv/loop.c:575 src/pv/loop.c:626 src/pv/loop.c:667 src/pv/watchpid.c:99 #: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128 #: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192 #: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301 @@ -459,15 +459,15 @@ msgid "failed to set interval timer" msgstr "" # "Przewidywany czas ukończenia" for ETA is too long -#: src/pv/transfer.c:694 +#: src/pv/transfer.c:697 msgid "failed to clear interval timer" msgstr "" -#: src/pv/transfer.c:818 +#: src/pv/transfer.c:822 msgid "write failed" msgstr "błąd zapisu" -#: src/pv/transfer.c:1051 +#: src/pv/transfer.c:1055 msgid "select call failed" msgstr "nie udało się wywołać funkcji select" diff --git a/po/pt.po b/po/pt.po index e707b69..8703e1d 100644 --- a/po/pt.po +++ b/po/pt.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2024-04-21 14:15+0100\n" +"POT-Creation-Date: 2024-06-08 12:44+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -360,7 +360,7 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:750 src/pv/transfer.c:954 +#: src/pv/display.c:750 src/pv/transfer.c:958 msgid "buffer allocation failed" msgstr "erro alocando o buffer" @@ -416,7 +416,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99 +#: src/pv/loop.c:575 src/pv/loop.c:626 src/pv/loop.c:667 src/pv/watchpid.c:99 #: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128 #: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192 #: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301 @@ -460,15 +460,15 @@ msgstr "" msgid "failed to set interval timer" msgstr "" -#: src/pv/transfer.c:694 +#: src/pv/transfer.c:697 msgid "failed to clear interval timer" msgstr "" -#: src/pv/transfer.c:818 +#: src/pv/transfer.c:822 msgid "write failed" msgstr "erro de gravação" -#: src/pv/transfer.c:1051 +#: src/pv/transfer.c:1055 msgid "select call failed" msgstr "erro na chamada da função select" diff --git a/src/include/options.h b/src/include/options.h index 5e019f3..6dd2fc6 100644 --- a/src/include/options.h +++ b/src/include/options.h @@ -54,11 +54,12 @@ struct opts_s { /* structure describing run-time options */ bool stop_at_size; /* set if we stop at "size" bytes */ bool sync_after_write; /* set if we sync after every write */ bool direct_io; /* set if O_DIRECT is to be used */ - bool discard_input; /* set to write nothing to stdout */ + bool discard_input; /* set to write nothing to output */ double interval; /* interval between updates */ double delay_start; /* delay before first display */ pid_t watch_pid; /* process to watch fds of */ int watch_fd; /* fd to watch */ + /*@keep@*/ /*@null@*/ char *output; /* fd to write output to */ unsigned int average_rate_window; /* time window in seconds for average rate calculations */ unsigned int width; /* screen width */ unsigned int height; /* screen height */ diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index b769a72..2451220 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -123,6 +123,8 @@ struct pvstate_s { double delay_start; /* delay before first display */ pid_t watch_pid; /* process to watch fds of */ int watch_fd; /* fd to watch */ + int output_fd; /* fd to write output to */ + /*@null@*/ char *output_name; /* name of the output, for diagnostics */ unsigned int average_rate_window; /* time window in seconds for average rate calculations */ unsigned int width; /* screen width */ unsigned int height; /* screen height */ diff --git a/src/include/pv.h b/src/include/pv.h index a4cd902..f8746ca 100644 --- a/src/include/pv.h +++ b/src/include/pv.h @@ -186,6 +186,7 @@ extern void pv_state_name_set(pvstate_t, /*@null@*/ const char *); extern void pv_state_format_string_set(pvstate_t, /*@null@*/ const char *); extern void pv_state_watch_pid_set(pvstate_t, pid_t); extern void pv_state_watch_fd_set(pvstate_t, int); +extern void pv_state_output_set(pvstate_t, int, const char *); extern void pv_state_average_rate_window_set(pvstate_t, unsigned int); extern void pv_state_inputfiles(pvstate_t, unsigned int, const char **); diff --git a/src/main/main.c b/src/main/main.c index be1b63a..4411270 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -300,6 +300,20 @@ int main(int argc, char **argv) opts->fineta, opts->rate, opts->average_rate, opts->bytes, opts->bufpercent, opts->lastwritten, opts->name); + /* + * Set output file, treating no output or "-" as stdout + */ + if (NULL == opts->output || 0 == strcmp(opts->output, "-")) { + pv_state_output_set(state, STDOUT_FILENO, "(stdout)"); + } else { + int fd = open(opts->output, O_WRONLY | O_CREAT); + if (fd < 0) { + fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->output, strerror(errno)); + return 1; + } + pv_state_output_set(state, fd, opts->output); + } + #ifdef MAKE_STDOUT_NONBLOCKING /* * Try and make standard output use non-blocking I/O. diff --git a/src/main/options.c b/src/main/options.c index a0be278..fe8af2d 100644 --- a/src/main/options.c +++ b/src/main/options.c @@ -44,6 +44,8 @@ void opts_free( /*@only@ */ opts_t opts) free(opts->format); if (NULL != opts->pidfile) free(opts->pidfile); + if (NULL != opts->output) + free(opts->output); if (NULL != opts->argv) free(opts->argv); /*@+keeptrans@ */ @@ -143,6 +145,7 @@ opts_t opts_parse(unsigned int argc, char **argv) { "remote", 1, NULL, (int) 'R' }, { "pidfile", 1, NULL, (int) 'P' }, { "watchfd", 1, NULL, (int) 'd' }, + { "output", 1, NULL, (int) 'o' }, { "average-rate-window", 1, NULL, (int) 'm' }, #ifdef ENABLE_DEBUGGING { "debug", 1, NULL, (int) '!' }, @@ -152,7 +155,7 @@ opts_t opts_parse(unsigned int argc, char **argv) /*@+nullassign@ */ int option_index = 0; #endif /* HAVE_GETOPT_LONG */ - char *short_options = "hVpteIrab8kTA:fnqcWD:s:l0i:w:H:N:F:L:B:CEZ:SYKXR:P:d:m:" + char *short_options = "hVpteIrab8kTA:fnqcWD:s:l0i:w:H:N:F:L:B:CEZ:SYKXR:P:d:m:o:" #ifdef ENABLE_DEBUGGING "!:" #endif @@ -476,6 +479,14 @@ opts_t opts_parse(unsigned int argc, char **argv) opts->watch_pid = (pid_t) parse_pid; opts->watch_fd = parse_fd; break; + case 'o': + opts->output = pv_strdup(optarg); + if (NULL == opts->output) { + fprintf(stderr, "%s: -o: %s\n", opts->program_name, strerror(errno)); + opts_free(opts); + return NULL; + } + break; case 'm': opts->average_rate_window = pv_getnum_count(optarg, opts->decimal_units); break; diff --git a/src/pv/file.c b/src/pv/file.c index eaf09ba..3720c45 100644 --- a/src/pv/file.c +++ b/src/pv/file.c @@ -127,24 +127,24 @@ static off_t pv_calc_total_bytes(pvstate_t state) * input, but we are writing to a block device, then use the size of * the output block device. * - * Further modified to check that stdout is not in append-only mode + * Further modified to check that output is not in append-only mode * and that we can seek back to the start after getting the size. */ if (total < 1) { int rc; - rc = fstat(STDOUT_FILENO, &sb); + rc = fstat(state->control.output_fd, &sb); if ((0 == rc) && S_ISBLK(sb.st_mode) - && (0 == (fcntl(STDOUT_FILENO, F_GETFL) & O_APPEND))) { + && (0 == (fcntl(state->control.output_fd, F_GETFL) & O_APPEND))) { off_t end_position; - end_position = lseek(STDOUT_FILENO, 0, SEEK_END); + end_position = lseek(state->control.output_fd, 0, SEEK_END); total = 0; if (end_position > 0) { total = end_position; } - if (lseek(STDOUT_FILENO, 0, SEEK_SET) != 0) { - pv_error(state, "%s: %s: %s", "(stdout)", + if (lseek(state->control.output_fd, 0, SEEK_SET) != 0) { + pv_error(state, "%s: %s: %s", state->control.output_name, _("failed to seek to start of output"), strerror(errno)); state->status.exit_status |= 2; } @@ -277,7 +277,7 @@ off_t pv_calc_total_size(pvstate_t state) * Close the given file descriptor and open the next one, whose number in * the list is "filenum", returning the new file descriptor (or negative on * error). It is an error if the next input file is the same as the file - * stdout is pointing to. + * the output is pointing to. * * Updates state->status.current_input_file in the process. */ @@ -286,7 +286,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) struct stat isb; struct stat osb; int fd; - bool input_file_is_stdout; + bool input_file_is_output; if (oldfd >= 0) { if (0 != close(oldfd)) { @@ -327,7 +327,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) return -1; } - if (0 != fstat(STDOUT_FILENO, &osb)) { + if (0 != fstat(state->control.output_fd, &osb)) { pv_error(state, "%s: %s", _("failed to stat output file"), strerror(errno)); (void) close(fd); state->status.exit_status |= 2; @@ -335,21 +335,21 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) } /* - * Check that this new input file is not the same as stdout's + * Check that this new input file is not the same as output's * destination. This restriction is ignored for anything other * than a regular file or block device. */ - input_file_is_stdout = true; + input_file_is_output = true; if (isb.st_dev != osb.st_dev) - input_file_is_stdout = false; + input_file_is_output = false; if (isb.st_ino != osb.st_ino) - input_file_is_stdout = false; + input_file_is_output = false; if (0 != isatty(fd)) - input_file_is_stdout = false; + input_file_is_output = false; if ((!S_ISREG(isb.st_mode)) && (!S_ISBLK(isb.st_mode))) - input_file_is_stdout = false; + input_file_is_output = false; - if (input_file_is_stdout) { + if (input_file_is_output) { pv_error(state, "%s: %s", _("input file is output file"), NULL == state->files.filename ? "-" : state->files.filename[filenum]); (void) close(fd); diff --git a/src/pv/signal.c b/src/pv/signal.c index b519833..9640f66 100644 --- a/src/pv/signal.c +++ b/src/pv/signal.c @@ -289,8 +289,8 @@ void pv_sig_init(pvstate_t state) */ /* - * Ignore SIGPIPE, so we don't die if stdout is a pipe and the other - * end closes unexpectedly. + * Ignore SIGPIPE, so we don't die if the output is a pipe and the + * other end closes unexpectedly. */ sa.sa_handler = SIG_IGN; (void) sigemptyset(&(sa.sa_mask)); diff --git a/src/pv/state.c b/src/pv/state.c index cae353a..95e1c86 100644 --- a/src/pv/state.c +++ b/src/pv/state.c @@ -67,6 +67,7 @@ pvstate_t pv_state_alloc(const char *program_name) state->control.watch_pid = 0; state->control.watch_fd = -1; + state->control.output_fd = -1; #ifdef HAVE_IPC state->cursor.shmid = -1; state->cursor.pvcount = 1; @@ -124,6 +125,23 @@ void pv_state_free(pvstate_t state) state->control.format_string = NULL; } + if (NULL != state->control.output_name) { + free(state->control.output_name); + state->control.output_name = NULL; + } + + if (NULL != state->control.output_name) { + free(state->control.output_name); + state->control.output_name = NULL; + } + + if (state->control.output_fd >= 0) { + if (STDOUT_FILENO != state->control.output_fd) { + close(state->control.output_fd); + } + state->control.output_fd = -1; + } + /*@-keeptrans@ */ if (NULL != state->transfer.transfer_buffer) free(state->transfer.transfer_buffer); @@ -347,6 +365,16 @@ void pv_state_watch_fd_set(pvstate_t state, int val) state->control.watch_fd = val; } +void pv_state_output_set(pvstate_t state, int fd, const char *name) +{ + if (NULL != state->control.output_name) + free(state->control.output_name); + if (state->control.output_fd >= 0 && state->control.output_fd != STDOUT_FILENO) + close(state->control.output_fd); + state->control.output_fd = fd; + state->control.output_name = strdup(name); +} + void pv_state_average_rate_window_set(pvstate_t state, unsigned int val) { if (val < 1) diff --git a/src/pv/transfer.c b/src/pv/transfer.c index eb44b6f..0d5419f 100644 --- a/src/pv/transfer.c +++ b/src/pv/transfer.c @@ -345,7 +345,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou /*@-nullpass@ */ /*@-type@ */ /* splint doesn't know about splice */ - nread = splice(fd, NULL, STDOUT_FILENO, NULL, bytes_to_splice, SPLICE_F_MORE); + nread = splice(fd, NULL, state->control.output_fd, NULL, bytes_to_splice, SPLICE_F_MORE); /*@+type@ */ /*@+nullpass@ */ @@ -370,7 +370,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * error, we cannot skip it, so set * "do_not_skip_errors". */ - if ((fdatasync(STDOUT_FILENO) < 0) + if ((fdatasync(state->control.output_fd) < 0) && (EIO == errno)) { nread = -1; do_not_skip_errors = true; @@ -612,13 +612,13 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou /* - * Write state->transfer.to_write bytes of data from the transfer buffer to stdout. + * Write state->transfer.to_write bytes of data from the transfer buffer to the output. * Returns zero if there was a transient error and we need to return 0 from * pv_transfer, otherwise returns 1. * * Updates state->transfer.write_position by moving it on by the number of bytes * written; adds the number of bytes written to state->transfer.written; sets - * *eof_out to true, on stdout EOF, or when the write position catches up + * *eof_out to true, on output EOF, or when the write position catches up * with the read position AND *eof_in is true (meaning we've reached the end * of data). * @@ -681,7 +681,7 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long debug("%s", "setting alarm"); #endif /* HAVE_SETITIMER */ debug("%s: %ld %s", "beginning write attempt", (long) (state->transfer.to_write), "bytes"); - nwritten = pv__transfer_write_repeated(STDOUT_FILENO, + nwritten = pv__transfer_write_repeated(state->control.output_fd, state->transfer.transfer_buffer + state->transfer.write_position, (size_t) (state->transfer.to_write), @@ -706,7 +706,7 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long if (0 == nwritten) { /* - * Write returned 0 - EOF on stdout. + * Write returned 0 - EOF on output. */ *eof_out = true; return 1; @@ -842,7 +842,7 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long */ /*@null@*/ /*@only@*/ -static char *pv__allocate_aligned_buffer(int fd, size_t target_size) +static char *pv__allocate_aligned_buffer(int outfd, int infd, size_t target_size) { char *newptr; @@ -850,8 +850,8 @@ static char *pv__allocate_aligned_buffer(int fd, size_t target_size) long input_alignment, output_alignment, min_alignment; long required_alignment; - input_alignment = fd >= 0 ? fpathconf(fd, _PC_REC_XFER_ALIGN) : -1; - output_alignment = fpathconf(STDOUT_FILENO, _PC_REC_XFER_ALIGN); + input_alignment = infd >= 0 ? fpathconf(infd, _PC_REC_XFER_ALIGN) : -1; + output_alignment = fpathconf(outfd, _PC_REC_XFER_ALIGN); #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) min_alignment = sysconf(_SC_PAGESIZE); #else /* ! defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) */ @@ -928,9 +928,10 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t } } if (!(*eof_out)) { - if (0 != fcntl(STDOUT_FILENO, F_SETFL, - (state->control.direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) { - debug("%s: %s: %s", "(stdout)", "fcntl", strerror(errno)); + if (0 != fcntl(state->control.output_fd, F_SETFL, + (state->control.direct_io ? O_DIRECT : 0) | + fcntl(state->control.output_fd, F_GETFL))) { + debug("%s: %s: %s", state->control.output_name, "fcntl", strerror(errno)); } } state->control.direct_io_changed = false; @@ -953,7 +954,7 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t */ if (NULL == state->transfer.transfer_buffer) { state->transfer.transfer_buffer = - pv__allocate_aligned_buffer(fd, state->control.target_buffer_size + 32); + pv__allocate_aligned_buffer(state->control.output_fd, fd, state->control.target_buffer_size + 32); if (NULL == state->transfer.transfer_buffer) { pv_error(state, "%s: %s", _("buffer allocation failed"), strerror(errno)); state->status.exit_status |= 64; @@ -971,7 +972,8 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t */ if (state->transfer.buffer_size < state->control.target_buffer_size) { char *newptr; - newptr = pv__allocate_aligned_buffer(fd, state->control.target_buffer_size + 32); + newptr = + pv__allocate_aligned_buffer(state->control.output_fd, fd, state->control.target_buffer_size + 32); if (NULL == newptr) { /* * Reset target if realloc failed so we don't keep @@ -1031,10 +1033,10 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t /* * If we don't think we've finished writing and there's anything - * we're allowed to write, look for the stdout becoming writable. + * we're allowed to write, look for the output becoming writable. */ if ((!(*eof_out)) && (state->transfer.to_write > 0)) { - check_write_fd = STDOUT_FILENO; + check_write_fd = state->control.output_fd; } ready_to_read = false; @@ -1092,9 +1094,9 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t } /* - * If there is data to write, and stdout is ready to receive it, and - * we didn't use splice() this time, write some data. Return early - * if there was a transient write error. + * If there is data to write, and the output is ready to receive it, + * and we didn't use splice() this time, write some data. + * Return early if there was a transient write error. */ if (ready_to_write #ifdef HAVE_SPLICE