chiark / gitweb /
util: port last code over to new namespace utility calls
[elogind.git] / src / shared / logs-show.c
index 7002675301311120b694b7c362c76b505fab6dad..b24bce50c06710fc018816cd2eed722c9bfb45b8 100644 (file)
 #include <assert.h>
 #include <errno.h>
 #include <sys/poll.h>
+#include <sys/socket.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include "logs-show.h"
 #include "log.h"
 #include "util.h"
 #include "utf8.h"
 #include "hashmap.h"
+#include "fileio.h"
 #include "journal-internal.h"
 
 /* up to three lines (each up to 100 characters),
@@ -105,7 +108,7 @@ static bool shall_print(const char *p, size_t l, OutputFlags flags) {
         return true;
 }
 
-static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputMode flags, int priority, const char* message, size_t message_len) {
+static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
         const char *color_on = "", *color_off = "";
         const char *pos, *end;
         bool ellipsized = false;
@@ -132,14 +135,14 @@ static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, Output
                 len = end - pos;
                 assert(len >= 0);
 
-                /* We need to figure out when we are showing the last line, and
+                /* We need to figure out when we are showing not-last line, *and*
                  * will skip subsequent lines. In that case, we will put the dots
                  * at the end of the line, instead of putting dots in the middle
                  * or not at all.
                  */
                 tail_line =
                         line + 1 == PRINT_LINE_THRESHOLD ||
-                        end + 1 >= message + message_len;
+                        end + 1 >= message + PRINT_CHAR_THRESHOLD;
 
                 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
                     (prefix + len + 1 < n_columns && !tail_line)) {
@@ -201,7 +204,7 @@ static int output_short(
         assert(j);
 
         /* Set the threshold to one bigger than the actual print
-         * treshold, so that if the line is actually longer than what
+         * threshold, so that if the line is actually longer than what
          * we're willing to print, ellipsization will occur. This way
          * we won't output a misleading line without any indication of
          * truncation.
@@ -399,11 +402,35 @@ static int output_verbose(
 
         sd_journal_set_data_threshold(j, 0);
 
-        r = sd_journal_get_realtime_usec(j, &realtime);
-        if (r < 0) {
+        r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
+        if (r == -ENOENT)
+                log_debug("Source realtime timestamp not found");
+        else if (r < 0) {
                 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
-                         "Failed to get realtime timestamp: %s", strerror(-r));
+                         "Failed to get source realtime timestamp: %s", strerror(-r));
                 return r;
+        } else {
+                _cleanup_free_ char *value = NULL;
+                size_t size;
+
+                r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
+                if (r < 0)
+                        log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
+                else {
+                        r = safe_atou64(value, &realtime);
+                        if (r < 0)
+                                log_debug("Failed to parse realtime timestamp: %s",
+                                          strerror(-r));
+                }
+        }
+
+        if (r < 0) {
+                r = sd_journal_get_realtime_usec(j, &realtime);
+                if (r < 0) {
+                        log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
+                                 "Failed to get realtime timestamp: %s", strerror(-r));
+                        return r;
+                }
         }
 
         r = sd_journal_get_cursor(j, &cursor);
@@ -512,7 +539,7 @@ static int output_export(
                 /* We already printed the boot id, from the data in
                  * the header, hence let's suppress it here */
                 if (length >= 9 &&
-                    hasprefix(data, "_BOOT_ID="))
+                    startswith(data, "_BOOT_ID="))
                         continue;
 
                 if (!utf8_is_printable(data, length)) {
@@ -1024,6 +1051,16 @@ int add_matches_for_unit(sd_journal *j, const char *unit) {
             (r = sd_journal_add_match(j, m4, 0))
         );
 
+        if (r == 0 && endswith(unit, ".slice")) {
+                char *m5 = strappend("_SYSTEMD_SLICE=", unit);
+
+                /* Show all messages belonging to a slice */
+                (void)(
+                        (r = sd_journal_add_disjunction(j)) ||
+                        (r = sd_journal_add_match(j, m5, 0))
+                        );
+        }
+
         return r;
 }
 
@@ -1063,20 +1100,115 @@ int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
                 (r = sd_journal_add_match(j, muid, 0)) ||
                 (r = sd_journal_add_match(j, "_UID=0", 0))
         );
+
+        if (r == 0 && endswith(unit, ".slice")) {
+                char *m5 = strappend("_SYSTEMD_SLICE=", unit);
+
+                /* Show all messages belonging to a slice */
+                (void)(
+                        (r = sd_journal_add_disjunction(j)) ||
+                        (r = sd_journal_add_match(j, m5, 0)) ||
+                        (r = sd_journal_add_match(j, muid, 0))
+                        );
+        }
+
         return r;
 }
 
-int add_match_this_boot(sd_journal *j) {
+static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
+        _cleanup_close_pipe_ int pair[2] = { -1, -1 };
+        _cleanup_close_ int nsfd = -1, rootfd = -1;
+        pid_t pid, child;
+        siginfo_t si;
+        char buf[37];
+        ssize_t k;
+        int r;
+
+        assert(machine);
+        assert(boot_id);
+
+        if (!filename_is_safe(machine))
+                return -EINVAL;
+
+        r = container_get_leader(machine, &pid);
+        if (r < 0)
+                return r;
+
+        r = namespace_open(pid, &nsfd, &rootfd);
+        if (r < 0)
+                return r;
+
+        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
+                return -errno;
+
+        child = fork();
+        if (child < 0)
+                return -errno;
+
+        if (child == 0) {
+                int fd;
+
+                close_nointr_nofail(pair[0]);
+                pair[0] = -1;
+
+                r = namespace_enter(nsfd, rootfd);
+                if (r < 0)
+                        _exit(EXIT_FAILURE);
+
+                fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+                if (fd < 0)
+                        _exit(EXIT_FAILURE);
+
+                k = loop_read(fd, buf, 36, false);
+                close_nointr_nofail(fd);
+                if (k != 36)
+                        _exit(EXIT_FAILURE);
+
+                k = send(pair[1], buf, 36, MSG_NOSIGNAL);
+                if (k != 36)
+                        _exit(EXIT_FAILURE);
+
+                _exit(EXIT_SUCCESS);
+        }
+
+        close_nointr_nofail(pair[1]);
+        pair[1] = -1;
+
+        k = recv(pair[0], buf, 36, 0);
+        if (k != 36)
+                return -EIO;
+
+        r = wait_for_terminate(child, &si);
+        if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
+                return r < 0 ? r : -EIO;
+
+        buf[36] = 0;
+        r = sd_id128_from_string(buf, boot_id);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int add_match_this_boot(sd_journal *j, const char *machine) {
         char match[9+32+1] = "_BOOT_ID=";
         sd_id128_t boot_id;
         int r;
 
         assert(j);
 
-        r = sd_id128_get_boot(&boot_id);
-        if (r < 0) {
-                log_error("Failed to get boot id: %s", strerror(-r));
-                return r;
+        if (machine) {
+                r = get_boot_id_for_machine(machine, &boot_id);
+                if (r < 0) {
+                        log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
+                        return r;
+                }
+        } else {
+                r = sd_id128_get_boot(&boot_id);
+                if (r < 0) {
+                        log_error("Failed to get boot id: %s", strerror(-r));
+                        return r;
+                }
         }
 
         sd_id128_to_string(boot_id, match + 9);
@@ -1120,7 +1252,7 @@ int show_journal_by_unit(
         if (r < 0)
                 return r;
 
-        r = add_match_this_boot(j);
+        r = add_match_this_boot(j, NULL);
         if (r < 0)
                 return r;