On Wed, Feb 09, 2011 at 05:20:59PM -0700, Eric Blake wrote:
>On 02/06/2011 02:54 AM, Corinna Vinschen wrote:
>>> We already provide our own strerror() (it provides a better experience
>>> for out-of-range values that the newlib interface), but we're currently
>>> using the newlib strerror_r() (in spite of its truncation flaw).
>>>
>>> How should I rework this patch?
>> 
>> It would be better if we implement strerror_r locally, in two versions,
>> just as on Linux.  I think the best approach is to implement this in
>> newlib first (I replied to your mail there) and then, given that we use
>> the newlib string.h, copy the method over to Cygwin to match our current
>> strerror more closely.
>
>Here's the cygwin side of things, to match newlib's <string.h> changes.
> Surprisingly, strerror_r turned out to be identical even when based on
>different root strerror(), so I left that inside #if 0, but it's easy
>enough to kill the #if 0 if you don't want cygwin to use any of newlib's
>strerror*.
>
>---
> winsup/cygwin/ChangeLog                |    9 +++
> winsup/cygwin/cygwin.din               |    1 +
> winsup/cygwin/errno.cc                 |   84
>+++++++++++++++++++++-----------
> winsup/cygwin/include/cygwin/version.h |    3 +-
> 4 files changed, 68 insertions(+), 29 deletions(-)
>
>2011-02-09  Eric Blake  <ebl...@redhat.com>
>
>       * errno.cc (__xpg_strerror_r): New function.
>       (strerror_r): Update comments to match newlib's fixes.
>       (strerror): Set errno on failure.
>       (_sys_errlist): Cause EINVAL failure for reserved values.
>       * cygwin.din: Export new function.
>       * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
>
>-- 
>Eric Blake   ebl...@redhat.com    +1-801-349-2682
>Libvirt virtualization library http://libvirt.org

>diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
>index 2e7e647..780179a 100644
>--- a/winsup/cygwin/cygwin.din
>+++ b/winsup/cygwin/cygwin.din
>@@ -1933,6 +1933,7 @@ xdrrec_skiprecord SIGFE
> __xdrrec_getrec SIGFE
> __xdrrec_setnonblock SIGFE
> xdrstdio_create SIGFE
>+__xpg_strerror_r SIGFE
> y0 NOSIGFE
> y0f NOSIGFE
> y1 NOSIGFE
>diff --git a/winsup/cygwin/errno.cc b/winsup/cygwin/errno.cc
>index a9860f4..0e9c863 100644
>--- a/winsup/cygwin/errno.cc
>+++ b/winsup/cygwin/errno.cc
>@@ -199,9 +199,9 @@ const char *_sys_errlist[] NO_COPY_INIT =
> /* EL2HLT 44 */                 "Level 2 halted",
> /* EDEADLK 45 */        "Resource deadlock avoided",
> /* ENOLCK 46 */                 "No locks available",
>-                        "error 47",
>-                        "error 48",
>-                        "error 49",
>+                        NULL,
>+                        NULL,
>+                        NULL,
> /* EBADE 50 */                  "Invalid exchange",
> /* EBADR 51 */                  "Invalid request descriptor",
> /* EXFULL 52 */                 "Exchange full",
>@@ -210,8 +210,8 @@ const char *_sys_errlist[] NO_COPY_INIT =
> /* EBADSLT 55 */        "Invalid slot",
> /* EDEADLOCK 56 */      "File locking deadlock error",
> /* EBFONT 57 */                 "Bad font file format",
>-                        "error 58",
>-                        "error 59",
>+                        NULL,
>+                        NULL,
> /* ENOSTR 60 */                 "Device not a stream",
> /* ENODATA 61 */        "No data available",
> /* ETIME 62 */                  "Timer expired",
>@@ -224,13 +224,13 @@ const char *_sys_errlist[] NO_COPY_INIT =
> /* ESRMNT 69 */                 "Srmount error",
> /* ECOMM 70 */                  "Communication error on send",
> /* EPROTO 71 */                 "Protocol error",
>-                        "error 72",
>-                        "error 73",
>+                        NULL,
>+                        NULL,
> /* EMULTIHOP 74 */      "Multihop attempted",
> /* ELBIN 75 */                  "Inode is remote (not really error)",
> /* EDOTDOT 76 */        "RFS specific error",
> /* EBADMSG 77 */        "Bad message",
>-                        "error 78",
>+                        NULL,
> /* EFTYPE 79 */                 "Inappropriate file type or format",
> /* ENOTUNIQ 80 */       "Name not unique on network",
> /* EBADFD 81 */                 "File descriptor in bad state",
>@@ -245,17 +245,17 @@ const char *_sys_errlist[] NO_COPY_INIT =
> /* ENOTEMPTY 90       */        "Directory not empty",
> /* ENAMETOOLONG 91 */   "File name too long",
> /* ELOOP 92 */                  "Too many levels of symbolic links",
>-                        "error 93",
>-                        "error 94",
>+                        NULL,
>+                        NULL,
> /* EOPNOTSUPP 95 */     "Operation not supported",
> /* EPFNOSUPPORT 96 */   "Protocol family not supported",
>-                        "error 97",
>-                        "error 98",
>-                        "error 99",
>-                        "error 100",
>-                        "error 101",
>-                        "error 102",
>-                        "error 103",
>+                        NULL,
>+                        NULL,
>+                        NULL,
>+                        NULL,
>+                        NULL,
>+                        NULL,
>+                        NULL,
> /* ECONNRESET 104 */    "Connection reset by peer",
> /* ENOBUFS 105 */       "No buffer space available",
> /* EAFNOSUPPORT 106 */          "Address family not supported by protocol",
>@@ -357,27 +357,55 @@ strerror_worker (int errnum)
>   return res;
> }
>
>-/* strerror: convert from errno values to error strings */
>+/* strerror: convert from errno values to error strings.  Newlib's
>+   strerror_r returns "" for unknown values, so we override it to
>+   provide a nicer thread-safe result string and set errno.  */
> extern "C" char *
> strerror (int errnum)
> {
>   char *errstr = strerror_worker (errnum);
>   if (!errstr)
>-    __small_sprintf (errstr = _my_tls.locals.strerror_buf, "Unknown error %u",
>-                   (unsigned) errnum);
>+    {
>+      __small_sprintf (errstr = _my_tls.locals.strerror_buf, "Unknown error 
>%u",
>+                     (unsigned) errnum);
>+      errno = _impure_ptr->_errno = EINVAL;

This should (as should the other usage in this file), just be "set_errno 
(EINVAL)".

>+    }
>   return errstr;
> }
>
>+/* Newlib's <string.h> provides declarations for two strerror_r
>+   variants, according to preprocessor feature macros.  It does the
>+   right thing for GNU strerror_r, but its __xpg_strerror_r mishandles
>+   a case of EINVAL when coupled with our strerror() override.*/
> #if 0

Can't we get rid of this now?

cgf

Reply via email to