]> arthur.barton.de Git - netdata.git/blob - src/proc_self_mountinfo.c
disk now get the mount point at the menu (only when they are not partitions) #295
[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 // free a linked list of mountinfo structures
30 void mountinfo_free(struct mountinfo *mi) {
31         if(unlikely(!mi))
32                 return;
33
34         if(likely(mi->next))
35                 mountinfo_free(mi->next);
36
37         free(mi->root);
38         free(mi->mount_point);
39         free(mi->mount_options);
40
41         if(mi->optional_fields_count) {
42                 int i;
43                 for(i = 0; i < mi->optional_fields_count ; i++)
44                         free(mi->optional_fields[i]);
45         }
46         free(mi->optional_fields);
47
48         free(mi->filesystem);
49         free(mi->mount_source);
50         free(mi->super_options);
51         free(mi);
52 }
53
54 // read the whole mountinfo into a linked list
55 struct mountinfo *mountinfo_read() {
56         procfile *ff = NULL;
57
58         char filename[FILENAME_MAX + 1];
59         snprintf(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix);
60         ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
61         if(!ff) {
62                 snprintf(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix);
63                 ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
64                 if(!ff) return NULL;
65         }
66
67         ff = procfile_readall(ff);
68         if(!ff) return NULL;
69
70         struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
71
72         unsigned long l, lines = procfile_lines(ff);
73         error("MOUNTINFO: file has %u lines", lines);
74         for(l = 0; l < lines ;l++) {
75                 if(procfile_linewords(ff, l) < 5)
76                         continue;
77
78                 mi = malloc(sizeof(struct mountinfo));
79                 if(unlikely(!mi)) fatal("Cannot allocate memory for mountinfo");
80
81                 if(unlikely(!root))
82                         root = last = mi;
83                 else
84                         last->next = mi;
85
86                 last = mi;
87                 mi->next = NULL;
88
89                 unsigned long w = 0;
90                 mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
91                 mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
92
93                 char *major = procfile_lineword(ff, l, w), *minor; w++;
94                 for(minor = major; *minor && *minor != ':' ;minor++) ;
95                 *minor = '\0';
96                 minor++;
97
98                 mi->major = strtoul(major, NULL, 10);
99                 mi->minor = strtoul(minor, NULL, 10);
100
101                 mi->root = strdup(procfile_lineword(ff, l, w)); w++;
102                 if(unlikely(!mi->root)) fatal("Cannot allocate memory");
103
104                 mi->mount_point = strdup(procfile_lineword(ff, l, w)); w++;
105                 if(unlikely(!mi->mount_point)) fatal("Cannot allocate memory");
106
107                 mi->mount_options = strdup(procfile_lineword(ff, l, w)); w++;
108                 if(unlikely(!mi->mount_options)) fatal("Cannot allocate memory");
109
110                 // count the optional fields
111                 unsigned long wo = w;
112                 mi->optional_fields_count = 0;
113                 char *s = procfile_lineword(ff, l, w);
114                 while(*s && *s != '-') {
115                         w++;
116                         s = procfile_lineword(ff, l, w);
117                         mi->optional_fields_count++;
118                 }
119
120                 if(unlikely(mi->optional_fields_count)) {
121                         // we have some optional fields
122                         // read them into a new array of pointers;
123
124                         mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
125                         if(unlikely(!mi->optional_fields))
126                                 fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
127
128                         int i;
129                         for(i = 0; i < mi->optional_fields_count ; i++) {
130                                 mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
131                                 if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
132                                 wo++;
133                         }
134                 }
135                 else
136                         mi->optional_fields = NULL;
137
138                 if(likely(*s == '-')) {
139                         mi->filesystem = strdup(procfile_lineword(ff, l, w)); w++;
140                         if(!mi->filesystem) fatal("Cannot allocate memory");
141
142                         mi->mount_source = strdup(procfile_lineword(ff, l, w)); w++;
143                         if(!mi->mount_source) fatal("Cannot allocate memory");
144
145                         mi->super_options = strdup(procfile_lineword(ff, l, w)); w++;
146                         if(!mi->super_options) fatal("Cannot allocate memory");
147                 }
148                 else {
149                         mi->filesystem = NULL;
150                         mi->mount_source = NULL;
151                         mi->super_options = NULL;
152                 }
153
154                 //info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
155                 //     mi->id,
156                 //     mi->parentid,
157                 //     mi->major,
158                 //     mi->minor,
159                 //     mi->root,
160                 //     mi->mount_point,
161                 //     mi->mount_options,
162                 //     mi->filesystem,
163                 //     mi->mount_source,
164                 //     mi->super_options
165                 //);
166         }
167
168         procfile_close(ff);
169         return root;
170 }