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