blob: ef16d2a83a27626a18d6e07f78ac9074e6f380e9 [file] [log] [blame]
Cody P Schaferf2d96272014-05-27 17:21:56 -07001#include <ctype.h>
Borislav Petkovcd0cfad2013-12-09 17:14:24 +01002#include <errno.h>
3#include <stdbool.h>
4#include <stdio.h>
Cody P Schaferf2d96272014-05-27 17:21:56 -07005#include <stdlib.h>
Borislav Petkovcd0cfad2013-12-09 17:14:24 +01006#include <string.h>
7#include <sys/vfs.h>
Arnaldo Carvalho de Melo3a351122014-12-11 13:17:46 -03008#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <unistd.h>
Jiri Olsa4299a542013-11-05 15:14:45 +010012
Borislav Petkovcd0cfad2013-12-09 17:14:24 +010013#include "debugfs.h"
14#include "fs.h"
Jiri Olsa4299a542013-11-05 15:14:45 +010015
Jiri Olsab86b0d32015-09-02 09:56:37 +020016#define _STR(x) #x
17#define STR(x) _STR(x)
18
Jiri Olsa41e3a1f2015-09-02 09:56:38 +020019#ifndef SYSFS_MAGIC
20#define SYSFS_MAGIC 0x62656572
21#endif
22
23#ifndef PROC_SUPER_MAGIC
24#define PROC_SUPER_MAGIC 0x9fa0
25#endif
26
Jiri Olsa8ccfabd2015-09-02 09:56:39 +020027#ifndef DEBUGFS_MAGIC
28#define DEBUGFS_MAGIC 0x64626720
29#endif
30
Jiri Olsac495afb42015-09-02 09:56:40 +020031#ifndef TRACEFS_MAGIC
32#define TRACEFS_MAGIC 0x74726163
33#endif
34
Jiri Olsa4299a542013-11-05 15:14:45 +010035static const char * const sysfs__fs_known_mountpoints[] = {
36 "/sys",
37 0,
38};
39
Jiri Olsaa9862412013-11-05 15:14:46 +010040static const char * const procfs__known_mountpoints[] = {
41 "/proc",
42 0,
43};
44
Jiri Olsa8ccfabd2015-09-02 09:56:39 +020045#ifndef DEBUGFS_DEFAULT_PATH
46#define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
47#endif
48
49static const char * const debugfs__known_mountpoints[] = {
50 DEBUGFS_DEFAULT_PATH,
51 "/debug",
52 0,
53};
54
Jiri Olsac495afb42015-09-02 09:56:40 +020055
56#ifndef TRACEFS_DEFAULT_PATH
57#define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
58#endif
59
60static const char * const tracefs__known_mountpoints[] = {
61 TRACEFS_DEFAULT_PATH,
62 "/sys/kernel/debug/tracing",
63 "/tracing",
64 "/trace",
65 0,
66};
67
Jiri Olsa4299a542013-11-05 15:14:45 +010068struct fs {
69 const char *name;
70 const char * const *mounts;
71 char path[PATH_MAX + 1];
72 bool found;
73 long magic;
74};
75
76enum {
Jiri Olsa8ccfabd2015-09-02 09:56:39 +020077 FS__SYSFS = 0,
78 FS__PROCFS = 1,
79 FS__DEBUGFS = 2,
Jiri Olsac495afb42015-09-02 09:56:40 +020080 FS__TRACEFS = 3,
Jiri Olsa4299a542013-11-05 15:14:45 +010081};
82
Jiri Olsac495afb42015-09-02 09:56:40 +020083#ifndef TRACEFS_MAGIC
84#define TRACEFS_MAGIC 0x74726163
85#endif
86
Jiri Olsa4299a542013-11-05 15:14:45 +010087static struct fs fs__entries[] = {
88 [FS__SYSFS] = {
89 .name = "sysfs",
90 .mounts = sysfs__fs_known_mountpoints,
91 .magic = SYSFS_MAGIC,
92 },
Jiri Olsaa9862412013-11-05 15:14:46 +010093 [FS__PROCFS] = {
94 .name = "proc",
95 .mounts = procfs__known_mountpoints,
96 .magic = PROC_SUPER_MAGIC,
97 },
Jiri Olsa8ccfabd2015-09-02 09:56:39 +020098 [FS__DEBUGFS] = {
99 .name = "debugfs",
100 .mounts = debugfs__known_mountpoints,
101 .magic = DEBUGFS_MAGIC,
102 },
Jiri Olsac495afb42015-09-02 09:56:40 +0200103 [FS__TRACEFS] = {
104 .name = "tracefs",
105 .mounts = tracefs__known_mountpoints,
106 .magic = TRACEFS_MAGIC,
107 },
Jiri Olsa4299a542013-11-05 15:14:45 +0100108};
109
110static bool fs__read_mounts(struct fs *fs)
111{
112 bool found = false;
113 char type[100];
114 FILE *fp;
115
116 fp = fopen("/proc/mounts", "r");
117 if (fp == NULL)
118 return NULL;
119
120 while (!found &&
121 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
122 fs->path, type) == 2) {
123
124 if (strcmp(type, fs->name) == 0)
125 found = true;
126 }
127
128 fclose(fp);
129 return fs->found = found;
130}
131
132static int fs__valid_mount(const char *fs, long magic)
133{
134 struct statfs st_fs;
135
136 if (statfs(fs, &st_fs) < 0)
137 return -ENOENT;
Alexey Brodkindb1806e2015-01-10 16:40:50 +0530138 else if ((long)st_fs.f_type != magic)
Jiri Olsa4299a542013-11-05 15:14:45 +0100139 return -ENOENT;
140
141 return 0;
142}
143
144static bool fs__check_mounts(struct fs *fs)
145{
146 const char * const *ptr;
147
148 ptr = fs->mounts;
149 while (*ptr) {
150 if (fs__valid_mount(*ptr, fs->magic) == 0) {
151 fs->found = true;
152 strcpy(fs->path, *ptr);
153 return true;
154 }
155 ptr++;
156 }
157
158 return false;
159}
160
Cody P Schaferf2d96272014-05-27 17:21:56 -0700161static void mem_toupper(char *f, size_t len)
162{
163 while (len) {
164 *f = toupper(*f);
165 f++;
166 len--;
167 }
168}
169
170/*
171 * Check for "NAME_PATH" environment variable to override fs location (for
172 * testing). This matches the recommendation in Documentation/sysfs-rules.txt
173 * for SYSFS_PATH.
174 */
175static bool fs__env_override(struct fs *fs)
176{
177 char *override_path;
178 size_t name_len = strlen(fs->name);
179 /* name + "_PATH" + '\0' */
180 char upper_name[name_len + 5 + 1];
181 memcpy(upper_name, fs->name, name_len);
182 mem_toupper(upper_name, name_len);
183 strcpy(&upper_name[name_len], "_PATH");
184
185 override_path = getenv(upper_name);
186 if (!override_path)
187 return false;
188
189 fs->found = true;
190 strncpy(fs->path, override_path, sizeof(fs->path));
191 return true;
192}
193
Jiri Olsa4299a542013-11-05 15:14:45 +0100194static const char *fs__get_mountpoint(struct fs *fs)
195{
Cody P Schaferf2d96272014-05-27 17:21:56 -0700196 if (fs__env_override(fs))
197 return fs->path;
198
Jiri Olsa4299a542013-11-05 15:14:45 +0100199 if (fs__check_mounts(fs))
200 return fs->path;
201
Cody P Schaferf2d96272014-05-27 17:21:56 -0700202 if (fs__read_mounts(fs))
203 return fs->path;
204
205 return NULL;
Jiri Olsa4299a542013-11-05 15:14:45 +0100206}
207
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300208static const char *fs__mountpoint(int idx)
Jiri Olsa4299a542013-11-05 15:14:45 +0100209{
210 struct fs *fs = &fs__entries[idx];
211
212 if (fs->found)
213 return (const char *)fs->path;
214
215 return fs__get_mountpoint(fs);
216}
217
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300218#define FS__MOUNTPOINT(name, idx) \
219const char *name##__mountpoint(void) \
220{ \
221 return fs__mountpoint(idx); \
Jiri Olsa4299a542013-11-05 15:14:45 +0100222}
223
Jiri Olsa8ccfabd2015-09-02 09:56:39 +0200224FS__MOUNTPOINT(sysfs, FS__SYSFS);
225FS__MOUNTPOINT(procfs, FS__PROCFS);
226FS__MOUNTPOINT(debugfs, FS__DEBUGFS);
Jiri Olsac495afb42015-09-02 09:56:40 +0200227FS__MOUNTPOINT(tracefs, FS__TRACEFS);
Arnaldo Carvalho de Melo3a351122014-12-11 13:17:46 -0300228
229int filename__read_int(const char *filename, int *value)
230{
231 char line[64];
232 int fd = open(filename, O_RDONLY), err = -1;
233
234 if (fd < 0)
235 return -1;
236
237 if (read(fd, line, sizeof(line)) > 0) {
238 *value = atoi(line);
239 err = 0;
240 }
241
242 close(fd);
243 return err;
244}
Arnaldo Carvalho de Melo42e3c4a2014-12-11 13:37:10 -0300245
246int sysctl__read_int(const char *sysctl, int *value)
247{
248 char path[PATH_MAX];
249 const char *procfs = procfs__mountpoint();
250
251 if (!procfs)
252 return -1;
253
254 snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl);
255
256 return filename__read_int(path, value);
257}