//error.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2011 * * This file is part of libroar a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * libroar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * NOTE for everyone want's to change something and send patches: * read README and HACKING! There a addition information on * the license of this document you need to read before you send * any patches. * * NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc * or libpulse*: * The libs libroaresd, libroararts and libroarpulse link this lib * and are therefore GPL. Because of this it may be illigal to use * them with any software that uses libesd, libartsc or libpulse*. */ #include "libroar.h" // 'no error' value for errno. // zero is true for GNU/Linux. // don't know about other systems. // IEEE Std 1003.1-2008 (POSIX 7) requires: // 'distinct positive values'. #define CLEAN_ERRNO 0 static int roar_errno = ROAR_ERROR_NONE; struct roar_error_frame * roar_err_errorframe(void) { static struct roar_error_frame frame = { .version = 0, .cmd = -1, .ra_errno = ROAR_ERROR_UNKNOWN, .ra_suberrno = -1, .p_errno = -1, .flags = 0, .datalen = 0, .data = NULL }; return &frame; } int roar_err_init(struct roar_error_frame * frame) { if ( frame == NULL ) { roar_err_set(ROAR_ERROR_FAULT); return -1; } memset(frame, 0, sizeof(struct roar_error_frame)); frame->cmd = -1; frame->ra_errno = ROAR_ERROR_UNKNOWN; frame->ra_suberrno = -1; frame->p_errno = -1; frame->datalen = 0; frame->data = NULL; return 0; } void * roar_err_buildmsg(struct roar_message * mes, void ** data, struct roar_error_frame * frame) { char * databuf = NULL; int16_t * d; size_t datalen; if ( mes == NULL || frame == NULL ) { roar_err_set(ROAR_ERROR_FAULT); return NULL; } if ( data != NULL ) *data = NULL; datalen = 8 + frame->datalen; if ( datalen > LIBROAR_BUFFER_MSGDATA ) { if ( data == NULL ) { roar_err_set(ROAR_ERROR_FAULT); return NULL; } roar_err_clear_errno(); *data = malloc(datalen); roar_err_from_errno(); if ( *data == NULL ) return NULL; databuf = *data; } else { databuf = mes->data; } memset(mes, 0, sizeof(struct roar_message)); memset(databuf, 0, mes->datalen); mes->datalen = datalen; d = (int16_t*)databuf; frame->data = &(databuf[8]); databuf[0] = 0; // version. databuf[1] = frame->cmd; databuf[2] = frame->ra_errno; databuf[3] = frame->ra_suberrno; d[2] = ROAR_HOST2NET16(frame->p_errno); d[3] = ROAR_HOST2NET16(frame->flags); return frame->data; } int roar_err_parsemsg(struct roar_message * mes, void * data, struct roar_error_frame * frame) { char * databuf = (char *)data; int16_t * d; ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?", mes, (int)mes->datalen, mes->data, data, frame); if ( mes == NULL || frame == NULL ) { roar_err_set(ROAR_ERROR_FAULT); ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = -1 // error=FAULT", mes, (int)mes->datalen, mes->data, data, frame); return -1; } ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?", mes, (int)mes->datalen, mes->data, data, frame); if ( databuf == NULL ) databuf = mes->data; d = (int16_t*)databuf; ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?", mes, (int)mes->datalen, mes->data, data, frame); if ( mes->datalen < 8 ) { roar_err_set(ROAR_ERROR_MSGSIZE); ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = -1 // error=MSGSIZE", mes, (int)mes->datalen, mes->data, data, frame); return -1; } ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?", mes, (int)mes->datalen, mes->data, data, frame); if ( databuf[0] != 0 ) { roar_err_set(ROAR_ERROR_NSVERSION); ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = -1 // error=NSVERSION", mes, (int)mes->datalen, mes->data, data, frame); return -1; } ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?", mes, (int)mes->datalen, mes->data, data, frame); frame->cmd = databuf[1]; frame->ra_errno = databuf[2]; frame->ra_suberrno = databuf[3]; frame->p_errno = ROAR_NET2HOST16(d[2]); frame->flags = ROAR_NET2HOST16(d[3]); frame->datalen = mes->datalen - 8; frame->data = &(databuf[8]); ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = 0", mes, (int)mes->datalen, mes->data, data, frame); return 0; } int * roar_errno2(void) { return &roar_errno; } void roar_err_clear(void) { *roar_errno2() = ROAR_ERROR_NONE; } void roar_err_clear_errno(void) { errno = CLEAN_ERRNO; } void roar_err_clear_all(void) { roar_err_clear(); roar_err_clear_errno(); } void roar_err_update(void) { int * err = roar_errno2(); // NOTE: _NEVER_ call ROAR_{DBG,INFO,WARN,ERR}() in here! (will result in endless loop) //printf("*err=%i, errno=%i\n", *err, (int)errno); if ( *err != ROAR_ERROR_NONE ) { roar_err_to_errno(); } else if ( !roar_err_is_errno_clear() ) { roar_err_from_errno(); } } int roar_err_is_errno_clear(void) { return errno == CLEAN_ERRNO ? 1 : 0; } void roar_err_set(const int error) { *roar_errno2() = error; } void roar_err_from_errno(void) { int _roar_errno = ROAR_ERROR_NONE; switch (errno) { #ifdef EACCES case EACCES: _roar_errno = ROAR_ERROR_PERM; break; #endif #ifdef EPERM case EPERM: _roar_errno = ROAR_ERROR_PERM; break; #endif #ifdef ENOENT case ENOENT: _roar_errno = ROAR_ERROR_NOENT; break; #endif #ifdef EBADMSG case EBADMSG: _roar_errno = ROAR_ERROR_BADMSG; break; #endif #ifdef EBUSY case EBUSY: _roar_errno = ROAR_ERROR_BUSY; break; #endif #ifdef ECONNREFUSED case ECONNREFUSED: _roar_errno = ROAR_ERROR_CONNREFUSED; break; #endif #ifdef ENOSYS case ENOSYS: _roar_errno = ROAR_ERROR_NOSYS; break; #endif #ifdef ENOTSUP case ENOTSUP: _roar_errno = ROAR_ERROR_NOTSUP; break; #endif #ifdef EPIPE case EPIPE: _roar_errno = ROAR_ERROR_PIPE; break; #endif #ifdef EPROTO case EPROTO: _roar_errno = ROAR_ERROR_PROTO; break; #endif #ifdef ERANGE case ERANGE: _roar_errno = ROAR_ERROR_RANGE; break; #endif #ifdef EMSGSIZE case EMSGSIZE: _roar_errno = ROAR_ERROR_MSGSIZE; break; #endif #ifdef ENOMEM case ENOMEM: _roar_errno = ROAR_ERROR_NOMEM; break; #endif #ifdef EINVAL case EINVAL: _roar_errno = ROAR_ERROR_INVAL; break; #endif #ifdef EALREADY case EALREADY: _roar_errno = ROAR_ERROR_ALREADY; break; #endif #ifdef EBADRQC case EBADRQC: _roar_errno = ROAR_ERROR_BADRQC; break; #endif #ifdef EDOM case EDOM: _roar_errno = ROAR_ERROR_DOM; break; #endif #ifdef EEXIST case EEXIST: _roar_errno = ROAR_ERROR_EXIST; break; #endif #ifdef EFAULT case EFAULT: _roar_errno = ROAR_ERROR_FAULT; break; #endif #ifdef EIO case EIO: _roar_errno = ROAR_ERROR_IO; break; #endif #ifdef EREMOTEIO case EREMOTEIO: _roar_errno = ROAR_ERROR_RIO; break; #endif #ifdef EKEYEXPIRED case EKEYEXPIRED: _roar_errno = ROAR_ERROR_KEYEXPIRED; break; #endif #ifdef EKEYREJECTED case EKEYREJECTED: _roar_errno = ROAR_ERROR_KEYREJECTED; break; #endif #ifdef ELOOP case ELOOP: _roar_errno = ROAR_ERROR_LOOP; break; #endif #ifdef EMFILE case EMFILE: _roar_errno = ROAR_ERROR_MFILE; break; #endif #ifdef ENAMETOOLONG case ENAMETOOLONG: _roar_errno = ROAR_ERROR_NAMETOOLONG; break; #endif #ifdef ENODATA case ENODATA: _roar_errno = ROAR_ERROR_NODATA; break; #endif #ifdef ENODEV case ENODEV: _roar_errno = ROAR_ERROR_NODEV; break; #endif #ifdef ENOSPC case ENOSPC: _roar_errno = ROAR_ERROR_NOSPC; break; #endif #ifdef ENOTCONN case ENOTCONN: _roar_errno = ROAR_ERROR_NOTCONN; break; #endif #ifdef EPROTONOSUPPORT case EPROTONOSUPPORT: _roar_errno = ROAR_ERROR_PROTONOSUP; break; #endif #ifdef EROFS case EROFS: _roar_errno = ROAR_ERROR_RO; break; #endif #ifdef ETIMEDOUT case ETIMEDOUT: _roar_errno = ROAR_ERROR_TIMEDOUT; break; #endif #ifdef EAGAIN case EAGAIN: _roar_errno = ROAR_ERROR_AGAIN; break; #endif #ifdef ENETDOWN case ENETDOWN: _roar_errno = ROAR_ERROR_LINKDOWN; break; #endif #ifdef EINTR case EINTR: _roar_errno = ROAR_ERROR_INTERRUPTED; break; #endif #ifdef EDQUOT case EDQUOT: _roar_errno = ROAR_ERROR_QUOTA; break; #endif #ifdef ELIBBAD case ELIBBAD: _roar_errno = ROAR_ERROR_BADLIB; break; #endif #ifdef ENOMEDIUM case ENOMEDIUM: _roar_errno = ROAR_ERROR_NOMEDIUM; break; #endif #ifdef ENOTUNIQ case ENOTUNIQ: _roar_errno = ROAR_ERROR_NOTUNIQ; break; #endif #ifdef EILSEQ case EILSEQ: _roar_errno = ROAR_ERROR_ILLSEQ; break; #endif #ifdef EADDRINUSE case EADDRINUSE: _roar_errno = ROAR_ERROR_ADDRINUSE; break; #endif #ifdef ESPIPE case ESPIPE: _roar_errno = ROAR_ERROR_BADSEEK; break; #endif #ifdef ECHERNOBYL case ECHERNOBYL: _roar_errno = ROAR_ERROR_CHERNOBYL; break; #endif #ifdef ECRAY case ECRAY: _roar_errno = ROAR_ERROR_CAUSALITY; break; #endif #ifdef ENOHORSE case ENOHORSE: _roar_errno = ROAR_ERROR_NOHORSE; break; #endif #ifdef ETXTBSY case ETXTBSY: _roar_errno = ROAR_ERROR_TEXTBUSY; break; #endif #ifdef ENOTEMPTY case ENOTEMPTY: _roar_errno = ROAR_ERROR_NOTEMPTY; break; #endif #ifdef EHOSTUNREACH case EHOSTUNREACH: _roar_errno = ROAR_ERROR_NODEUNREACH; break; #endif #ifdef EIDRM case EIDRM: _roar_errno = ROAR_ERROR_IDREMOVED; break; #endif #ifdef EINPROGRESS case EINPROGRESS: _roar_errno = ROAR_ERROR_INPROGRESS; break; #endif #ifdef ECHILD case ECHILD: _roar_errno = ROAR_ERROR_NOCHILD; break; #endif #ifdef ENETUNREACH case ENETUNREACH: _roar_errno = ROAR_ERROR_NETUNREACH; break; #endif #ifdef ECANCELED case ECANCELED: _roar_errno = ROAR_ERROR_CANCELED; break; #endif #ifdef EISDIR case EISDIR: _roar_errno = ROAR_ERROR_ISDIR; break; #endif #ifdef ENOTDIR case ENOTDIR: _roar_errno = ROAR_ERROR_NOTDIR; break; #endif #ifdef ENOEXEC case ENOEXEC: _roar_errno = ROAR_ERROR_BADEXEC; break; #endif #ifdef EISCONN case EISCONN: _roar_errno = ROAR_ERROR_ISCONN; break; #endif #ifdef EDEADLK case EDEADLK: _roar_errno = ROAR_ERROR_DEADLOCK; break; #endif #ifdef ECONNRESET case ECONNRESET: _roar_errno = ROAR_ERROR_CONNRST; break; #endif #ifdef EBADF case EBADF: _roar_errno = ROAR_ERROR_BADFH; break; #endif #ifdef ENOTSOCK case ENOTSOCK: _roar_errno = ROAR_ERROR_NOTSOCK; break; #endif #ifdef E2BIG case E2BIG: _roar_errno = ROAR_ERROR_TOOMANYARGS; break; #endif #ifdef EFBIG case EFBIG: _roar_errno = ROAR_ERROR_TOOLARGE; break; #endif #ifdef EDESTADDRREQ case EDESTADDRREQ: _roar_errno = ROAR_ERROR_DESTADDRREQ; break; #endif #ifdef EAFNOSUPPORT case EAFNOSUPPORT: _roar_errno = ROAR_ERROR_AFNOTSUP; break; #endif #ifdef ENFILE case ENFILE: _roar_errno = ROAR_ERROR_NFILE; break; #endif #ifdef ESTALE case ESTALE: _roar_errno = ROAR_ERROR_STALE; break; #endif #ifdef EXDEV case EXDEV: _roar_errno = ROAR_ERROR_XDEVLINK; break; #endif #ifdef EMLINK case EMLINK: _roar_errno = ROAR_ERROR_MLINK; break; #endif #ifdef ENONET case ENONET: _roar_errno = ROAR_ERROR_NONET; break; #endif #ifdef ENETRESET case ENETRESET: _roar_errno = ROAR_ERROR_CONNRSTNET; break; #endif #ifdef ECONNABORTED case ECONNABORTED: _roar_errno = ROAR_ERROR_CONNABORTED; break; #endif default: _roar_errno = ROAR_ERROR_UNKNOWN; break; } roar_err_set(_roar_errno); } void roar_err_to_errno(void) { int * err = roar_errno2(); switch (*err) { case ROAR_ERROR_NONE: roar_err_clear_errno(); break; #ifdef EPERM case ROAR_ERROR_PERM: errno = EPERM; break; #endif #ifdef ENOENT case ROAR_ERROR_NOENT: errno = ENOENT; break; #endif #ifdef EBADMSG case ROAR_ERROR_BADMSG: errno = EBADMSG; break; #endif #ifdef EBUSY case ROAR_ERROR_BUSY: errno = EBUSY; break; #endif #ifdef ECONNREFUSED case ROAR_ERROR_CONNREFUSED: errno = ECONNREFUSED; break; #endif #ifdef ENOSYS case ROAR_ERROR_NOSYS: errno = ENOSYS; break; #endif #ifdef ENOTSUP case ROAR_ERROR_NOTSUP: errno = ENOTSUP; break; #endif #ifdef EPIPE case ROAR_ERROR_PIPE: errno = EPIPE; break; #endif #ifdef EPROTO case ROAR_ERROR_PROTO: errno = EPROTO; break; #endif #ifdef ERANGE case ROAR_ERROR_RANGE: errno = ERANGE; break; #endif #ifdef EMSGSIZE case ROAR_ERROR_MSGSIZE: errno = EMSGSIZE; break; #endif #ifdef ENOMEM case ROAR_ERROR_NOMEM: errno = ENOMEM; break; #endif #ifdef EINVAL case ROAR_ERROR_INVAL: errno = EINVAL; break; #endif #ifdef EALREADY case ROAR_ERROR_ALREADY: errno = EALREADY; break; #endif #ifdef EBADRQC case ROAR_ERROR_BADRQC: errno = EBADRQC; break; #endif #ifdef EDOM case ROAR_ERROR_DOM: errno = EDOM; break; #endif #ifdef EEXIST case ROAR_ERROR_EXIST: errno = EEXIST; break; #endif #ifdef EFAULT case ROAR_ERROR_FAULT: errno = EFAULT; break; #endif #if defined(EREMOTEIO) || defined(EIO) case ROAR_ERROR_RIO: #ifdef EREMOTEIO errno = EREMOTEIO; #else errno = EIO; #endif break; #endif #ifdef EIO case ROAR_ERROR_IO: case ROAR_ERROR_HOLE: case ROAR_ERROR_BADCKSUM: case ROAR_ERROR_LOSTSYNC: case ROAR_ERROR_NOHORSE: errno = EIO; break; #endif #ifdef EKEYEXPIRED case ROAR_ERROR_KEYEXPIRED: errno = EKEYEXPIRED; break; #endif #ifdef EKEYREJECTED case ROAR_ERROR_KEYREJECTED: errno = EKEYREJECTED; break; #endif #ifdef ELOOP case ROAR_ERROR_LOOP: errno = ELOOP; break; #endif #ifdef EMFILE case ROAR_ERROR_MFILE: errno = EMFILE; break; #endif #ifdef ENAMETOOLONG case ROAR_ERROR_NAMETOOLONG: errno = ENAMETOOLONG; break; #endif #ifdef ENODATA case ROAR_ERROR_NODATA: errno = ENODATA; break; #endif #ifdef ENODEV case ROAR_ERROR_NODEV: case ROAR_ERROR_NODRV: errno = ENODEV; break; #endif #ifdef ENOSPC case ROAR_ERROR_NOSPC: errno = ENOSPC; break; #endif #ifdef EINVAL case ROAR_ERROR_TYPEMM: errno = EINVAL; break; #endif #ifdef ENOSYS case ROAR_ERROR_NORSYS: errno = ENOSYS; break; #endif #ifdef ENOTCONN case ROAR_ERROR_NOTCONN: errno = ENOTCONN; break; #endif #ifdef EPROTONOSUPPORT case ROAR_ERROR_PROTONOSUP: errno = EPROTONOSUPPORT; break; #endif #ifdef EROFS case ROAR_ERROR_RO: errno = EROFS; break; #endif #ifdef ETIMEDOUT case ROAR_ERROR_TIMEDOUT: errno = ETIMEDOUT; break; #endif #ifdef EAGAIN case ROAR_ERROR_AGAIN: errno = EAGAIN; break; #endif #ifdef ENETDOWN case ROAR_ERROR_LINKDOWN: errno = ENETDOWN; break; #endif #ifdef EINTR case ROAR_ERROR_INTERRUPTED: errno = EINTR; break; #endif #ifdef EDQUOT case ROAR_ERROR_QUOTA: errno = EDQUOT; break; #endif #ifdef ELIBBAD case ROAR_ERROR_BADLIB: errno = ELIBBAD; break; #endif #ifdef ENOMEDIUM case ROAR_ERROR_NOMEDIUM: errno = ENOMEDIUM; break; #endif #ifdef ENOTUNIQ case ROAR_ERROR_NOTUNIQ: errno = ENOTUNIQ; break; #endif #ifdef EILSEQ case ROAR_ERROR_ILLSEQ: errno = EILSEQ; break; #endif #ifdef EADDRINUSE case ROAR_ERROR_ADDRINUSE: errno = EADDRINUSE; break; #endif #ifdef ESPIPE case ROAR_ERROR_BADSEEK: case ROAR_ERROR_NOSEEK: errno = ESPIPE; break; #endif #ifdef ECHERNOBYL case ROAR_ERROR_CHERNOBYL: errno = ECHERNOBYL; break; #endif #ifdef ECRAY case ROAR_ERROR_CAUSALITY: errno = ECRAY; break; #endif #ifdef ENOHORSE case ROAR_ERROR_NOHORSE: errno = ENOHORSE; break; #endif #ifdef ETXTBSY case ROAR_ERROR_TEXTBUSY: errno = ETXTBSY; break; #endif #ifdef ENOTEMPTY case ROAR_ERROR_NOTEMPTY: errno = ENOTEMPTY; break; #endif #ifdef EHOSTUNREACH case ROAR_ERROR_NODEUNREACH: errno = EHOSTUNREACH; break; #endif #ifdef EIDRM case ROAR_ERROR_IDREMOVED: errno = EIDRM; break; #endif #ifdef EINPROGRESS case ROAR_ERROR_INPROGRESS: errno = EINPROGRESS; break; #endif #ifdef ECHILD case ROAR_ERROR_NOCHILD: errno = ECHILD; break; #endif #ifdef ENETUNREACH case ROAR_ERROR_NETUNREACH: errno = ENETUNREACH; break; #endif #ifdef ECANCELED case ROAR_ERROR_CANCELED: errno = ECANCELED; break; #endif #ifdef EISDIR case ROAR_ERROR_ISDIR: errno = EISDIR; break; #endif #ifdef ENOTDOR case ROAR_ERROR_NOTDIR: errno = ENOTDIR; break; #endif #ifdef ENOEXEC case ROAR_ERROR_BADEXEC: errno = ENOEXEC; break; #endif #ifdef EISCONN case ROAR_ERROR_ISCONN: errno = EISCONN; break; #endif #ifdef EDEADLK case ROAR_ERROR_DEADLOCK: errno = EDEADLK; break; #endif #ifdef ECONNRESET case ROAR_ERROR_CONNRST: errno = ECONNRESET; break; #endif #ifdef EBADF case ROAR_ERROR_BADFH: errno = EBADF; break; #endif #ifdef ENOTSOCK case ROAR_ERROR_NOTSOCK: errno = ENOTSOCK; break; #endif #ifdef E2BIG case ROAR_ERROR_TOOMANYARGS: errno = E2BIG; break; #endif #ifdef EFBIG case ROAR_ERROR_TOOLARGE: errno = EFBIG; break; #endif #ifdef EDESTADDRREQ case ROAR_ERROR_DESTADDRREQ: errno = EDESTADDRREQ; break; #endif #ifdef EAFNOSUPPORT case ROAR_ERROR_AFNOTSUP: errno = EAFNOSUPPORT; break; #endif // FIXME.... #ifdef ENOPOWER case ROAR_ERROR_NOPOWER: errno = ENOPOWER; break; #endif #ifdef EUSER case ROAR_ERROR_USER: errno = EUSER; break; #endif #ifdef ENFILE case ROAR_ERROR_NFILE: errno = ENFILE; break; #endif #ifdef ESTALE case ROAR_ERROR_STALE: errno = ESTALE; break; #endif #ifdef EXDEV case ROAR_ERROR_XDEVLINK: errno = EXDEV; break; #endif #ifdef EMLINK case ROAR_ERROR_MLINK: errno = EMLINK; break; #endif #ifdef ENONET case ROAR_ERROR_NONET: errno = ENONET; break; #endif #ifdef ENETRESET case ROAR_ERROR_CONNRSTNET: errno = ENETRESET; break; #endif #ifdef ECONNABORTED case ROAR_ERROR_CONNABORTED: errno = ECONNABORTED; break; #endif default: #ifdef EINVAL errno = EINVAL; #else errno = -1; // just guess #endif break; } } // store a error state (both libroar and system) int roar_err_store(struct roar_error_state * state) { if ( state == NULL ) return ROAR_ERROR_FAULT; memset(state, 0, sizeof(struct roar_error_state)); state->refc = 0; state->libroar_error = roar_error; state->system_error = errno; #ifdef ROAR_TARGET_WIN32 state->winsock_error = WSAGetLastError(); #endif #ifdef ROAR_HAVE_VAR_H_ERRNO state->syssock_herror = h_errno; #endif #ifdef __YIFF__ state->yiffc_error = yiffc_error; #endif return ROAR_ERROR_NONE; } // restore error state to values at time of call to roar_err_store() int roar_err_restore(struct roar_error_state * state) { if ( state == NULL ) return ROAR_ERROR_FAULT; roar_err_set(state->libroar_error); errno = state->system_error; #ifdef ROAR_TARGET_WIN32 WSASetLastError(state->winsock_error); #endif #ifdef ROAR_HAVE_VAR_H_ERRNO h_errno = state->syssock_herror; #endif #ifdef __YIFF__ yiffc_error = state->yiffc_error; #endif return ROAR_ERROR_NONE; } // phi@ph7:roaraudio $ grep '^#define ROAR_ERROR_' error.h | tr -d /\* | while read d c d t; do printf " {%-23s \"%s\"},\n" $c, "$t"; done static const char * roar_error2str_ms(const int error, const char * msg) { static char buf[1024] = ""; int num[8]; size_t i; int _ra_err = roar_error; int _sys_err = errno; for (i = 0; i < (sizeof(num)/sizeof(*num)); i++) num[i] = roar_random_uint32(); snprintf(buf, sizeof(buf), "\e[44;39;1m\e[2J\e[H" " RoarAudio\n" "\n\n" "Fatal error %.4x: %s\n" "RA Error: %.4i, Sys Error: %.4i (%s)\n" "Random numbers:\n" " A: 0x%.8X B: 0x%.8X\n" " C: 0x%.8X D: 0x%.8X\n" " E: 0x%.8X F: 0x%.8X\n" " G: 0x%.8X H: 0x%.8X\n" "\n\n" "\e[0m", error, msg, _ra_err, _sys_err, strerror(_sys_err), num[0], num[1], num[2], num[3], num[4], num[5], num[6], num[7]); return buf; } const char * roar_error2str(const int error) { struct roar_libroar_config * config = roar_libroar_get_config(); const struct { const int err; const char * msg; } msgs[] = { {ROAR_ERROR_NONE, "No error"}, {ROAR_ERROR_PERM, "Operation not permitted"}, {ROAR_ERROR_NOENT, "No such object, file, directory or node"}, {ROAR_ERROR_BADMSG, "Bad message"}, {ROAR_ERROR_BUSY, "Device or resource busy"}, {ROAR_ERROR_CONNREFUSED, "Connection refused"}, {ROAR_ERROR_NOSYS, "Function not implemented"}, {ROAR_ERROR_NOTSUP, "Operation not supported"}, {ROAR_ERROR_PIPE, "Broken pipe"}, {ROAR_ERROR_PROTO, "Protocol error"}, {ROAR_ERROR_RANGE, "Result too large or parameter out of range"}, {ROAR_ERROR_MSGSIZE, "Message too long"}, {ROAR_ERROR_NOMEM, "Not enough space"}, {ROAR_ERROR_INVAL, "Invalid argument"}, {ROAR_ERROR_ALREADY, "Connection already in progress"}, {ROAR_ERROR_BADRQC, "Invalid request code"}, {ROAR_ERROR_DOM, "Mathematics argument out of domain of function"}, {ROAR_ERROR_EXIST, "File or object exists"}, {ROAR_ERROR_FAULT, "Bad address"}, {ROAR_ERROR_IO, "I/O-Error"}, {ROAR_ERROR_KEYEXPIRED, "Key has expired"}, {ROAR_ERROR_KEYREJECTED, "Key was rejected by service"}, {ROAR_ERROR_LOOP, "Too many recursions"}, {ROAR_ERROR_MFILE, "Too many open files or objects"}, {ROAR_ERROR_NAMETOOLONG, "File or object name too long"}, {ROAR_ERROR_NODATA, "No message is available on the read queue"}, {ROAR_ERROR_NODEV, "No such device"}, {ROAR_ERROR_NODRV, "No such driver"}, {ROAR_ERROR_NOSPC, "No space left on device"}, {ROAR_ERROR_TYPEMM, "Type missmatch. Object of diffrent type required"}, {ROAR_ERROR_NORSYS, "Feature not implemented by remote end"}, {ROAR_ERROR_NOTCONN, "Socket or object not connected"}, {ROAR_ERROR_PROTONOSUP, "Protocol not supported"}, {ROAR_ERROR_RIO, "Remote I/O Error"}, {ROAR_ERROR_RO, "File or object is read only"}, {ROAR_ERROR_TIMEDOUT, "Connection timed out"}, {ROAR_ERROR_AGAIN, "Resource temporarily unavailable"}, {ROAR_ERROR_NOISE, "Line too noisy"}, {ROAR_ERROR_LINKDOWN, "Physical or logical link down"}, {ROAR_ERROR_INTERRUPTED, "Operation was interruped"}, {ROAR_ERROR_CAUSALITY, "Causality error"}, {ROAR_ERROR_QUOTA, "Quota exceeded"}, {ROAR_ERROR_BADLIB, "Accessing a corrupted shared library"}, {ROAR_ERROR_NOMEDIUM, "No medium found"}, {ROAR_ERROR_NOTUNIQ, "Name not unique"}, {ROAR_ERROR_ILLSEQ, "Illegal byte sequence"}, {ROAR_ERROR_ADDRINUSE, "Address in use"}, {ROAR_ERROR_HOLE, "Hole in data"}, {ROAR_ERROR_BADVERSION, "Bad version"}, {ROAR_ERROR_NSVERSION, "Not supported version"}, {ROAR_ERROR_BADMAGIC, "Bad magic number"}, {ROAR_ERROR_LOSTSYNC, "Lost synchronization"}, {ROAR_ERROR_BADSEEK, "Can not seek to destination position"}, {ROAR_ERROR_NOSEEK, "Seeking not supported on resource"}, {ROAR_ERROR_BADCKSUM, "Data integrity error"}, {ROAR_ERROR_NOHORSE, "Mount failed"}, {ROAR_ERROR_CHERNOBYL, "Fatal device error"}, {ROAR_ERROR_NOHUG, "Device needs love"}, {ROAR_ERROR_TEXTBUSY, "Text file busy"}, {ROAR_ERROR_NOTEMPTY, "Directory not empty"}, {ROAR_ERROR_NODEUNREACH, "Node is unreachable"}, {ROAR_ERROR_IDREMOVED, "Identifier removed"}, {ROAR_ERROR_INPROGRESS, "Operation in progress"}, {ROAR_ERROR_NOCHILD, "No child processes or object"}, {ROAR_ERROR_NETUNREACH, "Network unreachable"}, {ROAR_ERROR_CANCELED, "Operation canceled"}, {ROAR_ERROR_ISDIR, "Is a directory"}, {ROAR_ERROR_NOTDIR, "Not a directory"}, {ROAR_ERROR_BADEXEC, "Executable file format error"}, {ROAR_ERROR_ISCONN, "Socket or Object is connected"}, {ROAR_ERROR_DEADLOCK, "Resource deadlock would occur"}, {ROAR_ERROR_CONNRST, "Connection reset"}, {ROAR_ERROR_BADFH, "Bad file handle"}, {ROAR_ERROR_NOTSOCK, "Not a socket"}, {ROAR_ERROR_TOOMANYARGS, "Argument list too long"}, {ROAR_ERROR_TOOLARGE, "File or Object too large"}, {ROAR_ERROR_DESTADDRREQ, "Destination address required"}, {ROAR_ERROR_AFNOTSUP, "Address family not supported"}, {ROAR_ERROR_NOPOWER, "Operation can not be completed because we are low on power"}, {ROAR_ERROR_USER, "Error in front of screen"}, {ROAR_ERROR_NFILE, "Too many filesobjects open in system"}, {ROAR_ERROR_STALE, "Stale file handle or object"}, {ROAR_ERROR_XDEVLINK, "Cross-device link"}, {ROAR_ERROR_MLINK, "Too many links to file or object"}, {ROAR_ERROR_NONET, "Not connected to any network"}, {ROAR_ERROR_CONNRSTNET, "Connection reset by network"}, {ROAR_ERROR_CONNABORTED, "Connection aborted"}, {-1, NULL} }, msgs_funny[] = { // {ROAR_ERROR_UNKNOWN, "Unknown (maybe no) error"}, {ROAR_ERROR_NONE, "No error, huh?"}, {ROAR_ERROR_PERM, "Little kitty is not allowed to do this"}, {ROAR_ERROR_NOENT, "Mouse not found"}, // {ROAR_ERROR_BADMSG, "Bad message"}, {ROAR_ERROR_BUSY, "Another kitty is playing with this mouse"}, // {ROAR_ERROR_CONNREFUSED, "Connection refused"}, // {ROAR_ERROR_NOSYS, "Function not implemented"}, // {ROAR_ERROR_NOTSUP, "Operation not supported"}, {ROAR_ERROR_PIPE, "Flood"}, // {ROAR_ERROR_PROTO, "Protocol error"}, // {ROAR_ERROR_RANGE, "Result too largegeneral out of range"}, // {ROAR_ERROR_MSGSIZE, "Message too long"}, // {ROAR_ERROR_NOMEM, "Not enough space"}, // {ROAR_ERROR_INVAL, "Invalid argument"}, // {ROAR_ERROR_ALREADY, "Connection already in progress"}, {ROAR_ERROR_BADRQC, "Stupid staff"}, // {ROAR_ERROR_DOM, "Mathematics argument out of domain of function"}, // {ROAR_ERROR_EXIST, "File or object exists"}, // {ROAR_ERROR_FAULT, "Bad address"}, // {ROAR_ERROR_IO, "IO-Error"}, // {ROAR_ERROR_KEYEXPIRED, "Key has expired"}, // {ROAR_ERROR_KEYREJECTED, "Key was rejected by service"}, // {ROAR_ERROR_LOOP, "Too many recursions"}, // {ROAR_ERROR_MFILE, "Too many open files or objects"}, {ROAR_ERROR_NAMETOOLONG, "Staff can not remember long names"}, // {ROAR_ERROR_NODATA, "No message is available on the read queue"}, {ROAR_ERROR_NODEV, "No such mouse"}, // {ROAR_ERROR_NODRV, "No such driver"}, {ROAR_ERROR_NOSPC, "Too many fish on desk"}, // {ROAR_ERROR_TYPEMM, "Type missmatch. Object of diffrent type required"}, // {ROAR_ERROR_NORSYS, "Feature not implemented by remote end"}, // {ROAR_ERROR_NOTCONN, "Socket or object not connected"}, // {ROAR_ERROR_PROTONOSUP, "Protocol not supported"}, // {ROAR_ERROR_RIO, "Remote IO Error"}, {ROAR_ERROR_RO, "Touching disallowed"}, // {ROAR_ERROR_TIMEDOUT, "Connection timed out"}, // {ROAR_ERROR_AGAIN, "Resource temporarily unavailable"}, // {ROAR_ERROR_NOISE, "Line too noisy"}, // {ROAR_ERROR_LINKDOWN, "Physical or logical link down"}, // {ROAR_ERROR_INTERRUPTED, "Operation was interruped"}, // {ROAR_ERROR_CAUSALITY, "Causality error"}, // {ROAR_ERROR_QUOTA, "Quota exceeded"}, // {ROAR_ERROR_BADLIB, "Accessing a corrupted shared library"}, // {ROAR_ERROR_NOMEDIUM, "No medium found"}, // {ROAR_ERROR_NOTUNIQ, "Name not unique"}, // {ROAR_ERROR_ILLSEQ, "Illegal byte sequence"}, // {ROAR_ERROR_ADDRINUSE, "Address in use"}, {ROAR_ERROR_HOLE, "Hole in wall"}, // {ROAR_ERROR_BADVERSION, "Bad version"}, // {ROAR_ERROR_NSVERSION, "Not supported version"}, {ROAR_ERROR_BADMAGIC, "Magician's fault"}, // {ROAR_ERROR_LOSTSYNC, "Lost synchronization"}, // {ROAR_ERROR_BADSEEK, "Can not seek to destination position"}, // {ROAR_ERROR_NOSEEK, "Seeking not supported on resource"}, // {ROAR_ERROR_BADCKSUM, "Data integrity error"}, {ROAR_ERROR_NOHORSE, "No horse"}, // {ROAR_ERROR_CHERNOBYL, "Fatal device error"}, {ROAR_ERROR_NOHUG, "No hug"}, // {ROAR_ERROR_TEXTBUSY, "Text file busy"}, // {ROAR_ERROR_NOTEMPTY, "Directory not empty"}, // {ROAR_ERROR_NODEUNREACH, "Node is unreachable"}, // {ROAR_ERROR_IDREMOVED, "Identifier removed"}, // {ROAR_ERROR_INPROGRESS, "Operation in progress"}, // {ROAR_ERROR_NOCHILD, "No child processesobject"}, // {ROAR_ERROR_NETUNREACH, "Network unreachable"}, // {ROAR_ERROR_CANCELED, "Operation canceled"}, // {ROAR_ERROR_ISDIR, "Is a directory"}, // {ROAR_ERROR_NOTDIR, "Not a directory"}, // {ROAR_ERROR_BADEXEC, "Executable file format error"}, // {ROAR_ERROR_ISCONN, "Socket/Object is connected"}, {ROAR_ERROR_DEADLOCK, "Mouse would die"}, // {ROAR_ERROR_CONNRST, "Connection reset"}, // {ROAR_ERROR_BADFH, "Bad file handle"}, // {ROAR_ERROR_NOTSOCK, "Not a socket"}, // {ROAR_ERROR_TOOMANYARGS, "Argument list too long"}, // {ROAR_ERROR_TOOLARGE, "File/Object too large"}, // {ROAR_ERROR_DESTADDRREQ, "Destination address required"}, // {ROAR_ERROR_AFNOTSUP, "Address family not supported"}, // {ROAR_ERROR_NOPOWER, "Operation can not be completed because we are low on power"}, // {ROAR_ERROR_USER, "Error in front of screen"}, // {ROAR_ERROR_NFILE, "Too many filesobjects open in system"}, // {ROAR_ERROR_STALE, "Stale file handle or object"}, {ROAR_ERROR_XDEVLINK, "Mice tails too short for kinking"}, // {ROAR_ERROR_MLINK, "Too many links to file or object"}, // {ROAR_ERROR_NONET, "Not connected to any network"}, // {ROAR_ERROR_CONNRSTNET, "Connection reset by network"}, // {ROAR_ERROR_CONNABORTED, "Connection aborted"}, {-1, NULL} }; int i; if ( config->opmode == ROAR_LIBROAR_CONFIG_OPMODE_MS ) for (i = 0; msgs[i].msg != NULL; i++) if ( msgs[i].err == error ) return roar_error2str_ms(error, msgs[i].msg); if ( config->opmode == ROAR_LIBROAR_CONFIG_OPMODE_FUNNY ) for (i = 0; msgs_funny[i].msg != NULL; i++) if ( msgs_funny[i].err == error ) return msgs_funny[i].msg; for (i = 0; msgs[i].msg != NULL; i++) if ( msgs[i].err == error ) return msgs[i].msg; return NULL; } //ll