diff --git a/doc/ACKNOWLEDGEMENTS.md b/doc/ACKNOWLEDGEMENTS.md index 661175b..029955f 100644 --- a/doc/ACKNOWLEDGEMENTS.md +++ b/doc/ACKNOWLEDGEMENTS.md @@ -51,7 +51,7 @@ is acknowledged and greatly appreciated: * Kim Krecht - suggested buffer fill status and last bytes output display options * Cristian Ciupitu , Josh Stone - pointed out file descriptor leak with helpful suggestions (Josh Stone initially noticed the missing close) * Jan Seda - found issue with `splice()` and *SPLICE_F_NONBLOCK* causing slowdown - * André Stapf - pointed out formatting problem e.g. 13GB -> 13.1GB which should be shown 13.0GB -> 13.1GB; highlighted on-startup row swapping in "`-c`" + * André Stapf - pointed out formatting problem e.g. 13GB -> 13.1GB which should be shown 13.0GB -> 13.1GB; highlighted on-startup row swapping in "`-c`", and suggested "`--discard`" * Damon Harper - suggested "`-D`" / "`--delay-start`" option * Ganaël Laplanche - provided patch for `lstat64()` on systems that do not support it * Peter Korsgaard - provided similar patch for `lstat64()`, specifically for uClibc support; provided AIX cross-compilation patch to fix bug in "`-lc128`" check diff --git a/doc/NEWS.md b/doc/NEWS.md index b7d63fc..c6648d7 100644 --- a/doc/NEWS.md +++ b/doc/NEWS.md @@ -2,6 +2,7 @@ * feature: new "`--enable-static`" option to "`configure`" for static builds ([#75](https://codeberg.org/a-j-wood/pv/pull/75)) * feature: now uses `posix_fadvise()` like `cat`(1) does, to improve efficiency ([#39](https://codeberg.org/a-j-wood/pv/issues/39)) + * feature: new "`--discard`" option to discard input as if writing to */dev/null* ([#42](https://codeberg.org/a-j-wood/pv/issues/42)) * security: with "`--pidfile`", write to a temporary file and rename it into place, to improve security * security: keep self-contained copies of name and format string in PV internal state for memory safety * fix: auto-calculate total line count with "`--line-mode`" when all inputs are regular files diff --git a/doc/TODO.md b/doc/TODO.md index 471f502..8a90e3c 100644 --- a/doc/TODO.md +++ b/doc/TODO.md @@ -29,7 +29,6 @@ Feature requests * ([#38](https://codeberg.org/a-j-wood/pv/issues/38)) Reset ETA on *SIGUSR1* (Jacek Wielemborek - Jan 2019) * ([#40](https://codeberg.org/a-j-wood/pv/issues/40)) Permit "`-c`" with "`-d PID:FD`", reject "`-N`" with "`-d PID`" (Norman Rasmussen - Nov 2020) * ([#41](https://codeberg.org/a-j-wood/pv/issues/41)) Improve how backwards-moving reads are shown in "`--watchfd`" (Ryan Cooley - Dec 2017) - * ([#42](https://codeberg.org/a-j-wood/pv/issues/42)) Option to discard stdin so nothing is written to stdout (André Stapf - Apr 2017) * ([#43](https://codeberg.org/a-j-wood/pv/issues/43)) Differentiate between "`--eta`" and "`--fineta`" in display (André Stapf - Apr 2017) * ([#45](https://codeberg.org/a-j-wood/pv/issues/45)) Option "`--sparse`" (with block size option) to write sparse output (Andriy Galetski - Apr 2019) * ([#46](https://codeberg.org/a-j-wood/pv/issues/46)) Option to show speed gauge (% max speed) if progress not known (Ryan Cooley - Jun 2019) diff --git a/doc/pv.1 b/doc/pv.1 index 6c9cfe6..6c91ae5 100644 --- a/doc/pv.1 +++ b/doc/pv.1 @@ -366,11 +366,14 @@ but means that the transfer buffer may not be used. This prevents .B \-A and .B \-T -from working, and makes +from working, cannot work with +.BR \-X , +and makes .B \-B redundant, so using .BR \-A , .BR \-T , +.BR \-X , or .B \-B automatically switches on @@ -420,6 +423,15 @@ of filesystems in a single .B pv call. Use this option with caution. .TP +.B \-X, \-\-discard +Instead of transferring input data to standard output, discard it. This is +equivalent to redirecting standard output to +.IR /dev/null , +except that +.BR write (2) +is never called. Implies +.BR \-C . +.TP .B \-d PID[:FD], \-\-watchfd PID[:FD] Instead of transferring data, watch file descriptor .B FD diff --git a/src/include/options.h b/src/include/options.h index 012363a..d62646d 100644 --- a/src/include/options.h +++ b/src/include/options.h @@ -45,6 +45,7 @@ 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 */ double interval; /* interval between updates */ double delay_start; /* delay before first display */ unsigned int watch_pid; /* process to watch fds of */ diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 82a06a4..4405ace 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -97,6 +97,7 @@ struct pvstate_s { bool direct_io; /* set if O_DIRECT is to be used */ bool direct_io_changed; /* set when direct_io is changed */ bool no_splice; /* never use splice() */ + bool discard_input; /* write nothing to stdout */ unsigned long long rate_limit; /* rate limit, in bytes per second */ unsigned long long target_buffer_size; /* buffer size (0=default) */ unsigned long long size; /* total size of data */ diff --git a/src/include/pv.h b/src/include/pv.h index 177cc76..aefc281 100644 --- a/src/include/pv.h +++ b/src/include/pv.h @@ -116,6 +116,7 @@ extern void pv_state_direct_io_set(pvstate_t, bool); extern void pv_state_rate_limit_set(pvstate_t, unsigned long long); extern void pv_state_target_buffer_size_set(pvstate_t, unsigned long long); extern void pv_state_no_splice_set(pvstate_t, bool); +extern void pv_state_discard_input_set(pvstate_t, bool); extern void pv_state_size_set(pvstate_t, unsigned long long); extern void pv_state_interval_set(pvstate_t, double); extern void pv_state_width_set(pvstate_t, unsigned int); diff --git a/src/main/help.c b/src/main/help.c index 1d4ca93..41c5a0a 100644 --- a/src/main/help.c +++ b/src/main/help.c @@ -377,6 +377,9 @@ void display_help(void) { "-K", "--direct-io", NULL, N_("use direct I/O to bypass cache"), { 0, 0, 0, 0} }, + { "-X", "--discard", NULL, + N_("discard input instead of writing to output"), + { 0, 0, 0, 0} }, #ifdef HAVE_IPC { "-R", "--remote", N_("PID"), N_("update settings of process PID"), diff --git a/src/main/main.c b/src/main/main.c index 808315a..6671d44 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -273,6 +273,7 @@ int main(int argc, char **argv) pv_state_stop_at_size_set(state, opts->stop_at_size); pv_state_sync_after_write_set(state, opts->sync_after_write); pv_state_direct_io_set(state, opts->direct_io); + pv_state_discard_input_set(state, opts->discard_input); pv_state_rate_limit_set(state, opts->rate_limit); pv_state_target_buffer_size_set(state, opts->buffer_size); pv_state_no_splice_set(state, opts->no_splice); diff --git a/src/main/options.c b/src/main/options.c index 46c1d9c..13a3980 100644 --- a/src/main/options.c +++ b/src/main/options.c @@ -172,6 +172,7 @@ opts_t opts_parse(unsigned int argc, char **argv) { "stop-at-size", 0, NULL, (int) 'S' }, { "sync", 0, NULL, (int) 'Y' }, { "direct-io", 0, NULL, (int) 'K' }, + { "discard", 0, NULL, (int) 'X' }, { "remote", 1, NULL, (int) 'R' }, { "pidfile", 1, NULL, (int) 'P' }, { "watchfd", 1, NULL, (int) 'd' }, @@ -184,7 +185,7 @@ opts_t opts_parse(unsigned int argc, char **argv) /*@+nullassign@ */ int option_index = 0; #endif /* HAVE_GETOPT_LONG */ - char *short_options = "hVpteIrab8TA:fnqcWD:s:l0i:w:H:N:F:L:B:CESYKR:P:d:m:" + char *short_options = "hVpteIrab8TA:fnqcWD:s:l0i:w:H:N:F:L:B:CESYKXR:P:d:m:" #ifdef ENABLE_DEBUGGING "!:" #endif @@ -464,6 +465,10 @@ opts_t opts_parse(unsigned int argc, char **argv) case 'K': opts->direct_io = true; break; + case 'X': + opts->discard_input = true; + opts->no_splice = true; + break; case 'R': opts->remote = pv_getnum_ui(optarg); break; diff --git a/src/pv/state.c b/src/pv/state.c index 3a4c6ed..1be482b 100644 --- a/src/pv/state.c +++ b/src/pv/state.c @@ -223,6 +223,11 @@ void pv_state_direct_io_set(pvstate_t state, bool val) state->direct_io_changed = true; }; +void pv_state_discard_input_set(pvstate_t state, bool val) +{ + state->discard_input = val; +}; + void pv_state_rate_limit_set(pvstate_t state, unsigned long long val) { state->rate_limit = val; diff --git a/src/pv/transfer.c b/src/pv/transfer.c index d1d51f8..8d086d1 100644 --- a/src/pv/transfer.c +++ b/src/pv/transfer.c @@ -493,19 +493,23 @@ static int pv__transfer_read(pvstate_t state, int fd, int *eof_in, int *eof_out, * * On error, sets *eof_out to 1, sets state->written to -1, and updates * state->exit_status. + * + * If state->discard_input is true, does not actually write anything. */ static int pv__transfer_write(pvstate_t state, int *eof_in, int *eof_out, long *lineswritten) { ssize_t nwritten; - signal(SIGALRM, SIG_IGN); - alarm(1); - - nwritten = pv__transfer_write_repeated(STDOUT_FILENO, - state->transfer_buffer + - state->write_position, state->to_write, state->sync_after_write); - - alarm(0); + if (state->discard_input) { + nwritten = state->to_write; + } else { + signal(SIGALRM, SIG_IGN); + alarm(1); + nwritten = pv__transfer_write_repeated(STDOUT_FILENO, + state->transfer_buffer + + state->write_position, state->to_write, state->sync_after_write); + alarm(0); + } if (0 == nwritten) { /*