Files
s390-tools/cpumf/chcpumf.c
Szabina Korbai 95290562e0 cpumf: Implement zsh and bash autocompletion
Add autocompletion script generation for the cpumf
family of tools (chcpumf, lscpumf, lshwc, lspai, pai)

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-12-10 14:40:52 +01:00

159 lines
3.1 KiB
C

/*
* chcpumf - Change CPU Measurement Facility Characteristics
*
* 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 <err.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "lib/libcpumf.h"
#include "lib/util_opt.h"
#include "lib/util_path.h"
#include "lib/util_prg.h"
#include "chcpumf_cli.h"
static unsigned int verbose;
static unsigned long min_sdb, max_sdb;
static const struct util_prg prg = {
.desc = "Change CPU Measurement facility charactertics",
.copyright_vec = {
{
.owner = "IBM Corp.",
.pub_first = 2020,
.pub_last = 2020,
},
UTIL_PRG_COPYRIGHT_END
}
};
static long parse_buffersize(char *string)
{
char *suffix;
long bytes;
bytes = strtol(string, &suffix, 10);
if (strlen(suffix) > 1)
return -1;
switch (*suffix) {
case 'k':
case 'K':
bytes *= 1024;
break;
case 'm':
case 'M':
bytes *= 1048576;
break;
case '\0':
break;
default:
return 0;
}
return bytes;
}
static int write_sfb(unsigned int min, unsigned int max)
{
int rc = EXIT_SUCCESS;
char text[64], *path;
size_t len;
FILE *fp;
path = util_path_sysfs(S390_CPUMSF_BUFFERSZ);
fp = fopen(path, "w");
if (!fp)
err(EXIT_FAILURE, "%s", path);
snprintf(text, sizeof(text), "%u,%u", min, max);
len = strlen(text) + 1;
if (fwrite(text, 1, len, fp) != len) {
warn("%s", path);
rc = EXIT_FAILURE;
}
if (fclose(fp)) {
warn("%s", path);
rc = EXIT_FAILURE;
}
if (verbose && rc != EXIT_FAILURE)
warnx("Sampling buffer sizes:\n"
" Minimum:%7d sample-data-blocks\n"
" Maximum:%7d sample-data-blocks\n",
min, max);
free(path);
return rc;
}
static int parse_args(int argc, char **argv)
{
int opt, action = 0;
long new;
while ((opt = util_opt_getopt_long(argc, argv)) != -1) {
switch (opt) {
case 'h':
util_prg_print_help();
util_opt_print_help();
exit(EXIT_SUCCESS);
case 'v':
util_prg_print_version();
exit(EXIT_SUCCESS);
case 'x':
new = parse_buffersize(optarg);
if (new < 1)
errx(EXIT_FAILURE,
"The specified number(s) are not valid");
max_sdb = new;
action = 1;
break;
case 'm':
new = parse_buffersize(optarg);
if (new < 1)
errx(EXIT_FAILURE,
"The specified number(s) are not valid");
min_sdb = new;
action = 1;
break;
case 'V':
verbose = 1;
break;
default:
util_opt_print_parse_error(opt, argv);
exit(EXIT_FAILURE);
}
}
if (!action)
errx(EXIT_FAILURE, "You must specify a valid option");
return action;
}
int main(int argc, char **argv)
{
unsigned long my_min, my_max;
util_prg_init(&prg);
util_opt_init(chcpumf_opt_vec, NULL);
parse_args(argc, argv);
if (geteuid())
errx(EXIT_FAILURE, "Must run as root");
if (!libcpumf_have_sfb())
errx(EXIT_FAILURE,
"No CPU-measurement sampling facility detected");
libcpumf_sfb_info(&my_min, &my_max);
if (!min_sdb)
min_sdb = my_min;
if (!max_sdb)
max_sdb = my_max;
return write_sfb(min_sdb, max_sdb);
}