mirror of
https://github.com/netdata/netdata.git
synced 2025-04-25 21:43:55 +00:00

* modularized all external plugins * added README.md in plugins * fixed title * fixed typo * relative link to external plugins * external plugins configuration README * added plugins link * remove plugins link * plugin names are links * added links to external plugins * removed unecessary spacing * list to table * added language * fixed typo * list to table on internal plugins * added more documentation to internal plugins * moved python, node, and bash code and configs into the external plugins * added statsd README * fix bug with corrupting config.h every 2nd compilation * moved all config files together with their code * more documentation * diskspace info * fixed broken links in apps.plugin * added backends docs * updated plugins readme * move nc-backend.sh to backends * created daemon directory * moved all code outside src/ * fixed readme identation * renamed plugins.d.plugin to plugins.d * updated readme * removed linux- from linux plugins * updated readme * updated readme * updated readme * updated readme * updated readme * updated readme * fixed README.md links * fixed netdata tree links * updated codacy, codeclimate and lgtm excluded paths * update CMakeLists.txt * updated automake options at top directory * libnetdata slit into directories * updated READMEs * updated READMEs * updated ARL docs * updated ARL docs * moved /plugins to /collectors * moved all external plugins outside plugins.d * updated codacy, codeclimate, lgtm * updated README * updated url * updated readme * updated readme * updated readme * updated readme * moved api and web into webserver * web/api web/gui web/server * modularized webserver * removed web/gui/version.txt
262 lines
7 KiB
C
262 lines
7 KiB
C
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "../libnetdata.h"
|
|
|
|
struct simple_pattern {
|
|
const char *match;
|
|
size_t len;
|
|
|
|
SIMPLE_PREFIX_MODE mode;
|
|
char negative;
|
|
|
|
struct simple_pattern *child;
|
|
|
|
struct simple_pattern *next;
|
|
};
|
|
|
|
static inline struct simple_pattern *parse_pattern(char *str, SIMPLE_PREFIX_MODE default_mode) {
|
|
// fprintf(stderr, "PARSING PATTERN: '%s'\n", str);
|
|
|
|
SIMPLE_PREFIX_MODE mode;
|
|
struct simple_pattern *child = NULL;
|
|
|
|
char *s = str, *c = str;
|
|
|
|
// skip asterisks in front
|
|
while(*c == '*') c++;
|
|
|
|
// find the next asterisk
|
|
while(*c && *c != '*') c++;
|
|
|
|
// do we have an asterisk in the middle?
|
|
if(*c == '*' && c[1] != '\0') {
|
|
// yes, we have
|
|
child = parse_pattern(c, default_mode);
|
|
c[1] = '\0';
|
|
}
|
|
|
|
// check what this one matches
|
|
|
|
size_t len = strlen(s);
|
|
if(len >= 2 && *s == '*' && s[len - 1] == '*') {
|
|
s[len - 1] = '\0';
|
|
s++;
|
|
mode = SIMPLE_PATTERN_SUBSTRING;
|
|
}
|
|
else if(len >= 1 && *s == '*') {
|
|
s++;
|
|
mode = SIMPLE_PATTERN_SUFFIX;
|
|
}
|
|
else if(len >= 1 && s[len - 1] == '*') {
|
|
s[len - 1] = '\0';
|
|
mode = SIMPLE_PATTERN_PREFIX;
|
|
}
|
|
else
|
|
mode = default_mode;
|
|
|
|
// allocate the structure
|
|
struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
|
|
if(*s) {
|
|
m->match = strdupz(s);
|
|
m->len = strlen(m->match);
|
|
m->mode = mode;
|
|
}
|
|
else {
|
|
m->mode = SIMPLE_PATTERN_SUBSTRING;
|
|
}
|
|
|
|
m->child = child;
|
|
|
|
return m;
|
|
}
|
|
|
|
SIMPLE_PATTERN *simple_pattern_create(const char *list, const char *separators, SIMPLE_PREFIX_MODE default_mode) {
|
|
struct simple_pattern *root = NULL, *last = NULL;
|
|
|
|
if(unlikely(!list || !*list)) return root;
|
|
|
|
int isseparator[256] = {
|
|
[' '] = 1 // space
|
|
, ['\t'] = 1 // tab
|
|
, ['\r'] = 1 // carriage return
|
|
, ['\n'] = 1 // new line
|
|
, ['\f'] = 1 // form feed
|
|
, ['\v'] = 1 // vertical tab
|
|
};
|
|
|
|
if (unlikely(separators && *separators)) {
|
|
memset(&isseparator[0], 0, sizeof(isseparator));
|
|
while(*separators) isseparator[(unsigned char)*separators++] = 1;
|
|
}
|
|
|
|
char *buf = mallocz(strlen(list) + 1);
|
|
const char *s = list;
|
|
|
|
while(s && *s) {
|
|
buf[0] = '\0';
|
|
char *c = buf;
|
|
|
|
char negative = 0;
|
|
|
|
// skip all spaces
|
|
while(isseparator[(unsigned char)*s])
|
|
s++;
|
|
|
|
if(*s == '!') {
|
|
negative = 1;
|
|
s++;
|
|
}
|
|
|
|
// empty string
|
|
if(unlikely(!*s))
|
|
break;
|
|
|
|
// find the next space
|
|
char escape = 0;
|
|
while(*s) {
|
|
if(*s == '\\' && !escape) {
|
|
escape = 1;
|
|
s++;
|
|
}
|
|
else {
|
|
if (isseparator[(unsigned char)*s] && !escape) {
|
|
s++;
|
|
break;
|
|
}
|
|
|
|
*c++ = *s++;
|
|
escape = 0;
|
|
}
|
|
}
|
|
|
|
// terminate our string
|
|
*c = '\0';
|
|
|
|
// if we matched the empty string, skip it
|
|
if(unlikely(!*buf))
|
|
continue;
|
|
|
|
// fprintf(stderr, "FOUND PATTERN: '%s'\n", buf);
|
|
struct simple_pattern *m = parse_pattern(buf, default_mode);
|
|
m->negative = negative;
|
|
|
|
// link it at the end
|
|
if(unlikely(!root))
|
|
root = last = m;
|
|
else {
|
|
last->next = m;
|
|
last = m;
|
|
}
|
|
}
|
|
|
|
freez(buf);
|
|
return (SIMPLE_PATTERN *)root;
|
|
}
|
|
|
|
static inline char *add_wildcarded(const char *matched, size_t matched_size, char *wildcarded, size_t *wildcarded_size) {
|
|
//if(matched_size) {
|
|
// char buf[matched_size + 1];
|
|
// strncpyz(buf, matched, matched_size);
|
|
// fprintf(stderr, "ADD WILDCARDED '%s' of length %zu\n", buf, matched_size);
|
|
//}
|
|
|
|
if(unlikely(wildcarded && *wildcarded_size && matched && *matched && matched_size)) {
|
|
size_t wss = *wildcarded_size - 1;
|
|
size_t len = (matched_size < wss)?matched_size:wss;
|
|
if(likely(len)) {
|
|
strncpyz(wildcarded, matched, len);
|
|
|
|
*wildcarded_size -= len;
|
|
return &wildcarded[len];
|
|
}
|
|
}
|
|
|
|
return wildcarded;
|
|
}
|
|
|
|
static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len, char *wildcarded, size_t *wildcarded_size) {
|
|
char *s;
|
|
|
|
if(m->len <= len) {
|
|
switch(m->mode) {
|
|
case SIMPLE_PATTERN_SUBSTRING:
|
|
if(!m->len) return 1;
|
|
if((s = strstr(str, m->match))) {
|
|
wildcarded = add_wildcarded(str, s - str, wildcarded, wildcarded_size);
|
|
if(!m->child) {
|
|
wildcarded = add_wildcarded(&s[m->len], len - (&s[m->len] - str), wildcarded, wildcarded_size);
|
|
return 1;
|
|
}
|
|
return match_pattern(m->child, &s[m->len], len - (s - str) - m->len, wildcarded, wildcarded_size);
|
|
}
|
|
break;
|
|
|
|
case SIMPLE_PATTERN_PREFIX:
|
|
if(unlikely(strncmp(str, m->match, m->len) == 0)) {
|
|
if(!m->child) {
|
|
wildcarded = add_wildcarded(&str[m->len], len - m->len, wildcarded, wildcarded_size);
|
|
return 1;
|
|
}
|
|
return match_pattern(m->child, &str[m->len], len - m->len, wildcarded, wildcarded_size);
|
|
}
|
|
break;
|
|
|
|
case SIMPLE_PATTERN_SUFFIX:
|
|
if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
|
|
wildcarded = add_wildcarded(str, len - m->len, wildcarded, wildcarded_size);
|
|
if(!m->child) return 1;
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case SIMPLE_PATTERN_EXACT:
|
|
default:
|
|
if(unlikely(strcmp(str, m->match) == 0)) {
|
|
if(!m->child) return 1;
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int simple_pattern_matches_extract(SIMPLE_PATTERN *list, const char *str, char *wildcarded, size_t wildcarded_size) {
|
|
struct simple_pattern *m, *root = (struct simple_pattern *)list;
|
|
|
|
if(unlikely(!root || !str || !*str)) return 0;
|
|
|
|
size_t len = strlen(str);
|
|
for(m = root; m ; m = m->next) {
|
|
char *ws = wildcarded;
|
|
size_t wss = wildcarded_size;
|
|
if(unlikely(ws)) *ws = '\0';
|
|
|
|
if (match_pattern(m, str, len, ws, &wss)) {
|
|
|
|
//if(ws && wss)
|
|
// fprintf(stderr, "FINAL WILDCARDED '%s' of length %zu\n", ws, strlen(ws));
|
|
|
|
if (m->negative) return 0;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void free_pattern(struct simple_pattern *m) {
|
|
if(!m) return;
|
|
|
|
free_pattern(m->child);
|
|
free_pattern(m->next);
|
|
freez((void *)m->match);
|
|
freez(m);
|
|
}
|
|
|
|
void simple_pattern_free(SIMPLE_PATTERN *list) {
|
|
if(!list) return;
|
|
|
|
free_pattern(((struct simple_pattern *)list));
|
|
}
|