mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
228 lines
5.1 KiB
C
228 lines
5.1 KiB
C
/*
|
|
* lsstp - Display STP system information
|
|
*
|
|
* Copyright IBM Corp. 2020, 2022
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include <iconv.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "lib/util_opt.h"
|
|
#include "lib/util_file.h"
|
|
#include "lib/util_prg.h"
|
|
#include "lib/util_path.h"
|
|
|
|
static const struct util_prg prg = {
|
|
.desc = "Display STP system information",
|
|
.args = "",
|
|
.copyright_vec = {
|
|
{
|
|
.owner = "IBM Corp.",
|
|
.pub_first = 2020,
|
|
},
|
|
UTIL_PRG_COPYRIGHT_END
|
|
}
|
|
};
|
|
|
|
static struct util_opt opt_vec[] = {
|
|
UTIL_OPT_HELP,
|
|
UTIL_OPT_VERSION,
|
|
UTIL_OPT_END
|
|
};
|
|
|
|
struct stp_parms {
|
|
uint64_t ctn_id;
|
|
unsigned int online;
|
|
unsigned int leap_seconds;
|
|
int leap_seconds_diff;
|
|
unsigned int leap_seconds_utc;
|
|
unsigned int stratum;
|
|
unsigned int ctn_type;
|
|
unsigned int timing_mode;
|
|
unsigned int timing_state;
|
|
int dst_offset;
|
|
int time_offset;
|
|
int time_zone_offset;
|
|
};
|
|
|
|
static int convert_ctn_id(char *in, char *out)
|
|
{
|
|
iconv_t ic;
|
|
size_t inlen = sizeof(unsigned long long);
|
|
size_t outlen = sizeof(unsigned long long);
|
|
|
|
ic = iconv_open("ISO-8859-1", "EBCDIC-US");
|
|
if (ic == (iconv_t)-1) {
|
|
warn("Could not initialize EBCDIC to ISO-8859-1 conversion table");
|
|
return -1;
|
|
}
|
|
|
|
if (iconv(ic, &in, &inlen, (char **)&out, &outlen) == (size_t)-1) {
|
|
warn("Code page translation EBCDIC to ISO-8859-1 failed");
|
|
iconv_close(ic);
|
|
return -1;
|
|
}
|
|
iconv_close(ic);
|
|
return 0;
|
|
}
|
|
|
|
static const char *ctn_type_str(int type)
|
|
{
|
|
switch (type) {
|
|
case 0:
|
|
return "No CTN defined";
|
|
case 1:
|
|
return "STP-only";
|
|
case 2:
|
|
return "mixed";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
static const char *tmd_to_str(int mode)
|
|
{
|
|
switch (mode) {
|
|
case 0:
|
|
return "Local";
|
|
case 1:
|
|
return "ETR";
|
|
case 2:
|
|
return "STP";
|
|
case 15:
|
|
return "Uninitialized";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
static const char *tst_to_str(int mode)
|
|
{
|
|
switch (mode) {
|
|
case 0:
|
|
return "Unsynchronized";
|
|
case 1:
|
|
return "Synchronized";
|
|
case 2:
|
|
return "Physical clock stopped";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
static const char *yesno_str(int val)
|
|
{
|
|
return val ? "yes" : "no";
|
|
}
|
|
|
|
#define read_sysfs_attr(attr, parm, func, base) \
|
|
do { \
|
|
path = util_path_sysfs("devices/system/stp/%s", attr); \
|
|
ret = func(parm, base, path); \
|
|
if (ret) { \
|
|
fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); \
|
|
free(path); \
|
|
exit(EXIT_FAILURE); \
|
|
} \
|
|
free(path); \
|
|
} while (0)
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct stp_parms parm = { 0 };
|
|
char ctn_id[32] = { 0 };
|
|
char *path;
|
|
int ret, c;
|
|
|
|
util_prg_init(&prg);
|
|
util_opt_init(opt_vec, NULL);
|
|
|
|
for (;;) {
|
|
c = util_opt_getopt_long(argc, argv);
|
|
if (c == -1)
|
|
break;
|
|
|
|
switch (c) {
|
|
case 'v':
|
|
util_prg_print_version();
|
|
exit(EXIT_SUCCESS);
|
|
case 'h':
|
|
util_prg_print_help();
|
|
util_opt_print_help();
|
|
exit(EXIT_SUCCESS);
|
|
default:
|
|
fprintf(stderr, "Try 'lsstp --help' for more information.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
read_sysfs_attr("online", &parm.online, util_file_read_ui, 10);
|
|
if (!parm.online) {
|
|
printf("STP disabled\n");
|
|
goto out;
|
|
}
|
|
|
|
read_sysfs_attr("ctn_id", &parm.ctn_id, util_file_read_ul, 16);
|
|
read_sysfs_attr("ctn_type", &parm.ctn_type, util_file_read_ui, 10);
|
|
read_sysfs_attr("stratum", &parm.stratum, util_file_read_ui, 10);
|
|
read_sysfs_attr("leap_seconds", &parm.leap_seconds, util_file_read_ui, 10);
|
|
read_sysfs_attr("timing_mode", &parm.timing_mode, util_file_read_ui, 10);
|
|
read_sysfs_attr("timing_state", &parm.timing_state, util_file_read_ui, 10);
|
|
read_sysfs_attr("dst_offset", &parm.dst_offset, util_file_read_i, 10);
|
|
read_sysfs_attr("time_offset", &parm.time_offset, util_file_read_i, 10);
|
|
read_sysfs_attr("time_zone_offset", &parm.time_zone_offset, util_file_read_i, 10);
|
|
|
|
if (convert_ctn_id((char *)&parm.ctn_id, ctn_id))
|
|
snprintf(ctn_id, sizeof(ctn_id)-1, "%016" PRIx64, parm.ctn_id);
|
|
|
|
printf("STP online: %s\n"
|
|
"CTN ID: %s\n"
|
|
"CTN type: %s\n"
|
|
"Stratum: %d\n"
|
|
"Timing mode: %s\n"
|
|
"Timing state: %s\n"
|
|
"DST offset: %d\n"
|
|
"Timezone offset: %d\n"
|
|
"Time offset: %d\n"
|
|
"Active leap seconds: %d\n",
|
|
yesno_str(parm.online),
|
|
ctn_id,
|
|
ctn_type_str(parm.ctn_type),
|
|
parm.stratum,
|
|
tmd_to_str(parm.timing_mode),
|
|
tst_to_str(parm.timing_state),
|
|
parm.dst_offset,
|
|
parm.time_zone_offset,
|
|
parm.time_offset,
|
|
parm.leap_seconds);
|
|
|
|
printf("Scheduled leap second: ");
|
|
|
|
path = util_path_sysfs("devices/system/stp/leap_seconds_scheduled");
|
|
if (util_file_read_va(path, "%d,%d", &parm.leap_seconds_utc,
|
|
&parm.leap_seconds_diff) == 2 &&
|
|
parm.leap_seconds_diff && parm.leap_seconds_utc) {
|
|
time_t lsoup = parm.leap_seconds_utc;
|
|
|
|
printf("%s at: %s UTC",
|
|
parm.leap_seconds_diff > 0 ? "insertion" : "deletion",
|
|
ctime(&lsoup));
|
|
} else {
|
|
printf("-\n");
|
|
}
|
|
free(path);
|
|
return 0;
|
|
out:
|
|
return 1;
|
|
}
|