about summary refs log tree commit diff
path: root/shared/systemd/src/basic/strxcpyx.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-07-31 10:52:41 +0200
committerMichael Biebl <biebl@debian.org>2019-07-31 10:52:41 +0200
commit3a99ba5fd066fe42bd5461360a7411766496619c (patch)
treeb43863fbe867d7b0f9f9032fd40664c521c88fcb /shared/systemd/src/basic/strxcpyx.c
parent13cfe714153013158bdf3e74ab58ab713a04223c (diff)
parent2e5fa45ddfbb5cffa1e78221f1cea706e2f298af (diff)
Update upstream source from tag 'upstream/1.19.90'
Update to upstream version '1.19.90'
with Debian dir 6d1a5b9902866beee1365904d425141b5d4c944c
Diffstat (limited to 'shared/systemd/src/basic/strxcpyx.c')
-rw-r--r--shared/systemd/src/basic/strxcpyx.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/shared/systemd/src/basic/strxcpyx.c b/shared/systemd/src/basic/strxcpyx.c
new file mode 100644
index 00000000..301e6899
--- /dev/null
+++ b/shared/systemd/src/basic/strxcpyx.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+/*
+ * Concatenates/copies strings. In any case, terminates in all cases
+ * with '\0' and moves the @dest pointer forward to the added '\0'.
+ * Returns the remaining size, and 0 if the string was truncated.
+ *
+ * Due to the intended usage, these helpers silently noop invocations
+ * having zero size.  This is technically an exception to the above
+ * statement "terminates in all cases".  It's unexpected for such calls to
+ * occur outside of a loop where this is the preferred behavior.
+ */
+
+#include "nm-sd-adapt-shared.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "strxcpyx.h"
+
+size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) {
+        assert(dest);
+        assert(src);
+
+        if (size == 0)
+                return 0;
+
+        if (len >= size) {
+                if (size > 1)
+                        *dest = mempcpy(*dest, src, size-1);
+                size = 0;
+        } else if (len > 0) {
+                *dest = mempcpy(*dest, src, len);
+                size -= len;
+        }
+
+        *dest[0] = '\0';
+        return size;
+}
+
+size_t strpcpy(char **dest, size_t size, const char *src) {
+        assert(dest);
+        assert(src);
+
+        return strnpcpy(dest, size, src, strlen(src));
+}
+
+size_t strpcpyf(char **dest, size_t size, const char *src, ...) {
+        va_list va;
+        int i;
+
+        assert(dest);
+        assert(src);
+
+        if (size == 0)
+                return 0;
+
+        va_start(va, src);
+        i = vsnprintf(*dest, size, src, va);
+        if (i < (int)size) {
+                *dest += i;
+                size -= i;
+        } else
+                size = 0;
+        va_end(va);
+        return size;
+}
+
+size_t strpcpyl(char **dest, size_t size, const char *src, ...) {
+        va_list va;
+
+        assert(dest);
+        assert(src);
+
+        va_start(va, src);
+        do {
+                size = strpcpy(dest, size, src);
+                src = va_arg(va, char *);
+        } while (src);
+        va_end(va);
+        return size;
+}
+
+size_t strnscpy(char *dest, size_t size, const char *src, size_t len) {
+        char *s;
+
+        assert(dest);
+        assert(src);
+
+        s = dest;
+        return strnpcpy(&s, size, src, len);
+}
+
+size_t strscpy(char *dest, size_t size, const char *src) {
+        assert(dest);
+        assert(src);
+
+        return strnscpy(dest, size, src, strlen(src));
+}
+
+size_t strscpyl(char *dest, size_t size, const char *src, ...) {
+        va_list va;
+        char *s;
+
+        assert(dest);
+        assert(src);
+
+        va_start(va, src);
+        s = dest;
+        do {
+                size = strpcpy(&s, size, src);
+                src = va_arg(va, char *);
+        } while (src);
+        va_end(va);
+
+        return size;
+}