#include "closestream.h"
#include "optutils.h"
+#include "c_strtod.h"
+#include "sysfs.h"
#include "lscpu.h"
[VIRT_VENDOR_XEN] = "Xen",
[VIRT_VENDOR_KVM] = "KVM",
[VIRT_VENDOR_MSHV] = "Microsoft",
- [VIRT_VENDOR_VMWARE] = "VMware",
+ [VIRT_VENDOR_VMWARE] = "VMware",
[VIRT_VENDOR_IBM] = "IBM",
[VIRT_VENDOR_VSERVER] = "Linux-VServer",
[VIRT_VENDOR_UML] = "User-mode Linux",
[VIRT_VENDOR_INNOTEK] = "Innotek GmbH",
[VIRT_VENDOR_HITACHI] = "Hitachi",
- [VIRT_VENDOR_PARALLELS] = "Parallels",
+ [VIRT_VENDOR_PARALLELS] = "Parallels",
[VIRT_VENDOR_VBOX] = "Oracle",
[VIRT_VENDOR_OS400] = "OS/400",
[VIRT_VENDOR_PHYP] = "pHyp",
};
static struct polarization_modes polar_modes[] = {
- [POLAR_UNKNOWN] = {"U", "-"},
- [POLAR_VLOW] = {"VL", "vert-low"},
- [POLAR_VMEDIUM] = {"VM", "vert-medium"},
- [POLAR_VHIGH] = {"VH", "vert-high"},
+ [POLAR_UNKNOWN] = {"U", "-"},
+ [POLAR_VLOW] = {"VL", "vert-low"},
+ [POLAR_VMEDIUM] = {"VM", "vert-medium"},
+ [POLAR_VHIGH] = {"VH", "vert-high"},
[POLAR_HORIZONTAL] = {"H", "horizontal"},
};
COL_CPU_CONFIGURED,
COL_CPU_ONLINE,
COL_CPU_MHZ,
+ COL_CPU_SCALMHZ,
COL_CPU_MAXMHZ,
COL_CPU_MINMHZ,
+ COL_CPU_MODELNAME,
};
enum {
int flags;
unsigned int is_abbr:1; /* name is abbreviation */
+ int json_type;
};
static struct lscpu_coldesc coldescs_cpu[] =
{
- [COL_CPU_BOGOMIPS] = { "BOGOMIPS", N_("crude measurement of CPU speed"), SCOLS_FL_RIGHT, 1 },
- [COL_CPU_CPU] = { "CPU", N_("logical CPU number"), SCOLS_FL_RIGHT, 1 },
- [COL_CPU_CORE] = { "CORE", N_("logical core number"), SCOLS_FL_RIGHT },
- [COL_CPU_CLUSTER] = { "CLUSTER", N_("logical cluster number"), SCOLS_FL_RIGHT },
- [COL_CPU_SOCKET] = { "SOCKET", N_("logical socket number"), SCOLS_FL_RIGHT },
- [COL_CPU_NODE] = { "NODE", N_("logical NUMA node number"), SCOLS_FL_RIGHT },
- [COL_CPU_BOOK] = { "BOOK", N_("logical book number"), SCOLS_FL_RIGHT },
- [COL_CPU_DRAWER] = { "DRAWER", N_("logical drawer number"), SCOLS_FL_RIGHT },
+ [COL_CPU_BOGOMIPS] = { "BOGOMIPS", N_("crude measurement of CPU speed"), SCOLS_FL_RIGHT, 1, SCOLS_JSON_NUMBER },
+ [COL_CPU_CPU] = { "CPU", N_("logical CPU number"), SCOLS_FL_RIGHT, 1, SCOLS_JSON_NUMBER },
+ [COL_CPU_CORE] = { "CORE", N_("logical core number"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CPU_CLUSTER] = { "CLUSTER", N_("logical cluster number"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CPU_SOCKET] = { "SOCKET", N_("logical socket number"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CPU_NODE] = { "NODE", N_("logical NUMA node number"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CPU_BOOK] = { "BOOK", N_("logical book number"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
+ [COL_CPU_DRAWER] = { "DRAWER", N_("logical drawer number"), SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER },
[COL_CPU_CACHE] = { "CACHE", N_("shows how caches are shared between CPUs") },
[COL_CPU_POLARIZATION] = { "POLARIZATION", N_("CPU dispatching mode on virtual hardware") },
[COL_CPU_ADDRESS] = { "ADDRESS", N_("physical address of a CPU") },
- [COL_CPU_CONFIGURED] = { "CONFIGURED", N_("shows if the hypervisor has allocated the CPU") },
- [COL_CPU_ONLINE] = { "ONLINE", N_("shows if Linux currently makes use of the CPU"), SCOLS_FL_RIGHT },
- [COL_CPU_MHZ] = { "MHZ", N_("shows the currently MHz of the CPU"), SCOLS_FL_RIGHT },
- [COL_CPU_MAXMHZ] = { "MAXMHZ", N_("shows the maximum MHz of the CPU"), SCOLS_FL_RIGHT },
- [COL_CPU_MINMHZ] = { "MINMHZ", N_("shows the minimum MHz of the CPU"), SCOLS_FL_RIGHT }
+ [COL_CPU_CONFIGURED] = { "CONFIGURED", N_("shows if the hypervisor has allocated the CPU"), 0, 0, SCOLS_JSON_BOOLEAN_OPTIONAL },
+ [COL_CPU_ONLINE] = { "ONLINE", N_("shows if Linux currently makes use of the CPU"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_BOOLEAN_OPTIONAL },
+ [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_MODELNAME] = { "MODELNAME", N_("shows CPU model name"), 0, 0, SCOLS_JSON_STRING }
};
static struct lscpu_coldesc coldescs_cache[] =
{
[COL_CACHE_ALLSIZE] = { "ALL-SIZE", N_("size of all system caches"), SCOLS_FL_RIGHT },
- [COL_CACHE_LEVEL] = { "LEVEL", N_("cache level"), SCOLS_FL_RIGHT },
+ [COL_CACHE_LEVEL] = { "LEVEL", N_("cache level"), SCOLS_FL_RIGHT, 0, SCOLS_JSON_NUMBER },
[COL_CACHE_NAME] = { "NAME", N_("cache name") },
[COL_CACHE_ONESIZE] = { "ONE-SIZE", N_("size of one cache"), SCOLS_FL_RIGHT },
[COL_CACHE_TYPE] = { "TYPE", N_("cache type") },
- [COL_CACHE_WAYS] = { "WAYS", N_("ways of associativity"), SCOLS_FL_RIGHT },
+ [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 },
- [COL_CACHE_SETS] = { "SETS", N_("number of sets in the cache; set lines has the same cache index"), SCOLS_FL_RIGHT },
- [COL_CACHE_COHERENCYSIZE] = { "COHERENCY-SIZE", N_("minimum amount of data in bytes transferred from memory to cache"), SCOLS_FL_RIGHT }
+ [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++) {
}
}
+static void get_cell_boolean(
+ struct lscpu_cxt *cxt,
+ int has_data, int data,
+ char *buf, size_t bufsz)
+{
+ if (!has_data)
+ return;
+
+ if (cxt->mode == LSCPU_OUTPUT_PARSABLE || cxt->json)
+ snprintf(buf, bufsz, "%s",
+ data ? _("Y") : _("N"));
+ else
+ snprintf(buf, bufsz, "%s",
+ data ? _("yes") : _("no"));
+}
+
#define fill_id(_cxt, _cpu, NAME, _buf, _bufsz) \
__fill_id(_cxt, (_cpu), \
(_cpu)-> NAME ## id, \
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);
snprintf(buf, bufsz, "%d", cpu->address);
break;
case COL_CPU_CONFIGURED:
- if (cpu->configured < 0)
- break;
- if (cxt->mode == LSCPU_OUTPUT_PARSABLE)
- snprintf(buf, bufsz, "%s",
- cpu->configured ? _("Y") : _("N"));
- else
- snprintf(buf, bufsz, "%s",
- cpu->configured ? _("yes") : _("no"));
+ get_cell_boolean(cxt, cpu->configured >= 0, cpu->configured, buf, bufsz);
break;
case COL_CPU_ONLINE:
- if (!cxt->online)
- break;
- if (cxt->mode == LSCPU_OUTPUT_PARSABLE)
- snprintf(buf, bufsz, "%s",
- is_cpu_online(cxt, cpu) ? _("Y") : _("N"));
- else
- snprintf(buf, bufsz, "%s",
- is_cpu_online(cxt, cpu) ? _("yes") : _("no"));
+ get_cell_boolean(cxt, !!cxt->online, is_cpu_online(cxt, cpu), buf, bufsz);
break;
case COL_CPU_MHZ:
- if (cpu->mhz)
- xstrncpy(buf, cpu->mhz, bufsz);
+ if (cpu->mhz_cur_freq)
+ snprintf(buf, bufsz, "%.4f", cpu->mhz_cur_freq);
+ break;
+ case COL_CPU_SCALMHZ:
+ if (cpu->mhz_cur_freq && cpu->mhz_max_freq)
+ snprintf(buf, bufsz, "%.0f%%", cpu->mhz_cur_freq / cpu->mhz_max_freq * 100);
break;
case COL_CPU_MAXMHZ:
if (cpu->mhz_max_freq)
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;
}
{
uint64_t sz = 0;
if (ca->name)
- sz = lscpu_get_cache_full_size(cxt, ca->name);
+ sz = lscpu_get_cache_full_size(cxt, ca->name, NULL);
if (!sz)
break;
if (cxt->bytes)
for (i = 0; i < ncols; i++) {
struct lscpu_coldesc *cd = &coldescs_cache[cols[i]];
- if (!scols_table_new_column(tb, cd->name, 0, cd->flags))
+ 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 */
for (i = 0; i < ncols; i++) {
data = get_cell_header(cxt, cols[i], buf, sizeof(buf));
- if (!scols_table_new_column(tb, data, 0, coldescs_cpu[cols[i]].flags))
+ struct lscpu_coldesc *cd = &coldescs_cpu[cols[i]];
+ struct libscols_column *cl;
+
+ 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_s(tb, sec, _("CPU static MHz:"), ct->static_mhz);
if (ct->has_freq) {
+ float scal = lsblk_cputype_get_scalmhz(cxt, ct);
+ if (scal > 0.0)
+ add_summary_x(tb, sec, _("CPU(s) scaling MHz:"), "%.0f%%", scal);
add_summary_x(tb, sec, _("CPU max MHz:"), "%.4f", lsblk_cputype_get_maxmhz(cxt, ct));
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++)
/* The caches are sorted by name, cxt->caches[] may contains
* multiple instances for the same name.
*/
- sec = add_summary_e(tb, NULL, _("Caches (sum of all):"));
-
for (i = 0; i < cxt->ncaches; i++) {
const char *name = cxt->caches[i].name;
uint64_t sz;
+ int n = 0;
if (last && strcmp(last, name) == 0)
continue;
- sz = lscpu_get_cache_full_size(cxt, name);
+ sz = lscpu_get_cache_full_size(cxt, name, &n);
if (!sz)
continue;
- snprintf(field, sizeof(field), is_term ? _("%s:") : _("%s cache:"), name);
+ if (!hdr_caches) {
+ sec = add_summary_e(tb, NULL, _("Caches (sum of all):"));
+ hdr_caches = 1;
+ }
+
+ snprintf(field, sizeof(field), hierarchic ? _("%s:") : _("%s cache:"), name);
if (cxt->bytes)
- add_summary_x(tb, sec, field, "%" PRIu64, sz);
+ add_summary_sprint(tb, sec, field,
+ P_("%" PRIu64 " (%d instance)",
+ "%" PRIu64 " (%d instances)", n),
+ sz, n);
else {
char *tmp = size_to_human_string(
SIZE_SUFFIX_3LETTER |
SIZE_SUFFIX_SPACE,
sz);
- add_summary_s(tb, sec, field, tmp);
+ add_summary_sprint(tb, sec, field,
+ P_("%s (%d instance)",
+ "%s (%d instances)", n),
+ tmp, n);
free(tmp);
}
last = name;
}
}
- if (cxt->necaches) {
- if (!cxt->ncaches)
- sec = add_summary_e(tb, NULL, _("Caches:"));
-
- for (i = 0; i < cxt->necaches; i++) {
- struct lscpu_cache *ca = &cxt->ecaches[i];
+ for (i = 0; i < cxt->necaches; i++) {
+ struct lscpu_cache *ca = &cxt->ecaches[i];
- if (ca->size == 0)
- continue;
- snprintf(field, sizeof(field), is_term ? _("%s:") : _("%s cache:"), ca->name);
- if (cxt->bytes)
- add_summary_x(tb, sec, field, "%" PRIu64, ca->size);
- else {
- char *tmp = size_to_human_string(
- SIZE_SUFFIX_3LETTER |
- SIZE_SUFFIX_SPACE,
- ca->size);
- add_summary_s(tb, sec, field, tmp);
- free(tmp);
- }
+ if (ca->size == 0)
+ continue;
+ if (!hdr_caches) {
+ sec = add_summary_e(tb, NULL, _("Caches:"));
+ hdr_caches = 1;
+ }
+ snprintf(field, sizeof(field), hierarchic ? _("%s:") : _("%s cache:"), ca->name);
+ if (cxt->bytes)
+ add_summary_x(tb, sec, field, "%" PRIu64, ca->size);
+ else {
+ char *tmp = size_to_human_string(
+ SIZE_SUFFIX_3LETTER |
+ SIZE_SUFFIX_SPACE,
+ ca->size);
+ add_summary_s(tb, sec, field, tmp);
+ free(tmp);
}
}
sec = NULL;
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);
}
{
struct lscpu_cxt *cxt;
int c, all = 0;
- int columns[ARRAY_SIZE(coldescs_cpu)], ncolumns = 0;
+ int columns[ARRAY_SIZE(coldescs_cpu)];
int cpu_modifier_specified = 0;
- size_t i;
+ char *outarg = NULL;
+ 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 }
};
if (optarg) {
if (*optarg == '=')
optarg++;
- ncolumns = string_to_idarray(optarg,
- columns, ARRAY_SIZE(columns),
- cache_column_name_to_id);
- if (ncolumns < 0)
- return EXIT_FAILURE;
+ outarg = optarg;
}
cxt->mode = LSCPU_OUTPUT_CACHES;
break;
if (optarg) {
if (*optarg == '=')
optarg++;
- ncolumns = string_to_idarray(optarg,
- columns, ARRAY_SIZE(columns),
- cpu_column_name_to_id);
- if (ncolumns < 0)
- return EXIT_FAILURE;
+ outarg = optarg;
}
cxt->mode = c == 'p' ? LSCPU_OUTPUT_PARSABLE : LSCPU_OUTPUT_READABLE;
break;
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);
columns[ncolumns++] = COL_CACHE_PHYLINE;
columns[ncolumns++] = COL_CACHE_COHERENCYSIZE;
}
+ if (outarg && string_add_to_idarray(outarg, columns,
+ ARRAY_SIZE(columns),
+ &ncolumns, cache_column_name_to_id) < 0)
+ return EXIT_FAILURE;
+
print_caches_readable(cxt, columns, ncolumns);
break;
case LSCPU_OUTPUT_READABLE:
if (ct && ct->has_freq) {
columns[ncolumns++] = COL_CPU_MAXMHZ;
columns[ncolumns++] = COL_CPU_MINMHZ;
+ columns[ncolumns++] = COL_CPU_MHZ;
}
}
+ if (outarg && string_add_to_idarray(outarg, columns,
+ ARRAY_SIZE(columns),
+ &ncolumns, cpu_column_name_to_id) < 0)
+ return EXIT_FAILURE;
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) {
+ if (string_add_to_idarray(outarg, columns,
+ ARRAY_SIZE(columns),
+ &ncolumns, cpu_column_name_to_id) < 0)
+ return EXIT_FAILURE;
+ cxt->show_compatible = 0;
+ }
+
print_cpus_parsable(cxt, columns, ncolumns);
break;
}