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	ADD_ERROR(EPFNOSUPPORT);
53	ADD_ERROR(EAFNOSUPPORT);
54	ADD_ERROR(EADDRINUSE);
55	ADD_ERROR(EADDRNOTAVAIL);
56	ADD_ERROR(ENETDOWN);
57	ADD_ERROR(ENETUNREACH);
58	ADD_ERROR(ENETRESET);
59	ADD_ERROR(ECONNABORTED);
60	ADD_ERROR(ECONNRESET);
61	ADD_ERROR(EISCONN);
62	ADD_ERROR(ENOTCONN);
63	ADD_ERROR(ESHUTDOWN);
64	ADD_ERROR(ECONNREFUSED);
65	ADD_ERROR(EHOSTUNREACH);
66	ADD_ERROR(ENOPROTOOPT);
67	ADD_ERROR(ENOBUFS);
68	ADD_ERROR(EINPROGRESS);
69	ADD_ERROR(EALREADY);
70	ADD_ERROR(EILSEQ);
71	ADD_ERROR(ENOMSG);
72	ADD_ERROR(ESTALE);
73	ADD_ERROR(EOVERFLOW);
74	ADD_ERROR(EMSGSIZE);
75	ADD_ERROR(EOPNOTSUPP);
76	ADD_ERROR(ENOTSOCK);
77	ADD_ERROR(EHOSTDOWN);
78	ADD_ERROR(EBADMSG);
79	#ifdef ECANCELED
80		ADD_ERROR(ECANCELED);
81	#endif
82	ADD_ERROR(EDESTADDRREQ);
83	ADD_ERROR(EDQUOT);
84	ADD_ERROR(EIDRM);
85	ADD_ERROR(EMULTIHOP);
86	#ifdef ENODATA
87		ADD_ERROR(ENODATA);
88	#endif
89	ADD_ERROR(ENOLINK);
90	#ifdef ENOSR
91		ADD_ERROR(ENOSR);
92	#endif
93	#ifdef ENOSTR
94		ADD_ERROR(ENOSTR);
95	#endif
96	ADD_ERROR(ENOTSUP);
97	ADD_ERROR(EPROTO);
98	#ifdef ETIME
99		ADD_ERROR(ETIME);
100	#endif
101	ADD_ERROR(ETXTBSY);
102	ADD_ERROR(ENOMEM);
103	ADD_ERROR(EACCES);
104	ADD_ERROR(EINTR);
105	ADD_ERROR(EIO);
106	ADD_ERROR(EBUSY);
107	ADD_ERROR(EFAULT);
108	ADD_ERROR(ETIMEDOUT);
109	ADD_ERROR(EAGAIN);
110	ADD_ERROR(EWOULDBLOCK);
111	ADD_ERROR(EBADF);
112	ADD_ERROR(EEXIST);
113	ADD_ERROR(EINVAL);
114	ADD_ERROR(ENAMETOOLONG);
115	ADD_ERROR(ENOENT);
116	ADD_ERROR(EPERM);
117	ADD_ERROR(ENOTDIR);
118	ADD_ERROR(EISDIR);
119	ADD_ERROR(ENOTEMPTY);
120	ADD_ERROR(ENOSPC);
121	ADD_ERROR(EROFS);
122	ADD_ERROR(EMFILE);
123	ADD_ERROR(EXDEV);
124	ADD_ERROR(ELOOP);
125	ADD_ERROR(ENOEXEC);
126	ADD_ERROR(EPIPE);
127	#ifdef ENOATTR
128		ADD_ERROR(ENOATTR);
129	#endif
130
131	sErrorMapsInitialized = true;
132}
133
134// to_host_error
135static int
136to_host_error(int error)
137{
138	init_error_map();
139
140	map<int, int>::iterator it = sToHostErrorMap.find(error);
141	return (it != sToHostErrorMap.end() ? it->second : error);
142}
143
144// to_haiku_error
145static int
146to_haiku_error(int error)
147{
148	init_error_map();
149
150	map<int, int>::iterator it = sToHaikuErrorMap.find(error);
151	if (it != sToHaikuErrorMap.end())
152		return it->second;
153
154	return (error > 0 ? -error : error);
155}
156
157// _haiku_build_strerror
158char *
159_haiku_build_strerror(int errnum)
160{
161	return strerror(to_host_error(errnum));
162}
163
164// _haiku_build_errno
165int *
166_haiku_build_errno()
167{
168	static int previousErrno = 0;
169	static int localErrno = 0;
170	static int previousLocalErrno = 0;
171
172	// If the localErrno has been changed and the real errno has not changed
173	// in the meantime, we update errno itself, so that the local update will
174	// be reflected. If errno has changed we always update localErrno.
175	int currentErrno = errno;
176	if (currentErrno == previousErrno) {
177		if (localErrno != previousLocalErrno) {
178			errno = previousErrno = to_host_error(localErrno);
179			previousLocalErrno = localErrno;
180		}
181	} else {
182		previousErrno = currentErrno;
183		previousLocalErrno = localErrno = to_haiku_error(errno);
184	}
185
186	return &localErrno;
187}
188
189// _haiku_to_host_error
190int
191_haiku_to_host_error(int error)
192{
193	return to_host_error(error);
194}
195