fr_thread_local_setup(char *, fr_strerror_buffer) /* macro */
fr_thread_local_setup(char *, fr_syserror_buffer) /* macro */
+#ifndef NDEBUG
+/** POSIX-2008 errno macros
+ *
+ * Non-POSIX macros may be added, but you must check they're defined.
+ */
+char const *fr_errno_macro_names[] = {
+ [E2BIG] = "E2BIG",
+ [EACCES] = "EACCES",
+ [EADDRINUSE] = "EADDRINUSE",
+ [EADDRNOTAVAIL] = "EADDRNOTAVAIL",
+ [EAFNOSUPPORT] = "EAFNOSUPPORT",
+#if EWOULDBLOCK == EAGAIN
+ [EWOULDBLOCK] = "EWOULDBLOCK or EAGAIN",
+#else
+ [EAGAIN] = "EAGAIN",
+ [EWOULDBLOCK] = "EWOULDBLOCK",
+#endif
+ [EALREADY] = "EALREADY",
+ [EBADF] = "EBADF",
+ [EBADMSG] = "EBADMSG",
+ [EBUSY] = "EBUSY",
+ [ECANCELED] = "ECANCELED",
+ [ECHILD] = "ECHILD",
+ [ECONNABORTED] = "ECONNABORTED",
+ [ECONNREFUSED] = "ECONNREFUSED",
+ [ECONNRESET] = "ECONNRESET",
+ [EDEADLK] = "EDEADLK",
+ [EDESTADDRREQ] = "EDESTADDRREQ",
+ [EDOM] = "EDOM",
+ [EDQUOT] = "EDQUOT",
+ [EEXIST] = "EEXIST",
+ [EFAULT] = "EFAULT",
+ [EFBIG] = "EFBIG",
+ [EHOSTUNREACH] = "EHOSTUNREACH",
+ [EIDRM] = "EIDRM",
+ [EILSEQ] = "EILSEQ",
+ [EINPROGRESS] = "EINPROGRESS",
+ [EINTR] = "EINTR",
+ [EINVAL] = "EINVAL",
+ [EIO] = "EIO",
+ [EISCONN] = "EISCONN",
+ [EISDIR] = "EISDIR",
+ [ELOOP] = "ELOOP",
+ [EMFILE] = "EMFILE",
+ [EMLINK] = "EMLINK",
+ [EMSGSIZE] = "EMSGSIZE",
+ [EMULTIHOP] = "EMULTIHOP",
+ [ENAMETOOLONG] = "ENAMETOOLONG",
+ [ENETDOWN] = "ENETDOWN",
+ [ENETRESET] = "ENETRESET",
+ [ENETUNREACH] = "ENETUNREACH",
+ [ENFILE] = "ENFILE",
+ [ENOBUFS] = "ENOBUFS",
+ [ENODATA] = "ENODATA",
+ [ENODEV] = "ENODEV",
+ [ENOENT] = "ENOENT",
+ [ENOEXEC] = "ENOEXEC",
+ [ENOLCK] = "ENOLCK",
+ [ENOLINK] = "ENOLINK",
+ [ENOMEM] = "ENOMEM",
+ [ENOMSG] = "ENOMSG",
+ [ENOPROTOOPT] = "ENOPROTOOPT",
+ [ENOSPC] = "ENOSPC",
+ [ENOSR] = "ENOSR",
+ [ENOSTR] = "ENOSTR",
+ [ENOSYS] = "ENOSYS",
+ [ENOTCONN] = "ENOTCONN",
+ [ENOTDIR] = "ENOTDIR",
+ [ENOTEMPTY] = "ENOTEMPTY",
+ [ENOTRECOVERABLE] = "ENOTRECOVERABLE",
+ [ENOTSOCK] = "ENOTSOCK",
+ [ENOTSUP] = "ENOTSUP",
+ [ENOTTY] = "ENOTTY",
+ [ENXIO] = "ENXIO",
+ [EOPNOTSUPP] = "EOPNOTSUPP",
+ [EOVERFLOW] = "EOVERFLOW",
+ [EOWNERDEAD] = "EOWNERDEAD",
+ [EPERM] = "EPERM",
+ [EPIPE] = "EPIPE",
+ [EPROTO] = "EPROTO",
+ [EPROTONOSUPPORT] = "EPROTONOSUPPORT",
+ [EPROTOTYPE] = "EPROTOTYPE",
+ [ERANGE] = "ERANGE",
+ [EROFS] = "EROFS",
+ [ESPIPE] = "ESPIPE",
+ [ESRCH] = "ESRCH",
+ [ESTALE] = "ESTALE",
+ [ETIME] = "ETIME",
+ [ETIMEDOUT] = "ETIMEDOUT",
+ [ETXTBSY] = "ETXTBSY",
+ [EXDEV] = "EXDEV"
+};
+#endif
/*
* Explicitly cleanup the memory allocated to the error buffer,
*/
char const *fr_syserror(int num)
{
- char *buffer;
+ char *buffer, *p, *end;
int ret;
buffer = fr_thread_local_init(fr_syserror_buffer, _fr_logging_free);
}
}
- if (!num) {
- return "No error";
+ if (!num) return "No error";
+
+ p = buffer;
+ end = p + FR_STRERROR_BUFSIZE;
+
+#ifndef NDEBUG
+ /*
+ * Prefix system errors with the macro name and number
+ * if we're debugging.
+ */
+ if (num < (int)(sizeof(fr_errno_macro_names) / sizeof(*fr_errno_macro_names))) {
+ p += snprintf(p, end - p, "%s: ", fr_errno_macro_names[num]);
+ } else {
+ p += snprintf(p, end - p, "errno %i: ", num);
}
+ if (p >= end) return p;
+#endif
/*
* XSI-Compliant version
*/
#if !defined(HAVE_FEATURES_H) || !defined(__GLIBC__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 500) && ! _GNU_SOURCE)
- if ((ret = strerror_r(num, buffer, (size_t)FR_STRERROR_BUFSIZE) != 0)) {
+ ret = strerror_r(num, p, end - p);
+ if (ret != 0) {
# ifndef NDEBUG
fprintf(stderr, "strerror_r() failed to write error for errno %i to buffer %p (%zu bytes), "
"returned %i: %s\n", num, buffer, (size_t) FR_STRERROR_BUFSIZE, ret, strerror(ret));
*/
#else
{
- char const *p;
- p = strerror_r(num, buffer, (size_t)FR_STRERROR_BUFSIZE);
+ p = strerror_r(num, p, end - p);
if (!p) {
# ifndef NDEBUG
fprintf(stderr, "strerror_r() failed to write error for errno %i to buffer %p "
buffer[0] = '\0';
return buffer;
}
+
return p;
}
#endif