Index: kernel/generic/src/lib/string.c
===================================================================
--- kernel/generic/src/lib/string.c	(revision f2b8cdc51775d0938392285312ca1ea65eca2f5b)
+++ kernel/generic/src/lib/string.c	(revision 37c312a7ac9843a2f846a0434e94d88f096e94cb)
@@ -529,36 +529,69 @@
 }
 
-/** Copy NULL-terminated string.
- *
- * Copy source string @a src to destination buffer @a dst.
- * No more than @a size bytes are written. NULL-terminator is always
- * written after the last succesfully copied character (i.e. if the
- * destination buffer is has at least 1 byte, it will be always
- * NULL-terminated).
- *
- * @param src   Source string.
+/** Copy string.
+ *
+ * Copy source string @a src to destination buffer @a dest.
+ * No more than @a size bytes are written. If the size of the output buffer
+ * is at least one byte, the output string will always be well-formed, i.e.
+ * null-terminated and containing only complete characters.
+ *
  * @param dst   Destination buffer.
  * @param count Size of the destination buffer.
- *
- */
-void str_ncpy(char *dst, const char *src, size_t size)
-{
-	/* No space for the NULL-terminator in the buffer */
+ * @param src   Source string.
+ */
+void str_cpy(char *dest, size_t size, const char *src)
+{
+	wchar_t ch;
+	size_t src_off;
+	size_t dest_off;
+
+	/* No space for the NULL-terminator in the buffer. */
 	if (size == 0)
 		return;
 	
+	src_off = 0;
+	dest_off = 0;
+
+	while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
+		if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
+			break;
+	}
+
+	dest[dest_off] = '\0';
+}
+
+/** Copy size-limited substring.
+ *
+ * Copy source string @a src to destination buffer @a dest.
+ * No more than @a size bytes are written. If the size of the output buffer
+ * is at least one byte, the output string will always be well-formed, i.e.
+ * null-terminated and containing only complete characters.
+ *
+ * No more than @a n bytes are read from the input string, so it does not
+ * have to be null-terminated.
+ *
+ * @param dst   Destination buffer.
+ * @param count Size of the destination buffer.
+ * @param src   Source string.
+ */
+void str_ncpy(char *dest, size_t size, const char *src, size_t n)
+{
 	wchar_t ch;
-	size_t str_off = 0;
-	size_t dst_off = 0;
-	
-	while ((ch = str_decode(src, &str_off, STR_NO_LIMIT)) != 0) {
-		if (chr_encode(ch, dst, &dst_off, size) != EOK)
+	size_t src_off;
+	size_t dest_off;
+
+	/* No space for the null terminator in the buffer. */
+	if (size == 0)
+		return;
+	
+	src_off = 0;
+	dest_off = 0;
+
+	while ((ch = str_decode(src, &src_off, n)) != 0) {
+		if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
 			break;
 	}
-	
-	if (dst_off >= size)
-		dst[size - 1] = 0;
-	else
-		dst[dst_off] = 0;
+
+	dest[dest_off] = '\0';
 }
 
