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 "md5.h"
23 #include "file.h"
24 #include "dir.h"
25 #include "zbxregexp.h"
26 #include "log.h"
27 
28 #define ZBX_MAX_DB_FILE_SIZE	64 * ZBX_KIBIBYTE	/* files larger than 64 KB cannot be stored in the database */
29 
30 extern int	CONFIG_TIMEOUT;
31 
VFS_FILE_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)32 int	VFS_FILE_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
33 {
34 	zbx_stat_t	buf;
35 	char		*filename;
36 	int		ret = SYSINFO_RET_FAIL;
37 
38 	if (1 < request->nparam)
39 	{
40 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
41 		goto err;
42 	}
43 
44 	filename = get_rparam(request, 0);
45 
46 	if (NULL == filename || '\0' == *filename)
47 	{
48 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
49 		goto err;
50 	}
51 
52 	if (0 != zbx_stat(filename, &buf))
53 	{
54 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain file information: %s", zbx_strerror(errno)));
55 		goto err;
56 	}
57 
58 	SET_UI64_RESULT(result, buf.st_size);
59 
60 	ret = SYSINFO_RET_OK;
61 err:
62 	return ret;
63 }
64 
VFS_FILE_TIME(AGENT_REQUEST * request,AGENT_RESULT * result)65 int	VFS_FILE_TIME(AGENT_REQUEST *request, AGENT_RESULT *result)
66 {
67 	zbx_file_time_t	file_time;
68 	char		*filename, *type;
69 	int		ret = SYSINFO_RET_FAIL;
70 
71 	if (2 < request->nparam)
72 	{
73 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
74 		goto err;
75 	}
76 
77 	filename = get_rparam(request, 0);
78 	type = get_rparam(request, 1);
79 
80 	if (NULL == filename || '\0' == *filename)
81 	{
82 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
83 		goto err;
84 	}
85 
86 	if (SUCCEED != zbx_get_file_time(filename, &file_time))
87 	{
88 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain file information: %s", zbx_strerror(errno)));
89 		goto err;
90 	}
91 
92 	if (NULL == type || '\0' == *type || 0 == strcmp(type, "modify"))	/* default parameter */
93 		SET_UI64_RESULT(result, file_time.modification_time);
94 	else if (0 == strcmp(type, "access"))
95 		SET_UI64_RESULT(result, file_time.access_time);
96 	else if (0 == strcmp(type, "change"))
97 		SET_UI64_RESULT(result, file_time.change_time);
98 	else
99 	{
100 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
101 		goto err;
102 	}
103 
104 	ret = SYSINFO_RET_OK;
105 err:
106 	return ret;
107 }
108 
109 #if defined(_WINDOWS) || defined(__MINGW32__)
vfs_file_exists(AGENT_REQUEST * request,AGENT_RESULT * result)110 static int	vfs_file_exists(AGENT_REQUEST *request, AGENT_RESULT *result)
111 {
112 	const char	*filename;
113 	int		ret = SYSINFO_RET_FAIL, file_exists = 0, types, types_incl, types_excl;
114 	DWORD		file_attributes;
115 	wchar_t		*wpath;
116 
117 	if (3 < request->nparam)
118 	{
119 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
120 		goto err;
121 	}
122 
123 	filename = get_rparam(request, 0);
124 
125 	if (NULL == filename || '\0' == *filename)
126 	{
127 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
128 		goto err;
129 	}
130 
131 	if (FAIL == (types_incl = zbx_etypes_to_mask(get_rparam(request, 1), result)) ||
132 			FAIL == (types_excl = zbx_etypes_to_mask(get_rparam(request, 2), result)))
133 	{
134 		goto err;
135 	}
136 
137 	if (0 == types_incl)
138 	{
139 		if (0 == types_excl)
140 			types_incl = ZBX_FT_FILE;
141 		else
142 			types_incl = ZBX_FT_ALLMASK;
143 	}
144 
145 	types = types_incl & (~types_excl) & ZBX_FT_ALLMASK;
146 
147 	if (NULL == (wpath = zbx_utf8_to_unicode(filename)))
148 	{
149 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot convert file name to UTF-16."));
150 		goto err;
151 	}
152 
153 	file_attributes = GetFileAttributesW(wpath);
154 	zbx_free(wpath);
155 
156 	if (INVALID_FILE_ATTRIBUTES == file_attributes)
157 	{
158 		DWORD	error;
159 
160 		switch (error = GetLastError())
161 		{
162 			case ERROR_FILE_NOT_FOUND:
163 				goto exit;
164 			case ERROR_BAD_NETPATH:	/* special case from GetFileAttributesW() documentation */
165 				SET_MSG_RESULT(result, zbx_dsprintf(NULL, "The specified file is a network share."
166 						" Use a path to a subfolder on that share."));
167 				goto err;
168 			default:
169 				SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain file information: %s",
170 						strerror_from_system(error)));
171 				goto err;
172 		}
173 	}
174 
175 	switch (file_attributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY))
176 	{
177 		case FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY:
178 			if (0 != (types & ZBX_FT_SYM) || 0 != (types & ZBX_FT_DIR))
179 				file_exists = 1;
180 			break;
181 		case FILE_ATTRIBUTE_REPARSE_POINT:
182 						/* not a symlink directory => symlink regular file*/
183 						/* counting symlink files as MS explorer */
184 			if (0 != (types & ZBX_FT_FILE))
185 				file_exists = 1;
186 			break;
187 		case FILE_ATTRIBUTE_DIRECTORY:
188 			if (0 != (types & ZBX_FT_DIR))
189 				file_exists = 1;
190 			break;
191 		default:	/* not a directory => regular file */
192 			if (0 != (types & ZBX_FT_FILE))
193 				file_exists = 1;
194 	}
195 exit:
196 	SET_UI64_RESULT(result, file_exists);
197 	ret = SYSINFO_RET_OK;
198 err:
199 	return ret;
200 }
201 #else /* not _WINDOWS or __MINGW32__ */
vfs_file_exists(AGENT_REQUEST * request,AGENT_RESULT * result)202 static int	vfs_file_exists(AGENT_REQUEST *request, AGENT_RESULT *result)
203 {
204 	zbx_stat_t	buf;
205 	const char	*filename;
206 	int		types = 0, types_incl, types_excl;
207 
208 	if (3 < request->nparam)
209 	{
210 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
211 		return SYSINFO_RET_FAIL;
212 	}
213 
214 	filename = get_rparam(request, 0);
215 
216 	if (NULL == filename || '\0' == *filename)
217 	{
218 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
219 		return SYSINFO_RET_FAIL;
220 	}
221 
222 	if (FAIL == (types_incl = zbx_etypes_to_mask(get_rparam(request, 1), result)) ||
223 			FAIL == (types_excl = zbx_etypes_to_mask(get_rparam(request, 2), result)))
224 	{
225 		return SYSINFO_RET_FAIL;
226 	}
227 
228 	if (0 == types_incl)
229 	{
230 		if (0 == types_excl)
231 			types_incl = ZBX_FT_FILE;
232 		else
233 			types_incl = ZBX_FT_ALLMASK;
234 	}
235 
236 	if (0 != (types_incl & ZBX_FT_SYM) || 0 != (types_excl & ZBX_FT_SYM))
237 	{
238 		if (0 == lstat(filename, &buf))
239 		{
240 			if (0 != S_ISLNK(buf.st_mode))
241 				types |= ZBX_FT_SYM;
242 		}
243 		else if (ENOENT != errno)
244 		{
245 			SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain file information: %s",
246 					zbx_strerror(errno)));
247 			return SYSINFO_RET_FAIL;
248 		}
249 	}
250 
251 	if (0 == zbx_stat(filename, &buf))
252 	{
253 		if (0 != S_ISREG(buf.st_mode))
254 			types |= ZBX_FT_FILE;
255 		else if (0 != S_ISDIR(buf.st_mode))
256 			types |= ZBX_FT_DIR;
257 		else if (0 != S_ISSOCK(buf.st_mode))
258 			types |= ZBX_FT_SOCK;
259 		else if (0 != S_ISBLK(buf.st_mode))
260 			types |= ZBX_FT_BDEV;
261 		else if (0 != S_ISCHR(buf.st_mode))
262 			types |= ZBX_FT_CDEV;
263 		else if (0 != S_ISFIFO(buf.st_mode))
264 			types |= ZBX_FT_FIFO;
265 	}
266 	else if (ENOENT != errno)
267 	{
268 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain file information: %s", zbx_strerror(errno)));
269 		return SYSINFO_RET_FAIL;
270 	}
271 
272 	if (0 == (types & types_excl) && 0 != (types & types_incl))
273 		SET_UI64_RESULT(result, 1);
274 	else
275 		SET_UI64_RESULT(result, 0);
276 
277 	return SYSINFO_RET_OK;
278 }
279 #endif
280 
VFS_FILE_EXISTS(AGENT_REQUEST * request,AGENT_RESULT * result)281 int	VFS_FILE_EXISTS(AGENT_REQUEST *request, AGENT_RESULT *result)
282 {
283 	return vfs_file_exists(request, result);
284 }
285 
VFS_FILE_CONTENTS(AGENT_REQUEST * request,AGENT_RESULT * result)286 int	VFS_FILE_CONTENTS(AGENT_REQUEST *request, AGENT_RESULT *result)
287 {
288 	char		*filename, *tmp, encoding[32];
289 	char		read_buf[MAX_BUFFER_LEN], *utf8, *contents = NULL;
290 	size_t		contents_alloc = 0, contents_offset = 0;
291 	int		nbytes, flen, f = -1, ret = SYSINFO_RET_FAIL;
292 	zbx_stat_t	stat_buf;
293 	double		ts;
294 
295 	ts = zbx_time();
296 
297 	if (2 < request->nparam)
298 	{
299 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
300 		goto err;
301 	}
302 
303 	filename = get_rparam(request, 0);
304 	tmp = get_rparam(request, 1);
305 
306 	if (NULL == tmp)
307 		*encoding = '\0';
308 	else
309 		strscpy(encoding, tmp);
310 
311 	if (NULL == filename || '\0' == *filename)
312 	{
313 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
314 		goto err;
315 	}
316 
317 	if (-1 == (f = zbx_open(filename, O_RDONLY)))
318 	{
319 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open file: %s", zbx_strerror(errno)));
320 		goto err;
321 	}
322 
323 	if (CONFIG_TIMEOUT < zbx_time() - ts)
324 	{
325 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
326 		goto err;
327 	}
328 
329 	if (0 != zbx_fstat(f, &stat_buf))
330 	{
331 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain file information: %s", zbx_strerror(errno)));
332 		goto err;
333 	}
334 
335 	if (ZBX_MAX_DB_FILE_SIZE < stat_buf.st_size)
336 	{
337 		SET_MSG_RESULT(result, zbx_strdup(NULL, "File is too large for this check."));
338 		goto err;
339 	}
340 
341 	if (CONFIG_TIMEOUT < zbx_time() - ts)
342 	{
343 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
344 		goto err;
345 	}
346 
347 	flen = 0;
348 
349 	while (0 < (nbytes = zbx_read(f, read_buf, sizeof(read_buf), encoding)))
350 	{
351 		if (CONFIG_TIMEOUT < zbx_time() - ts)
352 		{
353 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
354 			zbx_free(contents);
355 			goto err;
356 		}
357 
358 		if (ZBX_MAX_DB_FILE_SIZE < (flen += nbytes))
359 		{
360 			SET_MSG_RESULT(result, zbx_strdup(NULL, "File is too large for this check."));
361 			zbx_free(contents);
362 			goto err;
363 		}
364 
365 		utf8 = convert_to_utf8(read_buf, nbytes, encoding);
366 		zbx_strcpy_alloc(&contents, &contents_alloc, &contents_offset, utf8);
367 		zbx_free(utf8);
368 	}
369 
370 	if (-1 == nbytes)	/* error occurred */
371 	{
372 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read from file."));
373 		zbx_free(contents);
374 		goto err;
375 	}
376 
377 	if (0 != contents_offset)
378 		contents_offset -= zbx_rtrim(contents, "\r\n");
379 
380 	if (0 == contents_offset) /* empty file */
381 	{
382 		zbx_free(contents);
383 		contents = zbx_strdup(contents, "");
384 	}
385 
386 	SET_TEXT_RESULT(result, contents);
387 
388 	ret = SYSINFO_RET_OK;
389 err:
390 	if (-1 != f)
391 		close(f);
392 
393 	return ret;
394 }
395 
VFS_FILE_REGEXP(AGENT_REQUEST * request,AGENT_RESULT * result)396 int	VFS_FILE_REGEXP(AGENT_REQUEST *request, AGENT_RESULT *result)
397 {
398 	char		*filename, *regexp, encoding[32], *output, *start_line_str, *end_line_str;
399 	char		buf[MAX_BUFFER_LEN], *utf8, *tmp, *ptr = NULL;
400 	int		nbytes, f = -1, ret = SYSINFO_RET_FAIL;
401 	zbx_uint32_t	start_line, end_line, current_line = 0;
402 	double		ts;
403 
404 	ts = zbx_time();
405 
406 	if (6 < request->nparam)
407 	{
408 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
409 		goto err;
410 	}
411 
412 	filename = get_rparam(request, 0);
413 	regexp = get_rparam(request, 1);
414 	tmp = get_rparam(request, 2);
415 	start_line_str = get_rparam(request, 3);
416 	end_line_str = get_rparam(request, 4);
417 	output = get_rparam(request, 5);
418 
419 	if (NULL == filename || '\0' == *filename)
420 	{
421 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
422 		goto err;
423 	}
424 
425 	if (NULL == regexp || '\0' == *regexp)
426 	{
427 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
428 		goto err;
429 	}
430 
431 	if (NULL == tmp)
432 		*encoding = '\0';
433 	else
434 		strscpy(encoding, tmp);
435 
436 	if (NULL == start_line_str || '\0' == *start_line_str)
437 		start_line = 0;
438 	else if (FAIL == is_uint32(start_line_str, &start_line))
439 	{
440 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
441 		goto err;
442 	}
443 
444 	if (NULL == end_line_str || '\0' == *end_line_str)
445 		end_line = 0xffffffff;
446 	else if (FAIL == is_uint32(end_line_str, &end_line))
447 	{
448 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter."));
449 		goto err;
450 	}
451 
452 	if (start_line > end_line)
453 	{
454 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Start line parameter must not exceed end line."));
455 		goto err;
456 	}
457 
458 	if (-1 == (f = zbx_open(filename, O_RDONLY)))
459 	{
460 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open file: %s", zbx_strerror(errno)));
461 		goto err;
462 	}
463 
464 	if (CONFIG_TIMEOUT < zbx_time() - ts)
465 	{
466 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
467 		goto err;
468 	}
469 
470 	while (0 < (nbytes = zbx_read(f, buf, sizeof(buf), encoding)))
471 	{
472 		if (CONFIG_TIMEOUT < zbx_time() - ts)
473 		{
474 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
475 			goto err;
476 		}
477 
478 		if (++current_line < start_line)
479 			continue;
480 
481 		utf8 = convert_to_utf8(buf, nbytes, encoding);
482 		zbx_rtrim(utf8, "\r\n");
483 		zbx_regexp_sub(utf8, regexp, output, &ptr);
484 		zbx_free(utf8);
485 
486 		if (NULL != ptr)
487 		{
488 			SET_STR_RESULT(result, ptr);
489 			break;
490 		}
491 
492 		if (current_line >= end_line)
493 		{
494 			/* force EOF state */
495 			nbytes = 0;
496 			break;
497 		}
498 	}
499 
500 	if (-1 == nbytes)	/* error occurred */
501 	{
502 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read from file."));
503 		goto err;
504 	}
505 
506 	if (0 == nbytes)	/* EOF */
507 		SET_STR_RESULT(result, zbx_strdup(NULL, ""));
508 
509 	ret = SYSINFO_RET_OK;
510 err:
511 	if (-1 != f)
512 		close(f);
513 
514 	return ret;
515 }
516 
VFS_FILE_REGMATCH(AGENT_REQUEST * request,AGENT_RESULT * result)517 int	VFS_FILE_REGMATCH(AGENT_REQUEST *request, AGENT_RESULT *result)
518 {
519 	char		*filename, *regexp, *tmp, encoding[32];
520 	char		buf[MAX_BUFFER_LEN], *utf8, *start_line_str, *end_line_str;
521 	int		nbytes, res, f = -1, ret = SYSINFO_RET_FAIL;
522 	zbx_uint32_t	start_line, end_line, current_line = 0;
523 	double		ts;
524 
525 	ts = zbx_time();
526 
527 	if (5 < request->nparam)
528 	{
529 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
530 		goto err;
531 	}
532 
533 	filename = get_rparam(request, 0);
534 	regexp = get_rparam(request, 1);
535 	tmp = get_rparam(request, 2);
536 	start_line_str = get_rparam(request, 3);
537 	end_line_str = get_rparam(request, 4);
538 
539 	if (NULL == filename || '\0' == *filename)
540 	{
541 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
542 		goto err;
543 	}
544 
545 	if (NULL == regexp || '\0' == *regexp)
546 	{
547 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
548 		goto err;
549 	}
550 
551 	if (NULL == tmp)
552 		*encoding = '\0';
553 	else
554 		strscpy(encoding, tmp);
555 
556 	if (NULL == start_line_str || '\0' == *start_line_str)
557 		start_line = 0;
558 	else if (FAIL == is_uint32(start_line_str, &start_line))
559 	{
560 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
561 		goto err;
562 	}
563 
564 	if (NULL == end_line_str || '\0' == *end_line_str)
565 		end_line = 0xffffffff;
566 	else if (FAIL == is_uint32(end_line_str, &end_line))
567 	{
568 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter."));
569 		goto err;
570 	}
571 
572 	if (start_line > end_line)
573 	{
574 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Start line must not exceed end line."));
575 		goto err;
576 	}
577 
578 	if (-1 == (f = zbx_open(filename, O_RDONLY)))
579 	{
580 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open file: %s", zbx_strerror(errno)));
581 		goto err;
582 	}
583 
584 	if (CONFIG_TIMEOUT < zbx_time() - ts)
585 	{
586 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
587 		goto err;
588 	}
589 
590 	res = 0;
591 
592 	while (0 == res && 0 < (nbytes = zbx_read(f, buf, sizeof(buf), encoding)))
593 	{
594 		if (CONFIG_TIMEOUT < zbx_time() - ts)
595 		{
596 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
597 			goto err;
598 		}
599 
600 		if (++current_line < start_line)
601 			continue;
602 
603 		utf8 = convert_to_utf8(buf, nbytes, encoding);
604 		zbx_rtrim(utf8, "\r\n");
605 		if (NULL != zbx_regexp_match(utf8, regexp, NULL))
606 			res = 1;
607 		zbx_free(utf8);
608 
609 		if (current_line >= end_line)
610 			break;
611 	}
612 
613 	if (-1 == nbytes)	/* error occurred */
614 	{
615 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read from file."));
616 		goto err;
617 	}
618 
619 	SET_UI64_RESULT(result, res);
620 
621 	ret = SYSINFO_RET_OK;
622 err:
623 	if (-1 != f)
624 		close(f);
625 
626 	return ret;
627 }
628 
VFS_FILE_MD5SUM(AGENT_REQUEST * request,AGENT_RESULT * result)629 int	VFS_FILE_MD5SUM(AGENT_REQUEST *request, AGENT_RESULT *result)
630 {
631 	char		*filename;
632 	int		i, nbytes, f = -1, ret = SYSINFO_RET_FAIL;
633 	md5_state_t	state;
634 	u_char		buf[16 * ZBX_KIBIBYTE];
635 	char		*hash_text = NULL;
636 	size_t		sz;
637 	md5_byte_t	hash[MD5_DIGEST_SIZE];
638 	double		ts;
639 
640 	ts = zbx_time();
641 
642 	if (1 < request->nparam)
643 	{
644 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
645 		goto err;
646 	}
647 
648 	filename = get_rparam(request, 0);
649 
650 	if (NULL == filename || '\0' == *filename)
651 	{
652 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
653 		goto err;
654 	}
655 
656 	if (-1 == (f = zbx_open(filename, O_RDONLY)))
657 	{
658 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open file: %s", zbx_strerror(errno)));
659 		goto err;
660 	}
661 
662 	if (CONFIG_TIMEOUT < zbx_time() - ts)
663 	{
664 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
665 		goto err;
666 	}
667 
668 	zbx_md5_init(&state);
669 
670 	while (0 < (nbytes = (int)read(f, buf, sizeof(buf))))
671 	{
672 		if (CONFIG_TIMEOUT < zbx_time() - ts)
673 		{
674 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
675 			goto err;
676 		}
677 
678 		zbx_md5_append(&state, (const md5_byte_t *)buf, nbytes);
679 	}
680 
681 	zbx_md5_finish(&state, hash);
682 
683 	if (0 > nbytes)
684 	{
685 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read from file."));
686 		goto err;
687 	}
688 
689 	/* convert MD5 hash to text form */
690 
691 	sz = MD5_DIGEST_SIZE * 2 + 1;
692 	hash_text = (char *)zbx_malloc(hash_text, sz);
693 
694 	for (i = 0; i < MD5_DIGEST_SIZE; i++)
695 	{
696 		zbx_snprintf(&hash_text[i << 1], sz - (i << 1), "%02x", hash[i]);
697 	}
698 
699 	SET_STR_RESULT(result, hash_text);
700 
701 	ret = SYSINFO_RET_OK;
702 err:
703 	if (-1 != f)
704 		close(f);
705 
706 	return ret;
707 }
708 
709 static u_long	crctab[] =
710 {
711 	0x0,
712 	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
713 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
714 	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
715 	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
716 	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
717 	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
718 	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
719 	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
720 	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
721 	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
722 	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
723 	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
724 	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
725 	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
726 	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
727 	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
728 	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
729 	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
730 	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
731 	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
732 	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
733 	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
734 	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
735 	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
736 	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
737 	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
738 	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
739 	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
740 	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
741 	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
742 	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
743 	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
744 	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
745 	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
746 	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
747 	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
748 	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
749 	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
750 	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
751 	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
752 	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
753 	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
754 	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
755 	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
756 	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
757 	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
758 	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
759 	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
760 	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
761 	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
762 	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
763 };
764 
765 /******************************************************************************
766  *                                                                            *
767  * Comments: computes POSIX 1003.2 checksum                                   *
768  *                                                                            *
769  ******************************************************************************/
VFS_FILE_CKSUM(AGENT_REQUEST * request,AGENT_RESULT * result)770 int	VFS_FILE_CKSUM(AGENT_REQUEST *request, AGENT_RESULT *result)
771 {
772 	char		*filename;
773 	int		i, nr, f = -1, ret = SYSINFO_RET_FAIL;
774 	zbx_uint32_t	crc, flen;
775 	u_char		buf[16 * ZBX_KIBIBYTE];
776 	u_long		cval;
777 	double		ts;
778 
779 	ts = zbx_time();
780 
781 	if (1 < request->nparam)
782 	{
783 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
784 		goto err;
785 	}
786 
787 	filename = get_rparam(request, 0);
788 
789 	if (NULL == filename || '\0' == *filename)
790 	{
791 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
792 		goto err;
793 	}
794 
795 	if (-1 == (f = zbx_open(filename, O_RDONLY)))
796 	{
797 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open file: %s", zbx_strerror(errno)));
798 		goto err;
799 	}
800 
801 	if (CONFIG_TIMEOUT < zbx_time() - ts)
802 	{
803 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
804 		goto err;
805 	}
806 
807 	crc = flen = 0;
808 
809 	while (0 < (nr = (int)read(f, buf, sizeof(buf))))
810 	{
811 		if (CONFIG_TIMEOUT < zbx_time() - ts)
812 		{
813 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Timeout while processing item."));
814 			goto err;
815 		}
816 
817 		flen += nr;
818 
819 		for (i = 0; i < nr; i++)
820 			crc = (crc << 8) ^ crctab[((crc >> 24) ^ buf[i]) & 0xff];
821 	}
822 
823 	if (0 > nr)
824 	{
825 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read from file."));
826 		goto err;
827 	}
828 
829 	/* include the length of the file */
830 	for (; 0 != flen; flen >>= 8)
831 		crc = (crc << 8) ^ crctab[((crc >> 24) ^ flen) & 0xff];
832 
833 	cval = ~crc;
834 
835 	SET_UI64_RESULT(result, cval);
836 
837 	ret = SYSINFO_RET_OK;
838 err:
839 	if (-1 != f)
840 		close(f);
841 
842 	return ret;
843 }
844