*/
long __strncpy_from_user(char *dst, const char *src, long count)
{
- long res;
+ long res, faultres;
+ int tmp;
- __do_strncpy_from_user(dst, src, count, res);
- return res;
- }
- EXPORT_SYMBOL(__strncpy_from_user);
-
- /*
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst: Destination address, in kernel space. This buffer must be at
- * least @count bytes long.
- * @src: Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
- long strncpy_from_user(char *dst, const char *src, long count)
- {
- long res = -EFAULT;
+ __asm__ __volatile__(
+ " cmpnei %3, 0 \n"
+ " bf 4f \n"
+ "1: cmpnei %1, 0 \n"
+ " bf 5f \n"
+ "2: ldb %4, (%3, 0) \n"
+ " stb %4, (%2, 0) \n"
+ " cmpnei %4, 0 \n"
+ " bf 3f \n"
+ " addi %3, 1 \n"
+ " addi %2, 1 \n"
+ " subi %1, 1 \n"
+ " br 1b \n"
+ "3: subu %0, %1 \n"
+ " br 5f \n"
+ "4: mov %0, %5 \n"
+ " br 5f \n"
+ ".section __ex_table, \"a\" \n"
+ ".align 2 \n"
+ ".long 2b, 4b \n"
+ ".previous \n"
+ "5: \n"
+ : "=r"(res), "=r"(count), "=r"(dst),
+ "=r"(src), "=r"(tmp), "=r"(faultres)
+ : "5"(-EFAULT), "0"(count), "1"(count),
+ "2"(dst), "3"(src)
+ : "memory");
- if (access_ok(src, 1))
- __do_strncpy_from_user(dst, src, count, res);
return res;
}
- EXPORT_SYMBOL(strncpy_from_user);
+ EXPORT_SYMBOL(__strncpy_from_user);
/*
- * strlen_user: - Get the size of a string in user space.
+ * strnlen_user: - Get the size of a string in user space.
* @str: The string to measure.
* @n: The maximum valid length
*