]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
log: add iov helpers for log_context
authorLuca Boccassi <bluca@debian.org>
Mon, 13 Mar 2023 21:33:58 +0000 (21:33 +0000)
committerLuca Boccassi <bluca@debian.org>
Tue, 14 Mar 2023 16:37:03 +0000 (16:37 +0000)
src/basic/log.c
src/basic/log.h
src/test/test-log.c

index 40602d5ddae2301469b00a954e30fb9c62a9848c..8b973f9e0a905502529aa63c01c7f249f1f89196 100644 (file)
@@ -76,6 +76,8 @@ typedef struct LogContext {
         /* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory
          * referenced by this is freed or not */
         char **fields;
+        struct iovec *input_iovec;
+        size_t n_input_iovec;
         bool owned;
         LIST_FIELDS(struct LogContext, ll);
 } LogContext;
@@ -613,7 +615,7 @@ static void log_do_context(struct iovec *iovec, size_t iovec_len, size_t *n) {
         assert(iovec);
         assert(n);
 
-        LIST_FOREACH(ll, c, _log_context)
+        LIST_FOREACH(ll, c, _log_context) {
                 STRV_FOREACH(s, c->fields) {
                         if (*n + 2 >= iovec_len)
                                 return;
@@ -621,6 +623,15 @@ static void log_do_context(struct iovec *iovec, size_t iovec_len, size_t *n) {
                         iovec[(*n)++] = IOVEC_MAKE_STRING(*s);
                         iovec[(*n)++] = IOVEC_MAKE_STRING("\n");
                 }
+
+                for (size_t i = 0; i < c->n_input_iovec; i++) {
+                        if (*n + 2 >= iovec_len)
+                                return;
+
+                        iovec[(*n)++] = c->input_iovec[i];
+                        iovec[(*n)++] = IOVEC_MAKE_STRING("\n");
+                }
+        }
 }
 
 static int write_to_journal(
@@ -1555,6 +1566,7 @@ LogContext* log_context_attach(LogContext *c) {
         assert(c);
 
         _log_context_num_fields += strv_length(c->fields);
+        _log_context_num_fields += c->n_input_iovec;
 
         return LIST_PREPEND(ll, _log_context, c);
 }
@@ -1563,8 +1575,9 @@ LogContext* log_context_detach(LogContext *c) {
         if (!c)
                 return NULL;
 
-        assert(_log_context_num_fields >= strv_length(c->fields));
+        assert(_log_context_num_fields >= strv_length(c->fields) + c->n_input_iovec);
         _log_context_num_fields -= strv_length(c->fields);
+        _log_context_num_fields -= c->n_input_iovec;
 
         LIST_REMOVE(ll, _log_context, c);
         return NULL;
@@ -1583,14 +1596,33 @@ LogContext* log_context_new(char **fields, bool owned) {
         return log_context_attach(c);
 }
 
+LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned) {
+        if (!input_iovec || n_input_iovec == 0)
+                return NULL; /* Nothing to do */
+
+        LogContext *c = new(LogContext, 1);
+        if (!c)
+                return NULL;
+
+        *c = (LogContext) {
+                .input_iovec = input_iovec,
+                .n_input_iovec = n_input_iovec,
+                .owned = owned,
+        };
+
+        return log_context_attach(c);
+}
+
 LogContext* log_context_free(LogContext *c) {
         if (!c)
                 return NULL;
 
         log_context_detach(c);
 
-        if (c->owned)
+        if (c->owned) {
                 strv_free(c->fields);
+                iovec_array_free(c->input_iovec, c->n_input_iovec);
+        }
 
         return mfree(c);
 }
@@ -1603,6 +1635,14 @@ LogContext* log_context_new_consume(char **fields) {
         return c;
 }
 
+LogContext* log_context_new_consumev(struct iovec *input_iovec, size_t n_input_iovec) {
+        LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ true);
+        if (!c)
+                iovec_array_free(input_iovec, n_input_iovec);
+
+        return c;
+}
+
 size_t log_context_num_contexts(void) {
         size_t n = 0;
 
index 0d4956e6b5782d65a8b52f49d94b44f4a4f713ef..c4ac73e27bcd5e2d2a2609cce5e132809d48e13f 100644 (file)
@@ -461,10 +461,12 @@ LogContext* log_context_attach(LogContext *c);
 LogContext* log_context_detach(LogContext *c);
 
 LogContext* log_context_new(char **fields, bool owned);
+LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned);
 LogContext* log_context_free(LogContext *c);
 
-/* Same as log_context_new(), but frees the given fields strv on failure. */
+/* Same as log_context_new(), but frees the given fields strv/iovec on failure. */
 LogContext* log_context_new_consume(char **fields);
+LogContext* log_context_new_consumev(struct iovec *input_iovec, size_t n_input_iovec);
 
 /* Returns the number of attached log context objects. */
 size_t log_context_num_contexts(void);
@@ -486,8 +488,15 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_free);
 #define LOG_CONTEXT_PUSH_STRV(strv) \
         _LOG_CONTEXT_PUSH_STRV(strv, UNIQ_T(c, UNIQ))
 
