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 <[email protected]> * 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 [email protected] +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;
+ }
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
-extern "C" int
+extern "C" char *
strerror_r (int errnum, char *buf, size_t n)
{
- char *errstr = strerror_worker (errnum);
- if (!errstr)
- return EINVAL;
- if (strlen (errstr) >= n)
- return ERANGE;
- strcpy (buf, errstr);
- return 0;
+ char *error = strerror (errnum);
+ if (strlen (error) >= n)
+ return error;
+ return strcpy (buf, error);
}
#endif
+
+extern "C" int
+__xpg_strerror_r (int errnum, char *buf, size_t n)
+{
+ if (!n)
+ return ERANGE;
+ int result = 0;
+ char *error = strerror_worker (errnum);
+ {
+ __small_sprintf (error = _my_tls.locals.strerror_buf, "Unknown error %u",
+ (unsigned) errnum);
+ result = EINVAL;
+ }
+ if (strlen (error) >= n)
+ {
+ memcpy (buf, error, n - 1);
+ buf[n - 1] = '\0';
+ return ERANGE;
+ }
+ strcpy (buf, error);
+ return result;
+}
diff --git a/winsup/cygwin/include/cygwin/version.h
b/winsup/cygwin/include/cygwin/version.h
index c757827..7246e8e 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -399,12 +399,13 @@ details. */
233: Add TIOCGPGRP, TIOCSPGRP. Export llround, llroundf.
234: Export program_invocation_name, program_invocation_short_name.
235: Export madvise.
+ 236: Export __xpg_strerror_r.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 235
+#define CYGWIN_VERSION_API_MINOR 236
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
--
1.7.3.3
signature.asc
Description: OpenPGP digital signature
