Home | History | Annotate | Download | only in arch-mips
      1 /*
      2  * Copyright 2012, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <portability.h>
     18 #include <pthread.h>
     19 #include <string.h>
     20 #include <errno.h>
     21 #include <errno_portable.h>
     22 
     23 #define PORTABLE_TAG "errno_portable"
     24 #include <log_portable.h>
     25 
     26 #if ENAMETOOLONG==ENAMETOOLONG_PORTABLE
     27 #error Bad build environment
     28 #endif
     29 
     30 __hidden int errno_ntop(int native_errno)
     31 {
     32     switch (native_errno) {
     33       case ENAMETOOLONG: return ENAMETOOLONG_PORTABLE;
     34       case ENOLCK: return ENOLCK_PORTABLE;
     35       case ENOSYS: return ENOSYS_PORTABLE;
     36       case ENOTEMPTY: return ENOTEMPTY_PORTABLE;
     37       case ELOOP: return ELOOP_PORTABLE;
     38       case EWOULDBLOCK: return EWOULDBLOCK_PORTABLE;
     39       case ENOMSG: return ENOMSG_PORTABLE;
     40       case EIDRM: return EIDRM_PORTABLE;
     41       case ECHRNG: return ECHRNG_PORTABLE;
     42       case EL2NSYNC: return EL2NSYNC_PORTABLE;
     43       case EL3HLT: return EL3HLT_PORTABLE;
     44       case EL3RST: return EL3RST_PORTABLE;
     45       case ELNRNG: return ELNRNG_PORTABLE;
     46       case EUNATCH: return EUNATCH_PORTABLE;
     47       case ENOCSI: return ENOCSI_PORTABLE;
     48       case EL2HLT: return EL2HLT_PORTABLE;
     49       case EBADE: return EBADE_PORTABLE;
     50       case EBADR: return EBADR_PORTABLE;
     51       case EXFULL: return EXFULL_PORTABLE;
     52       case ENOANO: return ENOANO_PORTABLE;
     53       case EBADRQC: return EBADRQC_PORTABLE;
     54       case EBADSLT: return EBADSLT_PORTABLE;
     55       case EDEADLOCK: return EDEADLOCK_PORTABLE;
     56       case EBFONT: return EBFONT_PORTABLE;
     57       case ENOSTR: return ENOSTR_PORTABLE;
     58       case ENODATA: return ENODATA_PORTABLE;
     59       case ETIME: return ETIME_PORTABLE;
     60       case ENOSR: return ENOSR_PORTABLE;
     61       case ENONET: return ENONET_PORTABLE;
     62       case ENOPKG: return ENOPKG_PORTABLE;
     63       case EREMOTE: return EREMOTE_PORTABLE;
     64       case ENOLINK: return ENOLINK_PORTABLE;
     65       case EADV: return EADV_PORTABLE;
     66       case ESRMNT: return ESRMNT_PORTABLE;
     67       case ECOMM: return ECOMM_PORTABLE;
     68       case EPROTO: return EPROTO_PORTABLE;
     69       case EMULTIHOP: return EMULTIHOP_PORTABLE;
     70       case EDOTDOT: return EDOTDOT_PORTABLE;
     71       case EBADMSG: return EBADMSG_PORTABLE;
     72       case EOVERFLOW: return EOVERFLOW_PORTABLE;
     73       case ENOTUNIQ: return ENOTUNIQ_PORTABLE;
     74       case EBADFD: return EBADFD_PORTABLE;
     75       case EREMCHG: return EREMCHG_PORTABLE;
     76       case ELIBACC: return ELIBACC_PORTABLE;
     77       case ELIBBAD: return ELIBBAD_PORTABLE;
     78       case ELIBSCN: return ELIBSCN_PORTABLE;
     79       case ELIBMAX: return ELIBMAX_PORTABLE;
     80       case ELIBEXEC: return ELIBEXEC_PORTABLE;
     81       case EILSEQ: return EILSEQ_PORTABLE;
     82       case ERESTART: return ERESTART_PORTABLE;
     83       case ESTRPIPE: return ESTRPIPE_PORTABLE;
     84       case EUSERS: return EUSERS_PORTABLE;
     85       case ENOTSOCK: return ENOTSOCK_PORTABLE;
     86       case EDESTADDRREQ: return EDESTADDRREQ_PORTABLE;
     87       case EMSGSIZE: return EMSGSIZE_PORTABLE;
     88       case EPROTOTYPE: return EPROTOTYPE_PORTABLE;
     89       case ENOPROTOOPT: return ENOPROTOOPT_PORTABLE;
     90       case EPROTONOSUPPORT: return EPROTONOSUPPORT_PORTABLE;
     91       case ESOCKTNOSUPPORT: return ESOCKTNOSUPPORT_PORTABLE;
     92       case EOPNOTSUPP: return EOPNOTSUPP_PORTABLE;
     93       case EPFNOSUPPORT: return EPFNOSUPPORT_PORTABLE;
     94       case EAFNOSUPPORT: return EAFNOSUPPORT_PORTABLE;
     95       case EADDRINUSE: return EADDRINUSE_PORTABLE;
     96       case EADDRNOTAVAIL: return EADDRNOTAVAIL_PORTABLE;
     97       case ENETDOWN: return ENETDOWN_PORTABLE;
     98       case ENETUNREACH: return ENETUNREACH_PORTABLE;
     99       case ENETRESET: return ENETRESET_PORTABLE;
    100       case ECONNABORTED: return ECONNABORTED_PORTABLE;
    101       case ECONNRESET: return ECONNRESET_PORTABLE;
    102       case ENOBUFS: return ENOBUFS_PORTABLE;
    103       case EISCONN: return EISCONN_PORTABLE;
    104       case ENOTCONN: return ENOTCONN_PORTABLE;
    105       case ESHUTDOWN: return ESHUTDOWN_PORTABLE;
    106       case ETOOMANYREFS: return ETOOMANYREFS_PORTABLE;
    107       case ETIMEDOUT: return ETIMEDOUT_PORTABLE;
    108       case ECONNREFUSED: return ECONNREFUSED_PORTABLE;
    109       case EHOSTDOWN: return EHOSTDOWN_PORTABLE;
    110       case EHOSTUNREACH: return EHOSTUNREACH_PORTABLE;
    111       case EALREADY: return EALREADY_PORTABLE;
    112       case EINPROGRESS: return EINPROGRESS_PORTABLE;
    113       case ESTALE: return ESTALE_PORTABLE;
    114       case EUCLEAN: return EUCLEAN_PORTABLE;
    115       case ENOTNAM: return ENOTNAM_PORTABLE;
    116       case ENAVAIL: return ENAVAIL_PORTABLE;
    117       case EISNAM: return EISNAM_PORTABLE;
    118       case EREMOTEIO: return EREMOTEIO_PORTABLE;
    119       case EDQUOT: return EDQUOT_PORTABLE;
    120       case ENOMEDIUM: return ENOMEDIUM_PORTABLE;
    121       case EMEDIUMTYPE: return EMEDIUMTYPE_PORTABLE;
    122       case ECANCELED: return ECANCELED_PORTABLE;
    123       case ENOKEY: return ENOKEY_PORTABLE;
    124       case EKEYEXPIRED: return EKEYEXPIRED_PORTABLE;
    125       case EKEYREVOKED: return EKEYREVOKED_PORTABLE;
    126       case EKEYREJECTED: return EKEYREJECTED_PORTABLE;
    127       case EOWNERDEAD: return EOWNERDEAD_PORTABLE;
    128       case ENOTRECOVERABLE: return ENOTRECOVERABLE_PORTABLE;
    129     }
    130     return native_errno;
    131 }
    132 
    133 __hidden int errno_pton(int portable_errno)
    134 {
    135     switch (portable_errno) {
    136       case ENAMETOOLONG_PORTABLE: return ENAMETOOLONG;
    137       case ENOLCK_PORTABLE: return ENOLCK;
    138       case ENOSYS_PORTABLE: return ENOSYS;
    139       case ENOTEMPTY_PORTABLE: return ENOTEMPTY;
    140       case ELOOP_PORTABLE: return ELOOP;
    141       case EWOULDBLOCK_PORTABLE: return EWOULDBLOCK;
    142       case ENOMSG_PORTABLE: return ENOMSG;
    143       case EIDRM_PORTABLE: return EIDRM;
    144       case ECHRNG_PORTABLE: return ECHRNG;
    145       case EL2NSYNC_PORTABLE: return EL2NSYNC;
    146       case EL3HLT_PORTABLE: return EL3HLT;
    147       case EL3RST_PORTABLE: return EL3RST;
    148       case ELNRNG_PORTABLE: return ELNRNG;
    149       case EUNATCH_PORTABLE: return EUNATCH;
    150       case ENOCSI_PORTABLE: return ENOCSI;
    151       case EL2HLT_PORTABLE: return EL2HLT;
    152       case EBADE_PORTABLE: return EBADE;
    153       case EBADR_PORTABLE: return EBADR;
    154       case EXFULL_PORTABLE: return EXFULL;
    155       case ENOANO_PORTABLE: return ENOANO;
    156       case EBADRQC_PORTABLE: return EBADRQC;
    157       case EBADSLT_PORTABLE: return EBADSLT;
    158       case EDEADLOCK_PORTABLE: return EDEADLOCK;
    159       case EBFONT_PORTABLE: return EBFONT;
    160       case ENOSTR_PORTABLE: return ENOSTR;
    161       case ENODATA_PORTABLE: return ENODATA;
    162       case ETIME_PORTABLE: return ETIME;
    163       case ENOSR_PORTABLE: return ENOSR;
    164       case ENONET_PORTABLE: return ENONET;
    165       case ENOPKG_PORTABLE: return ENOPKG;
    166       case EREMOTE_PORTABLE: return EREMOTE;
    167       case ENOLINK_PORTABLE: return ENOLINK;
    168       case EADV_PORTABLE: return EADV;
    169       case ESRMNT_PORTABLE: return ESRMNT;
    170       case ECOMM_PORTABLE: return ECOMM;
    171       case EPROTO_PORTABLE: return EPROTO;
    172       case EMULTIHOP_PORTABLE: return EMULTIHOP;
    173       case EDOTDOT_PORTABLE: return EDOTDOT;
    174       case EBADMSG_PORTABLE: return EBADMSG;
    175       case EOVERFLOW_PORTABLE: return EOVERFLOW;
    176       case ENOTUNIQ_PORTABLE: return ENOTUNIQ;
    177       case EBADFD_PORTABLE: return EBADFD;
    178       case EREMCHG_PORTABLE: return EREMCHG;
    179       case ELIBACC_PORTABLE: return ELIBACC;
    180       case ELIBBAD_PORTABLE: return ELIBBAD;
    181       case ELIBSCN_PORTABLE: return ELIBSCN;
    182       case ELIBMAX_PORTABLE: return ELIBMAX;
    183       case ELIBEXEC_PORTABLE: return ELIBEXEC;
    184       case EILSEQ_PORTABLE: return EILSEQ;
    185       case ERESTART_PORTABLE: return ERESTART;
    186       case ESTRPIPE_PORTABLE: return ESTRPIPE;
    187       case EUSERS_PORTABLE: return EUSERS;
    188       case ENOTSOCK_PORTABLE: return ENOTSOCK;
    189       case EDESTADDRREQ_PORTABLE: return EDESTADDRREQ;
    190       case EMSGSIZE_PORTABLE: return EMSGSIZE;
    191       case EPROTOTYPE_PORTABLE: return EPROTOTYPE;
    192       case ENOPROTOOPT_PORTABLE: return ENOPROTOOPT;
    193       case EPROTONOSUPPORT_PORTABLE: return EPROTONOSUPPORT;
    194       case ESOCKTNOSUPPORT_PORTABLE: return ESOCKTNOSUPPORT;
    195       case EOPNOTSUPP_PORTABLE: return EOPNOTSUPP;
    196       case EPFNOSUPPORT_PORTABLE: return EPFNOSUPPORT;
    197       case EAFNOSUPPORT_PORTABLE: return EAFNOSUPPORT;
    198       case EADDRINUSE_PORTABLE: return EADDRINUSE;
    199       case EADDRNOTAVAIL_PORTABLE: return EADDRNOTAVAIL;
    200       case ENETDOWN_PORTABLE: return ENETDOWN;
    201       case ENETUNREACH_PORTABLE: return ENETUNREACH;
    202       case ENETRESET_PORTABLE: return ENETRESET;
    203       case ECONNABORTED_PORTABLE: return ECONNABORTED;
    204       case ECONNRESET_PORTABLE: return ECONNRESET;
    205       case ENOBUFS_PORTABLE: return ENOBUFS;
    206       case EISCONN_PORTABLE: return EISCONN;
    207       case ENOTCONN_PORTABLE: return ENOTCONN;
    208       case ESHUTDOWN_PORTABLE: return ESHUTDOWN;
    209       case ETOOMANYREFS_PORTABLE: return ETOOMANYREFS;
    210       case ETIMEDOUT_PORTABLE: return ETIMEDOUT;
    211       case ECONNREFUSED_PORTABLE: return ECONNREFUSED;
    212       case EHOSTDOWN_PORTABLE: return EHOSTDOWN;
    213       case EHOSTUNREACH_PORTABLE: return EHOSTUNREACH;
    214       case EALREADY_PORTABLE: return EALREADY;
    215       case EINPROGRESS_PORTABLE: return EINPROGRESS;
    216       case ESTALE_PORTABLE: return ESTALE;
    217       case EUCLEAN_PORTABLE: return EUCLEAN;
    218       case ENOTNAM_PORTABLE: return ENOTNAM;
    219       case ENAVAIL_PORTABLE: return ENAVAIL;
    220       case EISNAM_PORTABLE: return EISNAM;
    221       case EREMOTEIO_PORTABLE: return EREMOTEIO;
    222       case EDQUOT_PORTABLE: return EDQUOT;
    223       case ENOMEDIUM_PORTABLE: return ENOMEDIUM;
    224       case EMEDIUMTYPE_PORTABLE: return EMEDIUMTYPE;
    225       case ECANCELED_PORTABLE: return ECANCELED;
    226       case ENOKEY_PORTABLE: return ENOKEY;
    227       case EKEYEXPIRED_PORTABLE: return EKEYEXPIRED;
    228       case EKEYREVOKED_PORTABLE: return EKEYREVOKED;
    229       case EKEYREJECTED_PORTABLE: return EKEYREJECTED;
    230       case EOWNERDEAD_PORTABLE: return EOWNERDEAD;
    231       case ENOTRECOVERABLE_PORTABLE: return ENOTRECOVERABLE;
    232     }
    233     return portable_errno;
    234 }
    235 
    236 /* Key for the thread-specific portable errno */
    237 static pthread_key_t errno_key;
    238 
    239 /* Once-only initialisation of the key */
    240 static pthread_once_t errno_key_once = PTHREAD_ONCE_INIT;
    241 
    242 /* Free the thread-specific portable errno */
    243 static void errno_key_destroy(void *buf)
    244 {
    245     if (buf)
    246         free(buf);
    247 }
    248 
    249 /* Allocate the key */
    250 static void errno_key_create(void)
    251 {
    252     pthread_key_create(&errno_key, errno_key_destroy);
    253 }
    254 
    255 struct errno_state {
    256     int pshadow;                /* copy of last portable errno */
    257     int perrno;                 /* portable errno that may be modified by app */
    258 };
    259 
    260 /* Return the thread-specific portable errno */
    261 static struct errno_state *errno_key_data(void)
    262 {
    263     struct errno_state *data;
    264     static struct errno_state errno_state;
    265 
    266     pthread_once(&errno_key_once, errno_key_create);
    267     data = (struct errno_state *)pthread_getspecific(errno_key);
    268     if (data == NULL) {
    269         data = malloc(sizeof(struct errno_state));
    270         pthread_setspecific(errno_key, data);
    271     }
    272     if (data == NULL)
    273         data = &errno_state;
    274     return data;
    275 }
    276 
    277 /*
    278  * Attempt to return a thread specific location containnig the portable errno.
    279  * This can be assigned to without affecting the native errno. If the key
    280  * allocation fails fall back to using the native errno location.
    281  */
    282 volatile int* WRAP(__errno)()
    283 {
    284     struct errno_state *p;
    285     int save_errno;
    286 
    287     /* pthread_* calls may modify errno so use a copy */
    288     save_errno = *REAL(__errno)();
    289 
    290     p = errno_key_data();
    291 
    292     ALOGV(" ");
    293     ALOGV("%s(): { save_errno = errno:%d, (p:%p)->{pshadow:%d, perrno:%d}", __func__,
    294                    save_errno,             p,   p->pshadow, p->perrno);
    295 
    296     if (save_errno == 0 && p->pshadow != p->perrno) {
    297         /*
    298          * portable errno has changed but native hasn't
    299          * - copy portable error back to native
    300          */
    301         p->pshadow = p->perrno;
    302         save_errno = errno_pton(p->perrno);
    303     }
    304     else if (save_errno != 0 && p->pshadow == p->perrno) {
    305         /*
    306          * Native errno has changed but portable hasn't
    307          * - copy native error to portable.
    308          */
    309         p->pshadow = p->perrno = errno_ntop(save_errno);
    310         save_errno = 0;
    311     }
    312     else if (save_errno != 0 && p->pshadow != p->perrno) {
    313         /*
    314          * Both native and portable errno values have changed
    315          * so give priority to native errno
    316          * - copy native error to portable
    317          */
    318         p->pshadow = p->perrno = errno_ntop(save_errno);
    319         save_errno = 0;
    320     }
    321 
    322     ALOGV("%s: new save_errno:%d p:%p->{pshadow:%d, perrno:%d}", __func__,
    323                    save_errno,   p,  p->pshadow, p->perrno);
    324 
    325     *REAL(__errno)() = save_errno;
    326 
    327     ALOGV("%s: return (&p->perrno):%p; }", __func__, &p->perrno);
    328 
    329     /* return pointer to the modifiable portable errno value */
    330     return &p->perrno;
    331 }
    332 
    333 
    334 /* set portable errno */
    335 void WRAP(__set_errno)(int portable_errno)
    336 {
    337     struct errno_state *p;
    338     int save_errno;
    339 
    340     /* pthread_* calls may modify errno so use a copy */
    341     save_errno = *REAL(__errno)();
    342 
    343     p = errno_key_data();
    344 
    345     ALOGV("%s(): { save_errno = errno:%d, p:%p->{pshadow:%d, perrno:%d}", __func__,
    346                    save_errno,            p,  p->pshadow, p->perrno);
    347 
    348     p->pshadow = p->perrno = portable_errno;
    349 
    350     save_errno = errno_pton(portable_errno);
    351 
    352     ALOGV("%s: new save_errno:%d, p:%p->{pshadow:%d, perrno:%d}", __func__,
    353                    save_errno,    p,  p->pshadow, p->perrno);
    354 
    355     *REAL(__errno)() = save_errno;
    356 
    357     ALOGV("%s: return; }", __func__);
    358 }
    359 
    360 extern char* REAL(strerror)(int);
    361 char *WRAP(strerror)(int errnum)
    362 {
    363     return REAL(strerror)(errno_pton(errnum));
    364 }
    365 
    366 /* BSD style strerror_r */
    367 int WRAP(strerror_r)(int errnum, char *buf, size_t buflen)
    368 {
    369     return REAL(strerror_r)(errno_pton(errnum), buf, buflen);
    370 }
    371