diff options
| -rw-r--r-- | .github/workflows/codeql.yml | 4 | ||||
| -rw-r--r-- | include/c.h | 1 | ||||
| -rw-r--r-- | libblkid/src/superblocks/bcache.c | 9 | ||||
| -rw-r--r-- | libblkid/src/superblocks/superblocks.c | 6 | ||||
| -rw-r--r-- | libmount/src/context_mount.c | 6 | ||||
| -rw-r--r-- | misc-utils/lsclocks.1.adoc | 9 | ||||
| -rw-r--r-- | misc-utils/lsclocks.c | 331 | ||||
| -rw-r--r-- | misc-utils/lsfd.1.adoc | 5 | ||||
| -rw-r--r-- | misc-utils/lsfd.c | 78 | ||||
| -rw-r--r-- | tests/expected/blkid/low-probe-bcachefs | 2 | ||||
| -rw-r--r-- | tests/expected/blkid/low-probe-bcachefs-2 | 2 | ||||
| -rw-r--r-- | tests/expected/misc/lsclocks-basic | 20 | ||||
| -rw-r--r-- | tests/expected/misc/lsclocks-dynamic | 1 | ||||
| -rwxr-xr-x | tests/ts/misc/lsclocks | 12 |
14 files changed, 331 insertions, 155 deletions
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 671e569daf..b7d98a0de7 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,6 +39,10 @@ jobs: with: languages: ${{ matrix.language }} queries: +security-extended,security-and-quality + config: | + query-filters: + - exclude: + id: cpp/path-injection - name: Install dependencies run: sudo -E .github/workflows/cibuild-setup-ubuntu.sh diff --git a/include/c.h b/include/c.h index f9f90f3bbe..752f568c50 100644 --- a/include/c.h +++ b/include/c.h @@ -452,6 +452,7 @@ static inline void __attribute__((__noreturn__)) ul_sig_err(int excode, const ch #define USAGE_COMMANDS _("\nCommands:\n") #define USAGE_ARGUMENTS _("\nArguments:\n") #define USAGE_COLUMNS _("\nAvailable output columns:\n") +#define USAGE_DEFAULT_COLUMNS _("\nDefault columns:\n") #define USAGE_SEPARATOR "\n" #define USAGE_OPTSTR_HELP _("display this help") diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c index bf7fed01fe..1a0c124d37 100644 --- a/libblkid/src/superblocks/bcache.c +++ b/libblkid/src/superblocks/bcache.c @@ -149,6 +149,9 @@ struct bcachefs_super_block { #define BCACHEFS_SB_FIELDS_OFF offsetof(struct bcachefs_super_block, _start) /* tag value for members field */ #define BCACHEFS_SB_FIELD_TYPE_MEMBERS 1 +/* version splitting helpers */ +#define BCH_VERSION_MAJOR(_v) ((uint16_t) ((_v) >> 10)) +#define BCH_VERSION_MINOR(_v) ((uint16_t) ((_v) & ~(~0U << 10))) #define BYTES(f) ((((uint64_t) le32_to_cpu((f)->u64s)) * 8)) @@ -300,6 +303,7 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag) struct bcachefs_super_block *bcs; const unsigned char *sb, *sb_end; uint64_t sb_size, blocksize; + uint16_t version; bcs = blkid_probe_get_sb(pr, mag, struct bcachefs_super_block); if (!bcs) @@ -325,7 +329,10 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag) blkid_probe_set_uuid(pr, bcs->user_uuid); blkid_probe_set_label(pr, bcs->label, sizeof(bcs->label)); - blkid_probe_sprintf_version(pr, "%d", le16_to_cpu(bcs->version)); + version = le16_to_cpu(bcs->version); + blkid_probe_sprintf_version(pr, "%"PRIu16".%"PRIu16, + BCH_VERSION_MAJOR(version), + BCH_VERSION_MINOR(version)); blocksize = le16_to_cpu(bcs->block_size); blkid_probe_set_block_size(pr, blocksize * BCACHEFS_SECTOR_SIZE); blkid_probe_set_fsblocksize(pr, blocksize * BCACHEFS_SECTOR_SIZE); diff --git a/libblkid/src/superblocks/superblocks.c b/libblkid/src/superblocks/superblocks.c index fb03927078..c7789a15be 100644 --- a/libblkid/src/superblocks/superblocks.c +++ b/libblkid/src/superblocks/superblocks.c @@ -94,11 +94,6 @@ static int blkid_probe_set_usage(blkid_probe pr, int usage); */ static const struct blkid_idinfo *idinfos[] = { - /* In case the volume is locked with OPAL we are going to get - * an I/O error when reading past the LUKS header, so try it - * first. */ - &luks_idinfo, - /* RAIDs */ &linuxraid_idinfo, &ddfraid_idinfo, @@ -124,6 +119,7 @@ static const struct blkid_idinfo *idinfos[] = &snapcow_idinfo, &verity_hash_idinfo, &integrity_idinfo, + &luks_idinfo, &vmfs_volume_idinfo, &ubi_idinfo, &vdo_idinfo, diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 87387ae366..05c84f1702 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -1517,6 +1517,12 @@ int mnt_context_get_mount_excode( * mount(2) syscall success, but something else failed * (probably error in utab processing). */ + if (rc == -MNT_ERR_APPLYFLAGS) { + if (buf) + snprintf(buf, bufsz, _("filesystem was mounted, but failed to apply flags")); + return MNT_EX_USAGE; + } + if (rc == -MNT_ERR_LOCK) { if (buf) snprintf(buf, bufsz, _("filesystem was mounted, but failed to update userspace mount table")); diff --git a/misc-utils/lsclocks.1.adoc b/misc-utils/lsclocks.1.adoc index 4024c93e4b..90497fba52 100644 --- a/misc-utils/lsclocks.1.adoc +++ b/misc-utils/lsclocks.1.adoc @@ -42,12 +42,21 @@ Use raw output format. *-r*, *--time* _clock_ Show current time of one specific clocks. +*--no-discover-dynamic* +Do not try to discover dynamic clocks. + +*-d*, *--dynamic-clock* _path_ +Also display specified dynamic clock. + include::man-common/help-version.adoc[] == OUTPUT COLUMNS Each column has a type. Types are surround by < and >. +TYPE <``string``>:: +Clock type. + ID <``number``>:: Numeric clock ID. diff --git a/misc-utils/lsclocks.c b/misc-utils/lsclocks.c index dd6fedda71..ec27b9a155 100644 --- a/misc-utils/lsclocks.c +++ b/misc-utils/lsclocks.c @@ -23,6 +23,7 @@ #include <time.h> #include <inttypes.h> #include <getopt.h> +#include <glob.h> #include <libsmartcols.h> @@ -34,9 +35,24 @@ #include "xalloc.h" #include "pathnames.h" #include "all-io.h" +#include "list.h" #define CLOCKFD 3 -#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) + +static inline clockid_t FD_TO_CLOCKID(int fd) +{ + return (~(unsigned int) fd << 3) | CLOCKFD; +} + +static inline int CLOCKID_TO_FD(clockid_t clk) +{ + return ~(clk >> 3); +} + +static inline bool CLOCKID_IS_DYNAMIC(clockid_t clk) +{ + return CLOCKID_TO_FD(clk) <= 0; +} #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 @@ -74,7 +90,24 @@ #define CLOCK_TAI 11 #endif +enum CLOCK_TYPE { + CT_SYS, + CT_PTP, +}; + +static const char *clock_type_name(enum CLOCK_TYPE type) +{ + switch (type) { + case CT_SYS: + return "sys"; + case CT_PTP: + return "ptp"; + } + errx(EXIT_FAILURE, _("Unknown clock type %d"), type); +} + struct clockinfo { + enum CLOCK_TYPE type; clockid_t id; const char * const id_name; const char * const name; @@ -82,21 +115,22 @@ struct clockinfo { }; static const struct clockinfo clocks[] = { - { CLOCK_REALTIME, "CLOCK_REALTIME", "realtime" }, - { CLOCK_MONOTONIC, "CLOCK_MONOTONIC", "monotonic", - .ns_offset_name = "monotonic" }, - { CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW", "monotonic-raw" }, - { CLOCK_REALTIME_COARSE, "CLOCK_REALTIME_COARSE", "realtime-coarse" }, - { CLOCK_MONOTONIC_COARSE, "CLOCK_MONOTONIC_COARSE", "monotonic-coarse" }, - { CLOCK_BOOTTIME, "CLOCK_BOOTTIME", "boottime", - .ns_offset_name = "boottime" }, - { CLOCK_REALTIME_ALARM, "CLOCK_REALTIME_ALARM", "realtime-alarm" }, - { CLOCK_BOOTTIME_ALARM, "CLOCK_BOOTTIME_ALARM", "boottime-alarm" }, - { CLOCK_TAI, "CLOCK_TAI", "tai" }, + { CT_SYS, CLOCK_REALTIME, "CLOCK_REALTIME", "realtime" }, + { CT_SYS, CLOCK_MONOTONIC, "CLOCK_MONOTONIC", "monotonic", + .ns_offset_name = "monotonic" }, + { CT_SYS, CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW", "monotonic-raw" }, + { CT_SYS, CLOCK_REALTIME_COARSE, "CLOCK_REALTIME_COARSE", "realtime-coarse" }, + { CT_SYS, CLOCK_MONOTONIC_COARSE, "CLOCK_MONOTONIC_COARSE", "monotonic-coarse" }, + { CT_SYS, CLOCK_BOOTTIME, "CLOCK_BOOTTIME", "boottime", + .ns_offset_name = "boottime" }, + { CT_SYS, CLOCK_REALTIME_ALARM, "CLOCK_REALTIME_ALARM", "realtime-alarm" }, + { CT_SYS, CLOCK_BOOTTIME_ALARM, "CLOCK_BOOTTIME_ALARM", "boottime-alarm" }, + { CT_SYS, CLOCK_TAI, "CLOCK_TAI", "tai" }, }; /* column IDs */ enum { + COL_TYPE, COL_ID, COL_CLOCK, COL_NAME, @@ -119,6 +153,7 @@ struct colinfo { /* columns descriptions */ static const struct colinfo infos[] = { + [COL_TYPE] = { "TYPE", 1, 0, SCOLS_JSON_STRING, N_("type") }, [COL_ID] = { "ID", 1, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, N_("numeric id") }, [COL_CLOCK] = { "CLOCK", 1, 0, SCOLS_JSON_STRING, N_("symbolic name") }, [COL_NAME] = { "NAME", 1, 0, SCOLS_JSON_STRING, N_("readable name") }, @@ -154,15 +189,17 @@ static void __attribute__((__noreturn__)) usage(void) fprintf(out, _(" %s [options]\n"), program_invocation_short_name); fputs(USAGE_OPTIONS, out); - fputs(_(" -J, --json use JSON output format\n"), out); - fputs(_(" -n, --noheadings don't print headings\n"), out); - fputs(_(" -o, --output <list> output columns\n"), out); - fputs(_(" --output-all output all columns\n"), out); - fputs(_(" -r, --raw use raw output format\n"), out); - fputs(_(" -t, --time <clock> show current time of single clock\n"), out); + fputs(_(" -J, --json use JSON output format\n"), out); + fputs(_(" -n, --noheadings don't print headings\n"), out); + fputs(_(" -o, --output <list> output columns\n"), out); + fputs(_(" --output-all output all columns\n"), out); + fputs(_(" -r, --raw use raw output format\n"), out); + fputs(_(" -t, --time <clock> show current time of single clock\n"), out); + fputs(_(" --no-discover-dynamic do not try to discover dynamic clocks\n"), out); + fputs(_(" -d, --dynamic-clock <path> also display specified dynamic clock\n"), out); fputs(USAGE_SEPARATOR, out); - printf(USAGE_HELP_OPTIONS(25)); + printf(USAGE_HELP_OPTIONS(29)); fprintf(out, USAGE_COLUMNS); @@ -249,38 +286,171 @@ static int64_t get_namespace_offset(const char *name) return ret; } +static void add_clock_line(struct libscols_table *tb, const int *columns, + size_t ncolumns, const struct clockinfo *clockinfo) +{ + struct timespec resolution, now; + char buf[FORMAT_TIMESTAMP_MAX]; + struct libscols_line *ln; + size_t i; + int rc; + + ln = scols_table_new_line(tb, NULL); + if (!ln) + errx(EXIT_FAILURE, _("failed to allocate output line")); + + /* outside the loop to guarantee consistency between COL_TIME and COL_ISO_TIME */ + rc = clock_gettime(clockinfo->id, &now); + if (rc) + now.tv_nsec = -1; + + rc = clock_getres(clockinfo->id, &resolution); + if (rc) + resolution.tv_nsec = -1; + + for (i = 0; i < ncolumns; i++) { + switch (columns[i]) { + case COL_TYPE: + scols_line_set_data(ln, i, clock_type_name(clockinfo->type)); + break; + case COL_ID: + if (CLOCKID_IS_DYNAMIC(clockinfo->id)) + scols_line_asprintf(ln, i, "%ju", (uintmax_t) clockinfo->id); + break; + case COL_CLOCK: + scols_line_set_data(ln, i, clockinfo->id_name); + break; + case COL_NAME: + scols_line_set_data(ln, i, clockinfo->name); + break; + case COL_TIME: + if (now.tv_nsec == -1) + break; + + scols_line_format_timespec(ln, i, &now); + break; + case COL_ISO_TIME: + if (now.tv_nsec == -1) + break; + + rc = strtimespec_iso(&now, + ISO_GMTIME | ISO_DATE | ISO_TIME | ISO_T | ISO_DOTNSEC | ISO_TIMEZONE, + buf, sizeof(buf)); + if (rc) + errx(EXIT_FAILURE, _("failed to format iso time")); + scols_line_set_data(ln, i, buf); + break; + case COL_RESOL: + if (resolution.tv_nsec == -1) + break; + + rc = strtimespec_relative(&resolution, buf, sizeof(buf)); + if (rc) + errx(EXIT_FAILURE, _("failed to format relative time")); + scols_line_set_data(ln, i, buf); + break; + case COL_RESOL_RAW: + if (resolution.tv_nsec == -1) + break; + scols_line_format_timespec(ln, i, &resolution); + break; + case COL_REL_TIME: + if (now.tv_nsec == -1) + break; + rc = strtimespec_relative(&now, buf, sizeof(buf)); + if (rc) + errx(EXIT_FAILURE, _("failed to format relative time")); + scols_line_set_data(ln, i, buf); + break; + case COL_NS_OFFSET: + if (clockinfo->ns_offset_name) + scols_line_asprintf(ln, i, "%"PRId64, + get_namespace_offset(clockinfo->ns_offset_name)); + break; + } + } +} + +struct dynamic_clock { + struct list_head head; + const char * path; +}; + +static void add_dynamic_clock_from_path(struct libscols_table *tb, + const int *columns, size_t ncolumns, + const char *path, bool explicit) +{ + int fd = open(path, O_RDONLY); + if (fd == -1) { + if (explicit) + err(EXIT_FAILURE, _("Could not open %s"), path); + else + return; + } + + struct clockinfo clockinfo = { + .type = CT_PTP, + .id = FD_TO_CLOCKID(fd), + .id_name = path, + .name = path, + }; + add_clock_line(tb, columns, ncolumns, &clockinfo); + close(fd); +} + +static void add_dynamic_clocks_from_discovery(struct libscols_table *tb, + const int *columns, size_t ncolumns) +{ + int rc; + size_t i; + glob_t state; + + rc = glob("/dev/ptp*", 0, NULL, &state); + if (rc) + errx(EXIT_FAILURE, _("Could not glob: %d"), rc); + + for (i = 0; i < state.gl_pathc; i++) + add_dynamic_clock_from_path(tb, columns, ncolumns, + state.gl_pathv[i], false); + + globfree(&state); +} + int main(int argc, char **argv) { - size_t i, j; + size_t i; int c, rc; const struct colinfo *colinfo; - const struct clockinfo *clockinfo; struct libscols_table *tb; - struct libscols_line *ln; struct libscols_column *col; - bool noheadings = false, raw = false, json = false; + bool noheadings = false, raw = false, json = false, disc_dynamic = true; const char *outarg = NULL; int columns[ARRAY_SIZE(infos) * 2]; size_t ncolumns = 0; clockid_t clock = -1; + struct dynamic_clock *dynamic_clock; + struct list_head *current_dynamic_clock; + struct list_head dynamic_clocks; - struct timespec resolution, now; - char buf[BUFSIZ]; + struct timespec now; enum { - OPT_OUTPUT_ALL = CHAR_MAX + 1 + OPT_OUTPUT_ALL = CHAR_MAX + 1, + OPT_NO_DISC_DYN, }; static const struct option longopts[] = { - { "noheadings", no_argument, NULL, 'n' }, - { "output", required_argument, NULL, 'o' }, - { "output-all", no_argument, NULL, OPT_OUTPUT_ALL }, - { "version", no_argument, NULL, 'V' }, - { "help", no_argument, NULL, 'h' }, - { "json", no_argument, NULL, 'J' }, - { "raw", no_argument, NULL, 'r' }, - { "time", required_argument, NULL, 't' }, + { "noheadings", no_argument, NULL, 'n' }, + { "output", required_argument, NULL, 'o' }, + { "output-all", no_argument, NULL, OPT_OUTPUT_ALL }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { "json", no_argument, NULL, 'J' }, + { "raw", no_argument, NULL, 'r' }, + { "time", required_argument, NULL, 't' }, + { "no-discover-dynamic", no_argument, NULL, OPT_NO_DISC_DYN }, + { "dynamic-clock", required_argument, NULL, 'd' }, { 0 } }; @@ -289,7 +459,9 @@ int main(int argc, char **argv) textdomain(PACKAGE); close_stdout_atexit(); - while ((c = getopt_long(argc, argv, "no:Jrt:Vh", longopts, NULL)) != -1) { + INIT_LIST_HEAD(&dynamic_clocks); + + while ((c = getopt_long(argc, argv, "no:Jrt:d:Vh", longopts, NULL)) != -1) { switch (c) { case 'n': noheadings = true; @@ -310,6 +482,14 @@ int main(int argc, char **argv) case 't': clock = parse_clock(optarg); break; + case 'd': + dynamic_clock = xmalloc(sizeof(*dynamic_clock)); + dynamic_clock->path = optarg; + list_add(&dynamic_clock->head, &dynamic_clocks); + break; + case OPT_NO_DISC_DYN: + disc_dynamic = false; + break; case 'V': print_version(EXIT_SUCCESS); case 'h': @@ -333,6 +513,7 @@ int main(int argc, char **argv) if (!ncolumns) { columns[ncolumns++] = COL_ID; columns[ncolumns++] = COL_NAME; + columns[ncolumns++] = COL_TYPE; columns[ncolumns++] = COL_TIME; columns[ncolumns++] = COL_RESOL; columns[ncolumns++] = COL_ISO_TIME; @@ -359,81 +540,19 @@ int main(int argc, char **argv) scols_column_set_json_type(col, colinfo->json_type); } - for (i = 0; i < ARRAY_SIZE(clocks); i++) { - clockinfo = &clocks[i]; - - ln = scols_table_new_line(tb, NULL); - if (!ln) - errx(EXIT_FAILURE, _("failed to allocate output line")); - - /* outside the loop to guarantee consistency between COL_TIME and COL_ISO_TIME */ - rc = clock_gettime(clockinfo->id, &now); - if (rc) - now.tv_nsec = -1; + for (i = 0; i < ARRAY_SIZE(clocks); i++) + add_clock_line(tb, columns, ncolumns, &clocks[i]); - rc = clock_getres(clockinfo->id, &resolution); - if (rc) - resolution.tv_nsec = -1; + if (disc_dynamic) + add_dynamic_clocks_from_discovery(tb, columns, ncolumns); - for (j = 0; j < ncolumns; j++) { - switch (columns[j]) { - case COL_ID: - scols_line_asprintf(ln, j, "%ju", (uintmax_t) clockinfo->id); - break; - case COL_CLOCK: - scols_line_set_data(ln, j, clockinfo->id_name); - break; - case COL_NAME: - scols_line_set_data(ln, j, clockinfo->name); - break; - case COL_TIME: - if (now.tv_nsec == -1) - break; - - scols_line_format_timespec(ln, j, &now); - break; - case COL_ISO_TIME: - if (now.tv_nsec == -1) - break; - - rc = strtimespec_iso(&now, - ISO_GMTIME | ISO_DATE | ISO_TIME | ISO_T | ISO_DOTNSEC | ISO_TIMEZONE, - buf, sizeof(buf)); - if (rc) - errx(EXIT_FAILURE, _("failed to format iso time")); - scols_line_set_data(ln, j, buf); - break; - case COL_RESOL: - if (resolution.tv_nsec == -1) - break; - - rc = strtimespec_relative(&resolution, buf, sizeof(buf)); - if (rc) - errx(EXIT_FAILURE, _("failed to format relative time")); - scols_line_set_data(ln, j, buf); - break; - case COL_RESOL_RAW: - if (resolution.tv_nsec == -1) - break; - scols_line_format_timespec(ln, j, &resolution); - break; - case COL_REL_TIME: - if (now.tv_nsec == -1) - break; - rc = strtimespec_relative(&now, buf, sizeof(buf)); - if (rc) - errx(EXIT_FAILURE, _("failed to format relative time")); - scols_line_set_data(ln, j, buf); - break; - case COL_NS_OFFSET: - if (clockinfo->ns_offset_name) - scols_line_asprintf(ln, j, "%"PRId64, - get_namespace_offset(clockinfo->ns_offset_name)); - break; - } - } + list_for_each(current_dynamic_clock, &dynamic_clocks) { + dynamic_clock = list_entry(current_dynamic_clock, struct dynamic_clock, head); + add_dynamic_clock_from_path(tb, columns, ncolumns, dynamic_clock->path, true); } + list_free(&dynamic_clocks, struct dynamic_clock, head, free); + scols_table_enable_json(tb, json); scols_table_enable_raw(tb, raw); scols_table_enable_noheadings(tb, noheadings); diff --git a/misc-utils/lsfd.1.adoc b/misc-utils/lsfd.1.adoc index 720be374f0..b2a6aa5322 100644 --- a/misc-utils/lsfd.1.adoc +++ b/misc-utils/lsfd.1.adoc @@ -70,7 +70,7 @@ and *-p* option, e.g. -p 1, may print the same output but using *-p* option is much more efficient because *-p* option works at a much earlier stage of processing than the *-Q* option. -*-i*[4|6], *--inet*[=4|6]:: +*-i*[4|6], *--inet*[=4|=6]:: List only IPv4 sockets and/or IPv6 sockets. *-Q*, *--filter* _expr_:: @@ -110,6 +110,9 @@ only for *lsfd* developers. *--dump-counters*:: Dump the definition of counters used in *--summary* output. +*-H*, *--list-columns*:: +List available columns that you can specify at *--output* option. + include::man-common/help-version.adoc[] == OUTPUT COLUMNS diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index 4a7bb5c57c..bc7f901d48 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -353,7 +353,7 @@ static const struct colinfo infos[] = { N_("user of the process") }, [COL_XMODE] = { "XMODE", 0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING, - N_("access mode and more (rwx)") }, + N_("extended version of MDOE (rwxD[Ll]m)") }, }; static const int default_columns[] = { @@ -1578,45 +1578,62 @@ static void collect_processes(struct lsfd_control *ctl, const pid_t pids[], int ul_unref_path(pc); } +static void __attribute__((__noreturn__)) list_colunms(FILE *out) +{ + fprintf(out, USAGE_COLUMNS); + for (size_t i = 0; i < ARRAY_SIZE(infos); i++) + fprintf(out, " %20s %-10s%s\n", infos[i].name, + infos[i].json_type == SCOLS_JSON_STRING? "<string>": + infos[i].json_type == SCOLS_JSON_ARRAY_STRING? "<string>": + infos[i].json_type == SCOLS_JSON_ARRAY_NUMBER? "<string>": + infos[i].json_type == SCOLS_JSON_NUMBER? "<number>": + "<boolean>", + _(infos[i].help)); + exit(EXIT_SUCCESS); +} + +static void print_columns(FILE *out, const char *prefix, const int cols[], size_t n_cols) +{ + fprintf(out, "%15s: ", prefix); + for (size_t i = 0; i < n_cols; i++) { + if (i) + fputc(',', out); + fputs(infos[cols[i]].name, out); + } + fputc('\n', out); +} + static void __attribute__((__noreturn__)) usage(void) { FILE *out = stdout; - size_t i; fputs(USAGE_HEADER, out); fprintf(out, _(" %s [options]\n"), program_invocation_short_name); fputs(USAGE_OPTIONS, out); - fputs(_(" -l, --threads list in threads level\n"), out); - fputs(_(" -J, --json use JSON output format\n"), out); - fputs(_(" -n, --noheadings don't print headings\n"), out); - fputs(_(" -o, --output <list> output columns\n"), out); - fputs(_(" -r, --raw use raw output format\n"), out); - fputs(_(" -u, --notruncate don't truncate text in columns\n"), out); - fputs(_(" -p, --pid <pid(s)> collect information only specified processes\n"), out); - fputs(_(" -i[4|6], --inet[=4|6] list only IPv4 and/or IPv6 sockets\n"), out); - fputs(_(" -Q, --filter <expr> apply display filter\n"), out); - fputs(_(" --debug-filter dump the internal data structure of filter and exit\n"), out); - fputs(_(" -C, --counter <name>:<expr>\n" - " define custom counter for --summary output\n"), out); - fputs(_(" --dump-counters dump counter definitions\n"), out); - fputs(_(" --summary[=<when>] print summary information (only, append, or never)\n"), out); + fputs(_(" -l, --threads list in threads level\n"), out); + fputs(_(" -J, --json use JSON output format\n"), out); + fputs(_(" -n, --noheadings don't print headings\n"), out); + fputs(_(" -o, --output <list> output columns\n"), out); + fputs(_(" -r, --raw use raw output format\n"), out); + fputs(_(" -u, --notruncate don't truncate text in columns\n"), out); + fputs(_(" -p, --pid <pid(s)> collect information only specified processes\n"), out); + fputs(_(" -i[4|6], --inet[=4|=6] list only IPv4 and/or IPv6 sockets\n"), out); + fputs(_(" -Q, --filter <expr> apply display filter\n"), out); + fputs(_(" --debug-filter dump the internal data structure of filter and exit\n"), out); + fputs(_(" -C, --counter <name>:<expr> define custom counter for --summary output\n"), out); + fputs(_(" --dump-counters dump counter definitions\n"), out); + fputs(_(" --summary[=<when>] print summary information (only, append, or never)\n"), out); fputs(USAGE_SEPARATOR, out); - printf(USAGE_HELP_OPTIONS(30)); - - fprintf(out, USAGE_COLUMNS); + fputs(_(" -H, --list-columns list the available columns\n"), out); + fprintf(out, USAGE_HELP_OPTIONS(30)); - for (i = 0; i < ARRAY_SIZE(infos); i++) - fprintf(out, " %16s %-10s%s\n", infos[i].name, - infos[i].json_type == SCOLS_JSON_STRING? "<string>": - infos[i].json_type == SCOLS_JSON_ARRAY_STRING? "<string>": - infos[i].json_type == SCOLS_JSON_ARRAY_NUMBER? "<string>": - infos[i].json_type == SCOLS_JSON_NUMBER? "<number>": - "<boolean>", - _(infos[i].help)); + fputs(USAGE_DEFAULT_COLUMNS, out); + print_columns(out, _("Default"), default_columns, ARRAY_SIZE(default_columns)); + print_columns(out, _("With --threads"), default_threads_columns, ARRAY_SIZE(default_threads_columns)); - printf(USAGE_MAN_TAIL("lsfd(1)")); + fprintf(out, USAGE_MAN_TAIL("lsfd(1)")); exit(EXIT_SUCCESS); } @@ -1927,6 +1944,7 @@ int main(int argc, char *argv[]) { "summary", optional_argument, NULL, OPT_SUMMARY }, { "counter", required_argument, NULL, 'C' }, { "dump-counters",no_argument, NULL, OPT_DUMP_COUNTERS }, + { "list-columns",no_argument, NULL, 'H' }, { NULL, 0, NULL, 0 }, }; @@ -1935,7 +1953,7 @@ int main(int argc, char *argv[]) textdomain(PACKAGE); close_stdout_atexit(); - while ((c = getopt_long(argc, argv, "no:JrVhluQ:p:i::C:s", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "no:JrVhluQ:p:i::C:sH", longopts, NULL)) != -1) { switch (c) { case 'n': ctl.noheadings = 1; @@ -2007,6 +2025,8 @@ int main(int argc, char *argv[]) print_version(EXIT_SUCCESS); case 'h': usage(); + case 'H': + list_colunms(stdout); default: errtryhelp(EXIT_FAILURE); } diff --git a/tests/expected/blkid/low-probe-bcachefs b/tests/expected/blkid/low-probe-bcachefs index 70fddbee8e..510ec89448 100644 --- a/tests/expected/blkid/low-probe-bcachefs +++ b/tests/expected/blkid/low-probe-bcachefs @@ -9,4 +9,4 @@ ID_FS_UUID=46bd306f-80ad-4cd0-af4f-147e7d85f393 ID_FS_UUID_ENC=46bd306f-80ad-4cd0-af4f-147e7d85f393 ID_FS_UUID_SUB=72a60ede-4cb6-4374-aa70-cb38a50af5ef ID_FS_UUID_SUB_ENC=72a60ede-4cb6-4374-aa70-cb38a50af5ef -ID_FS_VERSION=13 +ID_FS_VERSION=0.13 diff --git a/tests/expected/blkid/low-probe-bcachefs-2 b/tests/expected/blkid/low-probe-bcachefs-2 index 4a6d664c09..b6e220ea0a 100644 --- a/tests/expected/blkid/low-probe-bcachefs-2 +++ b/tests/expected/blkid/low-probe-bcachefs-2 @@ -9,4 +9,4 @@ ID_FS_UUID=4fa11b1e-75e6-4210-9167-34e1769c0fe1 ID_FS_UUID_ENC=4fa11b1e-75e6-4210-9167-34e1769c0fe1 ID_FS_UUID_SUB=0a3643b7-c515-47f8-a0ea-91fc38d043d1 ID_FS_UUID_SUB_ENC=0a3643b7-c515-47f8-a0ea-91fc38d043d1 -ID_FS_VERSION=26 +ID_FS_VERSION=0.26 diff --git a/tests/expected/misc/lsclocks-basic b/tests/expected/misc/lsclocks-basic index b3b25f4a63..1b375b83c1 100644 --- a/tests/expected/misc/lsclocks-basic +++ b/tests/expected/misc/lsclocks-basic @@ -1,10 +1,10 @@ -ID CLOCK NAME - 0 CLOCK_REALTIME realtime - 1 CLOCK_MONOTONIC monotonic - 4 CLOCK_MONOTONIC_RAW monotonic-raw - 5 CLOCK_REALTIME_COARSE realtime-coarse - 6 CLOCK_MONOTONIC_COARSE monotonic-coarse - 7 CLOCK_BOOTTIME boottime - 8 CLOCK_REALTIME_ALARM realtime-alarm - 9 CLOCK_BOOTTIME_ALARM boottime-alarm -11 CLOCK_TAI tai +TYPE ID CLOCK NAME +sys 0 CLOCK_REALTIME realtime +sys 1 CLOCK_MONOTONIC monotonic +sys 4 CLOCK_MONOTONIC_RAW monotonic-raw +sys 5 CLOCK_REALTIME_COARSE realtime-coarse +sys 6 CLOCK_MONOTONIC_COARSE monotonic-coarse +sys 7 CLOCK_BOOTTIME boottime +sys 8 CLOCK_REALTIME_ALARM realtime-alarm +sys 9 CLOCK_BOOTTIME_ALARM boottime-alarm +sys 11 CLOCK_TAI tai diff --git a/tests/expected/misc/lsclocks-dynamic b/tests/expected/misc/lsclocks-dynamic new file mode 100644 index 0000000000..156ee3f8d8 --- /dev/null +++ b/tests/expected/misc/lsclocks-dynamic @@ -0,0 +1 @@ +ptp /dev/ptp0 /dev/ptp0 diff --git a/tests/ts/misc/lsclocks b/tests/ts/misc/lsclocks index 55ee4df40e..48cd7d9092 100755 --- a/tests/ts/misc/lsclocks +++ b/tests/ts/misc/lsclocks @@ -29,7 +29,7 @@ mask_timestamps() { ts_init_subtest basic -"$TS_CMD_LSCLOCKS" -o ID,CLOCK,NAME > "$TS_OUTPUT" 2>> "$TS_ERRLOG" +"$TS_CMD_LSCLOCKS" --no-discover-dynamic -o TYPE,ID,CLOCK,NAME > "$TS_OUTPUT" 2>> "$TS_ERRLOG" ts_finalize_subtest @@ -39,4 +39,14 @@ ts_init_subtest time ts_finalize_subtest +ts_init_subtest dynamic + +if [ -c /dev/ptp0 ] && [ -r /dev/ptp0 ]; then + "$TS_CMD_LSCLOCKS" --no-discover-dynamic --dynamic-clock /dev/ptp0 --output TYPE,ID,CLOCK,NAME \ + | tail -1 > "$TS_OUTPUT" 2>> "$TS_ERRLOG" + ts_finalize_subtest +else + ts_skip_subtest "/dev/ptp0 not usable" +fi + ts_finalize |
