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 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 "Error string not specified yet";
142 int apr_canonical_error(apr_status_t err);
144 static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
147 unsigned char message[HUGE_STRING_LEN];
152 if (err >= 10000 && err < 12000) { /* socket error codes */
153 return stuffbuffer(buf, bufsize,
154 strerror(apr_canonical_error(err+APR_OS_START_SYSERR)));
156 else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err,
157 "OSO001.MSG", &len) == 0) {
162 if (len >= sizeof(result))
163 len = sizeof(result-1);
165 for (c=0; c<len; c++) {
166 /* skip multiple whitespace */
167 while (apr_isspace(message[c]) && apr_isspace(message[c+1]))
169 *(pos++) = apr_isspace(message[c]) ? ' ' : message[c];
175 sprintf(result, "OS/2 error %d", err);
178 /* Stuff the string into the caller supplied buffer, then return
181 return stuffbuffer(buf, bufsize, result);
184 #elif defined(WIN32) || defined(NETWARE)
186 static const struct {
190 WSAEINTR, "Interrupted system call",
191 WSAEBADF, "Bad file number",
192 WSAEACCES, "Permission denied",
193 WSAEFAULT, "Bad address",
194 WSAEINVAL, "Invalid argument",
195 WSAEMFILE, "Too many open sockets",
196 WSAEWOULDBLOCK, "Operation would block",
197 WSAEINPROGRESS, "Operation now in progress",
198 WSAEALREADY, "Operation already in progress",
199 WSAENOTSOCK, "Socket operation on non-socket",
200 WSAEDESTADDRREQ, "Destination address required",
201 WSAEMSGSIZE, "Message too long",
202 WSAEPROTOTYPE, "Protocol wrong type for socket",
203 WSAENOPROTOOPT, "Bad protocol option",
204 WSAEPROTONOSUPPORT, "Protocol not supported",
205 WSAESOCKTNOSUPPORT, "Socket type not supported",
206 WSAEOPNOTSUPP, "Operation not supported on socket",
207 WSAEPFNOSUPPORT, "Protocol family not supported",
208 WSAEAFNOSUPPORT, "Address family not supported",
209 WSAEADDRINUSE, "Address already in use",
210 WSAEADDRNOTAVAIL, "Can't assign requested address",
211 WSAENETDOWN, "Network is down",
212 WSAENETUNREACH, "Network is unreachable",
213 WSAENETRESET, "Net connection reset",
214 WSAECONNABORTED, "Software caused connection abort",
215 WSAECONNRESET, "Connection reset by peer",
216 WSAENOBUFS, "No buffer space available",
217 WSAEISCONN, "Socket is already connected",
218 WSAENOTCONN, "Socket is not connected",
219 WSAESHUTDOWN, "Can't send after socket shutdown",
220 WSAETOOMANYREFS, "Too many references, can't splice",
221 WSAETIMEDOUT, "Connection timed out",
222 WSAECONNREFUSED, "Connection refused",
223 WSAELOOP, "Too many levels of symbolic links",
224 WSAENAMETOOLONG, "File name too long",
225 WSAEHOSTDOWN, "Host is down",
226 WSAEHOSTUNREACH, "No route to host",
227 WSAENOTEMPTY, "Directory not empty",
228 WSAEPROCLIM, "Too many processes",
229 WSAEUSERS, "Too many users",
230 WSAEDQUOT, "Disc quota exceeded",
231 WSAESTALE, "Stale NFS file handle",
232 WSAEREMOTE, "Too many levels of remote in path",
233 WSASYSNOTREADY, "Network system is unavailable",
234 WSAVERNOTSUPPORTED, "Winsock version out of range",
235 WSANOTINITIALISED, "WSAStartup not yet called",
236 WSAEDISCON, "Graceful shutdown in progress",
237 WSAHOST_NOT_FOUND, "Host not found",
238 WSANO_DATA, "No host data of that type was found",
243 static char *apr_os_strerror(char *buf, apr_size_t bufsize, apr_status_t errcode)
248 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
249 | FORMAT_MESSAGE_IGNORE_INSERTS,
252 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
259 for (i = 0; gaErrorList[i].msg; ++i) {
260 if (gaErrorList[i].code == errcode) {
261 apr_cpystrn(buf, gaErrorList[i].msg, bufsize);
269 /* FormatMessage put the message in the buffer, but it may
270 * have embedded a newline (\r\n), and possible more than one.
271 * Remove the newlines replacing them with a space. This is not
272 * as visually perfect as moving all the remaining message over,
273 * but more efficient.
278 if ((buf[i] == '\r') || (buf[i] == '\n'))
283 /* Windows didn't provide us with a message. Even stuff like * WSAECONNREFUSED won't get a message.
285 apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
292 /* On Unix, apr_os_strerror() handles error codes from the resolver
295 static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
297 #ifdef HAVE_HSTRERROR
298 return stuffbuffer(buf, bufsize, hstrerror(err));
299 #else /* HAVE_HSTRERROR */
304 msg = "Unknown host";
308 #if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
311 msg = "No address for host";
313 #elif defined(NO_ADDRESS)
315 msg = "No address for host";
319 msg = "Unrecognized resolver error";
321 return stuffbuffer(buf, bufsize, msg);
322 #endif /* HAVE_STRERROR */
326 #if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT) && !defined(BEOS)
327 /* AIX and Tru64 style */
328 static char *native_strerror(apr_status_t statcode, char *buf,
331 if (strerror_r(statcode, buf, bufsize) < 0) {
332 return stuffbuffer(buf, bufsize,
333 "APR does not understand this error code");
339 #elif defined(HAVE_STRERROR_R)
342 /* BeOS has the function available, but it doesn't provide
343 * the prototype publically (doh!), so to avoid a build warning
344 * we add a suitable prototype here.
347 const char *strerror_r(apr_status_t, char *, apr_size_t);
350 static char *native_strerror(apr_status_t statcode, char *buf,
356 msg = strerror_r(statcode, buf, bufsize);
357 if (buf[0] == '\0') { /* libc didn't use our buffer */
358 return stuffbuffer(buf, bufsize, msg);
365 /* plain old strerror();
366 * thread-safe on some platforms (e.g., Solaris, OS/390)
368 static char *native_strerror(apr_status_t statcode, char *buf,
373 sprintf(err, "Native Error #%d", statcode);
374 return stuffbuffer(buf, bufsize, err);
376 const char *err = strerror(statcode);
378 return stuffbuffer(buf, bufsize, err);
380 return stuffbuffer(buf, bufsize,
381 "APR does not understand this error code");
387 APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
390 if (statcode < APR_OS_START_ERROR) {
391 return native_strerror(statcode, buf, bufsize);
393 else if (statcode < APR_OS_START_USERERR) {
394 return stuffbuffer(buf, bufsize, apr_error_string(statcode));
396 else if (statcode < APR_OS_START_EAIERR) {
397 return stuffbuffer(buf, bufsize, "APR does not understand this error code");
399 else if (statcode < APR_OS_START_SYSERR) {
400 #if defined(HAVE_GAI_STRERROR)
401 statcode -= APR_OS_START_EAIERR;
402 #if defined(NEGATIVE_EAI)
403 statcode = -statcode;
405 return stuffbuffer(buf, bufsize, gai_strerror(statcode));
407 return stuffbuffer(buf, bufsize, "APR does not understand this error code");
411 return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);