Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Pryor <jpryor@novell.com>2005-04-07 18:29:52 +0400
committerJonathan Pryor <jpryor@novell.com>2005-04-07 18:29:52 +0400
commit702376ddc120cd545da7355f0ac0a8f9ad205b43 (patch)
tree83a7f0966d35c5a26082f208e8672ec2358b2437 /support
parentf943410d7265cb08c076852614fe80db63186c77 (diff)
* errno.c: Use the GNU version of strerror_r if _GNU_SOURCE is defined
(otherwise assume existence of XPG variant). This allows proper compilation under Red Hat 9. * fstab.c: protect against users calling setfsent(), setfsent(), ... endfsent(), which would otherwise leak a FILE handle. svn path=/trunk/mono/; revision=42642
Diffstat (limited to 'support')
-rw-r--r--support/ChangeLog8
-rw-r--r--support/errno.c95
-rw-r--r--support/fstab.c3
3 files changed, 101 insertions, 5 deletions
diff --git a/support/ChangeLog b/support/ChangeLog
index 84ae4c23899..ee4196b63a2 100644
--- a/support/ChangeLog
+++ b/support/ChangeLog
@@ -1,3 +1,11 @@
+2005-04-07 Zoltan Varga <vargaz@freemail.hu>
+
+ * errno.c: Use the GNU version of strerror_r if _GNU_SOURCE is defined
+ (otherwise assume existence of XPG variant). This allows proper
+ compilation under Red Hat 9.
+ * fstab.c: protect against users calling setfsent(), setfsent(), ...
+ endfsent(), which would otherwise leak a FILE handle.
+
2005-04-05 Zoltan Varga <vargaz@freemail.hu>
* mph.h: Apply patch from the freebsd ports collection.
diff --git a/support/errno.c b/support/errno.c
index a5d215513bb..a28425e03b8 100644
--- a/support/errno.c
+++ b/support/errno.c
@@ -2,11 +2,6 @@
* <errno.h> wrapper functions.
*/
-/* to get XPG's strerror_r declaration */
-#undef _GNU_SOURCE
-#undef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 600
-
#include <errno.h>
#include <string.h>
#include "mph.h"
@@ -28,12 +23,102 @@ Mono_Posix_Stdlib_SetLastError (int error_number)
}
#ifdef HAVE_STRERROR_R
+
+/*
+ * There are two versions of strerror_r:
+ * - the GNU version: char *strerror_r (int errnum, char *buf, size_t n);
+ * - the XPG version: int strerror_r (int errnum, char *buf, size_t n);
+ *
+ * Ideally I could stick with the XPG version, but we need to support
+ * Red Hat 9, which only supports the GNU version.
+ *
+ * Furthermore, I do NOT want to export the GNU version in Mono.Posix.dll,
+ * as that's supposed to contain *standard* function definitions (give or
+ * take a few GNU extensions). Portability trumps all.
+ *
+ * Consequently, we export the functionality of the XPG version.
+ * Internally, we se the GNU version if _GNU_SOURCE is defined, otherwise
+ * we assume that the XPG version is present.
+ */
+
+#ifdef _GNU_SOURCE
+#define mph_min(x,y) ((x) <= (y) ? (x) : (y))
+
+/* If you pass an invalid errno value to glibc 2.3.2's strerror_r, you get
+ * back the string "Unknown error" with the error value appended. */
+static const char mph_unknown[] = "Unknown error ";
+
+/*
+ * Translate the GNU semantics to the XPG semantics.
+ *
+ * From reading the (RH9-using) GLibc 2.3.2 sysdeps/generic/_strerror.c,
+ * we can say the following:
+ * - If errnum is a valid error number, a pointer to a constant string is
+ * returned. Thus, the prototype *lies* (it's not really a char*).
+ * `buf' is unchanged (WTF?).
+ * - If errnum is an *invalid* error number, an error message is copied
+ * into `buf' and `buf' is returned. The error message returned is
+ * "Unknown error %i", where %i is the input errnum.
+ *
+ * Meanwhile, XPG always modifies `buf' if there's enough space, and either
+ * returns 0 (success) or -1 (error) with errno = EINVAL (bad errnum) or
+ * ERANGE (`buf' isn't big enough). Also, GLibc 2.3.3 (which has the XPG
+ * version) first checks the validity of errnum first, then does the copy.
+ *
+ * Assuming that the GNU implementation doesn't change much (ha!), we can
+ * check for EINVAL by comparing the strerror_r return to `buf', OR by
+ * comparing the return value to "Uknown error". (This assumes that
+ * strerror_r will always only return the input buffer for errors.)
+ *
+ * Check for ERANGE by comparing the string length returned by strerror_r to
+ * `n'.
+ *
+ * Then pray that this actually works...
+ */
+gint32
+Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n)
+{
+ char *r;
+ char ebuf [sizeof(mph_unknown)];
+ size_t len;
+ size_t blen;
+
+ mph_return_if_size_t_overflow (n);
+
+ /* first, check for valid errnum */
+ r = strerror_r (errnum, ebuf, sizeof(ebuf));
+ len = strlen (r);
+
+ if (r == ebuf ||
+ strncmp (r, mph_unknown, mph_min (len, sizeof(mph_unknown))) == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* valid errnum (we hope); is buffer big enough? */
+ blen = (size_t) n;
+ if ((len+1) > blen) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ strncpy (buf, r, len);
+ buf[len] = '\0';
+
+ return 0;
+}
+
+#else /* !def _GNU_SOURCE */
+
gint32
Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n)
{
mph_return_if_size_t_overflow (n);
return strerror_r (errnum, buf, (size_t) n);
}
+
+#endif /* def _GNU_SOURCE */
+
#endif /* def HAVE_STRERROR_R */
G_END_DECLS
diff --git a/support/fstab.c b/support/fstab.c
index c9ff50547a8..2fb79be2671 100644
--- a/support/fstab.c
+++ b/support/fstab.c
@@ -174,6 +174,9 @@ etc_fstab;
static int
setfsent (void)
{
+ /* protect from bad users calling setfsent(), setfsent(), ... endfsent() */
+ if (etc_fstab != NULL)
+ fclose (etc_fstab);
etc_fstab = fopen ("/etc/vfstab", "r");
if (etc_fstab != NULL)
return 1;