#include "closestream.h"
#include "optutils.h"
+#include "c_strtod.h"
+#include "sysfs.h"
#include "lscpu.h"
COL_CPU_SCALMHZ,
COL_CPU_MAXMHZ,
COL_CPU_MINMHZ,
+ COL_CPU_MODELNAME,
};
enum {
[COL_CPU_MHZ] = { "MHZ", N_("shows the currently MHz of the CPU"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
[COL_CPU_SCALMHZ] = { "SCALMHZ%", N_("shows scaling percentage of the CPU frequency"), SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER },
[COL_CPU_MAXMHZ] = { "MAXMHZ", N_("shows the maximum MHz of the CPU"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
- [COL_CPU_MINMHZ] = { "MINMHZ", N_("shows the minimum MHz of the CPU"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER }
+ [COL_CPU_MINMHZ] = { "MINMHZ", N_("shows the minimum MHz of the CPU"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CPU_MODELNAME] = { "MODELNAME", N_("shows CPU model name"), 0, 0, SCOLS_JSON_STRING }
};
static struct lscpu_coldesc coldescs_cache[] =
[COL_CACHE_WAYS] = { "WAYS", N_("ways of associativity"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
[COL_CACHE_ALLOCPOL] = { "ALLOC-POLICY", N_("allocation policy") },
[COL_CACHE_WRITEPOL] = { "WRITE-POLICY", N_("write policy") },
- [COL_CACHE_PHYLINE] = { "PHY-LINE", N_("number of physical cache line per cache t"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CACHE_PHYLINE] = { "PHY-LINE", N_("number of physical cache line per cache tag"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
[COL_CACHE_SETS] = { "SETS", N_("number of sets in the cache; set lines has the same cache index"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
[COL_CACHE_COHERENCYSIZE] = { "COHERENCY-SIZE", N_("minimum amount of data in bytes transferred from memory to cache"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER }
};
-static int is_term = 0;
+static int hierarchic = -1;
UL_DEBUG_DEFINE_MASK(lscpu);
UL_DEBUG_DEFINE_MASKNAMES(lscpu) = UL_DEBUG_EMPTY_MASKNAMES;
DBG(MISC, ul_debugobj(cxt, "initialize paths"));
ul_path_init_debug();
+ /* / */
+ cxt->rootfs = NULL;
+ if (cxt->prefix) {
+ cxt->rootfs = ul_new_path("/");
+ if (!cxt->rootfs)
+ err(EXIT_FAILURE, _("failed to initialize rootfs handler"));
+ ul_path_set_prefix(cxt->rootfs, cxt->prefix);
+ }
+
/* /sys/devices/system/cpu */
cxt->syscpu = ul_new_path(_PATH_SYS_CPU);
if (!cxt->syscpu)
DBG(MISC, ul_debugobj(cxt, " de-initialize paths"));
ul_unref_path(cxt->syscpu);
ul_unref_path(cxt->procfs);
+ ul_unref_path(cxt->rootfs);
DBG(MISC, ul_debugobj(cxt, " freeing cpus"));
for (i = 0; i < cxt->npossibles; i++) {
snprintf(buf, bufsz, "%d", cpu->logical_id);
break;
case COL_CPU_BOGOMIPS:
- if (cpu->bogomips)
- xstrncpy(buf, cpu->bogomips, bufsz);
- else if (cpu->type->bogomips)
- xstrncpy(buf, cpu->type->bogomips, bufsz);
+ if (!cpu->bogomips && !cpu->type->bogomips)
+ break;
+ snprintf(buf, bufsz, "%.2f", (float) c_strtod(
+ cpu->bogomips ? : cpu->type->bogomips, NULL));
break;
case COL_CPU_CORE:
fill_id(cxt, cpu, core, buf, bufsz);
if (cpu->mhz_min_freq)
snprintf(buf, bufsz, "%.4f", cpu->mhz_min_freq);
break;
+ case COL_CPU_MODELNAME:
+ if (cpu->type && cpu->type->modelname)
+ xstrncpy(buf, cpu->type->modelname, bufsz);
+ break;
}
return buf;
}
struct libscols_column *cl;
cl = scols_table_new_column(tb, cd->name, 0, cd->flags);
-
if (cl == NULL)
err(EXIT_FAILURE, _("failed to allocate output column"));
-
if (cxt->json)
scols_column_set_json_type(cl, cd->json_type);
-
-
}
/* standard caches */
cl = scols_table_new_column(tb, data, 0, cd->flags);
if (cl == NULL)
err(EXIT_FAILURE, _("failed to allocate output column"));
-
if (cxt->json)
scols_column_set_json_type(cl, cd->json_type);
-
}
for (i = 0; i < cxt->npossibles; i++) {
struct libscols_line *ln;
va_list args;
- /* Don't print section lines without data on non-terminal output */
- if (!is_term && fmt == NULL)
+ /* Don't print section lines without data */
+ if (!hierarchic && fmt == NULL)
return NULL;
ln = scols_table_new_line(tb, sec);
const char *key, cpu_set_t *set)
{
size_t setbuflen = 7 * cxt->maxcpus;
- char setbuf[setbuflen], *p;
+ char *setbuf, *p;
assert(set);
assert(key);
assert(tb);
assert(cxt);
+ setbuf = xmalloc(setbuflen);
+
if (cxt->hex) {
p = cpumask_create(setbuf, setbuflen, set, cxt->setsize);
add_summary_s(tb, sec, key, p);
p = cpulist_create(setbuf, setbuflen, set, cxt->setsize);
add_summary_s(tb, sec, key, p);
}
+
+ free(setbuf);
}
static void
struct libscols_table *tb,
struct libscols_line *sec)
{
- if (ct->modelname)
- sec = add_summary_s(tb, sec, _("Model name:"), ct->modelname);
+ sec = add_summary_s(tb, sec, _("Model name:"), ct->modelname ? ct->modelname : "-");
if (ct->bios_modelname)
add_summary_s(tb, sec, _("BIOS Model name:"), ct->bios_modelname);
+ if (ct->bios_family)
+ add_summary_s(tb, sec, _("BIOS CPU family:"), ct->bios_family);
if (ct->machinetype)
add_summary_s(tb, sec, _("Machine type:"), ct->machinetype);
if (ct->family)
add_summary_x(tb, sec, _("CPU min MHz:"), "%.4f", lsblk_cputype_get_minmhz(cxt, ct));
}
if (ct->bogomips)
- add_summary_s(tb, sec, _("BogoMIPS:"), ct->bogomips);
+ add_summary_x(tb, sec, _("BogoMIPS:"), "%.2f", (float) c_strtod(ct->bogomips, NULL));
if (ct->dispatching >= 0)
add_summary_s(tb, sec, _("Dispatching mode:"), _(disp_modes[ct->dispatching]));
char field[256];
size_t i = 0;
struct libscols_table *tb;
- struct libscols_line *sec = NULL;
+ struct libscols_line *sec;
int hdr_caches = 0;
scols_init_debug(0);
if (cxt->json) {
scols_table_enable_json(tb, 1);
scols_table_set_name(tb, "lscpu");
- } else if (is_term) {
+ } else if (hierarchic) {
struct libscols_symbols *sy = scols_new_symbols();
if (!sy)
scols_unref_symbols(sy);
}
- if (scols_table_new_column(tb, "field", 0, is_term ? SCOLS_FL_TREE : 0) == NULL ||
+ if (scols_table_new_column(tb, "field", 0, hierarchic ? SCOLS_FL_TREE : 0) == NULL ||
scols_table_new_column(tb, "data", 0, SCOLS_FL_NOEXTREMES | SCOLS_FL_WRAP) == NULL)
err(EXIT_FAILURE, _("failed to initialize output column"));
ct = lscpu_cputype_get_default(cxt);
/* Section: architecture */
- if (cxt->arch)
- sec = add_summary_s(tb, NULL, _("Architecture:"), cxt->arch->name);
- if (cxt->arch && (cxt->arch->bit32 || cxt->arch->bit64)) {
+ sec = add_summary_s(tb, NULL, _("Architecture:"), cxt->arch->name);
+ if (cxt->arch->bit32 || cxt->arch->bit64) {
char buf[32], *p = buf;
if (cxt->arch->bit32) {
*(p - 2) = '\0';
add_summary_s(tb, sec, _("CPU op-mode(s):"), buf);
}
- if (ct->addrsz)
+ if (ct && ct->addrsz)
add_summary_s(tb, sec, _("Address sizes:"), ct->addrsz);
-#if !defined(WORDS_BIGENDIAN)
- add_summary_s(tb, sec, _("Byte Order:"), "Little Endian");
-#else
- add_summary_s(tb, sec, _("Byte Order:"), "Big Endian");
-#endif
+
+ if (sysfs_get_byteorder(cxt->rootfs) == SYSFS_BYTEORDER_LITTLE)
+ add_summary_s(tb, sec, _("Byte Order:"), "Little Endian");
+ else
+ add_summary_s(tb, sec, _("Byte Order:"), "Big Endian");
/* Section: CPU lists */
sec = add_summary_n(tb, NULL, _("CPU(s):"), cxt->npresents);
sec = NULL;
/* Section: cpu type description */
- if (ct->vendor)
+ if (ct && ct->vendor)
sec = add_summary_s(tb, NULL, _("Vendor ID:"), ct->vendor);
- if (ct->bios_vendor)
+ if (ct && ct->bios_vendor)
add_summary_s(tb, sec, _("BIOS Vendor ID:"), ct->bios_vendor);
for (i = 0; i < cxt->ncputypes; i++)
hdr_caches = 1;
}
- snprintf(field, sizeof(field), is_term ? _("%s:") : _("%s cache:"), name);
+ snprintf(field, sizeof(field), hierarchic ? _("%s:") : _("%s cache:"), name);
if (cxt->bytes)
add_summary_sprint(tb, sec, field,
P_("%" PRIu64 " (%d instance)",
sec = add_summary_e(tb, NULL, _("Caches:"));
hdr_caches = 1;
}
- snprintf(field, sizeof(field), is_term ? _("%s:") : _("%s cache:"), ca->name);
+ snprintf(field, sizeof(field), hierarchic ? _("%s:") : _("%s cache:"), ca->name);
if (cxt->bytes)
add_summary_x(tb, sec, field, "%" PRIu64, ca->size);
else {
sec = add_summary_e(tb, NULL, _("Vulnerabilities:"));
for (i = 0; i < cxt->nvuls; i++) {
- snprintf(field, sizeof(field), is_term ?
+ snprintf(field, sizeof(field), hierarchic ?
_("%s:") : _("Vulnerability %s:"), cxt->vuls[i].name);
add_summary_s(tb, sec, field, cxt->vuls[i].text);
}
fputs(_(" -s, --sysroot <dir> use specified directory as system root\n"), out);
fputs(_(" -x, --hex print hexadecimal masks rather than lists of CPUs\n"), out);
fputs(_(" -y, --physical print physical instead of logical IDs\n"), out);
+ fputs(_(" --hierarchic[=when] use subsections in summary (auto, never, always)\n"), out);
fputs(_(" --output-all print all available columns for -e, -p or -C\n"), out);
fputs(USAGE_SEPARATOR, out);
- printf(USAGE_HELP_OPTIONS(25));
+ fprintf(out, USAGE_HELP_OPTIONS(25));
fputs(_("\nAvailable output columns for -e or -p:\n"), out);
for (i = 0; i < ARRAY_SIZE(coldescs_cpu); i++)
for (i = 0; i < ARRAY_SIZE(coldescs_cache); i++)
fprintf(out, " %13s %s\n", coldescs_cache[i].name, _(coldescs_cache[i].help));
- printf(USAGE_MAN_TAIL("lscpu(1)"));
+ fprintf(out, USAGE_MAN_TAIL("lscpu(1)"));
exit(EXIT_SUCCESS);
}
size_t i, ncolumns = 0;
enum {
OPT_OUTPUT_ALL = CHAR_MAX + 1,
+ OPT_HIERARCHIC,
};
static const struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
{ "hex", no_argument, NULL, 'x' },
{ "version", no_argument, NULL, 'V' },
{ "output-all", no_argument, NULL, OPT_OUTPUT_ALL },
+ { "hierarchic", optional_argument, NULL, OPT_HIERARCHIC },
{ NULL, 0, NULL, 0 }
};
case OPT_OUTPUT_ALL:
all = 1;
break;
-
+ case OPT_HIERARCHIC:
+ if (optarg) {
+ if (strcmp(optarg, "auto") == 0)
+ hierarchic = -1;
+ else if (strcmp(optarg, "never") == 0)
+ hierarchic = 0;
+ else if (strcmp(optarg, "always") == 0)
+ hierarchic = 1;
+ else
+ errx(EXIT_FAILURE, _("unsupported --flat argument"));
+ } else
+ hierarchic = 1;
+ break;
case 'h':
usage();
case 'V':
cxt->show_offline = cxt->mode == LSCPU_OUTPUT_READABLE ? 1 : 0;
}
- is_term = isatty(STDOUT_FILENO); /* global variable */
lscpu_init_debug();
cxt->virt = lscpu_read_virtualization(cxt);
+ if (hierarchic == -1)
+ hierarchic = isatty(STDOUT_FILENO); /* default */
+
switch(cxt->mode) {
case LSCPU_OUTPUT_SUMMARY:
print_summary(cxt);
print_cpus_readable(cxt, columns, ncolumns);
break;
case LSCPU_OUTPUT_PARSABLE:
+ cxt->show_compatible = 1;
if (!ncolumns) {
columns[ncolumns++] = COL_CPU_CPU;
columns[ncolumns++] = COL_CPU_CORE;
columns[ncolumns++] = COL_CPU_SOCKET;
columns[ncolumns++] = COL_CPU_NODE;
columns[ncolumns++] = COL_CPU_CACHE;
- cxt->show_compatible = 1;
}
- if (outarg && string_add_to_idarray(outarg, columns,
+ if (outarg) {
+ if (string_add_to_idarray(outarg, columns,
ARRAY_SIZE(columns),
&ncolumns, cpu_column_name_to_id) < 0)
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
+ cxt->show_compatible = 0;
+ }
print_cpus_parsable(cxt, columns, ncolumns);
break;