diff --git a/Makefile-otutil.am b/Makefile-otutil.am index db632705..ff7533e9 100644 --- a/Makefile-otutil.am +++ b/Makefile-otutil.am @@ -36,8 +36,6 @@ libotutil_la_SOURCES = \ src/libotutil/ot-variant-utils.h \ src/libotutil/ot-gio-utils.c \ src/libotutil/ot-gio-utils.h \ - src/libotutil/ot-log-utils.c \ - src/libotutil/ot-log-utils.h \ src/libotutil/ot-gpg-utils.c \ src/libotutil/ot-gpg-utils.h \ src/libotutil/otutil.c \ diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 7e72a3ef..622f9975 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -47,9 +47,9 @@ #include "ostree-linuxfsutil.h" #include "libglnx.h" -#define OSTREE_VARRELABEL_ID "da679b08acd34504b789d96f818ea781" -#define OSTREE_CONFIGMERGE_ID "d3863baec13e4449ab0384684a8af3a7" #ifdef HAVE_LIBSYSTEMD +#define OSTREE_VARRELABEL_ID SD_ID128_MAKE(da,67,9b,08,ac,d3,45,04,b7,89,d9,6f,81,8e,a7,81) +#define OSTREE_CONFIGMERGE_ID SD_ID128_MAKE(d3,86,3b,ae,c1,3e,44,49,ab,03,84,68,4a,8a,f3,a7) #define OSTREE_DEPLOYMENT_COMPLETE_ID SD_ID128_MAKE(dd,44,0e,3e,54,90,83,b6,3d,0e,fc,7d,c1,52,55,f1) #endif @@ -429,11 +429,19 @@ merge_configuration_from (OstreeSysroot *sysroot, cancellable, error)) return glnx_prefix_error (error, "While computing configuration diff"); - ot_log_structured_print_id_v (OSTREE_CONFIGMERGE_ID, - "Copying /etc changes: %u modified, %u removed, %u added", - modified->len, - removed->len, - added->len); + { g_autofree char *msg = + g_strdup_printf ("Copying /etc changes: %u modified, %u removed, %u added", + modified->len, removed->len, added->len); +#ifdef HAVE_LIBSYSTEMD + sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_CONFIGMERGE_ID), + "MESSAGE=%s", msg, + "ETC_N_MODIFIED=%u", modified->len, + "ETC_N_REMOVED=%u", removed->len, + "ETC_N_ADDED=%u", added->len, + NULL); +#endif + _ostree_sysroot_emit_journal_msg (sysroot, msg); + } glnx_fd_close int orig_etc_fd = -1; if (!glnx_opendirat (merge_deployment_dfd, "usr/etc", TRUE, &orig_etc_fd, error)) @@ -688,9 +696,15 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot, if (!deployment_var_labeled) { - ot_log_structured_print_id_v (OSTREE_VARRELABEL_ID, - "Relabeling /var (no stamp file '%s' found)", - selabeled); + { g_autofree char *msg = + g_strdup_printf ("Relabeling /var (no stamp file '%s' found)", selabeled); +#ifdef HAVE_LIBSYSTEMD + sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_VARRELABEL_ID), + "MESSAGE=%s", msg, + NULL); +#endif + _ostree_sysroot_emit_journal_msg (sysroot, msg); + } g_autoptr(GFile) deployment_var_path = ot_fdrel_to_gfile (os_deploy_dfd, "var"); if (!selinux_relabel_dir (sysroot, sepolicy, @@ -1917,8 +1931,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, "OSTREE_SYNCFS_EXTRA_MSEC=%" G_GUINT64_FORMAT, syncstats.extra_syncfs_msec, NULL); #endif - if (!ot_stdout_is_journal ()) - g_print ("%s\n", msg); + _ostree_sysroot_emit_journal_msg (self, msg); } if (!_ostree_sysroot_bump_mtime (self, error)) diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 07c4bf6e..4c6cb328 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -69,6 +69,10 @@ struct OstreeSysroot { #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_DIR "/run/ostree/deployment-state/" #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_DEVELOPMENT "unlocked-development" +void +_ostree_sysroot_emit_journal_msg (OstreeSysroot *self, + const char *msg); + gboolean _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, int bootversion, diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 20539e4d..5bdfe116 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -58,8 +58,18 @@ find_booted_deployment (OstreeSysroot *self, */ typedef struct { GObjectClass parent_class; + + /* Signals */ + void (*journal_msg) (OstreeSysroot *sysroot, + const char *msg); } OstreeSysrootClass; +enum { + JOURNAL_MSG_SIGNAL, + LAST_SIGNAL, +}; +static guint signals[LAST_SIGNAL] = { 0 }; + enum { PROP_0, @@ -159,6 +169,27 @@ ostree_sysroot_class_init (OstreeSysrootClass *klass) "", G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * OstreeSysroot::journal-msg: + * @self: Self + * @msg: Human-readable string (should not contain newlines) + * + * libostree will log to the journal various events, such as the /etc merge + * status, and transaction completion. Connect to this signal to also + * synchronously receive the text for those messages. This is intended to be + * used by command line tools which link to libostree as a library. + * + * Currently, the structured data is only available via the systemd journal. + * + * Since: 2017.10 + */ + signals[JOURNAL_MSG_SIGNAL] = + g_signal_new ("journal-msg", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (OstreeSysrootClass, journal_msg), + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); } static void @@ -319,6 +350,13 @@ ostree_sysroot_ensure_initialized (OstreeSysroot *self, return TRUE; } +void +_ostree_sysroot_emit_journal_msg (OstreeSysroot *self, + const char *msg) +{ + g_signal_emit (self, signals[JOURNAL_MSG_SIGNAL], 0, msg); +} + gboolean _ostree_sysroot_parse_deploy_path_name (const char *name, char **out_csum, diff --git a/src/libotutil/ot-log-utils.c b/src/libotutil/ot-log-utils.c deleted file mode 100644 index c8a3bda7..00000000 --- a/src/libotutil/ot-log-utils.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2016 Colin Walters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include - -#include - -#include "otutil.h" -#include "libglnx.h" - -#ifdef HAVE_LIBSYSTEMD -#define SD_JOURNAL_SUPPRESS_LOCATION -#include -#endif -#include - -/** - * ot_log_structured: - * @message: Text message to send - * @keys: (allow-none) (array zero-terminated=1) (element-type utf8): Optional structured data - * - * Log structured data in an operating-system specific fashion. The - * parameter @opts should be an array of UTF-8 KEY=VALUE strings. - * This function does not support binary data. See - * http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html - * for more information about fields that can be used on a systemd - * system. - */ -static void -ot_log_structured (const char *message, - const char *const *keys) -{ -#ifdef HAVE_LIBSYSTEMD - const char *const*iter; - g_autofree char *msgkey = NULL; - guint i, n_opts; - struct iovec *iovs; - - for (n_opts = 0, iter = keys; *iter; iter++, n_opts++) - ; - - n_opts++; /* Add one for MESSAGE= */ - iovs = g_alloca (sizeof (struct iovec) * n_opts); - - for (i = 0, iter = keys; *iter; iter++, i++) { - iovs[i].iov_base = (char*)keys[i]; - iovs[i].iov_len = strlen (keys[i]); - } - g_assert(i == n_opts-1); - msgkey = g_strconcat ("MESSAGE=", message, NULL); - iovs[i].iov_base = msgkey; - iovs[i].iov_len = strlen (msgkey); - - // The code location isn't useful since we're wrapping - sd_journal_sendv (iovs, n_opts); -#else - g_print ("%s\n", message); -#endif -} - -/** - * ot_stdout_is_journal: - * - * Use this function when you want your code to behave differently - * depeneding on whether your program was started as a systemd unit, - * or e.g. interactively at a terminal. - * - * Returns: %TRUE if stdout is (probably) connnected to the systemd journal - */ -gboolean -ot_stdout_is_journal (void) -{ - static gsize initialized; - static gboolean stdout_is_socket; - - if (g_once_init_enter (&initialized)) - { - guint64 pid = (guint64) getpid (); - g_autofree char *fdpath = g_strdup_printf ("/proc/%" G_GUINT64_FORMAT "/fd/1", pid); - char buf[1024]; - ssize_t bytes_read; - - if ((bytes_read = readlink (fdpath, buf, sizeof(buf) - 1)) != -1) - { - buf[bytes_read] = '\0'; - stdout_is_socket = g_str_has_prefix (buf, "socket:"); - } - else - stdout_is_socket = FALSE; - - g_once_init_leave (&initialized, TRUE); - } - - return stdout_is_socket; -} - -/** - * gs_log_structured_print: - * @message: A message to log - * @keys: (allow-none) (array zero-terminated=1) (element-type utf8): Optional structured data - * - * Like gs_log_structured(), but also print to standard output (if it - * is not already connected to the system log). - */ -static void -ot_log_structured_print (const char *message, - const char *const *keys) -{ - ot_log_structured (message, keys); - -#ifdef HAVE_LIBSYSTEMD - if (!ot_stdout_is_journal ()) - g_print ("%s\n", message); -#endif -} - -/** - * ot_log_structured_print_id_v: - * @message_id: A unique MESSAGE_ID - * @format: A format string - * - * The provided @message_id is a unique MESSAGE_ID (see for more information). - * - * This function otherwise acts as ot_log_structured_print(), taking - * @format as a format string. - */ -void -ot_log_structured_print_id_v (const char *message_id, - const char *format, - ...) -{ - const char *key0 = glnx_strjoina ("MESSAGE_ID=", message_id); - const char *keys[] = { key0, NULL }; - g_autofree char *msg = NULL; - va_list args; - - va_start (args, format); - msg = g_strdup_vprintf (format, args); - va_end (args); - - ot_log_structured_print (msg, (const char *const *)keys); -} diff --git a/src/libotutil/ot-log-utils.h b/src/libotutil/ot-log-utils.h deleted file mode 100644 index 4433ee16..00000000 --- a/src/libotutil/ot-log-utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2016 Colin Walters . - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#pragma once - -#include "ot-unix-utils.h" - -G_BEGIN_DECLS - -gboolean ot_stdout_is_journal (void); - -void ot_log_structured_print_id_v (const char *message_id, - const char *format, - ...) G_GNUC_PRINTF(2, 3); - -G_END_DECLS diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index dfe951d0..0647515c 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -51,7 +51,6 @@ #include #include #include -#include #include void ot_ptrarray_add_many (GPtrArray *a, ...) G_GNUC_NULL_TERMINATED; diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c index 5b6e301d..81d10b98 100644 --- a/src/ostree/ot-main.c +++ b/src/ostree/ot-main.c @@ -358,6 +358,13 @@ ostree_option_context_parse (GOptionContext *context, return TRUE; } +static void +on_sysroot_journal_msg (OstreeSysroot *sysroot, + const char *msg) +{ + g_print ("%s\n", msg); +} + gboolean ostree_admin_option_context_parse (GOptionContext *context, const GOptionEntry *main_entries, @@ -381,6 +388,7 @@ ostree_admin_option_context_parse (GOptionContext *context, sysroot_path = g_file_new_for_path (opt_sysroot); g_autoptr(OstreeSysroot) sysroot = ostree_sysroot_new (sysroot_path); + g_signal_connect (sysroot, "journal-msg", G_CALLBACK (on_sysroot_journal_msg), NULL); if (flags & OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER) {