lib/ucs2_string: Add UCS-2 strscpy function
authorMaximilian Luz <luzmaximilian@gmail.com>
Sun, 27 Aug 2023 21:14:04 +0000 (23:14 +0200)
committerBjorn Andersson <andersson@kernel.org>
Wed, 13 Sep 2023 17:18:42 +0000 (10:18 -0700)
Add a ucs2_strscpy() function for UCS-2 strings. The behavior is
equivalent to the standard strscpy() function, just for 16-bit character
UCS-2 strings.

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20230827211408.689076-2-luzmaximilian@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
include/linux/ucs2_string.h
lib/ucs2_string.c

index cf3ada3e820ed21e794f1f5ab911706e62c068a2..c499ae809c7d991cca9e9ed652167f4d89e8e700 100644 (file)
@@ -10,6 +10,7 @@ typedef u16 ucs2_char_t;
 unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength);
 unsigned long ucs2_strlen(const ucs2_char_t *s);
 unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
+ssize_t ucs2_strscpy(ucs2_char_t *dst, const ucs2_char_t *src, size_t count);
 int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
 
 unsigned long ucs2_utf8size(const ucs2_char_t *src);
index 0a559a42359b82182c37d5f9f1520e01cbe52f4f..9308bcfb2ad50c71b11f502002f68a347d660346 100644 (file)
@@ -32,6 +32,58 @@ ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
 }
 EXPORT_SYMBOL(ucs2_strsize);
 
+/**
+ * ucs2_strscpy() - Copy a UCS2 string into a sized buffer.
+ *
+ * @dst: Pointer to the destination buffer where to copy the string to.
+ * @src: Pointer to the source buffer where to copy the string from.
+ * @count: Size of the destination buffer, in UCS2 (16-bit) characters.
+ *
+ * Like strscpy(), only for UCS2 strings.
+ *
+ * Copy the source string @src, or as much of it as fits, into the destination
+ * buffer @dst. The behavior is undefined if the string buffers overlap. The
+ * destination buffer @dst is always NUL-terminated, unless it's zero-sized.
+ *
+ * Return: The number of characters copied into @dst (excluding the trailing
+ * %NUL terminator) or -E2BIG if @count is 0 or @src was truncated due to the
+ * destination buffer being too small.
+ */
+ssize_t ucs2_strscpy(ucs2_char_t *dst, const ucs2_char_t *src, size_t count)
+{
+       long res;
+
+       /*
+        * Ensure that we have a valid amount of space. We need to store at
+        * least one NUL-character.
+        */
+       if (count == 0 || WARN_ON_ONCE(count > INT_MAX / sizeof(*dst)))
+               return -E2BIG;
+
+       /*
+        * Copy at most 'count' characters, return early if we find a
+        * NUL-terminator.
+        */
+       for (res = 0; res < count; res++) {
+               ucs2_char_t c;
+
+               c = src[res];
+               dst[res] = c;
+
+               if (!c)
+                       return res;
+       }
+
+       /*
+        * The loop above terminated without finding a NUL-terminator,
+        * exceeding the 'count': Enforce proper NUL-termination and return
+        * error.
+        */
+       dst[count - 1] = 0;
+       return -E2BIG;
+}
+EXPORT_SYMBOL(ucs2_strscpy);
+
 int
 ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
 {