]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/lib/api/fs/fs.c
tools lib api fs: Add debugfs into fs.c object
[karo-tx-linux.git] / tools / lib / api / fs / fs.c
1 #include <ctype.h>
2 #include <errno.h>
3 #include <stdbool.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/vfs.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12
13 #include "debugfs.h"
14 #include "fs.h"
15
16 #define _STR(x) #x
17 #define STR(x) _STR(x)
18
19 #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
27 #ifndef DEBUGFS_MAGIC
28 #define DEBUGFS_MAGIC          0x64626720
29 #endif
30
31 static const char * const sysfs__fs_known_mountpoints[] = {
32         "/sys",
33         0,
34 };
35
36 static const char * const procfs__known_mountpoints[] = {
37         "/proc",
38         0,
39 };
40
41 #ifndef DEBUGFS_DEFAULT_PATH
42 #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
43 #endif
44
45 static const char * const debugfs__known_mountpoints[] = {
46         DEBUGFS_DEFAULT_PATH,
47         "/debug",
48         0,
49 };
50
51 struct fs {
52         const char              *name;
53         const char * const      *mounts;
54         char                     path[PATH_MAX + 1];
55         bool                     found;
56         long                     magic;
57 };
58
59 enum {
60         FS__SYSFS   = 0,
61         FS__PROCFS  = 1,
62         FS__DEBUGFS = 2,
63 };
64
65 static struct fs fs__entries[] = {
66         [FS__SYSFS] = {
67                 .name   = "sysfs",
68                 .mounts = sysfs__fs_known_mountpoints,
69                 .magic  = SYSFS_MAGIC,
70         },
71         [FS__PROCFS] = {
72                 .name   = "proc",
73                 .mounts = procfs__known_mountpoints,
74                 .magic  = PROC_SUPER_MAGIC,
75         },
76         [FS__DEBUGFS] = {
77                 .name   = "debugfs",
78                 .mounts = debugfs__known_mountpoints,
79                 .magic  = DEBUGFS_MAGIC,
80         },
81 };
82
83 static bool fs__read_mounts(struct fs *fs)
84 {
85         bool found = false;
86         char type[100];
87         FILE *fp;
88
89         fp = fopen("/proc/mounts", "r");
90         if (fp == NULL)
91                 return NULL;
92
93         while (!found &&
94                fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
95                       fs->path, type) == 2) {
96
97                 if (strcmp(type, fs->name) == 0)
98                         found = true;
99         }
100
101         fclose(fp);
102         return fs->found = found;
103 }
104
105 static int fs__valid_mount(const char *fs, long magic)
106 {
107         struct statfs st_fs;
108
109         if (statfs(fs, &st_fs) < 0)
110                 return -ENOENT;
111         else if ((long)st_fs.f_type != magic)
112                 return -ENOENT;
113
114         return 0;
115 }
116
117 static bool fs__check_mounts(struct fs *fs)
118 {
119         const char * const *ptr;
120
121         ptr = fs->mounts;
122         while (*ptr) {
123                 if (fs__valid_mount(*ptr, fs->magic) == 0) {
124                         fs->found = true;
125                         strcpy(fs->path, *ptr);
126                         return true;
127                 }
128                 ptr++;
129         }
130
131         return false;
132 }
133
134 static void mem_toupper(char *f, size_t len)
135 {
136         while (len) {
137                 *f = toupper(*f);
138                 f++;
139                 len--;
140         }
141 }
142
143 /*
144  * Check for "NAME_PATH" environment variable to override fs location (for
145  * testing). This matches the recommendation in Documentation/sysfs-rules.txt
146  * for SYSFS_PATH.
147  */
148 static bool fs__env_override(struct fs *fs)
149 {
150         char *override_path;
151         size_t name_len = strlen(fs->name);
152         /* name + "_PATH" + '\0' */
153         char upper_name[name_len + 5 + 1];
154         memcpy(upper_name, fs->name, name_len);
155         mem_toupper(upper_name, name_len);
156         strcpy(&upper_name[name_len], "_PATH");
157
158         override_path = getenv(upper_name);
159         if (!override_path)
160                 return false;
161
162         fs->found = true;
163         strncpy(fs->path, override_path, sizeof(fs->path));
164         return true;
165 }
166
167 static const char *fs__get_mountpoint(struct fs *fs)
168 {
169         if (fs__env_override(fs))
170                 return fs->path;
171
172         if (fs__check_mounts(fs))
173                 return fs->path;
174
175         if (fs__read_mounts(fs))
176                 return fs->path;
177
178         return NULL;
179 }
180
181 static const char *fs__mountpoint(int idx)
182 {
183         struct fs *fs = &fs__entries[idx];
184
185         if (fs->found)
186                 return (const char *)fs->path;
187
188         return fs__get_mountpoint(fs);
189 }
190
191 #define FS__MOUNTPOINT(name, idx)       \
192 const char *name##__mountpoint(void)    \
193 {                                       \
194         return fs__mountpoint(idx);     \
195 }
196
197 FS__MOUNTPOINT(sysfs,   FS__SYSFS);
198 FS__MOUNTPOINT(procfs,  FS__PROCFS);
199 FS__MOUNTPOINT(debugfs, FS__DEBUGFS);
200
201 int filename__read_int(const char *filename, int *value)
202 {
203         char line[64];
204         int fd = open(filename, O_RDONLY), err = -1;
205
206         if (fd < 0)
207                 return -1;
208
209         if (read(fd, line, sizeof(line)) > 0) {
210                 *value = atoi(line);
211                 err = 0;
212         }
213
214         close(fd);
215         return err;
216 }
217
218 int sysctl__read_int(const char *sysctl, int *value)
219 {
220         char path[PATH_MAX];
221         const char *procfs = procfs__mountpoint();
222
223         if (!procfs)
224                 return -1;
225
226         snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl);
227
228         return filename__read_int(path, value);
229 }