]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/log: add concept of "synthethic errnos"
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 20 Nov 2018 22:03:40 +0000 (23:03 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 22 Nov 2018 09:45:08 +0000 (10:45 +0100)
Synthetic errnos are processed like normal, and may be used in %m and become
the return value from log_*(), but they are not logged in the journal.

src/basic/log.c
src/basic/log.h
src/test/test-log.c

index f24431eef2c8be577289802d913f9bdc96f18c2c..71e7031bc40b6552a8781f984715096e06e55fab 100644 (file)
@@ -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;
 
index 683f97b942bbf4f6fcc4258bbe8e9e29af437eaf..ddec8116ff60733223273aa76fd72f1b960b5908 100644 (file)
@@ -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);
index c09f40c356977e58c18178c5af28d5f2506f37e2..1e010c08fb8c7c7e15c9508307659050c8895fbf 100644 (file)
@@ -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;
 }