Andy Dougherty via RT wrote:
On Thu, 17 Jul 2008, Christoph Otto via RT wrote:
On Thu Jul 17 15:53:12 2008, julianalbo wrote:
On Thu, Jul 17, 2008 at 9:59 PM, Christoph Otto via RT
<[EMAIL PROTECTED]> wrote:
trick. The attached patch (v5) properly fixes the problem on my system.
There shouldn't be any remaining issues, but the patch ought to be
tested on a another *nix and Windows.
[ . . . ]
char *errstr = strerror_r(errno, errmsg, ERRBUF_SIZE);
Unfortunately, that's not portable. The POSIXy version of strerror_r
returns an integer, specifically 0 if successful, and something else
otherwise. (What that "something" else actually is seems to be
defined differently by different vendors, alas. OpenBSD and Solaris
return errno. Linux/glibc returns -1.)
Thanks for pointing that out. After what it's taking to get this to work, I'm
looking forward to my next patch being silently ignored. I suppose there's a
reason my spell checker wanted to turn "strerror" to "terrorist".
This version of the patch should dtrt with all versions of strerror_r. It
works on my Debian/x86 box and I'll be testing it on any *nix I can get my
hands on Tuesday. If it works fine there, if someone can test it on windows
and if the patch looks OK, I'll commit it and close this ticket.
Christoph
Index: src/pmc/file.pmc
===================================================================
--- src/pmc/file.pmc (revision 29667)
+++ src/pmc/file.pmc (working copy)
@@ -24,8 +24,50 @@
#include "parrot/parrot.h"
-/* RT#46681 apparently, strerror_r is thread-safe and should be used instead.*/
+/* strerror_r should truncate the message if it's too long for the supplied
+ * buffer. It's probably best to just specify a sane default buffer size than
+ * to worry about retrying calls. */
+#define ERRBUF_SIZE 128
+/* feature test macro taken from Ubuntu's strerror man page */
+#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
+/* use POSIXy strerror_r */
+# define STRERROR_R_EXCEPTION(interp, func) \
+ { \
+ char errmsg[ERRBUF_SIZE]; \
+ int err_status; \
+ err_status = strerror_r(errno, errmsg, ERRBUF_SIZE); \
+ /* Linux's POSIXy strerror_r returns -1 on error, others return an error code */ \
+ if (err_status == -1) \
+ err_status = errno; \
+ \
+ if (err_status == 0 || err_status == ERANGE) { \
+ STRING *errmsg_pstring = string_make((interp), errmsg, strlen(errmsg), NULL, 0); \
+ real_exception((interp), NULL, E_SystemError, "%Ss", errmsg_pstring); \
+ } \
+ else if (err_status == EINVAL){ \
+ real_exception((interp), NULL, E_SystemError, \
+ "%s returned an invalid error code (%d)", #func, errno); \
+ else { \
+ real_exception((interp), NULL, E_SystemError, \
+ "strerror_r() returned an unknown error code: %d", err_status); \
+ } \
+ }
+#else
+/* use GNU-specific strerror_r */
+# define STRERROR_R_EXCEPTION(interp, func) \
+ { \
+ /* GNU strerror_r DTRT for unknown error codes */ \
+ char errmsg[ERRBUF_SIZE]; \
+ char *errstr = strerror_r(errno, errmsg, ERRBUF_SIZE); \
+ STRING *errmsg_pstring = string_make((interp), errstr, strlen(errstr), NULL, 0); \
+ real_exception((interp), NULL, E_SystemError, "%Ss", errmsg_pstring); \
+ }
+#endif
+
+
+
+
static PMC *File_PMC;
pmclass File singleton {
@@ -89,6 +131,7 @@
*/
+
METHOD is_dir(STRING *path) {
struct stat info;
char *cpath = string_to_cstring(interp, path);
@@ -100,8 +143,11 @@
string_cstring_free(cpath);
if (error) {
- char *errmsg = strerror(errno);
- real_exception(interp, NULL, E_SystemError, errmsg);
+#ifdef WIN32
+ STRERROR_R_EXCEPTION(INTERP, stat);
+#else
+ STRERROR_R_EXCEPTION(INTERP, lstat);
+#endif
}
if (S_ISDIR(info.st_mode))
@@ -131,8 +177,11 @@
string_cstring_free(cpath);
if (error) {
- char *errmsg = strerror(errno);
- real_exception(interp, NULL, E_SystemError, errmsg);
+#ifdef WIN32
+ STRERROR_R_EXCEPTION(INTERP, stat);
+#else
+ STRERROR_R_EXCEPTION(INTERP, lstat);
+#endif
}
if (S_ISREG(info.st_mode))
@@ -164,8 +213,7 @@
string_cstring_free(cpath);
if (error) {
- char *errmsg = strerror(errno);
- real_exception(interp, NULL, E_SystemError, errmsg);
+ STRERROR_R_EXCEPTION(INTERP, lstat);
}
if (S_ISLNK(info.st_mode))
@@ -199,6 +247,8 @@
string_cstring_free(cfrom);
+ char errmsg[ERRBUF_SIZE];
+
if (source) {
char *cto = string_to_cstring(interp, to);
FILE *target = fopen(cto, "w+b");
@@ -223,14 +273,12 @@
fclose(target);
}
else {
- char *errmsg = strerror(errno);
- real_exception(interp, NULL, E_SystemError, errmsg);
+ STRERROR_R_EXCEPTION(INTERP, fopen);
}
fclose(source);
}
else {
- char *errmsg = strerror(errno);
- real_exception(interp, NULL, E_SystemError, errmsg);
+ STRERROR_R_EXCEPTION(INTERP, fopen);
}
#undef CHUNK_SIZE
}
@@ -254,8 +302,7 @@
string_cstring_free(cto);
if (error) {
- char *errmsg = strerror(errno);
- real_exception(interp, NULL, E_SystemError, errmsg);
+ STRERROR_R_EXCEPTION(INTERP, rename);
}
}
}
Index: config/gen/platform/win32/string.h
===================================================================
--- config/gen/platform/win32/string.h (revision 29667)
+++ config/gen/platform/win32/string.h (working copy)
@@ -14,6 +14,8 @@
# endif
#endif
+#define strerror_r(errnum, buf, buflen) strerror_s((buf), (buflen), (errnum))
+
#endif /* PARROT_PLATFORM_WIN32_STRING_H_GUARD */
/*