lsclocks: new util to interact with system clocks
Usecases: * Compare current monotonic time to timestamps reported by systemd * Validate time namespace operations * Inspect clock resolutions Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
This commit is contained in:
parent
b9abaae312
commit
e9ddea7912
12 changed files with 580 additions and 0 deletions
|
@ -347,5 +347,8 @@ endif
|
|||
if BUILD_ENOSYS
|
||||
dist_bashcompletion_DATA += bash-completion/enosys
|
||||
endif
|
||||
if BUILD_LSCLOCKS
|
||||
dist_bashcompletion_DATA += bash-completion/lsclocks
|
||||
endif
|
||||
|
||||
endif # BUILD_BASH_COMPLETION
|
||||
|
|
48
bash-completion/lsclocks
Normal file
48
bash-completion/lsclocks
Normal file
|
@ -0,0 +1,48 @@
|
|||
_lsclocks_module()
|
||||
{
|
||||
local cur prev OPTS
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
case $prev in
|
||||
'-J'|'--json')
|
||||
return 0
|
||||
;;
|
||||
'-n'|'--noheadings')
|
||||
return 0
|
||||
;;
|
||||
'-o'|'--output')
|
||||
return 0
|
||||
;;
|
||||
'-r'|'--raw')
|
||||
return 0
|
||||
;;
|
||||
'-t'|'--time')
|
||||
clocks="$(command "$1" --noheadings --raw --output NAME)"
|
||||
COMPREPLY=( $(compgen -W "$clocks" -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
'-h'|'--help'|'-V'|'--version')
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
case $cur in
|
||||
-*)
|
||||
OPTS="--json
|
||||
--noheadings
|
||||
--output
|
||||
--raw
|
||||
--time
|
||||
--help
|
||||
--version"
|
||||
COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
complete -F _lsclocks_module lsclocks
|
|
@ -1894,6 +1894,9 @@ AS_IF([test "x$build_enosys" = xyes], [
|
|||
])
|
||||
AM_CONDITIONAL([BUILD_ENOSYS], [test "x$build_enosys" = xyes])
|
||||
|
||||
UL_BUILD_INIT([lsclocks], [yes])
|
||||
AM_CONDITIONAL([BUILD_LSCLOCKS], [test "x$build_lsclocks" = xyes])
|
||||
|
||||
UL_BUILD_INIT([getopt], [yes])
|
||||
AM_CONDITIONAL([BUILD_GETOPT], [test "x$build_getopt" = xyes])
|
||||
|
||||
|
|
13
meson.build
13
meson.build
|
@ -2908,6 +2908,19 @@ if cc.compiles(fs.read('include/audit-arch.h'), name : 'has AUDIT_ARCH_NATIVE')
|
|||
endif
|
||||
endif
|
||||
|
||||
exe = executable(
|
||||
'lsclocks',
|
||||
lsclocks_sources,
|
||||
include_directories : includes,
|
||||
link_with : [lib_common, lib_smartcols],
|
||||
install_dir : usrbin_exec_dir,
|
||||
install : true)
|
||||
if not is_disabler(exe)
|
||||
exes += exe
|
||||
manadocs += ['misc-utils/lsclocks.1.adoc']
|
||||
bashcompletions += ['lsclocks']
|
||||
endif
|
||||
|
||||
############################################################
|
||||
|
||||
opt = not get_option('build-schedutils').disabled()
|
||||
|
|
|
@ -316,3 +316,11 @@ enosys_SOURCES = misc-utils/enosys.c
|
|||
enosys_LDADD = $(LDADD) libcommon.la
|
||||
enosys_CFLAGS = $(AM_CFLAGS)
|
||||
endif
|
||||
|
||||
if BUILD_LSCLOCKS
|
||||
usrbin_exec_PROGRAMS += lsclocks
|
||||
MANPAGES += misc-utils/lsclocks.1
|
||||
lsclocks_SOURCES = misc-utils/lsclocks.c
|
||||
lsclocks_LDADD = $(LDADD) libcommon.la libsmartcols.la
|
||||
lsclocks_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir)
|
||||
endif
|
||||
|
|
81
misc-utils/lsclocks.1.adoc
Normal file
81
misc-utils/lsclocks.1.adoc
Normal file
|
@ -0,0 +1,81 @@
|
|||
//po4a: entry man manual
|
||||
= lsclocks(1)
|
||||
:doctype: manpage
|
||||
:man manual: User Commands
|
||||
:man source: util-linux {release-version}
|
||||
:page-layout: base
|
||||
:command: lsclocks
|
||||
|
||||
== NAME
|
||||
|
||||
lsclocks - display system clocks
|
||||
|
||||
== SYNOPSIS
|
||||
|
||||
*lsclocks* [option]
|
||||
|
||||
== DESCRIPTION
|
||||
|
||||
*lsclocks* is a simple command to display system clocks.
|
||||
|
||||
It allows to display information like current time and resolutionof clocks like
|
||||
CLOCK_MONOTONIC, CLOCK_REALTIME and CLOCK_BOOTTIME.
|
||||
|
||||
== OPTIONS
|
||||
|
||||
*-J*, *--json*::
|
||||
Use JSON output format.
|
||||
|
||||
*-n*, *--noheadings*::
|
||||
Don't print headings.
|
||||
|
||||
*-o*, *--output* _list_::
|
||||
Specify which output columns to print. See the *OUTPUT COLUMNS*
|
||||
section for details of available columns.
|
||||
|
||||
*-r*, *--raw*::
|
||||
Use raw output format.
|
||||
|
||||
*-r*, *--time* _clock_
|
||||
Show current time of one specific clocks.
|
||||
|
||||
include::man-common/help-version.adoc[]
|
||||
|
||||
== OUTPUT COLUMNS
|
||||
|
||||
Each column has a type. Types are surround by < and >.
|
||||
|
||||
ID <``number``>::
|
||||
Numeric clock ID.
|
||||
|
||||
CLOCK <``string``>::
|
||||
Name in the form *CLOCK_*
|
||||
|
||||
NAME <``string``>::
|
||||
Shorter, easier to read name.
|
||||
|
||||
TIME <``number``>::
|
||||
Current clock timestamp as returned by *clock_gettime()*.
|
||||
|
||||
ISO_TIME <``string``>::
|
||||
ISO8601 formatted version of *TIME*.
|
||||
|
||||
RESOLUTION <``number``>::
|
||||
Clock resolution as returned by *clock_getres()*.
|
||||
|
||||
|
||||
== AUTHORS
|
||||
|
||||
mailto:thomas@t-8ch.de[Thomas Weißschuh]
|
||||
|
||||
== SEE ALSO
|
||||
|
||||
*clock_getres*(2) *clock_gettime*(2)
|
||||
|
||||
include::man-common/bugreports.adoc[]
|
||||
|
||||
include::man-common/footer.adoc[]
|
||||
|
||||
ifdef::translation[]
|
||||
include::man-common/translation.adoc[]
|
||||
endif::[]
|
366
misc-utils/lsclocks.c
Normal file
366
misc-utils/lsclocks.c
Normal file
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* lsclocks(1) - display system clocks
|
||||
*
|
||||
* Copyright (C) 2023 Thomas Weißschuh <thomas@t-8ch.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <libsmartcols.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "nls.h"
|
||||
#include "strutils.h"
|
||||
#include "timeutils.h"
|
||||
#include "closestream.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#define CLOCKFD 3
|
||||
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
|
||||
|
||||
#ifndef CLOCK_REALTIME
|
||||
#define CLOCK_REALTIME 0
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
#define CLOCK_MONOTONIC 1
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_MONOTONIC_RAW
|
||||
#define CLOCK_MONOTONIC_RAW 4
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_REALTIME_COARSE
|
||||
#define CLOCK_REALTIME_COARSE 5
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_MONOTONIC_COARSE
|
||||
#define CLOCK_MONOTONIC_COARSE 6
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_BOOTTIME
|
||||
#define CLOCK_BOOTTIME 7
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_REALTIME_ALARM
|
||||
#define CLOCK_REALTIME_ALARM 8
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_BOOTTIME_ALARM
|
||||
#define CLOCK_BOOTTIME_ALARM 9
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_TAI
|
||||
#define CLOCK_TAI 11
|
||||
#endif
|
||||
|
||||
struct clockinfo {
|
||||
clockid_t id;
|
||||
const char * const id_name;
|
||||
const char * const name;
|
||||
};
|
||||
|
||||
static const struct clockinfo clocks[] = {
|
||||
{ CLOCK_REALTIME, "CLOCK_REALTIME", "realtime" },
|
||||
{ CLOCK_MONOTONIC, "CLOCK_MONOTONIC", "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" },
|
||||
{ CLOCK_REALTIME_ALARM, "CLOCK_REALTIME_ALARM", "realtime-alarm" },
|
||||
{ CLOCK_BOOTTIME_ALARM, "CLOCK_BOOTTIME_ALARM", "boottime-alarm" },
|
||||
{ CLOCK_TAI, "CLOCK_TAI", "tai" },
|
||||
};
|
||||
|
||||
/* column IDs */
|
||||
enum {
|
||||
COL_ID,
|
||||
COL_CLOCK,
|
||||
COL_NAME,
|
||||
COL_TIME,
|
||||
COL_ISO_TIME,
|
||||
COL_RESOLUTION,
|
||||
};
|
||||
|
||||
/* column names */
|
||||
struct colinfo {
|
||||
const char * const name; /* header */
|
||||
double whint; /* width hint (N < 1 is in percent of termwidth) */
|
||||
int flags; /* SCOLS_FL_* */
|
||||
int json_type; /* SCOLS_JSON_* */
|
||||
const char * const help;
|
||||
};
|
||||
|
||||
/* columns descriptions */
|
||||
static const struct colinfo infos[] = {
|
||||
[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") },
|
||||
[COL_TIME] = { "TIME", 1, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, N_("numeric time") },
|
||||
[COL_ISO_TIME] = { "ISO_TIME", 1, SCOLS_FL_RIGHT, SCOLS_JSON_STRING, N_("human readable ISO time") },
|
||||
[COL_RESOLUTION] = { "RESOLUTION", 1, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, N_("resolution") },
|
||||
};
|
||||
|
||||
static int column_name_to_id(const char *name, size_t namesz)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(infos); i++) {
|
||||
const char *cn = infos[i].name;
|
||||
|
||||
if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
|
||||
return i;
|
||||
}
|
||||
warnx(_("unknown column: %s"), name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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(_(" -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(_(" -t, --time <clock> show current time of single clock\n"), out);
|
||||
|
||||
fputs(USAGE_SEPARATOR, out);
|
||||
printf(USAGE_HELP_OPTIONS(25));
|
||||
|
||||
fprintf(out, USAGE_COLUMNS);
|
||||
|
||||
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));
|
||||
|
||||
printf(USAGE_MAN_TAIL("lslocks(1)"));
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)))
|
||||
static void scols_line_asprintf(struct libscols_line *ln, size_t n, const char *format, ...)
|
||||
{
|
||||
char *data;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
xvasprintf(&data, format, args);
|
||||
va_end(args);
|
||||
|
||||
scols_line_refer_data(ln, n, data);
|
||||
}
|
||||
|
||||
static void scols_line_format_timespec(struct libscols_line *ln, size_t n, const struct timespec *ts)
|
||||
{
|
||||
scols_line_asprintf(ln, n, "%ju.%09" PRId32, (uintmax_t) ts->tv_sec, (uint32_t) ts->tv_nsec);
|
||||
}
|
||||
|
||||
static clockid_t parse_clock(const char *name)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t id = -1;
|
||||
int rc;
|
||||
|
||||
rc = ul_strtou32(name, &id, 10);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clocks); i++) {
|
||||
if (!strcmp(name, clocks[i].id_name)
|
||||
|| !strcmp(name, clocks[i].name))
|
||||
return clocks[i].id;
|
||||
if (rc == 0 && (clockid_t) id == clocks[i].id)
|
||||
return id;
|
||||
}
|
||||
|
||||
errx(EXIT_FAILURE, _("Unknown clock: %s"), name);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
size_t i, j;
|
||||
char c;
|
||||
int 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;
|
||||
const char *outarg = NULL;
|
||||
int columns[ARRAY_SIZE(infos) * 2];
|
||||
size_t ncolumns = 0;
|
||||
clockid_t clock = -1;
|
||||
|
||||
struct timespec resolution, now;
|
||||
char buf[FORMAT_TIMESTAMP_MAX];
|
||||
|
||||
static const struct option longopts[] = {
|
||||
{ "noheadings", no_argument, NULL, 'n' },
|
||||
{ "output", required_argument, NULL, 'o' },
|
||||
{ "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' },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
close_stdout_atexit();
|
||||
|
||||
while ((c = getopt_long(argc, argv, "no:Jrt:Vh", longopts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
noheadings = true;
|
||||
break;
|
||||
case 'o':
|
||||
outarg = optarg;
|
||||
break;
|
||||
case 'J':
|
||||
json = true;
|
||||
break;
|
||||
case 'r':
|
||||
raw = true;
|
||||
break;
|
||||
case 't':
|
||||
clock = parse_clock(optarg);
|
||||
break;
|
||||
case 'V':
|
||||
print_version(EXIT_SUCCESS);
|
||||
case 'h':
|
||||
usage();
|
||||
default:
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[optind])
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
|
||||
if (clock != -1) {
|
||||
rc = clock_gettime(clock, &now);
|
||||
if (rc)
|
||||
err(EXIT_FAILURE, _("failed to get time"));
|
||||
printf("%ju.%09"PRId32"\n", (uintmax_t) now.tv_sec, (uint32_t) now.tv_nsec);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (!ncolumns) {
|
||||
columns[ncolumns++] = COL_ID;
|
||||
columns[ncolumns++] = COL_CLOCK;
|
||||
columns[ncolumns++] = COL_NAME;
|
||||
columns[ncolumns++] = COL_TIME;
|
||||
columns[ncolumns++] = COL_ISO_TIME;
|
||||
columns[ncolumns++] = COL_RESOLUTION;
|
||||
}
|
||||
|
||||
if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
|
||||
&ncolumns, column_name_to_id) < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
scols_init_debug(0);
|
||||
|
||||
tb = scols_new_table();
|
||||
if (!tb)
|
||||
errx(EXIT_FAILURE, _("failed to allocate output table"));
|
||||
scols_table_set_name(tb, "clocks");
|
||||
|
||||
for (i = 0; i < ncolumns; i++) {
|
||||
colinfo = &infos[columns[i]];
|
||||
|
||||
col = scols_table_new_column(tb, colinfo->name, colinfo->whint, colinfo->flags);
|
||||
if (!col)
|
||||
errx(EXIT_FAILURE, _("failed to allocate output column"));
|
||||
|
||||
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 (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_RESOLUTION:
|
||||
rc = clock_getres(clockinfo->id, &resolution);
|
||||
if (!rc)
|
||||
scols_line_format_timespec(ln, j, &resolution);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scols_table_enable_json(tb, json);
|
||||
scols_table_enable_raw(tb, raw);
|
||||
scols_table_enable_noheadings(tb, noheadings);
|
||||
scols_print_table(tb);
|
||||
scols_unref_table(tb);
|
||||
}
|
|
@ -165,3 +165,7 @@ fadvise_sources = files(
|
|||
waitpid_sources = files(
|
||||
'waitpid.c',
|
||||
)
|
||||
|
||||
lsclocks_sources = files(
|
||||
'lsclocks.c',
|
||||
)
|
||||
|
|
|
@ -87,6 +87,7 @@ TS_CMD_LINE=${TS_CMD_LINE-"${ts_commandsdir}line"}
|
|||
TS_CMD_LOOK=${TS_CMD_LOOK-"${ts_commandsdir}look"}
|
||||
TS_CMD_LOSETUP=${TS_CMD_LOSETUP:-"${ts_commandsdir}losetup"}
|
||||
TS_CMD_LSBLK=${TS_CMD_LSBLK-"${ts_commandsdir}lsblk"}
|
||||
TS_CMD_LSCLOCKS=${TS_CMD_LSCPU-"${ts_commandsdir}lsclocks"}
|
||||
TS_CMD_LSCPU=${TS_CMD_LSCPU-"${ts_commandsdir}lscpu"}
|
||||
TS_CMD_LSFD=${TS_CMD_LSFD-"${ts_commandsdir}lsfd"}
|
||||
TS_CMD_LSMEM=${TS_CMD_LSMEM-"${ts_commandsdir}lsmem"}
|
||||
|
|
10
tests/expected/misc/lsclocks-basic
Normal file
10
tests/expected/misc/lsclocks-basic
Normal file
|
@ -0,0 +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
|
1
tests/expected/misc/lsclocks-time
Normal file
1
tests/expected/misc/lsclocks-time
Normal file
|
@ -0,0 +1 @@
|
|||
X.X
|
42
tests/ts/misc/lsclocks
Executable file
42
tests/ts/misc/lsclocks
Executable file
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (C) 2023 Thomas Weißschuh <thomas@t-8ch.de>
|
||||
#
|
||||
# This file is part of util-linux.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
TS_TOPDIR="${0%/*}/../.."
|
||||
TS_DESC="lsclocks"
|
||||
|
||||
. "$TS_TOPDIR"/functions.sh
|
||||
ts_init "$*"
|
||||
|
||||
ts_check_test_command "$TS_CMD_LSCLOCKS"
|
||||
ts_check_prog sed
|
||||
|
||||
mask_timestamps() {
|
||||
sed 's/[0-9]\+\.[0-9]\+/X.X/g'
|
||||
}
|
||||
|
||||
ts_init_subtest basic
|
||||
|
||||
"$TS_CMD_LSCLOCKS" -o ID,CLOCK,NAME > "$TS_OUTPUT" 2>> "$TS_ERRLOG"
|
||||
|
||||
ts_finalize_subtest
|
||||
|
||||
ts_init_subtest time
|
||||
|
||||
"$TS_CMD_LSCLOCKS" --time monotonic | mask_timestamps > "$TS_OUTPUT" 2>> "$TS_ERRLOG"
|
||||
|
||||
ts_finalize_subtest
|
||||
|
||||
ts_finalize
|
Loading…
Add table
Add a link
Reference in a new issue