2 |
- |
1 |
#include "lib.h"
|
|
|
2 |
#include "sys9.h"
|
|
|
3 |
#include <string.h>
|
|
|
4 |
#include <errno.h>
|
|
|
5 |
|
|
|
6 |
/* make this global, so programs can look at it if errno is unilluminating */
|
|
|
7 |
|
|
|
8 |
/* see also: ../stdio/strerror.c, with errno-> string mapping */
|
|
|
9 |
|
|
|
10 |
char _plan9err[ERRMAX];
|
|
|
11 |
|
|
|
12 |
static struct errmap {
|
|
|
13 |
int errno;
|
|
|
14 |
char *ename;
|
|
|
15 |
} map[] = {
|
|
|
16 |
/* from /sys/src/9/port/errstr.h */
|
|
|
17 |
{EINVAL, "inconsistent mount"},
|
|
|
18 |
{EINVAL, "not mounted"},
|
|
|
19 |
{EINVAL, "not in union"},
|
|
|
20 |
{EIO, "mount rpc error"},
|
|
|
21 |
{EIO, "mounted device shut down"},
|
|
|
22 |
{EPERM, "mounted directory forbids creation"},
|
|
|
23 |
{ENOENT, "does not exist"},
|
|
|
24 |
{ENXIO, "unknown device in # filename"},
|
|
|
25 |
{ENOTDIR, "not a directory"},
|
|
|
26 |
{EISDIR, "file is a directory"},
|
|
|
27 |
{EINVAL, "bad character in file name"},
|
|
|
28 |
{EINVAL, "file name syntax"},
|
|
|
29 |
{EPERM, "permission denied"},
|
|
|
30 |
{EPERM, "inappropriate use of fd"},
|
|
|
31 |
{EINVAL, "bad arg in system call"},
|
|
|
32 |
{EBUSY, "device or object already in use"},
|
|
|
33 |
{EIO, "i/o error"},
|
|
|
34 |
{EIO, "read or write too large"},
|
|
|
35 |
{EIO, "read or write too small"},
|
|
|
36 |
{EADDRINUSE, "network port not available"},
|
|
|
37 |
{ESHUTDOWN, "write to hungup stream"},
|
|
|
38 |
{ESHUTDOWN, "i/o on hungup channel"},
|
|
|
39 |
{EINVAL, "bad process or channel control request"},
|
|
|
40 |
{EBUSY, "no free devices"},
|
|
|
41 |
{ESRCH, "process exited"},
|
|
|
42 |
{ECHILD, "no living children"},
|
|
|
43 |
{EIO, "i/o error in demand load"},
|
|
|
44 |
{ENOMEM, "virtual memory allocation failed"},
|
|
|
45 |
{EBADF, "fd out of range or not open"},
|
|
|
46 |
{EMFILE, "no free file descriptors"},
|
|
|
47 |
{ESPIPE, "seek on a stream"},
|
|
|
48 |
{ENOEXEC, "exec header invalid"},
|
|
|
49 |
{ETIMEDOUT, "connection timed out"},
|
|
|
50 |
{ECONNREFUSED, "connection refused"},
|
|
|
51 |
{ECONNREFUSED, "connection in use"},
|
|
|
52 |
{EINTR, "interrupted"},
|
|
|
53 |
{ENOMEM, "kernel allocate failed"},
|
|
|
54 |
{EINVAL, "segments overlap"},
|
|
|
55 |
{EIO, "i/o count too small"},
|
|
|
56 |
{EGREG, "ken has left the building"},
|
|
|
57 |
{EINVAL, "bad attach specifier"},
|
|
|
58 |
|
|
|
59 |
/* from exhausted() calls in kernel */
|
|
|
60 |
{ENFILE, "no free file descriptors"},
|
|
|
61 |
{EBUSY, "no free mount devices"},
|
|
|
62 |
{EBUSY, "no free mount rpc buffer"},
|
|
|
63 |
{EBUSY, "no free segments"},
|
|
|
64 |
{ENOMEM, "no free memory"},
|
|
|
65 |
{ENOBUFS, "no free Blocks"},
|
|
|
66 |
{EBUSY, "no free routes"},
|
|
|
67 |
|
|
|
68 |
/* from ken */
|
|
|
69 |
{EINVAL, "attach -- bad specifier"},
|
|
|
70 |
{EBADF, "unknown fid"},
|
|
|
71 |
{EINVAL, "bad character in directory name"},
|
|
|
72 |
{EBADF, "read/write -- on non open fid"},
|
|
|
73 |
{EIO, "read/write -- count too big"},
|
|
|
74 |
{EIO, "phase error -- directory entry not allocated"},
|
|
|
75 |
{EIO, "phase error -- qid does not match"},
|
|
|
76 |
{EACCES, "access permission denied"},
|
|
|
77 |
{ENOENT, "directory entry not found"},
|
|
|
78 |
{EINVAL, "open/create -- unknown mode"},
|
|
|
79 |
{ENOTDIR, "walk -- in a non-directory"},
|
|
|
80 |
{ENOTDIR, "create -- in a non-directory"},
|
|
|
81 |
{EIO, "phase error -- cannot happen"},
|
|
|
82 |
{EEXIST, "create -- file exists"},
|
|
|
83 |
{EINVAL, "create -- . and .. illegal names"},
|
|
|
84 |
{ENOTEMPTY, "directory not empty"},
|
|
|
85 |
{EINVAL, "attach -- privileged user"},
|
|
|
86 |
{EPERM, "wstat -- not owner"},
|
|
|
87 |
{EPERM, "wstat -- not in group"},
|
|
|
88 |
{EINVAL, "create/wstat -- bad character in file name"},
|
|
|
89 |
{EBUSY, "walk -- too many (system wide)"},
|
|
|
90 |
{EROFS, "file system read only"},
|
|
|
91 |
{ENOSPC, "file system full"},
|
|
|
92 |
{EINVAL, "read/write -- offset negative"},
|
|
|
93 |
{EBUSY, "open/create -- file is locked"},
|
|
|
94 |
{EBUSY, "close/read/write -- lock is broken"},
|
|
|
95 |
|
|
|
96 |
/* from sockets */
|
|
|
97 |
{ENOTSOCK, "not a socket"},
|
|
|
98 |
{EPROTONOSUPPORT, "protocol not supported"},
|
|
|
99 |
{ECONNREFUSED, "connection refused"},
|
|
|
100 |
{EAFNOSUPPORT, "address family not supported"},
|
|
|
101 |
{ENOBUFS, "insufficient buffer space"},
|
|
|
102 |
{EOPNOTSUPP, "operation not supported"},
|
|
|
103 |
{EADDRINUSE, "address in use"},
|
|
|
104 |
{EGREG, "unnamed error message"},
|
|
|
105 |
};
|
|
|
106 |
|
|
|
107 |
#define NERRMAP (sizeof(map)/sizeof(struct errmap))
|
|
|
108 |
|
|
|
109 |
/* convert last system call error to an errno */
|
|
|
110 |
void
|
|
|
111 |
_syserrno(void)
|
|
|
112 |
{
|
|
|
113 |
int i;
|
|
|
114 |
|
|
|
115 |
if(_ERRSTR(_plan9err, sizeof _plan9err) < 0)
|
|
|
116 |
errno = EINVAL;
|
|
|
117 |
else{
|
|
|
118 |
for(i = 0; i < NERRMAP; i++)
|
|
|
119 |
if(strstr(_plan9err, map[i].ename) != 0)
|
|
|
120 |
break;
|
|
|
121 |
_ERRSTR(_plan9err, sizeof _plan9err);
|
|
|
122 |
errno = (i < NERRMAP)? map[i].errno : EINVAL;
|
|
|
123 |
}
|
|
|
124 |
}
|