• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
errno_ntop(int native_errno)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 
errno_pton(int portable_errno)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 */
errno_key_destroy(void * buf)243 static void errno_key_destroy(void *buf)
244 {
245     if (buf)
246         free(buf);
247 }
248 
249 /* Allocate the key */
errno_key_create(void)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 */
errno_key_data(void)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  */
WRAP(__errno)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 */
WRAP(__set_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);
WRAP(strerror)361 char *WRAP(strerror)(int errnum)
362 {
363     return REAL(strerror)(errno_pton(errnum));
364 }
365 
366 /* BSD style strerror_r */
WRAP(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