Common O/S Caching Layer for users and groups (#18825)
* added cached-uid-usernames to libnetdata * added cached-gid-groupnames * apps.plugin uses the common cache for users and groups * apps.plugin cleanup * network-viewer and systemd-journal now use host prefix to ingest usernames and groups * fix compilation on windows * move unicode functions from windows-events to libnetdata * move sid-to-username from windows-events plugin to libnetdata * common.h in libnetdata for operating system includes and macros * sid uses STRINGs * apps.plugin now exposes per user charts on windows
Costa Tsaousis committed
Oct 21, 2024 at 10:04 UTC
34cbe9f98d4f3bdaa298074b1504021d7068247c
46 files changed
+1557
-1238
CMakeLists.txt
+12
-9
@@ -768,6 +768,14 @@ set(LIBNETDATA_FILES
768
src/libnetdata/os/windows-perflib/perflib.h
769
src/libnetdata/os/windows-perflib/perflib-names.c
770
src/libnetdata/os/windows-perflib/perflib-dump.c
771
+ src/libnetdata/os/system-maps/cached-uid-username.c
772
+ src/libnetdata/os/system-maps/cached-uid-username.h
773
+ src/libnetdata/os/system-maps/cached-sid-username.c
774
+ src/libnetdata/os/system-maps/cached-sid-username.h
775
+ src/libnetdata/os/system-maps/cached-gid-groupname.c
776
+ src/libnetdata/os/system-maps/cached-gid-groupname.h
777
+ src/libnetdata/os/system-maps/cache-host-users-and-groups.c
778
+ src/libnetdata/os/system-maps/cache-host-users-and-groups.h
779
src/libnetdata/spawn_server/spawn_server_nofork.c
780
src/libnetdata/spawn_server/spawn_server.h
781
src/libnetdata/spawn_server/spawn_popen.c
@@ -845,6 +853,7 @@ set(LIBNETDATA_FILES
853
src/libnetdata/spawn_server/log-forwarder.h
854
src/libnetdata/log/nd_log-common.h
855
src/libnetdata/log/nd_log-to-windows-common.h
856
+ src/libnetdata/common.h
857
)
858
859
if(ENABLE_PLUGIN_EBPF)
@@ -1332,9 +1341,7 @@ set(SYSTEMD_JOURNAL_PLUGIN_FILES
1341
src/collectors/systemd-journal.plugin/systemd-journal-fstat.c
1342
src/collectors/systemd-journal.plugin/systemd-journal-watcher.c
1343
src/collectors/systemd-journal.plugin/systemd-journal-dyncfg.c
1335
- src/libnetdata/maps/system-users.h
1336
- src/libnetdata/maps/system-groups.h
1337
- src/libnetdata/maps/system-services.h
1344
+ src/libnetdata/os/system-maps/system-services.h
1345
src/collectors/systemd-journal.plugin/systemd-journal-sampling.h
1346
)
1347
@@ -1464,8 +1471,6 @@ set(WINDOWS_EVENTS_PLUGIN_FILES
1471
src/collectors/windows-events.plugin/windows-events-query.c
1472
src/collectors/windows-events.plugin/windows-events-sources.c
1473
src/collectors/windows-events.plugin/windows-events-sources.h
1467
- src/collectors/windows-events.plugin/windows-events-sid.c
1468
- src/collectors/windows-events.plugin/windows-events-sid.h
1474
src/collectors/windows-events.plugin/windows-events-unicode.c
1475
src/collectors/windows-events.plugin/windows-events-unicode.h
1476
src/collectors/windows-events.plugin/windows-events-xml.c
@@ -2020,7 +2025,6 @@ if(ENABLE_PLUGIN_APPS)
2025
src/collectors/apps.plugin/apps_plugin.h
2026
src/collectors/apps.plugin/apps_functions.c
2027
src/collectors/apps.plugin/apps_targets.c
2023
- src/collectors/apps.plugin/apps_users_and_groups.c
2028
src/collectors/apps.plugin/apps_output.c
2029
src/collectors/apps.plugin/apps_pid_files.c
2030
src/collectors/apps.plugin/apps_pid.c
@@ -2356,7 +2360,7 @@ endif()
2360
if(ENABLE_PLUGIN_LOCAL_LISTENERS)
2361
set(LOCAL_LISTENERS_FILES
2362
src/collectors/utils/local_listeners.c
2359
- src/libnetdata/maps/local-sockets.h
2363
+ src/libnetdata/local-sockets/local-sockets.h
2364
)
2365
2366
add_executable(local-listeners ${LOCAL_LISTENERS_FILES})
@@ -2375,8 +2379,7 @@ endif()
2379
2380
if(ENABLE_PLUGIN_NETWORK_VIEWER)
2381
set(NETWORK_VIEWER_FILES
2378
- src/libnetdata/maps/local-sockets.h
2379
- src/libnetdata/maps/system-users.h
2382
+ src/libnetdata/local-sockets/local-sockets.h
2383
src/collectors/network-viewer.plugin/network-viewer.c
2384
)
2385
src/collectors/apps.plugin/apps_aggregations.c
+20
@@ -169,6 +169,9 @@ void aggregate_processes_to_targets(void) {
169
#if (PROCESSES_HAVE_GID == 1)
170
zero_all_targets(groups_root_target);
171
#endif
172
+#if (PROCESSES_HAVE_SID == 1)
173
+ zero_all_targets(sids_root_target);
174
+#endif
175
176
// this has to be done, before the cleanup
177
struct target *w = NULL, *o = NULL;
@@ -187,6 +190,8 @@ void aggregate_processes_to_targets(void) {
190
// user target
191
192
#if (PROCESSES_HAVE_UID == 1)
193
+ update_cached_host_users();
194
+
195
o = p->uid_target;
196
if(likely(p->uid_target && p->uid_target->uid == p->uid))
197
w = p->uid_target;
@@ -204,6 +209,8 @@ void aggregate_processes_to_targets(void) {
209
// user group target
210
211
#if (PROCESSES_HAVE_GID == 1)
212
+ update_cached_host_users();
213
+
214
o = p->gid_target;
215
if(likely(p->gid_target && p->gid_target->gid == p->gid))
216
w = p->gid_target;
@@ -214,6 +221,19 @@ void aggregate_processes_to_targets(void) {
221
w = p->gid_target = get_gid_target(p->gid);
222
}
223
224
+ aggregate_pid_on_target(w, p, o);
225
+#endif
226
+
227
+ // --------------------------------------------------------------------
228
+ // sid target
229
+
230
+#if (PROCESSES_HAVE_SID == 1)
231
+ o = p->sid_target;
232
+ if(likely(p->sid_target && p->sid_target->sid_name == p->sid_name))
233
+ w = p->sid_target;
234
+ else
235
+ w = p->sid_target = get_sid_target(p->sid_name);
236
+
237
aggregate_pid_on_target(w, p, o);
238
#endif
239
src/collectors/apps.plugin/apps_functions.c
+22
-5
@@ -27,7 +27,7 @@ static void apps_plugin_function_processes_help(const char *transaction) {
27
" parent:NAME\n"
28
" Shows only processes that are aggregated under parent `NAME`\n"
29
"\n"
30
-#if (PROCESSES_HAVE_UID == 1)
30
+#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
31
" user:NAME\n"
32
" Shows only processes that are running as user name `NAME`.\n"
33
"\n"
@@ -89,6 +89,12 @@ void function_processes(const char *transaction, char *function,
89
size_t num_words = quoted_strings_splitter_whitespace(function, words, PLUGINSD_MAX_WORDS);
90
91
struct target *category = NULL, *user = NULL, *group = NULL; (void)category; (void)user; (void)group;
92
+#if (PROCESSES_HAVE_UID == 1)
93
+ struct target *users_sid_root = users_root_target;
94
+#endif
95
+#if (PROCESSES_HAVE_SID == 1)
96
+ struct target *users_sid_root = sids_root_target;
97
+#endif
98
const char *process_name = NULL;
99
pid_t pid = 0;
100
uid_t uid = 0; (void)uid;
@@ -110,9 +116,9 @@ void function_processes(const char *transaction, char *function,
116
return;
117
}
118
}
113
-#if (PROCESSES_HAVE_UID == 1)
119
+#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
120
else if(!user && strncmp(keyword, PROCESS_FILTER_USER, strlen(PROCESS_FILTER_USER)) == 0) {
115
- user = find_target_by_name(users_root_target, &keyword[strlen(PROCESS_FILTER_USER)]);
121
+ user = find_target_by_name(users_sid_root, &keyword[strlen(PROCESS_FILTER_USER)]);
122
if(!user) {
123
pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST,
124
"No user with that name found.");
@@ -271,6 +277,11 @@ void function_processes(const char *transaction, char *function,
277
continue;
278
#endif
279
280
+#if (PROCESSES_HAVE_SID == 1)
281
+ if(user && p->sid_target != user)
282
+ continue;
283
+#endif
284
+
285
if(process_name && ((strcmp(pid_stat_comm(p), process_name) != 0 && !p->parent) || (p->parent && strcmp(pid_stat_comm(p), process_name) != 0 && strcmp(pid_stat_comm(p->parent), process_name) != 0)))
286
continue;
287
@@ -323,6 +334,10 @@ void function_processes(const char *transaction, char *function,
334
// uid
335
buffer_json_add_array_item_uint64(wb, p->uid);
336
#endif
337
+#if (PROCESSES_HAVE_SID == 1)
338
+ // account
339
+ buffer_json_add_array_item_string(wb, p->sid_target ? string2str(p->sid_target->name) : "-");
340
+#endif
341
342
#if (PROCESSES_HAVE_GID == 1)
343
// group
@@ -493,12 +508,14 @@ void function_processes(const char *transaction, char *function,
508
RRDF_FIELD_FILTER_MULTISELECT,
509
RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
510
496
-#if (PROCESSES_HAVE_UID == 1)
511
+#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
512
buffer_rrdf_table_add_field(wb, field_id++, "User", "User Owner", RRDF_FIELD_TYPE_STRING,
513
RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
514
RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
515
RRDF_FIELD_FILTER_MULTISELECT,
516
RRDF_FIELD_OPTS_VISIBLE, NULL);
517
+#endif
518
+#if (PROCESSES_HAVE_UID == 1)
519
buffer_rrdf_table_add_field(wb, field_id++, "Uid", "User ID", RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE,
520
RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
521
RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
@@ -1079,7 +1096,7 @@ void function_processes(const char *transaction, char *function,
1096
}
1097
buffer_json_object_close(wb);
1098
1082
-#if (PROCESSES_HAVE_UID == 1)
1099
+#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
1100
// group by User
1101
buffer_json_member_add_object(wb, "User");
1102
{
src/collectors/apps.plugin/apps_os_windows.c
+48
-1
@@ -525,7 +525,7 @@ static char *ansi_to_utf8(LPCSTR str) {
525
static __thread WCHAR unicode[PATH_MAX];
526
527
// Step 1: Convert ANSI string (LPSTR) to wide string (UTF-16)
528
- size_t count = any_to_utf16(CP_ACP, unicode, _countof(unicode), str, -1);
528
+ size_t count = any_to_utf16(CP_ACP, unicode, _countof(unicode), str, -1, NULL);
529
if (!count) return NULL;
530
531
return wchar_to_utf8(unicode);
@@ -664,6 +664,45 @@ static WCHAR *executable_path_from_cmdline(WCHAR *cmdline) {
664
return NULL;
665
}
666
667
+static BOOL GetProcessUserSID(HANDLE hProcess, PSID *ppSid) {
668
+ HANDLE hToken;
669
+ BOOL result = FALSE;
670
+ DWORD dwSize = 0;
671
+ PTOKEN_USER pTokenUser = NULL;
672
+
673
+ if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
674
+ return FALSE;
675
+
676
+ GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
677
+ if (dwSize == 0) {
678
+ CloseHandle(hToken);
679
+ return FALSE;
680
+ }
681
+
682
+ pTokenUser = (PTOKEN_USER)LocalAlloc(LPTR, dwSize);
683
+ if (pTokenUser == NULL) {
684
+ CloseHandle(hToken);
685
+ return FALSE;
686
+ }
687
+
688
+ if (GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) {
689
+ DWORD sidSize = GetLengthSid(pTokenUser->User.Sid);
690
+ *ppSid = (PSID)LocalAlloc(LPTR, sidSize);
691
+ if (*ppSid) {
692
+ if (CopySid(sidSize, *ppSid, pTokenUser->User.Sid)) {
693
+ result = TRUE;
694
+ } else {
695
+ LocalFree(*ppSid);
696
+ *ppSid = NULL;
697
+ }
698
+ }
699
+ }
700
+
701
+ LocalFree(pTokenUser);
702
+ CloseHandle(hToken);
703
+ return result;
704
+}
705
+
706
void GetAllProcessesInfo(void) {
707
static __thread wchar_t unicode[PATH_MAX];
708
static __thread DWORD unicode_size = sizeof(unicode) / sizeof(*unicode);
@@ -723,6 +762,14 @@ void GetAllProcessesInfo(void) {
762
}
763
}
764
765
+ if(!p->sid_name) {
766
+ PSID pSid = NULL;
767
+ if (GetProcessUserSID(hProcess, &pSid))
768
+ p->sid_name = cached_sid_fullname_or_sid_str(pSid);
769
+ else
770
+ p->sid_name = string_strdupz("Unknown");
771
+ }
772
+
773
CloseHandle(hProcess);
774
775
char *comm = wchar_to_utf8(pe32.szExeFile);
src/collectors/apps.plugin/apps_pid.c
+4
@@ -134,6 +134,10 @@ void del_pid_entry(pid_t pid) {
134
freez(p->fds);
135
#endif
136
137
+#if (PROCESSES_HAVE_SID == 1)
138
+ string_freez(p->sid_name);
139
+#endif
140
+
141
string_freez(p->comm_orig);
142
string_freez(p->comm);
143
string_freez(p->cmdline);
src/collectors/apps.plugin/apps_plugin.c
+30
-11
@@ -74,10 +74,10 @@ uint32_t
74
// the metrics. This results in utilization that exceeds the total utilization
75
// of the system.
76
//
77
-// During normalization, we align the per-process utilization, to the total of
78
-// the system. We first consume the exited children utilization and it the
79
-// collected values is above the total, we proportionally scale each reported
80
-// metric.
77
+// During normalization, we align the per-process utilization to the global
78
+// utilization of the system. We first consume the exited children utilization
79
+// and it the collected values is above the total, we proportionally scale each
80
+// reported metric.
81
82
// the total system time, as reported by /proc/stat
83
#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
@@ -211,9 +211,10 @@ void print_hierarchy(struct pid_stat *root) {
211
static void normalize_utilization(struct target *root) {
212
struct target *w;
213
214
- // childs processing introduces spikes
215
- // here we try to eliminate them by disabling childs processing either for specific dimensions
216
- // or entirely. Of course, either way, we disable it just a single iteration.
214
+ // children processing introduces spikes,
215
+ // here we try to eliminate them by disabling children processing either
216
+ // for specific dimensions or entirely.
217
+ // of course, either way, we disable it just for a single iteration.
218
219
kernel_uint_t max_time = os_get_system_cpus() * NSEC_PER_SEC;
220
kernel_uint_t utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
@@ -249,7 +250,7 @@ static void normalize_utilization(struct target *root) {
250
cgtime_fix_ratio = 1.0; //(NETDATA_DOUBLE)(global_utime + global_stime) / (NETDATA_DOUBLE)(utime + cutime + stime + cstime);
251
}
252
else if((global_utime + global_stime > utime + stime) && (cutime || cstime)) {
252
- // children resources are too high
253
+ // children resources are too high,
254
// lower only the children resources
255
utime_fix_ratio =
256
stime_fix_ratio =
@@ -481,7 +482,7 @@ static void parse_args(int argc, char **argv)
482
}
483
#endif
484
484
-#if (PROCESSES_HAVE_UID == 1)
485
+#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
486
if(strcmp("no-users", argv[i]) == 0 || strcmp("without-users", argv[i]) == 0) {
487
enable_users_charts = 0;
488
continue;
@@ -544,7 +545,7 @@ static void parse_args(int argc, char **argv)
545
" (default is enabled)\n"
546
"\n"
547
#endif
547
-#if (PROCESSES_HAVE_UID == 1)
548
+#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
549
" without-users disable reporting per user charts\n"
550
"\n"
551
#endif
@@ -734,7 +735,18 @@ int main(int argc, char **argv) {
735
736
netdata_log_info("started on pid %d", getpid());
737
737
- apps_users_and_groups_init();
738
+#if (PROCESSES_HAVE_UID == 1)
739
+ cached_usernames_init();
740
+#endif
741
+
742
+#if (PROCESSES_HAVE_GID == 1)
743
+ cached_groupnames_init();
744
+#endif
745
+
746
+#if (PROCESSES_HAVE_SID == 1)
747
+ cached_sid_username_init();
748
+#endif
749
+
750
apps_pids_init();
751
OS_FUNCTION(apps_os_init)();
752
@@ -823,6 +835,13 @@ int main(int argc, char **argv) {
835
}
836
#endif
837
838
+#if (PROCESSES_HAVE_SID == 1)
839
+ if (enable_users_charts) {
840
+ send_charts_updates_to_netdata(sids_root_target, "user", "user", "User Processes");
841
+ send_collected_data_to_netdata(sids_root_target, "user", dt);
842
+ }
843
+#endif
844
+
845
fflush(stdout);
846
847
debug_log("done Loop No %zu", global_iterations_counter);
src/collectors/apps.plugin/apps_plugin.h
+41
-40
@@ -22,6 +22,7 @@
22
#define PROCESSES_HAVE_IO_CALLS 0
23
#define PROCESSES_HAVE_UID 1
24
#define PROCESSES_HAVE_GID 1
25
+#define PROCESSES_HAVE_SID 0
26
#define PROCESSES_HAVE_MAJFLT 1
27
#define PROCESSES_HAVE_CHILDREN_FLTS 1
28
#define PROCESSES_HAVE_VMSWAP 0
@@ -65,6 +66,7 @@ struct pid_info {
66
#define PROCESSES_HAVE_IO_CALLS 0
67
#define PROCESSES_HAVE_UID 1
68
#define PROCESSES_HAVE_GID 1
69
+#define PROCESSES_HAVE_SID 0
70
#define PROCESSES_HAVE_MAJFLT 1
71
#define PROCESSES_HAVE_CHILDREN_FLTS 0
72
#define PROCESSES_HAVE_VMSWAP 0
@@ -96,6 +98,7 @@ struct pid_info {
98
#define PROCESSES_HAVE_IO_CALLS 1
99
#define PROCESSES_HAVE_UID 0
100
#define PROCESSES_HAVE_GID 0
101
+#define PROCESSES_HAVE_SID 1
102
#define PROCESSES_HAVE_MAJFLT 0
103
#define PROCESSES_HAVE_CHILDREN_FLTS 0
104
#define PROCESSES_HAVE_VMSWAP 1
@@ -125,6 +128,7 @@ struct pid_info {
128
#define PROCESSES_HAVE_IO_CALLS 1
129
#define PROCESSES_HAVE_UID 1
130
#define PROCESSES_HAVE_GID 1
131
+#define PROCESSES_HAVE_SID 0
132
#define PROCESSES_HAVE_MAJFLT 1
133
#define PROCESSES_HAVE_CHILDREN_FLTS 1
134
#define PROCESSES_HAVE_VMSWAP 1
@@ -149,6 +153,10 @@ extern int max_fds_cache_seconds;
153
#error "Unsupported operating system"
154
#endif
155
156
+#if (PROCESSES_HAVE_UID == 1) && (PROCESSES_HAVE_SID == 1)
157
+#error "Do not enable SID and UID at the same time"
158
+#endif
159
+
160
// --------------------------------------------------------------------------------------------------------------------
161
162
#define MAX_SYSTEM_FD_TO_ALLOW_FILES_PROCESSING 100000
@@ -205,12 +213,12 @@ extern size_t pagesize;
213
214
extern netdata_mutex_t apps_and_stdout_mutex;
215
208
-// ----------------------------------------------------------------------------
216
+// --------------------------------------------------------------------------------------------------------------------
217
// string lengths
218
219
#define MAX_CMDLINE 65536
220
213
-// ----------------------------------------------------------------------------
221
+// --------------------------------------------------------------------------------------------------------------------
222
// to avoid reallocating too frequently when we add file descriptors,
223
// we double the allocation at every increase request.
224
@@ -218,7 +226,7 @@ static inline uint32_t fds_new_size(uint32_t old_size, uint32_t new_fd) {
226
return MAX(old_size * 2, new_fd + 1); // 1 space always
227
}
228
221
-// ----------------------------------------------------------------------------
229
+// --------------------------------------------------------------------------------------------------------------------
230
// some variables for keeping track of processes count by states
231
#if (PROCESSES_HAVE_STATE == 1)
232
typedef enum {
@@ -234,7 +242,7 @@ extern proc_state proc_state_count[PROC_STATUS_END];
242
extern const char *proc_states[];
243
#endif
244
237
-// ----------------------------------------------------------------------------
245
+// --------------------------------------------------------------------------------------------------------------------
246
// the rates we are going to send to netdata will have this detail a value of:
247
// - 1 will send just integer parts to netdata
248
// - 100 will send 2 decimal points
@@ -257,7 +265,7 @@ struct openfds {
265
#define pid_openfds_sum(p) ((p)->openfds.files + (p)->openfds.pipes + (p)->openfds.sockets + (p)->openfds.inotifies + (p)->openfds.eventfds + (p)->openfds.timerfds + (p)->openfds.signalfds + (p)->openfds.eventpolls + (p)->openfds.other)
266
#endif
267
260
-// ----------------------------------------------------------------------------
268
+// --------------------------------------------------------------------------------------------------------------------
269
// target
270
//
271
// target is the structure that processes are aggregated to be reported
@@ -278,6 +286,9 @@ typedef enum __attribute__((packed)) {
286
#endif
287
#if (PROCESSES_HAVE_GID == 1)
288
TARGET_TYPE_GID,
289
+#endif
290
+#if (PROCESSES_HAVE_SID == 1)
291
+ TARGET_TYPE_SID,
292
#endif
293
TARGET_TYPE_TREE,
294
} TARGET_TYPE;
@@ -384,6 +395,9 @@ struct target {
395
#if (PROCESSES_HAVE_GID == 1)
396
gid_t gid;
397
#endif
398
+#if (PROCESSES_HAVE_SID == 1)
399
+ STRING *sid_name;
400
+#endif
401
402
kernel_uint_t values[PDF_MAX];
403
@@ -405,7 +419,7 @@ struct target {
419
struct target *next;
420
};
421
408
-// ----------------------------------------------------------------------------
422
+// --------------------------------------------------------------------------------------------------------------------
423
// internal flags
424
// handled in code (automatically set)
425
@@ -421,7 +435,7 @@ typedef enum __attribute__((packed)) {
435
PID_LOG_LIMITS_DETAIL = (1 << 6),
436
} PID_LOG;
437
424
-// ----------------------------------------------------------------------------
438
+// --------------------------------------------------------------------------------------------------------------------
439
// pid_stat
440
//
441
// structure to store data for each process running
@@ -460,8 +474,8 @@ struct pid_fd {
474
#endif
475
};
476
463
-#define pid_stat_comm(p) (string2str(p->comm))
464
-#define pid_stat_cmdline(p) (string2str(p->cmdline))
477
+#define pid_stat_comm(p) (string2str((p)->comm))
478
+#define pid_stat_cmdline(p) (string2str((p)->cmdline))
479
uint32_t all_files_len_get(void);
480
481
struct pid_stat {
@@ -485,10 +499,13 @@ struct pid_stat {
499
#if (PROCESSES_HAVE_GID == 1)
500
struct target *gid_target; // gid based targets
501
#endif
502
+#if (PROCESSES_HAVE_SID == 1)
503
+ struct target *sid_target; // sid based targets
504
+#endif
505
506
STRING *comm_orig; // the command, as-collected
507
STRING *comm; // the command, sanitized
491
- STRING *name; // the command name if any, sanitized
508
+ STRING *name; // the command name, if any, sanitized
509
STRING *cmdline; // the full command line of the program
510
511
#if defined(OS_WINDOWS)
@@ -505,6 +522,9 @@ struct pid_stat {
522
#if (PROCESSES_HAVE_GID == 1)
523
gid_t gid;
524
#endif
525
+#if (PROCESSES_HAVE_SID == 1)
526
+ STRING *sid_name;
527
+#endif
528
529
#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
530
uint32_t sortlist; // higher numbers = top on the process tree
@@ -521,8 +541,8 @@ struct pid_stat {
541
uint32_t fds_size; // the size of the fds array
542
#endif
543
524
- uint32_t children_count; // number of processes directly referencing this
525
- // it is absorbed by apps_groups.conf inheritance
544
+ uint32_t children_count; // the number of processes directly referencing this.
545
+ // used internally for apps_groups.conf inheritance.
546
// don't rely on it for anything else.
547
548
uint32_t keeploops; // increases by 1 every time keep is 1 and updated 0
@@ -566,32 +586,11 @@ struct pid_stat {
586
#endif
587
};
588
569
-// ----------------------------------------------------------------------------
570
-
571
-#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_GID == 1)
572
-struct user_or_group_id {
573
- avl_t avl;
574
-
575
- union {
576
-#if (PROCESSES_HAVE_UID == 1)
577
- uid_t uid;
578
-#endif
579
-#if (PROCESSES_HAVE_GID == 1)
580
- gid_t gid;
581
-#endif
582
- } id;
583
-
584
- char *name;
585
-
586
- int updated;
587
-
588
- struct user_or_group_id * next;
589
-};
590
-#endif
589
+// --------------------------------------------------------------------------------------------------------------------
590
591
extern int update_every;
592
594
-// ----------------------------------------------------------------------------
593
+// --------------------------------------------------------------------------------------------------------------------
594
// debugging
595
596
static inline void debug_log_int(const char *fmt, ... ) {
@@ -618,14 +617,14 @@ static inline void debug_log_dummy(void) {}
617
bool managed_log(struct pid_stat *p, PID_LOG log, bool status);
618
void sanitize_apps_plugin_chart_meta(char *buf);
619
621
-// ----------------------------------------------------------------------------
620
+// --------------------------------------------------------------------------------------------------------------------
621
// macro to calculate the incremental rate of a value
622
// each parameter is accessed only ONCE - so it is safe to pass function calls
623
// or other macros as parameters
624
625
#define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec, multiplier) do { \
626
kernel_uint_t _new_tmp = new_kernel_value; \
628
- (rate_variable) = (_new_tmp - (last_kernel_variable)) * (USEC_PER_SEC * multiplier) / ((collected_usec) - (last_collected_usec)); \
627
+ (rate_variable) = (_new_tmp - (last_kernel_variable)) * (USEC_PER_SEC * (multiplier)) / ((collected_usec) - (last_collected_usec)); \
628
(last_kernel_variable) = _new_tmp; \
629
} while(0)
630
@@ -637,7 +636,6 @@ void sanitize_apps_plugin_chart_meta(char *buf);
636
incremental_rate(p->values[idx], p->raw[idx], value, p->type##_collected_usec, p->last_##type##_collected_usec, CPU_TO_NANOSECONDCORES)
637
638
void apps_managers_and_aggregators_init(void);
640
-void apps_users_and_groups_init(void);
639
void apps_pids_init(void);
640
641
#if (PROCESSES_HAVE_CMDLINE == 1)
@@ -700,13 +698,16 @@ void aggregate_processes_to_targets(void);
698
#if (PROCESSES_HAVE_UID == 1)
699
extern struct target *users_root_target;
700
struct target *get_uid_target(uid_t uid);
703
-struct user_or_group_id *user_id_find(struct user_or_group_id *user_id_to_find);
701
#endif
702
703
#if (PROCESSES_HAVE_GID == 1)
704
extern struct target *groups_root_target;
705
struct target *get_gid_target(gid_t gid);
709
-struct user_or_group_id *group_id_find(struct user_or_group_id *group_id_to_find);
706
+#endif
707
+
708
+#if (PROCESSES_HAVE_SID == 1)
709
+extern struct target *sids_root_target;
710
+struct target *get_sid_target(STRING *sid_name);
711
#endif
712
713
extern struct target *apps_groups_root_target;
src/collectors/apps.plugin/apps_targets.c
+34
-35
@@ -228,24 +228,10 @@ struct target *get_uid_target(uid_t uid) {
228
w->uid = uid;
229
w->id = get_numeric_string(uid);
230
231
- struct user_or_group_id user_id_to_find = {
232
- .id = {
233
- .uid = uid,
234
- }
235
- };
236
- struct user_or_group_id *user_or_group_id = user_id_find(&user_id_to_find);
237
-
238
- if(user_or_group_id && user_or_group_id->name && *user_or_group_id->name)
239
- w->name = string_strdupz(user_or_group_id->name);
240
- else {
241
- struct passwd *pw = getpwuid(uid);
242
- if(!pw || !pw->pw_name || !*pw->pw_name)
243
- w->name = get_numeric_string(uid);
244
- else
245
- w->name = string_strdupz(pw->pw_name);
246
- }
247
-
231
+ CACHED_USERNAME cu = cached_username_get_by_uid(uid);
232
+ w->name = string_dup(cu.username);
233
w->clean_name = get_clean_name(w->name);
234
+ cached_username_release(cu);
235
236
w->next = users_root_target;
237
users_root_target = w;
@@ -272,24 +258,10 @@ struct target *get_gid_target(gid_t gid) {
258
w->gid = gid;
259
w->id = get_numeric_string(gid);
260
275
- struct user_or_group_id group_id_to_find = {
276
- .id = {
277
- .gid = gid,
278
- }
279
- };
280
- struct user_or_group_id *group_id = group_id_find(&group_id_to_find);
281
-
282
- if(group_id && group_id->name)
283
- w->name = string_strdupz(group_id->name);
284
- else {
285
- struct group *gr = getgrgid(gid);
286
- if(!gr || !gr->gr_name || !*gr->gr_name)
287
- w->name = get_numeric_string(gid);
288
- else
289
- w->name = string_strdupz(gr->gr_name);
290
- }
291
-
261
+ CACHED_GROUPNAME cg = cached_groupname_get_by_gid(gid);
262
+ w->name = string_dup(cg.groupname);
263
w->clean_name = get_clean_name(w->name);
264
+ cached_groupname_release(cg);
265
266
w->next = groups_root_target;
267
groups_root_target = w;
@@ -300,6 +272,33 @@ struct target *get_gid_target(gid_t gid) {
272
}
273
#endif
274
275
+// --------------------------------------------------------------------------------------------------------------------
276
+// SID
277
+
278
+#if (PROCESSES_HAVE_SID == 1)
279
+struct target *sids_root_target = NULL;
280
+
281
+struct target *get_sid_target(STRING *sid_name) {
282
+ struct target *w;
283
+ for(w = sids_root_target ; w ; w = w->next)
284
+ if(w->sid_name == sid_name) return w;
285
+
286
+ w = callocz(sizeof(struct target), 1);
287
+ w->type = TARGET_TYPE_SID;
288
+ w->sid_name = string_dup(sid_name);
289
+ w->id = string_dup(sid_name);
290
+ w->name = string_dup(sid_name);
291
+ w->clean_name = get_clean_name(w->name);
292
+
293
+ w->next = sids_root_target;
294
+ sids_root_target = w;
295
+
296
+ debug_log("added uid %s ('%s') target", string2str(w->sid_name), string2str(w->name));
297
+
298
+ return w;
299
+}
300
+#endif
301
+
302
// --------------------------------------------------------------------------------------------------------------------
303
// apps_groups.conf
304
@@ -425,7 +424,7 @@ int read_apps_groups_conf(const char *path, const char *file) {
424
managed_list_add(&tree.interpreters, s);
425
}
426
428
- // done with managers, proceed to next line
427
+ // done with managers, proceed to the next line
428
continue;
429
}
430
src/collectors/apps.plugin/apps_users_and_groups.c
deleted
-224
@@ -1,224 +0,0 @@
1
-// SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-#include "apps_plugin.h"
4
-
5
-#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_GID == 1)
6
-
7
-// ----------------------------------------------------------------------------
8
-// read users and groups from files
9
-
10
-enum user_or_group_id_type {
11
- USER_ID,
12
- GROUP_ID
13
-};
14
-
15
-struct user_or_group_ids {
16
- enum user_or_group_id_type type;
17
-
18
- avl_tree_type index;
19
- struct user_or_group_id *root;
20
-
21
- char filename[FILENAME_MAX + 1];
22
-};
23
-
24
-#if (PROCESSES_HAVE_UID == 1)
25
-static int user_id_compare(void* a, void* b) {
26
- if(((struct user_or_group_id *)a)->id.uid < ((struct user_or_group_id *)b)->id.uid)
27
- return -1;
28
-
29
- else if(((struct user_or_group_id *)a)->id.uid > ((struct user_or_group_id *)b)->id.uid)
30
- return 1;
31
-
32
- else
33
- return 0;
34
-}
35
-
36
-static struct user_or_group_ids all_user_ids = {
37
- .type = USER_ID,
38
-
39
- .index = {
40
- NULL,
41
- user_id_compare
42
- },
43
-
44
- .root = NULL,
45
-
46
- .filename = "",
47
-};
48
-#endif
49
-
50
-#if (PROCESSES_HAVE_GID == 1)
51
-static int group_id_compare(void* a, void* b) {
52
- if(((struct user_or_group_id *)a)->id.gid < ((struct user_or_group_id *)b)->id.gid)
53
- return -1;
54
-
55
- else if(((struct user_or_group_id *)a)->id.gid > ((struct user_or_group_id *)b)->id.gid)
56
- return 1;
57
-
58
- else
59
- return 0;
60
-}
61
-
62
-static struct user_or_group_ids all_group_ids = {
63
- .type = GROUP_ID,
64
-
65
- .index = {
66
- NULL,
67
- group_id_compare
68
- },
69
-
70
- .root = NULL,
71
-
72
- .filename = "",
73
-};
74
-#endif
75
-
76
-static int file_changed(const struct stat *statbuf __maybe_unused, struct timespec *last_modification_time __maybe_unused) {
77
-#if defined(OS_MACOS) || defined(OS_WINDOWS)
78
- return 0;
79
-#else
80
- if(likely(statbuf->st_mtim.tv_sec == last_modification_time->tv_sec &&
81
- statbuf->st_mtim.tv_nsec == last_modification_time->tv_nsec)) return 0;
82
-
83
- last_modification_time->tv_sec = statbuf->st_mtim.tv_sec;
84
- last_modification_time->tv_nsec = statbuf->st_mtim.tv_nsec;
85
-
86
- return 1;
87
-#endif
88
-}
89
-
90
-static int read_user_or_group_ids(struct user_or_group_ids *ids, struct timespec *last_modification_time) {
91
- struct stat statbuf;
92
- if(unlikely(stat(ids->filename, &statbuf)))
93
- return 1;
94
- else
95
- if(likely(!file_changed(&statbuf, last_modification_time))) return 0;
96
-
97
- procfile *ff = procfile_open(ids->filename, " :\t", PROCFILE_FLAG_DEFAULT);
98
- if(unlikely(!ff)) return 1;
99
-
100
- ff = procfile_readall(ff);
101
- if(unlikely(!ff)) return 1;
102
-
103
- size_t line, lines = procfile_lines(ff);
104
-
105
- for(line = 0; line < lines ;line++) {
106
- size_t words = procfile_linewords(ff, line);
107
- if(unlikely(words < 3)) continue;
108
-
109
- char *name = procfile_lineword(ff, line, 0);
110
- if(unlikely(!name || !*name)) continue;
111
-
112
- char *id_string = procfile_lineword(ff, line, 2);
113
- if(unlikely(!id_string || !*id_string)) continue;
114
-
115
-
116
- struct user_or_group_id *user_or_group_id = callocz(1, sizeof(struct user_or_group_id));
117
-
118
-#if (PROCESSES_HAVE_UID == 1)
119
- if(ids->type == USER_ID)
120
- user_or_group_id->id.uid = (uid_t) str2ull(id_string, NULL);
121
-#endif
122
-#if (PROCESSES_HAVE_GID == 1)
123
- if(ids->type == GROUP_ID)
124
- user_or_group_id->id.gid = (uid_t) str2ull(id_string, NULL);
125
-#endif
126
-
127
- user_or_group_id->name = strdupz(name);
128
- user_or_group_id->updated = 1;
129
-
130
- struct user_or_group_id *existing_user_id = NULL;
131
-
132
- if(likely(ids->root))
133
- existing_user_id = (struct user_or_group_id *)avl_search(&ids->index, (avl_t *) user_or_group_id);
134
-
135
- if(unlikely(existing_user_id)) {
136
- freez(existing_user_id->name);
137
- existing_user_id->name = user_or_group_id->name;
138
- existing_user_id->updated = 1;
139
- freez(user_or_group_id);
140
- }
141
- else {
142
- if(unlikely(avl_insert(&ids->index, (avl_t *) user_or_group_id) != (void *) user_or_group_id)) {
143
- netdata_log_error("INTERNAL ERROR: duplicate indexing of id during realloc");
144
- }
145
-
146
- user_or_group_id->next = ids->root;
147
- ids->root = user_or_group_id;
148
- }
149
- }
150
-
151
- procfile_close(ff);
152
-
153
- // remove unused ids
154
- struct user_or_group_id *user_or_group_id = ids->root, *prev_user_id = NULL;
155
-
156
- while(user_or_group_id) {
157
- if(unlikely(!user_or_group_id->updated)) {
158
- if(unlikely((struct user_or_group_id *)avl_remove(&ids->index, (avl_t *) user_or_group_id) != user_or_group_id))
159
- netdata_log_error("INTERNAL ERROR: removal of unused id from index, removed a different id");
160
-
161
- if(prev_user_id)
162
- prev_user_id->next = user_or_group_id->next;
163
- else
164
- ids->root = user_or_group_id->next;
165
-
166
- freez(user_or_group_id->name);
167
- freez(user_or_group_id);
168
-
169
- if(prev_user_id)
170
- user_or_group_id = prev_user_id->next;
171
- else
172
- user_or_group_id = ids->root;
173
- }
174
- else {
175
- user_or_group_id->updated = 0;
176
-
177
- prev_user_id = user_or_group_id;
178
- user_or_group_id = user_or_group_id->next;
179
- }
180
- }
181
-
182
- return 0;
183
-}
184
-
185
-#if (PROCESSES_HAVE_UID == 1)
186
-struct user_or_group_id *user_id_find(struct user_or_group_id *user_id_to_find) {
187
- if(*netdata_configured_host_prefix) {
188
- static struct timespec last_passwd_modification_time;
189
- int ret = read_user_or_group_ids(&all_user_ids, &last_passwd_modification_time);
190
-
191
- if(likely(!ret && all_user_ids.index.root))
192
- return (struct user_or_group_id *)avl_search(&all_user_ids.index, (avl_t *)user_id_to_find);
193
- }
194
-
195
- return NULL;
196
-}
197
-#endif
198
-
199
-#if (PROCESSES_HAVE_GID == 1)
200
-struct user_or_group_id *group_id_find(struct user_or_group_id *group_id_to_find) {
201
- if(*netdata_configured_host_prefix) {
202
- static struct timespec last_group_modification_time;
203
- int ret = read_user_or_group_ids(&all_group_ids, &last_group_modification_time);
204
-
205
- if(likely(!ret && all_group_ids.index.root))
206
- return (struct user_or_group_id *)avl_search(&all_group_ids.index, (avl_t *) &group_id_to_find);
207
- }
208
-
209
- return NULL;
210
-}
211
-#endif
212
-#endif
213
-
214
-void apps_users_and_groups_init(void) {
215
-#if (PROCESSES_HAVE_UID == 1)
216
- snprintfz(all_user_ids.filename, FILENAME_MAX, "%s/etc/passwd", netdata_configured_host_prefix);
217
- debug_log("passwd file: '%s'", all_user_ids.filename);
218
-#endif
219
-
220
-#if (PROCESSES_HAVE_GID == 1)
221
- snprintfz(all_group_ids.filename, FILENAME_MAX, "%s/etc/group", netdata_configured_host_prefix);
222
- debug_log("group file: '%s'", all_group_ids.filename);
223
-#endif
224
-}
src/collectors/network-viewer.plugin/network-viewer.c
+7
-8
@@ -23,9 +23,8 @@ static SPAWN_SERVER *spawn_srv = NULL;
23
} aggregated_key; \
24
} network_viewer;
25
26
-#include "libnetdata/maps/local-sockets.h"
27
-#include "libnetdata/maps/system-users.h"
28
-#include "libnetdata/maps/system-services.h"
26
+#include "libnetdata/local-sockets/local-sockets.h"
27
+#include "libnetdata/os/system-maps/system-services.h"
28
29
#define NETWORK_CONNECTIONS_VIEWER_FUNCTION "network-connections"
30
#define NETWORK_CONNECTIONS_VIEWER_HELP "Network connections explorer"
@@ -36,7 +35,6 @@ static SPAWN_SERVER *spawn_srv = NULL;
35
36
netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
37
static bool plugin_should_exit = false;
39
-static USERNAMES_CACHE *uc;
38
static SERVICENAMES_CACHE *sc;
39
40
ENUM_STR_MAP_DEFINE(SOCKET_DIRECTION) = {
@@ -151,9 +149,9 @@ static void local_socket_to_json_array(struct sockets_stats *st, const LOCAL_SOC
149
}
150
else {
151
// buffer_json_add_array_item_uint64(wb, n->uid);
154
- STRING *u = system_usernames_cache_lookup_uid(uc, n->uid);
155
- buffer_json_add_array_item_string(wb, string2str(u));
156
- string_freez(u);
152
+ CACHED_USERNAME cu = cached_username_get_by_uid(n->uid);
153
+ buffer_json_add_array_item_string(wb, string2str(cu.username));
154
+ cached_username_release(cu);
155
}
156
157
const struct socket_endpoint *server_endpoint;
@@ -975,7 +973,8 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
973
}
974
#endif
975
978
- uc = system_usernames_cache_init();
976
+ cached_usernames_init();
977
+ update_cached_host_users();
978
sc = system_servicenames_cache_init();
979
980
// ----------------------------------------------------------------------------------------------------------------
src/collectors/systemd-journal.plugin/systemd-journal-annotations.c
+10
-20
@@ -2,18 +2,6 @@
2
3
#include "systemd-internals.h"
4
5
-// ----------------------------------------------------------------------------
6
-#include "libnetdata/maps/system-users.h"
7
-#include "libnetdata/maps/system-groups.h"
8
-
9
-static struct {
10
- USERNAMES_CACHE *uc;
11
- GROUPNAMES_CACHE *gc;
12
-} systemd_annotations_globals = {
13
- .uc = NULL,
14
- .gc = NULL,
15
-};
16
-
5
// ----------------------------------------------------------------------------
6
7
const char *errno_map[] = {
@@ -369,9 +357,9 @@ void netdata_systemd_journal_transform_uid(FACETS *facets __maybe_unused, BUFFER
357
const char *v = buffer_tostring(wb);
358
if(*v && isdigit(*v)) {
359
uid_t uid = str2i(buffer_tostring(wb));
372
- STRING *u = system_usernames_cache_lookup_uid(systemd_annotations_globals.uc, uid);
373
- buffer_contents_replace(wb, string2str(u), string_strlen(u));
374
- string_freez(u);
360
+ CACHED_USERNAME cu = cached_username_get_by_uid(uid);
361
+ buffer_contents_replace(wb, string2str(cu.username), string_strlen(cu.username));
362
+ cached_username_release(cu);
363
}
364
}
365
@@ -382,9 +370,9 @@ void netdata_systemd_journal_transform_gid(FACETS *facets __maybe_unused, BUFFER
370
const char *v = buffer_tostring(wb);
371
if(*v && isdigit(*v)) {
372
gid_t gid = str2i(buffer_tostring(wb));
385
- STRING *g = system_groupnames_cache_lookup_gid(systemd_annotations_globals.gc, gid);
386
- buffer_contents_replace(wb, string2str(g), string_strlen(g));
387
- string_freez(g);
373
+ CACHED_GROUPNAME cg = cached_groupname_get_by_gid(gid);
374
+ buffer_contents_replace(wb, string2str(cg.groupname), string_strlen(cg.groupname));
375
+ cached_groupname_release(cg);
376
}
377
}
378
@@ -650,8 +638,10 @@ void netdata_systemd_journal_transform_message_id(FACETS *facets __maybe_unused,
638
// ----------------------------------------------------------------------------
639
640
void netdata_systemd_journal_annotations_init(void) {
653
- systemd_annotations_globals.uc = system_usernames_cache_init();
654
- systemd_annotations_globals.gc = system_groupnames_cache_init();
641
+ cached_usernames_init();
642
+ cached_groupnames_init();
643
+ update_cached_host_users();
644
+ update_cached_host_groups();
645
netdata_systemd_journal_message_ids_init();
646
}
647
src/collectors/utils/local_listeners.c
+1
-1
@@ -1,7 +1,7 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
3
#include "libnetdata/libnetdata.h"
4
-#include "libnetdata/maps/local-sockets.h"
4
+#include "libnetdata/local-sockets/local-sockets.h"
5
#include "libnetdata/required_dummies.h"
6
7
// --------------------------------------------------------------------------------------------------------------------
src/collectors/windows-events.plugin/windows-events-providers.c
+8
-6
@@ -78,7 +78,8 @@ static struct {
78
.spinlock = NETDATA_SPINLOCK_INITIALIZER,
79
};
80
81
-static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property, TXT_UNICODE *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id);
81
+static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property,
82
+ TXT_UTF16 *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id);
83
84
const char *provider_get_name(PROVIDER_META_HANDLE *p) {
85
return (p && p->provider && p->provider->name) ? p->provider->name : "__UNKNOWN PROVIDER__";
@@ -226,7 +227,7 @@ PROVIDER_META_HANDLE *provider_get(ND_UUID uuid, LPCWSTR providerName) {
227
if(load_it) {
228
WEVT_VARIANT content = { 0 };
229
WEVT_VARIANT property = { 0 };
229
- TXT_UNICODE unicode = { 0 };
230
+ TXT_UTF16 unicode = { 0 };
231
232
provider_detect_platform(h, &content);
233
provider_load_list(h, &content, &property, &unicode, &p->keyword, EvtPublisherMetadataKeywords);
@@ -234,7 +235,7 @@ PROVIDER_META_HANDLE *provider_get(ND_UUID uuid, LPCWSTR providerName) {
235
provider_load_list(h, &content, &property, &unicode, &p->opcodes, EvtPublisherMetadataOpcodes);
236
provider_load_list(h, &content, &property, &unicode, &p->tasks, EvtPublisherMetadataTasks);
237
237
- txt_unicode_cleanup(&unicode);
238
+ txt_utf16_cleanup(&unicode);
239
wevt_variant_cleanup(&content);
240
wevt_variant_cleanup(&property);
241
}
@@ -365,7 +366,8 @@ static int compare_ascending(const void *a, const void *b) {
366
// return 0;
367
//}
368
368
-static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property, TXT_UNICODE *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id) {
369
+static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property,
370
+ TXT_UTF16 *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id) {
371
if(!h || !h->hMetadata) return;
372
373
EVT_PUBLISHER_METADATA_PROPERTY_ID name_id, message_id, value_id;
@@ -477,7 +479,7 @@ static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, W
479
if (messageID != (uint32_t)-1) {
480
if (EvtFormatMessage_utf16(dst, hMetadata, NULL, messageID, EvtFormatMessageId)) {
481
size_t len;
480
- d->name = unicode2utf8_strdupz(dst->data, &len);
482
+ d->name = utf16_to_utf8_strdupz(dst->data, &len);
483
d->len = len;
484
}
485
}
@@ -487,7 +489,7 @@ static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, W
489
if (!d->name && wevt_get_property_from_array(property, hArray, i, name_id)) {
490
fatal_assert(property->data->Type == EvtVarTypeString);
491
size_t len;
490
- d->name = unicode2utf8_strdupz(property->data->StringVal, &len);
492
+ d->name = utf16_to_utf8_strdupz(property->data->StringVal, &len);
493
d->len = len;
494
}
495
src/collectors/windows-events.plugin/windows-events-query-evt-variant.c
+7
-6
@@ -21,13 +21,14 @@ static inline void append_utf16(BUFFER *b, LPCWSTR utf16Str, const char *separat
21
remaining = b->size - b->len;
22
}
23
24
- size_t used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1);
25
- if(used >= remaining) {
26
- // oops, we need to resize
27
- size_t needed = utf16_to_utf8(NULL, 0, utf16Str, -1); // find the size needed
24
+ bool truncated = false;
25
+ size_t used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1, &truncated);
26
+ if(truncated) {
27
+ // we need to resize
28
+ size_t needed = utf16_to_utf8(NULL, 0, utf16Str, -1, NULL); // find the size needed
29
buffer_need_bytes(b, needed);
30
remaining = b->size - b->len;
30
- used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1);
31
+ used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1, NULL);
32
}
33
34
if(used) {
@@ -113,7 +114,7 @@ static inline void append_filetime(BUFFER *b, FILETIME *ft, const char *separato
114
}
115
116
static inline void append_sid(BUFFER *b, PSID sid, const char *separator) {
116
- buffer_sid_to_sid_str_and_name(sid, b, separator);
117
+ cached_sid_to_buffer_append(sid, b, separator);
118
}
119
120
static inline void append_sbyte(BUFFER *b, INT8 n, const char *separator) {
src/collectors/windows-events.plugin/windows-events-query.c
+14
-13
@@ -29,7 +29,8 @@ static const char *EvtGetExtendedStatus_utf8(void) {
29
30
// --------------------------------------------------------------------------------------------------------------------
31
32
-bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags) {
32
+bool EvtFormatMessage_utf16(
33
+ TXT_UTF16 *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags) {
34
dst->used = 0;
35
36
DWORD size = 0;
@@ -39,7 +40,7 @@ bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE h
40
// nd_log(NDLS_COLLECTORS, NDLP_ERR, "EvtFormatMessage() to get message size failed.");
41
goto cleanup;
42
}
42
- txt_unicode_resize(dst, size, false);
43
+ txt_utf16_resize(dst, size, false);
44
}
45
46
// First, try to get the message using the existing buffer
@@ -50,7 +51,7 @@ bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE h
51
}
52
53
// Try again with the resized buffer
53
- txt_unicode_resize(dst, size, false);
54
+ txt_utf16_resize(dst, size, false);
55
if (!EvtFormatMessage(hMetadata, hEvent, dwMessageId, 0, NULL, flags, dst->size, dst->data, &size)) {
56
// nd_log(NDLS_COLLECTORS, NDLP_ERR, "EvtFormatMessage() failed after resizing buffer.");
57
goto cleanup;
@@ -75,23 +76,23 @@ cleanup:
76
}
77
78
static bool EvtFormatMessage_utf8(
78
- TXT_UNICODE *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent,
79
+ TXT_UTF16 *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent,
80
TXT_UTF8 *dst, EVT_FORMAT_MESSAGE_FLAGS flags) {
81
82
dst->src = TXT_SOURCE_EVENT_LOG;
83
84
if(EvtFormatMessage_utf16(tmp, provider_handle(p), hEvent, 0, flags))
84
- return wevt_str_unicode_to_utf8(dst, tmp);
85
+ return txt_utf16_to_utf8(dst, tmp);
86
86
- wevt_utf8_empty(dst);
87
+ txt_utf8_empty(dst);
88
return false;
89
}
90
90
-bool EvtFormatMessage_Event_utf8(TXT_UNICODE *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
91
+bool EvtFormatMessage_Event_utf8(TXT_UTF16 *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
92
return EvtFormatMessage_utf8(tmp, p, hEvent, dst, EvtFormatMessageEvent);
93
}
94
94
-bool EvtFormatMessage_Xml_utf8(TXT_UNICODE *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
95
+bool EvtFormatMessage_Xml_utf8(TXT_UTF16 *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
96
return EvtFormatMessage_utf8(tmp, p, hEvent, dst, EvtFormatMessageXml);
97
}
98
@@ -130,7 +131,7 @@ static void wevt_get_level(WEVT_LOG *log, WEVT_EVENT *ev, PROVIDER_META_HANDLE *
131
TXT_UTF8 *dst = &log->ops.level;
132
uint64_t value = ev->level;
133
133
- wevt_utf8_empty(dst);
134
+ txt_utf8_empty(dst);
135
136
EVT_FORMAT_MESSAGE_FLAGS flags = EvtFormatMessageLevel;
137
WEVT_FIELD_TYPE cache_type = WEVT_FIELD_TYPE_LEVEL;
@@ -182,7 +183,7 @@ static void wevt_get_opcode(WEVT_LOG *log, WEVT_EVENT *ev, PROVIDER_META_HANDLE
183
TXT_UTF8 *dst = &log->ops.opcode;
184
uint64_t value = ev->opcode;
185
185
- wevt_utf8_empty(dst);
186
+ txt_utf8_empty(dst);
187
188
EVT_FORMAT_MESSAGE_FLAGS flags = EvtFormatMessageOpcode;
189
WEVT_FIELD_TYPE cache_type = WEVT_FIELD_TYPE_OPCODE;
@@ -224,7 +225,7 @@ static void wevt_get_task(WEVT_LOG *log, WEVT_EVENT *ev, PROVIDER_META_HANDLE *h
225
TXT_UTF8 *dst = &log->ops.task;
226
uint64_t value = ev->task;
227
227
- wevt_utf8_empty(dst);
228
+ txt_utf8_empty(dst);
229
230
EVT_FORMAT_MESSAGE_FLAGS flags = EvtFormatMessageTask;
231
WEVT_FIELD_TYPE cache_type = WEVT_FIELD_TYPE_TASK;
@@ -273,7 +274,7 @@ static uint64_t wevt_keyword_handle_reserved(uint64_t value, TXT_UTF8 *dst) {
274
SET_BITS(WEVT_KEYWORD_RESPONSE_TIME, WEVT_KEYWORD_NAME_RESPONSE_TIME),
275
};
276
276
- wevt_utf8_empty(dst);
277
+ txt_utf8_empty(dst);
278
279
for(size_t i = 0; i < sizeof(bits) / sizeof(bits[0]) ;i++) {
280
if((value & bits[i].mask) == bits[i].mask) {
@@ -592,7 +593,7 @@ void wevt_closelog6(WEVT_LOG *log) {
593
594
wevt_variant_cleanup(&log->ops.raw.system);
595
wevt_variant_cleanup(&log->ops.raw.user);
595
- txt_unicode_cleanup(&log->ops.unicode);
596
+ txt_utf16_cleanup(&log->ops.unicode);
597
txt_utf8_cleanup(&log->ops.channel);
598
txt_utf8_cleanup(&log->ops.provider);
599
txt_utf8_cleanup(&log->ops.computer);
src/collectors/windows-events.plugin/windows-events-query.h
+13
-12
@@ -83,7 +83,7 @@ typedef struct wevt_log {
83
// every string operation overwrites it, multiple times per event log entry
84
// it can be used within any function, for its own purposes,
85
// but never share between functions
86
- TXT_UNICODE unicode;
86
+ TXT_UTF16 unicode;
87
88
// string attributes of the current event log entry
89
// valid until another event if fetched
@@ -136,10 +136,11 @@ void wevt_query_done(WEVT_LOG *log);
136
137
bool wevt_get_next_event(WEVT_LOG *log, WEVT_EVENT *ev);
138
139
-bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags);
139
+bool EvtFormatMessage_utf16(
140
+ TXT_UTF16 *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags);
141
141
-bool EvtFormatMessage_Event_utf8(TXT_UNICODE *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
142
-bool EvtFormatMessage_Xml_utf8(TXT_UNICODE *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
142
+bool EvtFormatMessage_Event_utf8(TXT_UTF16 *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
143
+bool EvtFormatMessage_Xml_utf8(TXT_UTF16 *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
144
145
void evt_variant_to_buffer(BUFFER *b, EVT_VARIANT *ev, const char *separator);
146
@@ -152,7 +153,7 @@ static inline void wevt_variant_resize(WEVT_VARIANT *v, size_t required_size) {
153
return;
154
155
wevt_variant_cleanup(v);
155
- v->size = compute_new_size(v->size, required_size);
156
+ v->size = txt_compute_new_size(v->size, required_size);
157
v->data = mallocz(v->size);
158
}
159
@@ -202,25 +203,25 @@ static inline uint64_t wevt_field_get_uint64_hex(EVT_VARIANT *ev) {
203
204
static inline bool wevt_field_get_string_utf8(EVT_VARIANT *ev, TXT_UTF8 *dst) {
205
if((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeNull) {
205
- wevt_utf8_empty(dst);
206
+ txt_utf8_empty(dst);
207
return false;
208
}
209
210
fatal_assert((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeString);
210
- return wevt_str_wchar_to_utf8(dst, ev->StringVal, -1);
211
+ return wchar_to_txt_utf8(dst, ev->StringVal, -1);
212
}
213
213
-bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
214
+bool cached_sid_to_account_domain_sidstr(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
215
static inline bool wevt_field_get_sid(EVT_VARIANT *ev, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str) {
216
if((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeNull) {
216
- wevt_utf8_empty(dst_account);
217
- wevt_utf8_empty(dst_domain);
218
- wevt_utf8_empty(dst_sid_str);
217
+ txt_utf8_empty(dst_account);
218
+ txt_utf8_empty(dst_domain);
219
+ txt_utf8_empty(dst_sid_str);
220
return false;
221
}
222
223
fatal_assert((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeSid);
223
- return wevt_convert_user_id_to_name(ev->SidVal, dst_account, dst_domain, dst_sid_str);
224
+ return cached_sid_to_account_domain_sidstr(ev->SidVal, dst_account, dst_domain, dst_sid_str);
225
}
226
227
static inline uint64_t wevt_field_get_filetime_to_ns(EVT_VARIANT *ev) {
src/collectors/windows-events.plugin/windows-events-sid.h
deleted
-13
@@ -1,13 +0,0 @@
1
-// SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-#ifndef NETDATA_WINDOWS_EVENTS_SID_H
4
-#define NETDATA_WINDOWS_EVENTS_SID_H
5
-
6
-#include "windows-events.h"
7
-
8
-struct wevt_log;
9
-bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
10
-bool buffer_sid_to_sid_str_and_name(PSID sid, BUFFER *dst, const char *prefix);
11
-void sid_cache_init(void);
12
-
13
-#endif //NETDATA_WINDOWS_EVENTS_SID_H
src/collectors/windows-events.plugin/windows-events-unicode.c
-98
@@ -21,24 +21,6 @@ inline void unicode2utf8(char *dst, size_t dst_size, const wchar_t *src) {
21
strncpyz(dst, "[null]", dst_size - 1);
22
}
23
24
-char *unicode2utf8_strdupz(const wchar_t *src, size_t *utf8_len) {
25
- int size = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
26
- if (size > 0) {
27
- char *dst = mallocz(size);
28
- WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, size, NULL, NULL);
29
-
30
- if(utf8_len)
31
- *utf8_len = size - 1;
32
-
33
- return dst;
34
- }
35
-
36
- if(utf8_len)
37
- *utf8_len = 0;
38
-
39
- return NULL;
40
-}
41
-
24
wchar_t *channel2unicode(const char *utf8str) {
25
static __thread wchar_t buffer[1024];
26
utf82unicode(buffer, _countof(buffer), utf8str);
@@ -51,18 +33,6 @@ char *channel2utf8(const wchar_t *channel) {
33
return buffer;
34
}
35
54
-char *account2utf8(const wchar_t *user) {
55
- static __thread char buffer[1024];
56
- unicode2utf8(buffer, sizeof(buffer), user);
57
- return buffer;
58
-}
59
-
60
-char *domain2utf8(const wchar_t *domain) {
61
- static __thread char buffer[1024];
62
- unicode2utf8(buffer, sizeof(buffer), domain);
63
- return buffer;
64
-}
65
-
36
char *query2utf8(const wchar_t *query) {
37
static __thread char buffer[16384];
38
unicode2utf8(buffer, sizeof(buffer), query);
@@ -74,71 +44,3 @@ char *provider2utf8(const wchar_t *provider) {
44
unicode2utf8(buffer, sizeof(buffer), provider);
45
return buffer;
46
}
77
-
78
-bool wevt_str_wchar_to_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len_with_null) {
79
- if(!src || !src_len_with_null)
80
- goto cleanup;
81
-
82
- // make sure the input is null terminated at the exact point we need it
83
- // (otherwise, the output will not be null terminated either)
84
- fatal_assert(src_len_with_null == -1 || (src_len_with_null >= 1 && src[src_len_with_null - 1] == 0));
85
-
86
- // Try to convert using the existing buffer (if it exists, otherwise get the required buffer size)
87
- int size = WideCharToMultiByte(CP_UTF8, 0, src, src_len_with_null, dst->data, (int)dst->size, NULL, NULL);
88
- if(size <= 0 || !dst->data) {
89
- // we have to set a buffer, or increase it
90
-
91
- if(dst->data) {
92
- // we need to increase it the buffer size
93
-
94
- if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
95
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "WideCharToMultiByte() failed.");
96
- goto cleanup;
97
- }
98
-
99
- // we have to find the required buffer size
100
- size = WideCharToMultiByte(CP_UTF8, 0, src, src_len_with_null, NULL, 0, NULL, NULL);
101
- if(size <= 0)
102
- goto cleanup;
103
- }
104
-
105
- // Retry conversion with the new buffer
106
- txt_utf8_resize(dst, size, false);
107
- size = WideCharToMultiByte(CP_UTF8, 0, src, src_len_with_null, dst->data, (int)dst->size, NULL, NULL);
108
- if (size <= 0) {
109
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "WideCharToMultiByte() failed after resizing.");
110
- goto cleanup;
111
- }
112
- }
113
-
114
- // Make sure it is not zero padded at the end
115
- while(size >= 2 && dst->data[size - 2] == 0)
116
- size--;
117
-
118
- dst->used = (size_t)size;
119
-
120
- internal_fatal(strlen(dst->data) + 1 != dst->used,
121
- "Wrong UTF8 string length");
122
-
123
- return true;
124
-
125
-cleanup:
126
- txt_utf8_resize(dst, 128, false);
127
- if(src)
128
- dst->used = snprintfz(dst->data, dst->size, "[failed conv.]") + 1;
129
- else {
130
- dst->data[0] = '\0';
131
- dst->used = 1;
132
- }
133
-
134
- return false;
135
-}
136
-
137
-bool wevt_str_unicode_to_utf8(TXT_UTF8 *dst, TXT_UNICODE *unicode) {
138
- fatal_assert(dst && ((dst->data && dst->size) || (!dst->data && !dst->size)));
139
- fatal_assert(unicode && ((unicode->data && unicode->size) || (!unicode->data && !unicode->size)));
140
-
141
- // pass the entire unicode size, including the null terminator
142
- // so that the resulting utf8 message will be null terminated too.
143
- return wevt_str_wchar_to_utf8(dst, unicode->data, (int)unicode->used);
144
-}
src/collectors/windows-events.plugin/windows-events-unicode.h
-140
@@ -7,87 +7,6 @@
7
#include <windows.h>
8
#include <wchar.h>
9
10
-typedef enum __attribute__((packed)) {
11
- TXT_SOURCE_UNKNOWN = 0,
12
- TXT_SOURCE_PROVIDER,
13
- TXT_SOURCE_FIELD_CACHE,
14
- TXT_SOURCE_EVENT_LOG,
15
- TXT_SOURCE_HARDCODED,
16
-
17
- // terminator
18
- TXT_SOURCE_MAX,
19
-} TXT_SOURCE;
20
-
21
-static inline size_t compute_new_size(size_t old_size, size_t required_size) {
22
- size_t size = (required_size % 2048 == 0) ? required_size : required_size + 2048;
23
- size = (size / 2048) * 2048;
24
-
25
- if(size < old_size * 2)
26
- size = old_size * 2;
27
-
28
- return size;
29
-}
30
-
31
-// --------------------------------------------------------------------------------------------------------------------
32
-// TXT_UTF8
33
-
34
-typedef struct {
35
- char *data;
36
- size_t size; // the allocated size of data buffer
37
- size_t used; // the used size of the data buffer (including null terminators, if any)
38
- TXT_SOURCE src;
39
-} TXT_UTF8;
40
-
41
-static inline void txt_utf8_cleanup(TXT_UTF8 *dst) {
42
- freez(dst->data);
43
- dst->data = NULL;
44
- dst->used = 0;
45
-}
46
-
47
-static inline void txt_utf8_resize(TXT_UTF8 *dst, size_t required_size, bool keep) {
48
- if(required_size <= dst->size)
49
- return;
50
-
51
- size_t new_size = compute_new_size(dst->size, required_size);
52
-
53
- if(keep && dst->data)
54
- dst->data = reallocz(dst->data, new_size);
55
- else {
56
- txt_utf8_cleanup(dst);
57
- dst->data = mallocz(new_size);
58
- dst->used = 0;
59
- }
60
-
61
- dst->size = new_size;
62
-}
63
-
64
-static inline void wevt_utf8_empty(TXT_UTF8 *dst) {
65
- txt_utf8_resize(dst, 1, false);
66
- dst->data[0] = '\0';
67
- dst->used = 1;
68
-}
69
-
70
-static inline void txt_utf8_set(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
71
- txt_utf8_resize(dst, dst->used + txt_len + 1, true);
72
- memcpy(dst->data, txt, txt_len);
73
- dst->used = txt_len + 1;
74
- dst->data[dst->used - 1] = '\0';
75
-}
76
-
77
-static inline void txt_utf8_append(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
78
- if(dst->used <= 1) {
79
- // the destination is empty
80
- txt_utf8_set(dst, txt, txt_len);
81
- }
82
- else {
83
- // there is something already in the buffer
84
- txt_utf8_resize(dst, dst->used + txt_len, true);
85
- memcpy(&dst->data[dst->used - 1], txt, txt_len);
86
- dst->used += txt_len; // the null was already counted
87
- dst->data[dst->used - 1] = '\0';
88
- }
89
-}
90
-
10
#define WINEVENT_NAME_KEYWORDS_SEPARATOR ", "
11
static inline void txt_utf8_add_keywords_separator_if_needed(TXT_UTF8 *dst) {
12
if(dst->used > 1)
@@ -110,75 +29,16 @@ static inline void txt_utf8_set_hex_if_empty(TXT_UTF8 *dst, const char *prefix,
29
}
30
}
31
113
-// --------------------------------------------------------------------------------------------------------------------
114
-// TXT_UNICODE
115
-
116
-typedef struct {
117
- wchar_t *data;
118
- size_t size; // the allocated size of data buffer
119
- size_t used; // the used size of the data buffer (including null terminators, if any)
120
-} TXT_UNICODE;
121
-
122
-static inline void txt_unicode_cleanup(TXT_UNICODE *dst) {
123
- freez(dst->data);
124
-}
125
-
126
-static inline void txt_unicode_resize(TXT_UNICODE *dst, size_t required_size, bool keep) {
127
- if(required_size <= dst->size)
128
- return;
129
-
130
- size_t new_size = compute_new_size(dst->size, required_size);
131
-
132
- if (keep && dst->data) {
133
- dst->data = reallocz(dst->data, new_size * sizeof(wchar_t));
134
- } else {
135
- txt_unicode_cleanup(dst);
136
- dst->data = mallocz(new_size * sizeof(wchar_t));
137
- dst->used = 0;
138
- }
139
-
140
- dst->size = new_size;
141
-}
142
-
143
-static inline void txt_unicode_set(TXT_UNICODE *dst, const wchar_t *txt, size_t txt_len) {
144
- txt_unicode_resize(dst, dst->used + txt_len + 1, true);
145
- memcpy(dst->data, txt, txt_len * sizeof(wchar_t));
146
- dst->used = txt_len + 1;
147
- dst->data[dst->used - 1] = '\0';
148
-}
149
-
150
-static inline void txt_unicode_append(TXT_UNICODE *dst, const wchar_t *txt, size_t txt_len) {
151
- if(dst->used <= 1) {
152
- // the destination is empty
153
- txt_unicode_set(dst, txt, txt_len);
154
- }
155
- else {
156
- // there is something already in the buffer
157
- txt_unicode_resize(dst, dst->used + txt_len, true);
158
- memcpy(&dst->data[dst->used - 1], txt, txt_len * sizeof(wchar_t));
159
- dst->used += txt_len; // the null was already counted
160
- dst->data[dst->used - 1] = '\0';
161
- }
162
-}
163
-
32
// --------------------------------------------------------------------------------------------------------------------
33
// conversions
34
167
-bool wevt_str_unicode_to_utf8(TXT_UTF8 *dst, TXT_UNICODE *unicode);
168
-bool wevt_str_wchar_to_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len_with_null);
169
-
35
void unicode2utf8(char *dst, size_t dst_size, const wchar_t *src);
36
void utf82unicode(wchar_t *dst, size_t dst_size, const char *src);
37
173
-char *account2utf8(const wchar_t *user);
174
-char *domain2utf8(const wchar_t *domain);
175
-
38
char *channel2utf8(const wchar_t *channel);
39
wchar_t *channel2unicode(const char *utf8str);
40
41
char *query2utf8(const wchar_t *query);
42
char *provider2utf8(const wchar_t *provider);
43
182
-char *unicode2utf8_strdupz(const wchar_t *src, size_t *utf8_len);
183
-
44
#endif //NETDATA_WINDOWS_EVENTS_UNICODE_H
src/collectors/windows-events.plugin/windows-events.c
+1
-1
@@ -1299,7 +1299,7 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
1299
1300
wevt_sources_init();
1301
provider_cache_init();
1302
- sid_cache_init();
1302
+ cached_sid_username_init();
1303
field_cache_init();
1304
1305
if(!EnableWindowsPrivilege(SE_SECURITY_NAME))
src/collectors/windows-events.plugin/windows-events.h
-1
@@ -126,7 +126,6 @@ typedef enum {
126
127
#include "windows-events-sources.h"
128
#include "windows-events-unicode.h"
129
-#include "windows-events-sid.h"
129
#include "windows-events-xml.h"
130
#include "windows-events-providers.h"
131
#include "windows-events-fields-cache.h"
src/collectors/windows.plugin/perflib-storage.c
-1
@@ -6,7 +6,6 @@
6
#define _COMMON_PLUGIN_NAME PLUGIN_WINDOWS_NAME
7
#define _COMMON_PLUGIN_MODULE_NAME "PerflibStorage"
8
#include "../common-contexts/common-contexts.h"
9
-
9
#include "libnetdata/os/windows-wmi/windows-wmi.h"
10
11
struct logical_disk {
src/database/engine/cache.h
+11
@@ -248,4 +248,15 @@ struct aral_statistics *pgc_aral_statistics(void);
248
size_t pgc_aral_structures(void);
249
size_t pgc_aral_overhead(void);
250
251
+static inline size_t indexing_partition(Word_t ptr, Word_t modulo) __attribute__((const));
252
+static inline size_t indexing_partition(Word_t ptr, Word_t modulo) {
253
+#ifdef ENV64BIT
254
+ uint64_t hash = murmur64(ptr);
255
+ return hash % modulo;
256
+#else
257
+ uint32_t hash = murmur32(ptr);
258
+ return hash % modulo;
259
+#endif
260
+}
261
+
262
#endif // DBENGINE_CACHE_H
src/libnetdata/buffer/buffer.h
+2
@@ -3,6 +3,8 @@
3
#ifndef NETDATA_WEB_BUFFER_H
4
#define NETDATA_WEB_BUFFER_H 1
5
6
+#include "../uuid/uuid.h"
7
+#include "../http/content_type.h"
8
#include "../string/utf8.h"
9
#include "../libnetdata.h"
10
src/libnetdata/common.h
new
+394
@@ -0,0 +1,394 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef LIBNETDATA_COMMON_H
4
+#define LIBNETDATA_COMMON_H
5
+
6
+# ifdef __cplusplus
7
+extern "C" {
8
+# endif
9
+
10
+#include "config.h"
11
+
12
+#if defined(NETDATA_DEV_MODE) && !defined(NETDATA_INTERNAL_CHECKS)
13
+#define NETDATA_INTERNAL_CHECKS 1
14
+#endif
15
+
16
+#ifndef SIZEOF_VOID_P
17
+#error SIZEOF_VOID_P is not defined
18
+#endif
19
+
20
+#if SIZEOF_VOID_P == 4
21
+#define ENV32BIT 1
22
+#else
23
+#define ENV64BIT 1
24
+#endif
25
+
26
+#ifdef HAVE_LIBDATACHANNEL
27
+#define ENABLE_WEBRTC 1
28
+#endif
29
+
30
+#define STRINGIFY(x) #x
31
+#define TOSTRING(x) STRINGIFY(x)
32
+
33
+// --------------------------------------------------------------------------------------------------------------------
34
+// NETDATA_OS_TYPE
35
+
36
+#if defined(__FreeBSD__)
37
+#include <pthread_np.h>
38
+#define NETDATA_OS_TYPE "freebsd"
39
+#elif defined(__APPLE__)
40
+#define NETDATA_OS_TYPE "macos"
41
+#elif defined(OS_WINDOWS)
42
+#define NETDATA_OS_TYPE "windows"
43
+#else
44
+#define NETDATA_OS_TYPE "linux"
45
+#endif /* __FreeBSD__, __APPLE__*/
46
+
47
+// --------------------------------------------------------------------------------------------------------------------
48
+// memory allocators
49
+
50
+/* select the memory allocator, based on autoconf findings */
51
+#if defined(ENABLE_JEMALLOC)
52
+
53
+#if defined(HAVE_JEMALLOC_JEMALLOC_H)
54
+#include <jemalloc/jemalloc.h>
55
+#else // !defined(HAVE_JEMALLOC_JEMALLOC_H)
56
+#include <malloc.h>
57
+#endif // !defined(HAVE_JEMALLOC_JEMALLOC_H)
58
+
59
+#elif defined(ENABLE_TCMALLOC)
60
+
61
+#include <google/tcmalloc.h>
62
+
63
+#else /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
64
+
65
+#if !(defined(__FreeBSD__) || defined(__APPLE__))
66
+#include <malloc.h>
67
+#endif /* __FreeBSD__ || __APPLE__ */
68
+
69
+#endif /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
70
+
71
+// --------------------------------------------------------------------------------------------------------------------
72
+
73
+#include <pthread.h>
74
+#include <errno.h>
75
+#include <stdbool.h>
76
+#include <stdio.h>
77
+#include <stdlib.h>
78
+#include <stdarg.h>
79
+#include <stddef.h>
80
+#include <ctype.h>
81
+#include <string.h>
82
+#include <strings.h>
83
+#include <libgen.h>
84
+#include <dirent.h>
85
+#include <fcntl.h>
86
+#include <getopt.h>
87
+#include <limits.h>
88
+#include <locale.h>
89
+#include <signal.h>
90
+#include <sys/time.h>
91
+#include <sys/types.h>
92
+#include <time.h>
93
+#include <unistd.h>
94
+#include <uv.h>
95
+#include <assert.h>
96
+
97
+#ifdef HAVE_ARPA_INET_H
98
+#include <arpa/inet.h>
99
+#endif
100
+
101
+#ifdef HAVE_NETINET_TCP_H
102
+#include <netinet/tcp.h>
103
+#endif
104
+
105
+#ifdef HAVE_SYS_IOCTL_H
106
+#include <sys/ioctl.h>
107
+#endif
108
+
109
+#ifdef HAVE_GRP_H
110
+#include <grp.h>
111
+#else
112
+typedef uint32_t gid_t;
113
+#endif
114
+
115
+#ifdef HAVE_PWD_H
116
+#include <pwd.h>
117
+#else
118
+typedef uint32_t uid_t;
119
+#endif
120
+
121
+#ifdef HAVE_NET_IF_H
122
+#include <net/if.h>
123
+#endif
124
+
125
+#ifdef HAVE_POLL_H
126
+#include <poll.h>
127
+#endif
128
+
129
+#ifdef HAVE_SYSLOG_H
130
+#include <syslog.h>
131
+#else
132
+/* priorities */
133
+#define LOG_EMERG 0 /* system is unusable */
134
+#define LOG_ALERT 1 /* action must be taken immediately */
135
+#define LOG_CRIT 2 /* critical conditions */
136
+#define LOG_ERR 3 /* error conditions */
137
+#define LOG_WARNING 4 /* warning conditions */
138
+#define LOG_NOTICE 5 /* normal but significant condition */
139
+#define LOG_INFO 6 /* informational */
140
+#define LOG_DEBUG 7 /* debug-level messages */
141
+
142
+/* facility codes */
143
+#define LOG_KERN (0<<3) /* kernel messages */
144
+#define LOG_USER (1<<3) /* random user-level messages */
145
+#define LOG_MAIL (2<<3) /* mail system */
146
+#define LOG_DAEMON (3<<3) /* system daemons */
147
+#define LOG_AUTH (4<<3) /* security/authorization messages */
148
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
149
+#define LOG_LPR (6<<3) /* line printer subsystem */
150
+#define LOG_NEWS (7<<3) /* network news subsystem */
151
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
152
+#define LOG_CRON (9<<3) /* clock daemon */
153
+#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
154
+#define LOG_FTP (11<<3) /* ftp daemon */
155
+
156
+/* other codes through 15 reserved for system use */
157
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
158
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
159
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
160
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
161
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
162
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
163
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
164
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
165
+#endif
166
+
167
+#ifdef HAVE_SYS_MMAN_H
168
+#include <sys/mman.h>
169
+#endif
170
+
171
+#ifdef HAVE_SYS_RESOURCE_H
172
+#include <sys/resource.h>
173
+#endif
174
+
175
+#ifdef HAVE_SYS_SOCKET_H
176
+#include <sys/socket.h>
177
+#endif
178
+
179
+#ifdef HAVE_SYS_WAIT_H
180
+#include <sys/wait.h>
181
+#endif
182
+
183
+#ifdef HAVE_SYS_UN_H
184
+#include <sys/un.h>
185
+#endif
186
+
187
+#ifdef HAVE_SPAWN_H
188
+#include <spawn.h>
189
+#endif
190
+
191
+#ifdef HAVE_NETINET_IN_H
192
+#include <netinet/in.h>
193
+#endif
194
+
195
+#ifdef HAVE_RESOLV_H
196
+#include <resolv.h>
197
+#endif
198
+
199
+#ifdef HAVE_NETDB_H
200
+#include <netdb.h>
201
+#endif
202
+
203
+#ifdef HAVE_SYS_PRCTL_H
204
+#include <sys/prctl.h>
205
+#endif
206
+
207
+#ifdef HAVE_SYS_STAT_H
208
+#include <sys/stat.h>
209
+#endif
210
+
211
+#ifdef HAVE_SYS_VFS_H
212
+#include <sys/vfs.h>
213
+#endif
214
+
215
+#ifdef HAVE_SYS_STATFS_H
216
+#include <sys/statfs.h>
217
+#endif
218
+
219
+#ifdef HAVE_LINUX_MAGIC_H
220
+#include <linux/magic.h>
221
+#endif
222
+
223
+#ifdef HAVE_SYS_MOUNT_H
224
+#include <sys/mount.h>
225
+#endif
226
+
227
+#ifdef HAVE_SYS_STATVFS_H
228
+#include <sys/statvfs.h>
229
+#endif
230
+
231
+// #1408
232
+#ifdef MAJOR_IN_MKDEV
233
+#include <sys/mkdev.h>
234
+#endif
235
+#ifdef MAJOR_IN_SYSMACROS
236
+#include <sys/sysmacros.h>
237
+#endif
238
+
239
+#include <math.h>
240
+#include <float.h>
241
+
242
+#if defined(HAVE_INTTYPES_H)
243
+#include <inttypes.h>
244
+#elif defined(HAVE_STDINT_H)
245
+#include <stdint.h>
246
+#endif
247
+
248
+#include <zlib.h>
249
+
250
+#ifdef HAVE_SYS_CAPABILITY_H
251
+#include <sys/capability.h>
252
+#endif
253
+
254
+#define XXH_INLINE_ALL
255
+#include "xxhash.h"
256
+
257
+// --------------------------------------------------------------------------------------------------------------------
258
+// OpenSSL
259
+
260
+#define OPENSSL_VERSION_095 0x00905100L
261
+#define OPENSSL_VERSION_097 0x0907000L
262
+#define OPENSSL_VERSION_110 0x10100000L
263
+#define OPENSSL_VERSION_111 0x10101000L
264
+#define OPENSSL_VERSION_300 0x30000000L
265
+
266
+#include <openssl/ssl.h>
267
+#include <openssl/rand.h>
268
+#include <openssl/err.h>
269
+#include <openssl/evp.h>
270
+#include <openssl/pem.h>
271
+#if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097) && (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
272
+#include <openssl/conf.h>
273
+#endif
274
+
275
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_300
276
+#include <openssl/core_names.h>
277
+#include <openssl/decoder.h>
278
+#endif
279
+
280
+// --------------------------------------------------------------------------------------------------------------------
281
+
282
+#ifndef O_CLOEXEC
283
+#define O_CLOEXEC (0)
284
+#endif
285
+
286
+// --------------------------------------------------------------------------------------------------------------------
287
+// FUNCTION ATTRIBUTES
288
+
289
+#define _cleanup_(x) __attribute__((__cleanup__(x)))
290
+
291
+#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
292
+#define NEVERNULL __attribute__((returns_nonnull))
293
+#else
294
+#define NEVERNULL
295
+#endif
296
+
297
+#ifdef HAVE_FUNC_ATTRIBUTE_NOINLINE
298
+#define NOINLINE __attribute__((noinline))
299
+#else
300
+#define NOINLINE
301
+#endif
302
+
303
+#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
304
+#define MALLOCLIKE __attribute__((malloc))
305
+#else
306
+#define MALLOCLIKE
307
+#endif
308
+
309
+#if defined(HAVE_FUNC_ATTRIBUTE_FORMAT_GNU_PRINTF)
310
+#define PRINTFLIKE(f, a) __attribute__ ((format(gnu_printf, f, a)))
311
+#elif defined(HAVE_FUNC_ATTRIBUTE_FORMAT_PRINTF)
312
+#define PRINTFLIKE(f, a) __attribute__ ((format(printf, f, a)))
313
+#else
314
+#define PRINTFLIKE(f, a)
315
+#endif
316
+
317
+#ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
318
+#define NORETURN __attribute__ ((noreturn))
319
+#else
320
+#define NORETURN
321
+#endif
322
+
323
+#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
324
+#define WARNUNUSED __attribute__ ((warn_unused_result))
325
+#else
326
+#define WARNUNUSED
327
+#endif
328
+
329
+#define UNUSED(x) (void)(x)
330
+
331
+#ifdef __GNUC__
332
+#define UNUSED_FUNCTION(x) __attribute__((unused)) UNUSED_##x
333
+#else
334
+#define UNUSED_FUNCTION(x) UNUSED_##x
335
+#endif
336
+
337
+// --------------------------------------------------------------------------------------------------------------------
338
+// fix for alpine linux
339
+
340
+#if !defined(RUSAGE_THREAD) && defined(RUSAGE_CHILDREN)
341
+#define RUSAGE_THREAD RUSAGE_CHILDREN
342
+#endif
343
+
344
+// --------------------------------------------------------------------------------------------------------------------
345
+// HELPFUL MACROS
346
+
347
+#define ABS(x) (((x) < 0)? (-(x)) : (x))
348
+#define MIN(a,b) (((a)<(b))?(a):(b))
349
+#define MAX(a,b) (((a)>(b))?(a):(b))
350
+#define SWAP(a, b) do { \
351
+ typeof(a) _tmp = b; \
352
+ b = a; \
353
+ a = _tmp; \
354
+} while(0)
355
+
356
+// --------------------------------------------------------------------------------------------------------------------
357
+// NETDATA CLOUD
358
+
359
+// BEWARE: this exists in alarm-notify.sh
360
+#define DEFAULT_CLOUD_BASE_URL "https://app.netdata.cloud"
361
+
362
+// --------------------------------------------------------------------------------------------------------------------
363
+// DBENGINE
364
+
365
+#define RRD_STORAGE_TIERS 5
366
+
367
+// --------------------------------------------------------------------------------------------------------------------
368
+// PIPES
369
+
370
+#define PIPE_READ 0
371
+#define PIPE_WRITE 1
372
+
373
+// --------------------------------------------------------------------------------------------------------------------
374
+// UUIDs
375
+
376
+#define GUID_LEN 36
377
+
378
+// --------------------------------------------------------------------------------------------------------------------
379
+// Macro-only includes
380
+
381
+#include "linked-lists.h"
382
+
383
+// --------------------------------------------------------------------------------------------------------------------
384
+
385
+// Taken from linux kernel
386
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
387
+
388
+// --------------------------------------------------------------------------------------------------------------------
389
+
390
+# ifdef __cplusplus
391
+}
392
+# endif
393
+
394
+#endif //LIBNETDATA_COMMON_H
src/libnetdata/inlined.h
-11
@@ -106,17 +106,6 @@ static inline uint64_t murmur64(uint64_t k) {
106
return k;
107
}
108
109
-static inline size_t indexing_partition(Word_t ptr, Word_t modulo) __attribute__((const));
110
-static inline size_t indexing_partition(Word_t ptr, Word_t modulo) {
111
-#ifdef ENV64BIT
112
- uint64_t hash = murmur64(ptr);
113
- return hash % modulo;
114
-#else
115
- uint32_t hash = murmur32(ptr);
116
- return hash % modulo;
117
-#endif
118
-}
119
-
109
static inline unsigned int str2u(const char *s) {
110
unsigned int n = 0;
111
src/libnetdata/libnetdata.c
+4
@@ -2,6 +2,10 @@
2
3
#include "libnetdata.h"
4
5
+#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
6
+#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
7
+#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
8
+
9
#if !defined(MADV_DONTFORK)
10
#define MADV_DONTFORK 0
11
#endif
src/libnetdata/libnetdata.h
+36
-357
@@ -7,323 +7,17 @@
7
extern "C" {
8
# endif
9
10
-#include "config.h"
11
-
12
-#ifdef HAVE_LIBDATACHANNEL
13
-#define ENABLE_WEBRTC 1
14
-#endif
15
-
16
-#define STRINGIFY(x) #x
17
-#define TOSTRING(x) STRINGIFY(x)
10
+#include "common.h"
11
12
#define JUDYHS_INDEX_SIZE_ESTIMATE(key_bytes) (((key_bytes) + sizeof(Word_t) - 1) / sizeof(Word_t) * 4)
13
21
-#if defined(NETDATA_DEV_MODE) && !defined(NETDATA_INTERNAL_CHECKS)
22
-#define NETDATA_INTERNAL_CHECKS 1
23
-#endif
24
-
25
-#ifndef SIZEOF_VOID_P
26
-#error SIZEOF_VOID_P is not defined
27
-#endif
28
-
29
-#if SIZEOF_VOID_P == 4
30
-#define ENV32BIT 1
31
-#else
32
-#define ENV64BIT 1
33
-#endif
34
-
14
// NETDATA_TRACE_ALLOCATIONS does not work under musl libc, so don't enable it
15
//#if defined(NETDATA_INTERNAL_CHECKS) && !defined(NETDATA_TRACE_ALLOCATIONS)
16
//#define NETDATA_TRACE_ALLOCATIONS 1
17
//#endif
18
40
-#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
41
-#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
42
-#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
43
-
44
-// ----------------------------------------------------------------------------
45
-// system include files for all netdata C programs
46
-
47
-/* select the memory allocator, based on autoconf findings */
48
-#if defined(ENABLE_JEMALLOC)
49
-
50
-#if defined(HAVE_JEMALLOC_JEMALLOC_H)
51
-#include <jemalloc/jemalloc.h>
52
-#else // !defined(HAVE_JEMALLOC_JEMALLOC_H)
53
-#include <malloc.h>
54
-#endif // !defined(HAVE_JEMALLOC_JEMALLOC_H)
55
-
56
-#elif defined(ENABLE_TCMALLOC)
57
-
58
-#include <google/tcmalloc.h>
59
-
60
-#else /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
61
-
62
-#if !(defined(__FreeBSD__) || defined(__APPLE__))
63
-#include <malloc.h>
64
-#endif /* __FreeBSD__ || __APPLE__ */
65
-
66
-#endif /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
67
-
68
-// ----------------------------------------------------------------------------
69
-
70
-#if defined(__FreeBSD__)
71
-#include <pthread_np.h>
72
-#define NETDATA_OS_TYPE "freebsd"
73
-#elif defined(__APPLE__)
74
-#define NETDATA_OS_TYPE "macos"
75
-#elif defined(OS_WINDOWS)
76
-#define NETDATA_OS_TYPE "windows"
77
-#else
78
-#define NETDATA_OS_TYPE "linux"
79
-#endif /* __FreeBSD__, __APPLE__*/
80
-
81
-#include <pthread.h>
82
-#include <errno.h>
83
-#include <stdbool.h>
84
-#include <stdio.h>
85
-#include <stdlib.h>
86
-#include <stdarg.h>
87
-#include <stddef.h>
88
-#include <ctype.h>
89
-#include <string.h>
90
-#include <strings.h>
91
-#include <libgen.h>
92
-#include <dirent.h>
93
-#include <fcntl.h>
94
-#include <getopt.h>
95
-#include <limits.h>
96
-#include <locale.h>
97
-#include <signal.h>
98
-#include <sys/time.h>
99
-#include <sys/types.h>
100
-#include <time.h>
101
-#include <unistd.h>
102
-#include <uv.h>
103
-#include <assert.h>
104
-
105
-#ifdef HAVE_ARPA_INET_H
106
-#include <arpa/inet.h>
107
-#endif
108
-
109
-#ifdef HAVE_NETINET_TCP_H
110
-#include <netinet/tcp.h>
111
-#endif
112
-
113
-#ifdef HAVE_SYS_IOCTL_H
114
-#include <sys/ioctl.h>
115
-#endif
116
-
117
-#ifdef HAVE_GRP_H
118
-#include <grp.h>
119
-#else
120
-typedef uint32_t gid_t;
121
-#endif
122
-
123
-#ifdef HAVE_PWD_H
124
-#include <pwd.h>
125
-#else
126
-typedef uint32_t uid_t;
127
-#endif
128
-
129
-#ifdef HAVE_NET_IF_H
130
-#include <net/if.h>
131
-#endif
132
-
133
-#ifdef HAVE_POLL_H
134
-#include <poll.h>
135
-#endif
136
-
137
-#ifdef HAVE_SYSLOG_H
138
-#include <syslog.h>
139
-#else
140
-/* priorities */
141
-#define LOG_EMERG 0 /* system is unusable */
142
-#define LOG_ALERT 1 /* action must be taken immediately */
143
-#define LOG_CRIT 2 /* critical conditions */
144
-#define LOG_ERR 3 /* error conditions */
145
-#define LOG_WARNING 4 /* warning conditions */
146
-#define LOG_NOTICE 5 /* normal but significant condition */
147
-#define LOG_INFO 6 /* informational */
148
-#define LOG_DEBUG 7 /* debug-level messages */
149
-
150
-/* facility codes */
151
-#define LOG_KERN (0<<3) /* kernel messages */
152
-#define LOG_USER (1<<3) /* random user-level messages */
153
-#define LOG_MAIL (2<<3) /* mail system */
154
-#define LOG_DAEMON (3<<3) /* system daemons */
155
-#define LOG_AUTH (4<<3) /* security/authorization messages */
156
-#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
157
-#define LOG_LPR (6<<3) /* line printer subsystem */
158
-#define LOG_NEWS (7<<3) /* network news subsystem */
159
-#define LOG_UUCP (8<<3) /* UUCP subsystem */
160
-#define LOG_CRON (9<<3) /* clock daemon */
161
-#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
162
-#define LOG_FTP (11<<3) /* ftp daemon */
163
-
164
-/* other codes through 15 reserved for system use */
165
-#define LOG_LOCAL0 (16<<3) /* reserved for local use */
166
-#define LOG_LOCAL1 (17<<3) /* reserved for local use */
167
-#define LOG_LOCAL2 (18<<3) /* reserved for local use */
168
-#define LOG_LOCAL3 (19<<3) /* reserved for local use */
169
-#define LOG_LOCAL4 (20<<3) /* reserved for local use */
170
-#define LOG_LOCAL5 (21<<3) /* reserved for local use */
171
-#define LOG_LOCAL6 (22<<3) /* reserved for local use */
172
-#define LOG_LOCAL7 (23<<3) /* reserved for local use */
173
-#endif
174
-
175
-#ifdef HAVE_SYS_MMAN_H
176
-#include <sys/mman.h>
177
-#endif
178
-
179
-#ifdef HAVE_SYS_RESOURCE_H
180
-#include <sys/resource.h>
181
-#endif
182
-
183
-#ifdef HAVE_SYS_SOCKET_H
184
-#include <sys/socket.h>
185
-#endif
186
-
187
-#ifdef HAVE_SYS_WAIT_H
188
-#include <sys/wait.h>
189
-#endif
190
-
191
-#ifdef HAVE_SYS_UN_H
192
-#include <sys/un.h>
193
-#endif
194
-
195
-#ifdef HAVE_SPAWN_H
196
-#include <spawn.h>
197
-#endif
198
-
199
-#ifdef HAVE_NETINET_IN_H
200
-#include <netinet/in.h>
201
-#endif
202
-
203
-#ifdef HAVE_RESOLV_H
204
-#include <resolv.h>
205
-#endif
206
-
207
-#ifdef HAVE_NETDB_H
208
-#include <netdb.h>
209
-#endif
210
-
211
-#ifdef HAVE_SYS_PRCTL_H
212
-#include <sys/prctl.h>
213
-#endif
214
-
215
-#ifdef HAVE_SYS_STAT_H
216
-#include <sys/stat.h>
217
-#endif
218
-
219
-#ifdef HAVE_SYS_VFS_H
220
-#include <sys/vfs.h>
221
-#endif
222
-
223
-#ifdef HAVE_SYS_STATFS_H
224
-#include <sys/statfs.h>
225
-#endif
226
-
227
-#ifdef HAVE_LINUX_MAGIC_H
228
-#include <linux/magic.h>
229
-#endif
230
-
231
-#ifdef HAVE_SYS_MOUNT_H
232
-#include <sys/mount.h>
233
-#endif
234
-
235
-#ifdef HAVE_SYS_STATVFS_H
236
-#include <sys/statvfs.h>
237
-#endif
238
-
239
-// #1408
240
-#ifdef MAJOR_IN_MKDEV
241
-#include <sys/mkdev.h>
242
-#endif
243
-#ifdef MAJOR_IN_SYSMACROS
244
-#include <sys/sysmacros.h>
245
-#endif
246
-
247
-#include <math.h>
248
-#include <float.h>
249
-
250
-#if defined(HAVE_INTTYPES_H)
251
-#include <inttypes.h>
252
-#elif defined(HAVE_STDINT_H)
253
-#include <stdint.h>
254
-#endif
255
-
256
-#include <zlib.h>
257
-
258
-#ifdef HAVE_SYS_CAPABILITY_H
259
-#include <sys/capability.h>
260
-#endif
261
-
262
-
263
-#ifndef O_CLOEXEC
264
-#define O_CLOEXEC (0)
265
-#endif
266
-
267
-// ----------------------------------------------------------------------------
268
-// netdata common definitions
269
-
270
-#define _cleanup_(x) __attribute__((__cleanup__(x)))
271
-
272
-#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
273
-#define NEVERNULL __attribute__((returns_nonnull))
274
-#else
275
-#define NEVERNULL
276
-#endif
277
-
278
-#ifdef HAVE_FUNC_ATTRIBUTE_NOINLINE
279
-#define NOINLINE __attribute__((noinline))
280
-#else
281
-#define NOINLINE
282
-#endif
283
-
284
-#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
285
-#define MALLOCLIKE __attribute__((malloc))
286
-#else
287
-#define MALLOCLIKE
288
-#endif
289
-
290
-#if defined(HAVE_FUNC_ATTRIBUTE_FORMAT_GNU_PRINTF)
291
-#define PRINTFLIKE(f, a) __attribute__ ((format(gnu_printf, f, a)))
292
-#elif defined(HAVE_FUNC_ATTRIBUTE_FORMAT_PRINTF)
293
-#define PRINTFLIKE(f, a) __attribute__ ((format(printf, f, a)))
294
-#else
295
-#define PRINTFLIKE(f, a)
296
-#endif
297
-
298
-#ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
299
-#define NORETURN __attribute__ ((noreturn))
300
-#else
301
-#define NORETURN
302
-#endif
303
-
304
-#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
305
-#define WARNUNUSED __attribute__ ((warn_unused_result))
306
-#else
307
-#define WARNUNUSED
308
-#endif
309
-
19
#include "libjudy/judy-malloc.h"
20
312
-#define ABS(x) (((x) < 0)? (-(x)) : (x))
313
-#define MIN(a,b) (((a)<(b))?(a):(b))
314
-#define MAX(a,b) (((a)>(b))?(a):(b))
315
-#define SWAP(a, b) do { \
316
- typeof(a) _tmp = b; \
317
- b = a; \
318
- a = _tmp; \
319
-} while(0)
320
-
321
-#define GUID_LEN 36
322
-
323
-#define PIPE_READ 0
324
-#define PIPE_WRITE 1
325
-
326
-#include "linked-lists.h"
21
#include "storage-point.h"
22
#include "paths/paths.h"
23
@@ -389,31 +83,11 @@ extern volatile sig_atomic_t netdata_exit;
83
char *read_by_filename(const char *filename, long *file_size);
84
char *find_and_replace(const char *src, const char *find, const char *replace, const char *where);
85
392
-/* fix for alpine linux */
393
-#ifndef RUSAGE_THREAD
394
-#ifdef RUSAGE_CHILDREN
395
-#define RUSAGE_THREAD RUSAGE_CHILDREN
396
-#endif
397
-#endif
398
-
86
#define BITS_IN_A_KILOBIT 1000
87
#define KILOBITS_IN_A_MEGABIT 1000
88
402
-/* misc. */
403
-
404
-#define UNUSED(x) (void)(x)
405
-
406
-#ifdef __GNUC__
407
-#define UNUSED_FUNCTION(x) __attribute__((unused)) UNUSED_##x
408
-#else
409
-#define UNUSED_FUNCTION(x) UNUSED_##x
410
-#endif
411
-
89
#define error_report(x, args...) do { errno_clear(); netdata_log_error(x, ##args); } while(0)
90
414
-// Taken from linux kernel
415
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
416
-
91
#include "bitmap64.h"
92
93
#define COMPRESSION_MAX_CHUNK 0x4000
@@ -432,47 +106,55 @@ void netdata_cleanup_and_exit(int ret, const char *action, const char *action_re
106
107
extern const char *netdata_configured_host_prefix;
108
435
-#include "os/os.h"
109
+// safe includes before O/S specific functions
110
+#include "template-enum.h"
111
+#include "libjudy/src/Judy.h"
112
+#include "july/july.h"
113
437
-#define XXH_INLINE_ALL
438
-#include "xxhash.h"
114
+#include "string/string.h"
115
+#include "buffer/buffer.h"
116
117
#include "uuid/uuid.h"
441
-#include "template-enum.h"
442
-#include "http/http_access.h"
118
#include "http/content_type.h"
444
-#include "config/dyncfg.h"
445
-#include "libjudy/src/Judy.h"
446
-#include "july/july.h"
119
+#include "http/http_access.h"
120
+
121
+#include "inlined.h"
122
+#include "parsers/parsers.h"
123
+
124
#include "threads/threads.h"
448
-#include "buffer/buffer.h"
449
-#include "ringbuffer/ringbuffer.h"
450
-#include "c_rhash/c_rhash.h"
125
#include "locks/locks.h"
452
-#include "circular_buffer/circular_buffer.h"
126
+#include "completion/completion.h"
127
+#include "clocks/clocks.h"
128
+#include "simple_pattern/simple_pattern.h"
129
+#include "libnetdata/log/nd_log.h"
130
+
131
+#include "socket/security.h" // must be before windows.h
132
+
133
+// this may include windows.h
134
+#include "os/os.h"
135
+
136
+#include "socket/socket.h"
137
#include "avl/avl.h"
454
-#include "inlined.h"
138
+
139
#include "line_splitter/line_splitter.h"
456
-#include "clocks/clocks.h"
457
-#include "parsers/parsers.h"
140
+#include "c_rhash/c_rhash.h"
141
+#include "ringbuffer/ringbuffer.h"
142
+#include "circular_buffer/circular_buffer.h"
143
+#include "buffered_reader/buffered_reader.h"
144
#include "datetime/iso8601.h"
145
#include "datetime/rfc3339.h"
146
#include "datetime/rfc7231.h"
461
-#include "completion/completion.h"
462
-#include "libnetdata/log/nd_log.h"
147
+#include "sanitizers/sanitizers.h"
148
+
149
+#include "config/dyncfg.h"
150
+#include "config/appconfig.h"
151
#include "spawn_server/spawn_server.h"
152
#include "spawn_server/spawn_popen.h"
465
-#include "simple_pattern/simple_pattern.h"
466
-#include "socket/security.h"
467
-#include "socket/socket.h"
468
-#include "config/appconfig.h"
469
-#include "log/systemd-journal-helpers.h"
470
-#include "buffered_reader/buffered_reader.h"
153
#include "procfile/procfile.h"
472
-#include "string/string.h"
154
#include "dictionary/dictionary.h"
155
#include "dictionary/thread-cache.h"
475
-#include "sanitizers/sanitizers.h"
156
+
157
+#include "log/systemd-journal-helpers.h"
158
159
#if defined(HAVE_LIBBPF) && !defined(__cplusplus)
160
#include "ebpf/ebpf.h"
@@ -494,11 +176,6 @@ extern const char *netdata_configured_host_prefix;
176
#include "functions_evloop/functions_evloop.h"
177
#include "query_progress/progress.h"
178
497
-// BEWARE: this exists in alarm-notify.sh
498
-#define DEFAULT_CLOUD_BASE_URL "https://app.netdata.cloud"
499
-
500
-#define RRD_STORAGE_TIERS 5
501
-
179
static inline size_t struct_natural_alignment(size_t size) __attribute__((const));
180
181
#define STRUCT_NATURAL_ALIGNMENT (sizeof(uintptr_t) * 2)
@@ -644,6 +321,8 @@ bool rrdr_relative_window_to_absolute_query(time_t *after, time_t *before, time_
321
int netdata_base64_decode(unsigned char *out, const unsigned char *in, int in_len);
322
int netdata_base64_encode(unsigned char *encoded, const unsigned char *input, size_t input_size);
323
324
+// --------------------------------------------------------------------------------------------------------------------
325
+
326
static inline void freez_charp(char **p) {
327
freez(*p);
328
}
src/libnetdata/local-sockets/local-sockets.h
renamed
src/libnetdata/maps/system-groups.h
deleted
-68
@@ -1,68 +0,0 @@
1
-// SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-#ifndef NETDATA_SYSTEM_GROUPS_H
4
-#define NETDATA_SYSTEM_GROUPS_H
5
-
6
-#include "libnetdata/libnetdata.h"
7
-
8
-// --------------------------------------------------------------------------------------------------------------------
9
-// hashtable for caching uid to username mappings
10
-// key is the uid, value is username (STRING)
11
-
12
-#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
13
-#define SIMPLE_HASHTABLE_NAME _GROUPNAMES_CACHE
14
-#include "libnetdata/simple_hashtable.h"
15
-
16
-typedef struct groupnames_cache {
17
- SPINLOCK spinlock;
18
- SIMPLE_HASHTABLE_GROUPNAMES_CACHE ht;
19
-} GROUPNAMES_CACHE;
20
-
21
-static inline STRING *system_groupnames_cache_lookup_gid(GROUPNAMES_CACHE *gc, gid_t gid) {
22
- spinlock_lock(&gc->spinlock);
23
-
24
- XXH64_hash_t hash = XXH3_64bits(&gid, sizeof(gid));
25
- SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&gc->ht, hash, &gid, true);
26
- STRING *g = SIMPLE_HASHTABLE_SLOT_DATA(sl);
27
- if(!g) {
28
- char tmp[1024 + 1];
29
- struct group grp, *result = NULL;
30
-
31
- if (getgrgid_r(gid, &grp, tmp, sizeof(tmp), &result) != 0 || !result || !grp.gr_name || !(*grp.gr_name)) {
32
- char name[50];
33
- snprintfz(name, sizeof(name), "%u", gid);
34
- g = string_strdupz(name);
35
- }
36
- else
37
- g = string_strdupz(grp.gr_name);
38
-
39
- simple_hashtable_set_slot_GROUPNAMES_CACHE(&gc->ht, sl, hash, g);
40
- }
41
-
42
- g = string_dup(g);
43
- spinlock_unlock(&gc->spinlock);
44
- return g;
45
-}
46
-
47
-static inline GROUPNAMES_CACHE *system_groupnames_cache_init(void) {
48
- GROUPNAMES_CACHE *gc = callocz(1, sizeof(*gc));
49
- spinlock_init(&gc->spinlock);
50
- simple_hashtable_init_GROUPNAMES_CACHE(&gc->ht, 100);
51
- return gc;
52
-}
53
-
54
-static inline void system_groupnames_cache_destroy(GROUPNAMES_CACHE *gc) {
55
- spinlock_lock(&gc->spinlock);
56
-
57
- for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&gc->ht);
58
- sl;
59
- sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&gc->ht, sl)) {
60
- STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
61
- string_freez(u);
62
- }
63
-
64
- simple_hashtable_destroy_GROUPNAMES_CACHE(&gc->ht);
65
- freez(gc);
66
-}
67
-
68
-#endif //NETDATA_SYSTEM_GROUPS_H
src/libnetdata/maps/system-users.h
deleted
-68
@@ -1,68 +0,0 @@
1
-// SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-#ifndef NETDATA_SYSTEM_USERS_H
4
-#define NETDATA_SYSTEM_USERS_H
5
-
6
-#include "libnetdata/libnetdata.h"
7
-
8
-// --------------------------------------------------------------------------------------------------------------------
9
-// hashtable for caching uid to username mappings
10
-// key is the uid, value is username (STRING)
11
-
12
-#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
13
-#define SIMPLE_HASHTABLE_NAME _USERNAMES_CACHE
14
-#include "libnetdata/simple_hashtable.h"
15
-
16
-typedef struct usernames_cache {
17
- SPINLOCK spinlock;
18
- SIMPLE_HASHTABLE_USERNAMES_CACHE ht;
19
-} USERNAMES_CACHE;
20
-
21
-static inline STRING *system_usernames_cache_lookup_uid(USERNAMES_CACHE *uc, uid_t uid) {
22
- spinlock_lock(&uc->spinlock);
23
-
24
- XXH64_hash_t hash = XXH3_64bits(&uid, sizeof(uid));
25
- SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc->ht, hash, &uid, true);
26
- STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
27
- if(!u) {
28
- char tmp[1024 + 1];
29
- struct passwd pw, *result = NULL;
30
-
31
- if (getpwuid_r(uid, &pw, tmp, sizeof(tmp), &result) != 0 || !result || !pw.pw_name || !(*pw.pw_name)) {
32
- char name[50];
33
- snprintfz(name, sizeof(name), "%u", uid);
34
- u = string_strdupz(name);
35
- }
36
- else
37
- u = string_strdupz(pw.pw_name);
38
-
39
- simple_hashtable_set_slot_USERNAMES_CACHE(&uc->ht, sl, hash, u);
40
- }
41
-
42
- u = string_dup(u);
43
- spinlock_unlock(&uc->spinlock);
44
- return u;
45
-}
46
-
47
-static inline USERNAMES_CACHE *system_usernames_cache_init(void) {
48
- USERNAMES_CACHE *uc = callocz(1, sizeof(*uc));
49
- spinlock_init(&uc->spinlock);
50
- simple_hashtable_init_USERNAMES_CACHE(&uc->ht, 100);
51
- return uc;
52
-}
53
-
54
-static inline void system_usernames_cache_destroy(USERNAMES_CACHE *uc) {
55
- spinlock_lock(&uc->spinlock);
56
-
57
- for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc->ht);
58
- sl;
59
- sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc->ht, sl)) {
60
- STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
61
- string_freez(u);
62
- }
63
-
64
- simple_hashtable_destroy_USERNAMES_CACHE(&uc->ht);
65
- freez(uc);
66
-}
67
-
68
-#endif //NETDATA_SYSTEM_USERS_H
src/libnetdata/os/os.h
+8
@@ -23,8 +23,16 @@
23
#include "os-freebsd-wrappers.h"
24
#include "os-macos-wrappers.h"
25
#include "os-windows-wrappers.h"
26
+#include "system-maps/cached-uid-username.h"
27
+#include "system-maps/cached-gid-groupname.h"
28
+#include "system-maps/cache-host-users-and-groups.h"
29
+#include "system-maps/cached-sid-username.h"
30
#include "windows-perflib/perflib.h"
31
32
+// this includes windows.h to the whole of netdata
33
+// so various conflicts arise
34
+// #include "windows-wmi/windows-wmi.h"
35
+
36
// =====================================================================================================================
37
// common defs for Apple/FreeBSD/Linux
38
src/libnetdata/os/system-maps/cache-host-users-and-groups.c
new
+101
@@ -0,0 +1,101 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "libnetdata/libnetdata.h"
4
+
5
+static bool file_changed(const struct stat *statbuf __maybe_unused, struct timespec *last_modification_time __maybe_unused) {
6
+#if defined(OS_MACOS) || defined(OS_WINDOWS)
7
+ return false;
8
+#else
9
+ if(likely(statbuf->st_mtim.tv_sec == last_modification_time->tv_sec &&
10
+ statbuf->st_mtim.tv_nsec == last_modification_time->tv_nsec)) return false;
11
+
12
+ last_modification_time->tv_sec = statbuf->st_mtim.tv_sec;
13
+ last_modification_time->tv_nsec = statbuf->st_mtim.tv_nsec;
14
+
15
+ return true;
16
+#endif
17
+}
18
+
19
+static size_t read_passwd_or_group(const char *filename, struct timespec *last_modification_time, void (*cb)(uint32_t gid, const char *name, uint32_t version), uint32_t version) {
20
+ struct stat statbuf;
21
+ if(unlikely(stat(filename, &statbuf) || !file_changed(&statbuf, last_modification_time)))
22
+ return 0;
23
+
24
+ procfile *ff = procfile_open(filename, " :\t", PROCFILE_FLAG_DEFAULT);
25
+ if(unlikely(!ff)) return 0;
26
+
27
+ ff = procfile_readall(ff);
28
+ if(unlikely(!ff)) return 0;
29
+
30
+ size_t line, lines = procfile_lines(ff);
31
+
32
+ size_t added = 0;
33
+ for(line = 0; line < lines ;line++) {
34
+ size_t words = procfile_linewords(ff, line);
35
+ if(unlikely(words < 3)) continue;
36
+
37
+ char *name = procfile_lineword(ff, line, 0);
38
+ if(unlikely(!name || !*name)) continue;
39
+
40
+ char *id_string = procfile_lineword(ff, line, 2);
41
+ if(unlikely(!id_string || !*id_string)) continue;
42
+
43
+ uint32_t id = str2ull(id_string, NULL);
44
+
45
+ cb(id, name, version);
46
+ added++;
47
+ }
48
+
49
+ procfile_close(ff);
50
+ return added;
51
+}
52
+
53
+void update_cached_host_users(void) {
54
+ if(!netdata_configured_host_prefix || !*netdata_configured_host_prefix) return;
55
+
56
+ static SPINLOCK spinlock = NETDATA_SPINLOCK_INITIALIZER;
57
+ if(!spinlock_trylock(&spinlock)) return;
58
+
59
+ char filename[FILENAME_MAX];
60
+ static bool initialized = false;
61
+
62
+ size_t added = 0;
63
+
64
+ if(!initialized) {
65
+ initialized = true;
66
+ cached_usernames_init();
67
+ }
68
+
69
+ static uint32_t passwd_version = 0;
70
+ static struct timespec passwd_ts = { 0 };
71
+ snprintfz(filename, FILENAME_MAX, "%s/etc/passwd", netdata_configured_host_prefix);
72
+ added = read_passwd_or_group(filename, &passwd_ts, cached_username_populate_by_uid, ++passwd_version);
73
+ if(added) cached_usernames_delete_old_versions(passwd_version);
74
+
75
+ spinlock_unlock(&spinlock);
76
+}
77
+
78
+void update_cached_host_groups(void) {
79
+ if(!netdata_configured_host_prefix || !*netdata_configured_host_prefix) return;
80
+
81
+ static SPINLOCK spinlock = NETDATA_SPINLOCK_INITIALIZER;
82
+ if(!spinlock_trylock(&spinlock)) return;
83
+
84
+ char filename[FILENAME_MAX];
85
+ static bool initialized = false;
86
+
87
+ size_t added = 0;
88
+
89
+ if(!initialized) {
90
+ initialized = true;
91
+ cached_groupnames_init();
92
+ }
93
+
94
+ static uint32_t group_version = 0;
95
+ static struct timespec group_ts = { 0 };
96
+ snprintfz(filename, FILENAME_MAX, "%s/etc/group", netdata_configured_host_prefix);
97
+ added = read_passwd_or_group(filename, &group_ts, cached_groupname_populate_by_gid, ++group_version);
98
+ if(added) cached_groupnames_delete_old_versions(group_version);
99
+
100
+ spinlock_unlock(&spinlock);
101
+}
src/libnetdata/os/system-maps/cache-host-users-and-groups.h
new
+9
@@ -0,0 +1,9 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_CACHE_HOST_USERS_AND_GROUPS_H
4
+#define NETDATA_CACHE_HOST_USERS_AND_GROUPS_H
5
+
6
+void update_cached_host_users(void);
7
+void update_cached_host_groups(void);
8
+
9
+#endif //NETDATA_CACHE_HOST_USERS_AND_GROUPS_H
src/libnetdata/os/system-maps/cached-gid-groupname.c
new
+147
@@ -0,0 +1,147 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "cached-gid-groupname.h"
4
+
5
+// --------------------------------------------------------------------------------------------------------------------
6
+// hashtable for caching gid to groupname mappings
7
+// key is the gid, value is groupname (STRING)
8
+
9
+#define SIMPLE_HASHTABLE_KEY_TYPE gid_t
10
+#define SIMPLE_HASHTABLE_VALUE_TYPE CACHED_GROUPNAME
11
+#define SIMPLE_HASHTABLE_VALUE2KEY_FUNCTION cached_groupname_to_gid_ptr
12
+#define SIMPLE_HASHTABLE_COMPARE_KEYS_FUNCTION compar_gid_ptr
13
+#define SIMPLE_HASHTABLE_NAME _GROUPNAMES_CACHE
14
+#include "libnetdata/simple_hashtable.h"
15
+
16
+static struct {
17
+ bool initialized;
18
+ SPINLOCK spinlock;
19
+ SIMPLE_HASHTABLE_GROUPNAMES_CACHE ht;
20
+} uc = {
21
+ .spinlock = NETDATA_SPINLOCK_INITIALIZER,
22
+ .ht = { 0 },
23
+};
24
+
25
+static gid_t *cached_groupname_to_gid_ptr(CACHED_GROUPNAME *cu) {
26
+ return &cu->gid;
27
+}
28
+
29
+static bool compar_gid_ptr(gid_t *a, gid_t *b) {
30
+ return *a == *b;
31
+}
32
+
33
+void cached_groupname_populate_by_gid(gid_t gid, const char *groupname, uint32_t version) {
34
+ internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
35
+ if(!groupname || !*groupname) return;
36
+
37
+ spinlock_lock(&uc.spinlock);
38
+
39
+ XXH64_hash_t hash = XXH3_64bits(&gid, sizeof(gid));
40
+ SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&uc.ht, hash, &gid, true);
41
+ CACHED_GROUPNAME *cg = SIMPLE_HASHTABLE_SLOT_DATA(sl);
42
+ if(!cg || (cg->version && version > cg->version)) {
43
+ internal_fatal(cg && cg->gid != gid, "invalid gid matched from cache");
44
+
45
+ if(cg)
46
+ string_freez(cg->groupname);
47
+ else
48
+ cg = callocz(1, sizeof(*cg));
49
+
50
+ cg->version = version;
51
+ cg->gid = gid;
52
+ cg->groupname = string_strdupz(groupname);
53
+ simple_hashtable_set_slot_GROUPNAMES_CACHE(&uc.ht, sl, hash, cg);
54
+ }
55
+
56
+ spinlock_unlock(&uc.spinlock);
57
+}
58
+
59
+CACHED_GROUPNAME cached_groupname_get_by_gid(gid_t gid) {
60
+ internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
61
+
62
+ spinlock_lock(&uc.spinlock);
63
+
64
+ XXH64_hash_t hash = XXH3_64bits(&gid, sizeof(gid));
65
+ SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&uc.ht, hash, &gid, true);
66
+ CACHED_GROUPNAME *cg = SIMPLE_HASHTABLE_SLOT_DATA(sl);
67
+ if(!cg) {
68
+ cg = callocz(1, sizeof(*cg));
69
+
70
+ static char tmp[1024]; // we are inside a global spinlock - it is ok to be static
71
+ struct group gr, *result = NULL;
72
+
73
+ if (getgrgid_r(gid, &gr, tmp, sizeof(tmp), &result) != 0 || !result || !gr.gr_name || !(*gr.gr_name)) {
74
+ char name[UINT64_MAX_LENGTH];
75
+ print_uint64(name, gid);
76
+ cg->groupname = string_strdupz(name);
77
+ }
78
+ else
79
+ cg->groupname = string_strdupz(gr.gr_name);
80
+
81
+ cg->gid = gid;
82
+ simple_hashtable_set_slot_GROUPNAMES_CACHE(&uc.ht, sl, hash, cg);
83
+ }
84
+
85
+ internal_fatal(cg->gid != gid, "invalid gid matched from cache");
86
+
87
+ CACHED_GROUPNAME rc = {
88
+ .version = cg->version,
89
+ .gid = cg->gid,
90
+ .groupname = string_dup(cg->groupname),
91
+ };
92
+
93
+ spinlock_unlock(&uc.spinlock);
94
+ return rc;
95
+}
96
+
97
+void cached_groupname_release(CACHED_GROUPNAME cg) {
98
+ string_freez(cg.groupname);
99
+}
100
+
101
+void cached_groupnames_init(void) {
102
+ if(uc.initialized) return;
103
+ uc.initialized = true;
104
+
105
+ spinlock_init(&uc.spinlock);
106
+ simple_hashtable_init_GROUPNAMES_CACHE(&uc.ht, 100);
107
+}
108
+
109
+void cached_groupnames_destroy(void) {
110
+ if(!uc.initialized) return;
111
+
112
+ spinlock_lock(&uc.spinlock);
113
+
114
+ for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&uc.ht);
115
+ sl;
116
+ sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&uc.ht, sl)) {
117
+ CACHED_GROUPNAME *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
118
+ if(u) {
119
+ string_freez(u->groupname);
120
+ freez(u);
121
+ // simple_hashtable_del_slot_GROUPNAMES_CACHE(&uc.ht, sl);
122
+ }
123
+ }
124
+
125
+ simple_hashtable_destroy_GROUPNAMES_CACHE(&uc.ht);
126
+ uc.initialized = false;
127
+}
128
+
129
+void cached_groupnames_delete_old_versions(uint32_t version) {
130
+ if(!uc.initialized) return;
131
+
132
+ spinlock_lock(&uc.spinlock);
133
+
134
+ for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&uc.ht);
135
+ sl;
136
+ sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&uc.ht, sl)) {
137
+ CACHED_GROUPNAME *cg = SIMPLE_HASHTABLE_SLOT_DATA(sl);
138
+ if(cg && cg->version && cg->version < version) {
139
+ string_freez(cg->groupname);
140
+ freez(cg);
141
+ simple_hashtable_del_slot_GROUPNAMES_CACHE(&uc.ht, sl);
142
+ }
143
+ }
144
+
145
+ simple_hashtable_destroy_GROUPNAMES_CACHE(&uc.ht);
146
+ uc.initialized = false;
147
+}
src/libnetdata/os/system-maps/cached-gid-groupname.h
new
+24
@@ -0,0 +1,24 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_CACHED_UID_GROUPNAME_H
4
+#define NETDATA_CACHED_UID_GROUPNAME_H
5
+
6
+#include "libnetdata/libnetdata.h"
7
+
8
+struct netdata_string;
9
+
10
+typedef struct {
11
+ uint32_t version;
12
+ gid_t gid;
13
+ struct netdata_string *groupname;
14
+} CACHED_GROUPNAME;
15
+
16
+void cached_groupname_populate_by_gid(gid_t gid, const char *groupname, uint32_t version);
17
+CACHED_GROUPNAME cached_groupname_get_by_gid(gid_t gid);
18
+void cached_groupname_release(CACHED_GROUPNAME cg);
19
+void cached_groupnames_delete_old_versions(uint32_t version);
20
+
21
+void cached_groupnames_init(void);
22
+void cached_groupnames_destroy(void);
23
+
24
+#endif //NETDATA_CACHED_UID_GROUPNAME_H
src/libnetdata/os/system-maps/cached-sid-username.c
renamed
+65
-45
@@ -1,6 +1,10 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
3
-#include "windows-events-sid.h"
3
+#include "../../libnetdata.h"
4
+
5
+#if defined(OS_WINDOWS)
6
+#include "cached-sid-username.h"
7
+#include <windows.h>
8
#include <sddl.h>
9
10
typedef struct {
@@ -12,15 +16,10 @@ typedef struct {
16
// IMPORTANT:
17
// This is malloc'd ! You have to manually set fields to zero.
18
15
- const char *account;
16
- const char *domain;
17
- const char *full;
18
- const char *sid_str;
19
-
20
- uint32_t account_len;
21
- uint32_t domain_len;
22
- uint32_t full_len;
23
- uint32_t sid_str_len;
19
+ STRING *account;
20
+ STRING *domain;
21
+ STRING *full;
22
+ STRING *sid_str;
23
24
// this needs to be last, because of its variable size
25
SID_KEY key;
@@ -49,11 +48,25 @@ static inline bool sid_cache_compar(SID_KEY *a, SID_KEY *b) {
48
return a->len == b->len && memcmp(&a->sid, &b->sid, a->len) == 0;
49
}
50
52
-void sid_cache_init(void) {
51
+void cached_sid_username_init(void) {
52
simple_hashtable_init_SID(&sid_globals.hashtable, 100);
53
}
54
56
-static void lookup_user(SID_VALUE *sv) {
55
+static char *account2utf8(const wchar_t *user) {
56
+ static __thread char buffer[256];
57
+ if(utf16_to_utf8(buffer, sizeof(buffer), user, -1, NULL) == 0)
58
+ buffer[0] = '\0';
59
+ return buffer;
60
+}
61
+
62
+static char *domain2utf8(const wchar_t *domain) {
63
+ static __thread char buffer[256];
64
+ if(utf16_to_utf8(buffer, sizeof(buffer), domain, -1, NULL) == 0)
65
+ buffer[0] = '\0';
66
+ return buffer;
67
+}
68
+
69
+static void lookup_user_in_system(SID_VALUE *sv) {
70
static __thread wchar_t account_unicode[256];
71
static __thread wchar_t domain_unicode[256];
72
static __thread char tmp[512 + 2];
@@ -66,28 +79,21 @@ static void lookup_user(SID_VALUE *sv) {
79
const char *account = account2utf8(account_unicode);
80
const char *domain = domain2utf8(domain_unicode);
81
snprintfz(tmp, sizeof(tmp), "%s\\%s", domain, account);
69
- sv->domain = strdupz(domain); sv->domain_len = strlen(sv->domain);
70
- sv->account = strdupz(account); sv->account_len = strlen(sv->account);
71
- sv->full = strdupz(tmp); sv->full_len = strlen(sv->full);
82
+ sv->domain = string_strdupz(domain);
83
+ sv->account = string_strdupz(account);
84
+ sv->full = string_strdupz(tmp);
85
}
86
else {
87
sv->domain = NULL;
88
sv->account = NULL;
89
sv->full = NULL;
77
- sv->domain_len = 0;
78
- sv->account_len = 0;
79
- sv->full_len = 0;
90
}
91
92
wchar_t *sid_string = NULL;
83
- if (ConvertSidToStringSidW(sv->key.sid, &sid_string)) {
84
- sv->sid_str = strdupz(account2utf8(sid_string));
85
- sv->sid_str_len = strlen(sv->sid_str);
86
- }
87
- else {
93
+ if (ConvertSidToStringSidW(sv->key.sid, &sid_string))
94
+ sv->sid_str = string_strdupz(account2utf8(sid_string));
95
+ else
96
sv->sid_str = NULL;
89
- sv->sid_str_len = 0;
90
- }
97
}
98
99
static SID_VALUE *lookup_or_convert_user_id_to_name_lookup(PSID sid) {
@@ -112,7 +118,7 @@ static SID_VALUE *lookup_or_convert_user_id_to_name_lookup(PSID sid) {
118
found = mallocz(tmp_size);
119
memcpy(found, buf, tmp_size);
120
115
- lookup_user(found);
121
+ lookup_user_in_system(found);
122
123
// add it to the cache
124
spinlock_lock(&sid_globals.spinlock);
@@ -122,41 +128,44 @@ static SID_VALUE *lookup_or_convert_user_id_to_name_lookup(PSID sid) {
128
return found;
129
}
130
125
-bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str) {
131
+bool cached_sid_to_account_domain_sidstr(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str) {
132
SID_VALUE *found = lookup_or_convert_user_id_to_name_lookup(sid);
133
134
if(found) {
135
if (found->account) {
130
- txt_utf8_resize(dst_account, found->account_len + 1, false);
131
- memcpy(dst_account->data, found->account, found->account_len + 1);
132
- dst_account->used = found->account_len + 1;
136
+ txt_utf8_resize(dst_account, string_strlen(found->account) + 1, false);
137
+ memcpy(dst_account->data, string2str(found->account), string_strlen(found->account) + 1);
138
+ dst_account->used = string_strlen(found->account) + 1;
139
}
134
- else wevt_utf8_empty(dst_account);
140
+ else
141
+ txt_utf8_empty(dst_account);
142
143
if (found->domain) {
137
- txt_utf8_resize(dst_domain, found->domain_len + 1, false);
138
- memcpy(dst_domain->data, found->domain, found->domain_len + 1);
139
- dst_domain->used = found->domain_len + 1;
144
+ txt_utf8_resize(dst_domain, string_strlen(found->domain) + 1, false);
145
+ memcpy(dst_domain->data, string2str(found->domain), string_strlen(found->domain) + 1);
146
+ dst_domain->used = string_strlen(found->domain) + 1;
147
}
141
- else wevt_utf8_empty(dst_domain);
148
+ else
149
+ txt_utf8_empty(dst_domain);
150
151
if (found->sid_str) {
144
- txt_utf8_resize(dst_sid_str, found->sid_str_len + 1, false);
145
- memcpy(dst_sid_str->data, found->sid_str, found->sid_str_len + 1);
146
- dst_sid_str->used = found->sid_str_len + 1;
152
+ txt_utf8_resize(dst_sid_str, string_strlen(found->sid_str) + 1, false);
153
+ memcpy(dst_sid_str->data, string2str(found->sid_str), string_strlen(found->sid_str) + 1);
154
+ dst_sid_str->used = string_strlen(found->sid_str) + 1;
155
}
148
- else wevt_utf8_empty(dst_sid_str);
156
+ else
157
+ txt_utf8_empty(dst_sid_str);
158
159
return true;
160
}
161
153
- wevt_utf8_empty(dst_account);
154
- wevt_utf8_empty(dst_domain);
155
- wevt_utf8_empty(dst_sid_str);
162
+ txt_utf8_empty(dst_account);
163
+ txt_utf8_empty(dst_domain);
164
+ txt_utf8_empty(dst_sid_str);
165
return false;
166
}
167
159
-bool buffer_sid_to_sid_str_and_name(PSID sid, BUFFER *dst, const char *prefix) {
168
+bool cached_sid_to_buffer_append(PSID sid, BUFFER *dst, const char *prefix) {
169
SID_VALUE *found = lookup_or_convert_user_id_to_name_lookup(sid);
170
size_t added = 0;
171
@@ -165,17 +174,28 @@ bool buffer_sid_to_sid_str_and_name(PSID sid, BUFFER *dst, const char *prefix) {
174
if (prefix && *prefix)
175
buffer_strcat(dst, prefix);
176
168
- buffer_fast_strcat(dst, found->full, found->full_len);
177
+ buffer_fast_strcat(dst, string2str(found->full), string_strlen(found->full));
178
added++;
179
}
180
if (found->sid_str) {
181
if (prefix && *prefix)
182
buffer_strcat(dst, prefix);
183
175
- buffer_fast_strcat(dst, found->sid_str, found->sid_str_len);
184
+ buffer_fast_strcat(dst, string2str(found->sid_str), string_strlen(found->sid_str));
185
added++;
186
}
187
}
188
189
return added > 0;
190
}
191
+
192
+STRING *cached_sid_fullname_or_sid_str(PSID sid) {
193
+ SID_VALUE *found = lookup_or_convert_user_id_to_name_lookup(sid);
194
+ if(found) {
195
+ if(found->full) return string_dup(found->full);
196
+ return string_dup(found->sid_str);
197
+ }
198
+ return NULL;
199
+}
200
+
201
+#endif
\ No newline at end of file
src/libnetdata/os/system-maps/cached-sid-username.h
new
+17
@@ -0,0 +1,17 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_CACHED_SID_USERNAME_H
4
+#define NETDATA_CACHED_SID_USERNAME_H
5
+
6
+#include "../../libnetdata.h"
7
+
8
+#if defined(OS_WINDOWS)
9
+#include "../../string/utf8.h"
10
+
11
+bool cached_sid_to_account_domain_sidstr(void *sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
12
+bool cached_sid_to_buffer_append(void *sid, BUFFER *dst, const char *prefix);
13
+void cached_sid_username_init(void);
14
+STRING *cached_sid_fullname_or_sid_str(void *sid);
15
+#endif
16
+
17
+#endif //NETDATA_CACHED_SID_USERNAME_H
src/libnetdata/os/system-maps/cached-uid-username.c
new
+148
@@ -0,0 +1,148 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "cached-uid-username.h"
4
+
5
+// --------------------------------------------------------------------------------------------------------------------
6
+// hashtable for caching uid to username mappings
7
+// key is the uid, value is username (STRING)
8
+
9
+#define SIMPLE_HASHTABLE_KEY_TYPE uid_t
10
+#define SIMPLE_HASHTABLE_VALUE_TYPE CACHED_USERNAME
11
+#define SIMPLE_HASHTABLE_VALUE2KEY_FUNCTION cached_username_to_uid_ptr
12
+#define SIMPLE_HASHTABLE_COMPARE_KEYS_FUNCTION compar_uid_ptr
13
+#define SIMPLE_HASHTABLE_NAME _USERNAMES_CACHE
14
+#include "libnetdata/simple_hashtable.h"
15
+
16
+static struct {
17
+ uint32_t version;
18
+ bool initialized;
19
+ SPINLOCK spinlock;
20
+ SIMPLE_HASHTABLE_USERNAMES_CACHE ht;
21
+} uc = {
22
+ .spinlock = NETDATA_SPINLOCK_INITIALIZER,
23
+ .ht = { 0 },
24
+};
25
+
26
+static uid_t *cached_username_to_uid_ptr(CACHED_USERNAME *cu) {
27
+ return &cu->uid;
28
+}
29
+
30
+static bool compar_uid_ptr(uid_t *a, uid_t *b) {
31
+ return *a == *b;
32
+}
33
+
34
+void cached_username_populate_by_uid(uid_t uid, const char *username, uint32_t version) {
35
+ internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
36
+ if(!username || !*username) return;
37
+
38
+ spinlock_lock(&uc.spinlock);
39
+
40
+ XXH64_hash_t hash = XXH3_64bits(&uid, sizeof(uid));
41
+ SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc.ht, hash, &uid, true);
42
+ CACHED_USERNAME *cu = SIMPLE_HASHTABLE_SLOT_DATA(sl);
43
+ if(!cu || (cu->version && version > cu->version)) {
44
+ internal_fatal(cu && cu->uid != uid, "invalid uid matched from cache");
45
+
46
+ if(cu)
47
+ string_freez(cu->username);
48
+ else
49
+ cu = callocz(1, sizeof(*cu));
50
+
51
+ cu->version = version;
52
+ cu->uid = uid;
53
+ cu->username = string_strdupz(username);
54
+ simple_hashtable_set_slot_USERNAMES_CACHE(&uc.ht, sl, hash, cu);
55
+ }
56
+
57
+ spinlock_unlock(&uc.spinlock);
58
+}
59
+
60
+CACHED_USERNAME cached_username_get_by_uid(uid_t uid) {
61
+ internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
62
+
63
+ spinlock_lock(&uc.spinlock);
64
+
65
+ XXH64_hash_t hash = XXH3_64bits(&uid, sizeof(uid));
66
+ SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc.ht, hash, &uid, true);
67
+ CACHED_USERNAME *cu = SIMPLE_HASHTABLE_SLOT_DATA(sl);
68
+ if(!cu) {
69
+ cu = callocz(1, sizeof(*cu));
70
+
71
+ static char tmp[1024]; // we are inside a global spinlock - it is ok to be static
72
+ struct passwd pw, *result = NULL;
73
+
74
+ if (getpwuid_r(uid, &pw, tmp, sizeof(tmp), &result) != 0 || !result || !pw.pw_name || !(*pw.pw_name)) {
75
+ char name[UINT64_MAX_LENGTH];
76
+ print_uint64(name, uid);
77
+ cu->username = string_strdupz(name);
78
+ }
79
+ else
80
+ cu->username = string_strdupz(pw.pw_name);
81
+
82
+ cu->uid = uid;
83
+ simple_hashtable_set_slot_USERNAMES_CACHE(&uc.ht, sl, hash, cu);
84
+ }
85
+
86
+ internal_fatal(cu->uid != uid, "invalid uid matched from cache");
87
+
88
+ CACHED_USERNAME rc = {
89
+ .version = cu->version,
90
+ .uid = cu->uid,
91
+ .username = string_dup(cu->username),
92
+ };
93
+
94
+ spinlock_unlock(&uc.spinlock);
95
+ return rc;
96
+}
97
+
98
+void cached_username_release(CACHED_USERNAME cu) {
99
+ string_freez(cu.username);
100
+}
101
+
102
+void cached_usernames_init(void) {
103
+ if(uc.initialized) return;
104
+ uc.initialized = true;
105
+
106
+ spinlock_init(&uc.spinlock);
107
+ simple_hashtable_init_USERNAMES_CACHE(&uc.ht, 100);
108
+}
109
+
110
+void cached_usernames_destroy(void) {
111
+ if(!uc.initialized) return;
112
+
113
+ spinlock_lock(&uc.spinlock);
114
+
115
+ for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc.ht);
116
+ sl;
117
+ sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc.ht, sl)) {
118
+ CACHED_USERNAME *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
119
+ if(u) {
120
+ string_freez(u->username);
121
+ freez(u);
122
+ // simple_hashtable_del_slot_USERNAMES_CACHE(&uc.ht, sl);
123
+ }
124
+ }
125
+
126
+ simple_hashtable_destroy_USERNAMES_CACHE(&uc.ht);
127
+ uc.initialized = false;
128
+}
129
+
130
+void cached_usernames_delete_old_versions(uint32_t version) {
131
+ if(!uc.initialized) return;
132
+
133
+ spinlock_lock(&uc.spinlock);
134
+
135
+ for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc.ht);
136
+ sl;
137
+ sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc.ht, sl)) {
138
+ CACHED_USERNAME *cu = SIMPLE_HASHTABLE_SLOT_DATA(sl);
139
+ if(cu && cu->version && cu->version < version) {
140
+ string_freez(cu->username);
141
+ freez(cu);
142
+ simple_hashtable_del_slot_USERNAMES_CACHE(&uc.ht, sl);
143
+ }
144
+ }
145
+
146
+ simple_hashtable_destroy_USERNAMES_CACHE(&uc.ht);
147
+ uc.initialized = false;
148
+}
src/libnetdata/os/system-maps/cached-uid-username.h
new
+24
@@ -0,0 +1,24 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_CACHED_UID_USERNAME_H
4
+#define NETDATA_CACHED_UID_USERNAME_H
5
+
6
+#include "libnetdata/libnetdata.h"
7
+
8
+struct netdata_string;
9
+
10
+typedef struct {
11
+ uint32_t version;
12
+ uid_t uid;
13
+ struct netdata_string *username;
14
+} CACHED_USERNAME;
15
+
16
+void cached_username_populate_by_uid(uid_t uid, const char *username, uint32_t version);
17
+CACHED_USERNAME cached_username_get_by_uid(uid_t uid);
18
+void cached_username_release(CACHED_USERNAME cu);
19
+
20
+void cached_usernames_init(void);
21
+void cached_usernames_destroy(void);
22
+void cached_usernames_delete_old_versions(uint32_t version);
23
+
24
+#endif //NETDATA_CACHED_UID_USERNAME_H
src/libnetdata/os/system-maps/system-services.h
renamed
+1
-1
@@ -8,7 +8,7 @@
8
9
// --------------------------------------------------------------------------------------------------------------------
10
// hashtable for caching port and protocol to service name mappings
11
-// key is the combination of protocol and port packed into a uint64_t, value is service name (STRING)
11
+// key is the combination of protocol and port packed into an uint64_t, value is service name (STRING)
12
13
#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
14
#define SIMPLE_HASHTABLE_NAME _SERVICENAMES_CACHE
src/libnetdata/os/windows-perflib/perflib.c
+1
-1
@@ -398,7 +398,7 @@ static inline BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodeP
398
}
399
else {
400
tempBuffer = unicode;
401
- charsCopied = any_to_utf16(CodePage, unicode, _countof(unicode), start, (int)length);
401
+ charsCopied = any_to_utf16(CodePage, unicode, _countof(unicode), start, (int)length, NULL);
402
if(!charsCopied) return FALSE;
403
}
404
src/libnetdata/socket/security.h
+1
-21
@@ -1,5 +1,5 @@
1
#ifndef NETDATA_SECURITY_H
2
-# define NETDATA_SECURITY_H
2
+#define NETDATA_SECURITY_H
3
4
typedef enum __attribute__((packed)) {
5
NETDATA_SSL_STATE_NOT_SSL = 1, // This connection is not SSL
@@ -12,26 +12,6 @@ typedef enum __attribute__((packed)) {
12
#define NETDATA_SSL_STREAMING_SENDER_CTX 1
13
#define NETDATA_SSL_EXPORTING_CTX 2
14
15
-#define OPENSSL_VERSION_095 0x00905100L
16
-#define OPENSSL_VERSION_097 0x0907000L
17
-#define OPENSSL_VERSION_110 0x10100000L
18
-#define OPENSSL_VERSION_111 0x10101000L
19
-#define OPENSSL_VERSION_300 0x30000000L
20
-
21
-# include <openssl/ssl.h>
22
-# include <openssl/rand.h>
23
-# include <openssl/err.h>
24
-# include <openssl/evp.h>
25
-# include <openssl/pem.h>
26
-# if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097) && (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
27
-# include <openssl/conf.h>
28
-# endif
29
-
30
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_300
31
-#include <openssl/core_names.h>
32
-#include <openssl/decoder.h>
33
-#endif
34
-
15
typedef struct netdata_ssl {
16
SSL *conn; // SSL connection
17
NETDATA_SSL_STATE state; // The state for SSL connection
src/libnetdata/socket/socket.c
+10
-10
@@ -576,7 +576,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
576
char buffer2[10 + 1];
577
snprintfz(buffer2, 10, "%d", default_port);
578
579
- char *ip = buffer, *port = buffer2, *interface = "", *portconfig;
579
+ char *ip = buffer, *port = buffer2, *iface = "", *portconfig;
580
581
int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
582
const char *protocol_str = "tcp";
@@ -631,7 +631,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
631
if(*e == '%') {
632
*e = '\0';
633
e++;
634
- interface = e;
634
+ iface = e;
635
while(*e && *e != ':' && *e != '=') e++;
636
}
637
@@ -668,13 +668,13 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
668
}
669
670
uint32_t scope_id = 0;
671
- if(*interface) {
672
- scope_id = if_nametoindex(interface);
671
+ if(*iface) {
672
+ scope_id = if_nametoindex(iface);
673
if(!scope_id)
674
nd_log(NDLS_DAEMON, NDLP_ERR,
675
"LISTENER: Cannot find a network interface named '%s'. "
676
"Continuing with limiting the network interface",
677
- interface);
677
+ iface);
678
}
679
680
if(!*ip || *ip == '*' || !strcmp(ip, "any") || !strcmp(ip, "all"))
@@ -1035,7 +1035,7 @@ int connect_to_this(const char *definition, int default_port, struct timeval *ti
1035
char default_service[10 + 1];
1036
snprintfz(default_service, 10, "%d", default_port);
1037
1038
- char *host = buffer, *service = default_service, *interface = "";
1038
+ char *host = buffer, *service = default_service, *iface = "";
1039
int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
1040
uint32_t scope_id = 0;
1041
@@ -1074,7 +1074,7 @@ int connect_to_this(const char *definition, int default_port, struct timeval *ti
1074
if(*e == '%') {
1075
*e = '\0';
1076
e++;
1077
- interface = e;
1077
+ iface = e;
1078
while(*e && *e != ':') e++;
1079
}
1080
@@ -1092,12 +1092,12 @@ int connect_to_this(const char *definition, int default_port, struct timeval *ti
1092
return -1;
1093
}
1094
1095
- if(*interface) {
1096
- scope_id = if_nametoindex(interface);
1095
+ if(*iface) {
1096
+ scope_id = if_nametoindex(iface);
1097
if(!scope_id)
1098
nd_log(NDLS_DAEMON, NDLP_ERR,
1099
"Cannot find a network interface named '%s'. Continuing with limiting the network interface",
1100
- interface);
1100
+ iface);
1101
}
1102
1103
if(!*service)
src/libnetdata/string/utf8.c
+225
-7
@@ -13,9 +13,12 @@
13
* 3. Always return the number of wide characters written, including the null terminator
14
*/
15
16
-size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len) {
16
+size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len, bool *truncated) {
17
if(!src || src_len == 0) {
18
// invalid input
19
+ if(truncated)
20
+ *truncated = true;
21
+
22
if(dst && dst_size)
23
*dst = L'\0';
24
return 0;
@@ -23,6 +26,10 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
26
27
if(!dst || !dst_size) {
28
// the caller wants to know the buffer to allocate for the conversion
29
+
30
+ if(truncated)
31
+ *truncated = true;
32
+
33
int required = MultiByteToWideChar(CodePage, 0, src, src_len, NULL, 0);
34
if(required <= 0) return 0; // error in the conversion
35
@@ -34,6 +41,9 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
41
// do the conversion directly to the destination buffer
42
int rc = MultiByteToWideChar(CodePage, 0, src, src_len, dst, (int)dst_size);
43
if(rc <= 0) {
44
+ if(truncated)
45
+ *truncated = true;
46
+
47
// conversion failed, let's see why...
48
DWORD status = GetLastError();
49
if(status == ERROR_INSUFFICIENT_BUFFER) {
@@ -81,9 +91,17 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
91
92
size_t len = rc;
93
94
+ if(truncated)
95
+ *truncated = false;
96
+
97
if(len >= dst_size) {
85
- // truncate it to fit the null
86
- dst[dst_size - 1] = L'\0';
98
+ if(dst[dst_size - 1] != L'\0') {
99
+ if (truncated)
100
+ *truncated = true;
101
+
102
+ // Truncate it to fit the null terminator
103
+ dst[dst_size - 1] = L'\0';
104
+ }
105
return dst_size;
106
}
107
@@ -106,16 +124,24 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
124
* 3. Always return the number of bytes written, including the null terminator
125
*/
126
109
-size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len) {
127
+size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len, bool *truncated) {
128
if (!src || src_len == 0) {
129
// invalid input
130
+ if(truncated)
131
+ *truncated = true;
132
+
133
if(dst && dst_size)
113
- *dst = L'\0';
134
+ *dst = '\0';
135
+
136
return 0;
137
}
138
139
if (!dst || dst_size == 0) {
140
// The caller wants to know the buffer size required for the conversion
141
+
142
+ if(truncated)
143
+ *truncated = true;
144
+
145
int required = WideCharToMultiByte(CP_UTF8, 0, src, src_len, NULL, 0, NULL, NULL);
146
if (required <= 0) return 0; // error in the conversion
147
@@ -126,6 +152,9 @@ size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len
152
// Perform the conversion directly into the destination buffer
153
int rc = WideCharToMultiByte(CP_UTF8, 0, src, src_len, dst, (int)dst_size, NULL, NULL);
154
if (rc <= 0) {
155
+ if(truncated)
156
+ *truncated = true;
157
+
158
// Conversion failed, let's see why...
159
DWORD status = GetLastError();
160
if (status == ERROR_INSUFFICIENT_BUFFER) {
@@ -173,9 +202,17 @@ size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len
202
203
size_t len = rc;
204
205
+ if(truncated)
206
+ *truncated = false;
207
+
208
if (len >= dst_size) {
177
- // Truncate it to fit the null terminator
178
- dst[dst_size - 1] = '\0';
209
+ if(dst[dst_size - 1] != '\0') {
210
+ if (truncated)
211
+ *truncated = true;
212
+
213
+ // Truncate it to fit the null terminator
214
+ dst[dst_size - 1] = '\0';
215
+ }
216
return dst_size;
217
}
218
@@ -189,4 +226,185 @@ size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len
226
// The result is already null-terminated
227
return len;
228
}
229
+
230
+// --------------------------------------------------------------------------------------------------------------------
231
+
232
+size_t txt_compute_new_size(size_t old_size, size_t required_size) {
233
+ size_t size = (required_size % 2048 == 0) ? required_size : required_size + 2048;
234
+ size = (size / 2048) * 2048;
235
+
236
+ if(size < old_size * 2)
237
+ size = old_size * 2;
238
+
239
+ return size;
240
+}
241
+
242
+// --------------------------------------------------------------------------------------------------------------------
243
+// TXT_UTF8
244
+
245
+void txt_utf8_cleanup(TXT_UTF8 *dst) {
246
+ freez(dst->data);
247
+ dst->data = NULL;
248
+ dst->used = 0;
249
+}
250
+
251
+void txt_utf8_resize(TXT_UTF8 *dst, size_t required_size, bool keep) {
252
+ if(required_size <= dst->size)
253
+ return;
254
+
255
+ size_t new_size = txt_compute_new_size(dst->size, required_size);
256
+
257
+ if(keep && dst->data)
258
+ dst->data = reallocz(dst->data, new_size);
259
+ else {
260
+ txt_utf8_cleanup(dst);
261
+ dst->data = mallocz(new_size);
262
+ dst->used = 0;
263
+ }
264
+
265
+ dst->size = new_size;
266
+}
267
+
268
+void txt_utf8_empty(TXT_UTF8 *dst) {
269
+ txt_utf8_resize(dst, 1, false);
270
+ dst->data[0] = '\0';
271
+ dst->used = 1;
272
+}
273
+
274
+void txt_utf8_set(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
275
+ txt_utf8_resize(dst, dst->used + txt_len + 1, true);
276
+ memcpy(dst->data, txt, txt_len);
277
+ dst->used = txt_len + 1;
278
+ dst->data[dst->used - 1] = '\0';
279
+}
280
+
281
+void txt_utf8_append(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
282
+ if(dst->used <= 1) {
283
+ // the destination is empty
284
+ txt_utf8_set(dst, txt, txt_len);
285
+ }
286
+ else {
287
+ // there is something already in the buffer
288
+ txt_utf8_resize(dst, dst->used + txt_len, true);
289
+ memcpy(&dst->data[dst->used - 1], txt, txt_len);
290
+ dst->used += txt_len; // the null was already counted
291
+ dst->data[dst->used - 1] = '\0';
292
+ }
293
+}
294
+
295
+// --------------------------------------------------------------------------------------------------------------------
296
+// TXT_UTF16
297
+
298
+void txt_utf16_cleanup(TXT_UTF16 *dst) {
299
+ freez(dst->data);
300
+}
301
+
302
+void txt_utf16_resize(TXT_UTF16 *dst, size_t required_size, bool keep) {
303
+ if(required_size <= dst->size)
304
+ return;
305
+
306
+ size_t new_size = txt_compute_new_size(dst->size, required_size);
307
+
308
+ if (keep && dst->data) {
309
+ dst->data = reallocz(dst->data, new_size * sizeof(wchar_t));
310
+ } else {
311
+ txt_utf16_cleanup(dst);
312
+ dst->data = mallocz(new_size * sizeof(wchar_t));
313
+ dst->used = 0;
314
+ }
315
+
316
+ dst->size = new_size;
317
+}
318
+
319
+void txt_utf16_set(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len) {
320
+ txt_utf16_resize(dst, dst->used + txt_len + 1, true);
321
+ memcpy(dst->data, txt, txt_len * sizeof(wchar_t));
322
+ dst->used = txt_len + 1;
323
+ dst->data[dst->used - 1] = '\0';
324
+}
325
+
326
+void txt_utf16_append(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len) {
327
+ if(dst->used <= 1) {
328
+ // the destination is empty
329
+ txt_utf16_set(dst, txt, txt_len);
330
+ }
331
+ else {
332
+ // there is something already in the buffer
333
+ txt_utf16_resize(dst, dst->used + txt_len, true);
334
+ memcpy(&dst->data[dst->used - 1], txt, txt_len * sizeof(wchar_t));
335
+ dst->used += txt_len; // the null was already counted
336
+ dst->data[dst->used - 1] = '\0';
337
+ }
338
+}
339
+
340
+// --------------------------------------------------------------------------------------------------------------------
341
+
342
+bool wchar_to_txt_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len) {
343
+ if(!src || !src_len) {
344
+ txt_utf8_empty(dst);
345
+ return false;
346
+ }
347
+
348
+ if(!dst->data && !dst->size) {
349
+ size_t size = utf16_to_utf8(NULL, 0, src, src_len, NULL);
350
+ if(!size) {
351
+ txt_utf8_empty(dst);
352
+ return false;
353
+ }
354
+
355
+ // we +1 here to avoid entering the next condition below
356
+ txt_utf8_resize(dst, size, false);
357
+ }
358
+
359
+ bool truncated = false;
360
+ dst->used = utf16_to_utf8(dst->data, dst->size, src, src_len, &truncated);
361
+ if(truncated) {
362
+ // we need to resize
363
+ size_t needed = utf16_to_utf8(NULL, 0, src, src_len, NULL); // find the size needed
364
+ if(!needed) {
365
+ txt_utf8_empty(dst);
366
+ return false;
367
+ }
368
+
369
+ txt_utf8_resize(dst, needed, false);
370
+ dst->used = utf16_to_utf8(dst->data, dst->size, src, src_len, NULL);
371
+ }
372
+
373
+ // Make sure it is not zero padded at the end
374
+ while(dst->used >= 2 && dst->data[dst->used - 2] == 0)
375
+ dst->used--;
376
+
377
+ internal_fatal(strlen(dst->data) + 1 != dst->used,
378
+ "Wrong UTF8 string length");
379
+
380
+ return true;
381
+}
382
+
383
+bool txt_utf16_to_utf8(TXT_UTF8 *utf8, TXT_UTF16 *utf16) {
384
+ fatal_assert(utf8 && ((utf8->data && utf8->size) || (!utf8->data && !utf8->size)));
385
+ fatal_assert(utf16 && ((utf16->data && utf16->size) || (!utf16->data && !utf16->size)));
386
+
387
+ // pass the entire utf16 size, including the null terminator
388
+ // so that the resulting utf8 message will be null terminated too.
389
+ return wchar_to_txt_utf8(utf8, utf16->data, (int)utf16->used - 1);
390
+}
391
+
392
+char *utf16_to_utf8_strdupz(const wchar_t *src, size_t *dst_len) {
393
+ size_t size = utf16_to_utf8(NULL, 0, src, -1, NULL);
394
+ if (size) {
395
+ char *dst = mallocz(size);
396
+
397
+ size = utf16_to_utf8(dst, size, src, -1, NULL);
398
+ if(dst_len)
399
+ *dst_len = size - 1;
400
+
401
+ return dst;
402
+ }
403
+
404
+ if(dst_len)
405
+ *dst_len = 0;
406
+
407
+ return NULL;
408
+}
409
+
410
#endif
src/libnetdata/string/utf8.h
+57
-4
@@ -3,6 +3,8 @@
3
#ifndef NETDATA_STRING_UTF8_H
4
#define NETDATA_STRING_UTF8_H 1
5
6
+#include "../libnetdata.h"
7
+
8
#define IS_UTF8_BYTE(x) ((uint8_t)(x) & (uint8_t)0x80)
9
#define IS_UTF8_STARTBYTE(x) (IS_UTF8_BYTE(x) && ((uint8_t)(x) & (uint8_t)0x40))
10
@@ -15,16 +17,67 @@
17
// return an always null terminated wide string, truncate to given size if destination is not big enough,
18
// src_len can be -1 use all of it.
19
// returns zero on errors, > 0 otherwise (including the null, even if src is not null terminated).
18
-size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len);
20
+size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len, bool *truncated);
21
22
// always null terminated, truncated if it does not fit, src_len can be -1 to use all of it.
23
// returns zero on errors, > 0 otherwise (including the null, even if src is not null terminated).
22
-#define utf8_to_utf16(utf16, utf16_count, src, src_len) any_to_utf16(CP_UTF8, utf16, utf16_count, src, src_len)
24
+#define utf8_to_utf16(utf16, utf16_count, src, src_len) any_to_utf16(CP_UTF8, utf16, utf16_count, src, src_len, NULL)
25
26
// always null terminated, truncated if it does not fit, src_len can be -1 to use all of it.
27
// returns zero on errors, > 0 otherwise (including the null, even if src is not null terminated).
26
-size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len);
28
+size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len, bool *truncated);
29
28
-#endif
30
+// --------------------------------------------------------------------------------------------------------------------
31
+// TXT_UTF8
32
+
33
+typedef enum __attribute__((packed)) {
34
+ TXT_SOURCE_UNKNOWN = 0,
35
+ TXT_SOURCE_PROVIDER,
36
+ TXT_SOURCE_FIELD_CACHE,
37
+ TXT_SOURCE_EVENT_LOG,
38
+ TXT_SOURCE_HARDCODED,
39
+
40
+ // terminator
41
+ TXT_SOURCE_MAX,
42
+} TXT_SOURCE;
43
+
44
+typedef struct {
45
+ char *data;
46
+ uint32_t size; // the allocated size of data buffer
47
+ uint32_t used; // the used size of the data buffer (including null terminators, if any)
48
+ TXT_SOURCE src;
49
+} TXT_UTF8;
50
+
51
+void txt_utf8_append(TXT_UTF8 *dst, const char *txt, size_t txt_len);
52
+void txt_utf8_set(TXT_UTF8 *dst, const char *txt, size_t txt_len);
53
+void txt_utf8_empty(TXT_UTF8 *dst);
54
+void txt_utf8_resize(TXT_UTF8 *dst, size_t required_size, bool keep);
55
+void txt_utf8_cleanup(TXT_UTF8 *dst);
56
+
57
+// --------------------------------------------------------------------------------------------------------------------
58
+// TXT_UTF16
59
+
60
+typedef struct {
61
+ wchar_t *data;
62
+ uint32_t size; // the allocated size of data buffer
63
+ uint32_t used; // the used size of the data buffer (including null terminators, if any)
64
+} TXT_UTF16;
65
+
66
+void txt_utf16_cleanup(TXT_UTF16 *dst);
67
+void txt_utf16_resize(TXT_UTF16 *dst, size_t required_size, bool keep);
68
+void txt_utf16_set(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len);
69
+void txt_utf16_append(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len);
70
+
71
+// --------------------------------------------------------------------------------------------------------------------
72
+
73
+size_t txt_compute_new_size(size_t old_size, size_t required_size);
74
+
75
+bool txt_utf16_to_utf8(TXT_UTF8 *utf8, TXT_UTF16 *utf16);
76
+bool wchar_to_txt_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len);
77
+char *utf16_to_utf8_strdupz(const wchar_t *src, size_t *dst_len);
78
+
79
+// --------------------------------------------------------------------------------------------------------------------
80
+
81
+#endif // OS_WINDOWS
82
83
#endif /* NETDATA_STRING_UTF8_H */