1/*
2 * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <errno.h>
8#include <string.h>
9
10#include <map>
11
12using namespace std;
13
14static map<int, int> sToHaikuErrorMap;
15static map<int, int> sToHostErrorMap;
16static bool sErrorMapsInitialized = false;
17
18// init_error_map
19static void
20init_error_map()
21{
22	if (sErrorMapsInitialized)
23		return;
24
25	#define ADD_ERROR(error) \
26		sToHaikuErrorMap[error] = HAIKU_##error; \
27		sToHostErrorMap[HAIKU_##error] = error;
28
29	ADD_ERROR(E2BIG);
30	ADD_ERROR(ECHILD);
31	ADD_ERROR(EDEADLK);
32	ADD_ERROR(EFBIG);
33	ADD_ERROR(EMLINK);
34	ADD_ERROR(ENFILE);
35	ADD_ERROR(ENODEV);
36	ADD_ERROR(ENOLCK);
37	ADD_ERROR(ENOSYS);
38	ADD_ERROR(ENOTTY);
39	ADD_ERROR(ENXIO);
40	ADD_ERROR(ESPIPE);
41	ADD_ERROR(ESRCH);
42	#ifdef EFPOS
43		ADD_ERROR(EFPOS);
44	#endif
45	#ifdef ESIGPARM
46		ADD_ERROR(ESIGPARM);
47	#endif
48	ADD_ERROR(EDOM);
49	ADD_ERROR(ERANGE);
50	ADD_ERROR(EPROTOTYPE);
51	ADD_ERROR(EPROTONOSUPPORT);
52	#ifdef EPFNOSUPPORT
53		ADD_ERROR(EPFNOSUPPORT);
54	#endif
55	ADD_ERROR(EAFNOSUPPORT);
56	ADD_ERROR(EADDRINUSE);
57	ADD_ERROR(EADDRNOTAVAIL);
58	ADD_ERROR(ENETDOWN);
59	ADD_ERROR(ENETUNREACH);
60	ADD_ERROR(ENETRESET);
61	ADD_ERROR(ECONNABORTED);
62	ADD_ERROR(ECONNRESET);
63	ADD_ERROR(EISCONN);
64	ADD_ERROR(ENOTCONN);
65	#ifdef ESHUTDOWN
66		ADD_ERROR(ESHUTDOWN);
67	#endif
68	ADD_ERROR(ECONNREFUSED);
69	ADD_ERROR(EHOSTUNREACH);
70	ADD_ERROR(ENOPROTOOPT);
71	ADD_ERROR(ENOBUFS);
72	ADD_ERROR(EINPROGRESS);
73	ADD_ERROR(EALREADY);
74	ADD_ERROR(EILSEQ);
75	#ifdef ENOMSG
76		ADD_ERROR(ENOMSG);
77	#endif
78	#ifdef ESTALE
79		ADD_ERROR(ESTALE);
80	#endif
81	ADD_ERROR(EOVERFLOW);
82	ADD_ERROR(EMSGSIZE);
83	ADD_ERROR(EOPNOTSUPP);
84	ADD_ERROR(ENOTSOCK);
85	#ifdef EHOSTDOWN
86		ADD_ERROR(EHOSTDOWN);
87	#endif
88	#ifdef EBADMSG
89		ADD_ERROR(EBADMSG);
90	#endif
91	#ifdef ECANCELED
92		ADD_ERROR(ECANCELED);
93	#endif
94	ADD_ERROR(EDESTADDRREQ);
95	#ifdef EDQUOT
96		ADD_ERROR(EDQUOT);
97	#endif
98	#ifdef EIDRM
99		ADD_ERROR(EIDRM);
100	#endif
101	#ifdef EMULTIHOP
102		ADD_ERROR(EMULTIHOP);
103	#endif
104	#ifdef ENODATA
105		ADD_ERROR(ENODATA);
106	#endif
107	#ifdef ENOLINK
108		ADD_ERROR(ENOLINK);
109	#endif
110	#ifdef ENOSR
111		ADD_ERROR(ENOSR);
112	#endif
113	#ifdef ENOSTR
114		ADD_ERROR(ENOSTR);
115	#endif
116	ADD_ERROR(ENOTSUP);
117	ADD_ERROR(EPROTO);
118	#ifdef ETIME
119		ADD_ERROR(ETIME);
120	#endif
121	#ifdef ETXTBSY
122		ADD_ERROR(ETXTBSY);
123	#endif
124	ADD_ERROR(ENOMEM);
125	ADD_ERROR(EACCES);
126	ADD_ERROR(EINTR);
127	ADD_ERROR(EIO);
128	ADD_ERROR(EBUSY);
129	ADD_ERROR(EFAULT);
130	ADD_ERROR(ETIMEDOUT);
131	ADD_ERROR(EAGAIN);
132	ADD_ERROR(EWOULDBLOCK);
133	ADD_ERROR(EBADF);
134	ADD_ERROR(EEXIST);
135	ADD_ERROR(EINVAL);
136	ADD_ERROR(ENAMETOOLONG);
137	ADD_ERROR(ENOENT);
138	ADD_ERROR(EPERM);
139	ADD_ERROR(ENOTDIR);
140	ADD_ERROR(EISDIR);
141	ADD_ERROR(ENOTEMPTY);
142	ADD_ERROR(ENOSPC);
143	ADD_ERROR(EROFS);
144	ADD_ERROR(EMFILE);
145	ADD_ERROR(EXDEV);
146	ADD_ERROR(ELOOP);
147	ADD_ERROR(ENOEXEC);
148	ADD_ERROR(EPIPE);
149	#ifdef ENOATTR
150		ADD_ERROR(ENOATTR);
151	#endif
152
153	sErrorMapsInitialized = true;
154}
155
156// to_host_error
157static int
158to_host_error(int error)
159{
160	init_error_map();
161
162	map<int, int>::iterator it = sToHostErrorMap.find(error);
163	return (it != sToHostErrorMap.end() ? it->second : error);
164}
165
166// to_haiku_error
167static int
168to_haiku_error(int error)
169{
170	init_error_map();
171
172	map<int, int>::iterator it = sToHaikuErrorMap.find(error);
173	if (it != sToHaikuErrorMap.end())
174		return it->second;
175
176	return (error > 0 ? -error : error);
177}
178
179// _haiku_build_strerror
180char *
181_haiku_build_strerror(int errnum)
182{
183	return strerror(to_host_error(errnum));
184}
185
186// _haiku_build_errno
187int *
188_haiku_build_errno()
189{
190	static int previousErrno = 0;
191	static int localErrno = 0;
192	static int previousLocalErrno = 0;
193
194	// If the localErrno has been changed and the real errno has not changed
195	// in the meantime, we update errno itself, so that the local update will
196	// be reflected. If errno has changed we always update localErrno.
197	int currentErrno = errno;
198	if (currentErrno == previousErrno) {
199		if (localErrno != previousLocalErrno) {
200			errno = previousErrno = to_host_error(localErrno);
201			previousLocalErrno = localErrno;
202		}
203	} else {
204		previousErrno = currentErrno;
205		previousLocalErrno = localErrno = to_haiku_error(errno);
206	}
207
208	return &localErrno;
209}
210
211// _haiku_to_host_error
212int
213_haiku_to_host_error(int error)
214{
215	return to_host_error(error);
216}
217