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