From 4e0771b2da184592e35952c8d4fdf8a9a8858ced Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 23 Oct 2020 23:56:00 +0000 Subject: [PATCH] warnx: Save errno across calls that might change it. When warn() family of functions is being used after err_set_file() has been set to, for example, /dev/null, errno is being clobbered, rendering it unreliable after, for example, procstat_getpathname() when it is supposed to emit a warning. Then the errno is changed to Inappropriate ioctl for device, destroying the original value (via calls to fprintf()functions). Submitted by: Juraj Lutter Differential Revision: https://reviews.freebsd.org/D26871 --- lib/libc/gen/err.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/libc/gen/err.c b/lib/libc/gen/err.c index 4193eca77f60..c536767f1a6b 100644 --- a/lib/libc/gen/err.c +++ b/lib/libc/gen/err.c @@ -161,6 +161,9 @@ warnc(int code, const char *fmt, ...) void vwarnc(int code, const char *fmt, va_list ap) { + static int saved_errno; + + saved_errno = errno; if (err_file == NULL) err_set_file(NULL); fprintf(err_file, "%s: ", _getprogname()); @@ -169,6 +172,7 @@ vwarnc(int code, const char *fmt, va_list ap) fprintf(err_file, ": "); } fprintf(err_file, "%s\n", strerror(code)); + errno = saved_errno; } void @@ -183,10 +187,14 @@ warnx(const char *fmt, ...) void vwarnx(const char *fmt, va_list ap) { + static int saved_errno; + + saved_errno = errno; if (err_file == NULL) err_set_file(NULL); fprintf(err_file, "%s: ", _getprogname()); if (fmt != NULL) vfprintf(err_file, fmt, ap); fprintf(err_file, "\n"); + errno = saved_errno; }