From 5a1355d848a0f6564a04c6d8268e72bc93d173de Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Sat, 12 Mar 2022 20:37:16 +0100
Subject: [PATCH] journal: convert --list-boots to a table

so it can be output as JSON as well.

```
$ build-san/journalctl --list-boots --file boot-test.journal
IDX BOOT ID                          FIRST ENTRY                 LAST ENTRY
 -3 39d66eb1925f4d01b8464d502650a714 Sat 2022-03-05 15:20:33 CET Sat 2022-03-05 16:19:21 CET
 -2 5dffeb08a27344d5ae9e2fc244bbcbc5 Fri 2022-03-11 17:23:57 CET Fri 2022-03-11 17:38:31 CET
 -1 c8ebd52915b642c39eda4bf00f864f79 Fri 2022-03-11 17:38:41 CET Fri 2022-03-11 20:03:46 CET
  0 00bcba97c7094fa88cc5d1cf2a389057 Sat 2022-03-12 20:39:08 CET Sat 2022-03-12 20:40:18 CET

$ build-san/journalctl --list-boots --file boot-test.journal -q
-3 39d66eb1925f4d01b8464d502650a714 Sat 2022-03-05 15:20:33 CET Sat 2022-03-05 16:19:21 CET
-2 5dffeb08a27344d5ae9e2fc244bbcbc5 Fri 2022-03-11 17:23:57 CET Fri 2022-03-11 17:38:31 CET
-1 c8ebd52915b642c39eda4bf00f864f79 Fri 2022-03-11 17:38:41 CET Fri 2022-03-11 20:03:46 CET
 0 00bcba97c7094fa88cc5d1cf2a389057 Sat 2022-03-12 20:39:08 CET Sat 2022-03-12 20:40:18 CET

$ build-san/journalctl --list-boots --file boot-test.journal -o json-pretty
[
        {
                "index" : -3,
                "boot_id" : "39d66eb1925f4d01b8464d502650a714",
                "first_entry" : 1646490033438495,
                "last_entry" : 1646493561047353
        },
        {
                "index" : -2,
                "boot_id" : "5dffeb08a27344d5ae9e2fc244bbcbc5",
                "first_entry" : 1647015837289036,
                "last_entry" : 1647016711595489
        },
        {
                "index" : -1,
                "boot_id" : "c8ebd52915b642c39eda4bf00f864f79",
                "first_entry" : 1647016721056382,
                "last_entry" : 1647025426397414
        },
        {
                "index" : 0,
                "boot_id" : "00bcba97c7094fa88cc5d1cf2a389057",
                "first_entry" : 1647113948506002,
                "last_entry" : 1647114018943637
        }
]
```

Resolves: #14625
---
 src/journal/journalctl.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 3c4a7c0a7a5..4e3d17678e0 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -33,6 +33,7 @@
 #include "dissect-image.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "format-table.h"
 #include "format-util.h"
 #include "fs-util.h"
 #include "fsprg.h"
@@ -84,6 +85,7 @@ enum {
 };
 
 static OutputMode arg_output = OUTPUT_SHORT;
+static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static bool arg_utc = false;
 static bool arg_follow = false;
 static bool arg_full = true;
@@ -577,6 +579,8 @@ static int parse_argv(int argc, char *argv[]) {
                         if (IN_SET(arg_output, OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_JSON_SEQ, OUTPUT_CAT))
                                 arg_quiet = true;
 
+                        if (OUTPUT_MODE_IS_JSON(arg_output))
+                                arg_json_format_flags = output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO;
                         break;
 
                 case 'l':
@@ -1441,8 +1445,9 @@ finish:
 }
 
 static int list_boots(sd_journal *j) {
-        int w, i, count;
+        _cleanup_(table_unrefp) Table *table = NULL;
         BootId *id, *all_ids;
+        int count, i, r;
 
         assert(j);
 
@@ -1452,23 +1457,30 @@ static int list_boots(sd_journal *j) {
         if (count == 0)
                 return count;
 
-        pager_open(arg_pager_flags);
+        table = table_new(OUTPUT_MODE_IS_JSON(arg_output) ? "index" : "idx", "boot id", "first entry", "last entry");
+        if (!table)
+                return log_oom();
 
-        /* numbers are one less, but we need an extra char for the sign */
-        w = DECIMAL_STR_WIDTH(count - 1) + 1;
+        if (arg_full)
+                table_set_width(table, 0);
 
         i = 0;
         LIST_FOREACH(boot_list, id, all_ids) {
-                char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
-
-                printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
-                       w, i - count + 1,
-                       SD_ID128_FORMAT_VAL(id->id),
-                       format_timestamp_maybe_utc(a, sizeof(a), id->first),
-                       format_timestamp_maybe_utc(b, sizeof(b), id->last));
+                r = table_add_many(table,
+                                   TABLE_INT, i - count + 1,
+                                   TABLE_SET_ALIGN_PERCENT, 100,
+                                   TABLE_ID128, id->id,
+                                   TABLE_TIMESTAMP, id->first,
+                                   TABLE_TIMESTAMP, id->last);
+                if (r < 0)
+                        return table_log_add_error(r);
                 i++;
         }
 
+        r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet);
+        if (r < 0)
+                return table_log_print_error(r);
+
         boot_id_free_all(all_ids);
 
         return 0;