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:51:42 +0200
committerMichael Biebl <biebl@debian.org>2019-07-31 10:51:42 +0200
commit2e5fa45ddfbb5cffa1e78221f1cea706e2f298af (patch)
tree86f69d36c56de3074280456eddc854a780b8e04b /shared/systemd/src/basic/strxcpyx.c
parent85563b7fc7ec2cd21e38debb9b28db342e2e8e7c (diff)
New upstream version 1.19.90 upstream/1.19.90
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;
+}