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