summary refs log tree commit diff
path: root/shared/systemd/src/basic/alloc-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/systemd/src/basic/alloc-util.c')
-rw-r--r--shared/systemd/src/basic/alloc-util.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/shared/systemd/src/basic/alloc-util.c b/shared/systemd/src/basic/alloc-util.c
new file mode 100644
index 00000000..d23624d8
--- /dev/null
+++ b/shared/systemd/src/basic/alloc-util.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "nm-sd-adapt-shared.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "alloc-util.h"
+#include "macro.h"
+#include "util.h"
+
+void* memdup(const void *p, size_t l) {
+        void *ret;
+
+        assert(l == 0 || p);
+
+        ret = malloc(l ?: 1);
+        if (!ret)
+                return NULL;
+
+        memcpy(ret, p, l);
+        return ret;
+}
+
+void* memdup_suffix0(const void *p, size_t l) {
+        void *ret;
+
+        assert(l == 0 || p);
+
+        /* The same as memdup() but place a safety NUL byte after the allocated memory */
+
+        ret = malloc(l + 1);
+        if (!ret)
+                return NULL;
+
+        *((uint8_t*) mempcpy(ret, p, l)) = 0;
+        return ret;
+}
+
+void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
+        size_t a, newalloc;
+        void *q;
+
+        assert(p);
+        assert(allocated);
+
+        if (*allocated >= need)
+                return *p;
+
+        newalloc = MAX(need * 2, 64u / size);
+        a = newalloc * size;
+
+        /* check for overflows */
+        if (a < size * need)
+                return NULL;
+
+        q = realloc(*p, a);
+        if (!q)
+                return NULL;
+
+        *p = q;
+        *allocated = newalloc;
+        return q;
+}
+
+void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
+        size_t prev;
+        uint8_t *q;
+
+        assert(p);
+        assert(allocated);
+
+        prev = *allocated;
+
+        q = greedy_realloc(p, allocated, need, size);
+        if (!q)
+                return NULL;
+
+        if (*allocated > prev)
+                memzero(q + prev * size, (*allocated - prev) * size);
+
+        return q;
+}