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