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 
14 static inline void tracefs_unmount(void)
15 {
16 	umount("/sys/kernel/tracing");
17 }
18 
19 static 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 
60 static 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