| /**************************************************************************** |
| * libs/libc/string/lib_strerror.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| #define STRERROR_UNKNOWN "Unknown error" |
| #define STRERROR_BUFSIZE sizeof(STRERROR_UNKNOWN " 2000") |
| |
| /**************************************************************************** |
| * Private Types |
| ****************************************************************************/ |
| |
| struct errno_strmap_s |
| { |
| uint8_t errnum; |
| FAR char *str; |
| }; |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| #ifdef CONFIG_LIBC_STRERROR |
| |
| /* This table maps all error numbers to descriptive strings. |
| * The only assumption that the code makes with regard to this |
| * this table is that it is ordered by error number. |
| * |
| * The size of this table is quite large. Its size can be |
| * reduced by eliminating some of the more obscure error |
| * strings. |
| */ |
| |
| #ifndef CONFIG_LIBC_STRERROR_SHORT |
| |
| static const struct errno_strmap_s g_errnomap[] = |
| { |
| { 0, "Success" }, |
| { EPERM, EPERM_STR }, |
| { ENOENT, ENOENT_STR }, |
| { ESRCH, ESRCH_STR }, |
| { EINTR, EINTR_STR }, |
| { EIO, EIO_STR }, |
| { ENXIO, ENXIO_STR }, |
| { E2BIG, E2BIG_STR }, |
| { ENOEXEC, ENOEXEC_STR }, |
| { EBADF, EBADF_STR }, |
| { ECHILD, ECHILD_STR }, |
| { EAGAIN, EAGAIN_STR }, |
| { ENOMEM, ENOMEM_STR }, |
| { EACCES, EACCES_STR }, |
| { EFAULT, EFAULT_STR }, |
| { ENOTBLK, ENOTBLK_STR }, |
| { EBUSY, EBUSY_STR }, |
| { EEXIST, EEXIST_STR }, |
| { EXDEV, EXDEV_STR }, |
| { ENODEV, ENODEV_STR }, |
| { ENOTDIR, ENOTDIR_STR }, |
| { EISDIR, EISDIR_STR }, |
| { EINVAL, EINVAL_STR }, |
| { ENFILE, ENFILE_STR }, |
| { EMFILE, EMFILE_STR }, |
| { ENOTTY, ENOTTY_STR }, |
| { ETXTBSY, ETXTBSY_STR }, |
| { EFBIG, EFBIG_STR }, |
| { ENOSPC, ENOSPC_STR }, |
| { ESPIPE, ESPIPE_STR }, |
| { EROFS, EROFS_STR }, |
| { EMLINK, EMLINK_STR }, |
| { EPIPE, EPIPE_STR }, |
| { EDOM, EDOM_STR }, |
| { ERANGE, ERANGE_STR }, |
| { EDEADLK, EDEADLK_STR }, |
| { ENAMETOOLONG, ENAMETOOLONG_STR }, |
| { ENOLCK, ENOLCK_STR }, |
| { ENOSYS, ENOSYS_STR }, |
| { ENOTEMPTY, ENOTEMPTY_STR }, |
| { ELOOP, ELOOP_STR }, |
| { ENOMSG, ENOMSG_STR }, |
| { EIDRM, EIDRM_STR }, |
| { ECHRNG, ECHRNG_STR }, |
| { EL2NSYNC, EL2NSYNC_STR }, |
| { EL3HLT, EL3HLT_STR }, |
| { EL3RST, EL3RST_STR }, |
| { ELNRNG, ELNRNG_STR }, |
| { EUNATCH, EUNATCH_STR }, |
| { ENOCSI, ENOCSI_STR }, |
| { EL2HLT, EL2HLT_STR }, |
| { EBADE, EBADE_STR }, |
| { EBADR, EBADR_STR }, |
| { EXFULL, EXFULL_STR }, |
| { ENOANO, ENOANO_STR }, |
| { EBADRQC, EBADRQC_STR }, |
| { EBADSLT, EBADSLT_STR }, |
| { EBFONT, EBFONT_STR }, |
| { ENOSTR, ENOSTR_STR }, |
| { ENODATA, ENODATA_STR }, |
| { ETIME, ETIME_STR }, |
| { ENOSR, ENOSR_STR }, |
| { ENONET, ENONET_STR }, |
| { ENOPKG, ENOPKG_STR }, |
| { EREMOTE, EREMOTE_STR }, |
| { ENOLINK, ENOLINK_STR }, |
| { EADV, EADV_STR }, |
| { ESRMNT, ESRMNT_STR }, |
| { ECOMM, ECOMM_STR }, |
| { EPROTO, EPROTO_STR }, |
| { EMULTIHOP, EMULTIHOP_STR }, |
| { EDOTDOT, EDOTDOT_STR }, |
| { EBADMSG, EBADMSG_STR }, |
| { EOVERFLOW, EOVERFLOW_STR }, |
| { ENOTUNIQ, ENOTUNIQ_STR }, |
| { EBADFD, EBADFD_STR }, |
| { EREMCHG, EREMCHG_STR }, |
| { ELIBACC, ELIBACC_STR }, |
| { ELIBBAD, ELIBBAD_STR }, |
| { ELIBSCN, ELIBSCN_STR }, |
| { ELIBMAX, ELIBMAX_STR }, |
| { ELIBEXEC, ELIBEXEC_STR }, |
| { EILSEQ, EILSEQ_STR }, |
| { ERESTART, ERESTART_STR }, |
| { ESTRPIPE, ESTRPIPE_STR }, |
| { EUSERS, EUSERS_STR }, |
| { ENOTSOCK, ENOTSOCK_STR }, |
| { EDESTADDRREQ, EDESTADDRREQ_STR }, |
| { EMSGSIZE, EMSGSIZE_STR }, |
| { EPROTOTYPE, EPROTOTYPE_STR }, |
| { ENOPROTOOPT, ENOPROTOOPT_STR }, |
| { EPROTONOSUPPORT, EPROTONOSUPPORT_STR }, |
| { ESOCKTNOSUPPORT, ESOCKTNOSUPPORT_STR }, |
| { EOPNOTSUPP, EOPNOTSUPP_STR }, |
| { EPFNOSUPPORT, EPFNOSUPPORT_STR }, |
| { EAFNOSUPPORT, EAFNOSUPPORT_STR }, |
| { EADDRINUSE, EADDRINUSE_STR }, |
| { EADDRNOTAVAIL, EADDRNOTAVAIL_STR }, |
| { ENETDOWN, ENETDOWN_STR }, |
| { ENETUNREACH, ENETUNREACH_STR }, |
| { ENETRESET, ENETRESET_STR }, |
| { ECONNABORTED, ECONNABORTED_STR }, |
| { ECONNRESET, ECONNRESET_STR }, |
| { ENOBUFS, ENOBUFS_STR }, |
| { EISCONN, EISCONN_STR }, |
| { ENOTCONN, ENOTCONN_STR }, |
| { ESHUTDOWN, ESHUTDOWN_STR }, |
| { ETOOMANYREFS, ETOOMANYREFS_STR }, |
| { ETIMEDOUT, ETIMEDOUT_STR }, |
| { ECONNREFUSED, ECONNREFUSED_STR }, |
| { EHOSTDOWN, EHOSTDOWN_STR }, |
| { EHOSTUNREACH, EHOSTUNREACH_STR }, |
| { EALREADY, EALREADY_STR }, |
| { EINPROGRESS, EINPROGRESS_STR }, |
| { ESTALE, ESTALE_STR }, |
| { EUCLEAN, EUCLEAN_STR }, |
| { ENOTNAM, ENOTNAM_STR }, |
| { ENAVAIL, ENAVAIL_STR }, |
| { EISNAM, EISNAM_STR }, |
| { EREMOTEIO, EREMOTEIO_STR }, |
| { EDQUOT, EDQUOT_STR }, |
| { ENOMEDIUM, ENOMEDIUM_STR }, |
| { EMEDIUMTYPE, EMEDIUMTYPE_STR }, |
| { ECANCELED, ECANCELED_STR }, |
| { ENOKEY, ENOKEY_STR }, |
| { EKEYEXPIRED, EKEYEXPIRED_STR }, |
| { EKEYREVOKED, EKEYREVOKED_STR }, |
| { EKEYREJECTED, EKEYREJECTED_STR }, |
| { EOWNERDEAD, EOWNERDEAD_STR }, |
| { ENOTRECOVERABLE, ENOTRECOVERABLE_STR }, |
| { ERFKILL, ERFKILL_STR }, |
| { EHWPOISON, EHWPOISON_STR }, |
| { ELBIN, ELBIN_STR }, |
| { EFTYPE, EFTYPE_STR }, |
| { ENMFILE, ENMFILE_STR }, |
| { EPROCLIM, EPROCLIM_STR }, |
| { ENOTSUP, ENOTSUP_STR }, |
| { ENOSHARE, ENOSHARE_STR }, |
| { ECASECLASH, ECASECLASH_STR }, |
| }; |
| |
| #else /* CONFIG_LIBC_STRERROR_SHORT */ |
| |
| static const struct errno_strmap_s g_errnomap[] = |
| { |
| { 0, "OK" }, |
| { EPERM, "EPERM" }, |
| { ENOENT, "ENOENT" }, |
| { ESRCH, "ESRCH" }, |
| { EINTR, "EINTR" }, |
| { EIO, "EIO" }, |
| { ENXIO, "ENXIO" }, |
| { E2BIG, "E2BIG" }, |
| { ENOEXEC, "ENOEXEC" }, |
| { EBADF, "EBADF" }, |
| { ECHILD, "ECHILD" }, |
| { EAGAIN, "EAGAIN" }, |
| { ENOMEM, "ENOMEM" }, |
| { EACCES, "EACCES" }, |
| { EFAULT, "EFAULT" }, |
| { ENOTBLK, "ENOTBLK" }, |
| { EBUSY, "EBUSY" }, |
| { EEXIST, "EEXIST" }, |
| { EXDEV, "EXDEV" }, |
| { ENODEV, "ENODEV" }, |
| { ENOTDIR, "ENOTDIR" }, |
| { EISDIR, "EISDIR" }, |
| { EINVAL, "EINVAL" }, |
| { ENFILE, "ENFILE" }, |
| { EMFILE, "EMFILE" }, |
| { ENOTTY, "ENOTTY" }, |
| { ETXTBSY, "ETXTBSY" }, |
| { EFBIG, "EFBIG" }, |
| { ENOSPC, "ENOSPC" }, |
| { ESPIPE, "ESPIPE" }, |
| { EROFS, "EROFS" }, |
| { EMLINK, "EMLINK" }, |
| { EPIPE, "EPIPE" }, |
| { EDOM, "EDOM" }, |
| { ERANGE, "ERANGE" }, |
| { EDEADLK, "EDEADLK" }, |
| { ENAMETOOLONG, "ENAMETOOLONG" }, |
| { ENOLCK, "ENOLCK" }, |
| { ENOSYS, "ENOSYS" }, |
| { ENOTEMPTY, "ENOTEMPTY" }, |
| { ELOOP, "ELOOP" }, |
| { ENOMSG, "ENOMSG" }, |
| { EIDRM, "EIDRM" }, |
| { ECHRNG, "ECHRNG" }, |
| { EL2NSYNC, "EL2NSYNC" }, |
| { EL3HLT, "EL3HLT" }, |
| { EL3RST, "EL3RST" }, |
| { ELNRNG, "ELNRNG" }, |
| { EUNATCH, "EUNATCH" }, |
| { ENOCSI, "ENOCSI" }, |
| { EL2HLT, "EL2HLT" }, |
| { EBADE, "EBADE" }, |
| { EBADR, "EBADR" }, |
| { EXFULL, "EXFULL" }, |
| { ENOANO, "ENOANO" }, |
| { EBADRQC, "EBADRQC" }, |
| { EBADSLT, "EBADSLT" }, |
| { EBFONT, "EBFONT" }, |
| { ENOSTR, "ENOSTR" }, |
| { ENODATA, "ENODATA" }, |
| { ETIME, "ETIME" }, |
| { ENOSR, "ENOSR" }, |
| { ENONET, "ENONET" }, |
| { ENOPKG, "ENOPKG" }, |
| { EREMOTE, "EREMOTE" }, |
| { ENOLINK, "ENOLINK" }, |
| { EADV, "EADV" }, |
| { ESRMNT, "ESRMNT" }, |
| { ECOMM, "ECOMM" }, |
| { EPROTO, "EPROTO" }, |
| { EMULTIHOP, "EMULTIHOP" }, |
| { EDOTDOT, "EDOTDOT" }, |
| { EBADMSG, "EBADMSG" }, |
| { EOVERFLOW, "EOVERFLOW" }, |
| { ENOTUNIQ, "ENOTUNIQ" }, |
| { EBADFD, "EBADFD" }, |
| { EREMCHG, "EREMCHG" }, |
| { ELIBACC, "ELIBACC" }, |
| { ELIBBAD, "ELIBBAD" }, |
| { ELIBSCN, "ELIBSCN" }, |
| { ELIBMAX, "ELIBMAX" }, |
| { ELIBEXEC, "ELIBEXEC" }, |
| { EILSEQ, "EILSEQ" }, |
| { ERESTART, "ERESTART" }, |
| { ESTRPIPE, "ESTRPIPE" }, |
| { EUSERS, "EUSERS" }, |
| { ENOTSOCK, "ENOTSOCK" }, |
| { EDESTADDRREQ, "EDESTADDRREQ" }, |
| { EMSGSIZE, "EMSGSIZE" }, |
| { EPROTOTYPE, "EPROTOTYPE" }, |
| { ENOPROTOOPT, "ENOPROTOOPT" }, |
| { EPROTONOSUPPORT, "EPROTONOSUPPORT" }, |
| { ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT" }, |
| { EOPNOTSUPP, "EOPNOTSUPP" }, |
| { EPFNOSUPPORT, "EPFNOSUPPORT" }, |
| { EAFNOSUPPORT, "EAFNOSUPPORT" }, |
| { EADDRINUSE, "EADDRINUSE" }, |
| { EADDRNOTAVAIL, "EADDRNOTAVAIL" }, |
| { ENETDOWN, "ENETDOWN" }, |
| { ENETUNREACH, "ENETUNREACH" }, |
| { ENETRESET, "ENETRESET" }, |
| { ECONNABORTED, "ECONNABORTED" }, |
| { ECONNRESET, "ECONNRESET" }, |
| { ENOBUFS, "ENOBUFS" }, |
| { EISCONN, "EISCONN" }, |
| { ENOTCONN, "ENOTCONN" }, |
| { ESHUTDOWN, "ESHUTDOWN" }, |
| { ETOOMANYREFS, "ETOOMANYREFS" }, |
| { ETIMEDOUT, "ETIMEDOUT" }, |
| { ECONNREFUSED, "ECONNREFUSED" }, |
| { EHOSTDOWN, "EHOSTDOWN" }, |
| { EHOSTUNREACH, "EHOSTUNREACH" }, |
| { EALREADY, "EALREADY" }, |
| { EINPROGRESS, "EINPROGRESS" }, |
| { ESTALE, "ESTALE" }, |
| { EUCLEAN, "EUCLEAN" }, |
| { ENOTNAM, "ENOTNAM" }, |
| { ENAVAIL, "ENAVAIL" }, |
| { EISNAM, "EISNAM" }, |
| { EREMOTEIO, "EREMOTEIO" }, |
| { EDQUOT, "EDQUOT" }, |
| { ENOMEDIUM, "ENOMEDIUM" }, |
| { EMEDIUMTYPE, "EMEDIUMTYPE" }, |
| { ECANCELED, "ECANCELED" }, |
| { ENOKEY, "ENOKEY" }, |
| { EKEYEXPIRED, "EKEYEXPIRED" }, |
| { EKEYREVOKED, "EKEYREVOKED" }, |
| { EKEYREJECTED, "EKEYREJECTED" }, |
| { EOWNERDEAD, "EOWNERDEAD" }, |
| { ENOTRECOVERABLE, "ENOTRECOVERABLE" }, |
| { ERFKILL, "ERFKILL" }, |
| { EHWPOISON, "EHWPOISON" }, |
| { ELBIN, "ELBIN" }, |
| { EFTYPE, "EFTYPE" }, |
| { ENMFILE, "ENMFILE" }, |
| { EPROCLIM, "EPROCLIM" }, |
| { ENOTSUP, "ENOTSUP" }, |
| { ENOSHARE, "ENOSHARE" }, |
| { ECASECLASH, "ECASECLASH" } |
| }; |
| |
| #endif /* CONFIG_LIBC_STRERROR_SHORT */ |
| |
| #define NERRNO_STRS (sizeof(g_errnomap) / sizeof(struct errno_strmap_s)) |
| |
| #endif /* CONFIG_LIBC_STRERROR */ |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: strerror |
| ****************************************************************************/ |
| |
| FAR char *strerror(int errnum) |
| { |
| #ifdef CONFIG_LIBC_STRERROR_ERRNUM |
| static char s_err[STRERROR_BUFSIZE]; |
| #endif |
| #ifdef CONFIG_LIBC_STRERROR |
| int ndxlow = 0; |
| int ndxhi = NERRNO_STRS - 1; |
| int ndxmid; |
| |
| do |
| { |
| ndxmid = (ndxlow + ndxhi) >> 1; |
| if (errnum > g_errnomap[ndxmid].errnum) |
| { |
| ndxlow = ndxmid + 1; |
| } |
| else if (errnum < g_errnomap[ndxmid].errnum) |
| { |
| ndxhi = ndxmid - 1; |
| } |
| else |
| { |
| return g_errnomap[ndxmid].str; |
| } |
| } |
| while (ndxlow <= ndxhi); |
| #endif |
| #ifdef CONFIG_LIBC_STRERROR_ERRNUM |
| if (snprintf(s_err, sizeof(s_err), STRERROR_UNKNOWN " %d", errnum) |
| < sizeof(s_err)) |
| { |
| return s_err; |
| } |
| #elif !defined(CONFIG_LIBC_STRERROR) |
| UNUSED(errnum); |
| #endif |
| |
| return STRERROR_UNKNOWN; |
| } |