-/* LOG_CONTEXT_CONSUME_STR()/LOG_CONTEXT_CONSUME_STRV() are identical to
- * LOG_CONTEXT_PUSH_STR()/LOG_CONTEXT_PUSH_STRV() except they take ownership of the given str/strv argument.
+#define _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, c) \
+        _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ false);
+
+#define LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec) \
+        _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ))
+
+/* LOG_CONTEXT_CONSUME_STR()/LOG_CONTEXT_CONSUME_STRV()/LOG_CONTEXT_CONSUME_IOV() are identical to
+ * LOG_CONTEXT_PUSH_STR()/LOG_CONTEXT_PUSH_STRV()/LOG_CONTEXT_PUSH_IOV() except they take ownership of the
+ * given str/strv argument.
  */
 
 #define _LOG_CONTEXT_CONSUME_STR(s, c, strv) \
@@ -504,3 +513,9 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_free);
 
 #define LOG_CONTEXT_CONSUME_STRV(strv) \
         _LOG_CONTEXT_CONSUME_STRV(strv, UNIQ_T(c, UNIQ))
+
+#define _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, c) \
+        _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_new_consumev(input_iovec, n_input_iovec);
+
+#define LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec) \
+        _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ))
index 30c536d5c7c9dcd220265027e1ca7d4ad83b3984..68b5cb5092c1fc74a0d309bd2d38ec0a2104f02f 100644 (file)
@@ -4,6 +4,7 @@
 #include <unistd.h>
 
 #include "format-util.h"
+#include "io-util.h"
 #include "log.h"
 #include "process-util.h"
 #include "string-util.h"
@@ -135,6 +136,28 @@ static void test_log_context(void) {
                 assert_se(log_context_num_fields() == 2);
         }
 
+        {
+                /* Test that everything still works with a mixed strv and iov. */
+                struct iovec iov[] = {
+                        IOVEC_MAKE_STRING("ABC=def"),
+                        IOVEC_MAKE_STRING("GHI=jkl"),
+                };
+                _cleanup_free_ struct iovec_wrapper *iovw = iovw_new();
+                assert_se(iovw);
+                assert_se(iovw_consume(iovw, strdup("MNO=pqr"), STRLEN("MNO=pqr") + 1) == 0);
+
+                LOG_CONTEXT_PUSH_IOV(iov, ELEMENTSOF(iov));
+                LOG_CONTEXT_CONSUME_IOV(iovw->iovec, iovw->count);
+                LOG_CONTEXT_PUSH("STU=vwx");
+
+                assert_se(log_context_num_contexts() == 3);
+                assert_se(log_context_num_fields() == 4);
+
+                test_log_struct();
+                test_long_lines();
+                test_log_syntax();
+        }
+
         assert_se(log_context_num_contexts() == 0);
         assert_se(log_context_num_fields() == 0);
 }