/src/httpd/srclib/apr/misc/unix/errorcodes.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Licensed to the Apache Software Foundation (ASF) under one or more |
2 | | * contributor license agreements. See the NOTICE file distributed with |
3 | | * this work for additional information regarding copyright ownership. |
4 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
5 | | * (the "License"); you may not use this file except in compliance with |
6 | | * the License. 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 "apr_arch_misc.h" |
18 | | #include "apr_strings.h" |
19 | | #include "apr_lib.h" |
20 | | #include "apr_dso.h" |
21 | | |
22 | | #include "apu_errno.h" |
23 | | |
24 | | #if APR_HAVE_NETDB_H |
25 | | #include <netdb.h> |
26 | | #endif |
27 | | #ifdef HAVE_DLFCN_H |
28 | | #include <dlfcn.h> |
29 | | #endif |
30 | | |
31 | | /* |
32 | | * stuffbuffer - like apr_cpystrn() but returns the address of the |
33 | | * dest buffer instead of the address of the terminating '\0' |
34 | | */ |
35 | | static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s) |
36 | 0 | { |
37 | 0 | apr_cpystrn(buf,s,bufsize); |
38 | 0 | return buf; |
39 | 0 | } |
40 | | |
41 | | static char *apr_error_string(apr_status_t statcode) |
42 | 0 | { |
43 | 0 | switch (statcode) { |
44 | 0 | case APR_ENOSTAT: |
45 | 0 | return "Could not perform a stat on the file."; |
46 | 0 | case APR_ENOPOOL: |
47 | 0 | return "A new pool could not be created."; |
48 | 0 | case APR_EBADDATE: |
49 | 0 | return "An invalid date has been provided"; |
50 | 0 | case APR_EINVALSOCK: |
51 | 0 | return "An invalid socket was returned"; |
52 | 0 | case APR_ENOPROC: |
53 | 0 | return "No process was provided and one was required."; |
54 | 0 | case APR_ENOTIME: |
55 | 0 | return "No time was provided and one was required."; |
56 | 0 | case APR_ENODIR: |
57 | 0 | return "No directory was provided and one was required."; |
58 | 0 | case APR_ENOLOCK: |
59 | 0 | return "No lock was provided and one was required."; |
60 | 0 | case APR_ENOPOLL: |
61 | 0 | return "No poll structure was provided and one was required."; |
62 | 0 | case APR_ENOSOCKET: |
63 | 0 | return "No socket was provided and one was required."; |
64 | 0 | case APR_ENOTHREAD: |
65 | 0 | return "No thread was provided and one was required."; |
66 | 0 | case APR_ENOTHDKEY: |
67 | 0 | return "No thread key structure was provided and one was required."; |
68 | 0 | case APR_ENOSHMAVAIL: |
69 | 0 | return "No shared memory is currently available"; |
70 | 0 | case APR_EDSOOPEN: |
71 | | #if APR_HAS_DSO && defined(HAVE_LIBDL) |
72 | | return dlerror(); |
73 | | #else |
74 | 0 | return "DSO load failed"; |
75 | 0 | #endif /* HAVE_LIBDL */ |
76 | 0 | case APR_EBADIP: |
77 | 0 | return "The specified IP address is invalid."; |
78 | 0 | case APR_EBADMASK: |
79 | 0 | return "The specified network mask is invalid."; |
80 | 0 | case APR_ESYMNOTFOUND: |
81 | 0 | return "Could not find the requested symbol."; |
82 | 0 | case APR_ENOTENOUGHENTROPY: |
83 | 0 | return "Not enough entropy to continue."; |
84 | 0 | case APR_INCHILD: |
85 | 0 | return |
86 | 0 | "Your code just forked, and you are currently executing in the " |
87 | 0 | "child process"; |
88 | 0 | case APR_INPARENT: |
89 | 0 | return |
90 | 0 | "Your code just forked, and you are currently executing in the " |
91 | 0 | "parent process"; |
92 | 0 | case APR_DETACH: |
93 | 0 | return "The specified thread is detached"; |
94 | 0 | case APR_NOTDETACH: |
95 | 0 | return "The specified thread is not detached"; |
96 | 0 | case APR_CHILD_DONE: |
97 | 0 | return "The specified child process is done executing"; |
98 | 0 | case APR_CHILD_NOTDONE: |
99 | 0 | return "The specified child process is not done executing"; |
100 | 0 | case APR_TIMEUP: |
101 | 0 | return "The timeout specified has expired"; |
102 | 0 | case APR_INCOMPLETE: |
103 | 0 | return "Partial results are valid but processing is incomplete"; |
104 | 0 | case APR_BADCH: |
105 | 0 | return "Bad character specified on command line"; |
106 | 0 | case APR_BADARG: |
107 | 0 | return "Missing parameter for the specified command line option"; |
108 | 0 | case APR_EOF: |
109 | 0 | return "End of file found"; |
110 | 0 | case APR_NOTFOUND: |
111 | 0 | return "Could not find specified socket in poll list."; |
112 | 0 | case APR_ANONYMOUS: |
113 | 0 | return "Shared memory is implemented anonymously"; |
114 | 0 | case APR_FILEBASED: |
115 | 0 | return "Shared memory is implemented using files"; |
116 | 0 | case APR_KEYBASED: |
117 | 0 | return "Shared memory is implemented using a key system"; |
118 | 0 | case APR_EINIT: |
119 | 0 | return |
120 | 0 | "There is no error, this value signifies an initialized " |
121 | 0 | "error code"; |
122 | 0 | case APR_ENOTIMPL: |
123 | 0 | return "This function has not been implemented on this platform"; |
124 | 0 | case APR_EMISMATCH: |
125 | 0 | return "passwords do not match"; |
126 | 0 | case APR_EABSOLUTE: |
127 | 0 | return "The given path is absolute"; |
128 | 0 | case APR_ERELATIVE: |
129 | 0 | return "The given path is relative"; |
130 | 0 | case APR_EINCOMPLETE: |
131 | 0 | return "The given path is incomplete"; |
132 | 0 | case APR_EABOVEROOT: |
133 | 0 | return "The given path was above the root path"; |
134 | 0 | case APR_EBADPATH: |
135 | 0 | return "The given path is misformatted or contained invalid characters"; |
136 | 0 | case APR_EPATHWILD: |
137 | 0 | return "The given path contained wildcard characters"; |
138 | 0 | case APR_EBUSY: |
139 | 0 | return "The given lock was busy."; |
140 | 0 | case APR_EPROC_UNKNOWN: |
141 | 0 | return "The process is not recognized."; |
142 | 0 | case APR_EALREADY: |
143 | 0 | return "Operation already in progress"; |
144 | 0 | case APR_EGENERAL: |
145 | 0 | return "Internal error (specific information not available)"; |
146 | | |
147 | | /* APR Util error codes */ |
148 | 0 | case APR_ECRYPT: |
149 | 0 | return "Internal error in the crypto subsystem (specific information not available)"; |
150 | 0 | case APR_ENOENGINE: |
151 | 0 | return "No engine found for crypto subsystem"; |
152 | 0 | case APR_EINITENGINE: |
153 | 0 | return "Failed to init engine for crypto subsystem"; |
154 | | |
155 | 0 | default: |
156 | 0 | return "Error string not specified yet"; |
157 | 0 | } |
158 | 0 | } |
159 | | |
160 | | |
161 | | #ifdef OS2 |
162 | | #include <ctype.h> |
163 | | |
164 | | int apr_canonical_error(apr_status_t err); |
165 | | |
166 | | static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err) |
167 | | { |
168 | | char result[200]; |
169 | | unsigned char message[HUGE_STRING_LEN]; |
170 | | ULONG len; |
171 | | char *pos; |
172 | | int c; |
173 | | |
174 | | if (err >= 10000 && err < 12000) { /* socket error codes */ |
175 | | return stuffbuffer(buf, bufsize, |
176 | | strerror(apr_canonical_error(err+APR_OS_START_SYSERR))); |
177 | | } |
178 | | else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err, |
179 | | "OSO001.MSG", &len) == 0) { |
180 | | len--; |
181 | | message[len] = 0; |
182 | | pos = result; |
183 | | |
184 | | if (len >= sizeof(result)) |
185 | | len = sizeof(result) - 1; |
186 | | |
187 | | for (c=0; c<len; c++) { |
188 | | /* skip multiple whitespace */ |
189 | | while (apr_isspace(message[c]) && apr_isspace(message[c+1])) |
190 | | c++; |
191 | | *(pos++) = apr_isspace(message[c]) ? ' ' : message[c]; |
192 | | } |
193 | | |
194 | | *pos = 0; |
195 | | } |
196 | | else { |
197 | | sprintf(result, "OS/2 error %d", err); |
198 | | } |
199 | | |
200 | | /* Stuff the string into the caller supplied buffer, then return |
201 | | * a pointer to it. |
202 | | */ |
203 | | return stuffbuffer(buf, bufsize, result); |
204 | | } |
205 | | |
206 | | #elif defined(WIN32) || (defined(NETWARE) && defined(USE_WINSOCK)) |
207 | | |
208 | | static const struct { |
209 | | apr_status_t code; |
210 | | const char *msg; |
211 | | } gaErrorList[] = { |
212 | | {WSAEINTR, "Interrupted system call"}, |
213 | | {WSAEBADF, "Bad file number"}, |
214 | | {WSAEACCES, "Permission denied"}, |
215 | | {WSAEFAULT, "Bad address"}, |
216 | | {WSAEINVAL, "Invalid argument"}, |
217 | | {WSAEMFILE, "Too many open sockets"}, |
218 | | {WSAEWOULDBLOCK, "Operation would block"}, |
219 | | {WSAEINPROGRESS, "Operation now in progress"}, |
220 | | {WSAEALREADY, "Operation already in progress"}, |
221 | | {WSAENOTSOCK, "Socket operation on non-socket"}, |
222 | | {WSAEDESTADDRREQ, "Destination address required"}, |
223 | | {WSAEMSGSIZE, "Message too long"}, |
224 | | {WSAEPROTOTYPE, "Protocol wrong type for socket"}, |
225 | | {WSAENOPROTOOPT, "Bad protocol option"}, |
226 | | {WSAEPROTONOSUPPORT, "Protocol not supported"}, |
227 | | {WSAESOCKTNOSUPPORT, "Socket type not supported"}, |
228 | | {WSAEOPNOTSUPP, "Operation not supported on socket"}, |
229 | | {WSAEPFNOSUPPORT, "Protocol family not supported"}, |
230 | | {WSAEAFNOSUPPORT, "Address family not supported"}, |
231 | | {WSAEADDRINUSE, "Address already in use"}, |
232 | | {WSAEADDRNOTAVAIL, "Can't assign requested address"}, |
233 | | {WSAENETDOWN, "Network is down"}, |
234 | | {WSAENETUNREACH, "Network is unreachable"}, |
235 | | {WSAENETRESET, "Net connection reset"}, |
236 | | {WSAECONNABORTED, "Software caused connection abort"}, |
237 | | {WSAECONNRESET, "Connection reset by peer"}, |
238 | | {WSAENOBUFS, "No buffer space available"}, |
239 | | {WSAEISCONN, "Socket is already connected"}, |
240 | | {WSAENOTCONN, "Socket is not connected"}, |
241 | | {WSAESHUTDOWN, "Can't send after socket shutdown"}, |
242 | | {WSAETOOMANYREFS, "Too many references, can't splice"}, |
243 | | {WSAETIMEDOUT, "Connection timed out"}, |
244 | | {WSAECONNREFUSED, "Connection refused"}, |
245 | | {WSAELOOP, "Too many levels of symbolic links"}, |
246 | | {WSAENAMETOOLONG, "File name too long"}, |
247 | | {WSAEHOSTDOWN, "Host is down"}, |
248 | | {WSAEHOSTUNREACH, "No route to host"}, |
249 | | {WSAENOTEMPTY, "Directory not empty"}, |
250 | | {WSAEPROCLIM, "Too many processes"}, |
251 | | {WSAEUSERS, "Too many users"}, |
252 | | {WSAEDQUOT, "Disc quota exceeded"}, |
253 | | {WSAESTALE, "Stale NFS file handle"}, |
254 | | {WSAEREMOTE, "Too many levels of remote in path"}, |
255 | | {WSASYSNOTREADY, "Network system is unavailable"}, |
256 | | {WSAVERNOTSUPPORTED, "Winsock version out of range"}, |
257 | | {WSANOTINITIALISED, "WSAStartup not yet called"}, |
258 | | {WSAEDISCON, "Graceful shutdown in progress"}, |
259 | | {WSAHOST_NOT_FOUND, "Host not found"}, |
260 | | {WSANO_DATA, "No host data of that type was found"}, |
261 | | {0, NULL} |
262 | | }; |
263 | | |
264 | | |
265 | | static char *apr_os_strerror(char *buf, apr_size_t bufsize, apr_status_t errcode) |
266 | | { |
267 | | apr_size_t len=0, i; |
268 | | |
269 | | #ifndef NETWARE |
270 | | len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
271 | | | FORMAT_MESSAGE_IGNORE_INSERTS, |
272 | | NULL, |
273 | | errcode, |
274 | | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ |
275 | | buf, |
276 | | (DWORD)bufsize, |
277 | | NULL); |
278 | | #endif |
279 | | |
280 | | if (!len) { |
281 | | for (i = 0; gaErrorList[i].msg; ++i) { |
282 | | if (gaErrorList[i].code == errcode) { |
283 | | apr_cpystrn(buf, gaErrorList[i].msg, bufsize); |
284 | | len = strlen(buf); |
285 | | break; |
286 | | } |
287 | | } |
288 | | } |
289 | | |
290 | | if (len) { |
291 | | /* FormatMessage put the message in the buffer, but it may |
292 | | * have embedded a newline (\r\n), and possible more than one. |
293 | | * Remove the newlines replacing them with a space. This is not |
294 | | * as visually perfect as moving all the remaining message over, |
295 | | * but more efficient. |
296 | | */ |
297 | | i = len; |
298 | | while (i) { |
299 | | i--; |
300 | | if ((buf[i] == '\r') || (buf[i] == '\n')) |
301 | | buf[i] = ' '; |
302 | | } |
303 | | } |
304 | | else { |
305 | | /* Windows didn't provide us with a message. Even stuff like * WSAECONNREFUSED won't get a message. |
306 | | */ |
307 | | apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode); |
308 | | } |
309 | | |
310 | | return buf; |
311 | | } |
312 | | |
313 | | #else |
314 | | /* On Unix, apr_os_strerror() handles error codes from the resolver |
315 | | * (h_errno). |
316 | | */ |
317 | | static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err) |
318 | 0 | { |
319 | | #ifdef HAVE_HSTRERROR |
320 | | return stuffbuffer(buf, bufsize, hstrerror(err)); |
321 | | #else /* HAVE_HSTRERROR */ |
322 | 0 | const char *msg; |
323 | |
|
324 | 0 | switch(err) { |
325 | 0 | case HOST_NOT_FOUND: |
326 | 0 | msg = "Unknown host"; |
327 | 0 | break; |
328 | 0 | #if defined(NO_DATA) |
329 | 0 | case NO_DATA: |
330 | | #if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS) |
331 | | case NO_ADDRESS: |
332 | | #endif |
333 | 0 | msg = "No address for host"; |
334 | 0 | break; |
335 | | #elif defined(NO_ADDRESS) |
336 | | case NO_ADDRESS: |
337 | | msg = "No address for host"; |
338 | | break; |
339 | | #endif /* NO_DATA */ |
340 | 0 | default: |
341 | 0 | msg = "Unrecognized resolver error"; |
342 | 0 | } |
343 | 0 | return stuffbuffer(buf, bufsize, msg); |
344 | 0 | #endif /* HAVE_STRERROR */ |
345 | 0 | } |
346 | | #endif |
347 | | |
348 | | #if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT) && !defined(BEOS) |
349 | | /* AIX and Tru64 style */ |
350 | | static char *native_strerror(apr_status_t statcode, char *buf, |
351 | | apr_size_t bufsize) |
352 | | { |
353 | | if (strerror_r(statcode, buf, bufsize) < 0) { |
354 | | return stuffbuffer(buf, bufsize, |
355 | | "APR does not understand this error code"); |
356 | | } |
357 | | else { |
358 | | return buf; |
359 | | } |
360 | | } |
361 | | #elif defined(HAVE_STRERROR_R) |
362 | | /* glibc style */ |
363 | | |
364 | | /* BeOS has the function available, but it doesn't provide |
365 | | * the prototype publicly (doh!), so to avoid a build warning |
366 | | * we add a suitable prototype here. |
367 | | */ |
368 | | #if defined(BEOS) |
369 | | const char *strerror_r(apr_status_t, char *, apr_size_t); |
370 | | #endif |
371 | | |
372 | | static char *native_strerror(apr_status_t statcode, char *buf, |
373 | | apr_size_t bufsize) |
374 | 0 | { |
375 | 0 | const char *msg; |
376 | |
|
377 | 0 | buf[0] = '\0'; |
378 | 0 | msg = strerror_r(statcode, buf, bufsize); |
379 | 0 | if (buf[0] == '\0') { /* libc didn't use our buffer */ |
380 | 0 | return stuffbuffer(buf, bufsize, msg); |
381 | 0 | } |
382 | 0 | else { |
383 | 0 | return buf; |
384 | 0 | } |
385 | 0 | } |
386 | | #else |
387 | | /* plain old strerror(); |
388 | | * thread-safe on some platforms (e.g., Solaris, OS/390) |
389 | | */ |
390 | | static char *native_strerror(apr_status_t statcode, char *buf, |
391 | | apr_size_t bufsize) |
392 | | { |
393 | | const char *err = strerror(statcode); |
394 | | if (err) { |
395 | | return stuffbuffer(buf, bufsize, err); |
396 | | } else { |
397 | | return stuffbuffer(buf, bufsize, |
398 | | "APR does not understand this error code"); |
399 | | } |
400 | | } |
401 | | #endif |
402 | | |
403 | | APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, |
404 | | apr_size_t bufsize) |
405 | 0 | { |
406 | 0 | if (statcode < APR_OS_START_ERROR) { |
407 | 0 | return native_strerror(statcode, buf, bufsize); |
408 | 0 | } |
409 | 0 | else if (statcode < APR_OS_START_USERERR) { |
410 | 0 | return stuffbuffer(buf, bufsize, apr_error_string(statcode)); |
411 | 0 | } |
412 | 0 | else if (statcode < APR_OS_START_EAIERR) { |
413 | 0 | return stuffbuffer(buf, bufsize, "APR does not understand this error code"); |
414 | 0 | } |
415 | 0 | else if (statcode < APR_OS_START_SYSERR) { |
416 | 0 | #if defined(HAVE_GAI_STRERROR) |
417 | 0 | statcode -= APR_OS_START_EAIERR; |
418 | 0 | #if defined(NEGATIVE_EAI) |
419 | 0 | statcode = -statcode; |
420 | 0 | #endif |
421 | 0 | return stuffbuffer(buf, bufsize, gai_strerror(statcode)); |
422 | | #else |
423 | | return stuffbuffer(buf, bufsize, "APR does not understand this error code"); |
424 | | #endif |
425 | 0 | } |
426 | 0 | else { |
427 | 0 | return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR); |
428 | 0 | } |
429 | 0 | } |
430 | | |