libnetdata.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074
  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. #define MAX_JUDY_SIZE_TO_ARAL 24
  19. static bool judy_sizes_config[MAX_JUDY_SIZE_TO_ARAL + 1] = {
  20. [3] = true,
  21. [4] = true,
  22. [5] = true,
  23. [6] = true,
  24. [7] = true,
  25. [8] = true,
  26. [10] = true,
  27. [11] = true,
  28. [15] = true,
  29. [23] = true,
  30. };
  31. static ARAL *judy_sizes_aral[MAX_JUDY_SIZE_TO_ARAL + 1] = {};
  32. struct aral_statistics judy_sizes_aral_statistics = {};
  33. void aral_judy_init(void) {
  34. for(size_t Words = 0; Words <= MAX_JUDY_SIZE_TO_ARAL; Words++)
  35. if(judy_sizes_config[Words]) {
  36. char buf[30+1];
  37. snprintfz(buf, 30, "judy-%zu", Words * sizeof(Word_t));
  38. judy_sizes_aral[Words] = aral_create(
  39. buf,
  40. Words * sizeof(Word_t),
  41. 0,
  42. 65536,
  43. &judy_sizes_aral_statistics,
  44. NULL, NULL, false, false);
  45. }
  46. }
  47. size_t judy_aral_overhead(void) {
  48. return aral_overhead_from_stats(&judy_sizes_aral_statistics);
  49. }
  50. size_t judy_aral_structures(void) {
  51. return aral_structures_from_stats(&judy_sizes_aral_statistics);
  52. }
  53. static ARAL *judy_size_aral(Word_t Words) {
  54. if(Words <= MAX_JUDY_SIZE_TO_ARAL && judy_sizes_aral[Words])
  55. return judy_sizes_aral[Words];
  56. return NULL;
  57. }
  58. inline Word_t JudyMalloc(Word_t Words) {
  59. Word_t Addr;
  60. ARAL *ar = judy_size_aral(Words);
  61. if(ar)
  62. Addr = (Word_t) aral_mallocz(ar);
  63. else
  64. Addr = (Word_t) mallocz(Words * sizeof(Word_t));
  65. return(Addr);
  66. }
  67. inline void JudyFree(void * PWord, Word_t Words) {
  68. ARAL *ar = judy_size_aral(Words);
  69. if(ar)
  70. aral_freez(ar, PWord);
  71. else
  72. freez(PWord);
  73. }
  74. Word_t JudyMallocVirtual(Word_t Words) {
  75. return JudyMalloc(Words);
  76. }
  77. void JudyFreeVirtual(void * PWord, Word_t Words) {
  78. JudyFree(PWord, Words);
  79. }
  80. // ----------------------------------------------------------------------------
  81. // memory allocation functions that handle failures
  82. // although netdata does not use memory allocations too often (netdata tries to
  83. // maintain its memory footprint stable during runtime, i.e. all buffers are
  84. // allocated during initialization and are adapted to current use throughout
  85. // its lifetime), these can be used to override the default system allocation
  86. // routines.
  87. #ifdef NETDATA_TRACE_ALLOCATIONS
  88. #warning NETDATA_TRACE_ALLOCATIONS ENABLED
  89. #include "Judy.h"
  90. #if defined(HAVE_DLSYM) && defined(ENABLE_DLSYM)
  91. #include <dlfcn.h>
  92. typedef void (*libc_function_t)(void);
  93. static void *malloc_first_run(size_t size);
  94. static void *(*libc_malloc)(size_t) = malloc_first_run;
  95. static void *calloc_first_run(size_t n, size_t size);
  96. static void *(*libc_calloc)(size_t, size_t) = calloc_first_run;
  97. static void *realloc_first_run(void *ptr, size_t size);
  98. static void *(*libc_realloc)(void *, size_t) = realloc_first_run;
  99. static void free_first_run(void *ptr);
  100. static void (*libc_free)(void *) = free_first_run;
  101. static char *strdup_first_run(const char *s);
  102. static char *(*libc_strdup)(const char *) = strdup_first_run;
  103. static size_t malloc_usable_size_first_run(void *ptr);
  104. #ifdef HAVE_MALLOC_USABLE_SIZE
  105. static size_t (*libc_malloc_usable_size)(void *) = malloc_usable_size_first_run;
  106. #else
  107. static size_t (*libc_malloc_usable_size)(void *) = NULL;
  108. #endif
  109. static void link_system_library_function(libc_function_t *func_pptr, const char *name, bool required) {
  110. *func_pptr = dlsym(RTLD_NEXT, name);
  111. if(!*func_pptr && required) {
  112. fprintf(stderr, "FATAL: Cannot find system's %s() function.\n", name);
  113. abort();
  114. }
  115. }
  116. static void *malloc_first_run(size_t size) {
  117. link_system_library_function((libc_function_t *) &libc_malloc, "malloc", true);
  118. return libc_malloc(size);
  119. }
  120. static void *calloc_first_run(size_t n, size_t size) {
  121. link_system_library_function((libc_function_t *) &libc_calloc, "calloc", true);
  122. return libc_calloc(n, size);
  123. }
  124. static void *realloc_first_run(void *ptr, size_t size) {
  125. link_system_library_function((libc_function_t *) &libc_realloc, "realloc", true);
  126. return libc_realloc(ptr, size);
  127. }
  128. static void free_first_run(void *ptr) {
  129. link_system_library_function((libc_function_t *) &libc_free, "free", true);
  130. libc_free(ptr);
  131. }
  132. static char *strdup_first_run(const char *s) {
  133. link_system_library_function((libc_function_t *) &libc_strdup, "strdup", true);
  134. return libc_strdup(s);
  135. }
  136. static size_t malloc_usable_size_first_run(void *ptr) {
  137. link_system_library_function((libc_function_t *) &libc_malloc_usable_size, "malloc_usable_size", false);
  138. if(libc_malloc_usable_size)
  139. return libc_malloc_usable_size(ptr);
  140. else
  141. return 0;
  142. }
  143. void *malloc(size_t size) {
  144. return mallocz(size);
  145. }
  146. void *calloc(size_t n, size_t size) {
  147. return callocz(n, size);
  148. }
  149. void *realloc(void *ptr, size_t size) {
  150. return reallocz(ptr, size);
  151. }
  152. void *reallocarray(void *ptr, size_t n, size_t size) {
  153. return reallocz(ptr, n * size);
  154. }
  155. void free(void *ptr) {
  156. freez(ptr);
  157. }
  158. char *strdup(const char *s) {
  159. return strdupz(s);
  160. }
  161. size_t malloc_usable_size(void *ptr) {
  162. return mallocz_usable_size(ptr);
  163. }
  164. #else // !HAVE_DLSYM
  165. static void *(*libc_malloc)(size_t) = malloc;
  166. static void *(*libc_calloc)(size_t, size_t) = calloc;
  167. static void *(*libc_realloc)(void *, size_t) = realloc;
  168. static void (*libc_free)(void *) = free;
  169. #ifdef HAVE_MALLOC_USABLE_SIZE
  170. static size_t (*libc_malloc_usable_size)(void *) = malloc_usable_size;
  171. #else
  172. static size_t (*libc_malloc_usable_size)(void *) = NULL;
  173. #endif
  174. #endif // HAVE_DLSYM
  175. void posix_memfree(void *ptr) {
  176. libc_free(ptr);
  177. }
  178. #define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
  179. #define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
  180. #define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
  181. struct malloc_header_signature {
  182. uint32_t magic;
  183. uint32_t size;
  184. struct malloc_trace *trace;
  185. };
  186. struct malloc_header {
  187. struct malloc_header_signature signature;
  188. uint8_t padding[(sizeof(struct malloc_header_signature) % MALLOC_ALIGNMENT) ? MALLOC_ALIGNMENT - (sizeof(struct malloc_header_signature) % MALLOC_ALIGNMENT) : 0];
  189. uint8_t data[];
  190. };
  191. static size_t malloc_header_size = sizeof(struct malloc_header);
  192. int malloc_trace_compare(void *A, void *B) {
  193. struct malloc_trace *a = A;
  194. struct malloc_trace *b = B;
  195. return strcmp(a->function, b->function);
  196. }
  197. static avl_tree_lock malloc_trace_index = {
  198. .avl_tree = {
  199. .root = NULL,
  200. .compar = malloc_trace_compare},
  201. .rwlock = NETDATA_RWLOCK_INITIALIZER
  202. };
  203. int malloc_trace_walkthrough(int (*callback)(void *item, void *data), void *data) {
  204. return avl_traverse_lock(&malloc_trace_index, callback, data);
  205. }
  206. NEVERNULL WARNUNUSED
  207. static struct malloc_trace *malloc_trace_find_or_create(const char *file, const char *function, size_t line) {
  208. struct malloc_trace tmp = {
  209. .line = line,
  210. .function = function,
  211. .file = file,
  212. };
  213. struct malloc_trace *t = (struct malloc_trace *)avl_search_lock(&malloc_trace_index, (avl_t *)&tmp);
  214. if(!t) {
  215. t = libc_calloc(1, sizeof(struct malloc_trace));
  216. if(!t) fatal("No memory");
  217. t->line = line;
  218. t->function = function;
  219. t->file = file;
  220. struct malloc_trace *t2 = (struct malloc_trace *)avl_insert_lock(&malloc_trace_index, (avl_t *)t);
  221. if(t2 != t)
  222. free(t);
  223. t = t2;
  224. }
  225. if(!t)
  226. fatal("Cannot insert to AVL");
  227. return t;
  228. }
  229. void malloc_trace_mmap(size_t size) {
  230. struct malloc_trace *p = malloc_trace_find_or_create("unknown", "netdata_mmap", 1);
  231. size_t_atomic_count(add, p->mmap_calls, 1);
  232. size_t_atomic_count(add, p->allocations, 1);
  233. size_t_atomic_bytes(add, p->bytes, size);
  234. }
  235. void malloc_trace_munmap(size_t size) {
  236. struct malloc_trace *p = malloc_trace_find_or_create("unknown", "netdata_mmap", 1);
  237. size_t_atomic_count(add, p->munmap_calls, 1);
  238. size_t_atomic_count(sub, p->allocations, 1);
  239. size_t_atomic_bytes(sub, p->bytes, size);
  240. }
  241. void *mallocz_int(size_t size, const char *file, const char *function, size_t line) {
  242. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  243. size_t_atomic_count(add, p->malloc_calls, 1);
  244. size_t_atomic_count(add, p->allocations, 1);
  245. size_t_atomic_bytes(add, p->bytes, size);
  246. struct malloc_header *t = (struct malloc_header *)libc_malloc(malloc_header_size + size);
  247. if (unlikely(!t)) fatal("mallocz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  248. t->signature.magic = 0x0BADCAFE;
  249. t->signature.trace = p;
  250. t->signature.size = size;
  251. #ifdef NETDATA_INTERNAL_CHECKS
  252. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  253. t->padding[i] = 0xFF;
  254. #endif
  255. return (void *)&t->data;
  256. }
  257. void *callocz_int(size_t nmemb, size_t size, const char *file, const char *function, size_t line) {
  258. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  259. size = nmemb * size;
  260. size_t_atomic_count(add, p->calloc_calls, 1);
  261. size_t_atomic_count(add, p->allocations, 1);
  262. size_t_atomic_bytes(add, p->bytes, size);
  263. struct malloc_header *t = (struct malloc_header *)libc_calloc(1, malloc_header_size + size);
  264. if (unlikely(!t)) fatal("mallocz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  265. t->signature.magic = 0x0BADCAFE;
  266. t->signature.trace = p;
  267. t->signature.size = size;
  268. #ifdef NETDATA_INTERNAL_CHECKS
  269. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  270. t->padding[i] = 0xFF;
  271. #endif
  272. return &t->data;
  273. }
  274. char *strdupz_int(const char *s, const char *file, const char *function, size_t line) {
  275. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  276. size_t size = strlen(s) + 1;
  277. size_t_atomic_count(add, p->strdup_calls, 1);
  278. size_t_atomic_count(add, p->allocations, 1);
  279. size_t_atomic_bytes(add, p->bytes, size);
  280. struct malloc_header *t = (struct malloc_header *)libc_malloc(malloc_header_size + size);
  281. if (unlikely(!t)) fatal("strdupz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  282. t->signature.magic = 0x0BADCAFE;
  283. t->signature.trace = p;
  284. t->signature.size = size;
  285. #ifdef NETDATA_INTERNAL_CHECKS
  286. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  287. t->padding[i] = 0xFF;
  288. #endif
  289. memcpy(&t->data, s, size);
  290. return (char *)&t->data;
  291. }
  292. static struct malloc_header *malloc_get_header(void *ptr, const char *caller, const char *file, const char *function, size_t line) {
  293. uint8_t *ret = (uint8_t *)ptr - malloc_header_size;
  294. struct malloc_header *t = (struct malloc_header *)ret;
  295. if(t->signature.magic != 0x0BADCAFE) {
  296. error("pointer %p is not our pointer (called %s() from %zu@%s, %s()).", ptr, caller, line, file, function);
  297. return NULL;
  298. }
  299. return t;
  300. }
  301. void *reallocz_int(void *ptr, size_t size, const char *file, const char *function, size_t line) {
  302. if(!ptr) return mallocz_int(size, file, function, line);
  303. struct malloc_header *t = malloc_get_header(ptr, __FUNCTION__, file, function, line);
  304. if(!t)
  305. return libc_realloc(ptr, size);
  306. if(t->signature.size == size) return ptr;
  307. size_t_atomic_count(add, t->signature.trace->free_calls, 1);
  308. size_t_atomic_count(sub, t->signature.trace->allocations, 1);
  309. size_t_atomic_bytes(sub, t->signature.trace->bytes, t->signature.size);
  310. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  311. size_t_atomic_count(add, p->realloc_calls, 1);
  312. size_t_atomic_count(add, p->allocations, 1);
  313. size_t_atomic_bytes(add, p->bytes, size);
  314. t = (struct malloc_header *)libc_realloc(t, malloc_header_size + size);
  315. if (unlikely(!t)) fatal("reallocz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  316. t->signature.magic = 0x0BADCAFE;
  317. t->signature.trace = p;
  318. t->signature.size = size;
  319. #ifdef NETDATA_INTERNAL_CHECKS
  320. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  321. t->padding[i] = 0xFF;
  322. #endif
  323. return (void *)&t->data;
  324. }
  325. size_t mallocz_usable_size_int(void *ptr, const char *file, const char *function, size_t line) {
  326. if(unlikely(!ptr)) return 0;
  327. struct malloc_header *t = malloc_get_header(ptr, __FUNCTION__, file, function, line);
  328. if(!t) {
  329. if(libc_malloc_usable_size)
  330. return libc_malloc_usable_size(ptr);
  331. else
  332. return 0;
  333. }
  334. return t->signature.size;
  335. }
  336. void freez_int(void *ptr, const char *file, const char *function, size_t line) {
  337. if(unlikely(!ptr)) return;
  338. struct malloc_header *t = malloc_get_header(ptr, __FUNCTION__, file, function, line);
  339. if(!t) {
  340. libc_free(ptr);
  341. return;
  342. }
  343. size_t_atomic_count(add, t->signature.trace->free_calls, 1);
  344. size_t_atomic_count(sub, t->signature.trace->allocations, 1);
  345. size_t_atomic_bytes(sub, t->signature.trace->bytes, t->signature.size);
  346. #ifdef NETDATA_INTERNAL_CHECKS
  347. // it should crash if it is used after freeing it
  348. memset(t, 0, malloc_header_size + t->signature.size);
  349. #endif
  350. libc_free(t);
  351. }
  352. #else
  353. char *strdupz(const char *s) {
  354. char *t = strdup(s);
  355. if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
  356. return t;
  357. }
  358. // If ptr is NULL, no operation is performed.
  359. void freez(void *ptr) {
  360. free(ptr);
  361. }
  362. void *mallocz(size_t size) {
  363. void *p = malloc(size);
  364. if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
  365. return p;
  366. }
  367. void *callocz(size_t nmemb, size_t size) {
  368. void *p = calloc(nmemb, size);
  369. if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
  370. return p;
  371. }
  372. void *reallocz(void *ptr, size_t size) {
  373. void *p = realloc(ptr, size);
  374. if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
  375. return p;
  376. }
  377. void posix_memfree(void *ptr) {
  378. free(ptr);
  379. }
  380. #endif
  381. // --------------------------------------------------------------------------------------------------------------------
  382. void json_escape_string(char *dst, const char *src, size_t size) {
  383. const char *t;
  384. char *d = dst, *e = &dst[size - 1];
  385. for(t = src; *t && d < e ;t++) {
  386. if(unlikely(*t == '\\' || *t == '"')) {
  387. if(unlikely(d + 1 >= e)) break;
  388. *d++ = '\\';
  389. }
  390. *d++ = *t;
  391. }
  392. *d = '\0';
  393. }
  394. void json_fix_string(char *s) {
  395. unsigned char c;
  396. while((c = (unsigned char)*s)) {
  397. if(unlikely(c == '\\'))
  398. *s++ = '/';
  399. else if(unlikely(c == '"'))
  400. *s++ = '\'';
  401. else if(unlikely(isspace(c) || iscntrl(c)))
  402. *s++ = ' ';
  403. else if(unlikely(!isprint(c) || c > 127))
  404. *s++ = '_';
  405. else
  406. s++;
  407. }
  408. }
  409. unsigned char netdata_map_chart_names[256] = {
  410. [0] = '\0', //
  411. [1] = '_', //
  412. [2] = '_', //
  413. [3] = '_', //
  414. [4] = '_', //
  415. [5] = '_', //
  416. [6] = '_', //
  417. [7] = '_', //
  418. [8] = '_', //
  419. [9] = '_', //
  420. [10] = '_', //
  421. [11] = '_', //
  422. [12] = '_', //
  423. [13] = '_', //
  424. [14] = '_', //
  425. [15] = '_', //
  426. [16] = '_', //
  427. [17] = '_', //
  428. [18] = '_', //
  429. [19] = '_', //
  430. [20] = '_', //
  431. [21] = '_', //
  432. [22] = '_', //
  433. [23] = '_', //
  434. [24] = '_', //
  435. [25] = '_', //
  436. [26] = '_', //
  437. [27] = '_', //
  438. [28] = '_', //
  439. [29] = '_', //
  440. [30] = '_', //
  441. [31] = '_', //
  442. [32] = '_', //
  443. [33] = '_', // !
  444. [34] = '_', // "
  445. [35] = '_', // #
  446. [36] = '_', // $
  447. [37] = '_', // %
  448. [38] = '_', // &
  449. [39] = '_', // '
  450. [40] = '_', // (
  451. [41] = '_', // )
  452. [42] = '_', // *
  453. [43] = '_', // +
  454. [44] = '.', // ,
  455. [45] = '-', // -
  456. [46] = '.', // .
  457. [47] = '/', // /
  458. [48] = '0', // 0
  459. [49] = '1', // 1
  460. [50] = '2', // 2
  461. [51] = '3', // 3
  462. [52] = '4', // 4
  463. [53] = '5', // 5
  464. [54] = '6', // 6
  465. [55] = '7', // 7
  466. [56] = '8', // 8
  467. [57] = '9', // 9
  468. [58] = '_', // :
  469. [59] = '_', // ;
  470. [60] = '_', // <
  471. [61] = '_', // =
  472. [62] = '_', // >
  473. [63] = '_', // ?
  474. [64] = '_', // @
  475. [65] = 'a', // A
  476. [66] = 'b', // B
  477. [67] = 'c', // C
  478. [68] = 'd', // D
  479. [69] = 'e', // E
  480. [70] = 'f', // F
  481. [71] = 'g', // G
  482. [72] = 'h', // H
  483. [73] = 'i', // I
  484. [74] = 'j', // J
  485. [75] = 'k', // K
  486. [76] = 'l', // L
  487. [77] = 'm', // M
  488. [78] = 'n', // N
  489. [79] = 'o', // O
  490. [80] = 'p', // P
  491. [81] = 'q', // Q
  492. [82] = 'r', // R
  493. [83] = 's', // S
  494. [84] = 't', // T
  495. [85] = 'u', // U
  496. [86] = 'v', // V
  497. [87] = 'w', // W
  498. [88] = 'x', // X
  499. [89] = 'y', // Y
  500. [90] = 'z', // Z
  501. [91] = '_', // [
  502. [92] = '/', // backslash
  503. [93] = '_', // ]
  504. [94] = '_', // ^
  505. [95] = '_', // _
  506. [96] = '_', // `
  507. [97] = 'a', // a
  508. [98] = 'b', // b
  509. [99] = 'c', // c
  510. [100] = 'd', // d
  511. [101] = 'e', // e
  512. [102] = 'f', // f
  513. [103] = 'g', // g
  514. [104] = 'h', // h
  515. [105] = 'i', // i
  516. [106] = 'j', // j
  517. [107] = 'k', // k
  518. [108] = 'l', // l
  519. [109] = 'm', // m
  520. [110] = 'n', // n
  521. [111] = 'o', // o
  522. [112] = 'p', // p
  523. [113] = 'q', // q
  524. [114] = 'r', // r
  525. [115] = 's', // s
  526. [116] = 't', // t
  527. [117] = 'u', // u
  528. [118] = 'v', // v
  529. [119] = 'w', // w
  530. [120] = 'x', // x
  531. [121] = 'y', // y
  532. [122] = 'z', // z
  533. [123] = '_', // {
  534. [124] = '_', // |
  535. [125] = '_', // }
  536. [126] = '_', // ~
  537. [127] = '_', //
  538. [128] = '_', //
  539. [129] = '_', //
  540. [130] = '_', //
  541. [131] = '_', //
  542. [132] = '_', //
  543. [133] = '_', //
  544. [134] = '_', //
  545. [135] = '_', //
  546. [136] = '_', //
  547. [137] = '_', //
  548. [138] = '_', //
  549. [139] = '_', //
  550. [140] = '_', //
  551. [141] = '_', //
  552. [142] = '_', //
  553. [143] = '_', //
  554. [144] = '_', //
  555. [145] = '_', //
  556. [146] = '_', //
  557. [147] = '_', //
  558. [148] = '_', //
  559. [149] = '_', //
  560. [150] = '_', //
  561. [151] = '_', //
  562. [152] = '_', //
  563. [153] = '_', //
  564. [154] = '_', //
  565. [155] = '_', //
  566. [156] = '_', //
  567. [157] = '_', //
  568. [158] = '_', //
  569. [159] = '_', //
  570. [160] = '_', //
  571. [161] = '_', //
  572. [162] = '_', //
  573. [163] = '_', //
  574. [164] = '_', //
  575. [165] = '_', //
  576. [166] = '_', //
  577. [167] = '_', //
  578. [168] = '_', //
  579. [169] = '_', //
  580. [170] = '_', //
  581. [171] = '_', //
  582. [172] = '_', //
  583. [173] = '_', //
  584. [174] = '_', //
  585. [175] = '_', //
  586. [176] = '_', //
  587. [177] = '_', //
  588. [178] = '_', //
  589. [179] = '_', //
  590. [180] = '_', //
  591. [181] = '_', //
  592. [182] = '_', //
  593. [183] = '_', //
  594. [184] = '_', //
  595. [185] = '_', //
  596. [186] = '_', //
  597. [187] = '_', //
  598. [188] = '_', //
  599. [189] = '_', //
  600. [190] = '_', //
  601. [191] = '_', //
  602. [192] = '_', //
  603. [193] = '_', //
  604. [194] = '_', //
  605. [195] = '_', //
  606. [196] = '_', //
  607. [197] = '_', //
  608. [198] = '_', //
  609. [199] = '_', //
  610. [200] = '_', //
  611. [201] = '_', //
  612. [202] = '_', //
  613. [203] = '_', //
  614. [204] = '_', //
  615. [205] = '_', //
  616. [206] = '_', //
  617. [207] = '_', //
  618. [208] = '_', //
  619. [209] = '_', //
  620. [210] = '_', //
  621. [211] = '_', //
  622. [212] = '_', //
  623. [213] = '_', //
  624. [214] = '_', //
  625. [215] = '_', //
  626. [216] = '_', //
  627. [217] = '_', //
  628. [218] = '_', //
  629. [219] = '_', //
  630. [220] = '_', //
  631. [221] = '_', //
  632. [222] = '_', //
  633. [223] = '_', //
  634. [224] = '_', //
  635. [225] = '_', //
  636. [226] = '_', //
  637. [227] = '_', //
  638. [228] = '_', //
  639. [229] = '_', //
  640. [230] = '_', //
  641. [231] = '_', //
  642. [232] = '_', //
  643. [233] = '_', //
  644. [234] = '_', //
  645. [235] = '_', //
  646. [236] = '_', //
  647. [237] = '_', //
  648. [238] = '_', //
  649. [239] = '_', //
  650. [240] = '_', //
  651. [241] = '_', //
  652. [242] = '_', //
  653. [243] = '_', //
  654. [244] = '_', //
  655. [245] = '_', //
  656. [246] = '_', //
  657. [247] = '_', //
  658. [248] = '_', //
  659. [249] = '_', //
  660. [250] = '_', //
  661. [251] = '_', //
  662. [252] = '_', //
  663. [253] = '_', //
  664. [254] = '_', //
  665. [255] = '_' //
  666. };
  667. // make sure the supplied string
  668. // is good for a netdata chart/dimension ID/NAME
  669. void netdata_fix_chart_name(char *s) {
  670. while ((*s = netdata_map_chart_names[(unsigned char) *s])) s++;
  671. }
  672. unsigned char netdata_map_chart_ids[256] = {
  673. [0] = '\0', //
  674. [1] = '_', //
  675. [2] = '_', //
  676. [3] = '_', //
  677. [4] = '_', //
  678. [5] = '_', //
  679. [6] = '_', //
  680. [7] = '_', //
  681. [8] = '_', //
  682. [9] = '_', //
  683. [10] = '_', //
  684. [11] = '_', //
  685. [12] = '_', //
  686. [13] = '_', //
  687. [14] = '_', //
  688. [15] = '_', //
  689. [16] = '_', //
  690. [17] = '_', //
  691. [18] = '_', //
  692. [19] = '_', //
  693. [20] = '_', //
  694. [21] = '_', //
  695. [22] = '_', //
  696. [23] = '_', //
  697. [24] = '_', //
  698. [25] = '_', //
  699. [26] = '_', //
  700. [27] = '_', //
  701. [28] = '_', //
  702. [29] = '_', //
  703. [30] = '_', //
  704. [31] = '_', //
  705. [32] = '_', //
  706. [33] = '_', // !
  707. [34] = '_', // "
  708. [35] = '_', // #
  709. [36] = '_', // $
  710. [37] = '_', // %
  711. [38] = '_', // &
  712. [39] = '_', // '
  713. [40] = '_', // (
  714. [41] = '_', // )
  715. [42] = '_', // *
  716. [43] = '_', // +
  717. [44] = '.', // ,
  718. [45] = '-', // -
  719. [46] = '.', // .
  720. [47] = '_', // /
  721. [48] = '0', // 0
  722. [49] = '1', // 1
  723. [50] = '2', // 2
  724. [51] = '3', // 3
  725. [52] = '4', // 4
  726. [53] = '5', // 5
  727. [54] = '6', // 6
  728. [55] = '7', // 7
  729. [56] = '8', // 8
  730. [57] = '9', // 9
  731. [58] = '_', // :
  732. [59] = '_', // ;
  733. [60] = '_', // <
  734. [61] = '_', // =
  735. [62] = '_', // >
  736. [63] = '_', // ?
  737. [64] = '_', // @
  738. [65] = 'a', // A
  739. [66] = 'b', // B
  740. [67] = 'c', // C
  741. [68] = 'd', // D
  742. [69] = 'e', // E
  743. [70] = 'f', // F
  744. [71] = 'g', // G
  745. [72] = 'h', // H
  746. [73] = 'i', // I
  747. [74] = 'j', // J
  748. [75] = 'k', // K
  749. [76] = 'l', // L
  750. [77] = 'm', // M
  751. [78] = 'n', // N
  752. [79] = 'o', // O
  753. [80] = 'p', // P
  754. [81] = 'q', // Q
  755. [82] = 'r', // R
  756. [83] = 's', // S
  757. [84] = 't', // T
  758. [85] = 'u', // U
  759. [86] = 'v', // V
  760. [87] = 'w', // W
  761. [88] = 'x', // X
  762. [89] = 'y', // Y
  763. [90] = 'z', // Z
  764. [91] = '_', // [
  765. [92] = '_', // backslash
  766. [93] = '_', // ]
  767. [94] = '_', // ^
  768. [95] = '_', // _
  769. [96] = '_', // `
  770. [97] = 'a', // a
  771. [98] = 'b', // b
  772. [99] = 'c', // c
  773. [100] = 'd', // d
  774. [101] = 'e', // e
  775. [102] = 'f', // f
  776. [103] = 'g', // g
  777. [104] = 'h', // h
  778. [105] = 'i', // i
  779. [106] = 'j', // j
  780. [107] = 'k', // k
  781. [108] = 'l', // l
  782. [109] = 'm', // m
  783. [110] = 'n', // n
  784. [111] = 'o', // o
  785. [112] = 'p', // p
  786. [113] = 'q', // q
  787. [114] = 'r', // r
  788. [115] = 's', // s
  789. [116] = 't', // t
  790. [117] = 'u', // u
  791. [118] = 'v', // v
  792. [119] = 'w', // w
  793. [120] = 'x', // x
  794. [121] = 'y', // y
  795. [122] = 'z', // z
  796. [123] = '_', // {
  797. [124] = '_', // |
  798. [125] = '_', // }
  799. [126] = '_', // ~
  800. [127] = '_', //
  801. [128] = '_', //
  802. [129] = '_', //
  803. [130] = '_', //
  804. [131] = '_', //
  805. [132] = '_', //
  806. [133] = '_', //
  807. [134] = '_', //
  808. [135] = '_', //
  809. [136] = '_', //
  810. [137] = '_', //
  811. [138] = '_', //
  812. [139] = '_', //
  813. [140] = '_', //
  814. [141] = '_', //
  815. [142] = '_', //
  816. [143] = '_', //
  817. [144] = '_', //
  818. [145] = '_', //
  819. [146] = '_', //
  820. [147] = '_', //
  821. [148] = '_', //
  822. [149] = '_', //
  823. [150] = '_', //
  824. [151] = '_', //
  825. [152] = '_', //
  826. [153] = '_', //
  827. [154] = '_', //
  828. [155] = '_', //
  829. [156] = '_', //
  830. [157] = '_', //
  831. [158] = '_', //
  832. [159] = '_', //
  833. [160] = '_', //
  834. [161] = '_', //
  835. [162] = '_', //
  836. [163] = '_', //
  837. [164] = '_', //
  838. [165] = '_', //
  839. [166] = '_', //
  840. [167] = '_', //
  841. [168] = '_', //
  842. [169] = '_', //
  843. [170] = '_', //
  844. [171] = '_', //
  845. [172] = '_', //
  846. [173] = '_', //
  847. [174] = '_', //
  848. [175] = '_', //
  849. [176] = '_', //
  850. [177] = '_', //
  851. [178] = '_', //
  852. [179] = '_', //
  853. [180] = '_', //
  854. [181] = '_', //
  855. [182] = '_', //
  856. [183] = '_', //
  857. [184] = '_', //
  858. [185] = '_', //
  859. [186] = '_', //
  860. [187] = '_', //
  861. [188] = '_', //
  862. [189] = '_', //
  863. [190] = '_', //
  864. [191] = '_', //
  865. [192] = '_', //
  866. [193] = '_', //
  867. [194] = '_', //
  868. [195] = '_', //
  869. [196] = '_', //
  870. [197] = '_', //
  871. [198] = '_', //
  872. [199] = '_', //
  873. [200] = '_', //
  874. [201] = '_', //
  875. [202] = '_', //
  876. [203] = '_', //
  877. [204] = '_', //
  878. [205] = '_', //
  879. [206] = '_', //
  880. [207] = '_', //
  881. [208] = '_', //
  882. [209] = '_', //
  883. [210] = '_', //
  884. [211] = '_', //
  885. [212] = '_', //
  886. [213] = '_', //
  887. [214] = '_', //
  888. [215] = '_', //
  889. [216] = '_', //
  890. [217] = '_', //
  891. [218] = '_', //
  892. [219] = '_', //
  893. [220] = '_', //
  894. [221] = '_', //
  895. [222] = '_', //
  896. [223] = '_', //
  897. [224] = '_', //
  898. [225] = '_', //
  899. [226] = '_', //
  900. [227] = '_', //
  901. [228] = '_', //
  902. [229] = '_', //
  903. [230] = '_', //
  904. [231] = '_', //
  905. [232] = '_', //
  906. [233] = '_', //
  907. [234] = '_', //
  908. [235] = '_', //
  909. [236] = '_', //
  910. [237] = '_', //
  911. [238] = '_', //
  912. [239] = '_', //
  913. [240] = '_', //
  914. [241] = '_', //
  915. [242] = '_', //
  916. [243] = '_', //
  917. [244] = '_', //
  918. [245] = '_', //
  919. [246] = '_', //
  920. [247] = '_', //
  921. [248] = '_', //
  922. [249] = '_', //
  923. [250] = '_', //
  924. [251] = '_', //
  925. [252] = '_', //
  926. [253] = '_', //
  927. [254] = '_', //
  928. [255] = '_' //
  929. };
  930. // make sure the supplied string
  931. // is good for a netdata chart/dimension ID/NAME
  932. void netdata_fix_chart_id(char *s) {
  933. while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
  934. }
  935. /*
  936. // http://stackoverflow.com/questions/7666509/hash-function-for-string
  937. uint32_t simple_hash(const char *name)
  938. {
  939. const char *s = name;
  940. uint32_t hash = 5381;
  941. int i;
  942. while((i = *s++)) hash = ((hash << 5) + hash) + i;
  943. // fprintf(stderr, "HASH: %lu %s\n", hash, name);
  944. return hash;
  945. }
  946. */
  947. /*
  948. // http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
  949. uint32_t simple_hash(const char *name) {
  950. unsigned char *s = (unsigned char *) name;
  951. uint32_t hval = 0x811c9dc5;
  952. // FNV-1a algorithm
  953. while (*s) {
  954. // multiply by the 32 bit FNV magic prime mod 2^32
  955. // NOTE: No need to optimize with left shifts.
  956. // GCC will use imul instruction anyway.
  957. // Tested with 'gcc -O3 -S'
  958. //hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
  959. hval *= 16777619;
  960. // xor the bottom with the current octet
  961. hval ^= (uint32_t) *s++;
  962. }
  963. // fprintf(stderr, "HASH: %u = %s\n", hval, name);
  964. return hval;
  965. }
  966. uint32_t simple_uhash(const char *name) {
  967. unsigned char *s = (unsigned char *) name;
  968. uint32_t hval = 0x811c9dc5, c;
  969. // FNV-1a algorithm
  970. while ((c = *s++)) {
  971. if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
  972. hval *= 16777619;
  973. hval ^= c;
  974. }
  975. return hval;
  976. }
  977. */
  978. /*
  979. // http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
  980. // one at a time hash
  981. uint32_t simple_hash(const char *name) {
  982. unsigned char *s = (unsigned char *)name;
  983. uint32_t h = 0;
  984. while(*s) {
  985. h += *s++;
  986. h += (h << 10);
  987. h ^= (h >> 6);
  988. }
  989. h += (h << 3);
  990. h ^= (h >> 11);
  991. h += (h << 15);
  992. // fprintf(stderr, "HASH: %u = %s\n", h, name);
  993. return h;
  994. }
  995. */
  996. void strreverse(char *begin, char *end) {
  997. while (end > begin) {
  998. // clearer code.
  999. char aux = *end;
  1000. *end-- = *begin;
  1001. *begin++ = aux;
  1002. }
  1003. }
  1004. char *strsep_on_1char(char **ptr, char c) {
  1005. if(unlikely(!ptr || !*ptr))
  1006. return NULL;
  1007. // remember the position we started
  1008. char *s = *ptr;
  1009. // skip separators in front
  1010. while(*s == c) s++;
  1011. char *ret = s;
  1012. // find the next separator
  1013. while(*s++) {
  1014. if(unlikely(*s == c)) {
  1015. *s++ = '\0';
  1016. *ptr = s;
  1017. return ret;
  1018. }
  1019. }
  1020. *ptr = NULL;
  1021. return ret;
  1022. }
  1023. char *mystrsep(char **ptr, char *s) {
  1024. char *p = "";
  1025. while (p && !p[0] && *ptr) p = strsep(ptr, s);
  1026. return (p);
  1027. }
  1028. char *trim(char *s) {
  1029. // skip leading spaces
  1030. while (*s && isspace(*s)) s++;
  1031. if (!*s) return NULL;
  1032. // skip tailing spaces
  1033. // this way is way faster. Writes only one NUL char.
  1034. ssize_t l = strlen(s);
  1035. if (--l >= 0) {
  1036. char *p = s + l;
  1037. while (p > s && isspace(*p)) p--;
  1038. *++p = '\0';
  1039. }
  1040. if (!*s) return NULL;
  1041. return s;
  1042. }
  1043. inline char *trim_all(char *buffer) {
  1044. char *d = buffer, *s = buffer;
  1045. // skip spaces
  1046. while(isspace(*s)) s++;
  1047. while(*s) {
  1048. // copy the non-space part
  1049. while(*s && !isspace(*s)) *d++ = *s++;
  1050. // add a space if we have to
  1051. if(*s && isspace(*s)) {
  1052. *d++ = ' ';
  1053. s++;
  1054. }
  1055. // skip spaces
  1056. while(isspace(*s)) s++;
  1057. }
  1058. *d = '\0';
  1059. if(d > buffer) {
  1060. d--;
  1061. if(isspace(*d)) *d = '\0';
  1062. }
  1063. if(!buffer[0]) return NULL;
  1064. return buffer;
  1065. }
  1066. static int memory_file_open(const char *filename, size_t size) {
  1067. // info("memory_file_open('%s', %zu", filename, size);
  1068. int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
  1069. if (fd != -1) {
  1070. if (lseek(fd, size, SEEK_SET) == (off_t) size) {
  1071. if (write(fd, "", 1) == 1) {
  1072. if (ftruncate(fd, size))
  1073. error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
  1074. }
  1075. else error("Cannot write to file '%s' at position %zu.", filename, size);
  1076. }
  1077. else error("Cannot seek file '%s' to size %zu.", filename, size);
  1078. }
  1079. else error("Cannot create/open file '%s'.", filename);
  1080. return fd;
  1081. }
  1082. inline int madvise_sequential(void *mem, size_t len) {
  1083. static int logger = 1;
  1084. int ret = madvise(mem, len, MADV_SEQUENTIAL);
  1085. if (ret != 0 && logger-- > 0) error("madvise(MADV_SEQUENTIAL) failed.");
  1086. return ret;
  1087. }
  1088. inline int madvise_random(void *mem, size_t len) {
  1089. static int logger = 1;
  1090. int ret = madvise(mem, len, MADV_RANDOM);
  1091. if (ret != 0 && logger-- > 0) error("madvise(MADV_RANDOM) failed.");
  1092. return ret;
  1093. }
  1094. inline int madvise_dontfork(void *mem, size_t len) {
  1095. static int logger = 1;
  1096. int ret = madvise(mem, len, MADV_DONTFORK);
  1097. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTFORK) failed.");
  1098. return ret;
  1099. }
  1100. inline int madvise_willneed(void *mem, size_t len) {
  1101. static int logger = 1;
  1102. int ret = madvise(mem, len, MADV_WILLNEED);
  1103. if (ret != 0 && logger-- > 0) error("madvise(MADV_WILLNEED) failed.");
  1104. return ret;
  1105. }
  1106. inline int madvise_dontneed(void *mem, size_t len) {
  1107. static int logger = 1;
  1108. int ret = madvise(mem, len, MADV_DONTNEED);
  1109. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTNEED) failed.");
  1110. return ret;
  1111. }
  1112. inline int madvise_dontdump(void *mem __maybe_unused, size_t len __maybe_unused) {
  1113. #if __linux__
  1114. static int logger = 1;
  1115. int ret = madvise(mem, len, MADV_DONTDUMP);
  1116. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTDUMP) failed.");
  1117. return ret;
  1118. #else
  1119. return 0;
  1120. #endif
  1121. }
  1122. inline int madvise_mergeable(void *mem __maybe_unused, size_t len __maybe_unused) {
  1123. #ifdef MADV_MERGEABLE
  1124. static int logger = 1;
  1125. int ret = madvise(mem, len, MADV_MERGEABLE);
  1126. if (ret != 0 && logger-- > 0) error("madvise(MADV_MERGEABLE) failed.");
  1127. return ret;
  1128. #else
  1129. return 0;
  1130. #endif
  1131. }
  1132. void *netdata_mmap(const char *filename, size_t size, int flags, int ksm, bool read_only, int *open_fd)
  1133. {
  1134. // info("netdata_mmap('%s', %zu", filename, size);
  1135. // MAP_SHARED is used in memory mode map
  1136. // MAP_PRIVATE is used in memory mode ram and save
  1137. if(unlikely(!(flags & MAP_SHARED) && !(flags & MAP_PRIVATE)))
  1138. fatal("Neither MAP_SHARED or MAP_PRIVATE were given to netdata_mmap()");
  1139. if(unlikely((flags & MAP_SHARED) && (flags & MAP_PRIVATE)))
  1140. fatal("Both MAP_SHARED and MAP_PRIVATE were given to netdata_mmap()");
  1141. if(unlikely((flags & MAP_SHARED) && (!filename || !*filename)))
  1142. fatal("MAP_SHARED requested, without a filename to netdata_mmap()");
  1143. // don't enable ksm is the global setting is disabled
  1144. if(unlikely(!enable_ksm)) ksm = 0;
  1145. // KSM only merges anonymous (private) pages, never pagecache (file) pages
  1146. // but MAP_PRIVATE without MAP_ANONYMOUS it fails too, so we need it always
  1147. if((flags & MAP_PRIVATE)) flags |= MAP_ANONYMOUS;
  1148. int fd = -1;
  1149. void *mem = MAP_FAILED;
  1150. if(filename && *filename) {
  1151. // open/create the file to be used
  1152. fd = memory_file_open(filename, size);
  1153. if(fd == -1) goto cleanup;
  1154. }
  1155. int fd_for_mmap = fd;
  1156. if(fd != -1 && (flags & MAP_PRIVATE)) {
  1157. // this is MAP_PRIVATE allocation
  1158. // no need for mmap() to use our fd
  1159. // we will copy the file into the memory allocated
  1160. fd_for_mmap = -1;
  1161. }
  1162. mem = mmap(NULL, size, read_only ? PROT_READ : PROT_READ | PROT_WRITE, flags, fd_for_mmap, 0);
  1163. if (mem != MAP_FAILED) {
  1164. #ifdef NETDATA_TRACE_ALLOCATIONS
  1165. malloc_trace_mmap(size);
  1166. #endif
  1167. // if we have a file open, but we didn't give it to mmap(),
  1168. // we have to read the file into the memory block we allocated
  1169. if(fd != -1 && fd_for_mmap == -1) {
  1170. if (lseek(fd, 0, SEEK_SET) == 0) {
  1171. if (read(fd, mem, size) != (ssize_t) size)
  1172. info("Cannot read from file '%s'", filename);
  1173. }
  1174. else info("Cannot seek to beginning of file '%s'.", filename);
  1175. }
  1176. // madvise_sequential(mem, size);
  1177. madvise_dontfork(mem, size);
  1178. madvise_dontdump(mem, size);
  1179. // if(flags & MAP_SHARED) madvise_willneed(mem, size);
  1180. if(ksm) madvise_mergeable(mem, size);
  1181. }
  1182. cleanup:
  1183. if(fd != -1) {
  1184. if (open_fd)
  1185. *open_fd = fd;
  1186. else
  1187. close(fd);
  1188. }
  1189. if(mem == MAP_FAILED) return NULL;
  1190. errno = 0;
  1191. return mem;
  1192. }
  1193. int netdata_munmap(void *ptr, size_t size) {
  1194. #ifdef NETDATA_TRACE_ALLOCATIONS
  1195. malloc_trace_munmap(size);
  1196. #endif
  1197. return munmap(ptr, size);
  1198. }
  1199. int memory_file_save(const char *filename, void *mem, size_t size) {
  1200. char tmpfilename[FILENAME_MAX + 1];
  1201. snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
  1202. int fd = open(tmpfilename, O_RDWR | O_CREAT | O_NOATIME, 0664);
  1203. if (fd < 0) {
  1204. error("Cannot create/open file '%s'.", filename);
  1205. return -1;
  1206. }
  1207. if (write(fd, mem, size) != (ssize_t) size) {
  1208. error("Cannot write to file '%s' %ld bytes.", filename, (long) size);
  1209. close(fd);
  1210. return -1;
  1211. }
  1212. close(fd);
  1213. if (rename(tmpfilename, filename)) {
  1214. error("Cannot rename '%s' to '%s'", tmpfilename, filename);
  1215. return -1;
  1216. }
  1217. return 0;
  1218. }
  1219. int fd_is_valid(int fd) {
  1220. return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
  1221. }
  1222. char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
  1223. char *s = fgets(buf, (int)buf_size, fp);
  1224. if (!s) return NULL;
  1225. char *t = s;
  1226. if (*t != '\0') {
  1227. // find the string end
  1228. while (*++t != '\0');
  1229. // trim trailing spaces/newlines/tabs
  1230. while (--t > s && *t == '\n')
  1231. *t = '\0';
  1232. }
  1233. if (len)
  1234. *len = t - s + 1;
  1235. return s;
  1236. }
  1237. int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
  1238. if(unlikely(!n)) return 0;
  1239. int size = vsnprintf(dst, n, fmt, args);
  1240. dst[n - 1] = '\0';
  1241. if (unlikely((size_t) size > n)) size = (int)n;
  1242. return size;
  1243. }
  1244. int snprintfz(char *dst, size_t n, const char *fmt, ...) {
  1245. va_list args;
  1246. va_start(args, fmt);
  1247. int ret = vsnprintfz(dst, n, fmt, args);
  1248. va_end(args);
  1249. return ret;
  1250. }
  1251. /*
  1252. // poor man cycle counting
  1253. static unsigned long tsc;
  1254. void begin_tsc(void) {
  1255. unsigned long a, d;
  1256. asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
  1257. tsc = ((unsigned long)d << 32) | (unsigned long)a;
  1258. }
  1259. unsigned long end_tsc(void) {
  1260. unsigned long a, d;
  1261. asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
  1262. return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
  1263. }
  1264. */
  1265. int recursively_delete_dir(const char *path, const char *reason) {
  1266. DIR *dir = opendir(path);
  1267. if(!dir) {
  1268. error("Cannot read %s directory to be deleted '%s'", reason?reason:"", path);
  1269. return -1;
  1270. }
  1271. int ret = 0;
  1272. struct dirent *de = NULL;
  1273. while((de = readdir(dir))) {
  1274. if(de->d_type == DT_DIR
  1275. && (
  1276. (de->d_name[0] == '.' && de->d_name[1] == '\0')
  1277. || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1278. ))
  1279. continue;
  1280. char fullpath[FILENAME_MAX + 1];
  1281. snprintfz(fullpath, FILENAME_MAX, "%s/%s", path, de->d_name);
  1282. if(de->d_type == DT_DIR) {
  1283. int r = recursively_delete_dir(fullpath, reason);
  1284. if(r > 0) ret += r;
  1285. continue;
  1286. }
  1287. info("Deleting %s file '%s'", reason?reason:"", fullpath);
  1288. if(unlikely(unlink(fullpath) == -1))
  1289. error("Cannot delete %s file '%s'", reason?reason:"", fullpath);
  1290. else
  1291. ret++;
  1292. }
  1293. info("Deleting empty directory '%s'", path);
  1294. if(unlikely(rmdir(path) == -1))
  1295. error("Cannot delete empty directory '%s'", path);
  1296. else
  1297. ret++;
  1298. closedir(dir);
  1299. return ret;
  1300. }
  1301. static int is_virtual_filesystem(const char *path, char **reason) {
  1302. #if defined(__APPLE__) || defined(__FreeBSD__)
  1303. (void)path;
  1304. (void)reason;
  1305. #else
  1306. struct statfs stat;
  1307. // stat.f_fsid.__val[0] is a file system id
  1308. // stat.f_fsid.__val[1] is the inode
  1309. // so their combination uniquely identifies the file/dir
  1310. if (statfs(path, &stat) == -1) {
  1311. if(reason) *reason = "failed to statfs()";
  1312. return -1;
  1313. }
  1314. if(stat.f_fsid.__val[0] != 0 || stat.f_fsid.__val[1] != 0) {
  1315. errno = EINVAL;
  1316. if(reason) *reason = "is not a virtual file system";
  1317. return -1;
  1318. }
  1319. #endif
  1320. return 0;
  1321. }
  1322. int verify_netdata_host_prefix() {
  1323. if(!netdata_configured_host_prefix)
  1324. netdata_configured_host_prefix = "";
  1325. if(!*netdata_configured_host_prefix)
  1326. return 0;
  1327. char buffer[FILENAME_MAX + 1];
  1328. char *path = netdata_configured_host_prefix;
  1329. char *reason = "unknown reason";
  1330. errno = 0;
  1331. struct stat sb;
  1332. if (stat(path, &sb) == -1) {
  1333. reason = "failed to stat()";
  1334. goto failed;
  1335. }
  1336. if((sb.st_mode & S_IFMT) != S_IFDIR) {
  1337. errno = EINVAL;
  1338. reason = "is not a directory";
  1339. goto failed;
  1340. }
  1341. path = buffer;
  1342. snprintfz(path, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
  1343. if(is_virtual_filesystem(path, &reason) == -1)
  1344. goto failed;
  1345. snprintfz(path, FILENAME_MAX, "%s/sys", netdata_configured_host_prefix);
  1346. if(is_virtual_filesystem(path, &reason) == -1)
  1347. goto failed;
  1348. if(netdata_configured_host_prefix && *netdata_configured_host_prefix)
  1349. info("Using host prefix directory '%s'", netdata_configured_host_prefix);
  1350. return 0;
  1351. failed:
  1352. error("Ignoring host prefix '%s': path '%s' %s", netdata_configured_host_prefix, path, reason);
  1353. netdata_configured_host_prefix = "";
  1354. return -1;
  1355. }
  1356. char *strdupz_path_subpath(const char *path, const char *subpath) {
  1357. if(unlikely(!path || !*path)) path = ".";
  1358. if(unlikely(!subpath)) subpath = "";
  1359. // skip trailing slashes in path
  1360. size_t len = strlen(path);
  1361. while(len > 0 && path[len - 1] == '/') len--;
  1362. // skip leading slashes in subpath
  1363. while(subpath[0] == '/') subpath++;
  1364. // if the last character in path is / and (there is a subpath or path is now empty)
  1365. // keep the trailing slash in path and remove the additional slash
  1366. char *slash = "/";
  1367. if(path[len] == '/' && (*subpath || len == 0)) {
  1368. slash = "";
  1369. len++;
  1370. }
  1371. else if(!*subpath) {
  1372. // there is no subpath
  1373. // no need for trailing slash
  1374. slash = "";
  1375. }
  1376. char buffer[FILENAME_MAX + 1];
  1377. snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, subpath);
  1378. return strdupz(buffer);
  1379. }
  1380. int path_is_dir(const char *path, const char *subpath) {
  1381. char *s = strdupz_path_subpath(path, subpath);
  1382. size_t max_links = 100;
  1383. int is_dir = 0;
  1384. struct stat statbuf;
  1385. while(max_links-- && stat(s, &statbuf) == 0) {
  1386. if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
  1387. is_dir = 1;
  1388. break;
  1389. }
  1390. else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
  1391. char buffer[FILENAME_MAX + 1];
  1392. ssize_t l = readlink(s, buffer, FILENAME_MAX);
  1393. if(l > 0) {
  1394. buffer[l] = '\0';
  1395. freez(s);
  1396. s = strdupz(buffer);
  1397. continue;
  1398. }
  1399. else {
  1400. is_dir = 0;
  1401. break;
  1402. }
  1403. }
  1404. else {
  1405. is_dir = 0;
  1406. break;
  1407. }
  1408. }
  1409. freez(s);
  1410. return is_dir;
  1411. }
  1412. int path_is_file(const char *path, const char *subpath) {
  1413. char *s = strdupz_path_subpath(path, subpath);
  1414. size_t max_links = 100;
  1415. int is_file = 0;
  1416. struct stat statbuf;
  1417. while(max_links-- && stat(s, &statbuf) == 0) {
  1418. if((statbuf.st_mode & S_IFMT) == S_IFREG) {
  1419. is_file = 1;
  1420. break;
  1421. }
  1422. else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
  1423. char buffer[FILENAME_MAX + 1];
  1424. ssize_t l = readlink(s, buffer, FILENAME_MAX);
  1425. if(l > 0) {
  1426. buffer[l] = '\0';
  1427. freez(s);
  1428. s = strdupz(buffer);
  1429. continue;
  1430. }
  1431. else {
  1432. is_file = 0;
  1433. break;
  1434. }
  1435. }
  1436. else {
  1437. is_file = 0;
  1438. break;
  1439. }
  1440. }
  1441. freez(s);
  1442. return is_file;
  1443. }
  1444. 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) {
  1445. if(depth > 3) {
  1446. error("CONFIG: Max directory depth reached while reading user path '%s', stock path '%s', subpath '%s'", user_path, stock_path, subpath);
  1447. return;
  1448. }
  1449. char *udir = strdupz_path_subpath(user_path, subpath);
  1450. char *sdir = strdupz_path_subpath(stock_path, subpath);
  1451. debug(D_HEALTH, "CONFIG traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
  1452. DIR *dir = opendir(udir);
  1453. if (!dir) {
  1454. error("CONFIG cannot open user-config directory '%s'.", udir);
  1455. }
  1456. else {
  1457. struct dirent *de = NULL;
  1458. while((de = readdir(dir))) {
  1459. if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
  1460. if( !de->d_name[0] ||
  1461. (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
  1462. (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1463. ) {
  1464. debug(D_HEALTH, "CONFIG ignoring user-config directory '%s/%s'", udir, de->d_name);
  1465. continue;
  1466. }
  1467. if(path_is_dir(udir, de->d_name)) {
  1468. recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
  1469. continue;
  1470. }
  1471. }
  1472. if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
  1473. size_t len = strlen(de->d_name);
  1474. if(path_is_file(udir, de->d_name) &&
  1475. len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
  1476. char *filename = strdupz_path_subpath(udir, de->d_name);
  1477. debug(D_HEALTH, "CONFIG calling callback for user file '%s'", filename);
  1478. callback(filename, data);
  1479. freez(filename);
  1480. continue;
  1481. }
  1482. }
  1483. debug(D_HEALTH, "CONFIG ignoring user-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
  1484. }
  1485. closedir(dir);
  1486. }
  1487. debug(D_HEALTH, "CONFIG traversing stock config directory '%s', user config directory '%s'", sdir, udir);
  1488. dir = opendir(sdir);
  1489. if (!dir) {
  1490. error("CONFIG cannot open stock config directory '%s'.", sdir);
  1491. }
  1492. else {
  1493. if (strcmp(udir, sdir)) {
  1494. struct dirent *de = NULL;
  1495. while((de = readdir(dir))) {
  1496. if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
  1497. if( !de->d_name[0] ||
  1498. (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
  1499. (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1500. ) {
  1501. debug(D_HEALTH, "CONFIG ignoring stock config directory '%s/%s'", sdir, de->d_name);
  1502. continue;
  1503. }
  1504. if(path_is_dir(sdir, de->d_name)) {
  1505. // we recurse in stock subdirectory, only when there is no corresponding
  1506. // user subdirectory - to avoid reading the files twice
  1507. if(!path_is_dir(udir, de->d_name))
  1508. recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
  1509. continue;
  1510. }
  1511. }
  1512. if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
  1513. size_t len = strlen(de->d_name);
  1514. if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) &&
  1515. len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
  1516. char *filename = strdupz_path_subpath(sdir, de->d_name);
  1517. debug(D_HEALTH, "CONFIG calling callback for stock file '%s'", filename);
  1518. callback(filename, data);
  1519. freez(filename);
  1520. continue;
  1521. }
  1522. }
  1523. debug(D_HEALTH, "CONFIG ignoring stock-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
  1524. }
  1525. }
  1526. closedir(dir);
  1527. }
  1528. debug(D_HEALTH, "CONFIG done traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
  1529. freez(udir);
  1530. freez(sdir);
  1531. }
  1532. // Returns the number of bytes read from the file if file_size is not NULL.
  1533. // The actual buffer has an extra byte set to zero (not included in the count).
  1534. char *read_by_filename(char *filename, long *file_size)
  1535. {
  1536. FILE *f = fopen(filename, "r");
  1537. if (!f)
  1538. return NULL;
  1539. if (fseek(f, 0, SEEK_END) < 0) {
  1540. fclose(f);
  1541. return NULL;
  1542. }
  1543. long size = ftell(f);
  1544. if (size <= 0 || fseek(f, 0, SEEK_END) < 0) {
  1545. fclose(f);
  1546. return NULL;
  1547. }
  1548. char *contents = callocz(size + 1, 1);
  1549. if (!contents) {
  1550. fclose(f);
  1551. return NULL;
  1552. }
  1553. if (fseek(f, 0, SEEK_SET) < 0) {
  1554. fclose(f);
  1555. freez(contents);
  1556. return NULL;
  1557. }
  1558. size_t res = fread(contents, 1, size, f);
  1559. if ( res != (size_t)size) {
  1560. freez(contents);
  1561. fclose(f);
  1562. return NULL;
  1563. }
  1564. fclose(f);
  1565. if (file_size)
  1566. *file_size = size;
  1567. return contents;
  1568. }
  1569. char *find_and_replace(const char *src, const char *find, const char *replace, const char *where)
  1570. {
  1571. size_t size = strlen(src) + 1;
  1572. size_t find_len = strlen(find);
  1573. size_t repl_len = strlen(replace);
  1574. char *value, *dst;
  1575. if (likely(where))
  1576. size += (repl_len - find_len);
  1577. value = mallocz(size);
  1578. dst = value;
  1579. if (likely(where)) {
  1580. size_t count = where - src;
  1581. memmove(dst, src, count);
  1582. src += count;
  1583. dst += count;
  1584. memmove(dst, replace, repl_len);
  1585. src += find_len;
  1586. dst += repl_len;
  1587. }
  1588. strcpy(dst, src);
  1589. return value;
  1590. }
  1591. inline int pluginsd_space(char c) {
  1592. switch(c) {
  1593. case ' ':
  1594. case '\t':
  1595. case '\r':
  1596. case '\n':
  1597. case '=':
  1598. return 1;
  1599. default:
  1600. return 0;
  1601. }
  1602. }
  1603. inline int config_isspace(char c)
  1604. {
  1605. switch (c) {
  1606. case ' ':
  1607. case '\t':
  1608. case '\r':
  1609. case '\n':
  1610. case ',':
  1611. return 1;
  1612. default:
  1613. return 0;
  1614. }
  1615. }
  1616. // split a text into words, respecting quotes
  1617. inline size_t quoted_strings_splitter(char *str, char **words, size_t max_words, int (*custom_isspace)(char), char *recover_input, char **recover_location, int max_recover)
  1618. {
  1619. char *s = str, quote = 0;
  1620. size_t i = 0;
  1621. int rec = 0;
  1622. char *recover = recover_input;
  1623. // skip all white space
  1624. while (unlikely(custom_isspace(*s)))
  1625. s++;
  1626. // check for quote
  1627. if (unlikely(*s == '\'' || *s == '"')) {
  1628. quote = *s; // remember the quote
  1629. s++; // skip the quote
  1630. }
  1631. // store the first word
  1632. words[i++] = s;
  1633. // while we have something
  1634. while (likely(*s)) {
  1635. // if it is escape
  1636. if (unlikely(*s == '\\' && s[1])) {
  1637. s += 2;
  1638. continue;
  1639. }
  1640. // if it is quote
  1641. else if (unlikely(*s == quote)) {
  1642. quote = 0;
  1643. if (recover && rec < max_recover) {
  1644. recover_location[rec++] = s;
  1645. *recover++ = *s;
  1646. }
  1647. *s = ' ';
  1648. continue;
  1649. }
  1650. // if it is a space
  1651. else if (unlikely(quote == 0 && custom_isspace(*s))) {
  1652. // terminate the word
  1653. if (recover && rec < max_recover) {
  1654. if (!rec || recover_location[rec-1] != s) {
  1655. recover_location[rec++] = s;
  1656. *recover++ = *s;
  1657. }
  1658. }
  1659. *s++ = '\0';
  1660. // skip all white space
  1661. while (likely(custom_isspace(*s)))
  1662. s++;
  1663. // check for quote
  1664. if (unlikely(*s == '\'' || *s == '"')) {
  1665. quote = *s; // remember the quote
  1666. s++; // skip the quote
  1667. }
  1668. // if we reached the end, stop
  1669. if (unlikely(!*s))
  1670. break;
  1671. // store the next word
  1672. if (likely(i < max_words))
  1673. words[i++] = s;
  1674. else
  1675. break;
  1676. }
  1677. // anything else
  1678. else
  1679. s++;
  1680. }
  1681. if (i < max_words)
  1682. words[i] = NULL;
  1683. return i;
  1684. }
  1685. inline size_t pluginsd_split_words(char *str, char **words, size_t max_words, char *recover_input, char **recover_location, int max_recover)
  1686. {
  1687. return quoted_strings_splitter(str, words, max_words, pluginsd_space, recover_input, recover_location, max_recover);
  1688. }
  1689. bool bitmap256_get_bit(BITMAP256 *ptr, uint8_t idx) {
  1690. if (unlikely(!ptr))
  1691. return false;
  1692. return (ptr->data[idx / 64] & (1ULL << (idx % 64)));
  1693. }
  1694. void bitmap256_set_bit(BITMAP256 *ptr, uint8_t idx, bool value) {
  1695. if (unlikely(!ptr))
  1696. return;
  1697. if (likely(value))
  1698. ptr->data[idx / 64] |= (1ULL << (idx % 64));
  1699. else
  1700. ptr->data[idx / 64] &= ~(1ULL << (idx % 64));
  1701. }
  1702. bool run_command_and_copy_output_to_stdout(const char *command, int max_line_length) {
  1703. pid_t pid;
  1704. FILE *fp = netdata_popen(command, &pid, NULL);
  1705. if(fp) {
  1706. char buffer[max_line_length + 1];
  1707. while (fgets(buffer, max_line_length, fp))
  1708. fprintf(stdout, "%s", buffer);
  1709. }
  1710. else {
  1711. error("Failed to execute command '%s'.", command);
  1712. return false;
  1713. }
  1714. netdata_pclose(NULL, fp, pid);
  1715. return true;
  1716. }
  1717. void for_each_open_fd(OPEN_FD_ACTION action, OPEN_FD_EXCLUDE excluded_fds){
  1718. int fd;
  1719. switch(action){
  1720. case OPEN_FD_ACTION_CLOSE:
  1721. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDIN)) (void)close(STDIN_FILENO);
  1722. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDOUT)) (void)close(STDOUT_FILENO);
  1723. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDERR)) (void)close(STDERR_FILENO);
  1724. #if defined(HAVE_CLOSE_RANGE)
  1725. if(close_range(STDERR_FILENO + 1, ~0U, 0) == 0) return;
  1726. error("close_range() failed, will try to close fds one by one");
  1727. #endif
  1728. break;
  1729. case OPEN_FD_ACTION_FD_CLOEXEC:
  1730. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDIN)) (void)fcntl(STDIN_FILENO, F_SETFD, FD_CLOEXEC);
  1731. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDOUT)) (void)fcntl(STDOUT_FILENO, F_SETFD, FD_CLOEXEC);
  1732. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDERR)) (void)fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC);
  1733. #if defined(HAVE_CLOSE_RANGE) && defined(CLOSE_RANGE_CLOEXEC) // Linux >= 5.11, FreeBSD >= 13.1
  1734. if(close_range(STDERR_FILENO + 1, ~0U, CLOSE_RANGE_CLOEXEC) == 0) return;
  1735. error("close_range() failed, will try to mark fds for closing one by one");
  1736. #endif
  1737. break;
  1738. default:
  1739. break; // do nothing
  1740. }
  1741. DIR *dir = opendir("/proc/self/fd");
  1742. if (dir == NULL) {
  1743. struct rlimit rl;
  1744. int open_max = -1;
  1745. if(getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) open_max = rl.rlim_max;
  1746. #ifdef _SC_OPEN_MAX
  1747. else open_max = sysconf(_SC_OPEN_MAX);
  1748. #endif
  1749. if (open_max == -1) open_max = 65535; // 65535 arbitrary default if everything else fails
  1750. for (fd = STDERR_FILENO + 1; fd < open_max; fd++) {
  1751. switch(action){
  1752. case OPEN_FD_ACTION_CLOSE:
  1753. if(fd_is_valid(fd)) (void)close(fd);
  1754. break;
  1755. case OPEN_FD_ACTION_FD_CLOEXEC:
  1756. (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
  1757. break;
  1758. default:
  1759. break; // do nothing
  1760. }
  1761. }
  1762. } else {
  1763. struct dirent *entry;
  1764. while ((entry = readdir(dir)) != NULL) {
  1765. fd = str2i(entry->d_name);
  1766. if(unlikely((fd == STDIN_FILENO ) || (fd == STDOUT_FILENO) || (fd == STDERR_FILENO) )) continue;
  1767. switch(action){
  1768. case OPEN_FD_ACTION_CLOSE:
  1769. if(fd_is_valid(fd)) (void)close(fd);
  1770. break;
  1771. case OPEN_FD_ACTION_FD_CLOEXEC:
  1772. (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
  1773. break;
  1774. default:
  1775. break; // do nothing
  1776. }
  1777. }
  1778. closedir(dir);
  1779. }
  1780. }