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