summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shared/pretty-print.c18
-rw-r--r--src/shared/pretty-print.h29
-rw-r--r--src/sysupdate/updatectl.c5
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;
}