Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision dd0502ae40ad37c48c1a61a8f4aadbaff4e9d3a0)
+++ uspace/lib/c/generic/str.c	(revision 1c9bf2921b28e891268eafe623bde93bee097636)
@@ -1471,408 +1471,4 @@
 	*end = '\0';
 	return start;
-}
-
-/** Convert string to uint64_t (internal variant).
- *
- * @param nptr   Pointer to string.
- * @param endptr Pointer to the first invalid character is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param neg    Indication of unary minus is stored here.
- * @apram result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-static errno_t str_uint(const char *nptr, char **endptr, unsigned int base,
-    bool *neg, uint64_t *result)
-{
-	assert(endptr != NULL);
-	assert(neg != NULL);
-	assert(result != NULL);
-
-	*neg = false;
-	const char *str = nptr;
-
-	/* Ignore leading whitespace */
-	while (isspace(*str))
-		str++;
-
-	if (*str == '-') {
-		*neg = true;
-		str++;
-	} else if (*str == '+')
-		str++;
-
-	if (base == 0) {
-		/* Decode base if not specified */
-		base = 10;
-
-		if (*str == '0') {
-			base = 8;
-			str++;
-
-			switch (*str) {
-			case 'b':
-			case 'B':
-				base = 2;
-				str++;
-				break;
-			case 'o':
-			case 'O':
-				base = 8;
-				str++;
-				break;
-			case 'd':
-			case 'D':
-			case 't':
-			case 'T':
-				base = 10;
-				str++;
-				break;
-			case 'x':
-			case 'X':
-				base = 16;
-				str++;
-				break;
-			default:
-				str--;
-			}
-		}
-	} else {
-		/* Check base range */
-		if ((base < 2) || (base > 36)) {
-			*endptr = (char *) str;
-			return EINVAL;
-		}
-	}
-
-	*result = 0;
-	const char *startstr = str;
-
-	while (*str != 0) {
-		unsigned int digit;
-
-		if ((*str >= 'a') && (*str <= 'z'))
-			digit = *str - 'a' + 10;
-		else if ((*str >= 'A') && (*str <= 'Z'))
-			digit = *str - 'A' + 10;
-		else if ((*str >= '0') && (*str <= '9'))
-			digit = *str - '0';
-		else
-			break;
-
-		if (digit >= base)
-			break;
-
-		uint64_t prev = *result;
-		*result = (*result) * base + digit;
-
-		if (*result < prev) {
-			/* Overflow */
-			*endptr = (char *) str;
-			return EOVERFLOW;
-		}
-
-		str++;
-	}
-
-	if (str == startstr) {
-		/*
-		 * No digits were decoded => first invalid character is
-		 * the first character of the string.
-		 */
-		str = nptr;
-	}
-
-	*endptr = (char *) str;
-
-	if (str == nptr)
-		return EINVAL;
-
-	return EOK;
-}
-
-/** Convert string to uint8_t.
- *
- * @param nptr   Pointer to string.
- * @param endptr If not NULL, pointer to the first invalid character
- *               is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param strict Do not allow any trailing characters.
- * @param result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
-    bool strict, uint8_t *result)
-{
-	assert(result != NULL);
-
-	bool neg;
-	char *lendptr;
-	uint64_t res;
-	errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
-
-	if (endptr != NULL)
-		*endptr = (char *) lendptr;
-
-	if (ret != EOK)
-		return ret;
-
-	/* Do not allow negative values */
-	if (neg)
-		return EINVAL;
-
-	/*
-	 * Check whether we are at the end of
-	 * the string in strict mode
-	 */
-	if ((strict) && (*lendptr != 0))
-		return EINVAL;
-
-	/* Check for overflow */
-	uint8_t _res = (uint8_t) res;
-	if (_res != res)
-		return EOVERFLOW;
-
-	*result = _res;
-
-	return EOK;
-}
-
-/** Convert string to uint16_t.
- *
- * @param nptr   Pointer to string.
- * @param endptr If not NULL, pointer to the first invalid character
- *               is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param strict Do not allow any trailing characters.
- * @param result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
-    bool strict, uint16_t *result)
-{
-	assert(result != NULL);
-
-	bool neg;
-	char *lendptr;
-	uint64_t res;
-	errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
-
-	if (endptr != NULL)
-		*endptr = (char *) lendptr;
-
-	if (ret != EOK)
-		return ret;
-
-	/* Do not allow negative values */
-	if (neg)
-		return EINVAL;
-
-	/*
-	 * Check whether we are at the end of
-	 * the string in strict mode
-	 */
-	if ((strict) && (*lendptr != 0))
-		return EINVAL;
-
-	/* Check for overflow */
-	uint16_t _res = (uint16_t) res;
-	if (_res != res)
-		return EOVERFLOW;
-
-	*result = _res;
-
-	return EOK;
-}
-
-/** Convert string to uint32_t.
- *
- * @param nptr   Pointer to string.
- * @param endptr If not NULL, pointer to the first invalid character
- *               is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param strict Do not allow any trailing characters.
- * @param result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
-    bool strict, uint32_t *result)
-{
-	assert(result != NULL);
-
-	bool neg;
-	char *lendptr;
-	uint64_t res;
-	errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
-
-	if (endptr != NULL)
-		*endptr = (char *) lendptr;
-
-	if (ret != EOK)
-		return ret;
-
-	/* Do not allow negative values */
-	if (neg)
-		return EINVAL;
-
-	/*
-	 * Check whether we are at the end of
-	 * the string in strict mode
-	 */
-	if ((strict) && (*lendptr != 0))
-		return EINVAL;
-
-	/* Check for overflow */
-	uint32_t _res = (uint32_t) res;
-	if (_res != res)
-		return EOVERFLOW;
-
-	*result = _res;
-
-	return EOK;
-}
-
-/** Convert string to uint64_t.
- *
- * @param nptr   Pointer to string.
- * @param endptr If not NULL, pointer to the first invalid character
- *               is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param strict Do not allow any trailing characters.
- * @param result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
-    bool strict, uint64_t *result)
-{
-	assert(result != NULL);
-
-	bool neg;
-	char *lendptr;
-	errno_t ret = str_uint(nptr, &lendptr, base, &neg, result);
-
-	if (endptr != NULL)
-		*endptr = (char *) lendptr;
-
-	if (ret != EOK)
-		return ret;
-
-	/* Do not allow negative values */
-	if (neg)
-		return EINVAL;
-
-	/*
-	 * Check whether we are at the end of
-	 * the string in strict mode
-	 */
-	if ((strict) && (*lendptr != 0))
-		return EINVAL;
-
-	return EOK;
-}
-
-/** Convert string to int64_t.
- *
- * @param nptr   Pointer to string.
- * @param endptr If not NULL, pointer to the first invalid character
- *               is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param strict Do not allow any trailing characters.
- * @param result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-int str_int64_t(const char *nptr, const char **endptr, unsigned int base,
-    bool strict, int64_t *result)
-{
-	assert(result != NULL);
-
-	bool neg;
-	char *lendptr;
-	uint64_t unsigned_result;
-	int ret = str_uint(nptr, &lendptr, base, &neg, &unsigned_result);
-
-	if (endptr != NULL)
-		*endptr = (char *) lendptr;
-
-	if (ret != EOK)
-		return ret;
-
-	/* Do not allow negative values */
-	if (neg) {
-		if (unsigned_result == UINT64_MAX)
-			return EINVAL;
-
-		*result = -(int64_t) unsigned_result;
-	} else
-		*result = unsigned_result;
-
-	/*
-	 * Check whether we are at the end of
-	 * the string in strict mode
-	 */
-	if ((strict) && (*lendptr != 0))
-		return EINVAL;
-
-	return EOK;
-}
-
-/** Convert string to size_t.
- *
- * @param nptr   Pointer to string.
- * @param endptr If not NULL, pointer to the first invalid character
- *               is stored here.
- * @param base   Zero or number between 2 and 36 inclusive.
- * @param strict Do not allow any trailing characters.
- * @param result Result of the conversion.
- *
- * @return EOK if conversion was successful.
- *
- */
-errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
-    bool strict, size_t *result)
-{
-	assert(result != NULL);
-
-	bool neg;
-	char *lendptr;
-	uint64_t res;
-	errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
-
-	if (endptr != NULL)
-		*endptr = (char *) lendptr;
-
-	if (ret != EOK)
-		return ret;
-
-	/* Do not allow negative values */
-	if (neg)
-		return EINVAL;
-
-	/*
-	 * Check whether we are at the end of
-	 * the string in strict mode
-	 */
-	if ((strict) && (*lendptr != 0))
-		return EINVAL;
-
-	/* Check for overflow */
-	size_t _res = (size_t) res;
-	if (_res != res)
-		return EOVERFLOW;
-
-	*result = _res;
-
-	return EOK;
 }
 
