tools: bpftool: fix reading from /proc/config.gz
/proc/config has never existed as far as I can see, but /proc/config.gz is present on Arch Linux. Add support for decompressing config.gz using zlib which is a mandatory dependency of libelf anyway. Replace existing stdio functions with gzFile operations since the latter transparently handles uncompressed and gzip-compressed files. Cc: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: Peter Wu <peter@lekensteyn.nl> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
9f30cd568b
commit
a664a83457
|
@ -52,7 +52,7 @@ ifneq ($(EXTRA_LDFLAGS),)
|
||||||
LDFLAGS += $(EXTRA_LDFLAGS)
|
LDFLAGS += $(EXTRA_LDFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBS = -lelf $(LIBBPF)
|
LIBS = -lelf -lz $(LIBBPF)
|
||||||
|
|
||||||
INSTALL ?= install
|
INSTALL ?= install
|
||||||
RM ?= rm -f
|
RM ?= rm -f
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <bpf.h>
|
#include <bpf.h>
|
||||||
#include <libbpf.h>
|
#include <libbpf.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
@ -284,34 +285,32 @@ static void probe_jit_limit(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_kernel_config_option(FILE *fd, const char *option)
|
static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n,
|
||||||
|
char **value)
|
||||||
{
|
{
|
||||||
size_t line_n = 0, optlen = strlen(option);
|
char *sep;
|
||||||
char *res, *strval, *line = NULL;
|
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
rewind(fd);
|
while (gzgets(file, buf, n)) {
|
||||||
while ((n = getline(&line, &line_n, fd)) > 0) {
|
if (strncmp(buf, "CONFIG_", 7))
|
||||||
if (strncmp(line, option, optlen))
|
|
||||||
continue;
|
continue;
|
||||||
/* Check we have at least '=', value, and '\n' */
|
|
||||||
if (strlen(line) < optlen + 3)
|
sep = strchr(buf, '=');
|
||||||
continue;
|
if (!sep)
|
||||||
if (*(line + optlen) != '=')
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Trim ending '\n' */
|
/* Trim ending '\n' */
|
||||||
line[strlen(line) - 1] = '\0';
|
buf[strlen(buf) - 1] = '\0';
|
||||||
|
|
||||||
/* Copy and return config option value */
|
/* Split on '=' and ensure that a value is present. */
|
||||||
strval = line + optlen + 1;
|
*sep = '\0';
|
||||||
res = strdup(strval);
|
if (!sep[1])
|
||||||
free(line);
|
continue;
|
||||||
return res;
|
|
||||||
|
*value = sep + 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
free(line);
|
|
||||||
|
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void probe_kernel_image_config(void)
|
static void probe_kernel_image_config(void)
|
||||||
|
@ -386,59 +385,61 @@ static void probe_kernel_image_config(void)
|
||||||
/* test_bpf module for BPF tests */
|
/* test_bpf module for BPF tests */
|
||||||
"CONFIG_TEST_BPF",
|
"CONFIG_TEST_BPF",
|
||||||
};
|
};
|
||||||
char *value, *buf = NULL;
|
char *values[ARRAY_SIZE(options)] = { };
|
||||||
struct utsname utsn;
|
struct utsname utsn;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
size_t i, n;
|
gzFile file = NULL;
|
||||||
ssize_t ret;
|
char buf[4096];
|
||||||
FILE *fd;
|
char *value;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (uname(&utsn))
|
if (!uname(&utsn)) {
|
||||||
goto no_config;
|
snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
|
/* gzopen also accepts uncompressed files. */
|
||||||
|
file = gzopen(path, "r");
|
||||||
fd = fopen(path, "r");
|
|
||||||
if (!fd && errno == ENOENT) {
|
|
||||||
/* Some distributions put the config file at /proc/config, give
|
|
||||||
* it a try.
|
|
||||||
* Sometimes it is also at /proc/config.gz but we do not try
|
|
||||||
* this one for now, it would require linking against libz.
|
|
||||||
*/
|
|
||||||
fd = fopen("/proc/config", "r");
|
|
||||||
}
|
}
|
||||||
if (!fd) {
|
|
||||||
|
if (!file) {
|
||||||
|
/* Some distributions build with CONFIG_IKCONFIG=y and put the
|
||||||
|
* config file at /proc/config.gz.
|
||||||
|
*/
|
||||||
|
file = gzopen("/proc/config.gz", "r");
|
||||||
|
}
|
||||||
|
if (!file) {
|
||||||
p_info("skipping kernel config, can't open file: %s",
|
p_info("skipping kernel config, can't open file: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto no_config;
|
goto end_parse;
|
||||||
}
|
}
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
ret = getline(&buf, &n, fd);
|
if (!gzgets(file, buf, sizeof(buf)) ||
|
||||||
ret = getline(&buf, &n, fd);
|
!gzgets(file, buf, sizeof(buf))) {
|
||||||
if (!buf || !ret) {
|
|
||||||
p_info("skipping kernel config, can't read from file: %s",
|
p_info("skipping kernel config, can't read from file: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
free(buf);
|
goto end_parse;
|
||||||
goto no_config;
|
|
||||||
}
|
}
|
||||||
if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
|
if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
|
||||||
p_info("skipping kernel config, can't find correct file");
|
p_info("skipping kernel config, can't find correct file");
|
||||||
free(buf);
|
goto end_parse;
|
||||||
goto no_config;
|
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
|
while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) {
|
||||||
|
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
||||||
|
if (values[i] || strcmp(buf, options[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
values[i] = strdup(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end_parse:
|
||||||
|
if (file)
|
||||||
|
gzclose(file);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
||||||
value = get_kernel_config_option(fd, options[i]);
|
print_kernel_option(options[i], values[i]);
|
||||||
print_kernel_option(options[i], value);
|
free(values[i]);
|
||||||
free(value);
|
|
||||||
}
|
}
|
||||||
fclose(fd);
|
|
||||||
return;
|
|
||||||
|
|
||||||
no_config:
|
|
||||||
for (i = 0; i < ARRAY_SIZE(options); i++)
|
|
||||||
print_kernel_option(options[i], NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool probe_bpf_syscall(const char *define_prefix)
|
static bool probe_bpf_syscall(const char *define_prefix)
|
||||||
|
|
Loading…
Reference in New Issue