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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "apr_arch_misc.h"
18 #include "apr_strings.h"
30 * stuffbuffer - like apr_cpystrn() but returns the address of the
31 * dest buffer instead of the address of the terminating '\0'
33 static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s)
35 apr_cpystrn(buf,s,bufsize);
39 static char *apr_error_string(apr_status_t statcode)
43 return "A new pool could not be created.";
45 return "An invalid date has been provided";
47 return "An invalid socket was returned";
49 return "No process was provided and one was required.";
51 return "No time was provided and one was required.";
53 return "No directory was provided and one was required.";
55 return "No lock was provided and one was required.";
57 return "No poll structure was provided and one was required.";
59 return "No socket was provided and one was required.";
61 return "No thread was provided and one was required.";
63 return "No thread key structure was provided and one was required.";
65 return "No shared memory is currently available";
67 #if APR_HAS_DSO && defined(HAVE_LIBDL)
70 return "DSO load failed";
71 #endif /* HAVE_LIBDL */
73 return "The specified IP address is invalid.";
75 return "The specified network mask is invalid.";
79 "Your code just forked, and you are currently executing in the "
83 "Your code just forked, and you are currently executing in the "
86 return "The specified thread is detached";
88 return "The specified thread is not detached";
90 return "The specified child process is done executing";
91 case APR_CHILD_NOTDONE:
92 return "The specified child process is not done executing";
94 return "The timeout specified has expired";
96 return "Partial results are valid but processing is incomplete";
98 return "Bad character specified on command line";
100 return "Missing parameter for the specified command line option";
102 return "End of file found";
104 return "Could not find specified socket in poll list.";
106 return "Shared memory is implemented anonymously";
108 return "Shared memory is implemented using files";
110 return "Shared memory is implemented using a key system";
113 "There is no error, this value signifies an initialized "
116 return "This function has not been implemented on this platform";
118 return "passwords do not match";
120 return "The given path is absolute";
122 return "The given path is relative";
123 case APR_EINCOMPLETE:
124 return "The given path is incomplete";
126 return "The given path was above the root path";
128 return "The given path is misformatted or contained invalid characters";
130 return "The given path contained wildcard characters";
131 case APR_EPROC_UNKNOWN:
132 return "The process is not recognized.";
134 return "Internal error";
136 return "Error string not specified yet";
144 int apr_canonical_error(apr_status_t err);
146 static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
149 unsigned char message[HUGE_STRING_LEN];
154 if (err >= 10000 && err < 12000) { /* socket error codes */
155 return stuffbuffer(buf, bufsize,
156 strerror(apr_canonical_error(err+APR_OS_START_SYSERR)));
158 else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err,
159 "OSO001.MSG", &len) == 0) {
164 if (len >= sizeof(result))
165 len = sizeof(result) - 1;
167 for (c=0; c<len; c++) {
168 /* skip multiple whitespace */
169 while (apr_isspace(message[c]) && apr_isspace(message[c+1]))
171 *(pos++) = apr_isspace(message[c]) ? ' ' : message[c];
177 sprintf(result, "OS/2 error %d", err);
180 /* Stuff the string into the caller supplied buffer, then return
183 return stuffbuffer(buf, bufsize, result);
186 #elif defined(WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
188 static const struct {
192 {WSAEINTR, "Interrupted system call"},
193 {WSAEBADF, "Bad file number"},
194 {WSAEACCES, "Permission denied"},
195 {WSAEFAULT, "Bad address"},
196 {WSAEINVAL, "Invalid argument"},
197 {WSAEMFILE, "Too many open sockets"},
198 {WSAEWOULDBLOCK, "Operation would block"},
199 {WSAEINPROGRESS, "Operation now in progress"},
200 {WSAEALREADY, "Operation already in progress"},
201 {WSAENOTSOCK, "Socket operation on non-socket"},
202 {WSAEDESTADDRREQ, "Destination address required"},
203 {WSAEMSGSIZE, "Message too long"},
204 {WSAEPROTOTYPE, "Protocol wrong type for socket"},
205 {WSAENOPROTOOPT, "Bad protocol option"},
206 {WSAEPROTONOSUPPORT, "Protocol not supported"},
207 {WSAESOCKTNOSUPPORT, "Socket type not supported"},
208 {WSAEOPNOTSUPP, "Operation not supported on socket"},
209 {WSAEPFNOSUPPORT, "Protocol family not supported"},
210 {WSAEAFNOSUPPORT, "Address family not supported"},
211 {WSAEADDRINUSE, "Address already in use"},
212 {WSAEADDRNOTAVAIL, "Can't assign requested address"},
213 {WSAENETDOWN, "Network is down"},
214 {WSAENETUNREACH, "Network is unreachable"},
215 {WSAENETRESET, "Net connection reset"},
216 {WSAECONNABORTED, "Software caused connection abort"},
217 {WSAECONNRESET, "Connection reset by peer"},
218 {WSAENOBUFS, "No buffer space available"},
219 {WSAEISCONN, "Socket is already connected"},
220 {WSAENOTCONN, "Socket is not connected"},
221 {WSAESHUTDOWN, "Can't send after socket shutdown"},
222 {WSAETOOMANYREFS, "Too many references, can't splice"},
223 {WSAETIMEDOUT, "Connection timed out"},
224 {WSAECONNREFUSED, "Connection refused"},
225 {WSAELOOP, "Too many levels of symbolic links"},
226 {WSAENAMETOOLONG, "File name too long"},
227 {WSAEHOSTDOWN, "Host is down"},
228 {WSAEHOSTUNREACH, "No route to host"},
229 {WSAENOTEMPTY, "Directory not empty"},
230 {WSAEPROCLIM, "Too many processes"},
231 {WSAEUSERS, "Too many users"},
232 {WSAEDQUOT, "Disc quota exceeded"},
233 {WSAESTALE, "Stale NFS file handle"},
234 {WSAEREMOTE, "Too many levels of remote in path"},
235 {WSASYSNOTREADY, "Network system is unavailable"},
236 {WSAVERNOTSUPPORTED, "Winsock version out of range"},
237 {WSANOTINITIALISED, "WSAStartup not yet called"},
238 {WSAEDISCON, "Graceful shutdown in progress"},
239 {WSAHOST_NOT_FOUND, "Host not found"},
240 {WSANO_DATA, "No host data of that type was found"},
245 static char *apr_os_strerror(char *buf, apr_size_t bufsize, apr_status_t errcode)
251 len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
252 | FORMAT_MESSAGE_IGNORE_INSERTS,
255 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
259 #else /* _WIN32_WCE speaks unicode */
260 LPTSTR msg = (LPTSTR) buf;
261 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
262 | FORMAT_MESSAGE_IGNORE_INSERTS,
265 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
267 (DWORD) (bufsize/sizeof(TCHAR)),
269 /* in-place convert to US-ASCII, substituting '?' for non ASCII */
270 for(i = 0; i <= len; i++) {
271 if (msg[i] < 0x80 && msg[i] >= 0) {
272 buf[i] = (char) msg[i];
281 for (i = 0; gaErrorList[i].msg; ++i) {
282 if (gaErrorList[i].code == errcode) {
283 apr_cpystrn(buf, gaErrorList[i].msg, bufsize);
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.
300 if ((buf[i] == '\r') || (buf[i] == '\n'))
305 /* Windows didn't provide us with a message. Even stuff like * WSAECONNREFUSED won't get a message.
307 apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
314 /* On Unix, apr_os_strerror() handles error codes from the resolver
317 static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
319 #ifdef HAVE_HSTRERROR
320 return stuffbuffer(buf, bufsize, hstrerror(err));
321 #else /* HAVE_HSTRERROR */
326 msg = "Unknown host";
330 #if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
333 msg = "No address for host";
335 #elif defined(NO_ADDRESS)
337 msg = "No address for host";
341 msg = "Unrecognized resolver error";
343 return stuffbuffer(buf, bufsize, msg);
344 #endif /* HAVE_STRERROR */
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,
353 if (strerror_r(statcode, buf, bufsize) < 0) {
354 return stuffbuffer(buf, bufsize,
355 "APR does not understand this error code");
361 #elif defined(HAVE_STRERROR_R)
364 /* BeOS has the function available, but it doesn't provide
365 * the prototype publically (doh!), so to avoid a build warning
366 * we add a suitable prototype here.
369 const char *strerror_r(apr_status_t, char *, apr_size_t);
372 static char *native_strerror(apr_status_t statcode, char *buf,
378 msg = strerror_r(statcode, buf, bufsize);
379 if (buf[0] == '\0') { /* libc didn't use our buffer */
380 return stuffbuffer(buf, bufsize, msg);
387 /* plain old strerror();
388 * thread-safe on some platforms (e.g., Solaris, OS/390)
390 static char *native_strerror(apr_status_t statcode, char *buf,
395 sprintf(err, "Native Error #%d", statcode);
396 return stuffbuffer(buf, bufsize, err);
398 const char *err = strerror(statcode);
400 return stuffbuffer(buf, bufsize, err);
402 return stuffbuffer(buf, bufsize,
403 "APR does not understand this error code");
409 APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
412 if (statcode < APR_OS_START_ERROR) {
413 return native_strerror(statcode, buf, bufsize);
415 else if (statcode < APR_OS_START_USERERR) {
416 return stuffbuffer(buf, bufsize, apr_error_string(statcode));
418 else if (statcode < APR_OS_START_EAIERR) {
419 return stuffbuffer(buf, bufsize, "APR does not understand this error code");
421 else if (statcode < APR_OS_START_SYSERR) {
422 #if defined(HAVE_GAI_STRERROR)
423 statcode -= APR_OS_START_EAIERR;
424 #if defined(NEGATIVE_EAI)
425 statcode = -statcode;
427 return stuffbuffer(buf, bufsize, gai_strerror(statcode));
429 return stuffbuffer(buf, bufsize, "APR does not understand this error code");
433 return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);