1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "sysinfo.h"
22 #include "zbxjson.h"
23 #include "log.h"
24
get_fs_size_stat(const char * fs,zbx_uint64_t * total,zbx_uint64_t * free,zbx_uint64_t * used,double * pfree,double * pused,char ** error)25 static int get_fs_size_stat(const char *fs, zbx_uint64_t *total, zbx_uint64_t *free,
26 zbx_uint64_t *used, double *pfree, double *pused, char **error)
27 {
28 #ifdef HAVE_SYS_STATVFS_H
29 # ifdef HAVE_SYS_STATVFS64
30 # define ZBX_STATFS statvfs64
31 # else
32 # define ZBX_STATFS statvfs
33 # endif
34 # define ZBX_BSIZE f_frsize
35 #else
36 # define ZBX_STATFS statfs
37 # define ZBX_BSIZE f_bsize
38 #endif
39 struct ZBX_STATFS s;
40
41 if (0 != ZBX_STATFS(fs, &s))
42 {
43 *error = zbx_dsprintf(NULL, "Cannot obtain filesystem information: %s", zbx_strerror(errno));
44 return SYSINFO_RET_FAIL;
45 }
46
47 /* Available space could be negative (top bit set) if we hit disk space */
48 /* reserved for non-privileged users. Treat it as 0. */
49 if (0 != ZBX_IS_TOP_BIT_SET(s.f_bavail))
50 s.f_bavail = 0;
51
52 if (NULL != total)
53 *total = (zbx_uint64_t)s.f_blocks * s.ZBX_BSIZE;
54
55 if (NULL != free)
56 *free = (zbx_uint64_t)s.f_bavail * s.ZBX_BSIZE;
57
58 if (NULL != used)
59 *used = (zbx_uint64_t)(s.f_blocks - s.f_bfree) * s.ZBX_BSIZE;
60
61 if (NULL != pfree)
62 {
63 if (0 != s.f_blocks - s.f_bfree + s.f_bavail)
64 *pfree = (double)(100.0 * s.f_bavail) / (s.f_blocks - s.f_bfree + s.f_bavail);
65 else
66 *pfree = 0;
67 }
68
69 if (NULL != pused)
70 {
71 if (0 != s.f_blocks - s.f_bfree + s.f_bavail)
72 *pused = 100.0 - (double)(100.0 * s.f_bavail) / (s.f_blocks - s.f_bfree + s.f_bavail);
73 else
74 *pused = 0;
75 }
76
77 return SYSINFO_RET_OK;
78 }
79
VFS_FS_USED(const char * fs,AGENT_RESULT * result)80 static int VFS_FS_USED(const char *fs, AGENT_RESULT *result)
81 {
82 zbx_uint64_t value;
83 char *error;
84
85 if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, NULL, &value, NULL, NULL, &error))
86 {
87 SET_MSG_RESULT(result, error);
88 return SYSINFO_RET_FAIL;
89 }
90
91 SET_UI64_RESULT(result, value);
92
93 return SYSINFO_RET_OK;
94 }
95
VFS_FS_FREE(const char * fs,AGENT_RESULT * result)96 static int VFS_FS_FREE(const char *fs, AGENT_RESULT *result)
97 {
98 zbx_uint64_t value;
99 char *error;
100
101 if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, &value, NULL, NULL, NULL, &error))
102 {
103 SET_MSG_RESULT(result, error);
104 return SYSINFO_RET_FAIL;
105 }
106
107 SET_UI64_RESULT(result, value);
108
109 return SYSINFO_RET_OK;
110 }
111
VFS_FS_TOTAL(const char * fs,AGENT_RESULT * result)112 static int VFS_FS_TOTAL(const char *fs, AGENT_RESULT *result)
113 {
114 zbx_uint64_t value;
115 char *error;
116
117 if (SYSINFO_RET_OK != get_fs_size_stat(fs, &value, NULL, NULL, NULL, NULL, &error))
118 {
119 SET_MSG_RESULT(result, error);
120 return SYSINFO_RET_FAIL;
121 }
122
123 SET_UI64_RESULT(result, value);
124
125 return SYSINFO_RET_OK;
126 }
127
VFS_FS_PFREE(const char * fs,AGENT_RESULT * result)128 static int VFS_FS_PFREE(const char *fs, AGENT_RESULT *result)
129 {
130 double value;
131 char *error;
132
133 if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, NULL, NULL, &value, NULL, &error))
134 {
135 SET_MSG_RESULT(result, error);
136 return SYSINFO_RET_FAIL;
137 }
138
139 SET_DBL_RESULT(result, value);
140
141 return SYSINFO_RET_OK;
142 }
143
VFS_FS_PUSED(const char * fs,AGENT_RESULT * result)144 static int VFS_FS_PUSED(const char *fs, AGENT_RESULT *result)
145 {
146 double value;
147 char *error;
148
149 if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, NULL, NULL, NULL, &value, &error))
150 {
151 SET_MSG_RESULT(result, error);
152 return SYSINFO_RET_FAIL;
153 }
154
155 SET_DBL_RESULT(result, value);
156
157 return SYSINFO_RET_OK;
158 }
159
vfs_fs_size(AGENT_REQUEST * request,AGENT_RESULT * result)160 static int vfs_fs_size(AGENT_REQUEST *request, AGENT_RESULT *result)
161 {
162 char *fsname, *mode;
163
164 if (2 < request->nparam)
165 {
166 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
167 return SYSINFO_RET_FAIL;
168 }
169
170 fsname = get_rparam(request, 0);
171 mode = get_rparam(request, 1);
172
173 if (NULL == fsname || '\0' == *fsname)
174 {
175 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
176 return SYSINFO_RET_FAIL;
177 }
178
179 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) /* default parameter */
180 return VFS_FS_TOTAL(fsname, result);
181 if (0 == strcmp(mode, "free"))
182 return VFS_FS_FREE(fsname, result);
183 if (0 == strcmp(mode, "pfree"))
184 return VFS_FS_PFREE(fsname, result);
185 if (0 == strcmp(mode, "used"))
186 return VFS_FS_USED(fsname, result);
187 if (0 == strcmp(mode, "pused"))
188 return VFS_FS_PUSED(fsname, result);
189
190 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
191
192 return SYSINFO_RET_FAIL;
193 }
194
VFS_FS_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)195 int VFS_FS_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
196 {
197 return zbx_execute_threaded_metric(vfs_fs_size, request, result);
198 }
199
VFS_FS_DISCOVERY(AGENT_REQUEST * request,AGENT_RESULT * result)200 int VFS_FS_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
201 {
202 struct mnttab mt;
203 FILE *f;
204 struct zbx_json j;
205
206 /* opening the mounted filesystems file */
207 if (NULL == (f = fopen("/etc/mnttab", "r")))
208 {
209 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /etc/mnttab: %s", zbx_strerror(errno)));
210 return SYSINFO_RET_FAIL;
211 }
212
213 zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
214
215 zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);
216
217 /* fill mnttab structure from file */
218 while (-1 != getmntent(f, &mt))
219 {
220 zbx_json_addobject(&j, NULL);
221 zbx_json_addstring(&j, "{#FSNAME}", mt.mnt_mountp, ZBX_JSON_TYPE_STRING);
222 zbx_json_addstring(&j, "{#FSTYPE}", mt.mnt_fstype, ZBX_JSON_TYPE_STRING);
223 zbx_json_close(&j);
224 }
225
226 zbx_fclose(f);
227
228 zbx_json_close(&j);
229
230 SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer));
231
232 zbx_json_free(&j);
233
234 return SYSINFO_RET_OK;
235 }
236