diff --git a/src/basic/log.c b/src/basic/log.c index f24431eef2..71e7031bc4 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -484,6 +484,8 @@ static int log_do_header( const char *extra_field, const char *extra) { int r; + error = IS_SYNTHETIC_ERRNO(error) ? 0 : ERRNO_VALUE(error); + r = snprintf(header, size, "PRIORITY=%i\n" "SYSLOG_FACILITY=%i\n" @@ -569,15 +571,12 @@ int log_dispatch_internal( assert_raw(buffer); - if (error < 0) - error = -error; - if (log_target == LOG_TARGET_NULL) - return -error; + return -ERRNO_VALUE(error); /* Patch in LOG_DAEMON facility if necessary */ if ((level & LOG_FACMASK) == 0) - level = log_facility | LOG_PRI(level); + level |= log_facility; if (open_when_needed) log_open(); @@ -636,7 +635,7 @@ int log_dispatch_internal( if (open_when_needed) log_close(); - return -error; + return -ERRNO_VALUE(error); } int log_dump_internal( @@ -652,11 +651,8 @@ int log_dump_internal( /* This modifies the buffer... */ - if (error < 0) - error = -error; - if (_likely_(LOG_PRI(level) > log_max_level[realm])) - return -error; + return -ERRNO_VALUE(error); return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); } @@ -674,14 +670,11 @@ int log_internalv_realm( char buffer[LINE_MAX]; PROTECT_ERRNO; - if (error < 0) - error = -error; - if (_likely_(LOG_PRI(level) > log_max_level[realm])) - return -error; + return -ERRNO_VALUE(error); /* Make sure that %m maps to the specified error (or "Success"). */ - errno = error; + errno = ERRNO_VALUE(error); (void) vsnprintf(buffer, sizeof buffer, format, ap); @@ -723,14 +716,11 @@ static int log_object_internalv( PROTECT_ERRNO; char *buffer, *b; - if (error < 0) - error = -error; - if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD])) - return -error; + return -ERRNO_VALUE(error); /* Make sure that %m maps to the specified error (or "Success"). */ - errno = error; + errno = ERRNO_VALUE(error); /* Prepend the object name before the message */ if (object) { @@ -853,7 +843,7 @@ int log_format_iovec( * since vasprintf() leaves it afterwards at * an undefined location */ - errno = error; + errno = ERRNO_VALUE(error); va_copy(aq, ap); r = vasprintf(&m, format, aq); @@ -892,17 +882,12 @@ int log_struct_internal( PROTECT_ERRNO; va_list ap; - if (error < 0) - error = -error; - - if (_likely_(LOG_PRI(level) > log_max_level[realm])) - return -error; - - if (log_target == LOG_TARGET_NULL) - return -error; + if (_likely_(LOG_PRI(level) > log_max_level[realm]) || + log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); if ((level & LOG_FACMASK) == 0) - level = log_facility | LOG_PRI(level); + level |= log_facility; if (IN_SET(log_target, LOG_TARGET_AUTO, @@ -922,7 +907,8 @@ int log_struct_internal( }; bool fallback = false; - /* If the journal is available do structured logging */ + /* If the journal is available do structured logging. + * Do not report the errno if it is synthetic. */ log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL); iovec[n++] = IOVEC_MAKE_STRING(header); @@ -943,7 +929,7 @@ int log_struct_internal( if (open_when_needed) log_close(); - return -error; + return -ERRNO_VALUE(error); } } } @@ -954,7 +940,7 @@ int log_struct_internal( while (format) { va_list aq; - errno = error; + errno = ERRNO_VALUE(error); va_copy(aq, ap); (void) vsnprintf(buf, sizeof buf, format, aq); @@ -975,7 +961,7 @@ int log_struct_internal( if (open_when_needed) log_close(); - return -error; + return -ERRNO_VALUE(error); } return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8); @@ -995,17 +981,12 @@ int log_struct_iovec_internal( size_t i; char *m; - if (error < 0) - error = -error; - - if (_likely_(LOG_PRI(level) > log_max_level[realm])) - return -error; - - if (log_target == LOG_TARGET_NULL) - return -error; + if (_likely_(LOG_PRI(level) > log_max_level[realm]) || + log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); if ((level & LOG_FACMASK) == 0) - level = log_facility | LOG_PRI(level); + level |= log_facility; if (IN_SET(log_target, LOG_TARGET_AUTO, LOG_TARGET_JOURNAL_OR_KMSG, @@ -1028,7 +1009,7 @@ int log_struct_iovec_internal( } if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0) - return -error; + return -ERRNO_VALUE(error); } for (i = 0; i < n_input_iovec; i++) @@ -1036,7 +1017,7 @@ int log_struct_iovec_internal( break; if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */ - return -error; + return -ERRNO_VALUE(error); m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="), input_iovec[i].iov_len - STRLEN("MESSAGE=")); @@ -1239,14 +1220,9 @@ int log_syntax_internal( va_list ap; const char *unit_fmt = NULL; - if (error < 0) - error = -error; - - if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD])) - return -error; - - if (log_target == LOG_TARGET_NULL) - return -error; + if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]) || + log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); errno = error; diff --git a/src/basic/log.h b/src/basic/log.h index 683f97b942..ddec8116ff 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -36,10 +36,11 @@ typedef enum LogTarget{ _LOG_TARGET_INVALID = -1 } LogTarget; -#define LOG_REALM_PLUS_LEVEL(realm, level) \ - ((realm) << 10 | (level)) -#define LOG_REALM_REMOVE_LEVEL(realm_level) \ - ((realm_level >> 10)) +#define LOG_REALM_PLUS_LEVEL(realm, level) ((realm) << 10 | (level)) +#define LOG_REALM_REMOVE_LEVEL(realm_level) ((realm_level) >> 10) +#define SYNTHETIC_ERRNO(num) (1 << 30 | (num)) +#define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1) +#define ERRNO_VALUE(val) (abs(val) & 255) void log_set_target(LogTarget target); void log_set_max_level_realm(LogRealm realm, int level); diff --git a/src/test/test-log.c b/src/test/test-log.c index c09f40c356..1e010c08fb 100644 --- a/src/test/test-log.c +++ b/src/test/test-log.c @@ -17,20 +17,27 @@ assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_LOCAL3 | LOG_DEBUG) & LOG assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMASK) == LOG_INFO); +assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(EINVAL))); +assert_cc(!IS_SYNTHETIC_ERRNO(EINVAL)); +assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(0))); +assert_cc(!IS_SYNTHETIC_ERRNO(0)); + #define X10(x) x x x x x x x x x x #define X100(x) X10(X10(x)) #define X1000(x) X100(X10(x)) -static void test_log_console(void) { +static void test_log_struct(void) { log_struct(LOG_INFO, - "MESSAGE=Waldo PID="PID_FMT, getpid_cached(), + "MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(), "SERVICE=piepapo"); -} -static void test_log_journal(void) { - log_struct(LOG_INFO, - "MESSAGE=Foobar PID="PID_FMT, getpid_cached(), - "SERVICE=foobar"); + log_struct_errno(LOG_INFO, EILSEQ, + "MESSAGE=Waldo PID="PID_FMT": %m (normal)", getpid_cached(), + "SERVICE=piepapo"); + + log_struct_errno(LOG_INFO, SYNTHETIC_ERRNO(EILSEQ), + "MESSAGE=Waldo PID="PID_FMT": %m (synthetic)", getpid_cached(), + "SERVICE=piepapo"); log_struct(LOG_INFO, "MESSAGE=Foobar PID="PID_FMT, getpid_cached(), @@ -59,10 +66,11 @@ int main(int argc, char* argv[]) { log_set_target(target); log_open(); - test_log_console(); - test_log_journal(); + test_log_struct(); test_long_lines(); } + assert_se(log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "foo") == -EUCLEAN); + return 0; }