• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
errno_ntop(int native_errno)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 
errno_pton(int portable_errno)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 */
errno_key_destroy(void * buf)346 static void errno_key_destroy(void *buf)
347 {
348     if (buf)
349         free(buf);
350 }
351 
352 /* Allocate the key */
errno_key_create(void)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 */
errno_key_data(void)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  */
WRAP(__errno)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 */
WRAP(__set_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);
WRAP(strerror)464 char *WRAP(strerror)(int errnum)
465 {
466     return REAL(strerror)(errno_pton(errnum));
467 }
468 
469 /* BSD style strerror_r */
WRAP(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