diff --git a/src/basic/macro.h b/src/basic/macro.h index aa04039e80..9e62f9c71c 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -319,13 +319,13 @@ static inline int __coverity_check_and_return__(int condition) { sizeof(type) <= 4 ? 10U : \ sizeof(type) <= 8 ? 20U : sizeof(int[-2*(sizeof(type) > 8)]))) -#define DECIMAL_STR_WIDTH(x) \ - ({ \ - typeof(x) _x_ = (x); \ - size_t ans = 1; \ - while ((_x_ /= 10) != 0) \ - ans++; \ - ans; \ +#define DECIMAL_STR_WIDTH(x) \ + ({ \ + typeof(x) _x_ = (x); \ + size_t ans = IS_SIGNED_INTEGER_TYPE(_x_) ? 2 : 1; \ + while ((_x_ /= 10) != 0) \ + ans++; \ + ans; \ }) #define SWAP_TWO(x, y) do { \ diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 3c4a7c0a7a..4e3d17678e 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; diff --git a/src/test/test-format-table.c b/src/test/test-format-table.c index 1b4963d928..60d5fee71f 100644 --- a/src/test/test-format-table.c +++ b/src/test/test-format-table.c @@ -396,28 +396,30 @@ TEST(table) { _cleanup_(table_unrefp) Table *t = NULL; _cleanup_free_ char *formatted = NULL; - assert_se(t = table_new("one", "two", "three")); + assert_se(t = table_new("one", "two", "three", "four")); - assert_se(table_set_align_percent(t, TABLE_HEADER_CELL(2), 100) >= 0); + assert_se(table_set_align_percent(t, TABLE_HEADER_CELL(3), 100) >= 0); assert_se(table_add_many(t, TABLE_STRING, "xxx", TABLE_STRING, "yyy", - TABLE_BOOLEAN, true) >= 0); + TABLE_BOOLEAN, true, + TABLE_INT, -1) >= 0); assert_se(table_add_many(t, TABLE_STRING, "a long field", TABLE_STRING, "yyy", TABLE_SET_UPPERCASE, 1, - TABLE_BOOLEAN, false) >= 0); + TABLE_BOOLEAN, false, + TABLE_INT, -999999) >= 0); assert_se(table_format(t, &formatted) >= 0); printf("%s\n", formatted); assert_se(streq(formatted, - "ONE TWO THREE\n" - "xxx yyy yes\n" - "a long field YYY no\n")); + "ONE TWO THREE FOUR\n" + "xxx yyy yes -1\n" + "a long field YYY no -999999\n")); formatted = mfree(formatted); @@ -427,20 +429,20 @@ TEST(table) { printf("%s\n", formatted); assert_se(streq(formatted, - "ONE TWO THREE\n" - "xxx yyy yes\n" - "a long field YYY no\n")); + "ONE TWO THREE FOUR\n" + "xxx yyy yes -1\n" + "a long field YYY no -999999\n")); formatted = mfree(formatted); - table_set_width(t, 12); + table_set_width(t, 15); assert_se(table_format(t, &formatted) >= 0); printf("%s\n", formatted); assert_se(streq(formatted, - "ONE TWO THR…\n" - "xxx yyy yes\n" - "a … YYY no\n")); + "ONE TWO TH… FO…\n" + "xxx yyy yes -1\n" + "a … YYY no -9…\n")); formatted = mfree(formatted); @@ -449,9 +451,9 @@ TEST(table) { printf("%s\n", formatted); assert_se(streq(formatted, - "… … …\n" - "… … …\n" - "… … …\n")); + "… … … …\n" + "… … … …\n" + "… … … …\n")); formatted = mfree(formatted); @@ -460,9 +462,9 @@ TEST(table) { printf("%s\n", formatted); assert_se(streq(formatted, - "… … …\n" - "… … …\n" - "… … …\n")); + "… … … …\n" + "… … … …\n" + "… … … …\n")); formatted = mfree(formatted); @@ -473,9 +475,9 @@ TEST(table) { printf("%s\n", formatted); assert_se(streq(formatted, - "ONE TWO THREE\n" - "a long field YYY no\n" - "xxx yyy yes\n")); + "ONE TWO THREE FOUR\n" + "a long field YYY no -999999\n" + "xxx yyy yes -1\n")); formatted = mfree(formatted); @@ -484,27 +486,30 @@ TEST(table) { assert_se(table_add_many(t, TABLE_STRING, "fäää", TABLE_STRING, "uuu", - TABLE_BOOLEAN, true) >= 0); + TABLE_BOOLEAN, true, + TABLE_INT, 42) >= 0); assert_se(table_add_many(t, TABLE_STRING, "fäää", TABLE_STRING, "zzz", - TABLE_BOOLEAN, false) >= 0); + TABLE_BOOLEAN, false, + TABLE_INT, 0) >= 0); assert_se(table_add_many(t, TABLE_EMPTY, TABLE_SIZE, (uint64_t) 4711, - TABLE_TIMESPAN, (usec_t) 5*USEC_PER_MINUTE) >= 0); + TABLE_TIMESPAN, (usec_t) 5*USEC_PER_MINUTE, + TABLE_INT64, (uint64_t) -123456789) >= 0); assert_se(table_format(t, &formatted) >= 0); printf("%s\n", formatted); assert_se(streq(formatted, - "a long field YYY no\n" - "fäää zzz no\n" - "fäää uuu yes\n" - "xxx yyy yes\n" - " 4.6K 5min\n")); + "a long field YYY no -999999\n" + "fäää zzz no 0\n" + "fäää uuu yes 42\n" + "xxx yyy yes -1\n" + " 4.6K 5min -123456789\n")); formatted = mfree(formatted); @@ -515,17 +520,17 @@ TEST(table) { if (isatty(STDOUT_FILENO)) assert_se(streq(formatted, - " no a long f… no a long f… a long fi…\n" - " no fäää no fäää fäää\n" - " yes fäää yes fäää fäää\n" - " yes xxx yes xxx xxx\n" + "no a long f… no a long f… a long fi…\n" + "no fäää no fäää fäää\n" + "yes fäää yes fäää fäää\n" + "yes xxx yes xxx xxx\n" "5min 5min \n")); else assert_se(streq(formatted, - " no a long field no a long field a long field\n" - " no fäää no fäää fäää\n" - " yes fäää yes fäää fäää\n" - " yes xxx yes xxx xxx\n" + "no a long field no a long field a long field\n" + "no fäää no fäää fäää\n" + "yes fäää yes fäää fäää\n" + "yes xxx yes xxx xxx\n" "5min 5min \n")); }