From 9e9fbaa620920c2422056d5eecd43cde0590e4ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Sep 2025 09:29:27 +0200 Subject: [PATCH 1/2] format-table: add TABLE_VERSION cell type This is exactly like TABLE_STRING, with one exception: it sorts via strverscmp_improved(). --- src/shared/format-table.c | 11 +++++++++-- src/shared/format-table.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index c672be326d..c129f260e8 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -287,6 +287,7 @@ static size_t table_data_size(TableDataType type, const void *data) { case TABLE_PATH_BASENAME: case TABLE_FIELD: case TABLE_HEADER: + case TABLE_VERSION: return strlen(data) + 1; case TABLE_STRV: @@ -526,7 +527,7 @@ int table_add_cell_stringf_full(Table *t, TableCell **ret_cell, TableDataType dt int r; assert(t); - assert(IN_SET(dt, TABLE_STRING, TABLE_PATH, TABLE_PATH_BASENAME, TABLE_FIELD, TABLE_HEADER)); + assert(IN_SET(dt, TABLE_STRING, TABLE_PATH, TABLE_PATH_BASENAME, TABLE_FIELD, TABLE_HEADER, TABLE_VERSION)); va_start(ap, format); r = vasprintf(&buffer, format, ap); @@ -934,6 +935,7 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) { case TABLE_PATH_BASENAME: case TABLE_FIELD: case TABLE_HEADER: + case TABLE_VERSION: data = va_arg(ap, const char *); break; @@ -1395,6 +1397,9 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t case TABLE_PATH_BASENAME: return path_compare(a->string, b->string); + case TABLE_VERSION: + return strverscmp_improved(a->string, b->string); + case TABLE_STRV: case TABLE_STRV_WRAPPED: return strv_compare(a->strv, b->strv); @@ -1579,7 +1584,8 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas case TABLE_PATH: case TABLE_PATH_BASENAME: case TABLE_FIELD: - case TABLE_HEADER: { + case TABLE_HEADER: + case TABLE_VERSION: { _cleanup_free_ char *bn = NULL; const char *s; @@ -2753,6 +2759,7 @@ static int table_data_to_json(TableData *d, sd_json_variant **ret) { case TABLE_PATH_BASENAME: case TABLE_FIELD: case TABLE_HEADER: + case TABLE_VERSION: return sd_json_variant_new_string(ret, d->string); case TABLE_STRV: diff --git a/src/shared/format-table.h b/src/shared/format-table.h index beea0cbe1b..3365a8feb7 100644 --- a/src/shared/format-table.h +++ b/src/shared/format-table.h @@ -16,6 +16,7 @@ typedef enum TableDataType { TABLE_STRV_WRAPPED, TABLE_PATH, TABLE_PATH_BASENAME, /* like TABLE_PATH, but display only last path element (i.e. the "basename") in regular output */ + TABLE_VERSION, /* just like TABLE_STRING, but uses version comparison when sorting */ TABLE_BOOLEAN, TABLE_BOOLEAN_CHECKMARK, TABLE_TIMESTAMP, From 435bef5d05b375d437b55975d00a4e9580d4bfe6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Sep 2025 09:30:57 +0200 Subject: [PATCH 2/2] kernel-install: when listing kernels sort them by version --- src/kernel-install/kernel-install.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c index a2faa0f850..c9ea1f1574 100644 --- a/src/kernel-install/kernel-install.c +++ b/src/kernel-install/kernel-install.c @@ -1368,7 +1368,7 @@ static int verb_inspect(int argc, char *argv[], void *userdata) { TABLE_FIELD, "Entry Directory", TABLE_STRING, c->entry_dir, TABLE_FIELD, "Kernel Version", - TABLE_STRING, c->version, + TABLE_VERSION, c->version, TABLE_FIELD, "Kernel", TABLE_STRING, c->kernel, TABLE_FIELD, "Initrds", @@ -1430,6 +1430,7 @@ static int verb_list(int argc, char *argv[], void *userdata) { table_set_ersatz_string(table, TABLE_ERSATZ_DASH); table_set_align_percent(table, table_get_cell(table, 0, 1), 100); + (void) table_set_sort(table, (size_t) 0); FOREACH_ARRAY(d, de->entries, de->n_entries) { _cleanup_free_ char *j = path_join("/usr/lib/modules/", (*d)->d_name); @@ -1460,7 +1461,7 @@ static int verb_list(int argc, char *argv[], void *userdata) { exists = true; r = table_add_many(table, - TABLE_STRING, (*d)->d_name, + TABLE_VERSION, (*d)->d_name, TABLE_BOOLEAN_CHECKMARK, exists, TABLE_SET_COLOR, ansi_highlight_green_red(exists), TABLE_PATH, j);