Index: uspace/lib/c/generic/strtol.c
===================================================================
--- uspace/lib/c/generic/strtol.c	(revision dd0502ae40ad37c48c1a61a8f4aadbaff4e9d3a0)
+++ uspace/lib/c/generic/strtol.c	(revision 1c9bf2921b28e891268eafe623bde93bee097636)
@@ -44,6 +44,11 @@
 #include <stdbool.h>
 #include <stdlib.h>
-
-// TODO: unit tests
+#include <str.h>
+
+// FIXME: The original HelenOS functions return EOVERFLOW instead
+//        of ERANGE. It's a pointless distinction from standard functions,
+//        so we should change that. Beware the callers though.
+
+// TODO: more unit tests
 
 static inline int _digit_value(int c)
@@ -69,5 +74,5 @@
 }
 
-static inline int _prefixbase(const char *restrict *nptrptr, bool nonstandard_prefixes)
+static inline int _prefixbase(const char *restrict *nptrptr, bool nonstd)
 {
 	const char *nptr = *nptrptr;
@@ -83,5 +88,5 @@
 	}
 
-	if (nonstandard_prefixes) {
+	if (nonstd) {
 		switch (nptr[1]) {
 		case 'b':
@@ -116,5 +121,5 @@
 static inline uintmax_t _strtoumax(
     const char *restrict nptr, char **restrict endptr, int base,
-    bool *restrict sgn, errno_t *err, bool nonstandard_prefixes)
+    bool *restrict sgn, errno_t *err, bool nonstd)
 {
 	assert(nptr != NULL);
@@ -144,7 +149,7 @@
 
 	if (base == 0)
-		base = _prefixbase(&nptr, nonstandard_prefixes);
-
-	if (base == 16 && !nonstandard_prefixes) {
+		base = _prefixbase(&nptr, nonstd);
+
+	if (base == 16 && !nonstd) {
 		/*
 		 * Standard strto* functions allow hexadecimal prefix to be
@@ -184,5 +189,5 @@
 		    __builtin_add_overflow(result * base, digit, &result)) {
 
-			*err = ERANGE;
+			*err = nonstd ? EOVERFLOW : ERANGE;
 			result = UINTMAX_MAX;
 			break;
@@ -212,9 +217,8 @@
 
 static inline intmax_t _strtosigned(const char *nptr, char **endptr, int base,
-    intmax_t min, intmax_t max, errno_t *err, bool nonstandard_prefixes)
+    intmax_t min, intmax_t max, errno_t *err, bool nonstd)
 {
 	bool sgn = false;
-	uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err,
-	    nonstandard_prefixes);
+	uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
 
 	if (number > (uintmax_t) max) {
@@ -223,5 +227,5 @@
 		}
 
-		*err = ERANGE;
+		*err = nonstd ? EOVERFLOW : ERANGE;
 		return (sgn ? min : max);
 	}
@@ -231,12 +235,17 @@
 
 static inline uintmax_t _strtounsigned(const char *nptr, char **endptr, int base,
-    uintmax_t max, errno_t *err, bool nonstandard_prefixes)
+    uintmax_t max, errno_t *err, bool nonstd)
 {
 	bool sgn = false;
-	uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err,
-	    nonstandard_prefixes);
+	uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
+
+	if (nonstd && sgn) {
+		/* Do not allow negative values */
+		*err = EINVAL;
+		return 0;
+	}
 
 	if (number > max) {
-		*err = ERANGE;
+		*err = nonstd ? EOVERFLOW : ERANGE;
 		return max;
 	}
@@ -316,4 +325,214 @@
 }
 
+/** Convert string to uint8_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return EOK if conversion was successful.
+ *
+ */
+errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
+    bool strict, uint8_t *result)
+{
+	assert(result != NULL);
+
+	errno_t rc = EOK;
+	char *lendptr = (char *) nptr;
+
+	uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT8_MAX, &rc, true);
+
+	if (endptr)
+		*endptr = lendptr;
+
+	if (rc != EOK)
+		return rc;
+
+	if (strict && *lendptr != '\0')
+		return EINVAL;
+
+	*result = r;
+	return EOK;
+}
+
+/** Convert string to uint16_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return EOK if conversion was successful.
+ *
+ */
+errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
+    bool strict, uint16_t *result)
+{
+	assert(result != NULL);
+
+	errno_t rc = EOK;
+	char *lendptr = (char *) nptr;
+
+	uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT16_MAX, &rc, true);
+
+	if (endptr)
+		*endptr = lendptr;
+
+	if (rc != EOK)
+		return rc;
+
+	if (strict && *lendptr != '\0')
+		return EINVAL;
+
+	*result = r;
+	return EOK;
+}
+
+/** Convert string to uint32_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return EOK if conversion was successful.
+ *
+ */
+errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
+    bool strict, uint32_t *result)
+{
+	assert(result != NULL);
+
+	errno_t rc = EOK;
+	char *lendptr = (char *) nptr;
+
+	uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT32_MAX, &rc, true);
+
+	if (endptr)
+		*endptr = lendptr;
+
+	if (rc != EOK)
+		return rc;
+
+	if (strict && *lendptr != '\0')
+		return EINVAL;
+
+	*result = r;
+	return EOK;
+}
+
+/** Convert string to uint64_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return EOK if conversion was successful.
+ *
+ */
+errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
+    bool strict, uint64_t *result)
+{
+	assert(result != NULL);
+
+	errno_t rc = EOK;
+	char *lendptr = (char *) nptr;
+
+	uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT64_MAX, &rc, true);
+
+	if (endptr)
+		*endptr = lendptr;
+
+	if (rc != EOK)
+		return rc;
+
+	if (strict && *lendptr != '\0')
+		return EINVAL;
+
+	*result = r;
+	return EOK;
+}
+
+/** Convert string to int64_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return EOK if conversion was successful.
+ *
+ */
+errno_t str_int64_t(const char *nptr, const char **endptr, unsigned int base,
+    bool strict, int64_t *result)
+{
+	assert(result != NULL);
+
+	errno_t rc = EOK;
+	char *lendptr = (char *) nptr;
+
+	intmax_t r = _strtosigned(nptr, &lendptr, base, INT64_MIN, INT64_MAX, &rc, true);
+
+	if (endptr)
+		*endptr = lendptr;
+
+	if (rc != EOK)
+		return rc;
+
+	if (strict && *lendptr != '\0')
+		return EINVAL;
+
+	*result = r;
+	return EOK;
+}
+
+/** Convert string to size_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return EOK if conversion was successful.
+ *
+ */
+errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
+    bool strict, size_t *result)
+{
+	assert(result != NULL);
+
+	errno_t rc = EOK;
+	char *lendptr = (char *) nptr;
+
+	uintmax_t r = _strtounsigned(nptr, &lendptr, base, SIZE_MAX, &rc, true);
+
+	if (endptr)
+		*endptr = lendptr;
+
+	if (rc != EOK)
+		return rc;
+
+	if (strict && *lendptr != '\0')
+		return EINVAL;
+
+	*result = r;
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision dd0502ae40ad37c48c1a61a8f4aadbaff4e9d3a0)
+++ uspace/lib/c/include/str.h	(revision 1c9bf2921b28e891268eafe623bde93bee097636)
@@ -134,5 +134,5 @@
 extern errno_t str_size_t(const char *, const char **, unsigned int, bool,
     size_t *);
-extern int str_int64_t(const char *, const char **, unsigned int, bool,
+extern errno_t str_int64_t(const char *, const char **, unsigned int, bool,
     int64_t *);
 
Index: uspace/lib/c/test/strtol.c
===================================================================
--- uspace/lib/c/test/strtol.c	(revision dd0502ae40ad37c48c1a61a8f4aadbaff4e9d3a0)
+++ uspace/lib/c/test/strtol.c	(revision 1c9bf2921b28e891268eafe623bde93bee097636)
@@ -218,5 +218,4 @@
 	/* Correct result. */
 	PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
-	PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);
 #endif
 
@@ -246,5 +245,4 @@
 	/* Correct result. */
 	PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
-	PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);
 #endif
 }
