/****************************************************************************** * * * Comments: Translate device name to the one used internally by kernel. The * * translation is done based on minor and major device numbers * * listed in INFO_FILE_NAME . If the names differ it is usually an * * LVM device which is listed in kernel device mapper. * * * ******************************************************************************/ static int get_kernel_devname(const char *devname, char *kernel_devname, size_t max_kernel_devname_len) { FILE *f; char tmp[MAX_STRING_LEN], name[MAX_STRING_LEN], dev_path[MAX_STRING_LEN]; int ret = FAIL; zbx_uint64_t ds[ZBX_DSTAT_MAX], rdev_major, rdev_minor; zbx_stat_t dev_st; if ('\0' == *devname) return ret; *dev_path = '\0'; if (0 != strncmp(devname, ZBX_DEV_PFX, ZBX_CONST_STRLEN(ZBX_DEV_PFX))) strscpy(dev_path, ZBX_DEV_PFX); strscat(dev_path, devname); if (zbx_stat(dev_path, &dev_st) < 0 || NULL == (f = fopen(INFO_FILE_NAME, "r"))) return ret; while (NULL != fgets(tmp, sizeof(tmp), f)) { PARSE(tmp); if (major(dev_st.st_rdev) != rdev_major || minor(dev_st.st_rdev) != rdev_minor) continue; zbx_strlcpy(kernel_devname, name, max_kernel_devname_len); ret = SUCCEED; break; } zbx_fclose(f); return ret; }
int get_diskstat(const char *devname, zbx_uint64_t *dstat) { FILE *f; char tmp[MAX_STRING_LEN], name[MAX_STRING_LEN], dev_path[MAX_STRING_LEN]; int i, ret = FAIL, dev_exists = FAIL; zbx_uint64_t ds[ZBX_DSTAT_MAX], rdev_major, rdev_minor; zbx_stat_t dev_st; int found = 0; for (i = 0; i < ZBX_DSTAT_MAX; i++) dstat[i] = (zbx_uint64_t)__UINT64_C(0); if (NULL != devname && '\0' != *devname && 0 != strcmp(devname, "all")) { *dev_path = '\0'; if (0 != strncmp(devname, ZBX_DEV_PFX, ZBX_CONST_STRLEN(ZBX_DEV_PFX))) strscpy(dev_path, ZBX_DEV_PFX); strscat(dev_path, devname); if (zbx_stat(dev_path, &dev_st) == 0) dev_exists = SUCCEED; } if (NULL == (f = fopen(INFO_FILE_NAME, "r"))) return FAIL; while (NULL != fgets(tmp, sizeof(tmp), f)) { PARSE(tmp); if (NULL != devname && '\0' != *devname && 0 != strcmp(devname, "all")) { if (0 != strcmp(name, devname)) { if (SUCCEED != dev_exists || major(dev_st.st_rdev) != rdev_major || minor(dev_st.st_rdev) != rdev_minor) continue; } else found = 1; } dstat[ZBX_DSTAT_R_OPER] += ds[ZBX_DSTAT_R_OPER]; dstat[ZBX_DSTAT_R_SECT] += ds[ZBX_DSTAT_R_SECT]; dstat[ZBX_DSTAT_W_OPER] += ds[ZBX_DSTAT_W_OPER]; dstat[ZBX_DSTAT_W_SECT] += ds[ZBX_DSTAT_W_SECT]; ret = SUCCEED; if (1 == found) break; } zbx_fclose(f); return ret; }
int zbx_is_regular_file(const char *path) { zbx_stat_t st; if (0 == zbx_stat(path, &st) && 0 != S_ISREG(st.st_mode)) return SUCCEED; return FAIL; }
/****************************************************************************** * * * Function: process_log * * * * Purpose: Get message from logfile WITHOUT rotation * * * * Parameters: filename - logfile name * * lastlogsize - offset for message * * value - pointer for logged message * * * * Return value: returns SUCCEED on successful reading, * * FAIL on other cases * * * * Author: Eugene Grigorjev * * * * Comments: * * This function allocates memory for 'value', because use zbx_free. * * Return SUCCEED and NULL value if end of file received. * * * ******************************************************************************/ int process_log(char *filename, long *lastlogsize, char **value, const char *encoding) { int f; struct stat buf; int nbytes, ret = FAIL; char buffer[MAX_BUFFER_LEN]; assert(filename); assert(lastlogsize); assert(value); assert(encoding); zabbix_log(LOG_LEVEL_DEBUG, "In process_log() filename:'%s' lastlogsize:%li", filename, *lastlogsize); /* handling of file shrinking */ if (0 != zbx_stat(filename, &buf)) { zabbix_log(LOG_LEVEL_WARNING, "cannot stat [%s]: %s", filename, zbx_strerror(errno)); return ret; } if (buf.st_size < *lastlogsize) *lastlogsize = 0; if (-1 == (f = zbx_open(filename, O_RDONLY))) { zabbix_log(LOG_LEVEL_WARNING, "cannot open [%s]: %s", filename, zbx_strerror(errno)); return ret; } if ((off_t)-1 != lseek(f, (off_t)*lastlogsize, SEEK_SET)) { if (-1 != (nbytes = zbx_read(f, buffer, sizeof(buffer), encoding))) { if (0 != nbytes) { *lastlogsize += nbytes; *value = convert_to_utf8(buffer, nbytes, encoding); zbx_rtrim(*value, "\r\n "); } ret = SUCCEED; } else zabbix_log(LOG_LEVEL_WARNING, "cannot read from [%s]: %s", filename, zbx_strerror(errno)); } else zabbix_log(LOG_LEVEL_WARNING, "cannot set position to [%li] for [%s]: %s", *lastlogsize, filename, zbx_strerror(errno)); close(f); return ret; }
/****************************************************************************** * * * Function: proc_get_process_uid * * * * Purpose: returns process user identifier * * * * Parameters: pid - [IN] the process identifier * * uid - [OUT] the user identifier * * * * Return value: SUCCEED * * FAIL * * * ******************************************************************************/ static int proc_get_process_uid(pid_t pid, uid_t *uid) { char tmp[MAX_STRING_LEN]; zbx_stat_t st; zbx_snprintf(tmp, sizeof(tmp), "/proc/%d", (int)pid); if (0 != zbx_stat(tmp, &st)) return FAIL; *uid = st.st_uid; return SUCCEED; }
/****************************************************************************** * * * Function: open_trap_file * * * * Purpose: open the trap file and get it's node number * * * * Return value: file descriptor of the opened file or -1 otherwise * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static int open_trap_file() { zbx_stat_t file_buf; if (-1 == (trap_fd = open(CONFIG_SNMPTRAP_FILE, O_RDONLY))) { if (ENOENT != errno) /* file exists but cannot be opened */ zabbix_log(LOG_LEVEL_CRIT, "cannot open [%s]: %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); } else if (0 != zbx_stat(CONFIG_SNMPTRAP_FILE, &file_buf)) { zabbix_log(LOG_LEVEL_CRIT, "cannot stat [%s]: %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); close_trap_file(); } else trap_ino = file_buf.st_ino; /* a new file was opened */ return trap_fd; }
/****************************************************************************** * * * Function: open_trap_file * * * * Purpose: open the trap file and get it's node number * * * * Return value: file descriptor of the opened file or -1 otherwise * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static int open_trap_file() { zbx_stat_t file_buf; if (0 != zbx_stat(CONFIG_SNMPTRAP_FILE, &file_buf)) { zabbix_log(LOG_LEVEL_CRIT, "cannot stat SNMP trapper file \"%s\": %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); goto out; } if (ZBX_SNMP_TRAPFILE_MAX_SIZE <= (zbx_uint64_t)file_buf.st_size) { if (0 == overflow_warning) { zabbix_log(LOG_LEVEL_CRIT, "cannot process SNMP trapper file \"%s\":" " file size exceeds the maximum supported size of 2 GB", CONFIG_SNMPTRAP_FILE); overflow_warning = 1; } goto out; } overflow_warning = 0; if (-1 == (trap_fd = open(CONFIG_SNMPTRAP_FILE, O_RDONLY))) { if (ENOENT != errno) /* file exists but cannot be opened */ { zabbix_log(LOG_LEVEL_CRIT, "cannot open SNMP trapper file \"%s\": %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); } goto out; } trap_ino = file_buf.st_ino; /* a new file was opened */ out: return trap_fd; }
/****************************************************************************** * * * Function: get_latest_data * * * * Purpose: Open the latest trap file. If the current file has been rotated, * * process that and then open the latest file. * * * * Return value: SUCCEED - there are new traps to be parsed * * FAIL - there are no new traps or trap file does not exist * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static int get_latest_data() { zbx_stat_t file_buf; if (-1 != trap_fd) /* a trap file is already open */ { if (0 != zbx_stat(CONFIG_SNMPTRAP_FILE, &file_buf)) { /* file might have been renamed or deleted, process the current file */ if (ENOENT != errno) { zabbix_log(LOG_LEVEL_CRIT, "cannot stat [%s]: %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); } read_traps(); close_trap_file(); } else if (file_buf.st_ino != trap_ino || file_buf.st_size < trap_lastsize) { /* file has been rotated, process the current file */ read_traps(); close_trap_file(); } else if (file_buf.st_size == trap_lastsize) { return FAIL; /* no new traps */ } } if (-1 == trap_fd && -1 == open_trap_file()) return FAIL; return SUCCEED; }
/****************************************************************************** * * * Function: get_latest_data * * * * Purpose: Open the latest trap file. If the current file has been rotated, * * process that and then open the latest file. * * * * Return value: SUCCEED - there are new traps to be parsed * * FAIL - there are no new traps or trap file does not exist * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static int get_latest_data() { zbx_stat_t file_buf; if (-1 != trap_fd) /* a trap file is already open */ { if (0 != zbx_stat(CONFIG_SNMPTRAP_FILE, &file_buf)) { /* file might have been renamed or deleted, process the current file */ if (ENOENT != errno) { zabbix_log(LOG_LEVEL_CRIT, "cannot stat SNMP trapper file \"%s\": %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); } while (0 < read_traps()) ; if (0 != offset) parse_traps(1); close_trap_file(); } else if (ZBX_SNMP_TRAPFILE_MAX_SIZE <= (zbx_uint64_t)file_buf.st_size) { close_trap_file(); } else if (file_buf.st_ino != trap_ino || file_buf.st_size < trap_lastsize) { /* file has been rotated, process the current file */ while (0 < read_traps()) ; if (0 != offset) parse_traps(1); close_trap_file(); } else if (file_buf.st_size == trap_lastsize) { if (1 == force) { parse_traps(1); force = 0; } else if (0 != offset && 0 == force) { force = 1; } return FAIL; /* no new traps */ } } force = 0; if (-1 == trap_fd && -1 == open_trap_file()) return FAIL; return SUCCEED; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char *procname, *proccomm, *param; double memsize = -1; int pgsize = getpagesize(); int proccount = 0, do_task; pid_t curr_pid = getpid(); if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information.")); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) /* default parameter */ do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { strscpy(filename, "/proc/"); zbx_strlcat(filename, entries->d_name, MAX_STRING_LEN); if (0 == zbx_stat(filename, &buf)) { proc = open(filename, O_RDONLY); if (-1 == proc) goto lbl_skip_procces; if (-1 == ioctl(proc, PIOCPSINFO, &psinfo)) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc.mem[zabbix_agentd]. */ if (psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if (NULL != procname && '\0' != *procname) if (0 == strcmp(procname, psinfo.pr_fname)) goto lbl_skip_procces; if (NULL != usrinfo) if (usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if (NULL != proccomm && '\0' != *proccomm) if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) goto lbl_skip_procces; proccount++; if (0 > memsize) /* first initialization */ { memsize = (double)(psinfo.pr_rssize * pgsize); } else { if (ZBX_DO_MAX == do_task) memsize = MAX(memsize, (double)(psinfo.pr_rssize * pgsize)); else if (ZBX_DO_MIN == do_task) memsize = MIN(memsize, (double)(psinfo.pr_rssize * pgsize)); else /* SUM */ memsize += (double)(psinfo.pr_rssize * pgsize); } lbl_skip_procces: if (-1 != proc) close(proc); } } closedir(dir); if (0 > memsize) { /* incorrect process name */ memsize = 0; } if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0 : memsize / (double)proccount); else SET_UI64_RESULT(result, memsize); return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: process_logrt * * * * Purpose: Get message from logfile with rotation * * * * Parameters: filename - logfile name (regular expression with a path) * * lastlogsize - offset for message * * mtime - last modification time of the file * * value - pointer for logged message * * * * Return value: returns SUCCEED on successful reading, * * FAIL on other cases * * * * Author: Dmitry Borovikov (logrotation) * * * * Comments: * * This function allocates memory for 'value', because use zbx_free. * * Return SUCCEED and NULL value if end of file received. * * * ******************************************************************************/ int process_logrt(char *filename, long *lastlogsize, int *mtime, char **value, const char *encoding) { int i = 0, nbytes, ret = FAIL, logfiles_num = 0, logfiles_alloc = 0, fd = 0, length = 0, j = 0; char buffer[MAX_BUFFER_LEN], *directory = NULL, *format = NULL, *logfile_candidate = NULL; struct stat file_buf; struct st_logfile *logfiles = NULL; #ifdef _WINDOWS char *find_path = NULL; intptr_t find_handle; struct _finddata_t find_data; #else DIR *dir = NULL; struct dirent *d_ent = NULL; #endif zabbix_log(LOG_LEVEL_DEBUG, "In process_logrt() filename [%s] lastlogsize [%li] mtime [%d]", filename, *lastlogsize, *mtime); /* splitting filename */ if (SUCCEED != split_filename(filename, &directory, &format)) { zabbix_log(LOG_LEVEL_WARNING, "filename [%s] does not contain a valid directory and/or format", filename); return FAIL; } #ifdef _WINDOWS /* try to "open" Windows directory */ find_path = zbx_dsprintf(find_path, "%s*", directory); find_handle = _findfirst((const char *)find_path, &find_data); if (-1 == find_handle) { zabbix_log(LOG_LEVEL_DEBUG, "cannot get entries from [%s] directory: %s", directory, zbx_strerror(errno)); zbx_free(directory); zbx_free(format); zbx_free(find_path); return FAIL; } zbx_free(find_path); zabbix_log(LOG_LEVEL_DEBUG, "we are in the Windows directory reading cycle"); do { logfile_candidate = zbx_dsprintf(logfile_candidate, "%s%s", directory, find_data.name); if (-1 == zbx_stat(logfile_candidate, &file_buf) || !S_ISREG(file_buf.st_mode)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot process read entry [%s]", logfile_candidate); } else if (NULL != zbx_regexp_match(find_data.name, format, &length)) { zabbix_log(LOG_LEVEL_DEBUG, "adding the file [%s] to logfiles", logfile_candidate); add_logfile(&logfiles, &logfiles_alloc, &logfiles_num, find_data.name, (int)file_buf.st_mtime); } else zabbix_log(LOG_LEVEL_DEBUG, "[%s] does not match [%s]", logfile_candidate, format); zbx_free(logfile_candidate); } while (0 == _findnext(find_handle, &find_data)); #else /* _WINDOWS */ if (NULL == (dir = opendir(directory))) { zabbix_log(LOG_LEVEL_WARNING, "cannot open directory [%s] for reading: %s", directory, zbx_strerror(errno)); zbx_free(directory); zbx_free(format); return FAIL; } zabbix_log(LOG_LEVEL_DEBUG, "we are in the *nix directory reading cycle"); while (NULL != (d_ent = readdir(dir))) { logfile_candidate = zbx_dsprintf(logfile_candidate, "%s%s", directory, d_ent->d_name); if (-1 == zbx_stat(logfile_candidate, &file_buf) || !S_ISREG(file_buf.st_mode)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot process read entry [%s]", logfile_candidate); } else if (NULL != zbx_regexp_match(d_ent->d_name, format, &length)) { zabbix_log(LOG_LEVEL_DEBUG, "adding the file [%s] to logfiles", logfile_candidate); add_logfile(&logfiles, &logfiles_alloc, &logfiles_num, d_ent->d_name, (int)file_buf.st_mtime); } else zabbix_log(LOG_LEVEL_DEBUG, "[%s] does not match [%s]", logfile_candidate, format); zbx_free(logfile_candidate); } #endif /*_WINDOWS*/ /* find the oldest file that match */ for (i = 0; i < logfiles_num; i++) { if (logfiles[i].mtime < *mtime) continue; /* not interested in mtimes less than the given mtime */ else break; /* the first occurrence is found */ } /* escaping those with the same mtime, taking the latest one (without exceptions!) */ for (j = i + 1; j < logfiles_num; j++) { if (logfiles[j].mtime == logfiles[i].mtime) i = j; /* moving to the newer one */ else break; /* all next mtimes are bigger */ } /* if all mtimes are less than the given one, take the latest file from existing ones */ if (0 < logfiles_num && i == logfiles_num) i = logfiles_num - 1; /* i cannot be bigger than logfiles_num */ /* processing matched or moving to the newer one and repeating the cycle */ for ( ; i < logfiles_num; i++) { logfile_candidate = zbx_dsprintf(logfile_candidate, "%s%s", directory, logfiles[i].filename); if (0 != zbx_stat(logfile_candidate, &file_buf))/* situation could have changed */ { zabbix_log(LOG_LEVEL_WARNING, "cannot stat [%s]: %s", logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } *mtime = (int)file_buf.st_mtime; /* must contain the latest mtime as possible */ if (file_buf.st_size < *lastlogsize) { *lastlogsize = 0; /* maintain backward compatibility */ } if (-1 == (fd = zbx_open(logfile_candidate, O_RDONLY))) { zabbix_log(LOG_LEVEL_WARNING, "cannot open [%s]: %s", logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } if ((off_t)-1 != lseek(fd, (off_t)*lastlogsize, SEEK_SET)) { if (-1 != (nbytes = zbx_read(fd, buffer, sizeof(buffer), encoding))) { if (0 != nbytes) { *lastlogsize += nbytes; *value = convert_to_utf8(buffer, nbytes, encoding); zbx_rtrim(*value, "\r\n "); ret = SUCCEED; break; /* return at this point */ } else /* EOF is reached, but there can be other files to try reading from */ { if (i == logfiles_num - 1) { ret = SUCCEED; /* EOF of the the most current file is reached */ break; } else { zbx_free(logfile_candidate); *lastlogsize = 0; close(fd); continue; /* try to read from more current file */ } } } else /* cannot read from the file */ { zabbix_log(LOG_LEVEL_WARNING, "cannot read from [%s]: %s", logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } } else /* cannot position in the file */ { zabbix_log(LOG_LEVEL_WARNING, "cannot set position to [%li] for [%s]: %s", *lastlogsize, logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } } /* trying to read from logfiles */ if (0 == logfiles_num) { zabbix_log(LOG_LEVEL_WARNING, "there are no files matching [%s] in [%s]", format, directory); } free_logfiles(&logfiles, &logfiles_alloc, &logfiles_num); if (0 != fd && -1 == close(fd)) { zabbix_log(LOG_LEVEL_WARNING, "could not close the file [%s]: %s", logfile_candidate, zbx_strerror(errno)); } #ifdef _WINDOWS if (0 != find_handle && -1 == _findclose(find_handle)) { zabbix_log(LOG_LEVEL_WARNING, "could not close the find directory handle: %s", zbx_strerror(errno)); } #else if (NULL != dir && -1 == closedir(dir)) { zabbix_log(LOG_LEVEL_WARNING, "could not close directory [%s]: %s", directory, zbx_strerror(errno)); } #endif zbx_free(logfile_candidate); zbx_free(directory); zbx_free(format); return ret; }
/****************************************************************************** * * * Function: zbx_module_docker_discovery * * * * Purpose: container discovery * * * * Return value: SYSINFO_RET_FAIL - function failed, item will be marked * * as not supported by zabbix * * SYSINFO_RET_OK - success * * * ******************************************************************************/ int zbx_module_docker_discovery(AGENT_REQUEST *request, AGENT_RESULT *result) { #include "zbxjson.h" zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_discovery()"); struct zbx_json j; if (stat_dir == NULL && zbx_docker_stat_detect() == SYSINFO_RET_FAIL) { zabbix_log(LOG_LEVEL_DEBUG, "docker.discovery is not available at the moment - no stat directory - empty discovery"); zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); zbx_json_close(&j); SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer)); zbx_json_free(&j); return SYSINFO_RET_OK; } char line[MAX_STRING_LEN], *p, *mpoint, *mtype, container; FILE *f; DIR *dir; zbx_stat_t sb; char *file = NULL; struct dirent *d; char *cgroup = "cpuacct/"; size_t ddir_size = strlen(base_dir) + strlen(cgroup) + strlen(stat_dir) + 2; char *ddir = malloc(ddir_size); zbx_strlcpy(ddir, base_dir, ddir_size); zbx_strlcat(ddir, cgroup, ddir_size); zbx_strlcat(ddir, stat_dir, ddir_size); if (NULL == (dir = opendir(ddir))) { zbx_error("%s: %s\n", ddir, zbx_strerror(errno)); } zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); char scontainerid[13]; while (NULL != (d = readdir(dir))) { if(0 == strcmp(d->d_name, ".") || 0 == strcmp(d->d_name, "..")) continue; file = zbx_dsprintf(file, "%s/%s", ddir, d->d_name); if (0 != zbx_stat(file, &sb) || 0 == S_ISDIR(sb.st_mode)) continue; zbx_json_addobject(&j, NULL); zbx_json_addstring(&j, "{#FCONTAINERID}", d->d_name, ZBX_JSON_TYPE_STRING); zbx_strlcpy(scontainerid, d->d_name, 13); zbx_json_addstring(&j, "{#SCONTAINERID}", scontainerid, ZBX_JSON_TYPE_STRING); zbx_json_close(&j); } if (0 != closedir(dir)) { zbx_error("%s: %s\n", ddir, zbx_strerror(errno)); } zbx_json_close(&j); SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer)); zbx_json_free(&j); return SYSINFO_RET_OK; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; zbx_uint64_t value = 0; int do_task; double memsize = 0; zbx_uint64_t proccount = 0; if (4 < request->nparam) return SYSINFO_RET_FAIL; procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) /* incorrect user name */ return SYSINFO_RET_FAIL; } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = DO_SUM; else if (0 == strcmp(param, "avg")) do_task = DO_AVG; else if (0 == strcmp(param, "max")) do_task = DO_MAX; else if (0 == strcmp(param, "min")) do_task = DO_MIN; else return SYSINFO_RET_FAIL; proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) return SYSINFO_RET_FAIL; while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; value = psinfo.pr_size; value <<= 10; /* kB to Byte */ if (0 == proccount++) memsize = value; else { if (do_task == DO_MAX) memsize = MAX(memsize, value); else if (do_task == DO_MIN) memsize = MIN(memsize, value); else memsize += value; } } closedir(dir); if (-1 != fd) close(fd); if (do_task == DO_AVG) { SET_DBL_RESULT(result, proccount == 0 ? 0 : memsize / proccount); } else { SET_UI64_RESULT(result, memsize); } return SYSINFO_RET_OK; }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; int zbx_proc_stat; zbx_uint64_t proccount = 0; if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { errno = 0; if (NULL == (usrinfo = getpwnam(param))) { if (0 == errno) SET_MSG_RESULT(result, zbx_strdup(NULL, "Specified user does not exist.")); else SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = ZBX_PROC_STAT_ALL; else if (0 == strcmp(param, "run")) zbx_proc_stat = ZBX_PROC_STAT_RUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = ZBX_PROC_STAT_SLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = ZBX_PROC_STAT_ZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (FAIL == check_procstate(&psinfo, zbx_proc_stat)) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; proccount++; } closedir(dir); if (-1 != fd) close(fd); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char *procname, *proccomm, *param; int proccount = 0, zbx_proc_stat; pid_t curr_pid = getpid(); if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information.")); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = -1; else if (0 == strcmp(param, "run")) zbx_proc_stat = PR_SRUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = PR_SSLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = PR_SZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { strscpy(filename, "/proc/"); zbx_strlcat(filename, entries->d_name,MAX_STRING_LEN); if (0 == zbx_stat(filename, &buf)) { proc = open(filename, O_RDONLY); if (-1 == proc) goto lbl_skip_procces; if (-1 == ioctl(proc, PIOCPSINFO, &psinfo)) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc.num[zabbix_agentd]. */ if (psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if (NULL != procname && '\0' != *procname) if (0 != strcmp(procname, psinfo.pr_fname)) goto lbl_skip_procces; if (NULL != usrinfo) if (usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if (-1 != zbx_proc_stat) if (psinfo.pr_sname != zbx_proc_stat) goto lbl_skip_procces; if (NULL != proccomm && '\0' != *proccomm) if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) goto lbl_skip_procces; proccount++; lbl_skip_procces: if (-1 != proc) close(proc); } } closedir(dir); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; zbx_uint64_t value = 0; int do_task; double memsize = 0; zbx_uint64_t proccount = 0; if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { errno = 0; if (NULL == (usrinfo = getpwnam(param))) { if (0 == errno) SET_MSG_RESULT(result, zbx_strdup(NULL, "Specified user does not exist.")); else SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; value = psinfo.pr_size; value <<= 10; /* kB to Byte */ if (0 == proccount++) memsize = value; else { if (ZBX_DO_MAX == do_task) memsize = MAX(memsize, value); else if (ZBX_DO_MIN == do_task) memsize = MIN(memsize, value); else memsize += value; } } closedir(dir); if (-1 != fd) close(fd); if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, proccount == 0 ? 0 : memsize / proccount); else SET_UI64_RESULT(result, memsize); return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: split_filename * * * * Purpose: separates filename to directory and to file format (regexp) * * * * Parameters: filename - first parameter of log[] item * * * * Return value: SUCCEED - on successful splitting * * FAIL - on unable to split sensibly * * * * Author: Dmitry Borovikov * * * * Comments: Allocates memory for "directory" and "format" only on success. * * On fail, memory, allocated for "directory" and "format", * * is freed. * * * ******************************************************************************/ static int split_filename(const char *filename, char **directory, char **format) { const char *__function_name = "split_filename"; const char *separator = NULL; struct stat buf; #ifdef _WINDOWS size_t sz; #endif/*_WINDOWS*/ zabbix_log(LOG_LEVEL_DEBUG, "In %s() filename:'%s'", __function_name, filename); assert(directory && !*directory); assert(format && !*format); if (!filename || *filename == '\0') { zabbix_log(LOG_LEVEL_DEBUG, "Cannot split empty path!"); return FAIL; } /* special processing for Windows world, since PATH part cannot be simply divided from REGEXP part (file format) */ #ifdef _WINDOWS for (sz = strlen(filename) - 1, separator = &filename[sz]; separator >= filename; separator--) { if (PATH_SEPARATOR != *separator) continue; zabbix_log(LOG_LEVEL_DEBUG, "%s() %s", __function_name, filename); zabbix_log(LOG_LEVEL_DEBUG, "%s() %*s", __function_name, separator - filename + 1, "^"); /* separator must be relative delimiter of the original filename */ if (FAIL == split_string(filename, separator, directory, format)) { zabbix_log(LOG_LEVEL_DEBUG, "Cannot split [%s].", filename); return FAIL; } sz = strlen(*directory); /* Windows world verification */ if (sz + 1 > MAX_PATH) { zabbix_log(LOG_LEVEL_DEBUG, "Directory path is too long. Cannot proceed."); zbx_free(*directory); zbx_free(*format); return FAIL; } /* Windows "stat" functions cannot get info about directories with '\' at the end of the path, */ /* except for root directories 'x:\' */ if (0 == zbx_stat(*directory, &buf) && S_ISDIR(buf.st_mode)) break; if (sz > 0 && PATH_SEPARATOR == (*directory)[sz - 1]) { (*directory)[sz - 1] = '\0'; if (0 == zbx_stat(*directory, &buf) && S_ISDIR(buf.st_mode)) { (*directory)[sz - 1] = PATH_SEPARATOR; break; } } zabbix_log(LOG_LEVEL_DEBUG, "Cannot find [%s] directory.", *directory); zbx_free(*directory); zbx_free(*format); } if (separator < filename) return FAIL; #else/* _WINDOWS */ separator = strrchr(filename, (int)PATH_SEPARATOR); if (separator == NULL) { zabbix_log(LOG_LEVEL_DEBUG, "Filename [%s] does not contain any path separator [%c].", filename, PATH_SEPARATOR); return FAIL; } if (SUCCEED != split_string(filename, separator, directory, format)) { zabbix_log(LOG_LEVEL_DEBUG, "Filename [%s] cannot be sensibly split by [%c].", filename, PATH_SEPARATOR); return FAIL; } /* Checking whether directory exists. */ if (-1 == zbx_stat(*directory, &buf)) { zabbix_log(LOG_LEVEL_WARNING, "Directory [%s] cannot be found on the file system.", *directory); zbx_free(*directory); zbx_free(*format); return FAIL; } /* Checking whether directory is really directory, not file. */ if (!S_ISDIR(buf.st_mode)) { zabbix_log(LOG_LEVEL_WARNING, "Directory [%s] is a file. Cannot proceed.", *directory); zbx_free(*directory); zbx_free(*format); return FAIL; } #endif/* _WINDOWS */ zabbix_log(LOG_LEVEL_DEBUG, "End %s() directory:'%s' format:'%s'", __function_name, *directory, *format); return SUCCEED; }