Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 // G++ automatically defines _GNU_SOURCE, which then means that <string.h>
     30 // gives us the GNU variant.
     31 #undef _GNU_SOURCE
     32 
     33 #include <string.h>
     34 
     35 #include <errno.h>
     36 #include <limits.h>
     37 
     38 #include <async_safe/log.h>
     39 
     40 #include "private/ErrnoRestorer.h"
     41 
     42 #include <string.h>
     43 
     44 #include "bionic/pthread_internal.h"
     45 
     46 static const char* __sys_error_strings[] = {
     47     [0] = "Success",
     48     [EPERM] = "Operation not permitted",
     49     [ENOENT] = "No such file or directory",
     50     [ESRCH] = "No such process",
     51     [EINTR] = "Interrupted system call",
     52     [EIO] = "I/O error",
     53     [ENXIO] = "No such device or address",
     54     [E2BIG] = "Argument list too long",
     55     [ENOEXEC] = "Exec format error",
     56     [EBADF] = "Bad file descriptor",
     57     [ECHILD] = "No child processes",
     58     [EAGAIN] = "Try again",
     59     [ENOMEM] = "Out of memory",
     60     [EACCES] = "Permission denied",
     61     [EFAULT] = "Bad address",
     62     [ENOTBLK] = "Block device required",
     63     [EBUSY] = "Device or resource busy",
     64     [EEXIST] = "File exists",
     65     [EXDEV] = "Cross-device link",
     66     [ENODEV] = "No such device",
     67     [ENOTDIR] = "Not a directory",
     68     [EISDIR] = "Is a directory",
     69     [EINVAL] = "Invalid argument",
     70     [ENFILE] = "File table overflow",
     71     [EMFILE] = "Too many open files",
     72     [ENOTTY] = "Not a typewriter",
     73     [ETXTBSY] = "Text file busy",
     74     [EFBIG] = "File too large",
     75     [ENOSPC] = "No space left on device",
     76     [ESPIPE] = "Illegal seek",
     77     [EROFS] = "Read-only file system",
     78     [EMLINK] = "Too many links",
     79     [EPIPE] = "Broken pipe",
     80     [EDOM] = "Math argument out of domain of func",
     81     [ERANGE] = "Math result not representable",
     82     [EDEADLK] = "Resource deadlock would occur",
     83     [ENAMETOOLONG] = "File name too long",
     84     [ENOLCK] = "No record locks available",
     85     [ENOSYS] = "Function not implemented",
     86     [ENOTEMPTY] = "Directory not empty",
     87     [ELOOP] = "Too many symbolic links encountered",
     88     [ENOMSG] = "No message of desired type",
     89     [EIDRM] = "Identifier removed",
     90     [ECHRNG] = "Channel number out of range",
     91     [EL2NSYNC] = "Level 2 not synchronized",
     92     [EL3HLT] = "Level 3 halted",
     93     [EL3RST] = "Level 3 reset",
     94     [ELNRNG] = "Link number out of range",
     95     [EUNATCH] = "Protocol driver not attached",
     96     [ENOCSI] = "No CSI structure available",
     97     [EL2HLT] = "Level 2 halted",
     98     [EBADE] = "Invalid exchange",
     99     [EBADR] = "Invalid request descriptor",
    100     [EXFULL] = "Exchange full",
    101     [ENOANO] = "No anode",
    102     [EBADRQC] = "Invalid request code",
    103     [EBADSLT] = "Invalid slot",
    104     [EBFONT] = "Bad font file format",
    105     [ENOSTR] = "Device not a stream",
    106     [ENODATA] = "No data available",
    107     [ETIME] = "Timer expired",
    108     [ENOSR] = "Out of streams resources",
    109     [ENONET] = "Machine is not on the network",
    110     [ENOPKG] = "Package not installed",
    111     [EREMOTE] = "Object is remote",
    112     [ENOLINK] = "Link has been severed",
    113     [EADV] = "Advertise error",
    114     [ESRMNT] = "Srmount error",
    115     [ECOMM] = "Communication error on send",
    116     [EPROTO] = "Protocol error",
    117     [EMULTIHOP] = "Multihop attempted",
    118     [EDOTDOT] = "RFS specific error",
    119     [EBADMSG] = "Not a data message",
    120     [EOVERFLOW] = "Value too large for defined data type",
    121     [ENOTUNIQ] = "Name not unique on network",
    122     [EBADFD] = "File descriptor in bad state",
    123     [EREMCHG] = "Remote address changed",
    124     [ELIBACC] = "Can not access a needed shared library",
    125     [ELIBBAD] = "Accessing a corrupted shared library",
    126     [ELIBSCN] = ".lib section in a.out corrupted",
    127     [ELIBMAX] = "Attempting to link in too many shared libraries",
    128     [ELIBEXEC] = "Cannot exec a shared library directly",
    129     [EILSEQ] = "Illegal byte sequence",
    130     [ERESTART] = "Interrupted system call should be restarted",
    131     [ESTRPIPE] = "Streams pipe error",
    132     [EUSERS] = "Too many users",
    133     [ENOTSOCK] = "Socket operation on non-socket",
    134     [EDESTADDRREQ] = "Destination address required",
    135     [EMSGSIZE] = "Message too long",
    136     [EPROTOTYPE] = "Protocol wrong type for socket",
    137     [ENOPROTOOPT] = "Protocol not available",
    138     [EPROTONOSUPPORT] = "Protocol not supported",
    139     [ESOCKTNOSUPPORT] = "Socket type not supported",
    140     [EOPNOTSUPP] = "Operation not supported on transport endpoint",
    141     [EPFNOSUPPORT] = "Protocol family not supported",
    142     [EAFNOSUPPORT] = "Address family not supported by protocol",
    143     [EADDRINUSE] = "Address already in use",
    144     [EADDRNOTAVAIL] = "Cannot assign requested address",
    145     [ENETDOWN] = "Network is down",
    146     [ENETUNREACH] = "Network is unreachable",
    147     [ENETRESET] = "Network dropped connection because of reset",
    148     [ECONNABORTED] = "Software caused connection abort",
    149     [ECONNRESET] = "Connection reset by peer",
    150     [ENOBUFS] = "No buffer space available",
    151     [EISCONN] = "Transport endpoint is already connected",
    152     [ENOTCONN] = "Transport endpoint is not connected",
    153     [ESHUTDOWN] = "Cannot send after transport endpoint shutdown",
    154     [ETOOMANYREFS] = "Too many references: cannot splice",
    155     [ETIMEDOUT] = "Connection timed out",
    156     [ECONNREFUSED] = "Connection refused",
    157     [EHOSTDOWN] = "Host is down",
    158     [EHOSTUNREACH] = "No route to host",
    159     [EALREADY] = "Operation already in progress",
    160     [EINPROGRESS] = "Operation now in progress",
    161     [ESTALE] = "Stale NFS file handle",
    162     [EUCLEAN] = "Structure needs cleaning",
    163     [ENOTNAM] = "Not a XENIX named type file",
    164     [ENAVAIL] = "No XENIX semaphores available",
    165     [EISNAM] = "Is a named type file",
    166     [EREMOTEIO] = "Remote I/O error",
    167     [EDQUOT] = "Quota exceeded",
    168     [ENOMEDIUM] = "No medium found",
    169     [EMEDIUMTYPE] = "Wrong medium type",
    170     [ECANCELED] = "Operation Canceled",
    171     [ENOKEY] = "Required key not available",
    172     [EKEYEXPIRED] = "Key has expired",
    173     [EKEYREVOKED] = "Key has been revoked",
    174     [EKEYREJECTED] = "Key was rejected by service",
    175     [EOWNERDEAD] = "Owner died",
    176     [ENOTRECOVERABLE] = "State not recoverable",
    177     [ERFKILL] = "Operation not possible due to RF-kill",
    178     [EHWPOISON] = "Memory page has hardware error",
    179 };
    180 
    181 static inline const char* __strerror_lookup(int error_number) {
    182   if (error_number < 0 || error_number >= static_cast<int>(arraysize(__sys_error_strings))) {
    183     return nullptr;
    184   }
    185   return __sys_error_strings[error_number];
    186 }
    187 
    188 int strerror_r(int error_number, char* buf, size_t buf_len) {
    189   ErrnoRestorer errno_restorer;
    190   size_t length;
    191 
    192   const char* error_name = __strerror_lookup(error_number);
    193   if (error_name != nullptr) {
    194     length = strlcpy(buf, error_name, buf_len);
    195   } else {
    196     length = async_safe_format_buffer(buf, buf_len, "Unknown error %d", error_number);
    197   }
    198   if (length >= buf_len) {
    199     errno_restorer.override(ERANGE);
    200     return -1;
    201   }
    202 
    203   return 0;
    204 }
    205 
    206 extern "C" char* __gnu_strerror_r(int error_number, char* buf, size_t buf_len) {
    207   ErrnoRestorer errno_restorer; // The glibc strerror_r doesn't set errno if it truncates...
    208   strerror_r(error_number, buf, buf_len);
    209   return buf; // ...and just returns whatever fit.
    210 }
    211 
    212 char* strerror(int error_number) {
    213   // Just return the original constant in the easy cases.
    214   char* result = const_cast<char*>(__strerror_lookup(error_number));
    215   if (result != nullptr) {
    216     return result;
    217   }
    218 
    219   bionic_tls& tls = __get_bionic_tls();
    220   result = tls.strerror_buf;
    221   strerror_r(error_number, result, sizeof(tls.strerror_buf));
    222   return result;
    223 }
    224