LCOV - code coverage report
Current view: top level - shared - logs-show.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 762 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 24 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 880 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <fcntl.h>
       5                 :            : #include <signal.h>
       6                 :            : #include <stdint.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <string.h>
       9                 :            : #include <sys/socket.h>
      10                 :            : #include <syslog.h>
      11                 :            : #include <time.h>
      12                 :            : #include <unistd.h>
      13                 :            : 
      14                 :            : #include "sd-id128.h"
      15                 :            : #include "sd-journal.h"
      16                 :            : 
      17                 :            : #include "alloc-util.h"
      18                 :            : #include "fd-util.h"
      19                 :            : #include "format-util.h"
      20                 :            : #include "hashmap.h"
      21                 :            : #include "hostname-util.h"
      22                 :            : #include "io-util.h"
      23                 :            : #include "journal-internal.h"
      24                 :            : #include "json.h"
      25                 :            : #include "log.h"
      26                 :            : #include "logs-show.h"
      27                 :            : #include "macro.h"
      28                 :            : #include "namespace-util.h"
      29                 :            : #include "output-mode.h"
      30                 :            : #include "parse-util.h"
      31                 :            : #include "process-util.h"
      32                 :            : #include "pretty-print.h"
      33                 :            : #include "sparse-endian.h"
      34                 :            : #include "stdio-util.h"
      35                 :            : #include "string-table.h"
      36                 :            : #include "string-util.h"
      37                 :            : #include "strv.h"
      38                 :            : #include "terminal-util.h"
      39                 :            : #include "time-util.h"
      40                 :            : #include "utf8.h"
      41                 :            : #include "util.h"
      42                 :            : 
      43                 :            : /* up to three lines (each up to 100 characters) or 300 characters, whichever is less */
      44                 :            : #define PRINT_LINE_THRESHOLD 3
      45                 :            : #define PRINT_CHAR_THRESHOLD 300
      46                 :            : 
      47                 :            : #define JSON_THRESHOLD 4096U
      48                 :            : 
      49                 :          0 : static int print_catalog(FILE *f, sd_journal *j) {
      50                 :            :         int r;
      51                 :          0 :         _cleanup_free_ char *t = NULL, *z = NULL;
      52                 :            : 
      53                 :          0 :         r = sd_journal_get_catalog(j, &t);
      54         [ #  # ]:          0 :         if (r < 0)
      55                 :          0 :                 return r;
      56                 :            : 
      57                 :          0 :         z = strreplace(strstrip(t), "\n", "\n-- ");
      58         [ #  # ]:          0 :         if (!z)
      59                 :          0 :                 return log_oom();
      60                 :            : 
      61                 :          0 :         fputs("-- ", f);
      62                 :          0 :         fputs(z, f);
      63                 :          0 :         fputc('\n', f);
      64                 :            : 
      65                 :          0 :         return 0;
      66                 :            : }
      67                 :            : 
      68                 :          0 : static int parse_field(const void *data, size_t length, const char *field, size_t field_len, char **target, size_t *target_len) {
      69                 :            :         size_t nl;
      70                 :            :         char *buf;
      71                 :            : 
      72         [ #  # ]:          0 :         assert(data);
      73         [ #  # ]:          0 :         assert(field);
      74         [ #  # ]:          0 :         assert(target);
      75                 :            : 
      76         [ #  # ]:          0 :         if (length < field_len)
      77                 :          0 :                 return 0;
      78                 :            : 
      79         [ #  # ]:          0 :         if (memcmp(data, field, field_len))
      80                 :          0 :                 return 0;
      81                 :            : 
      82                 :          0 :         nl = length - field_len;
      83                 :            : 
      84                 :          0 :         buf = newdup_suffix0(char, (const char*) data + field_len, nl);
      85         [ #  # ]:          0 :         if (!buf)
      86                 :          0 :                 return log_oom();
      87                 :            : 
      88                 :          0 :         free(*target);
      89                 :          0 :         *target = buf;
      90                 :            : 
      91         [ #  # ]:          0 :         if (target_len)
      92                 :          0 :                 *target_len = nl;
      93                 :            : 
      94                 :          0 :         return 1;
      95                 :            : }
      96                 :            : 
      97                 :            : typedef struct ParseFieldVec {
      98                 :            :         const char *field;
      99                 :            :         size_t field_len;
     100                 :            :         char **target;
     101                 :            :         size_t *target_len;
     102                 :            : } ParseFieldVec;
     103                 :            : 
     104                 :            : #define PARSE_FIELD_VEC_ENTRY(_field, _target, _target_len) \
     105                 :            :         { .field = _field, .field_len = strlen(_field), .target = _target, .target_len = _target_len }
     106                 :            : 
     107                 :          0 : static int parse_fieldv(const void *data, size_t length, const ParseFieldVec *fields, unsigned n_fields) {
     108                 :            :         unsigned i;
     109                 :            : 
     110         [ #  # ]:          0 :         for (i = 0; i < n_fields; i++) {
     111                 :          0 :                 const ParseFieldVec *f = &fields[i];
     112                 :            :                 int r;
     113                 :            : 
     114                 :          0 :                 r = parse_field(data, length, f->field, f->field_len, f->target, f->target_len);
     115         [ #  # ]:          0 :                 if (r < 0)
     116                 :          0 :                         return r;
     117         [ #  # ]:          0 :                 else if (r > 0)
     118                 :          0 :                         break;
     119                 :            :         }
     120                 :            : 
     121                 :          0 :         return 0;
     122                 :            : }
     123                 :            : 
     124                 :          0 : static int field_set_test(Set *fields, const char *name, size_t n) {
     125                 :          0 :         char *s = NULL;
     126                 :            : 
     127         [ #  # ]:          0 :         if (!fields)
     128                 :          0 :                 return 1;
     129                 :            : 
     130                 :          0 :         s = strndupa(name, n);
     131         [ #  # ]:          0 :         if (!s)
     132                 :          0 :                 return log_oom();
     133                 :            : 
     134                 :          0 :         return set_get(fields, s) ? 1 : 0;
     135                 :            : }
     136                 :            : 
     137                 :          0 : static bool shall_print(const char *p, size_t l, OutputFlags flags) {
     138         [ #  # ]:          0 :         assert(p);
     139                 :            : 
     140         [ #  # ]:          0 :         if (flags & OUTPUT_SHOW_ALL)
     141                 :          0 :                 return true;
     142                 :            : 
     143         [ #  # ]:          0 :         if (l >= PRINT_CHAR_THRESHOLD)
     144                 :          0 :                 return false;
     145                 :            : 
     146         [ #  # ]:          0 :         if (!utf8_is_printable(p, l))
     147                 :          0 :                 return false;
     148                 :            : 
     149                 :          0 :         return true;
     150                 :            : }
     151                 :            : 
     152                 :          0 : static bool print_multiline(
     153                 :            :                 FILE *f,
     154                 :            :                 unsigned prefix,
     155                 :            :                 unsigned n_columns,
     156                 :            :                 OutputFlags flags,
     157                 :            :                 int priority,
     158                 :            :                 bool audit,
     159                 :            :                 const char* message,
     160                 :            :                 size_t message_len,
     161                 :            :                 size_t highlight[2]) {
     162                 :            : 
     163                 :          0 :         const char *color_on = "", *color_off = "", *highlight_on = "";
     164                 :            :         const char *pos, *end;
     165                 :          0 :         bool ellipsized = false;
     166                 :          0 :         int line = 0;
     167                 :            : 
     168         [ #  # ]:          0 :         if (flags & OUTPUT_COLOR) {
     169                 :          0 :                 get_log_colors(priority, &color_on, &color_off, &highlight_on);
     170                 :            : 
     171   [ #  #  #  # ]:          0 :                 if (audit && strempty(color_on)) {
     172                 :          0 :                         color_on = ANSI_BLUE;
     173                 :          0 :                         color_off = ANSI_NORMAL;
     174                 :            :                 }
     175                 :            :         }
     176                 :            : 
     177                 :            :         /* A special case: make sure that we print a newline when
     178                 :            :            the message is empty. */
     179         [ #  # ]:          0 :         if (message_len == 0)
     180                 :          0 :                 fputs("\n", f);
     181                 :            : 
     182                 :          0 :         for (pos = message;
     183         [ #  # ]:          0 :              pos < message + message_len;
     184                 :          0 :              pos = end + 1, line++) {
     185                 :          0 :                 bool continuation = line > 0;
     186                 :            :                 bool tail_line;
     187                 :            :                 int len;
     188   [ #  #  #  # ]:          0 :                 for (end = pos; end < message + message_len && *end != '\n'; end++)
     189                 :            :                         ;
     190                 :          0 :                 len = end - pos;
     191         [ #  # ]:          0 :                 assert(len >= 0);
     192                 :            : 
     193                 :            :                 /* We need to figure out when we are showing not-last line, *and*
     194                 :            :                  * will skip subsequent lines. In that case, we will put the dots
     195                 :            :                  * at the end of the line, instead of putting dots in the middle
     196                 :            :                  * or not at all.
     197                 :            :                  */
     198                 :          0 :                 tail_line =
     199         [ #  # ]:          0 :                         line + 1 == PRINT_LINE_THRESHOLD ||
     200         [ #  # ]:          0 :                         end + 1 >= message + PRINT_CHAR_THRESHOLD;
     201                 :            : 
     202         [ #  # ]:          0 :                 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
     203   [ #  #  #  # ]:          0 :                     (prefix + len + 1 < n_columns && !tail_line)) {
     204         [ #  # ]:          0 :                         if (highlight &&
     205         [ #  # ]:          0 :                             (size_t) (pos - message) <= highlight[0] &&
     206         [ #  # ]:          0 :                             highlight[0] < (size_t) len) {
     207                 :            : 
     208                 :          0 :                                 fprintf(f, "%*s%s%.*s",
     209                 :            :                                         continuation * prefix, "",
     210                 :          0 :                                         color_on, (int) highlight[0], pos);
     211                 :          0 :                                 fprintf(f, "%s%.*s",
     212                 :            :                                         highlight_on,
     213                 :          0 :                                         (int) (MIN((size_t) len, highlight[1]) - highlight[0]),
     214                 :          0 :                                         pos + highlight[0]);
     215         [ #  # ]:          0 :                                 if ((size_t) len > highlight[1])
     216                 :          0 :                                         fprintf(f, "%s%.*s",
     217                 :            :                                                 color_on,
     218                 :          0 :                                                 (int) (len - highlight[1]),
     219                 :          0 :                                                 pos + highlight[1]);
     220                 :          0 :                                 fprintf(f, "%s\n", color_off);
     221                 :            : 
     222                 :            :                         } else
     223                 :          0 :                                 fprintf(f, "%*s%s%.*s%s\n",
     224                 :            :                                         continuation * prefix, "",
     225                 :            :                                         color_on, len, pos, color_off);
     226                 :          0 :                         continue;
     227                 :            :                 }
     228                 :            : 
     229                 :            :                 /* Beyond this point, ellipsization will happen. */
     230                 :          0 :                 ellipsized = true;
     231                 :            : 
     232   [ #  #  #  # ]:          0 :                 if (prefix < n_columns && n_columns - prefix >= 3) {
     233         [ #  # ]:          0 :                         if (n_columns - prefix > (unsigned) len + 3)
     234                 :          0 :                                 fprintf(f, "%*s%s%.*s...%s\n",
     235                 :            :                                         continuation * prefix, "",
     236                 :            :                                         color_on, len, pos, color_off);
     237                 :            :                         else {
     238                 :          0 :                                 _cleanup_free_ char *e;
     239                 :            : 
     240         [ #  # ]:          0 :                                 e = ellipsize_mem(pos, len, n_columns - prefix,
     241                 :            :                                                   tail_line ? 100 : 90);
     242         [ #  # ]:          0 :                                 if (!e)
     243                 :          0 :                                         fprintf(f, "%*s%s%.*s%s\n",
     244                 :            :                                                 continuation * prefix, "",
     245                 :            :                                                 color_on, len, pos, color_off);
     246                 :            :                                 else
     247                 :          0 :                                         fprintf(f, "%*s%s%s%s\n",
     248                 :            :                                                 continuation * prefix, "",
     249                 :            :                                                 color_on, e, color_off);
     250                 :            :                         }
     251                 :            :                 } else
     252                 :          0 :                         fputs("...\n", f);
     253                 :            : 
     254         [ #  # ]:          0 :                 if (tail_line)
     255                 :          0 :                         break;
     256                 :            :         }
     257                 :            : 
     258                 :          0 :         return ellipsized;
     259                 :            : }
     260                 :            : 
     261                 :          0 : static int output_timestamp_monotonic(FILE *f, sd_journal *j, const char *monotonic) {
     262                 :            :         sd_id128_t boot_id;
     263                 :            :         uint64_t t;
     264                 :            :         int r;
     265                 :            : 
     266         [ #  # ]:          0 :         assert(f);
     267         [ #  # ]:          0 :         assert(j);
     268                 :            : 
     269                 :          0 :         r = -ENXIO;
     270         [ #  # ]:          0 :         if (monotonic)
     271                 :          0 :                 r = safe_atou64(monotonic, &t);
     272         [ #  # ]:          0 :         if (r < 0)
     273                 :          0 :                 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
     274         [ #  # ]:          0 :         if (r < 0)
     275         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
     276                 :            : 
     277                 :          0 :         fprintf(f, "[%5"PRI_USEC".%06"PRI_USEC"]", t / USEC_PER_SEC, t % USEC_PER_SEC);
     278                 :          0 :         return 1 + 5 + 1 + 6 + 1;
     279                 :            : }
     280                 :            : 
     281                 :          0 : static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, OutputFlags flags, const char *realtime) {
     282                 :          0 :         char buf[MAX(FORMAT_TIMESTAMP_MAX, 64)];
     283                 :            :         struct tm *(*gettime_r)(const time_t *, struct tm *);
     284                 :            :         struct tm tm;
     285                 :            :         uint64_t x;
     286                 :            :         time_t t;
     287                 :            :         int r;
     288                 :            : 
     289         [ #  # ]:          0 :         assert(f);
     290         [ #  # ]:          0 :         assert(j);
     291                 :            : 
     292         [ #  # ]:          0 :         if (realtime)
     293                 :          0 :                 r = safe_atou64(realtime, &x);
     294   [ #  #  #  #  :          0 :         if (!realtime || r < 0 || !VALID_REALTIME(x))
                   #  # ]
     295                 :          0 :                 r = sd_journal_get_realtime_usec(j, &x);
     296         [ #  # ]:          0 :         if (r < 0)
     297         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
     298                 :            : 
     299   [ #  #  #  # ]:          0 :         if (IN_SET(mode, OUTPUT_SHORT_FULL, OUTPUT_WITH_UNIT)) {
     300                 :            :                 const char *k;
     301                 :            : 
     302         [ #  # ]:          0 :                 if (flags & OUTPUT_UTC)
     303                 :          0 :                         k = format_timestamp_utc(buf, sizeof(buf), x);
     304                 :            :                 else
     305                 :          0 :                         k = format_timestamp(buf, sizeof(buf), x);
     306         [ #  # ]:          0 :                 if (!k)
     307         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     308                 :            :                                                "Failed to format timestamp: %" PRIu64, x);
     309                 :            : 
     310                 :            :         } else {
     311                 :            :                 char usec[7];
     312                 :            : 
     313         [ #  # ]:          0 :                 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
     314                 :          0 :                 t = (time_t) (x / USEC_PER_SEC);
     315                 :            : 
     316   [ #  #  #  #  :          0 :                 switch (mode) {
                      # ]
     317                 :            : 
     318                 :          0 :                 case OUTPUT_SHORT_UNIX:
     319         [ #  # ]:          0 :                         xsprintf(buf, "%10"PRI_TIME".%06"PRIu64, t, x % USEC_PER_SEC);
     320                 :          0 :                         break;
     321                 :            : 
     322                 :          0 :                 case OUTPUT_SHORT_ISO:
     323         [ #  # ]:          0 :                         if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)) <= 0)
     324         [ #  # ]:          0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     325                 :            :                                                        "Failed to format ISO time");
     326                 :          0 :                         break;
     327                 :            : 
     328                 :          0 :                 case OUTPUT_SHORT_ISO_PRECISE:
     329                 :            :                         /* No usec in strftime, so we leave space and copy over */
     330         [ #  # ]:          0 :                         if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.xxxxxx%z", gettime_r(&t, &tm)) <= 0)
     331         [ #  # ]:          0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     332                 :            :                                                        "Failed to format ISO-precise time");
     333         [ #  # ]:          0 :                         xsprintf(usec, "%06"PRI_USEC, x % USEC_PER_SEC);
     334                 :          0 :                         memcpy(buf + 20, usec, 6);
     335                 :          0 :                         break;
     336                 :            : 
     337                 :          0 :                 case OUTPUT_SHORT:
     338                 :            :                 case OUTPUT_SHORT_PRECISE:
     339                 :            : 
     340         [ #  # ]:          0 :                         if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)) <= 0)
     341         [ #  # ]:          0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     342                 :            :                                                        "Failed to format syslog time");
     343                 :            : 
     344         [ #  # ]:          0 :                         if (mode == OUTPUT_SHORT_PRECISE) {
     345                 :            :                                 size_t k;
     346                 :            : 
     347         [ #  # ]:          0 :                                 assert(sizeof(buf) > strlen(buf));
     348                 :          0 :                                 k = sizeof(buf) - strlen(buf);
     349                 :            : 
     350                 :          0 :                                 r = snprintf(buf + strlen(buf), k, ".%06"PRIu64, x % USEC_PER_SEC);
     351   [ #  #  #  # ]:          0 :                                 if (r <= 0 || (size_t) r >= k) /* too long? */
     352         [ #  # ]:          0 :                                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     353                 :            :                                                                "Failed to format precise time");
     354                 :            :                         }
     355                 :          0 :                         break;
     356                 :            : 
     357                 :          0 :                 default:
     358                 :          0 :                         assert_not_reached("Unknown time format");
     359                 :            :                 }
     360                 :            :         }
     361                 :            : 
     362                 :          0 :         fputs(buf, f);
     363                 :          0 :         return (int) strlen(buf);
     364                 :            : }
     365                 :            : 
     366                 :          0 : static int output_short(
     367                 :            :                 FILE *f,
     368                 :            :                 sd_journal *j,
     369                 :            :                 OutputMode mode,
     370                 :            :                 unsigned n_columns,
     371                 :            :                 OutputFlags flags,
     372                 :            :                 Set *output_fields,
     373                 :            :                 const size_t highlight[2]) {
     374                 :            : 
     375                 :            :         int r;
     376                 :            :         const void *data;
     377                 :            :         size_t length;
     378                 :          0 :         size_t n = 0;
     379                 :          0 :         _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *transport = NULL, *config_file = NULL, *unit = NULL, *user_unit = NULL;
     380                 :          0 :         size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, transport_len = 0, config_file_len = 0, unit_len = 0, user_unit_len = 0;
     381                 :          0 :         int p = LOG_INFO;
     382                 :          0 :         bool ellipsized = false, audit;
     383                 :          0 :         const ParseFieldVec fields[] = {
     384                 :            :                 PARSE_FIELD_VEC_ENTRY("_PID=", &pid, &pid_len),
     385                 :            :                 PARSE_FIELD_VEC_ENTRY("_COMM=", &comm, &comm_len),
     386                 :            :                 PARSE_FIELD_VEC_ENTRY("MESSAGE=", &message, &message_len),
     387                 :            :                 PARSE_FIELD_VEC_ENTRY("PRIORITY=", &priority, &priority_len),
     388                 :            :                 PARSE_FIELD_VEC_ENTRY("_TRANSPORT=", &transport, &transport_len),
     389                 :            :                 PARSE_FIELD_VEC_ENTRY("_HOSTNAME=", &hostname, &hostname_len),
     390                 :            :                 PARSE_FIELD_VEC_ENTRY("SYSLOG_PID=", &fake_pid, &fake_pid_len),
     391                 :            :                 PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len),
     392                 :            :                 PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len),
     393                 :            :                 PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len),
     394                 :            :                 PARSE_FIELD_VEC_ENTRY("CONFIG_FILE=", &config_file, &config_file_len),
     395                 :            :                 PARSE_FIELD_VEC_ENTRY("_SYSTEMD_UNIT=", &unit, &unit_len),
     396                 :            :                 PARSE_FIELD_VEC_ENTRY("_SYSTEMD_USER_UNIT=", &user_unit, &user_unit_len),
     397                 :            :         };
     398   [ #  #  #  # ]:          0 :         size_t highlight_shifted[] = {highlight ? highlight[0] : 0, highlight ? highlight[1] : 0};
     399                 :            : 
     400         [ #  # ]:          0 :         assert(f);
     401         [ #  # ]:          0 :         assert(j);
     402                 :            : 
     403                 :            :         /* Set the threshold to one bigger than the actual print
     404                 :            :          * threshold, so that if the line is actually longer than what
     405                 :            :          * we're willing to print, ellipsization will occur. This way
     406                 :            :          * we won't output a misleading line without any indication of
     407                 :            :          * truncation.
     408                 :            :          */
     409         [ #  # ]:          0 :         sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
     410                 :            : 
     411         [ #  # ]:          0 :         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
     412                 :          0 :                 r = parse_fieldv(data, length, fields, ELEMENTSOF(fields));
     413         [ #  # ]:          0 :                 if (r < 0)
     414                 :          0 :                         return r;
     415                 :            :         }
     416         [ #  # ]:          0 :         if (r == -EBADMSG) {
     417         [ #  # ]:          0 :                 log_debug_errno(r, "Skipping message we can't read: %m");
     418                 :          0 :                 return 0;
     419                 :            :         }
     420         [ #  # ]:          0 :         if (r < 0)
     421         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get journal fields: %m");
     422                 :            : 
     423         [ #  # ]:          0 :         if (!message) {
     424         [ #  # ]:          0 :                 log_debug("Skipping message without MESSAGE= field.");
     425                 :          0 :                 return 0;
     426                 :            :         }
     427                 :            : 
     428         [ #  # ]:          0 :         if (!(flags & OUTPUT_SHOW_ALL))
     429                 :          0 :                 strip_tab_ansi(&message, &message_len, highlight_shifted);
     430                 :            : 
     431   [ #  #  #  #  :          0 :         if (priority_len == 1 && *priority >= '0' && *priority <= '7')
                   #  # ]
     432                 :          0 :                 p = *priority - '0';
     433                 :            : 
     434                 :          0 :         audit = streq_ptr(transport, "audit");
     435                 :            : 
     436         [ #  # ]:          0 :         if (mode == OUTPUT_SHORT_MONOTONIC)
     437                 :          0 :                 r = output_timestamp_monotonic(f, j, monotonic);
     438                 :            :         else
     439                 :          0 :                 r = output_timestamp_realtime(f, j, mode, flags, realtime);
     440         [ #  # ]:          0 :         if (r < 0)
     441                 :          0 :                 return r;
     442                 :          0 :         n += r;
     443                 :            : 
     444         [ #  # ]:          0 :         if (flags & OUTPUT_NO_HOSTNAME) {
     445                 :            :                 /* Suppress display of the hostname if this is requested. */
     446                 :          0 :                 hostname = mfree(hostname);
     447                 :          0 :                 hostname_len = 0;
     448                 :            :         }
     449                 :            : 
     450   [ #  #  #  # ]:          0 :         if (hostname && shall_print(hostname, hostname_len, flags)) {
     451                 :          0 :                 fprintf(f, " %.*s", (int) hostname_len, hostname);
     452                 :          0 :                 n += hostname_len + 1;
     453                 :            :         }
     454                 :            : 
     455   [ #  #  #  #  :          0 :         if (mode == OUTPUT_WITH_UNIT && ((unit && shall_print(unit, unit_len, flags)) ||
                   #  # ]
     456   [ #  #  #  # ]:          0 :                                          (user_unit && shall_print(user_unit, user_unit_len, flags)))) {
     457         [ #  # ]:          0 :                 if (unit) {
     458                 :          0 :                         fprintf(f, " %.*s", (int) unit_len, unit);
     459                 :          0 :                         n += unit_len + 1;
     460                 :            :                 }
     461         [ #  # ]:          0 :                 if (user_unit) {
     462         [ #  # ]:          0 :                         if (unit)
     463                 :          0 :                                 fprintf(f, "/%.*s", (int) user_unit_len, user_unit);
     464                 :            :                         else
     465                 :          0 :                                 fprintf(f, " %.*s", (int) user_unit_len, user_unit);
     466                 :          0 :                         n += unit_len + 1;
     467                 :            :                 }
     468   [ #  #  #  # ]:          0 :         } else if (identifier && shall_print(identifier, identifier_len, flags)) {
     469                 :          0 :                 fprintf(f, " %.*s", (int) identifier_len, identifier);
     470                 :          0 :                 n += identifier_len + 1;
     471   [ #  #  #  # ]:          0 :         } else if (comm && shall_print(comm, comm_len, flags)) {
     472                 :          0 :                 fprintf(f, " %.*s", (int) comm_len, comm);
     473                 :          0 :                 n += comm_len + 1;
     474                 :            :         } else
     475                 :          0 :                 fputs(" unknown", f);
     476                 :            : 
     477   [ #  #  #  # ]:          0 :         if (pid && shall_print(pid, pid_len, flags)) {
     478                 :          0 :                 fprintf(f, "[%.*s]", (int) pid_len, pid);
     479                 :          0 :                 n += pid_len + 2;
     480   [ #  #  #  # ]:          0 :         } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
     481                 :          0 :                 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
     482                 :          0 :                 n += fake_pid_len + 2;
     483                 :            :         }
     484                 :            : 
     485   [ #  #  #  # ]:          0 :         if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
     486                 :            :                 char bytes[FORMAT_BYTES_MAX];
     487                 :          0 :                 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
     488                 :            :         } else {
     489                 :          0 :                 fputs(": ", f);
     490                 :            : 
     491                 :            :                 /* URLify config_file string in message, if the message starts with it.
     492                 :            :                  * Skip URLification if the highlighted pattern overlaps. */
     493         [ #  # ]:          0 :                 if (config_file &&
     494         [ #  # ]:          0 :                     message_len >= config_file_len &&
     495         [ #  # ]:          0 :                     memcmp(message, config_file, config_file_len) == 0 &&
     496   [ #  #  #  #  :          0 :                     IN_SET(message[config_file_len], ':', ' ', '\0') &&
                   #  # ]
     497   [ #  #  #  # ]:          0 :                     (!highlight || highlight_shifted[0] == 0 || highlight_shifted[0] > config_file_len)) {
     498                 :            : 
     499                 :          0 :                         _cleanup_free_ char *t = NULL, *urlified = NULL;
     500                 :            : 
     501                 :          0 :                         t = strndup(config_file, config_file_len);
     502   [ #  #  #  # ]:          0 :                         if (t && terminal_urlify_path(t, NULL, &urlified) >= 0) {
     503                 :          0 :                                 size_t shift = strlen(urlified) - config_file_len;
     504                 :            :                                 char *joined;
     505                 :            : 
     506                 :          0 :                                 joined = strjoin(urlified, message + config_file_len);
     507         [ #  # ]:          0 :                                 if (joined) {
     508                 :          0 :                                         free_and_replace(message, joined);
     509                 :          0 :                                         message_len += shift;
     510         [ #  # ]:          0 :                                         if (highlight) {
     511                 :          0 :                                                 highlight_shifted[0] += shift;
     512                 :          0 :                                                 highlight_shifted[1] += shift;
     513                 :            :                                         }
     514                 :            :                                 }
     515                 :            :                         }
     516                 :            :                 }
     517                 :            : 
     518                 :          0 :                 ellipsized |=
     519                 :          0 :                         print_multiline(f, n + 2, n_columns, flags, p, audit,
     520                 :            :                                         message, message_len,
     521                 :            :                                         highlight_shifted);
     522                 :            :         }
     523                 :            : 
     524         [ #  # ]:          0 :         if (flags & OUTPUT_CATALOG)
     525                 :          0 :                 print_catalog(f, j);
     526                 :            : 
     527                 :          0 :         return ellipsized;
     528                 :            : }
     529                 :            : 
     530                 :          0 : static int output_verbose(
     531                 :            :                 FILE *f,
     532                 :            :                 sd_journal *j,
     533                 :            :                 OutputMode mode,
     534                 :            :                 unsigned n_columns,
     535                 :            :                 OutputFlags flags,
     536                 :            :                 Set *output_fields,
     537                 :            :                 const size_t highlight[2]) {
     538                 :            : 
     539                 :            :         const void *data;
     540                 :            :         size_t length;
     541                 :          0 :         _cleanup_free_ char *cursor = NULL;
     542                 :          0 :         uint64_t realtime = 0;
     543                 :            :         char ts[FORMAT_TIMESTAMP_MAX + 7];
     544                 :            :         const char *timestamp;
     545                 :            :         int r;
     546                 :            : 
     547         [ #  # ]:          0 :         assert(f);
     548         [ #  # ]:          0 :         assert(j);
     549                 :            : 
     550                 :          0 :         sd_journal_set_data_threshold(j, 0);
     551                 :            : 
     552                 :          0 :         r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
     553         [ #  # ]:          0 :         if (r == -ENOENT)
     554         [ #  # ]:          0 :                 log_debug("Source realtime timestamp not found");
     555         [ #  # ]:          0 :         else if (r < 0)
     556   [ #  #  #  # ]:          0 :                 return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m");
     557                 :            :         else {
     558         [ #  # ]:          0 :                 _cleanup_free_ char *value = NULL;
     559                 :            : 
     560                 :          0 :                 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=",
     561                 :            :                                 STRLEN("_SOURCE_REALTIME_TIMESTAMP="), &value,
     562                 :            :                                 NULL);
     563         [ #  # ]:          0 :                 if (r < 0)
     564                 :          0 :                         return r;
     565         [ #  # ]:          0 :                 assert(r > 0);
     566                 :            : 
     567                 :          0 :                 r = safe_atou64(value, &realtime);
     568         [ #  # ]:          0 :                 if (r < 0)
     569         [ #  # ]:          0 :                         log_debug_errno(r, "Failed to parse realtime timestamp: %m");
     570                 :            :         }
     571                 :            : 
     572         [ #  # ]:          0 :         if (r < 0) {
     573                 :          0 :                 r = sd_journal_get_realtime_usec(j, &realtime);
     574         [ #  # ]:          0 :                 if (r < 0)
     575   [ #  #  #  # ]:          0 :                         return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m");
     576                 :            :         }
     577                 :            : 
     578                 :          0 :         r = sd_journal_get_cursor(j, &cursor);
     579         [ #  # ]:          0 :         if (r < 0)
     580         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get cursor: %m");
     581                 :            : 
     582         [ #  # ]:          0 :         timestamp = flags & OUTPUT_UTC ? format_timestamp_us_utc(ts, sizeof ts, realtime)
     583                 :          0 :                                        : format_timestamp_us(ts, sizeof ts, realtime);
     584                 :          0 :         fprintf(f, "%s [%s]\n",
     585         [ #  # ]:          0 :                 timestamp ?: "(no timestamp)",
     586                 :            :                 cursor);
     587                 :            : 
     588         [ #  # ]:          0 :         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
     589                 :            :                 const char *c, *p;
     590                 :            :                 int fieldlen;
     591                 :          0 :                 const char *on = "", *off = "";
     592      [ #  #  # ]:          0 :                 _cleanup_free_ char *urlified = NULL;
     593                 :            :                 size_t valuelen;
     594                 :            : 
     595                 :          0 :                 c = memchr(data, '=', length);
     596         [ #  # ]:          0 :                 if (!c)
     597         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     598                 :            :                                                "Invalid field.");
     599                 :          0 :                 fieldlen = c - (const char*) data;
     600                 :            : 
     601                 :          0 :                 r = field_set_test(output_fields, data, fieldlen);
     602         [ #  # ]:          0 :                 if (r < 0)
     603                 :          0 :                         return r;
     604         [ #  # ]:          0 :                 if (r == 0)
     605                 :          0 :                         continue;
     606                 :            : 
     607                 :          0 :                 valuelen = length - 1 - fieldlen;
     608                 :            : 
     609   [ #  #  #  # ]:          0 :                 if ((flags & OUTPUT_COLOR) && (p = startswith(data, "MESSAGE="))) {
     610                 :          0 :                         on = ANSI_HIGHLIGHT;
     611                 :          0 :                         off = ANSI_NORMAL;
     612         [ #  # ]:          0 :                 } else if ((p = startswith(data, "CONFIG_FILE="))) {
     613         [ #  # ]:          0 :                         if (terminal_urlify_path(p, NULL, &urlified) >= 0) {
     614                 :          0 :                                 p = urlified;
     615                 :          0 :                                 valuelen = strlen(urlified);
     616                 :            :                         }
     617                 :            :                 } else
     618                 :          0 :                         p = c + 1;
     619                 :            : 
     620         [ #  # ]:          0 :                 if ((flags & OUTPUT_SHOW_ALL) ||
     621   [ #  #  #  # ]:          0 :                     (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
     622         [ #  # ]:          0 :                      && utf8_is_printable(data, length))) {
     623                 :          0 :                         fprintf(f, "    %s%.*s=", on, fieldlen, (const char*)data);
     624                 :          0 :                         print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, false,
     625                 :            :                                         p, valuelen,
     626                 :            :                                         NULL);
     627                 :          0 :                         fputs(off, f);
     628                 :            :                 } else {
     629                 :            :                         char bytes[FORMAT_BYTES_MAX];
     630                 :            : 
     631                 :          0 :                         fprintf(f, "    %s%.*s=[%s blob data]%s\n",
     632                 :            :                                 on,
     633                 :          0 :                                 (int) (c - (const char*) data),
     634                 :            :                                 (const char*) data,
     635                 :          0 :                                 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
     636                 :            :                                 off);
     637                 :            :                 }
     638                 :            :         }
     639                 :            : 
     640         [ #  # ]:          0 :         if (r < 0)
     641                 :          0 :                 return r;
     642                 :            : 
     643         [ #  # ]:          0 :         if (flags & OUTPUT_CATALOG)
     644                 :          0 :                 print_catalog(f, j);
     645                 :            : 
     646                 :          0 :         return 0;
     647                 :            : }
     648                 :            : 
     649                 :          0 : static int output_export(
     650                 :            :                 FILE *f,
     651                 :            :                 sd_journal *j,
     652                 :            :                 OutputMode mode,
     653                 :            :                 unsigned n_columns,
     654                 :            :                 OutputFlags flags,
     655                 :            :                 Set *output_fields,
     656                 :            :                 const size_t highlight[2]) {
     657                 :            : 
     658                 :            :         sd_id128_t boot_id;
     659                 :            :         char sid[33];
     660                 :            :         int r;
     661                 :            :         usec_t realtime, monotonic;
     662                 :          0 :         _cleanup_free_ char *cursor = NULL;
     663                 :            :         const void *data;
     664                 :            :         size_t length;
     665                 :            : 
     666         [ #  # ]:          0 :         assert(j);
     667                 :            : 
     668                 :          0 :         sd_journal_set_data_threshold(j, 0);
     669                 :            : 
     670                 :          0 :         r = sd_journal_get_realtime_usec(j, &realtime);
     671         [ #  # ]:          0 :         if (r < 0)
     672         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
     673                 :            : 
     674                 :          0 :         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
     675         [ #  # ]:          0 :         if (r < 0)
     676         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
     677                 :            : 
     678                 :          0 :         r = sd_journal_get_cursor(j, &cursor);
     679         [ #  # ]:          0 :         if (r < 0)
     680         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get cursor: %m");
     681                 :            : 
     682                 :          0 :         fprintf(f,
     683                 :            :                 "__CURSOR=%s\n"
     684                 :            :                 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
     685                 :            :                 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
     686                 :            :                 "_BOOT_ID=%s\n",
     687                 :            :                 cursor,
     688                 :            :                 realtime,
     689                 :            :                 monotonic,
     690                 :            :                 sd_id128_to_string(boot_id, sid));
     691                 :            : 
     692         [ #  # ]:          0 :         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
     693                 :            :                 const char *c;
     694                 :            : 
     695                 :            :                 /* We already printed the boot id from the data in the header, hence let's suppress it here */
     696         [ #  # ]:          0 :                 if (memory_startswith(data, length, "_BOOT_ID="))
     697                 :          0 :                         continue;
     698                 :            : 
     699                 :          0 :                 c = memchr(data, '=', length);
     700         [ #  # ]:          0 :                 if (!c)
     701         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     702                 :            :                                                "Invalid field.");
     703                 :            : 
     704                 :          0 :                 r = field_set_test(output_fields, data, c - (const char *) data);
     705         [ #  # ]:          0 :                 if (r < 0)
     706                 :          0 :                         return r;
     707         [ #  # ]:          0 :                 if (!r)
     708                 :          0 :                         continue;
     709                 :            : 
     710         [ #  # ]:          0 :                 if (utf8_is_printable_newline(data, length, false))
     711                 :          0 :                         fwrite(data, length, 1, f);
     712                 :            :                 else {
     713                 :            :                         uint64_t le64;
     714                 :            : 
     715                 :          0 :                         fwrite(data, c - (const char*) data, 1, f);
     716                 :          0 :                         fputc('\n', f);
     717                 :          0 :                         le64 = htole64(length - (c - (const char*) data) - 1);
     718                 :          0 :                         fwrite(&le64, sizeof(le64), 1, f);
     719                 :          0 :                         fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
     720                 :            :                 }
     721                 :            : 
     722                 :          0 :                 fputc('\n', f);
     723                 :            :         }
     724         [ #  # ]:          0 :         if (r == -EBADMSG) {
     725         [ #  # ]:          0 :                 log_debug_errno(r, "Skipping message we can't read: %m");
     726                 :          0 :                 return 0;
     727                 :            :         }
     728                 :            : 
     729         [ #  # ]:          0 :         if (r < 0)
     730                 :          0 :                 return r;
     731                 :            : 
     732                 :          0 :         fputc('\n', f);
     733                 :            : 
     734                 :          0 :         return 0;
     735                 :            : }
     736                 :            : 
     737                 :          0 : void json_escape(
     738                 :            :                 FILE *f,
     739                 :            :                 const char* p,
     740                 :            :                 size_t l,
     741                 :            :                 OutputFlags flags) {
     742                 :            : 
     743         [ #  # ]:          0 :         assert(f);
     744         [ #  # ]:          0 :         assert(p);
     745                 :            : 
     746   [ #  #  #  # ]:          0 :         if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
     747                 :          0 :                 fputs("null", f);
     748                 :            : 
     749   [ #  #  #  # ]:          0 :         else if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(p, l)) {
     750                 :          0 :                 bool not_first = false;
     751                 :            : 
     752                 :          0 :                 fputs("[ ", f);
     753                 :            : 
     754         [ #  # ]:          0 :                 while (l > 0) {
     755         [ #  # ]:          0 :                         if (not_first)
     756                 :          0 :                                 fprintf(f, ", %u", (uint8_t) *p);
     757                 :            :                         else {
     758                 :          0 :                                 not_first = true;
     759                 :          0 :                                 fprintf(f, "%u", (uint8_t) *p);
     760                 :            :                         }
     761                 :            : 
     762                 :          0 :                         p++;
     763                 :          0 :                         l--;
     764                 :            :                 }
     765                 :            : 
     766                 :          0 :                 fputs(" ]", f);
     767                 :            :         } else {
     768                 :          0 :                 fputc('"', f);
     769                 :            : 
     770         [ #  # ]:          0 :                 while (l > 0) {
     771   [ #  #  #  # ]:          0 :                         if (IN_SET(*p, '"', '\\')) {
     772                 :          0 :                                 fputc('\\', f);
     773                 :          0 :                                 fputc(*p, f);
     774         [ #  # ]:          0 :                         } else if (*p == '\n')
     775                 :          0 :                                 fputs("\\n", f);
     776         [ #  # ]:          0 :                         else if ((uint8_t) *p < ' ')
     777                 :          0 :                                 fprintf(f, "\\u%04x", (uint8_t) *p);
     778                 :            :                         else
     779                 :          0 :                                 fputc(*p, f);
     780                 :            : 
     781                 :          0 :                         p++;
     782                 :          0 :                         l--;
     783                 :            :                 }
     784                 :            : 
     785                 :          0 :                 fputc('"', f);
     786                 :            :         }
     787                 :          0 : }
     788                 :            : 
     789                 :            : struct json_data {
     790                 :            :         JsonVariant* name;
     791                 :            :         size_t n_values;
     792                 :            :         JsonVariant* values[];
     793                 :            : };
     794                 :            : 
     795                 :          0 : static int update_json_data(
     796                 :            :                 Hashmap *h,
     797                 :            :                 OutputFlags flags,
     798                 :            :                 const char *name,
     799                 :            :                 const void *value,
     800                 :            :                 size_t size) {
     801                 :            : 
     802                 :          0 :         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
     803                 :            :         struct json_data *d;
     804                 :            :         int r;
     805                 :            : 
     806   [ #  #  #  # ]:          0 :         if (!(flags & OUTPUT_SHOW_ALL) && strlen(name) + 1 + size >= JSON_THRESHOLD)
     807                 :          0 :                 r = json_variant_new_null(&v);
     808         [ #  # ]:          0 :         else if (utf8_is_printable(value, size))
     809                 :          0 :                 r = json_variant_new_stringn(&v, value, size);
     810                 :            :         else
     811                 :          0 :                 r = json_variant_new_array_bytes(&v, value, size);
     812         [ #  # ]:          0 :         if (r < 0)
     813         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to allocate JSON data: %m");
     814                 :            : 
     815                 :          0 :         d = hashmap_get(h, name);
     816         [ #  # ]:          0 :         if (d) {
     817                 :            :                 struct json_data *w;
     818                 :            : 
     819                 :          0 :                 w = realloc(d, offsetof(struct json_data, values) + sizeof(JsonVariant*) * (d->n_values + 1));
     820         [ #  # ]:          0 :                 if (!w)
     821                 :          0 :                         return log_oom();
     822                 :            : 
     823                 :          0 :                 d = w;
     824         [ #  # ]:          0 :                 assert_se(hashmap_update(h, json_variant_string(d->name), d) >= 0);
     825                 :            :         } else {
     826         [ #  # ]:          0 :                 _cleanup_(json_variant_unrefp) JsonVariant *n = NULL;
     827                 :            : 
     828                 :          0 :                 r = json_variant_new_string(&n, name);
     829         [ #  # ]:          0 :                 if (r < 0)
     830         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to allocate JSON name variant: %m");
     831                 :            : 
     832                 :          0 :                 d = malloc0(offsetof(struct json_data, values) + sizeof(JsonVariant*));
     833         [ #  # ]:          0 :                 if (!d)
     834                 :          0 :                         return log_oom();
     835                 :            : 
     836                 :          0 :                 r = hashmap_put(h, json_variant_string(n), d);
     837         [ #  # ]:          0 :                 if (r < 0) {
     838                 :          0 :                         free(d);
     839         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to insert JSON name into hashmap: %m");
     840                 :            :                 }
     841                 :            : 
     842                 :          0 :                 d->name = TAKE_PTR(n);
     843                 :            :         }
     844                 :            : 
     845                 :          0 :         d->values[d->n_values++] = TAKE_PTR(v);
     846                 :          0 :         return 0;
     847                 :            : }
     848                 :            : 
     849                 :          0 : static int update_json_data_split(
     850                 :            :                 Hashmap *h,
     851                 :            :                 OutputFlags flags,
     852                 :            :                 Set *output_fields,
     853                 :            :                 const void *data,
     854                 :            :                 size_t size) {
     855                 :            : 
     856                 :            :         const char *eq;
     857                 :            :         char *name;
     858                 :            : 
     859         [ #  # ]:          0 :         assert(h);
     860   [ #  #  #  # ]:          0 :         assert(data || size == 0);
     861                 :            : 
     862         [ #  # ]:          0 :         if (memory_startswith(data, size, "_BOOT_ID="))
     863                 :          0 :                 return 0;
     864                 :            : 
     865                 :          0 :         eq = memchr(data, '=', MIN(size, JSON_THRESHOLD));
     866         [ #  # ]:          0 :         if (!eq)
     867                 :          0 :                 return 0;
     868                 :            : 
     869         [ #  # ]:          0 :         if (eq == data)
     870                 :          0 :                 return 0;
     871                 :            : 
     872                 :          0 :         name = strndupa(data, eq - (const char*) data);
     873   [ #  #  #  # ]:          0 :         if (output_fields && !set_get(output_fields, name))
     874                 :          0 :                 return 0;
     875                 :            : 
     876                 :          0 :         return update_json_data(h, flags, name, eq + 1, size - (eq - (const char*) data) - 1);
     877                 :            : }
     878                 :            : 
     879                 :          0 : static int output_json(
     880                 :            :                 FILE *f,
     881                 :            :                 sd_journal *j,
     882                 :            :                 OutputMode mode,
     883                 :            :                 unsigned n_columns,
     884                 :            :                 OutputFlags flags,
     885                 :            :                 Set *output_fields,
     886                 :            :                 const size_t highlight[2]) {
     887                 :            : 
     888                 :            :         char sid[SD_ID128_STRING_MAX], usecbuf[DECIMAL_STR_MAX(usec_t)];
     889                 :          0 :         _cleanup_(json_variant_unrefp) JsonVariant *object = NULL;
     890                 :          0 :         _cleanup_free_ char *cursor = NULL;
     891                 :            :         uint64_t realtime, monotonic;
     892                 :          0 :         JsonVariant **array = NULL;
     893                 :            :         struct json_data *d;
     894                 :            :         sd_id128_t boot_id;
     895                 :          0 :         Hashmap *h = NULL;
     896                 :          0 :         size_t n = 0;
     897                 :            :         Iterator i;
     898                 :            :         int r;
     899                 :            : 
     900         [ #  # ]:          0 :         assert(j);
     901                 :            : 
     902         [ #  # ]:          0 :         (void) sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
     903                 :            : 
     904                 :          0 :         r = sd_journal_get_realtime_usec(j, &realtime);
     905         [ #  # ]:          0 :         if (r < 0)
     906         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
     907                 :            : 
     908                 :          0 :         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
     909         [ #  # ]:          0 :         if (r < 0)
     910         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
     911                 :            : 
     912                 :          0 :         r = sd_journal_get_cursor(j, &cursor);
     913         [ #  # ]:          0 :         if (r < 0)
     914         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get cursor: %m");
     915                 :            : 
     916                 :          0 :         h = hashmap_new(&string_hash_ops);
     917         [ #  # ]:          0 :         if (!h)
     918                 :          0 :                 return log_oom();
     919                 :            : 
     920                 :          0 :         r = update_json_data(h, flags, "__CURSOR", cursor, strlen(cursor));
     921         [ #  # ]:          0 :         if (r < 0)
     922                 :          0 :                 goto finish;
     923                 :            : 
     924         [ #  # ]:          0 :         xsprintf(usecbuf, USEC_FMT, realtime);
     925                 :          0 :         r = update_json_data(h, flags, "__REALTIME_TIMESTAMP", usecbuf, strlen(usecbuf));
     926         [ #  # ]:          0 :         if (r < 0)
     927                 :          0 :                 goto finish;
     928                 :            : 
     929         [ #  # ]:          0 :         xsprintf(usecbuf, USEC_FMT, monotonic);
     930                 :          0 :         r = update_json_data(h, flags, "__MONOTONIC_TIMESTAMP", usecbuf, strlen(usecbuf));
     931         [ #  # ]:          0 :         if (r < 0)
     932                 :          0 :                 goto finish;
     933                 :            : 
     934                 :          0 :         sd_id128_to_string(boot_id, sid);
     935                 :          0 :         r = update_json_data(h, flags, "_BOOT_ID", sid, strlen(sid));
     936         [ #  # ]:          0 :         if (r < 0)
     937                 :          0 :                 goto finish;
     938                 :            : 
     939                 :          0 :         for (;;) {
     940                 :            :                 const void *data;
     941                 :            :                 size_t size;
     942                 :            : 
     943                 :          0 :                 r = sd_journal_enumerate_data(j, &data, &size);
     944         [ #  # ]:          0 :                 if (r == -EBADMSG) {
     945         [ #  # ]:          0 :                         log_debug_errno(r, "Skipping message we can't read: %m");
     946                 :          0 :                         r = 0;
     947                 :          0 :                         goto finish;
     948                 :            :                 }
     949         [ #  # ]:          0 :                 if (r < 0) {
     950         [ #  # ]:          0 :                         log_error_errno(r, "Failed to read journal: %m");
     951                 :          0 :                         goto finish;
     952                 :            :                 }
     953         [ #  # ]:          0 :                 if (r == 0)
     954                 :          0 :                         break;
     955                 :            : 
     956                 :          0 :                 r = update_json_data_split(h, flags, output_fields, data, size);
     957         [ #  # ]:          0 :                 if (r < 0)
     958                 :          0 :                         goto finish;
     959                 :            :         }
     960                 :            : 
     961                 :          0 :         array = new(JsonVariant*, hashmap_size(h)*2);
     962         [ #  # ]:          0 :         if (!array) {
     963                 :          0 :                 r = log_oom();
     964                 :          0 :                 goto finish;
     965                 :            :         }
     966                 :            : 
     967         [ #  # ]:          0 :         HASHMAP_FOREACH(d, h, i) {
     968         [ #  # ]:          0 :                 assert(d->n_values > 0);
     969                 :            : 
     970                 :          0 :                 array[n++] = json_variant_ref(d->name);
     971                 :            : 
     972         [ #  # ]:          0 :                 if (d->n_values == 1)
     973                 :          0 :                         array[n++] = json_variant_ref(d->values[0]);
     974                 :            :                 else {
     975         [ #  # ]:          0 :                         _cleanup_(json_variant_unrefp) JsonVariant *q = NULL;
     976                 :            : 
     977                 :          0 :                         r = json_variant_new_array(&q, d->values, d->n_values);
     978         [ #  # ]:          0 :                         if (r < 0) {
     979         [ #  # ]:          0 :                                 log_error_errno(r, "Failed to create JSON array: %m");
     980                 :          0 :                                 goto finish;
     981                 :            :                         }
     982                 :            : 
     983                 :          0 :                         array[n++] = TAKE_PTR(q);
     984                 :            :                 }
     985                 :            :         }
     986                 :            : 
     987                 :          0 :         r = json_variant_new_object(&object, array, n);
     988         [ #  # ]:          0 :         if (r < 0) {
     989         [ #  # ]:          0 :                 log_error_errno(r, "Failed to allocate JSON object: %m");
     990                 :          0 :                 goto finish;
     991                 :            :         }
     992                 :            : 
     993                 :          0 :         json_variant_dump(object,
     994                 :          0 :                           output_mode_to_json_format_flags(mode) |
     995                 :          0 :                           (FLAGS_SET(flags, OUTPUT_COLOR) ? JSON_FORMAT_COLOR : 0),
     996                 :            :                           f, NULL);
     997                 :            : 
     998                 :          0 :         r = 0;
     999                 :            : 
    1000                 :          0 : finish:
    1001         [ #  # ]:          0 :         while ((d = hashmap_steal_first(h))) {
    1002                 :            :                 size_t k;
    1003                 :            : 
    1004                 :          0 :                 json_variant_unref(d->name);
    1005         [ #  # ]:          0 :                 for (k = 0; k < d->n_values; k++)
    1006                 :          0 :                         json_variant_unref(d->values[k]);
    1007                 :            : 
    1008                 :          0 :                 free(d);
    1009                 :            :         }
    1010                 :            : 
    1011                 :          0 :         hashmap_free(h);
    1012                 :            : 
    1013                 :          0 :         json_variant_unref_many(array, n);
    1014                 :          0 :         free(array);
    1015                 :            : 
    1016                 :          0 :         return r;
    1017                 :            : }
    1018                 :            : 
    1019                 :          0 : static int output_cat(
    1020                 :            :                 FILE *f,
    1021                 :            :                 sd_journal *j,
    1022                 :            :                 OutputMode mode,
    1023                 :            :                 unsigned n_columns,
    1024                 :            :                 OutputFlags flags,
    1025                 :            :                 Set *output_fields,
    1026                 :            :                 const size_t highlight[2]) {
    1027                 :            : 
    1028                 :            :         const void *data;
    1029                 :            :         size_t l;
    1030                 :            :         int r;
    1031                 :          0 :         const char *highlight_on = "", *highlight_off = "";
    1032                 :            : 
    1033         [ #  # ]:          0 :         assert(j);
    1034         [ #  # ]:          0 :         assert(f);
    1035                 :            : 
    1036         [ #  # ]:          0 :         if (flags & OUTPUT_COLOR) {
    1037                 :          0 :                 highlight_on = ANSI_HIGHLIGHT_RED;
    1038                 :          0 :                 highlight_off = ANSI_NORMAL;
    1039                 :            :         }
    1040                 :            : 
    1041                 :          0 :         sd_journal_set_data_threshold(j, 0);
    1042                 :            : 
    1043                 :          0 :         r = sd_journal_get_data(j, "MESSAGE", &data, &l);
    1044         [ #  # ]:          0 :         if (r == -EBADMSG) {
    1045         [ #  # ]:          0 :                 log_debug_errno(r, "Skipping message we can't read: %m");
    1046                 :          0 :                 return 0;
    1047                 :            :         }
    1048         [ #  # ]:          0 :         if (r < 0) {
    1049                 :            :                 /* An entry without MESSAGE=? */
    1050         [ #  # ]:          0 :                 if (r == -ENOENT)
    1051                 :          0 :                         return 0;
    1052                 :            : 
    1053         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get data: %m");
    1054                 :            :         }
    1055                 :            : 
    1056         [ #  # ]:          0 :         assert(l >= 8);
    1057                 :            : 
    1058   [ #  #  #  # ]:          0 :         if (highlight && (flags & OUTPUT_COLOR)) {
    1059         [ #  # ]:          0 :                 assert(highlight[0] <= highlight[1]);
    1060         [ #  # ]:          0 :                 assert(highlight[1] <= l - 8);
    1061                 :            : 
    1062                 :          0 :                 fwrite((const char*) data + 8, 1, highlight[0], f);
    1063                 :          0 :                 fwrite(highlight_on, 1, strlen(highlight_on), f);
    1064                 :          0 :                 fwrite((const char*) data + 8 + highlight[0], 1, highlight[1] - highlight[0], f);
    1065                 :          0 :                 fwrite(highlight_off, 1, strlen(highlight_off), f);
    1066                 :          0 :                 fwrite((const char*) data + 8 + highlight[1], 1, l - 8 - highlight[1], f);
    1067                 :            :         } else
    1068                 :          0 :                 fwrite((const char*) data + 8, 1, l - 8, f);
    1069                 :          0 :         fputc('\n', f);
    1070                 :            : 
    1071                 :          0 :         return 0;
    1072                 :            : }
    1073                 :            : 
    1074                 :            : static int (*output_funcs[_OUTPUT_MODE_MAX])(
    1075                 :            :                 FILE *f,
    1076                 :            :                 sd_journal *j,
    1077                 :            :                 OutputMode mode,
    1078                 :            :                 unsigned n_columns,
    1079                 :            :                 OutputFlags flags,
    1080                 :            :                 Set *output_fields,
    1081                 :            :                 const size_t highlight[2]) = {
    1082                 :            : 
    1083                 :            :         [OUTPUT_SHORT]             = output_short,
    1084                 :            :         [OUTPUT_SHORT_ISO]         = output_short,
    1085                 :            :         [OUTPUT_SHORT_ISO_PRECISE] = output_short,
    1086                 :            :         [OUTPUT_SHORT_PRECISE]     = output_short,
    1087                 :            :         [OUTPUT_SHORT_MONOTONIC]   = output_short,
    1088                 :            :         [OUTPUT_SHORT_UNIX]        = output_short,
    1089                 :            :         [OUTPUT_SHORT_FULL]        = output_short,
    1090                 :            :         [OUTPUT_VERBOSE]           = output_verbose,
    1091                 :            :         [OUTPUT_EXPORT]            = output_export,
    1092                 :            :         [OUTPUT_JSON]              = output_json,
    1093                 :            :         [OUTPUT_JSON_PRETTY]       = output_json,
    1094                 :            :         [OUTPUT_JSON_SSE]          = output_json,
    1095                 :            :         [OUTPUT_JSON_SEQ]          = output_json,
    1096                 :            :         [OUTPUT_CAT]               = output_cat,
    1097                 :            :         [OUTPUT_WITH_UNIT]         = output_short,
    1098                 :            : };
    1099                 :            : 
    1100                 :          0 : int show_journal_entry(
    1101                 :            :                 FILE *f,
    1102                 :            :                 sd_journal *j,
    1103                 :            :                 OutputMode mode,
    1104                 :            :                 unsigned n_columns,
    1105                 :            :                 OutputFlags flags,
    1106                 :            :                 char **output_fields,
    1107                 :            :                 const size_t highlight[2],
    1108                 :            :                 bool *ellipsized) {
    1109                 :            : 
    1110                 :            :         int ret;
    1111                 :          0 :         _cleanup_set_free_free_ Set *fields = NULL;
    1112         [ #  # ]:          0 :         assert(mode >= 0);
    1113         [ #  # ]:          0 :         assert(mode < _OUTPUT_MODE_MAX);
    1114                 :            : 
    1115         [ #  # ]:          0 :         if (n_columns <= 0)
    1116                 :          0 :                 n_columns = columns();
    1117                 :            : 
    1118         [ #  # ]:          0 :         if (output_fields) {
    1119                 :          0 :                 fields = set_new(&string_hash_ops);
    1120         [ #  # ]:          0 :                 if (!fields)
    1121                 :          0 :                         return log_oom();
    1122                 :            : 
    1123                 :          0 :                 ret = set_put_strdupv(fields, output_fields);
    1124         [ #  # ]:          0 :                 if (ret < 0)
    1125                 :          0 :                         return ret;
    1126                 :            :         }
    1127                 :            : 
    1128                 :          0 :         ret = output_funcs[mode](f, j, mode, n_columns, flags, fields, highlight);
    1129                 :            : 
    1130   [ #  #  #  # ]:          0 :         if (ellipsized && ret > 0)
    1131                 :          0 :                 *ellipsized = true;
    1132                 :            : 
    1133                 :          0 :         return ret;
    1134                 :            : }
    1135                 :            : 
    1136                 :          0 : static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
    1137         [ #  # ]:          0 :         assert(f);
    1138         [ #  # ]:          0 :         assert(flags);
    1139                 :            : 
    1140         [ #  # ]:          0 :         if (!(*flags & OUTPUT_BEGIN_NEWLINE))
    1141                 :          0 :                 return 0;
    1142                 :            : 
    1143                 :            :         /* Print a beginning new line if that's request, but only once
    1144                 :            :          * on the first line we print. */
    1145                 :            : 
    1146                 :          0 :         fputc('\n', f);
    1147                 :          0 :         *flags &= ~OUTPUT_BEGIN_NEWLINE;
    1148                 :          0 :         return 0;
    1149                 :            : }
    1150                 :            : 
    1151                 :          0 : int show_journal(
    1152                 :            :                 FILE *f,
    1153                 :            :                 sd_journal *j,
    1154                 :            :                 OutputMode mode,
    1155                 :            :                 unsigned n_columns,
    1156                 :            :                 usec_t not_before,
    1157                 :            :                 unsigned how_many,
    1158                 :            :                 OutputFlags flags,
    1159                 :            :                 bool *ellipsized) {
    1160                 :            : 
    1161                 :            :         int r;
    1162                 :          0 :         unsigned line = 0;
    1163                 :          0 :         bool need_seek = false;
    1164                 :          0 :         int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
    1165                 :            : 
    1166         [ #  # ]:          0 :         assert(j);
    1167         [ #  # ]:          0 :         assert(mode >= 0);
    1168         [ #  # ]:          0 :         assert(mode < _OUTPUT_MODE_MAX);
    1169                 :            : 
    1170         [ #  # ]:          0 :         if (how_many == (unsigned) -1)
    1171                 :          0 :                 need_seek = true;
    1172                 :            :         else {
    1173                 :            :                 /* Seek to end */
    1174                 :          0 :                 r = sd_journal_seek_tail(j);
    1175         [ #  # ]:          0 :                 if (r < 0)
    1176         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to seek to tail: %m");
    1177                 :            : 
    1178                 :          0 :                 r = sd_journal_previous_skip(j, how_many);
    1179         [ #  # ]:          0 :                 if (r < 0)
    1180         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to skip previous: %m");
    1181                 :            :         }
    1182                 :            : 
    1183                 :          0 :         for (;;) {
    1184                 :          0 :                 for (;;) {
    1185                 :            :                         usec_t usec;
    1186                 :            : 
    1187         [ #  # ]:          0 :                         if (need_seek) {
    1188                 :          0 :                                 r = sd_journal_next(j);
    1189         [ #  # ]:          0 :                                 if (r < 0)
    1190         [ #  # ]:          0 :                                         return log_error_errno(r, "Failed to iterate through journal: %m");
    1191                 :            :                         }
    1192                 :            : 
    1193         [ #  # ]:          0 :                         if (r == 0)
    1194                 :          0 :                                 break;
    1195                 :            : 
    1196                 :          0 :                         need_seek = true;
    1197                 :            : 
    1198         [ #  # ]:          0 :                         if (not_before > 0) {
    1199                 :          0 :                                 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
    1200                 :            : 
    1201                 :            :                                 /* -ESTALE is returned if the
    1202                 :            :                                    timestamp is not from this boot */
    1203         [ #  # ]:          0 :                                 if (r == -ESTALE)
    1204                 :          0 :                                         continue;
    1205         [ #  # ]:          0 :                                 else if (r < 0)
    1206         [ #  # ]:          0 :                                         return log_error_errno(r, "Failed to get journal time: %m");
    1207                 :            : 
    1208         [ #  # ]:          0 :                                 if (usec < not_before)
    1209                 :          0 :                                         continue;
    1210                 :            :                         }
    1211                 :            : 
    1212                 :          0 :                         line++;
    1213                 :          0 :                         maybe_print_begin_newline(f, &flags);
    1214                 :            : 
    1215                 :          0 :                         r = show_journal_entry(f, j, mode, n_columns, flags, NULL, NULL, ellipsized);
    1216         [ #  # ]:          0 :                         if (r < 0)
    1217                 :          0 :                                 return r;
    1218                 :            :                 }
    1219                 :            : 
    1220   [ #  #  #  #  :          0 :                 if (warn_cutoff && line < how_many && not_before > 0) {
                   #  # ]
    1221                 :            :                         sd_id128_t boot_id;
    1222                 :          0 :                         usec_t cutoff = 0;
    1223                 :            : 
    1224                 :            :                         /* Check whether the cutoff line is too early */
    1225                 :            : 
    1226                 :          0 :                         r = sd_id128_get_boot(&boot_id);
    1227         [ #  # ]:          0 :                         if (r < 0)
    1228         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to get boot id: %m");
    1229                 :            : 
    1230                 :          0 :                         r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
    1231         [ #  # ]:          0 :                         if (r < 0)
    1232         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to get journal cutoff time: %m");
    1233                 :            : 
    1234   [ #  #  #  # ]:          0 :                         if (r > 0 && not_before < cutoff) {
    1235                 :          0 :                                 maybe_print_begin_newline(f, &flags);
    1236                 :          0 :                                 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
    1237                 :            :                         }
    1238                 :            : 
    1239                 :          0 :                         warn_cutoff = false;
    1240                 :            :                 }
    1241                 :            : 
    1242         [ #  # ]:          0 :                 if (!(flags & OUTPUT_FOLLOW))
    1243                 :          0 :                         break;
    1244                 :            : 
    1245                 :          0 :                 r = sd_journal_wait(j, USEC_INFINITY);
    1246         [ #  # ]:          0 :                 if (r < 0)
    1247         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to wait for journal: %m");
    1248                 :            : 
    1249                 :            :         }
    1250                 :            : 
    1251                 :          0 :         return 0;
    1252                 :            : }
    1253                 :            : 
    1254                 :          0 : int add_matches_for_unit(sd_journal *j, const char *unit) {
    1255                 :            :         const char *m1, *m2, *m3, *m4;
    1256                 :            :         int r;
    1257                 :            : 
    1258         [ #  # ]:          0 :         assert(j);
    1259         [ #  # ]:          0 :         assert(unit);
    1260                 :            : 
    1261   [ #  #  #  #  :          0 :         m1 = strjoina("_SYSTEMD_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1262   [ #  #  #  #  :          0 :         m2 = strjoina("COREDUMP_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1263   [ #  #  #  #  :          0 :         m3 = strjoina("UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1264   [ #  #  #  #  :          0 :         m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1265                 :            : 
    1266         [ #  # ]:          0 :         (void)(
    1267                 :            :             /* Look for messages from the service itself */
    1268         [ #  # ]:          0 :             (r = sd_journal_add_match(j, m1, 0)) ||
    1269                 :            : 
    1270                 :            :             /* Look for coredumps of the service */
    1271         [ #  # ]:          0 :             (r = sd_journal_add_disjunction(j)) ||
    1272         [ #  # ]:          0 :             (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
    1273         [ #  # ]:          0 :             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
    1274         [ #  # ]:          0 :             (r = sd_journal_add_match(j, m2, 0)) ||
    1275                 :            : 
    1276                 :            :              /* Look for messages from PID 1 about this service */
    1277         [ #  # ]:          0 :             (r = sd_journal_add_disjunction(j)) ||
    1278         [ #  # ]:          0 :             (r = sd_journal_add_match(j, "_PID=1", 0)) ||
    1279         [ #  # ]:          0 :             (r = sd_journal_add_match(j, m3, 0)) ||
    1280                 :            : 
    1281                 :            :             /* Look for messages from authorized daemons about this service */
    1282         [ #  # ]:          0 :             (r = sd_journal_add_disjunction(j)) ||
    1283         [ #  # ]:          0 :             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
    1284                 :          0 :             (r = sd_journal_add_match(j, m4, 0))
    1285                 :            :         );
    1286                 :            : 
    1287   [ #  #  #  # ]:          0 :         if (r == 0 && endswith(unit, ".slice")) {
    1288                 :            :                 const char *m5;
    1289                 :            : 
    1290   [ #  #  #  #  :          0 :                 m5 = strjoina("_SYSTEMD_SLICE=", unit);
          #  #  #  #  #  
                #  #  # ]
    1291                 :            : 
    1292                 :            :                 /* Show all messages belonging to a slice */
    1293         [ #  # ]:          0 :                 (void)(
    1294         [ #  # ]:          0 :                         (r = sd_journal_add_disjunction(j)) ||
    1295                 :          0 :                         (r = sd_journal_add_match(j, m5, 0))
    1296                 :            :                         );
    1297                 :            :         }
    1298                 :            : 
    1299                 :          0 :         return r;
    1300                 :            : }
    1301                 :            : 
    1302                 :          0 : int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
    1303                 :            :         int r;
    1304                 :            :         char *m1, *m2, *m3, *m4;
    1305                 :            :         char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
    1306                 :            : 
    1307         [ #  # ]:          0 :         assert(j);
    1308         [ #  # ]:          0 :         assert(unit);
    1309                 :            : 
    1310   [ #  #  #  #  :          0 :         m1 = strjoina("_SYSTEMD_USER_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1311   [ #  #  #  #  :          0 :         m2 = strjoina("USER_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1312   [ #  #  #  #  :          0 :         m3 = strjoina("COREDUMP_USER_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1313   [ #  #  #  #  :          0 :         m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit);
          #  #  #  #  #  
                #  #  # ]
    1314                 :          0 :         sprintf(muid, "_UID="UID_FMT, uid);
    1315                 :            : 
    1316         [ #  # ]:          0 :         (void) (
    1317                 :            :                 /* Look for messages from the user service itself */
    1318         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, m1, 0)) ||
    1319         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, muid, 0)) ||
    1320                 :            : 
    1321                 :            :                 /* Look for messages from systemd about this service */
    1322         [ #  # ]:          0 :                 (r = sd_journal_add_disjunction(j)) ||
    1323         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, m2, 0)) ||
    1324         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, muid, 0)) ||
    1325                 :            : 
    1326                 :            :                 /* Look for coredumps of the service */
    1327         [ #  # ]:          0 :                 (r = sd_journal_add_disjunction(j)) ||
    1328         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, m3, 0)) ||
    1329         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, muid, 0)) ||
    1330         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
    1331                 :            : 
    1332                 :            :                 /* Look for messages from authorized daemons about this service */
    1333         [ #  # ]:          0 :                 (r = sd_journal_add_disjunction(j)) ||
    1334         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, m4, 0)) ||
    1335         [ #  # ]:          0 :                 (r = sd_journal_add_match(j, muid, 0)) ||
    1336                 :          0 :                 (r = sd_journal_add_match(j, "_UID=0", 0))
    1337                 :            :         );
    1338                 :            : 
    1339   [ #  #  #  # ]:          0 :         if (r == 0 && endswith(unit, ".slice")) {
    1340                 :            :                 const char *m5;
    1341                 :            : 
    1342   [ #  #  #  #  :          0 :                 m5 = strjoina("_SYSTEMD_SLICE=", unit);
          #  #  #  #  #  
                #  #  # ]
    1343                 :            : 
    1344                 :            :                 /* Show all messages belonging to a slice */
    1345         [ #  # ]:          0 :                 (void)(
    1346         [ #  # ]:          0 :                         (r = sd_journal_add_disjunction(j)) ||
    1347         [ #  # ]:          0 :                         (r = sd_journal_add_match(j, m5, 0)) ||
    1348                 :          0 :                         (r = sd_journal_add_match(j, muid, 0))
    1349                 :            :                         );
    1350                 :            :         }
    1351                 :            : 
    1352                 :          0 :         return r;
    1353                 :            : }
    1354                 :            : 
    1355                 :          0 : static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
    1356                 :          0 :         _cleanup_close_pair_ int pair[2] = { -1, -1 };
    1357                 :          0 :         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
    1358                 :            :         pid_t pid, child;
    1359                 :            :         char buf[37];
    1360                 :            :         ssize_t k;
    1361                 :            :         int r;
    1362                 :            : 
    1363         [ #  # ]:          0 :         assert(machine);
    1364         [ #  # ]:          0 :         assert(boot_id);
    1365                 :            : 
    1366         [ #  # ]:          0 :         if (!machine_name_is_valid(machine))
    1367                 :          0 :                 return -EINVAL;
    1368                 :            : 
    1369                 :          0 :         r = container_get_leader(machine, &pid);
    1370         [ #  # ]:          0 :         if (r < 0)
    1371                 :          0 :                 return r;
    1372                 :            : 
    1373                 :          0 :         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, NULL, &rootfd);
    1374         [ #  # ]:          0 :         if (r < 0)
    1375                 :          0 :                 return r;
    1376                 :            : 
    1377         [ #  # ]:          0 :         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
    1378                 :          0 :                 return -errno;
    1379                 :            : 
    1380                 :          0 :         r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
    1381                 :            :                            pidnsfd, mntnsfd, -1, -1, rootfd, &child);
    1382         [ #  # ]:          0 :         if (r < 0)
    1383                 :          0 :                 return r;
    1384         [ #  # ]:          0 :         if (r == 0) {
    1385                 :            :                 int fd;
    1386                 :            : 
    1387                 :          0 :                 pair[0] = safe_close(pair[0]);
    1388                 :            : 
    1389                 :          0 :                 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
    1390         [ #  # ]:          0 :                 if (fd < 0)
    1391                 :          0 :                         _exit(EXIT_FAILURE);
    1392                 :            : 
    1393                 :          0 :                 r = loop_read_exact(fd, buf, 36, false);
    1394                 :          0 :                 safe_close(fd);
    1395         [ #  # ]:          0 :                 if (r < 0)
    1396                 :          0 :                         _exit(EXIT_FAILURE);
    1397                 :            : 
    1398                 :          0 :                 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
    1399         [ #  # ]:          0 :                 if (k != 36)
    1400                 :          0 :                         _exit(EXIT_FAILURE);
    1401                 :            : 
    1402                 :          0 :                 _exit(EXIT_SUCCESS);
    1403                 :            :         }
    1404                 :            : 
    1405                 :          0 :         pair[1] = safe_close(pair[1]);
    1406                 :            : 
    1407                 :          0 :         r = wait_for_terminate_and_check("(sd-bootidns)", child, 0);
    1408         [ #  # ]:          0 :         if (r < 0)
    1409                 :          0 :                 return r;
    1410         [ #  # ]:          0 :         if (r != EXIT_SUCCESS)
    1411                 :          0 :                 return -EIO;
    1412                 :            : 
    1413                 :          0 :         k = recv(pair[0], buf, 36, 0);
    1414         [ #  # ]:          0 :         if (k != 36)
    1415                 :          0 :                 return -EIO;
    1416                 :            : 
    1417                 :          0 :         buf[36] = 0;
    1418                 :          0 :         r = sd_id128_from_string(buf, boot_id);
    1419         [ #  # ]:          0 :         if (r < 0)
    1420                 :          0 :                 return r;
    1421                 :            : 
    1422                 :          0 :         return 0;
    1423                 :            : }
    1424                 :            : 
    1425                 :          0 : int add_match_this_boot(sd_journal *j, const char *machine) {
    1426                 :          0 :         char match[9+32+1] = "_BOOT_ID=";
    1427                 :            :         sd_id128_t boot_id;
    1428                 :            :         int r;
    1429                 :            : 
    1430         [ #  # ]:          0 :         assert(j);
    1431                 :            : 
    1432         [ #  # ]:          0 :         if (machine) {
    1433                 :          0 :                 r = get_boot_id_for_machine(machine, &boot_id);
    1434         [ #  # ]:          0 :                 if (r < 0)
    1435         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
    1436                 :            :         } else {
    1437                 :          0 :                 r = sd_id128_get_boot(&boot_id);
    1438         [ #  # ]:          0 :                 if (r < 0)
    1439         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to get boot id: %m");
    1440                 :            :         }
    1441                 :            : 
    1442                 :          0 :         sd_id128_to_string(boot_id, match + 9);
    1443                 :          0 :         r = sd_journal_add_match(j, match, strlen(match));
    1444         [ #  # ]:          0 :         if (r < 0)
    1445         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add match: %m");
    1446                 :            : 
    1447                 :          0 :         r = sd_journal_add_conjunction(j);
    1448         [ #  # ]:          0 :         if (r < 0)
    1449         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add conjunction: %m");
    1450                 :            : 
    1451                 :          0 :         return 0;
    1452                 :            : }
    1453                 :            : 
    1454                 :          0 : int show_journal_by_unit(
    1455                 :            :                 FILE *f,
    1456                 :            :                 const char *unit,
    1457                 :            :                 OutputMode mode,
    1458                 :            :                 unsigned n_columns,
    1459                 :            :                 usec_t not_before,
    1460                 :            :                 unsigned how_many,
    1461                 :            :                 uid_t uid,
    1462                 :            :                 OutputFlags flags,
    1463                 :            :                 int journal_open_flags,
    1464                 :            :                 bool system_unit,
    1465                 :            :                 bool *ellipsized) {
    1466                 :            : 
    1467                 :          0 :         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
    1468                 :            :         int r;
    1469                 :            : 
    1470         [ #  # ]:          0 :         assert(mode >= 0);
    1471         [ #  # ]:          0 :         assert(mode < _OUTPUT_MODE_MAX);
    1472         [ #  # ]:          0 :         assert(unit);
    1473                 :            : 
    1474         [ #  # ]:          0 :         if (how_many <= 0)
    1475                 :          0 :                 return 0;
    1476                 :            : 
    1477                 :          0 :         r = sd_journal_open(&j, journal_open_flags);
    1478         [ #  # ]:          0 :         if (r < 0)
    1479         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to open journal: %m");
    1480                 :            : 
    1481                 :          0 :         r = add_match_this_boot(j, NULL);
    1482         [ #  # ]:          0 :         if (r < 0)
    1483                 :          0 :                 return r;
    1484                 :            : 
    1485         [ #  # ]:          0 :         if (system_unit)
    1486                 :          0 :                 r = add_matches_for_unit(j, unit);
    1487                 :            :         else
    1488                 :          0 :                 r = add_matches_for_user_unit(j, unit, uid);
    1489         [ #  # ]:          0 :         if (r < 0)
    1490         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add unit matches: %m");
    1491                 :            : 
    1492         [ #  # ]:          0 :         if (DEBUG_LOGGING) {
    1493         [ #  # ]:          0 :                 _cleanup_free_ char *filter;
    1494                 :            : 
    1495                 :          0 :                 filter = journal_make_match_string(j);
    1496         [ #  # ]:          0 :                 if (!filter)
    1497                 :          0 :                         return log_oom();
    1498                 :            : 
    1499         [ #  # ]:          0 :                 log_debug("Journal filter: %s", filter);
    1500                 :            :         }
    1501                 :            : 
    1502                 :          0 :         return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
    1503                 :            : }

Generated by: LCOV version 1.14