From: Thomas Weißschuh Date: Fri, 30 Jun 2023 11:32:18 +0000 (+0200) Subject: lsclocks: add support for dynamic clocks X-Git-Tag: v2.40-rc1~332^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4620c6a040cd5ef17fc955c2352035c54a762dd;p=thirdparty%2Futil-linux.git lsclocks: add support for dynamic clocks Signed-off-by: Thomas Weißschuh --- diff --git a/misc-utils/lsclocks.1.adoc b/misc-utils/lsclocks.1.adoc index af3e55d851..644887bacb 100644 --- a/misc-utils/lsclocks.1.adoc +++ b/misc-utils/lsclocks.1.adoc @@ -42,6 +42,9 @@ Use raw output format. *-r*, *--time* _clock_ Show current time of one specific clocks. +*-d*, *--dynamic-clock* _path_ +Also display specified dynamic clock. + include::man-common/help-version.adoc[] == OUTPUT COLUMNS diff --git a/misc-utils/lsclocks.c b/misc-utils/lsclocks.c index 16ff87bada..a0fe55bd4d 100644 --- a/misc-utils/lsclocks.c +++ b/misc-utils/lsclocks.c @@ -34,9 +34,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 @@ -76,6 +91,7 @@ enum CLOCK_TYPE { CT_SYS, + CT_PTP, }; static const char *clock_type_name(enum CLOCK_TYPE type) @@ -83,6 +99,8 @@ 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); } @@ -170,15 +188,16 @@ 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 output columns\n"), out); - fputs(_(" --output-all output all columns\n"), out); - fputs(_(" -r, --raw use raw output format\n"), out); - fputs(_(" -t, --time 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 output columns\n"), out); + fputs(_(" --output-all output all columns\n"), out); + fputs(_(" -r, --raw use raw output format\n"), out); + fputs(_(" -t, --time show current time of single clock\n"), out); + fputs(_(" -d, --dynamic-clock 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); @@ -293,7 +312,8 @@ static void add_clock_line(struct libscols_table *tb, const int *columns, scols_line_set_data(ln, i, clock_type_name(clockinfo->type)); break; case COL_ID: - scols_line_asprintf(ln, i, "%ju", (uintmax_t) clockinfo->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); @@ -349,6 +369,29 @@ static void add_clock_line(struct libscols_table *tb, const int *columns, } } +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) +{ + int fd = open(path, O_RDONLY); + if (fd == -1) + err(EXIT_FAILURE, _("Could not open %s"), path); + + 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); +} + int main(int argc, char **argv) { size_t i; @@ -363,6 +406,9 @@ int main(int argc, char **argv) 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 now; @@ -370,14 +416,15 @@ int main(int argc, char **argv) OPT_OUTPUT_ALL = CHAR_MAX + 1 }; 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' }, + { "dynamic-clock", required_argument, NULL, 'd' }, { 0 } }; @@ -386,7 +433,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; @@ -407,6 +456,11 @@ 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 'V': print_version(EXIT_SUCCESS); case 'h': @@ -460,6 +514,13 @@ int main(int argc, char **argv) for (i = 0; i < ARRAY_SIZE(clocks); i++) add_clock_line(tb, columns, ncolumns, &clocks[i]); + 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); + } + + 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/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 4cf414bdd0..a5f2936ee9 100755 --- a/tests/ts/misc/lsclocks +++ b/tests/ts/misc/lsclocks @@ -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" --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