]> arthur.barton.de Git - netdata.git/blob - src/proc_self_mountinfo.c
code cleanup by replacing all memory allocation functions with ones that handle excep...
[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                 *minor = '\0';
156                 minor++;
157
158                 mi->major = strtoul(major, NULL, 10);
159                 mi->minor = strtoul(minor, NULL, 10);
160
161                 mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
162                 mi->root_hash = simple_hash(mi->root);
163
164                 mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
165                 mi->mount_point_hash = simple_hash(mi->mount_point);
166
167                 mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
168
169                 // count the optional fields
170 /*
171                 unsigned long wo = w;
172 */
173                 mi->optional_fields_count = 0;
174                 char *s = procfile_lineword(ff, l, w);
175                 while(*s && *s != '-') {
176                         w++;
177                         s = procfile_lineword(ff, l, w);
178                         mi->optional_fields_count++;
179                 }
180
181 /*
182                 if(unlikely(mi->optional_fields_count)) {
183                         // we have some optional fields
184                         // read them into a new array of pointers;
185
186                         mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
187                         if(unlikely(!mi->optional_fields))
188                                 fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
189
190                         int i;
191                         for(i = 0; i < mi->optional_fields_count ; i++) {
192                                 *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
193                                 if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
194                                 wo++;
195                         }
196                 }
197                 else
198                         mi->optional_fields = NULL;
199 */
200
201                 if(likely(*s == '-')) {
202                         w++;
203
204                         mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++;
205                         mi->filesystem_hash = simple_hash(mi->filesystem);
206
207                         mi->mount_source = strdupz(procfile_lineword(ff, l, w)); w++;
208                         mi->mount_source_hash = simple_hash(mi->mount_source);
209
210                         mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
211                 }
212                 else {
213                         mi->filesystem = NULL;
214                         mi->mount_source = NULL;
215                         mi->super_options = NULL;
216                 }
217
218 /*
219                 info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
220                      mi->id,
221                      mi->parentid,
222                      mi->major,
223                      mi->minor,
224                      mi->root,
225                      mi->mount_point,
226                      mi->mount_options,
227                      mi->filesystem,
228                      mi->mount_source,
229                      mi->super_options
230                 );
231 */
232         }
233
234         procfile_close(ff);
235         return root;
236 }