/* * Attempt to return a thread specific location containnig the portable errno. * This can be assigned to without affecting the native errno. If the key * allocation fails fall back to using the native errno location. */ volatile int* WRAP(__errno)() { struct errno_state *p; int save_errno; /* pthread_* calls may modify errno so use a copy */ save_errno = *REAL(__errno)(); p = errno_key_data(); ALOGV(" "); ALOGV("%s(): { save_errno = errno:%d, (p:%p)->{pshadow:%d, perrno:%d}", __func__, save_errno, p, p->pshadow, p->perrno); if (save_errno == 0 && p->pshadow != p->perrno) { /* * portable errno has changed but native hasn't * - copy portable error back to native */ p->pshadow = p->perrno; save_errno = errno_pton(p->perrno); } else if (save_errno != 0 && p->pshadow == p->perrno) { /* * Native errno has changed but portable hasn't * - copy native error to portable. */ p->pshadow = p->perrno = errno_ntop(save_errno); save_errno = 0; } else if (save_errno != 0 && p->pshadow != p->perrno) { /* * Both native and portable errno values have changed * so give priority to native errno * - copy native error to portable */ p->pshadow = p->perrno = errno_ntop(save_errno); save_errno = 0; } ALOGV("%s: new save_errno:%d p:%p->{pshadow:%d, perrno:%d}", __func__, save_errno, p, p->pshadow, p->perrno); *REAL(__errno)() = save_errno; ALOGV("%s: return (&p->perrno):%p; }", __func__, &p->perrno); /* return pointer to the modifiable portable errno value */ return &p->perrno; }
/* set portable errno */ void WRAP(__set_errno)(int portable_errno) { struct errno_state *p; int save_errno; /* pthread_* calls may modify errno so use a copy */ save_errno = *REAL(__errno)(); p = errno_key_data(); ALOGV("%s(): { save_errno = errno:%d, p:%p->{pshadow:%d, perrno:%d}", __func__, save_errno, p, p->pshadow, p->perrno); p->pshadow = p->perrno = portable_errno; save_errno = errno_pton(portable_errno); ALOGV("%s: new save_errno:%d, p:%p->{pshadow:%d, perrno:%d}", __func__, save_errno, p, p->pshadow, p->perrno); *REAL(__errno)() = save_errno; ALOGV("%s: return; }", __func__); }
/* BSD style strerror_r */ int WRAP(strerror_r)(int errnum, char *buf, size_t buflen) { return REAL(strerror_r)(errno_pton(errnum), buf, buflen); }
char *WRAP(strerror)(int errnum) { return REAL(strerror)(errno_pton(errnum)); }
/* BSD style strerror_r */ int strerror_r_portable(int errnum, char *buf, size_t buflen) { return strerror_r(errno_pton(errnum), buf, buflen); }
char *strerror_portable(int errnum) { return strerror(errno_pton(errnum)); }