Index: kernel/generic/src/lib/str.c
===================================================================
--- kernel/generic/src/lib/str.c	(revision d99c1d2ba8c7b2c687d430f2e9fd237046606545)
+++ kernel/generic/src/lib/str.c	(revision 3292623d2c53a7386c3a2e4d98465ae659411b56)
@@ -537,25 +537,23 @@
  * null-terminated and containing only complete characters.
  *
- * @param dest   Destination buffer.
+ * @param dest  Destination buffer.
  * @param count Size of the destination buffer (must be > 0).
  * @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;
-
 	/* There must be space for a null terminator in the buffer. */
 	ASSERT(size > 0);
 	
-	src_off = 0;
-	dest_off = 0;
-
+	size_t src_off = 0;
+	size_t dest_off = 0;
+	
+	wchar_t ch;
 	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';
 }
@@ -571,27 +569,84 @@
  * have to be null-terminated.
  *
- * @param dest   Destination buffer.
+ * @param dest  Destination buffer.
  * @param count Size of the destination buffer (must be > 0).
  * @param src   Source string.
- * @param n	Maximum number of bytes to read from @a src.
+ * @param n     Maximum number of bytes to read from @a src.
+ *
  */
 void str_ncpy(char *dest, size_t size, const char *src, size_t n)
 {
-	wchar_t ch;
-	size_t src_off;
-	size_t dest_off;
-
 	/* There must be space for a null terminator in the buffer. */
 	ASSERT(size > 0);
 	
-	src_off = 0;
-	dest_off = 0;
-
+	size_t src_off = 0;
+	size_t dest_off = 0;
+	
+	wchar_t ch;
 	while ((ch = str_decode(src, &src_off, n)) != 0) {
 		if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
 			break;
 	}
-
+	
 	dest[dest_off] = '\0';
+}
+
+/** Duplicate string.
+ *
+ * Allocate a new string and copy characters from the source
+ * string into it. The duplicate string is allocated via sleeping
+ * malloc(), thus this function can sleep in no memory conditions.
+ *
+ * The allocation cannot fail and the return value is always
+ * a valid pointer. The duplicate string is always a well-formed
+ * null-terminated UTF-8 string, but it can differ from the source
+ * string on the byte level.
+ *
+ * @param src Source string.
+ *
+ * @return Duplicate string.
+ *
+ */
+char *str_dup(const char *src)
+{
+	size_t size = str_size(src) + 1;
+	char *dest = malloc(size, 0);
+	ASSERT(dest);
+	
+	str_cpy(dest, size, src);
+	return dest;
+}
+
+/** Duplicate string with size limit.
+ *
+ * Allocate a new string and copy up to @max_size bytes from the source
+ * string into it. The duplicate string is allocated via sleeping
+ * malloc(), thus this function can sleep in no memory conditions.
+ * No more than @max_size + 1 bytes is allocated, but if the size
+ * occupied by the source string is smaller than @max_size + 1,
+ * less is allocated.
+ *
+ * The allocation cannot fail and the return value is always
+ * a valid pointer. The duplicate string is always a well-formed
+ * null-terminated UTF-8 string, but it can differ from the source
+ * string on the byte level.
+ *
+ * @param src Source string.
+ * @param n   Maximum number of bytes to duplicate.
+ *
+ * @return Duplicate string.
+ *
+ */
+char *str_ndup(const char *src, size_t n)
+{
+	size_t size = str_size(src);
+	if (size > n)
+		size = n;
+	
+	char *dest = malloc(size + 1, 0);
+	ASSERT(dest);
+	
+	str_ncpy(dest, size + 1, src, size);
+	return dest;
 }
 
