diff options
Diffstat (limited to '')
31 files changed, 896 insertions, 0 deletions
diff --git a/src/libnetdata/os/adjtimex.c b/src/libnetdata/os/adjtimex.c new file mode 100644 index 000000000..b7a910095 --- /dev/null +++ b/src/libnetdata/os/adjtimex.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +int os_adjtimex(struct timex *buf __maybe_unused) { +#if defined(OS_MACOS) || defined(OS_FREEBSD) + return ntp_adjtime(buf); +#endif + +#if defined(OS_LINUX) + return adjtimex(buf); +#endif + + errno = ENOSYS; + return -1; +} diff --git a/src/libnetdata/os/adjtimex.h b/src/libnetdata/os/adjtimex.h new file mode 100644 index 000000000..d37ebf887 --- /dev/null +++ b/src/libnetdata/os/adjtimex.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_ADJTIMEX_H +#define NETDATA_ADJTIMEX_H + +#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_MACOS) +#include <sys/timex.h> +#endif + +struct timex; +int os_adjtimex(struct timex *buf); + +#endif //NETDATA_ADJTIMEX_H diff --git a/src/libnetdata/os/byteorder.h b/src/libnetdata/os/byteorder.h new file mode 100644 index 000000000..28fc9e663 --- /dev/null +++ b/src/libnetdata/os/byteorder.h @@ -0,0 +1,32 @@ +#ifndef LIBNETDATA_BYTE_ORDER_H +#define LIBNETDATA_BYTE_ORDER_H + +/** compatibility header for endian.h + * This is a simple compatibility shim to convert + * BSD/Linux endian macros to the Mac OS X equivalents. + * It is public domain. + * */ + +#ifndef __APPLE__ +#error "This header file (endian.h) is MacOS X specific.\n" +#endif /* __APPLE__ */ + + +#include <libkern/OSByteOrder.h> + +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) + +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) + +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) + +#endif /* LIBNETDATA_BYTE_ORDER_H */ diff --git a/src/libnetdata/os/get_pid_max.c b/src/libnetdata/os/get_pid_max.c new file mode 100644 index 000000000..45027961a --- /dev/null +++ b/src/libnetdata/os/get_pid_max.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +pid_t pid_max = 32768; +pid_t os_get_system_pid_max(void) { +#if defined(OS_MACOS) + + // As we currently do not know a solution to query pid_max from the os + // we use the number defined in bsd/sys/proc_internal.h in XNU sources + pid_max = 99999; + return pid_max; + +#elif defined(OS_FREEBSD) + + int32_t tmp_pid_max; + + if (unlikely(GETSYSCTL_BY_NAME("kern.pid_max", tmp_pid_max))) { + pid_max = 99999; + netdata_log_error("Assuming system's maximum pid is %d.", pid_max); + } else { + pid_max = tmp_pid_max; + } + + return pid_max; + +#elif defined(OS_LINUX) + + static char read = 0; + if(unlikely(read)) return pid_max; + read = 1; + + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", netdata_configured_host_prefix?netdata_configured_host_prefix:""); + + unsigned long long max = 0; + if(read_single_number_file(filename, &max) != 0) { + netdata_log_error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max); + return pid_max; + } + + if(!max) { + netdata_log_error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max); + return pid_max; + } + + pid_max = (pid_t) max; + return pid_max; + +#else + + // just a big default + + pid_max = 4194304; + return pid_max; + +#endif +} diff --git a/src/libnetdata/os/get_pid_max.h b/src/libnetdata/os/get_pid_max.h new file mode 100644 index 000000000..a6da0a4df --- /dev/null +++ b/src/libnetdata/os/get_pid_max.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_GET_PID_MAX_H +#define NETDATA_GET_PID_MAX_H + +#include <unistd.h> + +extern pid_t pid_max; +pid_t os_get_system_pid_max(void); + +#endif //NETDATA_GET_PID_MAX_H diff --git a/src/libnetdata/os/get_system_cpus.c b/src/libnetdata/os/get_system_cpus.c new file mode 100644 index 000000000..5a76d8aa5 --- /dev/null +++ b/src/libnetdata/os/get_system_cpus.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +#if defined(OS_WINDOWS) +#include <windows.h> +#endif + +#define CPUS_FOR_COLLECTORS 0 +#define CPUS_FOR_NETDATA 1 + +long os_get_system_cpus_cached(bool cache, bool for_netdata) { + static long processors[2] = { 0, 0 }; + + int index = for_netdata ? CPUS_FOR_NETDATA : CPUS_FOR_COLLECTORS; + + if(likely(cache && processors[index] > 0)) + return processors[index]; + +#if defined(OS_FREEBSD) || defined(OS_MACOS) +#if defined(OS_MACOS) +#define HW_CPU_NAME "hw.logicalcpu" +#else +#define HW_CPU_NAME "hw.ncpu" +#endif + + int32_t tmp_processors; + bool error = false; + + if (unlikely(GETSYSCTL_BY_NAME(HW_CPU_NAME, tmp_processors))) + error = true; + else + processors[index] = tmp_processors; + + if(processors[index] < 1) { + processors[index] = 1; + + if(error) + netdata_log_error("Assuming system has %ld processors.", processors[index]); + } + + return processors[index]; +#elif defined(OS_LINUX) + + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/proc/stat", + (!for_netdata && netdata_configured_host_prefix) ? netdata_configured_host_prefix : ""); + + procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); + if(!ff) { + processors[index] = 1; + netdata_log_error("Cannot open file '%s'. Assuming system has %ld processors.", filename, processors[index]); + return processors[index]; + } + + ff = procfile_readall(ff); + if(!ff) { + processors[index] = 1; + netdata_log_error("Cannot open file '%s'. Assuming system has %ld processors.", filename, processors[index]); + return processors[index]; + } + + long tmp_processors = 0; + unsigned int i; + for(i = 0; i < procfile_lines(ff); i++) { + if(!procfile_linewords(ff, i)) continue; + + if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) + tmp_processors++; + } + procfile_close(ff); + + processors[index] = --tmp_processors; + + if(processors[index] < 1) + processors[index] = 1; + + netdata_log_debug(D_SYSTEM, "System has %ld processors.", processors[index]); + return processors[index]; + +#elif defined(OS_WINDOWS) + + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + return (long) sysInfo.dwNumberOfProcessors; + +#else + + processors[index] = 1; + return processors[index]; + +#endif +} diff --git a/src/libnetdata/os/get_system_cpus.h b/src/libnetdata/os/get_system_cpus.h new file mode 100644 index 000000000..3c608df81 --- /dev/null +++ b/src/libnetdata/os/get_system_cpus.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_GET_SYSTEM_CPUS_H +#define NETDATA_GET_SYSTEM_CPUS_H + +#include "../libnetdata.h" + +long os_get_system_cpus_cached(bool cache, bool for_netdata); + +#endif //NETDATA_GET_SYSTEM_CPUS_H diff --git a/src/libnetdata/os/getgrouplist.c b/src/libnetdata/os/getgrouplist.c new file mode 100644 index 000000000..7f32faf33 --- /dev/null +++ b/src/libnetdata/os/getgrouplist.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +int os_getgrouplist(const char *username __maybe_unused, gid_t gid __maybe_unused, gid_t *supplementary_groups __maybe_unused, int *ngroups __maybe_unused) { +#if defined(OS_LINUX) || defined(OS_FREEBSD) + return getgrouplist(username, gid, supplementary_groups, ngroups); +#endif + +#if defined(OS_MACOS) + return getgrouplist(username, gid, (int *)supplementary_groups, ngroups); +#endif + + errno = ENOSYS; + return -1; +} diff --git a/src/libnetdata/os/getgrouplist.h b/src/libnetdata/os/getgrouplist.h new file mode 100644 index 000000000..336462553 --- /dev/null +++ b/src/libnetdata/os/getgrouplist.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_GETGROUPLIST_H +#define NETDATA_GETGROUPLIST_H + +#include <unistd.h> +int os_getgrouplist(const char *username, gid_t gid, gid_t *supplementary_groups, int *ngroups); + +#endif //NETDATA_GETGROUPLIST_H diff --git a/src/libnetdata/os/gettid.c b/src/libnetdata/os/gettid.c new file mode 100644 index 000000000..273c428f8 --- /dev/null +++ b/src/libnetdata/os/gettid.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +#if defined(OS_WINDOWS) +#include <windows.h> +#endif + +pid_t os_gettid(void) { +#if defined(HAVE_GETTID) + return gettid(); +#elif defined(HAVE_PTHREAD_GETTHREADID_NP) + return (pid_t)pthread_getthreadid_np(); +#elif defined(HAVE_PTHREAD_THREADID_NP) + uint64_t curthreadid; + pthread_threadid_np(NULL, &curthreadid); + return curthreadid; +#elif defined(OS_WINDOWS) + return (pid_t)GetCurrentThreadId(); +#elif defined(OS_LINUX) + return (pid_t)syscall(SYS_gettid); +#else + return (pid_t)pthread_self(); +#endif +} + +static __thread pid_t gettid_cached_tid = 0; +pid_t gettid_cached(void) { + if(unlikely(gettid_cached_tid == 0)) + gettid_cached_tid = os_gettid(); + + return gettid_cached_tid; +}
\ No newline at end of file diff --git a/src/libnetdata/os/gettid.h b/src/libnetdata/os/gettid.h new file mode 100644 index 000000000..f04d9c365 --- /dev/null +++ b/src/libnetdata/os/gettid.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_GETTID_H +#define NETDATA_GETTID_H + +#include <unistd.h> + +pid_t os_gettid(void); +pid_t gettid_cached(void); + +#endif //NETDATA_GETTID_H diff --git a/src/libnetdata/os/os-freebsd-wrappers.c b/src/libnetdata/os/os-freebsd-wrappers.c new file mode 100644 index 000000000..c3d1bda04 --- /dev/null +++ b/src/libnetdata/os/os-freebsd-wrappers.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +#if defined(OS_FREEBSD) + +int getsysctl_by_name(const char *name, void *ptr, size_t len) { + size_t nlen = len; + + if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) { + netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); + return 1; + } + if (unlikely(nlen != len)) { + netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); + return 1; + } + return 0; +} + +int getsysctl_simple(const char *name, int *mib, size_t miblen, void *ptr, size_t len) { + size_t nlen = len; + + if (unlikely(!mib[0])) + if (unlikely(getsysctl_mib(name, mib, miblen))) + return 1; + + if (unlikely(sysctl(mib, miblen, ptr, &nlen, NULL, 0) == -1)) { + netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); + return 1; + } + if (unlikely(nlen != len)) { + netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); + return 1; + } + + return 0; +} + +int getsysctl(const char *name, int *mib, size_t miblen, void *ptr, size_t *len) { + size_t nlen = *len; + + if (unlikely(!mib[0])) + if (unlikely(getsysctl_mib(name, mib, miblen))) + return 1; + + if (unlikely(sysctl(mib, miblen, ptr, len, NULL, 0) == -1)) { + netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); + return 1; + } + if (unlikely(ptr != NULL && nlen != *len)) { + netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)*len, (unsigned long)nlen); + return 1; + } + + return 0; +} + +int getsysctl_mib(const char *name, int *mib, size_t len) { + size_t nlen = len; + + if (unlikely(sysctlnametomib(name, mib, &nlen) == -1)) { + netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); + return 1; + } + if (unlikely(nlen != len)) { + netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); + return 1; + } + return 0; +} + +#endif diff --git a/src/libnetdata/os/os-freebsd-wrappers.h b/src/libnetdata/os/os-freebsd-wrappers.h new file mode 100644 index 000000000..6f54a2e9d --- /dev/null +++ b/src/libnetdata/os/os-freebsd-wrappers.h @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_OS_FREEBSD_WRAPPERS_H +#define NETDATA_OS_FREEBSD_WRAPPERS_H + +#include "../libnetdata.h" + +#if defined(OS_FREEBSD) +#include <sys/sysctl.h> + +#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var)) +int getsysctl_by_name(const char *name, void *ptr, size_t len); + +#define GETSYSCTL_MIB(name, mib) getsysctl_mib(name, mib, sizeof(mib)/sizeof(int)) + +int getsysctl_mib(const char *name, int *mib, size_t len); + +#define GETSYSCTL_SIMPLE(name, mib, var) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), &(var), sizeof(var)) +#define GETSYSCTL_WSIZE(name, mib, var, size) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), var, size) + +int getsysctl_simple(const char *name, int *mib, size_t miblen, void *ptr, size_t len); + +#define GETSYSCTL_SIZE(name, mib, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), NULL, &(size)) +#define GETSYSCTL(name, mib, var, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), &(var), &(size)) + +int getsysctl(const char *name, int *mib, size_t miblen, void *ptr, size_t *len); +#endif + +#endif //NETDATA_OS_FREEBSD_WRAPPERS_H diff --git a/src/libnetdata/os/os-macos-wrappers.c b/src/libnetdata/os/os-macos-wrappers.c new file mode 100644 index 000000000..b3d3ee4e6 --- /dev/null +++ b/src/libnetdata/os/os-macos-wrappers.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +#if defined(OS_MACOS) + +int getsysctl_by_name(const char *name, void *ptr, size_t len) { + size_t nlen = len; + + if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) { + netdata_log_error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno)); + return 1; + } + if (unlikely(nlen != len)) { + netdata_log_error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); + return 1; + } + return 0; +} + +#endif diff --git a/src/libnetdata/os/os-macos-wrappers.h b/src/libnetdata/os/os-macos-wrappers.h new file mode 100644 index 000000000..ec863c664 --- /dev/null +++ b/src/libnetdata/os/os-macos-wrappers.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_OS_MACOS_WRAPPERS_H +#define NETDATA_OS_MACOS_WRAPPERS_H + +#include "../libnetdata.h" + +#if defined(OS_MACOS) +#include <sys/sysctl.h> +#include "byteorder.h" + +#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var)) +int getsysctl_by_name(const char *name, void *ptr, size_t len); + +#endif + +#endif //NETDATA_OS_MACOS_WRAPPERS_H diff --git a/src/libnetdata/os/os.c b/src/libnetdata/os/os.c new file mode 100644 index 000000000..1caa25f85 --- /dev/null +++ b/src/libnetdata/os/os.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +// ---------------------------------------------------------------------------- +// system functions +// to retrieve settings of the system + +unsigned int system_hz; +void os_get_system_HZ(void) { + long ticks; + + if ((ticks = sysconf(_SC_CLK_TCK)) == -1) { + netdata_log_error("Cannot get system clock ticks"); + } + + system_hz = (unsigned int) ticks; +} + +static inline unsigned long cpuset_str2ul(char **s) { + unsigned long n = 0; + char c; + for(c = **s; c >= '0' && c <= '9' ; c = *(++*s)) { + n *= 10; + n += c - '0'; + } + return n; +} + +unsigned long os_read_cpuset_cpus(const char *filename, long system_cpus) { + static char *buf = NULL; + static size_t buf_size = 0; + + if(!buf) { + buf_size = 100U + 6 * system_cpus + 1; // taken from kernel/cgroup/cpuset.c + buf = mallocz(buf_size); + } + + int ret = read_txt_file(filename, buf, buf_size); + + if(!ret) { + char *s = buf; + unsigned long ncpus = 0; + + // parse the cpuset string and calculate the number of cpus the cgroup is allowed to use + while (*s) { + if (isspace((uint8_t)*s)) { + s++; + continue; + } + unsigned long n = cpuset_str2ul(&s); + ncpus++; + if(*s == ',') { + s++; + continue; + } + if(*s == '-') { + s++; + unsigned long m = cpuset_str2ul(&s); + ncpus += m - n; // calculate the number of cpus in the region + } + s++; + } + + if(!ncpus) + return 0; + + return ncpus; + } + + return 0; +} + +// ===================================================================================================================== +// os_type + +#if defined(OS_LINUX) +const char *os_type = "linux"; +#endif + +#if defined(OS_FREEBSD) +const char *os_type = "freebsd"; +#endif + +#if defined(OS_MACOS) +const char *os_type = "macos"; +#endif + +#if defined(OS_WINDOWS) +const char *os_type = "windows"; +#endif + diff --git a/src/libnetdata/os/os.h b/src/libnetdata/os/os.h new file mode 100644 index 000000000..350096159 --- /dev/null +++ b/src/libnetdata/os/os.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_OS_H +#define NETDATA_OS_H + +#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_MACOS) +#include <sys/syscall.h> +#endif + +#include "setresuid.h" +#include "setresgid.h" +#include "getgrouplist.h" +#include "adjtimex.h" +#include "gettid.h" +#include "waitid.h" +#include "get_pid_max.h" +#include "get_system_cpus.h" +#include "tinysleep.h" +#include "uuid_generate.h" +#include "setenv.h" +#include "os-freebsd-wrappers.h" +#include "os-macos-wrappers.h" + +// ===================================================================================================================== +// common defs for Apple/FreeBSD/Linux + +extern const char *os_type; + +#define os_get_system_cpus() os_get_system_cpus_cached(true, false) +#define os_get_system_cpus_uncached() os_get_system_cpus_cached(false, false) +long os_get_system_cpus_cached(bool cache, bool for_netdata); +unsigned long os_read_cpuset_cpus(const char *filename, long system_cpus); + +extern unsigned int system_hz; +void os_get_system_HZ(void); + +#endif //NETDATA_OS_H diff --git a/src/libnetdata/os/setenv.c b/src/libnetdata/os/setenv.c new file mode 100644 index 000000000..5aa4302b8 --- /dev/null +++ b/src/libnetdata/os/setenv.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "config.h"
+
+#ifndef HAVE_SETENV
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int os_setenv(const char *name, const char *value, int overwrite) {
+ char *env_var;
+ int result;
+
+ if (!overwrite) {
+ env_var = getenv(name);
+ if (env_var) return 0; // Already set
+ }
+
+ size_t len = strlen(name) + strlen(value) + 2; // +2 for '=' and '\0'
+ env_var = malloc(len);
+ if (!env_var) return -1; // Allocation failure
+ snprintf(env_var, len, "%s=%s", name, value);
+
+ result = putenv(env_var);
+ // free(env_var); // _putenv in Windows makes a copy of the string
+ return result;
+}
+
+#endif
diff --git a/src/libnetdata/os/setenv.h b/src/libnetdata/os/setenv.h new file mode 100644 index 000000000..3ed63714c --- /dev/null +++ b/src/libnetdata/os/setenv.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_SETENV_H
+#define NETDATA_SETENV_H
+
+#include "config.h"
+
+#ifndef HAVE_SETENV
+int os_setenv(const char *name, const char *value, int overwrite);
+#define setenv(name, value, overwrite) os_setenv(name, value, overwrite)
+#endif
+
+#endif //NETDATA_SETENV_H
diff --git a/src/libnetdata/os/setresgid.c b/src/libnetdata/os/setresgid.c new file mode 100644 index 000000000..e9f1b1860 --- /dev/null +++ b/src/libnetdata/os/setresgid.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +int os_setresgid(gid_t gid __maybe_unused, gid_t egid __maybe_unused, gid_t sgid __maybe_unused) { +#if defined(OS_LINUX) || defined(OS_FREEBSD) + return setresgid(gid, egid, sgid); +#endif + +#if defined(OS_MACOS) + return setregid(gid, egid); +#endif + + errno = ENOSYS; + return -1; +} diff --git a/src/libnetdata/os/setresgid.h b/src/libnetdata/os/setresgid.h new file mode 100644 index 000000000..fc6d41f95 --- /dev/null +++ b/src/libnetdata/os/setresgid.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_SETRESGID_H +#define NETDATA_SETRESGID_H + +#include <unistd.h> +int os_setresgid(gid_t gid, gid_t egid, gid_t sgid); + +#endif //NETDATA_SETRESGID_H diff --git a/src/libnetdata/os/setresuid.c b/src/libnetdata/os/setresuid.c new file mode 100644 index 000000000..081690291 --- /dev/null +++ b/src/libnetdata/os/setresuid.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +int os_setresuid(uid_t uid __maybe_unused, uid_t euid __maybe_unused, uid_t suid __maybe_unused) { +#if defined(OS_LINUX) || defined(OS_FREEBSD) + return setresuid(uid, euid, suid); +#endif + +#if defined(OS_MACOS) + return setreuid(uid, euid); +#endif + + errno = ENOSYS; + return -1; +} diff --git a/src/libnetdata/os/setresuid.h b/src/libnetdata/os/setresuid.h new file mode 100644 index 000000000..9f95d5d69 --- /dev/null +++ b/src/libnetdata/os/setresuid.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_SETRESUID_H +#define NETDATA_SETRESUID_H + +#include <unistd.h> + +int os_setresuid(uid_t uid, uid_t euid, uid_t suid); + +#endif //NETDATA_SETRESUID_H diff --git a/src/libnetdata/os/strndup.c b/src/libnetdata/os/strndup.c new file mode 100644 index 000000000..17210f124 --- /dev/null +++ b/src/libnetdata/os/strndup.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef HAVE_STRNDUP +#include "../libnetdata.h" + +static inline char *os_strndup( const char *s1, size_t n) +{ + char *copy= (char*)malloc( n+1 ); + memcpy( copy, s1, n ); + copy[n] = 0; + return copy; +}; +#endif diff --git a/src/libnetdata/os/strndup.h b/src/libnetdata/os/strndup.h new file mode 100644 index 000000000..9e51c8fd3 --- /dev/null +++ b/src/libnetdata/os/strndup.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef STRNDUP_H +#define STRNDUP_H + +#include "config.h" + +#ifndef HAVE_STRNDUP +#define strndup(s, n) os_strndup(s, n) +#endif + +#endif //STRNDUP_H diff --git a/src/libnetdata/os/tinysleep.c b/src/libnetdata/os/tinysleep.c new file mode 100644 index 000000000..f04cbdadc --- /dev/null +++ b/src/libnetdata/os/tinysleep.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +#ifdef OS_WINDOWS +#include <windows.h> + +void tinysleep(void) { + // Improve the system timer resolution to 1 ms + timeBeginPeriod(1); + + // Sleep for the desired duration + Sleep(1); + + // Reset the system timer resolution + timeEndPeriod(1); +} +#else +void tinysleep(void) { + static const struct timespec ns = { .tv_sec = 0, .tv_nsec = 1 }; + nanosleep(&ns, NULL); +} +#endif diff --git a/src/libnetdata/os/tinysleep.h b/src/libnetdata/os/tinysleep.h new file mode 100644 index 000000000..480575a3a --- /dev/null +++ b/src/libnetdata/os/tinysleep.h @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_TINYSLEEP_H
+#define NETDATA_TINYSLEEP_H
+
+void tinysleep(void);
+
+#endif //NETDATA_TINYSLEEP_H
diff --git a/src/libnetdata/os/uuid_generate.c b/src/libnetdata/os/uuid_generate.c new file mode 100644 index 000000000..4a7a9b6bc --- /dev/null +++ b/src/libnetdata/os/uuid_generate.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" +#undef uuid_generate +#undef uuid_generate_random +#undef uuid_generate_time + +#ifdef OS_WINDOWS +#include <windows.h> + +void os_uuid_generate(void *out) { + RPC_STATUS status = UuidCreate(out); + while (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { + tinysleep(); + status = UuidCreate(out); + } +} + +void os_uuid_generate_random(void *out) { + os_uuid_generate(out); +} + +void os_uuid_generate_time(void *out) { + os_uuid_generate(out); +} + +#else + +#if !defined(OS_MACOS) +#include <uuid.h> +#endif + +void os_uuid_generate(void *out) { + uuid_generate(out); +} + +void os_uuid_generate_random(void *out) { + uuid_generate_random(out); +} + +void os_uuid_generate_time(void *out) { + uuid_generate_time(out); +} + +#endif diff --git a/src/libnetdata/os/uuid_generate.h b/src/libnetdata/os/uuid_generate.h new file mode 100644 index 000000000..95f07c796 --- /dev/null +++ b/src/libnetdata/os/uuid_generate.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_UUID_GENERATE_H
+#define NETDATA_UUID_GENERATE_H
+
+void os_uuid_generate(void *out);
+void os_uuid_generate_random(void *out);
+void os_uuid_generate_time(void *out);
+
+#endif //NETDATA_UUID_GENERATE_H
diff --git a/src/libnetdata/os/waitid.c b/src/libnetdata/os/waitid.c new file mode 100644 index 000000000..b78d704ed --- /dev/null +++ b/src/libnetdata/os/waitid.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +int os_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) { +#if defined(HAVE_WAITID) + return waitid(idtype, id, infop, options); +#else + // emulate waitid() using waitpid() + + // a cache for WNOWAIT + static const struct pid_status empty = { 0, 0 }; + static __thread struct pid_status last = { 0, 0 }; // the cache + struct pid_status current = { 0, 0 }; + + // zero the infop structure + memset(infop, 0, sizeof(*infop)); + + // from the infop structure we use only 3 fields: + // - si_pid + // - si_code + // - si_status + // so, we update only these 3 + + switch(idtype) { + case P_ALL: + current.pid = waitpid((pid_t)-1, ¤t.status, options); + if(options & WNOWAIT) + last = current; + else + last = empty; + break; + + case P_PID: + if(last.pid == (pid_t)id) { + current = last; + last = empty; + } + else + current.pid = waitpid((pid_t)id, ¤t.status, options); + + break; + + default: + errno = ENOSYS; + return -1; + } + + if (current.pid > 0) { + if (WIFEXITED(current.status)) { + infop->si_code = CLD_EXITED; + infop->si_status = WEXITSTATUS(current.status); + } else if (WIFSIGNALED(current.status)) { + infop->si_code = WTERMSIG(current.status) == SIGABRT ? CLD_DUMPED : CLD_KILLED; + infop->si_status = WTERMSIG(current.status); + } else if (WIFSTOPPED(current.status)) { + infop->si_code = CLD_STOPPED; + infop->si_status = WSTOPSIG(current.status); + } else if (WIFCONTINUED(current.status)) { + infop->si_code = CLD_CONTINUED; + infop->si_status = SIGCONT; + } + infop->si_pid = current.pid; + return 0; + } else if (current.pid == 0) { + // No change in state, depends on WNOHANG + return 0; + } + + return -1; +#endif +} diff --git a/src/libnetdata/os/waitid.h b/src/libnetdata/os/waitid.h new file mode 100644 index 000000000..9e1fd6be7 --- /dev/null +++ b/src/libnetdata/os/waitid.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WAITID_H +#define NETDATA_WAITID_H + +#include "config.h" +#include <sys/types.h> +#include <signal.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifndef WNOWAIT +#define WNOWAIT 0x01000000 +#endif + +#ifndef WEXITED +#define WEXITED 4 +#endif + +#if !defined(HAVE_WAITID) +typedef enum +{ + P_ALL, /* Wait for any child. */ + P_PID, /* Wait for specified process. */ + P_PGID, /* Wait for members of process group. */ + P_PIDFD, /* Wait for the child referred by the PID file descriptor. */ +} idtype_t; + +struct pid_status { + pid_t pid; + int status; +}; + +#if defined(OS_WINDOWS) && !defined(__CYGWIN__) +typedef uint32_t id_t; +typedef struct { + int si_code; /* Signal code. */ + int si_status; /* Exit value or signal. */ + pid_t si_pid; /* Sending process ID. */ +} siginfo_t; +#endif +#endif + +int os_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); + +#endif //NETDATA_WAITID_H |