]> arthur.barton.de Git - netdata.git/blob - src/proc_self_mountinfo.c
registry folder will be forced
[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     freez(mi->root);
73     freez(mi->mount_point);
74     freez(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     freez(mi->filesystem);
85     freez(mi->mount_source);
86     freez(mi->super_options);
87     freez(mi);
88 }
89
90 static char *strdupz_decoding_octal(const char *string) {
91     char *buffer = strdupz(string);
92
93     char *d = buffer;
94     const char *s = string;
95
96     while(*s) {
97         if(unlikely(*s == '\\')) {
98             s++;
99             if(likely(isdigit(*s) && isdigit(s[1]) && isdigit(s[2]))) {
100                 char c = *s++ - '0';
101                 c <<= 3;
102                 c |= *s++ - '0';
103                 c <<= 3;
104                 c |= *s++ - '0';
105                 *d++ = c;
106             }
107             else *d++ = '_';
108         }
109         else *d++ = *s++;
110     }
111     *d = '\0';
112
113     return buffer;
114 }
115
116 // read the whole mountinfo into a linked list
117 struct mountinfo *mountinfo_read() {
118     procfile *ff = NULL;
119
120     char filename[FILENAME_MAX + 1];
121     snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix);
122     ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
123     if(!ff) {
124         snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix);
125         ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
126         if(!ff) return NULL;
127     }
128
129     ff = procfile_readall(ff);
130     if(!ff) return NULL;
131
132     struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
133
134     unsigned long l, lines = procfile_lines(ff);
135     for(l = 0; l < lines ;l++) {
136         if(procfile_linewords(ff, l) < 5)
137             continue;
138
139         mi = mallocz(sizeof(struct mountinfo));
140
141         if(unlikely(!root))
142             root = last = mi;
143         else
144             last->next = mi;
145
146         last = mi;
147         mi->next = NULL;
148
149         unsigned long w = 0;
150         mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
151         mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
152
153         char *major = procfile_lineword(ff, l, w), *minor; w++;
154         for(minor = major; *minor && *minor != ':' ;minor++) ;
155
156         if(!*minor) {
157             error("Cannot parse major:minor on '%s' at line %lu of '%s'", major, l + 1, filename);
158             continue;
159         }
160
161         *minor = '\0';
162         minor++;
163
164         mi->major = strtoul(major, NULL, 10);
165         mi->minor = strtoul(minor, NULL, 10);
166
167         mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
168         mi->root_hash = simple_hash(mi->root);
169
170         mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
171         mi->mount_point_hash = simple_hash(mi->mount_point);
172
173         mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
174
175         // count the optional fields
176 /*
177         unsigned long wo = w;
178 */
179         mi->optional_fields_count = 0;
180         char *s = procfile_lineword(ff, l, w);
181         while(*s && *s != '-') {
182             w++;
183             s = procfile_lineword(ff, l, w);
184             mi->optional_fields_count++;
185         }
186
187 /*
188         if(unlikely(mi->optional_fields_count)) {
189             // we have some optional fields
190             // read them into a new array of pointers;
191
192             mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
193             if(unlikely(!mi->optional_fields))
194                 fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
195
196             int i;
197             for(i = 0; i < mi->optional_fields_count ; i++) {
198                 *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
199                 if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
200                 wo++;
201             }
202         }
203         else
204             mi->optional_fields = NULL;
205 */
206
207         if(likely(*s == '-')) {
208             w++;
209
210             mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++;
211             mi->filesystem_hash = simple_hash(mi->filesystem);
212
213             mi->mount_source = strdupz(procfile_lineword(ff, l, w)); w++;
214             mi->mount_source_hash = simple_hash(mi->mount_source);
215
216             mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
217         }
218         else {
219             mi->filesystem = NULL;
220             mi->mount_source = NULL;
221             mi->super_options = NULL;
222         }
223
224 /*
225         info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
226              mi->id,
227              mi->parentid,
228              mi->major,
229              mi->minor,
230              mi->root,
231              mi->mount_point,
232              mi->mount_options,
233              mi->filesystem,
234              mi->mount_source,
235              mi->super_options
236         );
237 */
238     }
239
240     procfile_close(ff);
241     return root;
242 }