]> arthur.barton.de Git - netdata.git/blob - src/proc_self_mountinfo.c
all required system headers in common.h; some progress on health variables
[netdata.git] / src / proc_self_mountinfo.c
1 #include "common.h"
2
3 // find the mount info with the given major:minor
4 // in the supplied linked list of mountinfo structures
5 struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor) {
6         struct mountinfo *mi;
7
8         for(mi = root; mi ; mi = mi->next)
9                 if(mi->major == major && mi->minor == minor)
10                         return mi;
11
12         return NULL;
13 }
14
15 // find the mount info with the given filesystem and mount_source
16 // in the supplied linked list of mountinfo structures
17 struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *root, const char *filesystem, const char *mount_source) {
18         struct mountinfo *mi;
19         uint32_t filesystem_hash = simple_hash(filesystem), mount_source_hash = simple_hash(mount_source);
20
21         for(mi = root; mi ; mi = mi->next)
22                 if(mi->filesystem
23                                 && mi->mount_source
24                                 && mi->filesystem_hash == filesystem_hash
25                                 && mi->mount_source_hash == mount_source_hash
26                                 && !strcmp(mi->filesystem, filesystem)
27                                 && !strcmp(mi->mount_source, mount_source))
28                         return mi;
29
30         return NULL;
31 }
32
33 struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *root, const char *filesystem, const char *super_options) {
34         struct mountinfo *mi;
35         uint32_t filesystem_hash = simple_hash(filesystem);
36
37         size_t solen = strlen(super_options);
38
39         for(mi = root; mi ; mi = mi->next)
40                 if(mi->filesystem
41                                 && mi->super_options
42                                 && mi->filesystem_hash == filesystem_hash
43                                 && !strcmp(mi->filesystem, filesystem)) {
44
45                         // super_options is a comma separated list
46                         char *s = mi->super_options, *e;
47                         while(*s) {
48                                 e = s + 1;
49                                 while(*e && *e != ',') e++;
50
51                                 size_t len = e - s;
52                                 if(len == solen && !strncmp(s, super_options, len))
53                                         return mi;
54
55                                 if(*e == ',') s = ++e;
56                                 else s = e;
57                         }
58                 }
59
60         return NULL;
61 }
62
63
64 // free a linked list of mountinfo structures
65 void mountinfo_free(struct mountinfo *mi) {
66         if(unlikely(!mi))
67                 return;
68
69         if(likely(mi->next))
70                 mountinfo_free(mi->next);
71
72         if(mi->root) free(mi->root);
73         if(mi->mount_point) free(mi->mount_point);
74         if(mi->mount_options) free(mi->mount_options);
75
76 /*
77         if(mi->optional_fields_count) {
78                 int i;
79                 for(i = 0; i < mi->optional_fields_count ; i++)
80                         free(*mi->optional_fields[i]);
81         }
82         free(mi->optional_fields);
83 */
84         free(mi->filesystem);
85         free(mi->mount_source);
86         free(mi->super_options);
87         free(mi);
88 }
89
90 static char *strdup_decoding_octal(const char *string) {
91         char *buffer = strdup(string);
92         if(!buffer) fatal("Cannot allocate memory.");
93
94         char *d = buffer;
95         const char *s = string;
96
97         while(*s) {
98                 if(unlikely(*s == '\\')) {
99                         s++;
100                         if(likely(isdigit(*s) && isdigit(s[1]) && isdigit(s[2]))) {
101                                 char c = *s++ - '0';
102                                 c <<= 3;
103                                 c |= *s++ - '0';
104                                 c <<= 3;
105                                 c |= *s++ - '0';
106                                 *d++ = c;
107                         }
108                         else *d++ = '_';
109                 }
110                 else *d++ = *s++;
111         }
112         *d = '\0';
113
114         return buffer;
115 }
116
117 // read the whole mountinfo into a linked list
118 struct mountinfo *mountinfo_read() {
119         procfile *ff = NULL;
120
121         char filename[FILENAME_MAX + 1];
122         snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix);
123         ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
124         if(!ff) {
125                 snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix);
126                 ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
127                 if(!ff) return NULL;
128         }
129
130         ff = procfile_readall(ff);
131         if(!ff) return NULL;
132
133         struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
134
135         unsigned long l, lines = procfile_lines(ff);
136         for(l = 0; l < lines ;l++) {
137                 if(procfile_linewords(ff, l) < 5)
138                         continue;
139
140                 mi = malloc(sizeof(struct mountinfo));
141                 if(unlikely(!mi)) fatal("Cannot allocate memory for mountinfo");
142
143                 if(unlikely(!root))
144                         root = last = mi;
145                 else
146                         last->next = mi;
147
148                 last = mi;
149                 mi->next = NULL;
150
151                 unsigned long w = 0;
152                 mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
153                 mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
154
155                 char *major = procfile_lineword(ff, l, w), *minor; w++;
156                 for(minor = major; *minor && *minor != ':' ;minor++) ;
157                 *minor = '\0';
158                 minor++;
159
160                 mi->major = strtoul(major, NULL, 10);
161                 mi->minor = strtoul(minor, NULL, 10);
162
163                 mi->root = strdup(procfile_lineword(ff, l, w)); w++;
164                 if(unlikely(!mi->root)) fatal("Cannot allocate memory");
165                 mi->root_hash = simple_hash(mi->root);
166
167                 mi->mount_point = strdup_decoding_octal(procfile_lineword(ff, l, w)); w++;
168                 if(unlikely(!mi->mount_point)) fatal("Cannot allocate memory");
169                 mi->mount_point_hash = simple_hash(mi->mount_point);
170
171                 mi->mount_options = strdup(procfile_lineword(ff, l, w)); w++;
172                 if(unlikely(!mi->mount_options)) fatal("Cannot allocate memory");
173
174                 // count the optional fields
175 /*
176                 unsigned long wo = w;
177 */
178                 mi->optional_fields_count = 0;
179                 char *s = procfile_lineword(ff, l, w);
180                 while(*s && *s != '-') {
181                         w++;
182                         s = procfile_lineword(ff, l, w);
183                         mi->optional_fields_count++;
184                 }
185
186 /*
187                 if(unlikely(mi->optional_fields_count)) {
188                         // we have some optional fields
189                         // read them into a new array of pointers;
190
191                         mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
192                         if(unlikely(!mi->optional_fields))
193                                 fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
194
195                         int i;
196                         for(i = 0; i < mi->optional_fields_count ; i++) {
197                                 *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
198                                 if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
199                                 wo++;
200                         }
201                 }
202                 else
203                         mi->optional_fields = NULL;
204 */
205
206                 if(likely(*s == '-')) {
207                         w++;
208
209                         mi->filesystem = strdup(procfile_lineword(ff, l, w)); w++;
210                         if(!mi->filesystem) fatal("Cannot allocate memory");
211                         mi->filesystem_hash = simple_hash(mi->filesystem);
212
213                         mi->mount_source = strdup(procfile_lineword(ff, l, w)); w++;
214                         if(!mi->mount_source) fatal("Cannot allocate memory");
215                         mi->mount_source_hash = simple_hash(mi->mount_source);
216
217                         mi->super_options = strdup(procfile_lineword(ff, l, w)); w++;
218                         if(!mi->super_options) fatal("Cannot allocate memory");
219                 }
220                 else {
221                         mi->filesystem = NULL;
222                         mi->mount_source = NULL;
223                         mi->super_options = NULL;
224                 }
225
226 /*
227                 info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
228                      mi->id,
229                      mi->parentid,
230                      mi->major,
231                      mi->minor,
232                      mi->root,
233                      mi->mount_point,
234                      mi->mount_options,
235                      mi->filesystem,
236                      mi->mount_source,
237                      mi->super_options
238                 );
239 */
240         }
241
242         procfile_close(ff);
243         return root;
244 }