summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/libnetdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnetdata/libnetdata.c')
-rw-r--r--src/libnetdata/libnetdata.c1066
1 files changed, 99 insertions, 967 deletions
diff --git a/src/libnetdata/libnetdata.c b/src/libnetdata/libnetdata.c
index b36a139d2..e21bf119d 100644
--- a/src/libnetdata/libnetdata.c
+++ b/src/libnetdata/libnetdata.c
@@ -2,6 +2,10 @@
#include "libnetdata.h"
+#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
+#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
+#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
+
#if !defined(MADV_DONTFORK)
#define MADV_DONTFORK 0
#endif
@@ -13,88 +17,13 @@
struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 };
#if defined(MADV_MERGEABLE)
-int enable_ksm = 1;
+int enable_ksm = CONFIG_BOOLEAN_AUTO;
#else
int enable_ksm = 0;
#endif
volatile sig_atomic_t netdata_exit = 0;
-#define MAX_JUDY_SIZE_TO_ARAL 24
-static bool judy_sizes_config[MAX_JUDY_SIZE_TO_ARAL + 1] = {
- [3] = true,
- [4] = true,
- [5] = true,
- [6] = true,
- [7] = true,
- [8] = true,
- [10] = true,
- [11] = true,
- [15] = true,
- [23] = true,
-};
-static ARAL *judy_sizes_aral[MAX_JUDY_SIZE_TO_ARAL + 1] = {};
-
-struct aral_statistics judy_sizes_aral_statistics = {};
-
-void aral_judy_init(void) {
- for(size_t Words = 0; Words <= MAX_JUDY_SIZE_TO_ARAL; Words++)
- if(judy_sizes_config[Words]) {
- char buf[30+1];
- snprintfz(buf, sizeof(buf) - 1, "judy-%zu", Words * sizeof(Word_t));
- judy_sizes_aral[Words] = aral_create(
- buf,
- Words * sizeof(Word_t),
- 0,
- 65536,
- &judy_sizes_aral_statistics,
- NULL, NULL, false, false);
- }
-}
-
-size_t judy_aral_overhead(void) {
- return aral_overhead_from_stats(&judy_sizes_aral_statistics);
-}
-
-size_t judy_aral_structures(void) {
- return aral_structures_from_stats(&judy_sizes_aral_statistics);
-}
-
-static ARAL *judy_size_aral(Word_t Words) {
- if(Words <= MAX_JUDY_SIZE_TO_ARAL && judy_sizes_aral[Words])
- return judy_sizes_aral[Words];
-
- return NULL;
-}
-
-inline Word_t JudyMalloc(Word_t Words) {
- Word_t Addr;
-
- ARAL *ar = judy_size_aral(Words);
- if(ar)
- Addr = (Word_t) aral_mallocz(ar);
- else
- Addr = (Word_t) mallocz(Words * sizeof(Word_t));
-
- return(Addr);
-}
-
-inline void JudyFree(void * PWord, Word_t Words) {
- ARAL *ar = judy_size_aral(Words);
- if(ar)
- aral_freez(ar, PWord);
- else
- freez(PWord);
-}
-
-Word_t JudyMallocVirtual(Word_t Words) {
- return JudyMalloc(Words);
-}
-
-void JudyFreeVirtual(void * PWord, Word_t Words) {
- JudyFree(PWord, Words);
-}
-
// ----------------------------------------------------------------------------
// memory allocation functions that handle failures
@@ -553,536 +482,6 @@ void json_fix_string(char *s) {
}
}
-unsigned char netdata_map_chart_names[256] = {
- [0] = '\0', //
- [1] = '_', //
- [2] = '_', //
- [3] = '_', //
- [4] = '_', //
- [5] = '_', //
- [6] = '_', //
- [7] = '_', //
- [8] = '_', //
- [9] = '_', //
- [10] = '_', //
- [11] = '_', //
- [12] = '_', //
- [13] = '_', //
- [14] = '_', //
- [15] = '_', //
- [16] = '_', //
- [17] = '_', //
- [18] = '_', //
- [19] = '_', //
- [20] = '_', //
- [21] = '_', //
- [22] = '_', //
- [23] = '_', //
- [24] = '_', //
- [25] = '_', //
- [26] = '_', //
- [27] = '_', //
- [28] = '_', //
- [29] = '_', //
- [30] = '_', //
- [31] = '_', //
- [32] = '_', //
- [33] = '_', // !
- [34] = '_', // "
- [35] = '_', // #
- [36] = '_', // $
- [37] = '_', // %
- [38] = '_', // &
- [39] = '_', // '
- [40] = '_', // (
- [41] = '_', // )
- [42] = '_', // *
- [43] = '_', // +
- [44] = '.', // ,
- [45] = '-', // -
- [46] = '.', // .
- [47] = '/', // /
- [48] = '0', // 0
- [49] = '1', // 1
- [50] = '2', // 2
- [51] = '3', // 3
- [52] = '4', // 4
- [53] = '5', // 5
- [54] = '6', // 6
- [55] = '7', // 7
- [56] = '8', // 8
- [57] = '9', // 9
- [58] = '_', // :
- [59] = '_', // ;
- [60] = '_', // <
- [61] = '_', // =
- [62] = '_', // >
- [63] = '_', // ?
- [64] = '_', // @
- [65] = 'a', // A
- [66] = 'b', // B
- [67] = 'c', // C
- [68] = 'd', // D
- [69] = 'e', // E
- [70] = 'f', // F
- [71] = 'g', // G
- [72] = 'h', // H
- [73] = 'i', // I
- [74] = 'j', // J
- [75] = 'k', // K
- [76] = 'l', // L
- [77] = 'm', // M
- [78] = 'n', // N
- [79] = 'o', // O
- [80] = 'p', // P
- [81] = 'q', // Q
- [82] = 'r', // R
- [83] = 's', // S
- [84] = 't', // T
- [85] = 'u', // U
- [86] = 'v', // V
- [87] = 'w', // W
- [88] = 'x', // X
- [89] = 'y', // Y
- [90] = 'z', // Z
- [91] = '_', // [
- [92] = '/', // backslash
- [93] = '_', // ]
- [94] = '_', // ^
- [95] = '_', // _
- [96] = '_', // `
- [97] = 'a', // a
- [98] = 'b', // b
- [99] = 'c', // c
- [100] = 'd', // d
- [101] = 'e', // e
- [102] = 'f', // f
- [103] = 'g', // g
- [104] = 'h', // h
- [105] = 'i', // i
- [106] = 'j', // j
- [107] = 'k', // k
- [108] = 'l', // l
- [109] = 'm', // m
- [110] = 'n', // n
- [111] = 'o', // o
- [112] = 'p', // p
- [113] = 'q', // q
- [114] = 'r', // r
- [115] = 's', // s
- [116] = 't', // t
- [117] = 'u', // u
- [118] = 'v', // v
- [119] = 'w', // w
- [120] = 'x', // x
- [121] = 'y', // y
- [122] = 'z', // z
- [123] = '_', // {
- [124] = '_', // |
- [125] = '_', // }
- [126] = '_', // ~
- [127] = '_', //
- [128] = '_', //
- [129] = '_', //
- [130] = '_', //
- [131] = '_', //
- [132] = '_', //
- [133] = '_', //
- [134] = '_', //
- [135] = '_', //
- [136] = '_', //
- [137] = '_', //
- [138] = '_', //
- [139] = '_', //
- [140] = '_', //
- [141] = '_', //
- [142] = '_', //
- [143] = '_', //
- [144] = '_', //
- [145] = '_', //
- [146] = '_', //
- [147] = '_', //
- [148] = '_', //
- [149] = '_', //
- [150] = '_', //
- [151] = '_', //
- [152] = '_', //
- [153] = '_', //
- [154] = '_', //
- [155] = '_', //
- [156] = '_', //
- [157] = '_', //
- [158] = '_', //
- [159] = '_', //
- [160] = '_', //
- [161] = '_', //
- [162] = '_', //
- [163] = '_', //
- [164] = '_', //
- [165] = '_', //
- [166] = '_', //
- [167] = '_', //
- [168] = '_', //
- [169] = '_', //
- [170] = '_', //
- [171] = '_', //
- [172] = '_', //
- [173] = '_', //
- [174] = '_', //
- [175] = '_', //
- [176] = '_', //
- [177] = '_', //
- [178] = '_', //
- [179] = '_', //
- [180] = '_', //
- [181] = '_', //
- [182] = '_', //
- [183] = '_', //
- [184] = '_', //
- [185] = '_', //
- [186] = '_', //
- [187] = '_', //
- [188] = '_', //
- [189] = '_', //
- [190] = '_', //
- [191] = '_', //
- [192] = '_', //
- [193] = '_', //
- [194] = '_', //
- [195] = '_', //
- [196] = '_', //
- [197] = '_', //
- [198] = '_', //
- [199] = '_', //
- [200] = '_', //
- [201] = '_', //
- [202] = '_', //
- [203] = '_', //
- [204] = '_', //
- [205] = '_', //
- [206] = '_', //
- [207] = '_', //
- [208] = '_', //
- [209] = '_', //
- [210] = '_', //
- [211] = '_', //
- [212] = '_', //
- [213] = '_', //
- [214] = '_', //
- [215] = '_', //
- [216] = '_', //
- [217] = '_', //
- [218] = '_', //
- [219] = '_', //
- [220] = '_', //
- [221] = '_', //
- [222] = '_', //
- [223] = '_', //
- [224] = '_', //
- [225] = '_', //
- [226] = '_', //
- [227] = '_', //
- [228] = '_', //
- [229] = '_', //
- [230] = '_', //
- [231] = '_', //
- [232] = '_', //
- [233] = '_', //
- [234] = '_', //
- [235] = '_', //
- [236] = '_', //
- [237] = '_', //
- [238] = '_', //
- [239] = '_', //
- [240] = '_', //
- [241] = '_', //
- [242] = '_', //
- [243] = '_', //
- [244] = '_', //
- [245] = '_', //
- [246] = '_', //
- [247] = '_', //
- [248] = '_', //
- [249] = '_', //
- [250] = '_', //
- [251] = '_', //
- [252] = '_', //
- [253] = '_', //
- [254] = '_', //
- [255] = '_' //
-};
-
-// make sure the supplied string
-// is good for a netdata chart/dimension ID/NAME
-void netdata_fix_chart_name(char *s) {
- while ((*s = netdata_map_chart_names[(unsigned char) *s])) s++;
-}
-
-unsigned char netdata_map_chart_ids[256] = {
- [0] = '\0', //
- [1] = '_', //
- [2] = '_', //
- [3] = '_', //
- [4] = '_', //
- [5] = '_', //
- [6] = '_', //
- [7] = '_', //
- [8] = '_', //
- [9] = '_', //
- [10] = '_', //
- [11] = '_', //
- [12] = '_', //
- [13] = '_', //
- [14] = '_', //
- [15] = '_', //
- [16] = '_', //
- [17] = '_', //
- [18] = '_', //
- [19] = '_', //
- [20] = '_', //
- [21] = '_', //
- [22] = '_', //
- [23] = '_', //
- [24] = '_', //
- [25] = '_', //
- [26] = '_', //
- [27] = '_', //
- [28] = '_', //
- [29] = '_', //
- [30] = '_', //
- [31] = '_', //
- [32] = '_', //
- [33] = '_', // !
- [34] = '_', // "
- [35] = '_', // #
- [36] = '_', // $
- [37] = '_', // %
- [38] = '_', // &
- [39] = '_', // '
- [40] = '_', // (
- [41] = '_', // )
- [42] = '_', // *
- [43] = '_', // +
- [44] = '.', // ,
- [45] = '-', // -
- [46] = '.', // .
- [47] = '_', // /
- [48] = '0', // 0
- [49] = '1', // 1
- [50] = '2', // 2
- [51] = '3', // 3
- [52] = '4', // 4
- [53] = '5', // 5
- [54] = '6', // 6
- [55] = '7', // 7
- [56] = '8', // 8
- [57] = '9', // 9
- [58] = '_', // :
- [59] = '_', // ;
- [60] = '_', // <
- [61] = '_', // =
- [62] = '_', // >
- [63] = '_', // ?
- [64] = '_', // @
- [65] = 'a', // A
- [66] = 'b', // B
- [67] = 'c', // C
- [68] = 'd', // D
- [69] = 'e', // E
- [70] = 'f', // F
- [71] = 'g', // G
- [72] = 'h', // H
- [73] = 'i', // I
- [74] = 'j', // J
- [75] = 'k', // K
- [76] = 'l', // L
- [77] = 'm', // M
- [78] = 'n', // N
- [79] = 'o', // O
- [80] = 'p', // P
- [81] = 'q', // Q
- [82] = 'r', // R
- [83] = 's', // S
- [84] = 't', // T
- [85] = 'u', // U
- [86] = 'v', // V
- [87] = 'w', // W
- [88] = 'x', // X
- [89] = 'y', // Y
- [90] = 'z', // Z
- [91] = '_', // [
- [92] = '_', // backslash
- [93] = '_', // ]
- [94] = '_', // ^
- [95] = '_', // _
- [96] = '_', // `
- [97] = 'a', // a
- [98] = 'b', // b
- [99] = 'c', // c
- [100] = 'd', // d
- [101] = 'e', // e
- [102] = 'f', // f
- [103] = 'g', // g
- [104] = 'h', // h
- [105] = 'i', // i
- [106] = 'j', // j
- [107] = 'k', // k
- [108] = 'l', // l
- [109] = 'm', // m
- [110] = 'n', // n
- [111] = 'o', // o
- [112] = 'p', // p
- [113] = 'q', // q
- [114] = 'r', // r
- [115] = 's', // s
- [116] = 't', // t
- [117] = 'u', // u
- [118] = 'v', // v
- [119] = 'w', // w
- [120] = 'x', // x
- [121] = 'y', // y
- [122] = 'z', // z
- [123] = '_', // {
- [124] = '_', // |
- [125] = '_', // }
- [126] = '_', // ~
- [127] = '_', //
- [128] = '_', //
- [129] = '_', //
- [130] = '_', //
- [131] = '_', //
- [132] = '_', //
- [133] = '_', //
- [134] = '_', //
- [135] = '_', //
- [136] = '_', //
- [137] = '_', //
- [138] = '_', //
- [139] = '_', //
- [140] = '_', //
- [141] = '_', //
- [142] = '_', //
- [143] = '_', //
- [144] = '_', //
- [145] = '_', //
- [146] = '_', //
- [147] = '_', //
- [148] = '_', //
- [149] = '_', //
- [150] = '_', //
- [151] = '_', //
- [152] = '_', //
- [153] = '_', //
- [154] = '_', //
- [155] = '_', //
- [156] = '_', //
- [157] = '_', //
- [158] = '_', //
- [159] = '_', //
- [160] = '_', //
- [161] = '_', //
- [162] = '_', //
- [163] = '_', //
- [164] = '_', //
- [165] = '_', //
- [166] = '_', //
- [167] = '_', //
- [168] = '_', //
- [169] = '_', //
- [170] = '_', //
- [171] = '_', //
- [172] = '_', //
- [173] = '_', //
- [174] = '_', //
- [175] = '_', //
- [176] = '_', //
- [177] = '_', //
- [178] = '_', //
- [179] = '_', //
- [180] = '_', //
- [181] = '_', //
- [182] = '_', //
- [183] = '_', //
- [184] = '_', //
- [185] = '_', //
- [186] = '_', //
- [187] = '_', //
- [188] = '_', //
- [189] = '_', //
- [190] = '_', //
- [191] = '_', //
- [192] = '_', //
- [193] = '_', //
- [194] = '_', //
- [195] = '_', //
- [196] = '_', //
- [197] = '_', //
- [198] = '_', //
- [199] = '_', //
- [200] = '_', //
- [201] = '_', //
- [202] = '_', //
- [203] = '_', //
- [204] = '_', //
- [205] = '_', //
- [206] = '_', //
- [207] = '_', //
- [208] = '_', //
- [209] = '_', //
- [210] = '_', //
- [211] = '_', //
- [212] = '_', //
- [213] = '_', //
- [214] = '_', //
- [215] = '_', //
- [216] = '_', //
- [217] = '_', //
- [218] = '_', //
- [219] = '_', //
- [220] = '_', //
- [221] = '_', //
- [222] = '_', //
- [223] = '_', //
- [224] = '_', //
- [225] = '_', //
- [226] = '_', //
- [227] = '_', //
- [228] = '_', //
- [229] = '_', //
- [230] = '_', //
- [231] = '_', //
- [232] = '_', //
- [233] = '_', //
- [234] = '_', //
- [235] = '_', //
- [236] = '_', //
- [237] = '_', //
- [238] = '_', //
- [239] = '_', //
- [240] = '_', //
- [241] = '_', //
- [242] = '_', //
- [243] = '_', //
- [244] = '_', //
- [245] = '_', //
- [246] = '_', //
- [247] = '_', //
- [248] = '_', //
- [249] = '_', //
- [250] = '_', //
- [251] = '_', //
- [252] = '_', //
- [253] = '_', //
- [254] = '_', //
- [255] = '_' //
-};
-
-// make sure the supplied string
-// is good for a netdata chart/dimension ID/NAME
-void netdata_fix_chart_id(char *s) {
- while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
-}
-
static int memory_file_open(const char *filename, size_t size) {
// netdata_log_info("memory_file_open('%s', %zu", filename, size);
@@ -1302,315 +701,6 @@ int snprintfz(char *dst, size_t n, const char *fmt, ...) {
return ret;
}
-static int is_procfs(const char *path, char **reason) {
-#if defined(__APPLE__) || defined(__FreeBSD__)
- (void)path;
- (void)reason;
-#else
- struct statfs stat;
-
- if (statfs(path, &stat) == -1) {
- if (reason)
- *reason = "failed to statfs()";
- return -1;
- }
-
-#if defined PROC_SUPER_MAGIC
- if (stat.f_type != PROC_SUPER_MAGIC) {
- if (reason)
- *reason = "type is not procfs";
- return -1;
- }
-#endif
-
-#endif
-
- return 0;
-}
-
-static int is_sysfs(const char *path, char **reason) {
-#if defined(__APPLE__) || defined(__FreeBSD__)
- (void)path;
- (void)reason;
-#else
- struct statfs stat;
-
- if (statfs(path, &stat) == -1) {
- if (reason)
- *reason = "failed to statfs()";
- return -1;
- }
-
-#if defined SYSFS_MAGIC
- if (stat.f_type != SYSFS_MAGIC) {
- if (reason)
- *reason = "type is not sysfs";
- return -1;
- }
-#endif
-
-#endif
-
- return 0;
-}
-
-int verify_netdata_host_prefix(bool log_msg) {
- if(!netdata_configured_host_prefix)
- netdata_configured_host_prefix = "";
-
- if(!*netdata_configured_host_prefix)
- return 0;
-
- char buffer[FILENAME_MAX + 1];
- char *path = netdata_configured_host_prefix;
- char *reason = "unknown reason";
- errno_clear();
-
- struct stat sb;
- if (stat(path, &sb) == -1) {
- reason = "failed to stat()";
- goto failed;
- }
-
- if((sb.st_mode & S_IFMT) != S_IFDIR) {
- errno = EINVAL;
- reason = "is not a directory";
- goto failed;
- }
-
- path = buffer;
- snprintfz(path, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
- if(is_procfs(path, &reason) == -1)
- goto failed;
-
- snprintfz(path, FILENAME_MAX, "%s/sys", netdata_configured_host_prefix);
- if(is_sysfs(path, &reason) == -1)
- goto failed;
-
- if (netdata_configured_host_prefix && *netdata_configured_host_prefix) {
- if (log_msg)
- netdata_log_info("Using host prefix directory '%s'", netdata_configured_host_prefix);
- }
-
- return 0;
-
-failed:
- if (log_msg)
- netdata_log_error("Ignoring host prefix '%s': path '%s' %s", netdata_configured_host_prefix, path, reason);
- netdata_configured_host_prefix = "";
- return -1;
-}
-
-char *strdupz_path_subpath(const char *path, const char *subpath) {
- if(unlikely(!path || !*path)) path = ".";
- if(unlikely(!subpath)) subpath = "";
-
- // skip trailing slashes in path
- size_t len = strlen(path);
- while(len > 0 && path[len - 1] == '/') len--;
-
- // skip leading slashes in subpath
- while(subpath[0] == '/') subpath++;
-
- // if the last character in path is / and (there is a subpath or path is now empty)
- // keep the trailing slash in path and remove the additional slash
- char *slash = "/";
- if(path[len] == '/' && (*subpath || len == 0)) {
- slash = "";
- len++;
- }
- else if(!*subpath) {
- // there is no subpath
- // no need for trailing slash
- slash = "";
- }
-
- char buffer[FILENAME_MAX + 1];
- snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, subpath);
- return strdupz(buffer);
-}
-
-int path_is_dir(const char *path, const char *subpath) {
- char *s = strdupz_path_subpath(path, subpath);
-
- size_t max_links = 100;
-
- int is_dir = 0;
- struct stat statbuf;
- while(max_links-- && stat(s, &statbuf) == 0) {
- if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
- is_dir = 1;
- break;
- }
- else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
- char buffer[FILENAME_MAX + 1];
- ssize_t l = readlink(s, buffer, FILENAME_MAX);
- if(l > 0) {
- buffer[l] = '\0';
- freez(s);
- s = strdupz(buffer);
- continue;
- }
- else {
- is_dir = 0;
- break;
- }
- }
- else {
- is_dir = 0;
- break;
- }
- }
-
- freez(s);
- return is_dir;
-}
-
-int path_is_file(const char *path, const char *subpath) {
- char *s = strdupz_path_subpath(path, subpath);
-
- size_t max_links = 100;
-
- int is_file = 0;
- struct stat statbuf;
- while(max_links-- && stat(s, &statbuf) == 0) {
- if((statbuf.st_mode & S_IFMT) == S_IFREG) {
- is_file = 1;
- break;
- }
- else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
- char buffer[FILENAME_MAX + 1];
- ssize_t l = readlink(s, buffer, FILENAME_MAX);
- if(l > 0) {
- buffer[l] = '\0';
- freez(s);
- s = strdupz(buffer);
- continue;
- }
- else {
- is_file = 0;
- break;
- }
- }
- else {
- is_file = 0;
- break;
- }
- }
-
- freez(s);
- return is_file;
-}
-
-void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath, int (*callback)(const char *filename, void *data, bool stock_config), void *data, size_t depth) {
- if(depth > 3) {
- netdata_log_error("CONFIG: Max directory depth reached while reading user path '%s', stock path '%s', subpath '%s'", user_path, stock_path, subpath);
- return;
- }
-
- if(!stock_path)
- stock_path = user_path;
-
- char *udir = strdupz_path_subpath(user_path, subpath);
- char *sdir = strdupz_path_subpath(stock_path, subpath);
-
- netdata_log_debug(D_HEALTH, "CONFIG traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
-
- DIR *dir = opendir(udir);
- if (!dir) {
- netdata_log_error("CONFIG cannot open user-config directory '%s'.", udir);
- }
- else {
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
- if( !de->d_name[0] ||
- (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
- (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- ) {
- netdata_log_debug(D_HEALTH, "CONFIG ignoring user-config directory '%s/%s'", udir, de->d_name);
- continue;
- }
-
- if(path_is_dir(udir, de->d_name)) {
- recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
- continue;
- }
- }
-
- if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
- size_t len = strlen(de->d_name);
- if(path_is_file(udir, de->d_name) &&
- len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
- char *filename = strdupz_path_subpath(udir, de->d_name);
- netdata_log_debug(D_HEALTH, "CONFIG calling callback for user file '%s'", filename);
- callback(filename, data, false);
- freez(filename);
- continue;
- }
- }
-
- netdata_log_debug(D_HEALTH, "CONFIG ignoring user-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
- }
-
- closedir(dir);
- }
-
- netdata_log_debug(D_HEALTH, "CONFIG traversing stock config directory '%s', user config directory '%s'", sdir, udir);
-
- dir = opendir(sdir);
- if (!dir) {
- netdata_log_error("CONFIG cannot open stock config directory '%s'.", sdir);
- }
- else {
- if (strcmp(udir, sdir)) {
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
- if( !de->d_name[0] ||
- (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
- (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- ) {
- netdata_log_debug(D_HEALTH, "CONFIG ignoring stock config directory '%s/%s'", sdir, de->d_name);
- continue;
- }
-
- if(path_is_dir(sdir, de->d_name)) {
- // we recurse in stock subdirectory, only when there is no corresponding
- // user subdirectory - to avoid reading the files twice
-
- if(!path_is_dir(udir, de->d_name))
- recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
-
- continue;
- }
- }
-
- if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
- size_t len = strlen(de->d_name);
- if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) &&
- len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
- char *filename = strdupz_path_subpath(sdir, de->d_name);
- netdata_log_debug(D_HEALTH, "CONFIG calling callback for stock file '%s'", filename);
- callback(filename, data, true);
- freez(filename);
- continue;
- }
-
- }
-
- netdata_log_debug(D_HEALTH, "CONFIG ignoring stock-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
- }
- }
- closedir(dir);
- }
-
- netdata_log_debug(D_HEALTH, "CONFIG done traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
-
- freez(udir);
- freez(sdir);
-}
-
// Returns the number of bytes read from the file if file_size is not NULL.
// The actual buffer has an extra byte set to zero (not included in the count).
char *read_by_filename(const char *filename, long *file_size)
@@ -1618,34 +708,37 @@ char *read_by_filename(const char *filename, long *file_size)
FILE *f = fopen(filename, "r");
if (!f)
return NULL;
+
if (fseek(f, 0, SEEK_END) < 0) {
fclose(f);
return NULL;
}
+
long size = ftell(f);
if (size <= 0 || fseek(f, 0, SEEK_END) < 0) {
fclose(f);
return NULL;
}
+
char *contents = callocz(size + 1, 1);
- if (!contents) {
- fclose(f);
- return NULL;
- }
if (fseek(f, 0, SEEK_SET) < 0) {
fclose(f);
freez(contents);
return NULL;
}
+
size_t res = fread(contents, 1, size, f);
if ( res != (size_t)size) {
freez(contents);
fclose(f);
return NULL;
}
+
fclose(f);
+
if (file_size)
*file_size = size;
+
return contents;
}
@@ -1685,7 +778,7 @@ BUFFER *run_command_and_get_output_to_buffer(const char *command, int max_line_l
POPEN_INSTANCE *pi = spawn_popen_run(command);
if(pi) {
char buffer[max_line_length + 1];
- while (fgets(buffer, max_line_length, pi->child_stdout_fp)) {
+ while (fgets(buffer, max_line_length, spawn_popen_stdout(pi))) {
buffer[max_line_length] = '\0';
buffer_strcat(wb, buffer);
}
@@ -1705,7 +798,7 @@ bool run_command_and_copy_output_to_stdout(const char *command, int max_line_len
if(pi) {
char buffer[max_line_length + 1];
- while (fgets(buffer, max_line_length, pi->child_stdout_fp))
+ while (fgets(buffer, max_line_length, spawn_popen_stdout(pi)))
fprintf(stdout, "%s", buffer);
spawn_popen_kill(pi);
@@ -1831,7 +924,6 @@ void timing_action(TIMING_ACTION action, TIMING_STEP step) {
}
}
-#ifdef ENABLE_HTTPS
int hash256_string(const unsigned char *string, size_t size, char *hash) {
EVP_MD_CTX *ctx;
ctx = EVP_MD_CTX_create();
@@ -1856,7 +948,6 @@ int hash256_string(const unsigned char *string, size_t size, char *hash) {
EVP_MD_CTX_destroy(ctx);
return 1;
}
-#endif
bool rrdr_relative_window_to_absolute(time_t *after, time_t *before, time_t now) {
@@ -1953,52 +1044,93 @@ bool rrdr_relative_window_to_absolute_query(time_t *after, time_t *before, time_
return (absolute_period_requested != 1);
}
-int netdata_base64_decode(const char *encoded, char *decoded, size_t decoded_size) {
- static const unsigned char base64_table[256] = {
- ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
- ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
- ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
- ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31,
- ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
- ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47,
- ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55,
- ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63,
- [0 ... '+' - 1] = 255,
- ['+' + 1 ... '/' - 1] = 255,
- ['9' + 1 ... 'A' - 1] = 255,
- ['Z' + 1 ... 'a' - 1] = 255,
- ['z' + 1 ... 255] = 255
- };
- size_t count = 0;
- unsigned int tmp = 0;
- int i, bit;
-
- if (decoded_size < 1)
- return 0; // Buffer size must be at least 1 for null termination
-
- for (i = 0, bit = 0; encoded[i]; i++) {
- unsigned char value = base64_table[(unsigned char)encoded[i]];
- if (value > 63)
- return -1; // Invalid character in input
-
- tmp = tmp << 6 | value;
- if (++bit == 4) {
- if (count + 3 >= decoded_size) break; // Stop decoding if buffer is full
- decoded[count++] = (tmp >> 16) & 0xFF;
- decoded[count++] = (tmp >> 8) & 0xFF;
- decoded[count++] = tmp & 0xFF;
- tmp = 0;
- bit = 0;
- }
- }
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
+static inline EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
+{
+ EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
- if (bit > 0 && count + 1 < decoded_size) {
- tmp <<= 6 * (4 - bit);
- if (bit > 2 && count + 1 < decoded_size) decoded[count++] = (tmp >> 16) & 0xFF;
- if (bit > 3 && count + 1 < decoded_size) decoded[count++] = (tmp >> 8) & 0xFF;
+ if (ctx != NULL) {
+ memset(ctx, 0, sizeof(*ctx));
}
+ return ctx;
+}
+
+static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
+{
+ OPENSSL_free(ctx);
+}
+#endif
- decoded[count] = '\0'; // Null terminate the output string
- return count;
+int netdata_base64_decode(unsigned char *out, const unsigned char *in, const int in_len)
+{
+ int outl;
+ unsigned char remaining_data[256];
+
+ EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
+ EVP_DecodeInit(ctx);
+ EVP_DecodeUpdate(ctx, out, &outl, in, in_len);
+ int remainder = 0;
+ EVP_DecodeFinal(ctx, remaining_data, &remainder);
+ EVP_ENCODE_CTX_free(ctx);
+ if (remainder)
+ return -1;
+
+ return outl;
}
+
+int netdata_base64_encode(unsigned char *encoded, const unsigned char *input, size_t input_size)
+{
+ return EVP_EncodeBlock(encoded, input, input_size);
+}
+
+// Keep internal implementation
+// int netdata_base64_decode_internal(const char *encoded, char *decoded, size_t decoded_size) {
+// static const unsigned char base64_table[256] = {
+// ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
+// ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
+// ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
+// ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31,
+// ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
+// ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47,
+// ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55,
+// ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63,
+// [0 ... '+' - 1] = 255,
+// ['+' + 1 ... '/' - 1] = 255,
+// ['9' + 1 ... 'A' - 1] = 255,
+// ['Z' + 1 ... 'a' - 1] = 255,
+// ['z' + 1 ... 255] = 255
+// };
+//
+// size_t count = 0;
+// unsigned int tmp = 0;
+// int i, bit;
+//
+// if (decoded_size < 1)
+// return 0; // Buffer size must be at least 1 for null termination
+//
+// for (i = 0, bit = 0; encoded[i]; i++) {
+// unsigned char value = base64_table[(unsigned char)encoded[i]];
+// if (value > 63)
+// return -1; // Invalid character in input
+//
+// tmp = tmp << 6 | value;
+// if (++bit == 4) {
+// if (count + 3 >= decoded_size) break; // Stop decoding if buffer is full
+// decoded[count++] = (tmp >> 16) & 0xFF;
+// decoded[count++] = (tmp >> 8) & 0xFF;
+// decoded[count++] = tmp & 0xFF;
+// tmp = 0;
+// bit = 0;
+// }
+// }
+//
+// if (bit > 0 && count + 1 < decoded_size) {
+// tmp <<= 6 * (4 - bit);
+// if (bit > 2 && count + 1 < decoded_size) decoded[count++] = (tmp >> 16) & 0xFF;
+// if (bit > 3 && count + 1 < decoded_size) decoded[count++] = (tmp >> 8) & 0xFF;
+// }
+//
+// decoded[count] = '\0'; // Null terminate the output string
+// return count;
+// }