//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 int roar_errno = ROAR_ERROR_NONE; int roar_err_int(struct roar_error_frame * frame) { if ( frame == NULL ) return -1; memset(frame, 0, sizeof(struct roar_error_frame)); frame->cmd = -1; frame->ra_errno = -1; frame->ra_suberrno = -1; frame->p_errno = -1; return 0; } void * roar_err_buildmsg(struct roar_message * mes, struct roar_error_frame * frame) { int16_t * d; if ( mes == NULL || frame == NULL ) return NULL; memset(mes, 0, sizeof(struct roar_message)); d = (int16_t*)mes->data; mes->datalen = 8 + frame->datalen; frame->data = &(mes->data[8]); mes->data[0] = 0; // version. mes->data[1] = frame->cmd; mes->data[2] = frame->ra_errno; mes->data[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, struct roar_error_frame * frame) { int16_t * d; if ( mes == NULL || frame == NULL ) return -1; d = (int16_t*)mes->data; if ( mes->datalen < 8 ) return -1; if ( mes->data[0] != 0 ) return -1; frame->cmd = mes->data[1]; frame->ra_errno = mes->data[2]; frame->ra_suberrno = mes->data[3]; frame->p_errno = ROAR_NET2HOST16(d[2]); frame->flags = ROAR_NET2HOST16(d[3]); frame->datalen = mes->datalen - 8; frame->data = &(mes->data[8]); 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,ERRO}() 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_clean() ) { roar_err_from_errno(); } } int roar_err_is_errno_clean(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 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 default: #ifdef EINVAL errno = EINVAL; #else errno = -1; // just guess #endif break; } } // 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 const char * roar_error2str(const int error) { 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 or directory"}, {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"}, {-1, NULL} }; int i; for (i = 0; msgs[i].msg != NULL; i++) if ( msgs[i].err == error ) return msgs[i].msg; return NULL; } //ll