xref: /linux/tools/testing/selftests/bpf/bpftool_helpers.c (revision f17b474e36647c23801ef8fdaf2255ab66dd2973)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include "bpftool_helpers.h"
3 #include <unistd.h>
4 #include <string.h>
5 #include <stdbool.h>
6 
7 #define BPFTOOL_PATH_MAX_LEN		64
8 #define BPFTOOL_FULL_CMD_MAX_LEN	512
9 
10 #define BPFTOOL_DEFAULT_PATH		"tools/sbin/bpftool"
11 
12 static int detect_bpftool_path(char *buffer)
13 {
14 	char tmp[BPFTOOL_PATH_MAX_LEN];
15 
16 	/* Check default bpftool location (will work if we are running the
17 	 * default flavor of test_progs)
18 	 */
19 	snprintf(tmp, BPFTOOL_PATH_MAX_LEN, "./%s", BPFTOOL_DEFAULT_PATH);
20 	if (access(tmp, X_OK) == 0) {
21 		strncpy(buffer, tmp, BPFTOOL_PATH_MAX_LEN);
22 		return 0;
23 	}
24 
25 	/* Check alternate bpftool location (will work if we are running a
26 	 * specific flavor of test_progs, e.g. cpuv4 or no_alu32)
27 	 */
28 	snprintf(tmp, BPFTOOL_PATH_MAX_LEN, "../%s", BPFTOOL_DEFAULT_PATH);
29 	if (access(tmp, X_OK) == 0) {
30 		strncpy(buffer, tmp, BPFTOOL_PATH_MAX_LEN);
31 		return 0;
32 	}
33 
34 	/* Failed to find bpftool binary */
35 	return 1;
36 }
37 
38 static int run_command(char *args, char *output_buf, size_t output_max_len)
39 {
40 	static char bpftool_path[BPFTOOL_PATH_MAX_LEN] = {0};
41 	bool suppress_output = !(output_buf && output_max_len);
42 	char command[BPFTOOL_FULL_CMD_MAX_LEN];
43 	FILE *f;
44 	int ret;
45 
46 	/* Detect and cache bpftool binary location */
47 	if (bpftool_path[0] == 0 && detect_bpftool_path(bpftool_path))
48 		return 1;
49 
50 	ret = snprintf(command, BPFTOOL_FULL_CMD_MAX_LEN, "%s %s%s",
51 		       bpftool_path, args,
52 		       suppress_output ? " > /dev/null 2>&1" : "");
53 
54 	f = popen(command, "r");
55 	if (!f)
56 		return 1;
57 
58 	if (!suppress_output)
59 		fread(output_buf, 1, output_max_len, f);
60 	ret = pclose(f);
61 
62 	return ret;
63 }
64 
65 int run_bpftool_command(char *args)
66 {
67 	return run_command(args, NULL, 0);
68 }
69 
70 int get_bpftool_command_output(char *args, char *output_buf, size_t output_max_len)
71 {
72 	return run_command(args, output_buf, output_max_len);
73 }
74 
75