1 /* 2 * Copyright 2014, 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 #ifndef _ERRNO_PORTABLE_H_ 18 #define _ERRNO_PORTABLE_H_ 19 20 #include <portability.h> 21 #include <errno.h> 22 #include <pthread.h> 23 #include <string.h> 24 25 #define ALOGV(...) 26 27 #define EDEADLK_PORTABLE 35 28 #define ENAMETOOLONG_PORTABLE 36 29 #define ENOLCK_PORTABLE 37 30 #define ENOSYS_PORTABLE 38 31 #define ENOTEMPTY_PORTABLE 39 32 #define ELOOP_PORTABLE 40 33 #define EWOULDBLOCK_PORTABLE 11 /* EAGAIN */ 34 #define ENOMSG_PORTABLE 42 35 #define EIDRM_PORTABLE 43 36 #define ECHRNG_PORTABLE 44 37 #define EL2NSYNC_PORTABLE 45 38 #define EL3HLT_PORTABLE 46 39 #define EL3RST_PORTABLE 47 40 #define ELNRNG_PORTABLE 48 41 #define EUNATCH_PORTABLE 49 42 #define ENOCSI_PORTABLE 50 43 #define EL2HLT_PORTABLE 51 44 #define EBADE_PORTABLE 52 45 #define EBADR_PORTABLE 53 46 #define EXFULL_PORTABLE 54 47 #define ENOANO_PORTABLE 55 48 #define EBADRQC_PORTABLE 56 49 #define EBADSLT_PORTABLE 57 50 51 #define EDEADLOCK_PORTABLE EDEADLK_PORTABLE 52 53 #define EBFONT_PORTABLE 59 54 #define ENOSTR_PORTABLE 60 55 #define ENODATA_PORTABLE 61 56 #define ETIME_PORTABLE 62 57 #define ENOSR_PORTABLE 63 58 #define ENONET_PORTABLE 64 59 #define ENOPKG_PORTABLE 65 60 #define EREMOTE_PORTABLE 66 61 #define ENOLINK_PORTABLE 67 62 #define EADV_PORTABLE 68 63 #define ESRMNT_PORTABLE 69 64 #define ECOMM_PORTABLE 70 65 #define EPROTO_PORTABLE 71 66 #define EMULTIHOP_PORTABLE 72 67 #define EDOTDOT_PORTABLE 73 68 #define EBADMSG_PORTABLE 74 69 #define EOVERFLOW_PORTABLE 75 70 #define ENOTUNIQ_PORTABLE 76 71 #define EBADFD_PORTABLE 77 72 #define EREMCHG_PORTABLE 78 73 #define ELIBACC_PORTABLE 79 74 #define ELIBBAD_PORTABLE 80 75 #define ELIBSCN_PORTABLE 81 76 #define ELIBMAX_PORTABLE 82 77 #define ELIBEXEC_PORTABLE 83 78 #define EILSEQ_PORTABLE 84 79 #define ERESTART_PORTABLE 85 80 #define ESTRPIPE_PORTABLE 86 81 #define EUSERS_PORTABLE 87 82 #define ENOTSOCK_PORTABLE 88 83 #define EDESTADDRREQ_PORTABLE 89 84 #define EMSGSIZE_PORTABLE 90 85 #define EPROTOTYPE_PORTABLE 91 86 #define ENOPROTOOPT_PORTABLE 92 87 #define EPROTONOSUPPORT_PORTABLE 93 88 #define ESOCKTNOSUPPORT_PORTABLE 94 89 #define EOPNOTSUPP_PORTABLE 95 90 #define EPFNOSUPPORT_PORTABLE 96 91 #define EAFNOSUPPORT_PORTABLE 97 92 #define EADDRINUSE_PORTABLE 98 93 #define EADDRNOTAVAIL_PORTABLE 99 94 #define ENETDOWN_PORTABLE 100 95 #define ENETUNREACH_PORTABLE 101 96 #define ENETRESET_PORTABLE 102 97 #define ECONNABORTED_PORTABLE 103 98 #define ECONNRESET_PORTABLE 104 99 #define ENOBUFS_PORTABLE 105 100 #define EISCONN_PORTABLE 106 101 #define ENOTCONN_PORTABLE 107 102 #define ESHUTDOWN_PORTABLE 108 103 #define ETOOMANYREFS_PORTABLE 109 104 #define ETIMEDOUT_PORTABLE 110 105 #define ECONNREFUSED_PORTABLE 111 106 #define EHOSTDOWN_PORTABLE 112 107 #define EHOSTUNREACH_PORTABLE 113 108 #define EALREADY_PORTABLE 114 109 #define EINPROGRESS_PORTABLE 115 110 #define ESTALE_PORTABLE 116 111 #define EUCLEAN_PORTABLE 117 112 #define ENOTNAM_PORTABLE 118 113 #define ENAVAIL_PORTABLE 119 114 #define EISNAM_PORTABLE 120 115 #define EREMOTEIO_PORTABLE 121 116 #define EDQUOT_PORTABLE 122 117 118 #define ENOMEDIUM_PORTABLE 123 119 #define EMEDIUMTYPE_PORTABLE 124 120 #define ECANCELED_PORTABLE 125 121 #define ENOKEY_PORTABLE 126 122 #define EKEYEXPIRED_PORTABLE 127 123 #define EKEYREVOKED_PORTABLE 128 124 #define EKEYREJECTED_PORTABLE 129 125 126 #define EOWNERDEAD_PORTABLE 130 127 #define ENOTRECOVERABLE_PORTABLE 131 128 #define ERFKILL_PORTABLE 132 129 #define EHWPOISON_PORTABLE 133 130 131 extern volatile int* REAL(__errno)(); 132 133 static int errno_ntop(int native_errno) 134 { 135 switch (native_errno) { 136 case ENAMETOOLONG: return ENAMETOOLONG_PORTABLE; 137 case ENOLCK: return ENOLCK_PORTABLE; 138 case ENOSYS: return ENOSYS_PORTABLE; 139 case ENOTEMPTY: return ENOTEMPTY_PORTABLE; 140 case ELOOP: return ELOOP_PORTABLE; 141 case EWOULDBLOCK: return EWOULDBLOCK_PORTABLE; 142 case ENOMSG: return ENOMSG_PORTABLE; 143 case EIDRM: return EIDRM_PORTABLE; 144 case ECHRNG: return ECHRNG_PORTABLE; 145 case EL2NSYNC: return EL2NSYNC_PORTABLE; 146 case EL3HLT: return EL3HLT_PORTABLE; 147 case EL3RST: return EL3RST_PORTABLE; 148 case ELNRNG: return ELNRNG_PORTABLE; 149 case EUNATCH: return EUNATCH_PORTABLE; 150 case ENOCSI: return ENOCSI_PORTABLE; 151 case EL2HLT: return EL2HLT_PORTABLE; 152 case EBADE: return EBADE_PORTABLE; 153 case EBADR: return EBADR_PORTABLE; 154 case EXFULL: return EXFULL_PORTABLE; 155 case ENOANO: return ENOANO_PORTABLE; 156 case EBADRQC: return EBADRQC_PORTABLE; 157 case EBADSLT: return EBADSLT_PORTABLE; 158 case EDEADLOCK: return EDEADLOCK_PORTABLE; 159 case EBFONT: return EBFONT_PORTABLE; 160 case ENOSTR: return ENOSTR_PORTABLE; 161 case ENODATA: return ENODATA_PORTABLE; 162 case ETIME: return ETIME_PORTABLE; 163 case ENOSR: return ENOSR_PORTABLE; 164 case ENONET: return ENONET_PORTABLE; 165 case ENOPKG: return ENOPKG_PORTABLE; 166 case EREMOTE: return EREMOTE_PORTABLE; 167 case ENOLINK: return ENOLINK_PORTABLE; 168 case EADV: return EADV_PORTABLE; 169 case ESRMNT: return ESRMNT_PORTABLE; 170 case ECOMM: return ECOMM_PORTABLE; 171 case EPROTO: return EPROTO_PORTABLE; 172 case EMULTIHOP: return EMULTIHOP_PORTABLE; 173 case EDOTDOT: return EDOTDOT_PORTABLE; 174 case EBADMSG: return EBADMSG_PORTABLE; 175 case EOVERFLOW: return EOVERFLOW_PORTABLE; 176 case ENOTUNIQ: return ENOTUNIQ_PORTABLE; 177 case EBADFD: return EBADFD_PORTABLE; 178 case EREMCHG: return EREMCHG_PORTABLE; 179 case ELIBACC: return ELIBACC_PORTABLE; 180 case ELIBBAD: return ELIBBAD_PORTABLE; 181 case ELIBSCN: return ELIBSCN_PORTABLE; 182 case ELIBMAX: return ELIBMAX_PORTABLE; 183 case ELIBEXEC: return ELIBEXEC_PORTABLE; 184 case EILSEQ: return EILSEQ_PORTABLE; 185 case ERESTART: return ERESTART_PORTABLE; 186 case ESTRPIPE: return ESTRPIPE_PORTABLE; 187 case EUSERS: return EUSERS_PORTABLE; 188 case ENOTSOCK: return ENOTSOCK_PORTABLE; 189 case EDESTADDRREQ: return EDESTADDRREQ_PORTABLE; 190 case EMSGSIZE: return EMSGSIZE_PORTABLE; 191 case EPROTOTYPE: return EPROTOTYPE_PORTABLE; 192 case ENOPROTOOPT: return ENOPROTOOPT_PORTABLE; 193 case EPROTONOSUPPORT: return EPROTONOSUPPORT_PORTABLE; 194 case ESOCKTNOSUPPORT: return ESOCKTNOSUPPORT_PORTABLE; 195 case EOPNOTSUPP: return EOPNOTSUPP_PORTABLE; 196 case EPFNOSUPPORT: return EPFNOSUPPORT_PORTABLE; 197 case EAFNOSUPPORT: return EAFNOSUPPORT_PORTABLE; 198 case EADDRINUSE: return EADDRINUSE_PORTABLE; 199 case EADDRNOTAVAIL: return EADDRNOTAVAIL_PORTABLE; 200 case ENETDOWN: return ENETDOWN_PORTABLE; 201 case ENETUNREACH: return ENETUNREACH_PORTABLE; 202 case ENETRESET: return ENETRESET_PORTABLE; 203 case ECONNABORTED: return ECONNABORTED_PORTABLE; 204 case ECONNRESET: return ECONNRESET_PORTABLE; 205 case ENOBUFS: return ENOBUFS_PORTABLE; 206 case EISCONN: return EISCONN_PORTABLE; 207 case ENOTCONN: return ENOTCONN_PORTABLE; 208 case ESHUTDOWN: return ESHUTDOWN_PORTABLE; 209 case ETOOMANYREFS: return ETOOMANYREFS_PORTABLE; 210 case ETIMEDOUT: return ETIMEDOUT_PORTABLE; 211 case ECONNREFUSED: return ECONNREFUSED_PORTABLE; 212 case EHOSTDOWN: return EHOSTDOWN_PORTABLE; 213 case EHOSTUNREACH: return EHOSTUNREACH_PORTABLE; 214 case EALREADY: return EALREADY_PORTABLE; 215 case EINPROGRESS: return EINPROGRESS_PORTABLE; 216 case ESTALE: return ESTALE_PORTABLE; 217 case EUCLEAN: return EUCLEAN_PORTABLE; 218 case ENOTNAM: return ENOTNAM_PORTABLE; 219 case ENAVAIL: return ENAVAIL_PORTABLE; 220 case EISNAM: return EISNAM_PORTABLE; 221 case EREMOTEIO: return EREMOTEIO_PORTABLE; 222 case EDQUOT: return EDQUOT_PORTABLE; 223 case ENOMEDIUM: return ENOMEDIUM_PORTABLE; 224 case EMEDIUMTYPE: return EMEDIUMTYPE_PORTABLE; 225 case ECANCELED: return ECANCELED_PORTABLE; 226 case ENOKEY: return ENOKEY_PORTABLE; 227 case EKEYEXPIRED: return EKEYEXPIRED_PORTABLE; 228 case EKEYREVOKED: return EKEYREVOKED_PORTABLE; 229 case EKEYREJECTED: return EKEYREJECTED_PORTABLE; 230 case EOWNERDEAD: return EOWNERDEAD_PORTABLE; 231 case ENOTRECOVERABLE: return ENOTRECOVERABLE_PORTABLE; 232 } 233 return native_errno; 234 } 235 236 static int errno_pton(int portable_errno) 237 { 238 switch (portable_errno) { 239 case ENAMETOOLONG_PORTABLE: return ENAMETOOLONG; 240 case ENOLCK_PORTABLE: return ENOLCK; 241 case ENOSYS_PORTABLE: return ENOSYS; 242 case ENOTEMPTY_PORTABLE: return ENOTEMPTY; 243 case ELOOP_PORTABLE: return ELOOP; 244 case EWOULDBLOCK_PORTABLE: return EWOULDBLOCK; 245 case ENOMSG_PORTABLE: return ENOMSG; 246 case EIDRM_PORTABLE: return EIDRM; 247 case ECHRNG_PORTABLE: return ECHRNG; 248 case EL2NSYNC_PORTABLE: return EL2NSYNC; 249 case EL3HLT_PORTABLE: return EL3HLT; 250 case EL3RST_PORTABLE: return EL3RST; 251 case ELNRNG_PORTABLE: return ELNRNG; 252 case EUNATCH_PORTABLE: return EUNATCH; 253 case ENOCSI_PORTABLE: return ENOCSI; 254 case EL2HLT_PORTABLE: return EL2HLT; 255 case EBADE_PORTABLE: return EBADE; 256 case EBADR_PORTABLE: return EBADR; 257 case EXFULL_PORTABLE: return EXFULL; 258 case ENOANO_PORTABLE: return ENOANO; 259 case EBADRQC_PORTABLE: return EBADRQC; 260 case EBADSLT_PORTABLE: return EBADSLT; 261 case EDEADLOCK_PORTABLE: return EDEADLOCK; 262 case EBFONT_PORTABLE: return EBFONT; 263 case ENOSTR_PORTABLE: return ENOSTR; 264 case ENODATA_PORTABLE: return ENODATA; 265 case ETIME_PORTABLE: return ETIME; 266 case ENOSR_PORTABLE: return ENOSR; 267 case ENONET_PORTABLE: return ENONET; 268 case ENOPKG_PORTABLE: return ENOPKG; 269 case EREMOTE_PORTABLE: return EREMOTE; 270 case ENOLINK_PORTABLE: return ENOLINK; 271 case EADV_PORTABLE: return EADV; 272 case ESRMNT_PORTABLE: return ESRMNT; 273 case ECOMM_PORTABLE: return ECOMM; 274 case EPROTO_PORTABLE: return EPROTO; 275 case EMULTIHOP_PORTABLE: return EMULTIHOP; 276 case EDOTDOT_PORTABLE: return EDOTDOT; 277 case EBADMSG_PORTABLE: return EBADMSG; 278 case EOVERFLOW_PORTABLE: return EOVERFLOW; 279 case ENOTUNIQ_PORTABLE: return ENOTUNIQ; 280 case EBADFD_PORTABLE: return EBADFD; 281 case EREMCHG_PORTABLE: return EREMCHG; 282 case ELIBACC_PORTABLE: return ELIBACC; 283 case ELIBBAD_PORTABLE: return ELIBBAD; 284 case ELIBSCN_PORTABLE: return ELIBSCN; 285 case ELIBMAX_PORTABLE: return ELIBMAX; 286 case ELIBEXEC_PORTABLE: return ELIBEXEC; 287 case EILSEQ_PORTABLE: return EILSEQ; 288 case ERESTART_PORTABLE: return ERESTART; 289 case ESTRPIPE_PORTABLE: return ESTRPIPE; 290 case EUSERS_PORTABLE: return EUSERS; 291 case ENOTSOCK_PORTABLE: return ENOTSOCK; 292 case EDESTADDRREQ_PORTABLE: return EDESTADDRREQ; 293 case EMSGSIZE_PORTABLE: return EMSGSIZE; 294 case EPROTOTYPE_PORTABLE: return EPROTOTYPE; 295 case ENOPROTOOPT_PORTABLE: return ENOPROTOOPT; 296 case EPROTONOSUPPORT_PORTABLE: return EPROTONOSUPPORT; 297 case ESOCKTNOSUPPORT_PORTABLE: return ESOCKTNOSUPPORT; 298 case EOPNOTSUPP_PORTABLE: return EOPNOTSUPP; 299 case EPFNOSUPPORT_PORTABLE: return EPFNOSUPPORT; 300 case EAFNOSUPPORT_PORTABLE: return EAFNOSUPPORT; 301 case EADDRINUSE_PORTABLE: return EADDRINUSE; 302 case EADDRNOTAVAIL_PORTABLE: return EADDRNOTAVAIL; 303 case ENETDOWN_PORTABLE: return ENETDOWN; 304 case ENETUNREACH_PORTABLE: return ENETUNREACH; 305 case ENETRESET_PORTABLE: return ENETRESET; 306 case ECONNABORTED_PORTABLE: return ECONNABORTED; 307 case ECONNRESET_PORTABLE: return ECONNRESET; 308 case ENOBUFS_PORTABLE: return ENOBUFS; 309 case EISCONN_PORTABLE: return EISCONN; 310 case ENOTCONN_PORTABLE: return ENOTCONN; 311 case ESHUTDOWN_PORTABLE: return ESHUTDOWN; 312 case ETOOMANYREFS_PORTABLE: return ETOOMANYREFS; 313 case ETIMEDOUT_PORTABLE: return ETIMEDOUT; 314 case ECONNREFUSED_PORTABLE: return ECONNREFUSED; 315 case EHOSTDOWN_PORTABLE: return EHOSTDOWN; 316 case EHOSTUNREACH_PORTABLE: return EHOSTUNREACH; 317 case EALREADY_PORTABLE: return EALREADY; 318 case EINPROGRESS_PORTABLE: return EINPROGRESS; 319 case ESTALE_PORTABLE: return ESTALE; 320 case EUCLEAN_PORTABLE: return EUCLEAN; 321 case ENOTNAM_PORTABLE: return ENOTNAM; 322 case ENAVAIL_PORTABLE: return ENAVAIL; 323 case EISNAM_PORTABLE: return EISNAM; 324 case EREMOTEIO_PORTABLE: return EREMOTEIO; 325 case EDQUOT_PORTABLE: return EDQUOT; 326 case ENOMEDIUM_PORTABLE: return ENOMEDIUM; 327 case EMEDIUMTYPE_PORTABLE: return EMEDIUMTYPE; 328 case ECANCELED_PORTABLE: return ECANCELED; 329 case ENOKEY_PORTABLE: return ENOKEY; 330 case EKEYEXPIRED_PORTABLE: return EKEYEXPIRED; 331 case EKEYREVOKED_PORTABLE: return EKEYREVOKED; 332 case EKEYREJECTED_PORTABLE: return EKEYREJECTED; 333 case EOWNERDEAD_PORTABLE: return EOWNERDEAD; 334 case ENOTRECOVERABLE_PORTABLE: return ENOTRECOVERABLE; 335 } 336 return portable_errno; 337 } 338 339 /* Key for the thread-specific portable errno */ 340 static pthread_key_t errno_key; 341 342 /* Once-only initialisation of the key */ 343 static pthread_once_t errno_key_once = PTHREAD_ONCE_INIT; 344 345 /* Free the thread-specific portable errno */ 346 static void errno_key_destroy(void *buf) 347 { 348 if (buf) 349 free(buf); 350 } 351 352 /* Allocate the key */ 353 static void errno_key_create(void) 354 { 355 pthread_key_create(&errno_key, errno_key_destroy); 356 } 357 358 struct errno_state { 359 int pshadow; /* copy of last portable errno */ 360 int perrno; /* portable errno that may be modified by app */ 361 }; 362 363 /* Return the thread-specific portable errno */ 364 static struct errno_state *errno_key_data(void) 365 { 366 struct errno_state *data; 367 static struct errno_state errno_state; 368 369 pthread_once(&errno_key_once, errno_key_create); 370 data = (struct errno_state *)pthread_getspecific(errno_key); 371 if (data == NULL) { 372 data = malloc(sizeof(struct errno_state)); 373 pthread_setspecific(errno_key, data); 374 } 375 if (data == NULL) 376 data = &errno_state; 377 return data; 378 } 379 380 /* 381 * Attempt to return a thread specific location containnig the portable errno. 382 * This can be assigned to without affecting the native errno. If the key 383 * allocation fails fall back to using the native errno location. 384 */ 385 volatile int* WRAP(__errno)() 386 { 387 struct errno_state *p; 388 int save_errno; 389 390 /* pthread_* calls may modify errno so use a copy */ 391 save_errno = *REAL(__errno)(); 392 393 p = errno_key_data(); 394 395 ALOGV(" "); 396 ALOGV("%s(): { save_errno = errno:%d, (p:%p)->{pshadow:%d, perrno:%d}", __func__, 397 save_errno, p, p->pshadow, p->perrno); 398 399 if (save_errno == 0 && p->pshadow != p->perrno) { 400 /* 401 * portable errno has changed but native hasn't 402 * - copy portable error back to native 403 */ 404 p->pshadow = p->perrno; 405 save_errno = errno_pton(p->perrno); 406 } 407 else if (save_errno != 0 && p->pshadow == p->perrno) { 408 /* 409 * Native errno has changed but portable hasn't 410 * - copy native error to portable. 411 */ 412 p->pshadow = p->perrno = errno_ntop(save_errno); 413 save_errno = 0; 414 } 415 else if (save_errno != 0 && p->pshadow != p->perrno) { 416 /* 417 * Both native and portable errno values have changed 418 * so give priority to native errno 419 * - copy native error to portable 420 */ 421 p->pshadow = p->perrno = errno_ntop(save_errno); 422 save_errno = 0; 423 } 424 425 ALOGV("%s: new save_errno:%d p:%p->{pshadow:%d, perrno:%d}", __func__, 426 save_errno, p, p->pshadow, p->perrno); 427 428 *REAL(__errno)() = save_errno; 429 430 ALOGV("%s: return (&p->perrno):%p; }", __func__, &p->perrno); 431 432 /* return pointer to the modifiable portable errno value */ 433 return &p->perrno; 434 } 435 436 437 /* set portable errno */ 438 void WRAP(__set_errno)(int portable_errno) 439 { 440 struct errno_state *p; 441 int save_errno; 442 443 /* pthread_* calls may modify errno so use a copy */ 444 save_errno = *REAL(__errno)(); 445 446 p = errno_key_data(); 447 448 ALOGV("%s(): { save_errno = errno:%d, p:%p->{pshadow:%d, perrno:%d}", __func__, 449 save_errno, p, p->pshadow, p->perrno); 450 451 p->pshadow = p->perrno = portable_errno; 452 453 save_errno = errno_pton(portable_errno); 454 455 ALOGV("%s: new save_errno:%d, p:%p->{pshadow:%d, perrno:%d}", __func__, 456 save_errno, p, p->pshadow, p->perrno); 457 458 *REAL(__errno)() = save_errno; 459 460 ALOGV("%s: return; }", __func__); 461 } 462 463 extern char* REAL(strerror)(int); 464 char *WRAP(strerror)(int errnum) 465 { 466 return REAL(strerror)(errno_pton(errnum)); 467 } 468 469 /* BSD style strerror_r */ 470 int WRAP(strerror_r)(int errnum, char *buf, size_t buflen) 471 { 472 return REAL(strerror_r)(errno_pton(errnum), buf, buflen); 473 } 474 #endif /* _ERRNO_PORTABLE_H */ 475