/* 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;
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;
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(
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);
}
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;
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);
}
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;
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);
#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) \
#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))
#include <unistd.h>
#include "format-util.h"
+#include "io-util.h"
#include "log.h"
#include "process-util.h"
#include "string-util.h"
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);
}