On Wed, Dec 6, 2023 at 11:36 AM Alejandro Colomar <alx@xxxxxxxxxx> wrote: > Also, I was going to ask for strtoi(3bsd) in glibc, since strtol(3) > isn't easy to use portably (since POSIX allows EINVAL on no conversion, > how to differentiate strtoi(3bsd)'s ECANCELED from EINVAL in strtol(3)?). I feel like this is rather overstating the difficulty. In practice, the no-conversion condition is very commonly detected by checking whether *endptr == nptr after the call. The usual idiom I see is something like: char *end; errno = 0; value = strtol(ptr, &end, 10); if (end == ptr || *end != '\0' || errno == ERANGE) goto err; Of course, the *end != '\0' condition can be omitted or adapted as necessary. Alternatively, one can avoid checking errno at all, by just checking whether the value is in the permitted range, since the saturating behavior will make such a check reject on overflow. And even without an explicit permitted range, one can just reject on on value == LONG_MIN || value == LONG_MAX, or just on value == ULONG_MAX for strtoul(3); rejecting a value that's almost an overflow isn't going to harm anything, except for the rare scenarios where a printed integer can actually reach the minimum or maximum, but needs to be round-tripped unconditionally. In general, I don't think most programmers are in the habit of carefully distinguishing errno values for <string.h> functions. They'd rather check for self-explanatory conditions, such as *endptr == nptr, that readers don't have to refer to the man page to decipher. There's a reason that most high-level language bindings return errno values for file I/O but not for anything else. Thank you, Matthew House