diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/shared/pretty-print.c | 18 | ||||
-rw-r--r-- | src/shared/pretty-print.h | 29 | ||||
-rw-r--r-- | src/sysupdate/updatectl.c | 5 |
3 files changed, 32 insertions, 20 deletions
diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index 9d3f6be1f4..0360fa9d72 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -531,28 +531,14 @@ void clear_progress_bar_impl(const char *prefix) { } void draw_progress_bar(const char *prefix, double percentage) { - /* We are going output a bunch of small strings that shall appear as a single line to STDERR which is * unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty * as a single buffer, to make things more efficient. */ - char buffer[LONG_LINE_MAX]; - setvbuf(stderr, buffer, _IOFBF, sizeof(buffer)); - + WITH_BUFFERED_STDERR; draw_progress_bar_impl(prefix, percentage); - - fflush(stderr); - - /* Disable buffering again */ - setvbuf(stderr, NULL, _IONBF, 0); } void clear_progress_bar(const char *prefix) { - char buffer[LONG_LINE_MAX]; - setvbuf(stderr, buffer, _IOFBF, sizeof(buffer)); - + WITH_BUFFERED_STDERR; clear_progress_bar_impl(prefix); - - fflush(stderr); - - setvbuf(stderr, NULL, _IONBF, 0); } diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h index 4efac1d7ed..446f305b73 100644 --- a/src/shared/pretty-print.h +++ b/src/shared/pretty-print.h @@ -57,3 +57,32 @@ void draw_progress_bar(const char *prefix, double percentage); void clear_progress_bar(const char *prefix); void draw_progress_bar_impl(const char *prefix, double percentage); void clear_progress_bar_impl(const char *prefix); + +static inline FILE* enable_buffering(FILE *f, char *buffer, size_t size) { + assert(f); + assert(buffer); + assert(size > 0); + + if (setvbuf(f, buffer, _IOFBF, size) != 0) + return NULL; + + return f; +} + +static inline void fflush_and_disable_bufferingp(FILE **p) { + assert(p); + + if (*p) { + fflush(*p); + setvbuf(*p, NULL, _IONBF, 0); /* Disable buffering again. */ + } +} + +/* Even though the macro below is slightly generic, but it may not work most streams except for stderr, + * as stdout is buffered and fopen() enables buffering by default. */ +#define _WITH_BUFFERED_STREAM(f, size, p) \ + _unused_ _cleanup_(fflush_and_disable_bufferingp) FILE *p = \ + enable_buffering(f, (char[size]) {}, size) + +#define WITH_BUFFERED_STDERR \ + _WITH_BUFFERED_STREAM(stderr, LONG_LINE_MAX, UNIQ_T(p, UNIQ)) diff --git a/src/sysupdate/updatectl.c b/src/sysupdate/updatectl.c index 87dd78b4c6..fad68ebd88 100644 --- a/src/sysupdate/updatectl.c +++ b/src/sysupdate/updatectl.c @@ -798,8 +798,7 @@ static int update_render_progress(sd_event_source *source, void *userdata) { /* We're outputting lots of small strings to STDERR, which is unbuffered by default. So let's turn * on full buffering, so we pass this all to the TTY in one go, to make things more efficient */ - char buffer[LONG_LINE_MAX]; - setvbuf(stderr, buffer, _IOFBF, sizeof(buffer)); + WITH_BUFFERED_STDERR; if (!terminal_is_dumb()) { for (size_t i = 0; i <= n; i++) @@ -855,8 +854,6 @@ static int update_render_progress(sd_event_source *source, void *userdata) { } else if (!exiting) fputs("------\n", stderr); - fflush(stderr); - setvbuf(stderr, NULL, _IONBF, 0); /* Disable buffering again */ return 0; } |