1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef _USER_EVENTS_SELFTESTS_H
4#define _USER_EVENTS_SELFTESTS_H
5
6#include <sys/stat.h>
7#include <sys/types.h>
8#include <sys/mount.h>
9#include <unistd.h>
10#include <errno.h>
11
12#include "../kselftest.h"
13
14static inline void tracefs_unmount(void)
15{
16	umount("/sys/kernel/tracing");
17}
18
19static inline bool tracefs_enabled(char **message, bool *fail, bool *umount)
20{
21	struct stat buf;
22	int ret;
23
24	*message = "";
25	*fail = false;
26	*umount = false;
27
28	/* Ensure tracefs is installed */
29	ret = stat("/sys/kernel/tracing", &buf);
30
31	if (ret == -1) {
32		*message = "Tracefs is not installed";
33		return false;
34	}
35
36	/* Ensure mounted tracefs */
37	ret = stat("/sys/kernel/tracing/README", &buf);
38
39	if (ret == -1 && errno == ENOENT) {
40		if (mount(NULL, "/sys/kernel/tracing", "tracefs", 0, NULL) != 0) {
41			*message = "Cannot mount tracefs";
42			*fail = true;
43			return false;
44		}
45
46		*umount = true;
47
48		ret = stat("/sys/kernel/tracing/README", &buf);
49	}
50
51	if (ret == -1) {
52		*message = "Cannot access tracefs";
53		*fail = true;
54		return false;
55	}
56
57	return true;
58}
59
60static inline bool user_events_enabled(char **message, bool *fail, bool *umount)
61{
62	struct stat buf;
63	int ret;
64
65	*message = "";
66	*fail = false;
67	*umount = false;
68
69	if (getuid() != 0) {
70		*message = "Must be run as root";
71		*fail = true;
72		return false;
73	}
74
75	if (!tracefs_enabled(message, fail, umount))
76		return false;
77
78	/* Ensure user_events is installed */
79	ret = stat("/sys/kernel/tracing/user_events_data", &buf);
80
81	if (ret == -1) {
82		switch (errno) {
83		case ENOENT:
84			*message = "user_events is not installed";
85			return false;
86
87		default:
88			*message = "Cannot access user_events_data";
89			*fail = true;
90			return false;
91		}
92	}
93
94	return true;
95}
96
97#define USER_EVENT_FIXTURE_SETUP(statement, umount) do { \
98	char *message; \
99	bool fail; \
100	if (!user_events_enabled(&message, &fail, &(umount))) { \
101		if (fail) { \
102			TH_LOG("Setup failed due to: %s", message); \
103			ASSERT_FALSE(fail); \
104		} \
105		SKIP(statement, "Skipping due to: %s", message); \
106	} \
107} while (0)
108
109#define USER_EVENT_FIXTURE_TEARDOWN(umount) do { \
110	if ((umount))  \
111		tracefs_unmount(); \
112} while (0)
113
114#endif /* _USER_EVENTS_SELFTESTS_H */
115