d8071a294ccb9d312688f7a4e187c2bb90047a0d
[public/netxms.git] / src / agent / subagents / linux / disk.cpp
1 /*
2 ** NetXMS subagent for GNU/Linux
3 ** Copyright (C) 2004-2015 Raden Solutions
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 **/
20
21 #include "linux_subagent.h"
22
23 /**
24 * Find mount point by device
25 */
26 static void FindMountpointByDevice(char *dev, int size)
27 {
28 FILE *f = setmntent(_PATH_MOUNTED, "r");
29 if (f != NULL)
30 {
31 struct mntent *mnt;
32 while ((mnt = getmntent(f)) != NULL)
33 {
34 if (!strcmp(mnt->mnt_fsname, dev))
35 {
36 strncpy(dev, mnt->mnt_dir, size);
37 break;
38 }
39 }
40 endmntent(f);
41 }
42 }
43
44 /**
45 * Handler for FileSystem.* parameters
46 */
47 LONG H_DiskInfo(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
48 {
49 int nRet = SYSINFO_RC_ERROR;
50 char szArg[512] = {0};
51
52 AgentGetParameterArgA(pszParam, 1, szArg, sizeof(szArg));
53
54 if (szArg[0] != 0)
55 {
56 FindMountpointByDevice(szArg, sizeof(szArg));
57
58 struct statfs s;
59 if (statfs(szArg, &s) == 0)
60 {
61 nRet = SYSINFO_RC_SUCCESS;
62
63 QWORD usedBlocks = (QWORD)(s.f_blocks - s.f_bfree);
64 QWORD totalBlocks = (QWORD)s.f_blocks;
65 QWORD blockSize = (QWORD)s.f_bsize;
66 QWORD freeBlocks = (QWORD)s.f_bfree;
67 QWORD availableBlocks = (QWORD)s.f_bavail;
68
69 switch((long)pArg)
70 {
71 case DISK_TOTAL:
72 ret_uint64(pValue, totalBlocks * blockSize);
73 break;
74 case DISK_USED:
75 ret_uint64(pValue, usedBlocks * blockSize);
76 break;
77 case DISK_FREE:
78 ret_uint64(pValue, freeBlocks * blockSize);
79 break;
80 case DISK_AVAIL:
81 ret_uint64(pValue, availableBlocks * blockSize);
82 break;
83 case DISK_USED_PERC:
84 if (totalBlocks > 0)
85 {
86 ret_double(pValue, (usedBlocks * 100.0) / totalBlocks);
87 }
88 else
89 {
90 ret_double(pValue, 0.0);
91 }
92 break;
93 case DISK_AVAIL_PERC:
94 if (totalBlocks > 0)
95 {
96 ret_double(pValue, (availableBlocks * 100.0) / totalBlocks);
97 }
98 else
99 {
100 ret_double(pValue, 0.0);
101 }
102 break;
103 case DISK_FREE_PERC:
104 if (totalBlocks > 0)
105 {
106 ret_double(pValue, (freeBlocks * 100.0) / totalBlocks);
107 }
108 else
109 {
110 ret_double(pValue, 0.0);
111 }
112 break;
113 default:
114 nRet = SYSINFO_RC_ERROR;
115 break;
116 }
117 }
118 }
119
120 return nRet;
121 }
122
123 /**
124 * Handler for FileSystem.Volumes table
125 */
126 LONG H_FileSystems(const TCHAR *cmd, const TCHAR *arg, Table *table, AbstractCommSession *session)
127 {
128 LONG rc = SYSINFO_RC_SUCCESS;
129
130 FILE *in = fopen("/etc/mtab", "r");
131 if (in != NULL)
132 {
133 table->addColumn(_T("MOUNTPOINT"), DCI_DT_STRING, _T("Mount Point"), true);
134 table->addColumn(_T("VOLUME"), DCI_DT_STRING, _T("Volume"));
135 table->addColumn(_T("LABEL"), DCI_DT_STRING, _T("Label"));
136 table->addColumn(_T("FSTYPE"), DCI_DT_STRING, _T("FS Type"));
137 table->addColumn(_T("SIZE.TOTAL"), DCI_DT_UINT64, _T("Total"));
138 table->addColumn(_T("SIZE.FREE"), DCI_DT_UINT64, _T("Free"));
139 table->addColumn(_T("SIZE.FREE.PCT"), DCI_DT_FLOAT, _T("Free %"));
140 table->addColumn(_T("SIZE.AVAIL"), DCI_DT_UINT64, _T("Available"));
141 table->addColumn(_T("SIZE.AVAIL.PCT"), DCI_DT_FLOAT, _T("Available %"));
142 table->addColumn(_T("SIZE.USED"), DCI_DT_UINT64, _T("Used"));
143 table->addColumn(_T("SIZE.USED.PCT"), DCI_DT_FLOAT, _T("Used %"));
144
145 while(1)
146 {
147 char line[256];
148 if (fgets(line, 256, in) == NULL)
149 break;
150 if (!strncmp(line, "rootfs /", 8))
151 continue;
152
153 table->addRow();
154
155 char device[256], mountPoint[256], fsType[256];
156 const char *next = ExtractWordA(line, device);
157 next = ExtractWordA(next, mountPoint);
158 ExtractWordA(next, fsType);
159
160 #ifdef UNICODE
161 table->setPreallocated(0, WideStringFromMBString(mountPoint));
162 table->setPreallocated(1, WideStringFromMBString(device));
163 table->setPreallocated(3, WideStringFromMBString(fsType));
164 #else
165 table->set(0, mountPoint);
166 table->set(1, device);
167 table->set(3, fsType);
168 #endif
169
170 struct statfs s;
171 if (statfs(mountPoint, &s) == 0)
172 {
173 QWORD usedBlocks = (QWORD)(s.f_blocks - s.f_bfree);
174 QWORD totalBlocks = (QWORD)s.f_blocks;
175 QWORD blockSize = (QWORD)s.f_bsize;
176 QWORD freeBlocks = (QWORD)s.f_bfree;
177 QWORD availableBlocks = (QWORD)s.f_bavail;
178
179 table->set(4, totalBlocks * blockSize);
180 table->set(5, freeBlocks * blockSize);
181 table->set(6, (totalBlocks > 0) ? (freeBlocks * 100.0) / totalBlocks : 0);
182 table->set(7, availableBlocks * blockSize);
183 table->set(8, (totalBlocks > 0) ? (availableBlocks * 100.0) / totalBlocks : 0);
184 table->set(9, usedBlocks * blockSize);
185 table->set(10, (totalBlocks > 0) ? (usedBlocks * 100.0) / totalBlocks : 0);
186 }
187 else
188 {
189 TCHAR buffer[1024];
190 AgentWriteDebugLog(4, _T("Linux: H_FileSystems: Call to statfs(\"%hs\") failed (%hs)"), mountPoint, strerror(errno));
191
192 table->set(4, (QWORD)0);
193 table->set(5, (QWORD)0);
194 table->set(6, (QWORD)0);
195 table->set(7, (QWORD)0);
196 table->set(8, (QWORD)0);
197 table->set(9, (QWORD)0);
198 table->set(10, (QWORD)0);
199 }
200 }
201 fclose(in);
202 }
203 else
204 {
205 AgentWriteDebugLog(4, _T("Linux: H_FileSystems: cannot open /etc/mtab"));
206 rc = SYSINFO_RC_ERROR;
207 }
208 return rc;
209 }
210
211 /**
212 * Handler for FileSystem.MountPoints list
213 */
214 LONG H_MountPoints(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session)
215 {
216 LONG rc = SYSINFO_RC_SUCCESS;
217
218 FILE *in = fopen("/etc/mtab", "r");
219 if (in != NULL)
220 {
221 while(1)
222 {
223 char line[256];
224 if (fgets(line, 256, in) == NULL)
225 break;
226 if (!strncmp(line, "rootfs /", 8))
227 continue;
228 char *ptr = strchr(line, ' ');
229 if (ptr != NULL)
230 {
231 ptr++;
232 char *mp = ptr;
233 ptr = strchr(mp, ' ');
234 if (ptr != NULL)
235 *ptr = 0;
236 #ifdef UNICODE
237 value->addPreallocated(WideStringFromMBString(mp));
238 #else
239 value->add(mp);
240 #endif
241 }
242 }
243 fclose(in);
244 }
245 else
246 {
247 AgentWriteDebugLog(4, _T("Linux: H_MountPoints: cannot open /etc/mtab"));
248 rc = SYSINFO_RC_ERROR;
249 }
250 return rc;
251 }
252
253 /**
254 * Handler for FileSystem.Type(*)
255 */
256 LONG H_FileSystemType(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
257 {
258 char path[MAX_PATH];
259 if (!AgentGetParameterArgA(cmd, 1, path, MAX_PATH))
260 return SYSINFO_RC_UNSUPPORTED;
261
262 LONG rc = SYSINFO_RC_UNSUPPORTED;
263
264 FILE *f = setmntent(_PATH_MOUNTED, "r");
265 if (f != NULL)
266 {
267 struct mntent *mnt;
268 while((mnt = getmntent(f)) != NULL)
269 {
270 if (!strcmp(mnt->mnt_type, "rootfs"))
271 continue; // ignore rootfs entries
272
273 if (!strcmp(mnt->mnt_fsname, path) || !strcmp(mnt->mnt_dir, path))
274 {
275 ret_mbstring(value, mnt->mnt_type);
276 rc = SYSINFO_RC_SUCCESS;
277 break;
278 }
279 }
280 endmntent(f);
281 }
282 else
283 {
284 AgentWriteDebugLog(4, _T("Linux: H_FileSystemType: call to setmntent failed"));
285 rc = SYSINFO_RC_ERROR;
286 }
287 return rc;
288 }