This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: strerror_r questions


Hi Eric,

On Feb  9 14:09, Eric Blake wrote:
> On 02/06/2011 02:52 AM, Corinna Vinschen wrote:
> > First of all, the existing implementation follows glibc's lead, so
> > it should stick to the API but the behavior should be fixed.
> > 
> > Other than that, the Linux approach would work best.  Provide both
> > interfaces and use test macros.  Fortunately they are documented in the
> > man page:
> > 
> >   The XSI-compliant version of strerror_r() is provided if:
> >   (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
> >   Otherwise, the GNU-specific version is provided.
> > 
> > Ideally we don't define _GNU_SOURCE by default, so this should result in
> > getting the POSIX version by default.
> 
> Well, for backwards compatibility (as well as glibc compatibility), I
> thought it better we still get the _GNU_SOURCE version by default; but I
> can tweak things if you really want me to default to POSIX when no
> feature test macros are present.  At any rate, here's the newlib side of
> the patch (cygwin will need to be patched separately).

My POV is, Linux compatibility is a nice feature, but if glibc and POSIX
disagree, then POSIX should have precedent.  It's the standard.  Anyway,
I'm not adamant about it, and backward-compatibility is certainly a good
point as well.

> --- a/newlib/libc/include/string.h
> +++ b/newlib/libc/include/string.h
> @@ -66,7 +66,22 @@ char 	*_EXFUN(strdup,(const char *));
>  char 	*_EXFUN(_strdup_r,(struct _reent *, const char *));
>  char 	*_EXFUN(strndup,(const char *, size_t));
>  char 	*_EXFUN(_strndup_r,(struct _reent *, const char *, size_t));
> -char 	*_EXFUN(strerror_r,(int, char *, size_t));
> +/* There are two common strerror_r variants.  If you request
> +   _GNU_SOURCE, you get the GNU version; otherwise if you request
> +   standards compliance, you get the POSIX version; otherwise (for
> +   backwards compatibility) you get the GNU version.  POSIX requires
> +   that #undef strerror_r will still let you invoke the underlying
> +   function, but we only support that with gcc.  */
> +#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
> +# ifdef __GNUC__
> +char    *_EXFUN(strerror_r,(int, char *, size_t)) __asm__ ("__xpg_strerror_r");

Erm... shouldn't the return value be "int" rather than "char *" in this
case?

> @@ -49,5 +64,6 @@ _DEFUN (strerror_r, (errnum, buffer, n),
>    char *error;
>    error = strerror (errnum);
> 
> -  return strncpy (buffer, (const char *)error, n);
> +  strncpy (buffer, error, n);
> +  return strlen (error) >= n ? error : buffer;

This looks wrong to me.  Glibc guarantees that the copied result in
buffer is NUL-terminated, and I'm missing the "Unknown error XXX"
message.  Wern't these problems the main reason for this patch?  So,
shouldn't that be rather something like this?

  if (strlen (error) >= n)
    return error;
  if (!*error)
    snprintf (buffer, n, "Unknown error %d", errnum);
  else if (n > 0)
    {
      buffer[0] = '\0';
      strncat (buffer, error, n - 1);
    }
  return buffer;


> +_DEFUN (__xpg_strerror_r, (errnum, buffer, n),
> +	int errnum _AND
> +	char *buffer _AND
> +	size_t n)
> +{
> +  char *error;
> +  error = strerror (errnum);
> +
> +  strncpy (buffer, error, n);

Same here.  POSIX does not require that the string in buffer is
NUL-terminated, that's what the ERANGE is for, but the POSIX man page
also contains words about unknown error codes as a [CX] type extension:

  "If the value of errnum is a valid error number, the message string
   shall indicate what error occurred; otherwise, if these functions
   complete successfully, the message string shall indicate that an
   unknown error occurred."

I think it makes sense to implement this as well.


Corinna

-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]