1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/*
3 * This file essentially replicates NSPR's source for the functions that
4 * map system-specific error codes to NSPR error codes.  We would use
5 * NSPR's functions, instead of duplicating them, but they're private.
6 * As long as SSL's server session cache code must do platform native I/O
7 * to accomplish its job, and NSPR's error mapping functions remain private,
8 * this code will continue to need to be replicated.
9 *
10 * This Source Code Form is subject to the terms of the Mozilla Public
11 * License, v. 2.0. If a copy of the MPL was not distributed with this
12 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
13
14#if 0
15#include "primpl.h"
16#else
17#define _PR_POLL_AVAILABLE 1
18#include "prerror.h"
19#endif
20
21#if defined (__bsdi__) || defined(NTO) || defined(DARWIN) || defined(BEOS)
22#undef _PR_POLL_AVAILABLE
23#endif
24
25#if defined(_PR_POLL_AVAILABLE)
26#include <poll.h>
27#endif
28#include <errno.h>
29
30/* forward declarations. */
31void nss_MD_unix_map_default_error(int err);
32
33void nss_MD_unix_map_opendir_error(int err)
34{
35    nss_MD_unix_map_default_error(err);
36}
37
38void nss_MD_unix_map_closedir_error(int err)
39{
40    PRErrorCode prError;
41    switch (err) {
42    case EINVAL:	prError = PR_BAD_DESCRIPTOR_ERROR; break;
43    default:		nss_MD_unix_map_default_error(err); return;
44    }
45    PR_SetError(prError, err);
46}
47
48void nss_MD_unix_readdir_error(int err)
49{
50    PRErrorCode prError;
51
52    switch (err) {
53    case ENOENT:	prError = PR_NO_MORE_FILES_ERROR; break;
54#ifdef EOVERFLOW
55    case EOVERFLOW:	prError = PR_IO_ERROR; break;
56#endif
57    case EINVAL:	prError = PR_IO_ERROR; break;
58    case ENXIO:		prError = PR_IO_ERROR; break;
59    default:		nss_MD_unix_map_default_error(err); return;
60    }
61    PR_SetError(prError, err);
62}
63
64void nss_MD_unix_map_unlink_error(int err)
65{
66    PRErrorCode prError;
67    switch (err) {
68    case EPERM:		prError = PR_IS_DIRECTORY_ERROR; break;
69    default:		nss_MD_unix_map_default_error(err); return;
70    }
71    PR_SetError(prError, err);
72}
73
74void nss_MD_unix_map_stat_error(int err)
75{
76    PRErrorCode prError;
77    switch (err) {
78    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
79    default:		nss_MD_unix_map_default_error(err); return;
80    }
81    PR_SetError(prError, err);
82}
83
84void nss_MD_unix_map_fstat_error(int err)
85{
86    PRErrorCode prError;
87    switch (err) {
88    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
89    default:		nss_MD_unix_map_default_error(err); return;
90    }
91    PR_SetError(prError, err);
92}
93
94void nss_MD_unix_map_rename_error(int err)
95{
96    PRErrorCode prError;
97    switch (err) {
98    case EEXIST:	prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break;
99    default:		nss_MD_unix_map_default_error(err); return;
100    }
101    PR_SetError(prError, err);
102}
103
104void nss_MD_unix_map_access_error(int err)
105{
106    PRErrorCode prError;
107    switch (err) {
108    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
109    default:		nss_MD_unix_map_default_error(err); return;
110    }
111    PR_SetError(prError, err);
112}
113
114void nss_MD_unix_map_mkdir_error(int err)
115{
116    nss_MD_unix_map_default_error(err);
117}
118
119void nss_MD_unix_map_rmdir_error(int err)
120{
121    PRErrorCode prError;
122
123    switch (err) {
124    case EEXIST:	prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break;
125    case EINVAL:	prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break;
126    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
127    default:		nss_MD_unix_map_default_error(err); return;
128    }
129    PR_SetError(prError, err);
130}
131
132void nss_MD_unix_map_read_error(int err)
133{
134    PRErrorCode prError;
135    switch (err) {
136    case EINVAL:	prError = PR_INVALID_METHOD_ERROR; break;
137    case ENXIO:		prError = PR_INVALID_ARGUMENT_ERROR; break;
138    default:		nss_MD_unix_map_default_error(err); return;
139    }
140    PR_SetError(prError, err);
141}
142
143void nss_MD_unix_map_write_error(int err)
144{
145    PRErrorCode prError;
146    switch (err) {
147    case EINVAL:	prError = PR_INVALID_METHOD_ERROR; break;
148    case ENXIO:		prError = PR_INVALID_METHOD_ERROR; break;
149    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
150    default:		nss_MD_unix_map_default_error(err); return;
151    }
152    PR_SetError(prError, err);
153}
154
155void nss_MD_unix_map_lseek_error(int err)
156{
157    nss_MD_unix_map_default_error(err);
158}
159
160void nss_MD_unix_map_fsync_error(int err)
161{
162    PRErrorCode prError;
163    switch (err) {
164    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
165    case EINVAL:	prError = PR_INVALID_METHOD_ERROR; break;
166    default:		nss_MD_unix_map_default_error(err); return;
167    }
168    PR_SetError(prError, err);
169}
170
171void nss_MD_unix_map_close_error(int err)
172{
173    PRErrorCode prError;
174    switch (err) {
175    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
176    default:		nss_MD_unix_map_default_error(err); return;
177    }
178    PR_SetError(prError, err);
179}
180
181void nss_MD_unix_map_socket_error(int err)
182{
183    PRErrorCode prError;
184    switch (err) {
185    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
186    default:		nss_MD_unix_map_default_error(err); return;
187    }
188    PR_SetError(prError, err);
189}
190
191void nss_MD_unix_map_socketavailable_error(int err)
192{
193    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
194}
195
196void nss_MD_unix_map_recv_error(int err)
197{
198    nss_MD_unix_map_default_error(err);
199}
200
201void nss_MD_unix_map_recvfrom_error(int err)
202{
203    nss_MD_unix_map_default_error(err);
204}
205
206void nss_MD_unix_map_send_error(int err)
207{
208    nss_MD_unix_map_default_error(err);
209}
210
211void nss_MD_unix_map_sendto_error(int err)
212{
213    nss_MD_unix_map_default_error(err);
214}
215
216void nss_MD_unix_map_writev_error(int err)
217{
218    nss_MD_unix_map_default_error(err);
219}
220
221void nss_MD_unix_map_accept_error(int err)
222{
223    PRErrorCode prError;
224    switch (err) {
225    case ENODEV:	prError = PR_NOT_TCP_SOCKET_ERROR; break;
226    default:		nss_MD_unix_map_default_error(err); return;
227    }
228    PR_SetError(prError, err);
229}
230
231void nss_MD_unix_map_connect_error(int err)
232{
233    PRErrorCode prError;
234    switch (err) {
235    case EACCES:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
236#if defined(UNIXWARE) || defined(SNI) || defined(NEC)
237    /*
238     * On some platforms, if we connect to a port on the local host
239     * (the loopback address) that no process is listening on, we get
240     * EIO instead of ECONNREFUSED.
241     */
242    case EIO:		prError = PR_CONNECT_REFUSED_ERROR; break;
243#endif
244    case ELOOP:		prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
245    case ENOENT:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
246    case ENXIO:		prError = PR_IO_ERROR; break;
247    default:		nss_MD_unix_map_default_error(err); return;
248    }
249    PR_SetError(prError, err);
250}
251
252void nss_MD_unix_map_bind_error(int err)
253{
254    PRErrorCode prError;
255    switch (err) {
256    case EINVAL:	prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break;
257        /*
258         * UNIX domain sockets are not supported in NSPR
259         */
260    case EIO:		prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
261    case EISDIR:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
262    case ELOOP:		prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
263    case ENOENT:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
264    case ENOTDIR:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
265    case EROFS:		prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
266    default:		nss_MD_unix_map_default_error(err); return;
267    }
268    PR_SetError(prError, err);
269}
270
271void nss_MD_unix_map_listen_error(int err)
272{
273    nss_MD_unix_map_default_error(err);
274}
275
276void nss_MD_unix_map_shutdown_error(int err)
277{
278    nss_MD_unix_map_default_error(err);
279}
280
281void nss_MD_unix_map_socketpair_error(int err)
282{
283    PRErrorCode prError;
284    switch (err) {
285    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
286    default:		nss_MD_unix_map_default_error(err); return;
287    }
288    PR_SetError(prError, err);
289}
290
291void nss_MD_unix_map_getsockname_error(int err)
292{
293    PRErrorCode prError;
294    switch (err) {
295    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
296    default:		nss_MD_unix_map_default_error(err); return;
297    }
298    PR_SetError(prError, err);
299}
300
301void nss_MD_unix_map_getpeername_error(int err)
302{
303    PRErrorCode prError;
304
305    switch (err) {
306    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
307    default:		nss_MD_unix_map_default_error(err); return;
308    }
309    PR_SetError(prError, err);
310}
311
312void nss_MD_unix_map_getsockopt_error(int err)
313{
314    PRErrorCode prError;
315    switch (err) {
316    case EINVAL:	prError = PR_BUFFER_OVERFLOW_ERROR; break;
317    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
318    default:		nss_MD_unix_map_default_error(err); return;
319    }
320    PR_SetError(prError, err);
321}
322
323void nss_MD_unix_map_setsockopt_error(int err)
324{
325    PRErrorCode prError;
326    switch (err) {
327    case EINVAL:	prError = PR_BUFFER_OVERFLOW_ERROR; break;
328    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
329    default:		nss_MD_unix_map_default_error(err); return;
330    }
331    PR_SetError(prError, err);
332}
333
334void nss_MD_unix_map_open_error(int err)
335{
336    PRErrorCode prError;
337    switch (err) {
338    case EAGAIN:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
339    case EBUSY:		prError = PR_IO_ERROR; break;
340    case ENODEV:	prError = PR_FILE_NOT_FOUND_ERROR; break;
341    case ENOMEM:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
342    case ETIMEDOUT:	prError = PR_REMOTE_FILE_ERROR; break;
343    default:		nss_MD_unix_map_default_error(err); return;
344    }
345    PR_SetError(prError, err);
346}
347
348void nss_MD_unix_map_mmap_error(int err)
349{
350    PRErrorCode prError;
351    switch (err) {
352    case EAGAIN:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
353    case EMFILE:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
354    case ENODEV:	prError = PR_OPERATION_NOT_SUPPORTED_ERROR; break;
355    case ENXIO:		prError = PR_INVALID_ARGUMENT_ERROR; break;
356    default:		nss_MD_unix_map_default_error(err); return;
357    }
358    PR_SetError(prError, err);
359}
360
361void nss_MD_unix_map_gethostname_error(int err)
362{
363    nss_MD_unix_map_default_error(err);
364}
365
366void nss_MD_unix_map_select_error(int err)
367{
368    nss_MD_unix_map_default_error(err);
369}
370
371#ifdef _PR_POLL_AVAILABLE
372void nss_MD_unix_map_poll_error(int err)
373{
374    PRErrorCode prError;
375
376    switch (err) {
377    case EAGAIN:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
378    default:		nss_MD_unix_map_default_error(err); return;
379    }
380    PR_SetError(prError, err);
381}
382
383void nss_MD_unix_map_poll_revents_error(int err)
384{
385    if (err & POLLNVAL)
386        PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
387    else if (err & POLLHUP)
388        PR_SetError(PR_CONNECT_RESET_ERROR, EPIPE);
389    else if (err & POLLERR)
390        PR_SetError(PR_IO_ERROR, EIO);
391    else
392        PR_SetError(PR_UNKNOWN_ERROR, err);
393}
394#endif /* _PR_POLL_AVAILABLE */
395
396
397void nss_MD_unix_map_flock_error(int err)
398{
399    PRErrorCode prError;
400    switch (err) {
401    case EINVAL:	prError = PR_BAD_DESCRIPTOR_ERROR; break;
402    case EWOULDBLOCK:	prError = PR_FILE_IS_LOCKED_ERROR; break;
403    default:		nss_MD_unix_map_default_error(err); return;
404    }
405    PR_SetError(prError, err);
406}
407
408void nss_MD_unix_map_lockf_error(int err)
409{
410    PRErrorCode prError;
411    switch (err) {
412    case EACCES:	prError = PR_FILE_IS_LOCKED_ERROR; break;
413    case EDEADLK:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
414    default:		nss_MD_unix_map_default_error(err); return;
415    }
416    PR_SetError(prError, err);
417}
418
419#ifdef HPUX11
420void nss_MD_hpux_map_sendfile_error(int err)
421{
422    nss_MD_unix_map_default_error(err);
423}
424#endif /* HPUX11 */
425
426
427void nss_MD_unix_map_default_error(int err)
428{
429    PRErrorCode prError;
430    switch (err ) {
431    case EACCES:	prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
432    case EADDRINUSE:	prError = PR_ADDRESS_IN_USE_ERROR; break;
433    case EADDRNOTAVAIL:	prError = PR_ADDRESS_NOT_AVAILABLE_ERROR; break;
434    case EAFNOSUPPORT:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
435    case EAGAIN:	prError = PR_WOULD_BLOCK_ERROR; break;
436    /*
437     * On QNX and Neutrino, EALREADY is defined as EBUSY.
438     */
439#if EALREADY != EBUSY
440    case EALREADY:	prError = PR_ALREADY_INITIATED_ERROR; break;
441#endif
442    case EBADF:		prError = PR_BAD_DESCRIPTOR_ERROR; break;
443#ifdef EBADMSG
444    case EBADMSG:	prError = PR_IO_ERROR; break;
445#endif
446    case EBUSY:		prError = PR_FILESYSTEM_MOUNTED_ERROR; break;
447    case ECONNREFUSED:	prError = PR_CONNECT_REFUSED_ERROR; break;
448    case ECONNRESET:	prError = PR_CONNECT_RESET_ERROR; break;
449    case EDEADLK:	prError = PR_DEADLOCK_ERROR; break;
450#ifdef EDIRCORRUPTED
451    case EDIRCORRUPTED:	prError = PR_DIRECTORY_CORRUPTED_ERROR; break;
452#endif
453#ifdef EDQUOT
454    case EDQUOT:	prError = PR_NO_DEVICE_SPACE_ERROR; break;
455#endif
456    case EEXIST:	prError = PR_FILE_EXISTS_ERROR; break;
457    case EFAULT:	prError = PR_ACCESS_FAULT_ERROR; break;
458    case EFBIG:		prError = PR_FILE_TOO_BIG_ERROR; break;
459    case EINPROGRESS:	prError = PR_IN_PROGRESS_ERROR; break;
460    case EINTR:		prError = PR_PENDING_INTERRUPT_ERROR; break;
461    case EINVAL:	prError = PR_INVALID_ARGUMENT_ERROR; break;
462    case EIO:		prError = PR_IO_ERROR; break;
463    case EISCONN:	prError = PR_IS_CONNECTED_ERROR; break;
464    case EISDIR:	prError = PR_IS_DIRECTORY_ERROR; break;
465    case ELOOP:		prError = PR_LOOP_ERROR; break;
466    case EMFILE:	prError = PR_PROC_DESC_TABLE_FULL_ERROR; break;
467    case EMLINK:	prError = PR_MAX_DIRECTORY_ENTRIES_ERROR; break;
468    case EMSGSIZE:	prError = PR_INVALID_ARGUMENT_ERROR; break;
469#ifdef EMULTIHOP
470    case EMULTIHOP:	prError = PR_REMOTE_FILE_ERROR; break;
471#endif
472    case ENAMETOOLONG:	prError = PR_NAME_TOO_LONG_ERROR; break;
473    case ENETUNREACH:	prError = PR_NETWORK_UNREACHABLE_ERROR; break;
474    case ENFILE:	prError = PR_SYS_DESC_TABLE_FULL_ERROR; break;
475#if !defined(SCO)
476    case ENOBUFS:	prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
477#endif
478    case ENODEV:	prError = PR_FILE_NOT_FOUND_ERROR; break;
479    case ENOENT:	prError = PR_FILE_NOT_FOUND_ERROR; break;
480    case ENOLCK:	prError = PR_FILE_IS_LOCKED_ERROR; break;
481#ifdef ENOLINK
482    case ENOLINK:	prError = PR_REMOTE_FILE_ERROR; break;
483#endif
484    case ENOMEM:	prError = PR_OUT_OF_MEMORY_ERROR; break;
485    case ENOPROTOOPT:	prError = PR_INVALID_ARGUMENT_ERROR; break;
486    case ENOSPC:	prError = PR_NO_DEVICE_SPACE_ERROR; break;
487#ifdef ENOSR
488    case ENOSR:		prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
489#endif
490    case ENOTCONN:	prError = PR_NOT_CONNECTED_ERROR; break;
491    case ENOTDIR:	prError = PR_NOT_DIRECTORY_ERROR; break;
492    case ENOTSOCK:	prError = PR_NOT_SOCKET_ERROR; break;
493    case ENXIO:		prError = PR_FILE_NOT_FOUND_ERROR; break;
494    case EOPNOTSUPP:	prError = PR_NOT_TCP_SOCKET_ERROR; break;
495#ifdef EOVERFLOW
496    case EOVERFLOW:	prError = PR_BUFFER_OVERFLOW_ERROR; break;
497#endif
498    case EPERM:		prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
499    case EPIPE:		prError = PR_CONNECT_RESET_ERROR; break;
500#ifdef EPROTO
501    case EPROTO:	prError = PR_IO_ERROR; break;
502#endif
503    case EPROTONOSUPPORT: prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR; break;
504    case EPROTOTYPE:	prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
505    case ERANGE:	prError = PR_INVALID_METHOD_ERROR; break;
506    case EROFS:		prError = PR_READ_ONLY_FILESYSTEM_ERROR; break;
507    case ESPIPE:	prError = PR_INVALID_METHOD_ERROR; break;
508    case ETIMEDOUT:	prError = PR_IO_TIMEOUT_ERROR; break;
509#if EWOULDBLOCK != EAGAIN
510    case EWOULDBLOCK:	prError = PR_WOULD_BLOCK_ERROR; break;
511#endif
512    case EXDEV:		prError = PR_NOT_SAME_DEVICE_ERROR; break;
513
514    default:		prError = PR_UNKNOWN_ERROR; break;
515    }
516    PR_SetError(prError, err);
517}
518