libnetdata.c 41 KB

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