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 
vfs_fs_size(AGENT_REQUEST * request,AGENT_RESULT * result)24 static int	vfs_fs_size(AGENT_REQUEST *request, AGENT_RESULT *result)
25 {
26 	char		*path, *mode;
27 	wchar_t 	*wpath;
28 	ULARGE_INTEGER	freeBytes, totalBytes;
29 
30 	if (2 < request->nparam)
31 	{
32 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
33 		return SYSINFO_RET_FAIL;
34 	}
35 
36 	path = get_rparam(request, 0);
37 	mode = get_rparam(request, 1);
38 
39 	if (NULL == path || '\0' == *path)
40 	{
41 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
42 		return SYSINFO_RET_FAIL;
43 	}
44 
45 	wpath = zbx_utf8_to_unicode(path);
46 	if (0 == GetDiskFreeSpaceEx(wpath, &freeBytes, &totalBytes, NULL))
47 	{
48 		zbx_free(wpath);
49 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain filesystem information."));
50 		return SYSINFO_RET_FAIL;
51 	}
52 	zbx_free(wpath);
53 
54 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
55 		SET_UI64_RESULT(result, totalBytes.QuadPart);
56 	else if (0 == strcmp(mode, "free"))
57 		SET_UI64_RESULT(result, freeBytes.QuadPart);
58 	else if (0 == strcmp(mode, "used"))
59 		SET_UI64_RESULT(result, totalBytes.QuadPart - freeBytes.QuadPart);
60 	else if (0 == strcmp(mode, "pfree"))
61 		SET_DBL_RESULT(result, (double)(__int64)freeBytes.QuadPart * 100. / (double)(__int64)totalBytes.QuadPart);
62 	else if (0 == strcmp(mode, "pused"))
63 		SET_DBL_RESULT(result, (double)((__int64)totalBytes.QuadPart - (__int64)freeBytes.QuadPart) * 100. /
64 				(double)(__int64)totalBytes.QuadPart);
65 	else
66 	{
67 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
68 		return SYSINFO_RET_FAIL;
69 	}
70 
71 	return SYSINFO_RET_OK;
72 }
73 
VFS_FS_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)74 int	VFS_FS_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
75 {
76 	return zbx_execute_threaded_metric(vfs_fs_size, request, result);
77 }
78 
get_drive_type_string(UINT type)79 static const char	*get_drive_type_string(UINT type)
80 {
81 	switch (type)
82 	{
83 		case DRIVE_UNKNOWN:
84 			return "unknown";
85 		case DRIVE_NO_ROOT_DIR:
86 			return "norootdir";
87 		case DRIVE_REMOVABLE:
88 			return "removable";
89 		case DRIVE_FIXED:
90 			return "fixed";
91 		case DRIVE_REMOTE:
92 			return "remote";
93 		case DRIVE_CDROM:
94 			return "cdrom";
95 		case DRIVE_RAMDISK:
96 			return "ramdisk";
97 		default:
98 			THIS_SHOULD_NEVER_HAPPEN;
99 			return "unknown";
100 	}
101 }
102 
VFS_FS_DISCOVERY(AGENT_REQUEST * request,AGENT_RESULT * result)103 int	VFS_FS_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
104 {
105 	wchar_t		fsName[MAX_PATH + 1];
106 	wchar_t 	*buffer = NULL, *p;
107 	char		*utf8;
108 	DWORD		dwSize;
109 	size_t		sz;
110 	struct zbx_json	j;
111 
112 	/* Make an initial call to GetLogicalDriveStrings to
113 	   get the necessary size into the dwSize variable */
114 	if (0 == (dwSize = GetLogicalDriveStrings(0, buffer)))
115 	{
116 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain necessary buffer size from system."));
117 		return SYSINFO_RET_FAIL;
118 	}
119 
120 	buffer = (wchar_t *)zbx_malloc(buffer, (dwSize + 1) * sizeof(wchar_t));
121 
122 	/* Make a second call to GetLogicalDriveStrings to get
123 	   the actual data we require */
124 	if (0 == (dwSize = GetLogicalDriveStrings(dwSize, buffer)))
125 	{
126 		zbx_free(buffer);
127 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain a list of filesystems."));
128 		return SYSINFO_RET_FAIL;
129 	}
130 
131 	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
132 
133 	zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);
134 
135 	for (p = buffer, sz = wcslen(p); sz > 0; p += sz + 1, sz = wcslen(p))
136 	{
137 		zbx_json_addobject(&j, NULL);
138 
139 		utf8 = zbx_unicode_to_utf8(p);
140 
141 		/* remove trailing backslash */
142 		if ('A' <= utf8[0] && utf8[0] <= 'Z' && ':' == utf8[1] && '\\' == utf8[2] && '\0' == utf8[3])
143 			utf8[2] = '\0';
144 
145 		zbx_json_addstring(&j, "{#FSNAME}", utf8, ZBX_JSON_TYPE_STRING);
146 		zbx_free(utf8);
147 
148 		if (TRUE == GetVolumeInformation(p, NULL, 0, NULL, NULL, NULL, fsName, ARRSIZE(fsName)))
149 		{
150 			utf8 = zbx_unicode_to_utf8(fsName);
151 			zbx_json_addstring(&j, "{#FSTYPE}", utf8, ZBX_JSON_TYPE_STRING);
152 			zbx_free(utf8);
153 		}
154 		else
155 			zbx_json_addstring(&j, "{#FSTYPE}", "UNKNOWN", ZBX_JSON_TYPE_STRING);
156 
157 		zbx_json_addstring(&j, "{#FSDRIVETYPE}", get_drive_type_string(GetDriveType(p)), ZBX_JSON_TYPE_STRING);
158 
159 		zbx_json_close(&j);
160 	}
161 
162 	zbx_free(buffer);
163 
164 	zbx_json_close(&j);
165 
166 	SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer));
167 
168 	zbx_json_free(&j);
169 
170 	return SYSINFO_RET_OK;
171 }
172