aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2020-03-28 21:04:54 +0000
committerBen Hutchings <ben@decadent.org.uk>2020-03-28 21:42:12 +0000
commit89742f0fc6f93a4a748ab783856a9d441511b808 (patch)
tree8a7f1a38c3acd7c9f390f9693a7b0446c8046b0b
parenta99e81cedacbfaed18e580455969667f2320de5e (diff)
downloadklibc-89742f0fc6f93a4a748ab783856a9d441511b808.tar.gz
[klibc] Implement stpcpy() and stpncpy()
These functions are included in POSIX.1-2008, and current upstream dash now uses stpncpy() without providing a fallback definition. Also add tests for these functions. Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--usr/include/string.h2
-rw-r--r--usr/klibc/Kbuild1
-rw-r--r--usr/klibc/stpcpy.c19
-rw-r--r--usr/klibc/stpncpy.c23
-rw-r--r--usr/klibc/tests/Kbuild1
-rw-r--r--usr/klibc/tests/stpcpy.c75
6 files changed, 121 insertions, 0 deletions
diff --git a/usr/include/string.h b/usr/include/string.h
index 0c8c0461555bd..86d5b6c6b289f 100644
--- a/usr/include/string.h
+++ b/usr/include/string.h
@@ -45,5 +45,7 @@ __extern size_t strspn(const char *, const char *);
__extern char *strstr(const char *, const char *);
__extern char *strtok(char *, const char *);
__extern char *strtok_r(char *, const char *, char **);
+__extern char *stpcpy(char *, const char *);
+__extern char *stpncpy(char *, const char *, size_t);
#endif /* _STRING_H */
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index 19ccfbec3f535..b966e306ee1c0 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -46,6 +46,7 @@ klib-y += vsnprintf.o snprintf.o vsprintf.o sprintf.o \
strstr.o strncmp.o strncpy.o strrchr.o \
strxspn.o strspn.o strcspn.o strpbrk.o strsep.o strtok.o \
strtok_r.o \
+ stpcpy.o stpncpy.o \
fnmatch.o \
gethostname.o getdomainname.o getcwd.o \
seteuid.o setegid.o \
diff --git a/usr/klibc/stpcpy.c b/usr/klibc/stpcpy.c
new file mode 100644
index 0000000000000..c5fc607dca849
--- /dev/null
+++ b/usr/klibc/stpcpy.c
@@ -0,0 +1,19 @@
+/*
+ * stpcpy.c
+ */
+
+#include <string.h>
+
+char *stpcpy(char *dst, const char *src)
+{
+ char ch;
+
+ for (;;) {
+ *dst = ch = *src++;
+ if (!ch)
+ break;
+ dst++;
+ }
+
+ return dst;
+}
diff --git a/usr/klibc/stpncpy.c b/usr/klibc/stpncpy.c
new file mode 100644
index 0000000000000..f28992ab8f5cf
--- /dev/null
+++ b/usr/klibc/stpncpy.c
@@ -0,0 +1,23 @@
+/*
+ * stpncpy.c
+ */
+
+#include <string.h>
+
+char *stpncpy(char *dst, const char *src, size_t n)
+{
+ char *end;
+ char ch;
+
+ while (n) {
+ ch = *src++;
+ if (!ch)
+ break;
+ n--;
+ *dst++ = ch;
+ }
+
+ end = dst;
+ memset(dst, 0, n);
+ return end;
+}
diff --git a/usr/klibc/tests/Kbuild b/usr/klibc/tests/Kbuild
index c7ca531f726db..50e381602e36b 100644
--- a/usr/klibc/tests/Kbuild
+++ b/usr/klibc/tests/Kbuild
@@ -42,6 +42,7 @@ sscanf.shared-y := sscanf.o
stat.shared-y := stat.o
statfs.shared-y := statfs.o
stdio.shared-y := stdio.o
+stpcpy.shared-y := stpcpy.o
strlcpycat.shared-y := strlcpycat.o
strtoimax.shared-y := strtoimax.o
strtotime.shared-y := strtotime.o
diff --git a/usr/klibc/tests/stpcpy.c b/usr/klibc/tests/stpcpy.c
new file mode 100644
index 0000000000000..4340f61a8e090
--- /dev/null
+++ b/usr/klibc/tests/stpcpy.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(void)
+{
+ char temp[10];
+#define clear_temp() strcpy(temp, "XXXXXXXXX")
+ char *end;
+
+ printf("stpcpy:\n");
+
+ clear_temp();
+ end = stpcpy(temp, "123");
+ printf("'%s'len:%zu strlen:%zu\n", temp, end - temp, strlen(temp));
+ if (end != temp + 3 || memcmp(temp, "123\0XXXXX", 10))
+ goto error;
+
+ clear_temp();
+ end = stpcpy(temp, "");
+ printf("'%s'len:%zu strlen:%zu\n", temp, end - temp, strlen(temp));
+ if (end != temp || memcmp(temp, "\0XXXXXXXX", 10))
+ goto error;
+
+ clear_temp();
+ end = stpcpy(temp, "1234567");
+ printf("'%s'len:%zu strlen:%zu\n", temp, end - temp, strlen(temp));
+ if (end != temp + 7 || memcmp(temp, "1234567\0X", 10))
+ goto error;
+
+ printf("\n");
+ printf("stpncpy:\n");
+
+ clear_temp();
+ end = stpncpy(temp, "123", 8);
+ printf("'%s'len:%zu strnlen:%zu\n", temp, end - temp, strnlen(temp, 8));
+ if (end != temp + 3 || memcmp(temp, "123\0\0\0\0\0X", 10))
+ goto error;
+
+ clear_temp();
+ end = stpncpy(temp, "", 8);
+ printf("'%s'len:%zu strnlen:%zu\n", temp, end - temp, strnlen(temp, 8));
+ if (end != temp || memcmp(temp, "\0\0\0\0\0\0\0\0X", 10))
+ goto error;
+
+ clear_temp();
+ end = stpncpy(temp, "1234567890", 8);
+ printf("'%s'len:%zu strnlen:%zu\n", temp, end - temp, strnlen(temp, 8));
+ if (end != temp + 8 || memcmp(temp, "12345678X", 10))
+ goto error;
+
+ clear_temp();
+ end = stpncpy(temp, "123", 5);
+ printf("'%s'len:%zu strnlen:%zu\n", temp, end - temp, strnlen(temp, 5));
+ if (end != temp + 3 || memcmp(temp, "123\0\0XXXX", 10))
+ goto error;
+
+ clear_temp();
+ end = stpncpy(temp, "123", 1);
+ printf("'%s'len:%zu strnlen:%zu\n", temp, end - temp, strnlen(temp, 1));
+ if (end != temp + 1 || memcmp(temp, "1XXXXXXXX", 10))
+ goto error;
+
+ clear_temp();
+ end = stpncpy(temp, "123", 0);
+ printf("'%s'len:%zu strnlen:%zu\n", temp, end - temp, strnlen(temp, 0));
+ if (end != temp || memcmp(temp, "XXXXXXXXX", 10))
+ goto error;
+
+ exit(0);
+error:
+ printf("unexpected result\n");
+ exit(1);
+}