xref: /linux/tools/lib/api/fs/tracing_path.c (revision 988bdb319246dea977a375beee39a5452e99b3ef)
1 #ifndef _GNU_SOURCE
2 # define _GNU_SOURCE
3 #endif
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include "debugfs.h"
11 #include "tracefs.h"
12 
13 #include "tracing_path.h"
14 
15 
16 char tracing_path[PATH_MAX + 1]        = "/sys/kernel/debug/tracing";
17 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
18 
19 
20 static void __tracing_path_set(const char *tracing, const char *mountpoint)
21 {
22 	snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
23 		 mountpoint, tracing);
24 	snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
25 		 mountpoint, tracing, "events");
26 }
27 
28 static const char *tracing_path_tracefs_mount(void)
29 {
30 	const char *mnt;
31 
32 	mnt = tracefs_mount(NULL);
33 	if (!mnt)
34 		return NULL;
35 
36 	__tracing_path_set("", mnt);
37 
38 	return mnt;
39 }
40 
41 static const char *tracing_path_debugfs_mount(void)
42 {
43 	const char *mnt;
44 
45 	mnt = debugfs_mount(NULL);
46 	if (!mnt)
47 		return NULL;
48 
49 	__tracing_path_set("tracing/", mnt);
50 
51 	return mnt;
52 }
53 
54 const char *tracing_path_mount(void)
55 {
56 	const char *mnt;
57 
58 	mnt = tracing_path_tracefs_mount();
59 	if (mnt)
60 		return mnt;
61 
62 	mnt = tracing_path_debugfs_mount();
63 
64 	return mnt;
65 }
66 
67 void tracing_path_set(const char *mntpt)
68 {
69 	__tracing_path_set("tracing/", mntpt);
70 }
71 
72 char *get_tracing_file(const char *name)
73 {
74 	char *file;
75 
76 	if (asprintf(&file, "%s/%s", tracing_path, name) < 0)
77 		return NULL;
78 
79 	return file;
80 }
81 
82 void put_tracing_file(char *file)
83 {
84 	free(file);
85 }
86 
87 static int strerror_open(int err, char *buf, size_t size, const char *filename)
88 {
89 	char sbuf[128];
90 
91 	switch (err) {
92 	case ENOENT:
93 		if (debugfs_configured()) {
94 			snprintf(buf, size,
95 				 "Error:\tFile %s/%s not found.\n"
96 				 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
97 				 debugfs_mountpoint, filename);
98 			break;
99 		}
100 		snprintf(buf, size, "%s",
101 			 "Error:\tUnable to find debugfs\n"
102 			 "Hint:\tWas your kernel compiled with debugfs support?\n"
103 			 "Hint:\tIs the debugfs filesystem mounted?\n"
104 			 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
105 		break;
106 	case EACCES: {
107 		const char *mountpoint = debugfs_mountpoint;
108 
109 		if (!access(debugfs_mountpoint, R_OK) && strncmp(filename, "tracing/", 8) == 0) {
110 			const char *tracefs_mntpoint = tracefs_find_mountpoint();
111 
112 			if (tracefs_mntpoint)
113 				mountpoint = tracefs_mntpoint;
114 		}
115 
116 		snprintf(buf, size,
117 			 "Error:\tNo permissions to read %s/%s\n"
118 			 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
119 			 debugfs_mountpoint, filename, mountpoint);
120 	}
121 		break;
122 	default:
123 		snprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
124 		break;
125 	}
126 
127 	return 0;
128 }
129 
130 int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
131 {
132 	char path[PATH_MAX];
133 
134 	snprintf(path, PATH_MAX, "tracing/events/%s/%s", sys, name ?: "*");
135 
136 	return strerror_open(err, buf, size, path);
137 }
138