libnetdata.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "libnetdata.h"
  3. #ifdef __APPLE__
  4. #define INHERIT_NONE 0
  5. #endif /* __APPLE__ */
  6. #if defined(__FreeBSD__) || defined(__APPLE__)
  7. # define O_NOATIME 0
  8. # define MADV_DONTFORK INHERIT_NONE
  9. #endif /* __FreeBSD__ || __APPLE__*/
  10. struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 };
  11. #ifdef MADV_MERGEABLE
  12. int enable_ksm = 1;
  13. #else
  14. int enable_ksm = 0;
  15. #endif
  16. volatile sig_atomic_t netdata_exit = 0;
  17. const char *program_version = VERSION;
  18. // ----------------------------------------------------------------------------
  19. // memory allocation functions that handle failures
  20. // although netdata does not use memory allocations too often (netdata tries to
  21. // maintain its memory footprint stable during runtime, i.e. all buffers are
  22. // allocated during initialization and are adapted to current use throughout
  23. // its lifetime), these can be used to override the default system allocation
  24. // routines.
  25. #ifdef NETDATA_LOG_ALLOCATIONS
  26. #warning NETDATA_LOG_ALLOCATIONS ENABLED - set log_thread_memory_allocations=1 on any thread to log all its allocations - or use log_allocations() to log them on demand
  27. static __thread struct memory_statistics {
  28. volatile ssize_t malloc_calls_made;
  29. volatile ssize_t calloc_calls_made;
  30. volatile ssize_t realloc_calls_made;
  31. volatile ssize_t strdup_calls_made;
  32. volatile ssize_t free_calls_made;
  33. volatile ssize_t memory_calls_made;
  34. volatile ssize_t allocated_memory;
  35. volatile ssize_t mmapped_memory;
  36. } memory_statistics = { 0, 0, 0, 0, 0, 0, 0, 0 };
  37. __thread size_t log_thread_memory_allocations = 0;
  38. inline void log_allocations_int(const char *file, const char *function, const unsigned long line) {
  39. static __thread struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
  40. fprintf(stderr, "%s MEMORY ALLOCATIONS: (%04lu@%s:%s): Allocated %zd KiB (%+zd B), mmapped %zd KiB (%+zd B): : malloc %zd (%+zd), calloc %zd (%+zd), realloc %zd (%+zd), strdup %zd (%+zd), free %zd (%+zd)\n",
  41. netdata_thread_tag(),
  42. line, file, function,
  43. (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
  44. (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
  45. memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
  46. memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
  47. memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
  48. memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
  49. memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
  50. );
  51. memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
  52. }
  53. static inline void mmap_accounting(size_t size) {
  54. if(log_thread_memory_allocations) {
  55. memory_statistics.memory_calls_made++;
  56. memory_statistics.mmapped_memory += size;
  57. }
  58. }
  59. void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
  60. memory_statistics.memory_calls_made++;
  61. memory_statistics.malloc_calls_made++;
  62. memory_statistics.allocated_memory += size;
  63. if(log_thread_memory_allocations)
  64. log_allocations_int(file, function, line);
  65. size_t *n = (size_t *)malloc(sizeof(size_t) + size);
  66. if (unlikely(!n)) fatal("mallocz() cannot allocate %zu bytes of memory.", size);
  67. *n = size;
  68. return (void *)&n[1];
  69. }
  70. void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
  71. size = nmemb * size;
  72. memory_statistics.memory_calls_made++;
  73. memory_statistics.calloc_calls_made++;
  74. memory_statistics.allocated_memory += size;
  75. if(log_thread_memory_allocations)
  76. log_allocations_int(file, function, line);
  77. size_t *n = (size_t *)calloc(1, sizeof(size_t) + size);
  78. if (unlikely(!n)) fatal("callocz() cannot allocate %zu bytes of memory.", size);
  79. *n = size;
  80. return (void *)&n[1];
  81. }
  82. void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
  83. if(!ptr) return mallocz_int(file, function, line, size);
  84. size_t *n = (size_t *)ptr;
  85. n--;
  86. size_t old_size = *n;
  87. n = realloc(n, sizeof(size_t) + size);
  88. if (unlikely(!n)) fatal("reallocz() cannot allocate %zu bytes of memory (from %zu bytes).", size, old_size);
  89. memory_statistics.memory_calls_made++;
  90. memory_statistics.realloc_calls_made++;
  91. memory_statistics.allocated_memory += (size - old_size);
  92. if(log_thread_memory_allocations)
  93. log_allocations_int(file, function, line);
  94. *n = size;
  95. return (void *)&n[1];
  96. }
  97. char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
  98. size_t size = strlen(s) + 1;
  99. memory_statistics.memory_calls_made++;
  100. memory_statistics.strdup_calls_made++;
  101. memory_statistics.allocated_memory += size;
  102. if(log_thread_memory_allocations)
  103. log_allocations_int(file, function, line);
  104. size_t *n = (size_t *)malloc(sizeof(size_t) + size);
  105. if (unlikely(!n)) fatal("strdupz() cannot allocate %zu bytes of memory.", size);
  106. *n = size;
  107. char *t = (char *)&n[1];
  108. strcpy(t, s);
  109. return t;
  110. }
  111. void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
  112. if(unlikely(!ptr)) return;
  113. size_t *n = (size_t *)ptr;
  114. n--;
  115. size_t size = *n;
  116. memory_statistics.memory_calls_made++;
  117. memory_statistics.free_calls_made++;
  118. memory_statistics.allocated_memory -= size;
  119. if(log_thread_memory_allocations)
  120. log_allocations_int(file, function, line);
  121. free(n);
  122. }
  123. #else
  124. char *strdupz(const char *s) {
  125. char *t = strdup(s);
  126. if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
  127. return t;
  128. }
  129. // If ptr is NULL, no operation is performed.
  130. void freez(void *ptr) {
  131. free(ptr);
  132. }
  133. void *mallocz(size_t size) {
  134. void *p = malloc(size);
  135. if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
  136. return p;
  137. }
  138. void *callocz(size_t nmemb, size_t size) {
  139. void *p = calloc(nmemb, size);
  140. if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
  141. return p;
  142. }
  143. void *reallocz(void *ptr, size_t size) {
  144. void *p = realloc(ptr, size);
  145. if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
  146. return p;
  147. }
  148. #endif
  149. // --------------------------------------------------------------------------------------------------------------------
  150. void json_escape_string(char *dst, const char *src, size_t size) {
  151. const char *t;
  152. char *d = dst, *e = &dst[size - 1];
  153. for(t = src; *t && d < e ;t++) {
  154. if(unlikely(*t == '\\' || *t == '"')) {
  155. if(unlikely(d + 1 >= e)) break;
  156. *d++ = '\\';
  157. }
  158. *d++ = *t;
  159. }
  160. *d = '\0';
  161. }
  162. void json_fix_string(char *s) {
  163. unsigned char c;
  164. while((c = (unsigned char)*s)) {
  165. if(unlikely(c == '\\'))
  166. *s++ = '/';
  167. else if(unlikely(c == '"'))
  168. *s++ = '\'';
  169. else if(unlikely(isspace(c) || iscntrl(c)))
  170. *s++ = ' ';
  171. else if(unlikely(!isprint(c) || c > 127))
  172. *s++ = '_';
  173. else
  174. s++;
  175. }
  176. }
  177. unsigned char netdata_map_chart_names[256] = {
  178. [0] = '\0', //
  179. [1] = '_', //
  180. [2] = '_', //
  181. [3] = '_', //
  182. [4] = '_', //
  183. [5] = '_', //
  184. [6] = '_', //
  185. [7] = '_', //
  186. [8] = '_', //
  187. [9] = '_', //
  188. [10] = '_', //
  189. [11] = '_', //
  190. [12] = '_', //
  191. [13] = '_', //
  192. [14] = '_', //
  193. [15] = '_', //
  194. [16] = '_', //
  195. [17] = '_', //
  196. [18] = '_', //
  197. [19] = '_', //
  198. [20] = '_', //
  199. [21] = '_', //
  200. [22] = '_', //
  201. [23] = '_', //
  202. [24] = '_', //
  203. [25] = '_', //
  204. [26] = '_', //
  205. [27] = '_', //
  206. [28] = '_', //
  207. [29] = '_', //
  208. [30] = '_', //
  209. [31] = '_', //
  210. [32] = '_', //
  211. [33] = '_', // !
  212. [34] = '_', // "
  213. [35] = '_', // #
  214. [36] = '_', // $
  215. [37] = '_', // %
  216. [38] = '_', // &
  217. [39] = '_', // '
  218. [40] = '_', // (
  219. [41] = '_', // )
  220. [42] = '_', // *
  221. [43] = '_', // +
  222. [44] = '.', // ,
  223. [45] = '-', // -
  224. [46] = '.', // .
  225. [47] = '/', // /
  226. [48] = '0', // 0
  227. [49] = '1', // 1
  228. [50] = '2', // 2
  229. [51] = '3', // 3
  230. [52] = '4', // 4
  231. [53] = '5', // 5
  232. [54] = '6', // 6
  233. [55] = '7', // 7
  234. [56] = '8', // 8
  235. [57] = '9', // 9
  236. [58] = '_', // :
  237. [59] = '_', // ;
  238. [60] = '_', // <
  239. [61] = '_', // =
  240. [62] = '_', // >
  241. [63] = '_', // ?
  242. [64] = '_', // @
  243. [65] = 'a', // A
  244. [66] = 'b', // B
  245. [67] = 'c', // C
  246. [68] = 'd', // D
  247. [69] = 'e', // E
  248. [70] = 'f', // F
  249. [71] = 'g', // G
  250. [72] = 'h', // H
  251. [73] = 'i', // I
  252. [74] = 'j', // J
  253. [75] = 'k', // K
  254. [76] = 'l', // L
  255. [77] = 'm', // M
  256. [78] = 'n', // N
  257. [79] = 'o', // O
  258. [80] = 'p', // P
  259. [81] = 'q', // Q
  260. [82] = 'r', // R
  261. [83] = 's', // S
  262. [84] = 't', // T
  263. [85] = 'u', // U
  264. [86] = 'v', // V
  265. [87] = 'w', // W
  266. [88] = 'x', // X
  267. [89] = 'y', // Y
  268. [90] = 'z', // Z
  269. [91] = '_', // [
  270. [92] = '/', // backslash
  271. [93] = '_', // ]
  272. [94] = '_', // ^
  273. [95] = '_', // _
  274. [96] = '_', // `
  275. [97] = 'a', // a
  276. [98] = 'b', // b
  277. [99] = 'c', // c
  278. [100] = 'd', // d
  279. [101] = 'e', // e
  280. [102] = 'f', // f
  281. [103] = 'g', // g
  282. [104] = 'h', // h
  283. [105] = 'i', // i
  284. [106] = 'j', // j
  285. [107] = 'k', // k
  286. [108] = 'l', // l
  287. [109] = 'm', // m
  288. [110] = 'n', // n
  289. [111] = 'o', // o
  290. [112] = 'p', // p
  291. [113] = 'q', // q
  292. [114] = 'r', // r
  293. [115] = 's', // s
  294. [116] = 't', // t
  295. [117] = 'u', // u
  296. [118] = 'v', // v
  297. [119] = 'w', // w
  298. [120] = 'x', // x
  299. [121] = 'y', // y
  300. [122] = 'z', // z
  301. [123] = '_', // {
  302. [124] = '_', // |
  303. [125] = '_', // }
  304. [126] = '_', // ~
  305. [127] = '_', //
  306. [128] = '_', //
  307. [129] = '_', //
  308. [130] = '_', //
  309. [131] = '_', //
  310. [132] = '_', //
  311. [133] = '_', //
  312. [134] = '_', //
  313. [135] = '_', //
  314. [136] = '_', //
  315. [137] = '_', //
  316. [138] = '_', //
  317. [139] = '_', //
  318. [140] = '_', //
  319. [141] = '_', //
  320. [142] = '_', //
  321. [143] = '_', //
  322. [144] = '_', //
  323. [145] = '_', //
  324. [146] = '_', //
  325. [147] = '_', //
  326. [148] = '_', //
  327. [149] = '_', //
  328. [150] = '_', //
  329. [151] = '_', //
  330. [152] = '_', //
  331. [153] = '_', //
  332. [154] = '_', //
  333. [155] = '_', //
  334. [156] = '_', //
  335. [157] = '_', //
  336. [158] = '_', //
  337. [159] = '_', //
  338. [160] = '_', //
  339. [161] = '_', //
  340. [162] = '_', //
  341. [163] = '_', //
  342. [164] = '_', //
  343. [165] = '_', //
  344. [166] = '_', //
  345. [167] = '_', //
  346. [168] = '_', //
  347. [169] = '_', //
  348. [170] = '_', //
  349. [171] = '_', //
  350. [172] = '_', //
  351. [173] = '_', //
  352. [174] = '_', //
  353. [175] = '_', //
  354. [176] = '_', //
  355. [177] = '_', //
  356. [178] = '_', //
  357. [179] = '_', //
  358. [180] = '_', //
  359. [181] = '_', //
  360. [182] = '_', //
  361. [183] = '_', //
  362. [184] = '_', //
  363. [185] = '_', //
  364. [186] = '_', //
  365. [187] = '_', //
  366. [188] = '_', //
  367. [189] = '_', //
  368. [190] = '_', //
  369. [191] = '_', //
  370. [192] = '_', //
  371. [193] = '_', //
  372. [194] = '_', //
  373. [195] = '_', //
  374. [196] = '_', //
  375. [197] = '_', //
  376. [198] = '_', //
  377. [199] = '_', //
  378. [200] = '_', //
  379. [201] = '_', //
  380. [202] = '_', //
  381. [203] = '_', //
  382. [204] = '_', //
  383. [205] = '_', //
  384. [206] = '_', //
  385. [207] = '_', //
  386. [208] = '_', //
  387. [209] = '_', //
  388. [210] = '_', //
  389. [211] = '_', //
  390. [212] = '_', //
  391. [213] = '_', //
  392. [214] = '_', //
  393. [215] = '_', //
  394. [216] = '_', //
  395. [217] = '_', //
  396. [218] = '_', //
  397. [219] = '_', //
  398. [220] = '_', //
  399. [221] = '_', //
  400. [222] = '_', //
  401. [223] = '_', //
  402. [224] = '_', //
  403. [225] = '_', //
  404. [226] = '_', //
  405. [227] = '_', //
  406. [228] = '_', //
  407. [229] = '_', //
  408. [230] = '_', //
  409. [231] = '_', //
  410. [232] = '_', //
  411. [233] = '_', //
  412. [234] = '_', //
  413. [235] = '_', //
  414. [236] = '_', //
  415. [237] = '_', //
  416. [238] = '_', //
  417. [239] = '_', //
  418. [240] = '_', //
  419. [241] = '_', //
  420. [242] = '_', //
  421. [243] = '_', //
  422. [244] = '_', //
  423. [245] = '_', //
  424. [246] = '_', //
  425. [247] = '_', //
  426. [248] = '_', //
  427. [249] = '_', //
  428. [250] = '_', //
  429. [251] = '_', //
  430. [252] = '_', //
  431. [253] = '_', //
  432. [254] = '_', //
  433. [255] = '_' //
  434. };
  435. // make sure the supplied string
  436. // is good for a netdata chart/dimension ID/NAME
  437. void netdata_fix_chart_name(char *s) {
  438. while ((*s = netdata_map_chart_names[(unsigned char) *s])) s++;
  439. }
  440. unsigned char netdata_map_chart_ids[256] = {
  441. [0] = '\0', //
  442. [1] = '_', //
  443. [2] = '_', //
  444. [3] = '_', //
  445. [4] = '_', //
  446. [5] = '_', //
  447. [6] = '_', //
  448. [7] = '_', //
  449. [8] = '_', //
  450. [9] = '_', //
  451. [10] = '_', //
  452. [11] = '_', //
  453. [12] = '_', //
  454. [13] = '_', //
  455. [14] = '_', //
  456. [15] = '_', //
  457. [16] = '_', //
  458. [17] = '_', //
  459. [18] = '_', //
  460. [19] = '_', //
  461. [20] = '_', //
  462. [21] = '_', //
  463. [22] = '_', //
  464. [23] = '_', //
  465. [24] = '_', //
  466. [25] = '_', //
  467. [26] = '_', //
  468. [27] = '_', //
  469. [28] = '_', //
  470. [29] = '_', //
  471. [30] = '_', //
  472. [31] = '_', //
  473. [32] = '_', //
  474. [33] = '_', // !
  475. [34] = '_', // "
  476. [35] = '_', // #
  477. [36] = '_', // $
  478. [37] = '_', // %
  479. [38] = '_', // &
  480. [39] = '_', // '
  481. [40] = '_', // (
  482. [41] = '_', // )
  483. [42] = '_', // *
  484. [43] = '_', // +
  485. [44] = '.', // ,
  486. [45] = '-', // -
  487. [46] = '.', // .
  488. [47] = '_', // /
  489. [48] = '0', // 0
  490. [49] = '1', // 1
  491. [50] = '2', // 2
  492. [51] = '3', // 3
  493. [52] = '4', // 4
  494. [53] = '5', // 5
  495. [54] = '6', // 6
  496. [55] = '7', // 7
  497. [56] = '8', // 8
  498. [57] = '9', // 9
  499. [58] = '_', // :
  500. [59] = '_', // ;
  501. [60] = '_', // <
  502. [61] = '_', // =
  503. [62] = '_', // >
  504. [63] = '_', // ?
  505. [64] = '_', // @
  506. [65] = 'a', // A
  507. [66] = 'b', // B
  508. [67] = 'c', // C
  509. [68] = 'd', // D
  510. [69] = 'e', // E
  511. [70] = 'f', // F
  512. [71] = 'g', // G
  513. [72] = 'h', // H
  514. [73] = 'i', // I
  515. [74] = 'j', // J
  516. [75] = 'k', // K
  517. [76] = 'l', // L
  518. [77] = 'm', // M
  519. [78] = 'n', // N
  520. [79] = 'o', // O
  521. [80] = 'p', // P
  522. [81] = 'q', // Q
  523. [82] = 'r', // R
  524. [83] = 's', // S
  525. [84] = 't', // T
  526. [85] = 'u', // U
  527. [86] = 'v', // V
  528. [87] = 'w', // W
  529. [88] = 'x', // X
  530. [89] = 'y', // Y
  531. [90] = 'z', // Z
  532. [91] = '_', // [
  533. [92] = '_', // backslash
  534. [93] = '_', // ]
  535. [94] = '_', // ^
  536. [95] = '_', // _
  537. [96] = '_', // `
  538. [97] = 'a', // a
  539. [98] = 'b', // b
  540. [99] = 'c', // c
  541. [100] = 'd', // d
  542. [101] = 'e', // e
  543. [102] = 'f', // f
  544. [103] = 'g', // g
  545. [104] = 'h', // h
  546. [105] = 'i', // i
  547. [106] = 'j', // j
  548. [107] = 'k', // k
  549. [108] = 'l', // l
  550. [109] = 'm', // m
  551. [110] = 'n', // n
  552. [111] = 'o', // o
  553. [112] = 'p', // p
  554. [113] = 'q', // q
  555. [114] = 'r', // r
  556. [115] = 's', // s
  557. [116] = 't', // t
  558. [117] = 'u', // u
  559. [118] = 'v', // v
  560. [119] = 'w', // w
  561. [120] = 'x', // x
  562. [121] = 'y', // y
  563. [122] = 'z', // z
  564. [123] = '_', // {
  565. [124] = '_', // |
  566. [125] = '_', // }
  567. [126] = '_', // ~
  568. [127] = '_', //
  569. [128] = '_', //
  570. [129] = '_', //
  571. [130] = '_', //
  572. [131] = '_', //
  573. [132] = '_', //
  574. [133] = '_', //
  575. [134] = '_', //
  576. [135] = '_', //
  577. [136] = '_', //
  578. [137] = '_', //
  579. [138] = '_', //
  580. [139] = '_', //
  581. [140] = '_', //
  582. [141] = '_', //
  583. [142] = '_', //
  584. [143] = '_', //
  585. [144] = '_', //
  586. [145] = '_', //
  587. [146] = '_', //
  588. [147] = '_', //
  589. [148] = '_', //
  590. [149] = '_', //
  591. [150] = '_', //
  592. [151] = '_', //
  593. [152] = '_', //
  594. [153] = '_', //
  595. [154] = '_', //
  596. [155] = '_', //
  597. [156] = '_', //
  598. [157] = '_', //
  599. [158] = '_', //
  600. [159] = '_', //
  601. [160] = '_', //
  602. [161] = '_', //
  603. [162] = '_', //
  604. [163] = '_', //
  605. [164] = '_', //
  606. [165] = '_', //
  607. [166] = '_', //
  608. [167] = '_', //
  609. [168] = '_', //
  610. [169] = '_', //
  611. [170] = '_', //
  612. [171] = '_', //
  613. [172] = '_', //
  614. [173] = '_', //
  615. [174] = '_', //
  616. [175] = '_', //
  617. [176] = '_', //
  618. [177] = '_', //
  619. [178] = '_', //
  620. [179] = '_', //
  621. [180] = '_', //
  622. [181] = '_', //
  623. [182] = '_', //
  624. [183] = '_', //
  625. [184] = '_', //
  626. [185] = '_', //
  627. [186] = '_', //
  628. [187] = '_', //
  629. [188] = '_', //
  630. [189] = '_', //
  631. [190] = '_', //
  632. [191] = '_', //
  633. [192] = '_', //
  634. [193] = '_', //
  635. [194] = '_', //
  636. [195] = '_', //
  637. [196] = '_', //
  638. [197] = '_', //
  639. [198] = '_', //
  640. [199] = '_', //
  641. [200] = '_', //
  642. [201] = '_', //
  643. [202] = '_', //
  644. [203] = '_', //
  645. [204] = '_', //
  646. [205] = '_', //
  647. [206] = '_', //
  648. [207] = '_', //
  649. [208] = '_', //
  650. [209] = '_', //
  651. [210] = '_', //
  652. [211] = '_', //
  653. [212] = '_', //
  654. [213] = '_', //
  655. [214] = '_', //
  656. [215] = '_', //
  657. [216] = '_', //
  658. [217] = '_', //
  659. [218] = '_', //
  660. [219] = '_', //
  661. [220] = '_', //
  662. [221] = '_', //
  663. [222] = '_', //
  664. [223] = '_', //
  665. [224] = '_', //
  666. [225] = '_', //
  667. [226] = '_', //
  668. [227] = '_', //
  669. [228] = '_', //
  670. [229] = '_', //
  671. [230] = '_', //
  672. [231] = '_', //
  673. [232] = '_', //
  674. [233] = '_', //
  675. [234] = '_', //
  676. [235] = '_', //
  677. [236] = '_', //
  678. [237] = '_', //
  679. [238] = '_', //
  680. [239] = '_', //
  681. [240] = '_', //
  682. [241] = '_', //
  683. [242] = '_', //
  684. [243] = '_', //
  685. [244] = '_', //
  686. [245] = '_', //
  687. [246] = '_', //
  688. [247] = '_', //
  689. [248] = '_', //
  690. [249] = '_', //
  691. [250] = '_', //
  692. [251] = '_', //
  693. [252] = '_', //
  694. [253] = '_', //
  695. [254] = '_', //
  696. [255] = '_' //
  697. };
  698. // make sure the supplied string
  699. // is good for a netdata chart/dimension ID/NAME
  700. void netdata_fix_chart_id(char *s) {
  701. while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
  702. }
  703. /*
  704. // http://stackoverflow.com/questions/7666509/hash-function-for-string
  705. uint32_t simple_hash(const char *name)
  706. {
  707. const char *s = name;
  708. uint32_t hash = 5381;
  709. int i;
  710. while((i = *s++)) hash = ((hash << 5) + hash) + i;
  711. // fprintf(stderr, "HASH: %lu %s\n", hash, name);
  712. return hash;
  713. }
  714. */
  715. /*
  716. // http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
  717. uint32_t simple_hash(const char *name) {
  718. unsigned char *s = (unsigned char *) name;
  719. uint32_t hval = 0x811c9dc5;
  720. // FNV-1a algorithm
  721. while (*s) {
  722. // multiply by the 32 bit FNV magic prime mod 2^32
  723. // NOTE: No need to optimize with left shifts.
  724. // GCC will use imul instruction anyway.
  725. // Tested with 'gcc -O3 -S'
  726. //hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
  727. hval *= 16777619;
  728. // xor the bottom with the current octet
  729. hval ^= (uint32_t) *s++;
  730. }
  731. // fprintf(stderr, "HASH: %u = %s\n", hval, name);
  732. return hval;
  733. }
  734. uint32_t simple_uhash(const char *name) {
  735. unsigned char *s = (unsigned char *) name;
  736. uint32_t hval = 0x811c9dc5, c;
  737. // FNV-1a algorithm
  738. while ((c = *s++)) {
  739. if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
  740. hval *= 16777619;
  741. hval ^= c;
  742. }
  743. return hval;
  744. }
  745. */
  746. /*
  747. // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
  748. // one at a time hash
  749. uint32_t simple_hash(const char *name) {
  750. unsigned char *s = (unsigned char *)name;
  751. uint32_t h = 0;
  752. while(*s) {
  753. h += *s++;
  754. h += (h << 10);
  755. h ^= (h >> 6);
  756. }
  757. h += (h << 3);
  758. h ^= (h >> 11);
  759. h += (h << 15);
  760. // fprintf(stderr, "HASH: %u = %s\n", h, name);
  761. return h;
  762. }
  763. */
  764. void strreverse(char *begin, char *end) {
  765. while (end > begin) {
  766. // clearer code.
  767. char aux = *end;
  768. *end-- = *begin;
  769. *begin++ = aux;
  770. }
  771. }
  772. char *strsep_on_1char(char **ptr, char c) {
  773. if(unlikely(!ptr || !*ptr))
  774. return NULL;
  775. // remember the position we started
  776. char *s = *ptr;
  777. // skip separators in front
  778. while(*s == c) s++;
  779. char *ret = s;
  780. // find the next separator
  781. while(*s++) {
  782. if(unlikely(*s == c)) {
  783. *s++ = '\0';
  784. *ptr = s;
  785. return ret;
  786. }
  787. }
  788. *ptr = NULL;
  789. return ret;
  790. }
  791. char *mystrsep(char **ptr, char *s) {
  792. char *p = "";
  793. while (p && !p[0] && *ptr) p = strsep(ptr, s);
  794. return (p);
  795. }
  796. char *trim(char *s) {
  797. // skip leading spaces
  798. while (*s && isspace(*s)) s++;
  799. if (!*s) return NULL;
  800. // skip tailing spaces
  801. // this way is way faster. Writes only one NUL char.
  802. ssize_t l = strlen(s);
  803. if (--l >= 0) {
  804. char *p = s + l;
  805. while (p > s && isspace(*p)) p--;
  806. *++p = '\0';
  807. }
  808. if (!*s) return NULL;
  809. return s;
  810. }
  811. inline char *trim_all(char *buffer) {
  812. char *d = buffer, *s = buffer;
  813. // skip spaces
  814. while(isspace(*s)) s++;
  815. while(*s) {
  816. // copy the non-space part
  817. while(*s && !isspace(*s)) *d++ = *s++;
  818. // add a space if we have to
  819. if(*s && isspace(*s)) {
  820. *d++ = ' ';
  821. s++;
  822. }
  823. // skip spaces
  824. while(isspace(*s)) s++;
  825. }
  826. *d = '\0';
  827. if(d > buffer) {
  828. d--;
  829. if(isspace(*d)) *d = '\0';
  830. }
  831. if(!buffer[0]) return NULL;
  832. return buffer;
  833. }
  834. static int memory_file_open(const char *filename, size_t size) {
  835. // info("memory_file_open('%s', %zu", filename, size);
  836. int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
  837. if (fd != -1) {
  838. if (lseek(fd, size, SEEK_SET) == (off_t) size) {
  839. if (write(fd, "", 1) == 1) {
  840. if (ftruncate(fd, size))
  841. error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
  842. }
  843. else error("Cannot write to file '%s' at position %zu.", filename, size);
  844. }
  845. else error("Cannot seek file '%s' to size %zu.", filename, size);
  846. }
  847. else error("Cannot create/open file '%s'.", filename);
  848. return fd;
  849. }
  850. static inline int madvise_sequential(void *mem, size_t len) {
  851. static int logger = 1;
  852. int ret = madvise(mem, len, MADV_SEQUENTIAL);
  853. if (ret != 0 && logger-- > 0) error("madvise(MADV_SEQUENTIAL) failed.");
  854. return ret;
  855. }
  856. static inline int madvise_dontfork(void *mem, size_t len) {
  857. static int logger = 1;
  858. int ret = madvise(mem, len, MADV_DONTFORK);
  859. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTFORK) failed.");
  860. return ret;
  861. }
  862. static inline int madvise_willneed(void *mem, size_t len) {
  863. static int logger = 1;
  864. int ret = madvise(mem, len, MADV_WILLNEED);
  865. if (ret != 0 && logger-- > 0) error("madvise(MADV_WILLNEED) failed.");
  866. return ret;
  867. }
  868. #if __linux__
  869. static inline int madvise_dontdump(void *mem, size_t len) {
  870. static int logger = 1;
  871. int ret = madvise(mem, len, MADV_DONTDUMP);
  872. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTDUMP) failed.");
  873. return ret;
  874. }
  875. #else
  876. static inline int madvise_dontdump(void *mem, size_t len) {
  877. UNUSED(mem);
  878. UNUSED(len);
  879. return 0;
  880. }
  881. #endif
  882. static inline int madvise_mergeable(void *mem, size_t len) {
  883. #ifdef MADV_MERGEABLE
  884. static int logger = 1;
  885. int ret = madvise(mem, len, MADV_MERGEABLE);
  886. if (ret != 0 && logger-- > 0) error("madvise(MADV_MERGEABLE) failed.");
  887. return ret;
  888. #else
  889. UNUSED(mem);
  890. UNUSED(len);
  891. return 0;
  892. #endif
  893. }
  894. void *netdata_mmap(const char *filename, size_t size, int flags, int ksm) {
  895. // info("netdata_mmap('%s', %zu", filename, size);
  896. // MAP_SHARED is used in memory mode map
  897. // MAP_PRIVATE is used in memory mode ram and save
  898. if(unlikely(!(flags & MAP_SHARED) && !(flags & MAP_PRIVATE)))
  899. fatal("Neither MAP_SHARED or MAP_PRIVATE were given to netdata_mmap()");
  900. if(unlikely((flags & MAP_SHARED) && (flags & MAP_PRIVATE)))
  901. fatal("Both MAP_SHARED and MAP_PRIVATE were given to netdata_mmap()");
  902. if(unlikely((flags & MAP_SHARED) && (!filename || !*filename)))
  903. fatal("MAP_SHARED requested, without a filename to netdata_mmap()");
  904. // don't enable ksm is the global setting is disabled
  905. if(unlikely(!enable_ksm)) ksm = 0;
  906. // KSM only merges anonymous (private) pages, never pagecache (file) pages
  907. // but MAP_PRIVATE without MAP_ANONYMOUS it fails too, so we need it always
  908. if((flags & MAP_PRIVATE)) flags |= MAP_ANONYMOUS;
  909. int fd = -1;
  910. void *mem = MAP_FAILED;
  911. if(filename && *filename) {
  912. // open/create the file to be used
  913. fd = memory_file_open(filename, size);
  914. if(fd == -1) goto cleanup;
  915. }
  916. int fd_for_mmap = fd;
  917. if(fd != -1 && (flags & MAP_PRIVATE)) {
  918. // this is MAP_PRIVATE allocation
  919. // no need for mmap() to use our fd
  920. // we will copy the file into the memory allocated
  921. fd_for_mmap = -1;
  922. }
  923. mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd_for_mmap, 0);
  924. if (mem != MAP_FAILED) {
  925. #ifdef NETDATA_LOG_ALLOCATIONS
  926. mmap_accounting(size);
  927. #endif
  928. // if we have a file open, but we didn't give it to mmap(),
  929. // we have to read the file into the memory block we allocated
  930. if(fd != -1 && fd_for_mmap == -1) {
  931. if (lseek(fd, 0, SEEK_SET) == 0) {
  932. if (read(fd, mem, size) != (ssize_t) size)
  933. info("Cannot read from file '%s'", filename);
  934. }
  935. else info("Cannot seek to beginning of file '%s'.", filename);
  936. }
  937. madvise_sequential(mem, size);
  938. madvise_dontfork(mem, size);
  939. madvise_dontdump(mem, size);
  940. if(flags & MAP_SHARED) madvise_willneed(mem, size);
  941. if(ksm) madvise_mergeable(mem, size);
  942. }
  943. cleanup:
  944. if(fd != -1) close(fd);
  945. if(mem == MAP_FAILED) return NULL;
  946. errno = 0;
  947. return mem;
  948. }
  949. int memory_file_save(const char *filename, void *mem, size_t size) {
  950. char tmpfilename[FILENAME_MAX + 1];
  951. snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
  952. int fd = open(tmpfilename, O_RDWR | O_CREAT | O_NOATIME, 0664);
  953. if (fd < 0) {
  954. error("Cannot create/open file '%s'.", filename);
  955. return -1;
  956. }
  957. if (write(fd, mem, size) != (ssize_t) size) {
  958. error("Cannot write to file '%s' %ld bytes.", filename, (long) size);
  959. close(fd);
  960. return -1;
  961. }
  962. close(fd);
  963. if (rename(tmpfilename, filename)) {
  964. error("Cannot rename '%s' to '%s'", tmpfilename, filename);
  965. return -1;
  966. }
  967. return 0;
  968. }
  969. int fd_is_valid(int fd) {
  970. return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
  971. }
  972. char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
  973. char *s = fgets(buf, (int)buf_size, fp);
  974. if (!s) return NULL;
  975. char *t = s;
  976. if (*t != '\0') {
  977. // find the string end
  978. while (*++t != '\0');
  979. // trim trailing spaces/newlines/tabs
  980. while (--t > s && *t == '\n')
  981. *t = '\0';
  982. }
  983. if (len)
  984. *len = t - s + 1;
  985. return s;
  986. }
  987. int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
  988. if(unlikely(!n)) return 0;
  989. int size = vsnprintf(dst, n, fmt, args);
  990. dst[n - 1] = '\0';
  991. if (unlikely((size_t) size > n)) size = (int)n;
  992. return size;
  993. }
  994. int snprintfz(char *dst, size_t n, const char *fmt, ...) {
  995. va_list args;
  996. va_start(args, fmt);
  997. int ret = vsnprintfz(dst, n, fmt, args);
  998. va_end(args);
  999. return ret;
  1000. }
  1001. /*
  1002. // poor man cycle counting
  1003. static unsigned long tsc;
  1004. void begin_tsc(void) {
  1005. unsigned long a, d;
  1006. asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
  1007. tsc = ((unsigned long)d << 32) | (unsigned long)a;
  1008. }
  1009. unsigned long end_tsc(void) {
  1010. unsigned long a, d;
  1011. asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
  1012. return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
  1013. }
  1014. */
  1015. int recursively_delete_dir(const char *path, const char *reason) {
  1016. DIR *dir = opendir(path);
  1017. if(!dir) {
  1018. error("Cannot read %s directory to be deleted '%s'", reason?reason:"", path);
  1019. return -1;
  1020. }
  1021. int ret = 0;
  1022. struct dirent *de = NULL;
  1023. while((de = readdir(dir))) {
  1024. if(de->d_type == DT_DIR
  1025. && (
  1026. (de->d_name[0] == '.' && de->d_name[1] == '\0')
  1027. || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1028. ))
  1029. continue;
  1030. char fullpath[FILENAME_MAX + 1];
  1031. snprintfz(fullpath, FILENAME_MAX, "%s/%s", path, de->d_name);
  1032. if(de->d_type == DT_DIR) {
  1033. int r = recursively_delete_dir(fullpath, reason);
  1034. if(r > 0) ret += r;
  1035. continue;
  1036. }
  1037. info("Deleting %s file '%s'", reason?reason:"", fullpath);
  1038. if(unlikely(unlink(fullpath) == -1))
  1039. error("Cannot delete %s file '%s'", reason?reason:"", fullpath);
  1040. else
  1041. ret++;
  1042. }
  1043. info("Deleting empty directory '%s'", path);
  1044. if(unlikely(rmdir(path) == -1))
  1045. error("Cannot delete empty directory '%s'", path);
  1046. else
  1047. ret++;
  1048. closedir(dir);
  1049. return ret;
  1050. }
  1051. static int is_virtual_filesystem(const char *path, char **reason) {
  1052. #if defined(__APPLE__) || defined(__FreeBSD__)
  1053. (void)path;
  1054. (void)reason;
  1055. #else
  1056. struct statfs stat;
  1057. // stat.f_fsid.__val[0] is a file system id
  1058. // stat.f_fsid.__val[1] is the inode
  1059. // so their combination uniquely identifies the file/dir
  1060. if (statfs(path, &stat) == -1) {
  1061. if(reason) *reason = "failed to statfs()";
  1062. return -1;
  1063. }
  1064. if(stat.f_fsid.__val[0] != 0 || stat.f_fsid.__val[1] != 0) {
  1065. errno = EINVAL;
  1066. if(reason) *reason = "is not a virtual file system";
  1067. return -1;
  1068. }
  1069. #endif
  1070. return 0;
  1071. }
  1072. int verify_netdata_host_prefix() {
  1073. if(!netdata_configured_host_prefix)
  1074. netdata_configured_host_prefix = "";
  1075. if(!*netdata_configured_host_prefix)
  1076. return 0;
  1077. char buffer[FILENAME_MAX + 1];
  1078. char *path = netdata_configured_host_prefix;
  1079. char *reason = "unknown reason";
  1080. errno = 0;
  1081. struct stat sb;
  1082. if (stat(path, &sb) == -1) {
  1083. reason = "failed to stat()";
  1084. goto failed;
  1085. }
  1086. if((sb.st_mode & S_IFMT) != S_IFDIR) {
  1087. errno = EINVAL;
  1088. reason = "is not a directory";
  1089. goto failed;
  1090. }
  1091. path = buffer;
  1092. snprintfz(path, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
  1093. if(is_virtual_filesystem(path, &reason) == -1)
  1094. goto failed;
  1095. snprintfz(path, FILENAME_MAX, "%s/sys", netdata_configured_host_prefix);
  1096. if(is_virtual_filesystem(path, &reason) == -1)
  1097. goto failed;
  1098. if(netdata_configured_host_prefix && *netdata_configured_host_prefix)
  1099. info("Using host prefix directory '%s'", netdata_configured_host_prefix);
  1100. return 0;
  1101. failed:
  1102. error("Ignoring host prefix '%s': path '%s' %s", netdata_configured_host_prefix, path, reason);
  1103. netdata_configured_host_prefix = "";
  1104. return -1;
  1105. }
  1106. char *strdupz_path_subpath(const char *path, const char *subpath) {
  1107. if(unlikely(!path || !*path)) path = ".";
  1108. if(unlikely(!subpath)) subpath = "";
  1109. // skip trailing slashes in path
  1110. size_t len = strlen(path);
  1111. while(len > 0 && path[len - 1] == '/') len--;
  1112. // skip leading slashes in subpath
  1113. while(subpath[0] == '/') subpath++;
  1114. // if the last character in path is / and (there is a subpath or path is now empty)
  1115. // keep the trailing slash in path and remove the additional slash
  1116. char *slash = "/";
  1117. if(path[len] == '/' && (*subpath || len == 0)) {
  1118. slash = "";
  1119. len++;
  1120. }
  1121. else if(!*subpath) {
  1122. // there is no subpath
  1123. // no need for trailing slash
  1124. slash = "";
  1125. }
  1126. char buffer[FILENAME_MAX + 1];
  1127. snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, subpath);
  1128. return strdupz(buffer);
  1129. }
  1130. int path_is_dir(const char *path, const char *subpath) {
  1131. char *s = strdupz_path_subpath(path, subpath);
  1132. size_t max_links = 100;
  1133. int is_dir = 0;
  1134. struct stat statbuf;
  1135. while(max_links-- && stat(s, &statbuf) == 0) {
  1136. if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
  1137. is_dir = 1;
  1138. break;
  1139. }
  1140. else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
  1141. char buffer[FILENAME_MAX + 1];
  1142. ssize_t l = readlink(s, buffer, FILENAME_MAX);
  1143. if(l > 0) {
  1144. buffer[l] = '\0';
  1145. freez(s);
  1146. s = strdupz(buffer);
  1147. continue;
  1148. }
  1149. else {
  1150. is_dir = 0;
  1151. break;
  1152. }
  1153. }
  1154. else {
  1155. is_dir = 0;
  1156. break;
  1157. }
  1158. }
  1159. freez(s);
  1160. return is_dir;
  1161. }
  1162. int path_is_file(const char *path, const char *subpath) {
  1163. char *s = strdupz_path_subpath(path, subpath);
  1164. size_t max_links = 100;
  1165. int is_file = 0;
  1166. struct stat statbuf;
  1167. while(max_links-- && stat(s, &statbuf) == 0) {
  1168. if((statbuf.st_mode & S_IFMT) == S_IFREG) {
  1169. is_file = 1;
  1170. break;
  1171. }
  1172. else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
  1173. char buffer[FILENAME_MAX + 1];
  1174. ssize_t l = readlink(s, buffer, FILENAME_MAX);
  1175. if(l > 0) {
  1176. buffer[l] = '\0';
  1177. freez(s);
  1178. s = strdupz(buffer);
  1179. continue;
  1180. }
  1181. else {
  1182. is_file = 0;
  1183. break;
  1184. }
  1185. }
  1186. else {
  1187. is_file = 0;
  1188. break;
  1189. }
  1190. }
  1191. freez(s);
  1192. return is_file;
  1193. }
  1194. void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath, int (*callback)(const char *filename, void *data), void *data, size_t depth) {
  1195. if(depth > 3) {
  1196. error("CONFIG: Max directory depth reached while reading user path '%s', stock path '%s', subpath '%s'", user_path, stock_path, subpath);
  1197. return;
  1198. }
  1199. char *udir = strdupz_path_subpath(user_path, subpath);
  1200. char *sdir = strdupz_path_subpath(stock_path, subpath);
  1201. debug(D_HEALTH, "CONFIG traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
  1202. DIR *dir = opendir(udir);
  1203. if (!dir) {
  1204. error("CONFIG cannot open user-config directory '%s'.", udir);
  1205. }
  1206. else {
  1207. struct dirent *de = NULL;
  1208. while((de = readdir(dir))) {
  1209. if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
  1210. if( !de->d_name[0] ||
  1211. (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
  1212. (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1213. ) {
  1214. debug(D_HEALTH, "CONFIG ignoring user-config directory '%s/%s'", udir, de->d_name);
  1215. continue;
  1216. }
  1217. if(path_is_dir(udir, de->d_name)) {
  1218. recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
  1219. continue;
  1220. }
  1221. }
  1222. if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
  1223. size_t len = strlen(de->d_name);
  1224. if(path_is_file(udir, de->d_name) &&
  1225. len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
  1226. char *filename = strdupz_path_subpath(udir, de->d_name);
  1227. debug(D_HEALTH, "CONFIG calling callback for user file '%s'", filename);
  1228. callback(filename, data);
  1229. freez(filename);
  1230. continue;
  1231. }
  1232. }
  1233. debug(D_HEALTH, "CONFIG ignoring user-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
  1234. }
  1235. closedir(dir);
  1236. }
  1237. debug(D_HEALTH, "CONFIG traversing stock config directory '%s', user config directory '%s'", sdir, udir);
  1238. dir = opendir(sdir);
  1239. if (!dir) {
  1240. error("CONFIG cannot open stock config directory '%s'.", sdir);
  1241. }
  1242. else {
  1243. if (strcmp(udir, sdir)) {
  1244. struct dirent *de = NULL;
  1245. while((de = readdir(dir))) {
  1246. if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
  1247. if( !de->d_name[0] ||
  1248. (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
  1249. (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1250. ) {
  1251. debug(D_HEALTH, "CONFIG ignoring stock config directory '%s/%s'", sdir, de->d_name);
  1252. continue;
  1253. }
  1254. if(path_is_dir(sdir, de->d_name)) {
  1255. // we recurse in stock subdirectory, only when there is no corresponding
  1256. // user subdirectory - to avoid reading the files twice
  1257. if(!path_is_dir(udir, de->d_name))
  1258. recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
  1259. continue;
  1260. }
  1261. }
  1262. if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
  1263. size_t len = strlen(de->d_name);
  1264. if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) &&
  1265. len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
  1266. char *filename = strdupz_path_subpath(sdir, de->d_name);
  1267. debug(D_HEALTH, "CONFIG calling callback for stock file '%s'", filename);
  1268. callback(filename, data);
  1269. freez(filename);
  1270. continue;
  1271. }
  1272. }
  1273. debug(D_HEALTH, "CONFIG ignoring stock-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
  1274. }
  1275. }
  1276. closedir(dir);
  1277. }
  1278. debug(D_HEALTH, "CONFIG done traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
  1279. freez(udir);
  1280. freez(sdir);
  1281. }
  1282. // Returns the number of bytes read from the file if file_size is not NULL.
  1283. // The actual buffer has an extra byte set to zero (not included in the count).
  1284. char *read_by_filename(char *filename, long *file_size)
  1285. {
  1286. FILE *f = fopen(filename, "r");
  1287. if (!f)
  1288. return NULL;
  1289. if (fseek(f, 0, SEEK_END) < 0) {
  1290. fclose(f);
  1291. return NULL;
  1292. }
  1293. long size = ftell(f);
  1294. if (size <= 0 || fseek(f, 0, SEEK_END) < 0) {
  1295. fclose(f);
  1296. return NULL;
  1297. }
  1298. char *contents = callocz(size + 1, 1);
  1299. if (!contents) {
  1300. fclose(f);
  1301. return NULL;
  1302. }
  1303. if (fseek(f, 0, SEEK_SET) < 0) {
  1304. fclose(f);
  1305. freez(contents);
  1306. return NULL;
  1307. }
  1308. size_t res = fread(contents, 1, size, f);
  1309. if ( res != (size_t)size) {
  1310. freez(contents);
  1311. fclose(f);
  1312. return NULL;
  1313. }
  1314. fclose(f);
  1315. if (file_size)
  1316. *file_size = size;
  1317. return contents;
  1318. }
  1319. char *find_and_replace(const char *src, const char *find, const char *replace, const char *where)
  1320. {
  1321. size_t size = strlen(src) + 1;
  1322. size_t find_len = strlen(find);
  1323. size_t repl_len = strlen(replace);
  1324. char *value, *dst;
  1325. if (likely(where))
  1326. size += (repl_len - find_len);
  1327. value = mallocz(size);
  1328. dst = value;
  1329. if (likely(where)) {
  1330. size_t count = where - src;
  1331. memmove(dst, src, count);
  1332. src += count;
  1333. dst += count;
  1334. memmove(dst, replace, repl_len);
  1335. src += find_len;
  1336. dst += repl_len;
  1337. }
  1338. strcpy(dst, src);
  1339. return value;
  1340. }
  1341. bool bitmap256_get_bit(BITMAP256 *ptr, uint8_t idx) {
  1342. if (unlikely(!ptr))
  1343. return false;
  1344. return (ptr->data[idx / 64] & (1ULL << (idx % 64)));
  1345. }
  1346. void bitmap256_set_bit(BITMAP256 *ptr, uint8_t idx, bool value) {
  1347. if (unlikely(!ptr))
  1348. return;
  1349. if (likely(value))
  1350. ptr->data[idx / 64] |= (1ULL << (idx % 64));
  1351. else
  1352. ptr->data[idx / 64] &= ~(1ULL << (idx % 64));
  1353. }