1 #include <sys/stat.h>
2
3 #ifndef _WIN32
4 # include <sys/types.h>
5 #endif /* _WIN32 */
6
7 #include "uv.h"
8 #include "wasi_types.h"
9 #include "uv_mapping.h"
10
11 #if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
12 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
13 #endif
14
15 #if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
16 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
17 #endif
18
19 #if !defined(S_ISCHR) && defined(S_IFMT) && defined(S_IFCHR)
20 # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
21 #endif
22
23 #if !defined(S_ISLNK) && defined(S_IFMT) && defined(S_IFLNK)
24 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
25 #endif
26
27
uvwasi__translate_uv_error(int err)28 uvwasi_errno_t uvwasi__translate_uv_error(int err) {
29 switch (err) {
30 case UV_E2BIG: return UVWASI_E2BIG;
31 case UV_EACCES: return UVWASI_EACCES;
32 case UV_EADDRINUSE: return UVWASI_EADDRINUSE;
33 case UV_EADDRNOTAVAIL: return UVWASI_EADDRNOTAVAIL;
34 case UV_EAFNOSUPPORT: return UVWASI_EAFNOSUPPORT;
35 case UV_EAGAIN: return UVWASI_EAGAIN;
36 case UV_EALREADY: return UVWASI_EALREADY;
37 case UV_EBADF: return UVWASI_EBADF;
38 case UV_EBUSY: return UVWASI_EBUSY;
39 case UV_ECANCELED: return UVWASI_ECANCELED;
40 case UV_ECONNABORTED: return UVWASI_ECONNABORTED;
41 case UV_ECONNREFUSED: return UVWASI_ECONNREFUSED;
42 case UV_ECONNRESET: return UVWASI_ECONNRESET;
43 case UV_EDESTADDRREQ: return UVWASI_EDESTADDRREQ;
44 case UV_EEXIST: return UVWASI_EEXIST;
45 case UV_EFAULT: return UVWASI_EFAULT;
46 case UV_EFBIG: return UVWASI_EFBIG;
47 case UV_EHOSTUNREACH: return UVWASI_EHOSTUNREACH;
48 case UV_EINTR: return UVWASI_EINTR;
49 case UV_EINVAL: return UVWASI_EINVAL;
50 case UV_EIO: return UVWASI_EIO;
51 case UV_EISCONN: return UVWASI_EISCONN;
52 case UV_EISDIR: return UVWASI_EISDIR;
53 case UV_ELOOP: return UVWASI_ELOOP;
54 case UV_EMFILE: return UVWASI_EMFILE;
55 case UV_EMLINK: return UVWASI_EMLINK;
56 case UV_EMSGSIZE: return UVWASI_EMSGSIZE;
57 case UV_ENAMETOOLONG: return UVWASI_ENAMETOOLONG;
58 case UV_ENETDOWN: return UVWASI_ENETDOWN;
59 case UV_ENETUNREACH: return UVWASI_ENETUNREACH;
60 case UV_ENFILE: return UVWASI_ENFILE;
61 case UV_ENOBUFS: return UVWASI_ENOBUFS;
62 case UV_ENODEV: return UVWASI_ENODEV;
63 case UV_ENOENT: return UVWASI_ENOENT;
64 case UV_ENOMEM: return UVWASI_ENOMEM;
65 case UV_ENOPROTOOPT: return UVWASI_ENOPROTOOPT;
66 case UV_ENOSPC: return UVWASI_ENOSPC;
67 case UV_ENOSYS: return UVWASI_ENOSYS;
68 case UV_ENOTCONN: return UVWASI_ENOTCONN;
69 case UV_ENOTDIR: return UVWASI_ENOTDIR;
70 /* On at least some AIX machines, ENOTEMPTY and EEXIST are equivalent. */
71 #if ENOTEMPTY != EEXIST
72 case UV_ENOTEMPTY: return UVWASI_ENOTEMPTY;
73 #endif /* ENOTEMPTY != EEXIST */
74 case UV_ENOTSOCK: return UVWASI_ENOTSOCK;
75 case UV_ENOTSUP: return UVWASI_ENOTSUP;
76 case UV_ENXIO: return UVWASI_ENXIO;
77 case UV_EPERM: return UVWASI_EPERM;
78 case UV_EPIPE: return UVWASI_EPIPE;
79 case UV_EPROTO: return UVWASI_EPROTO;
80 case UV_EPROTONOSUPPORT: return UVWASI_EPROTONOSUPPORT;
81 case UV_EPROTOTYPE: return UVWASI_EPROTOTYPE;
82 case UV_ERANGE: return UVWASI_ERANGE;
83 case UV_EROFS: return UVWASI_EROFS;
84 case UV_ESPIPE: return UVWASI_ESPIPE;
85 case UV_ESRCH: return UVWASI_ESRCH;
86 case UV_ETIMEDOUT: return UVWASI_ETIMEDOUT;
87 case UV_ETXTBSY: return UVWASI_ETXTBSY;
88 case UV_EXDEV: return UVWASI_EXDEV;
89 case 0: return UVWASI_ESUCCESS;
90 /* The following libuv error codes have no corresponding WASI error code:
91 UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, UV_EAI_BADHINTS,
92 UV_EAI_CANCELED, UV_EAI_FAIL, UV_EAI_FAMILY, UV_EAI_MEMORY,
93 UV_EAI_NODATA, UV_EAI_NONAME, UV_EAI_OVERFLOW, UV_EAI_PROTOCOL,
94 UV_EAI_SERVICE, UV_EAI_SOCKTYPE, UV_ECHARSET, UV_ENONET, UV_EOF,
95 UV_ESHUTDOWN, UV_UNKNOWN
96 */
97 default:
98 /* libuv errors are < 0 */
99 if (err > 0)
100 return err;
101
102 return UVWASI_ENOSYS;
103 }
104 }
105
106
uvwasi__translate_to_uv_signal(uvwasi_signal_t sig)107 int uvwasi__translate_to_uv_signal(uvwasi_signal_t sig) {
108 switch (sig) {
109 #ifdef SIGABRT
110 case UVWASI_SIGABRT: return SIGABRT;
111 #endif
112 #ifdef SIGALRM
113 case UVWASI_SIGALRM: return SIGALRM;
114 #endif
115 #ifdef SIGBUS
116 case UVWASI_SIGBUS: return SIGBUS;
117 #endif
118 #ifdef SIGCHLD
119 case UVWASI_SIGCHLD: return SIGCHLD;
120 #endif
121 #ifdef SIGCONT
122 case UVWASI_SIGCONT: return SIGCONT;
123 #endif
124 #ifdef SIGFPE
125 case UVWASI_SIGFPE: return SIGFPE;
126 #endif
127 #ifdef SIGHUP
128 case UVWASI_SIGHUP: return SIGHUP;
129 #endif
130 #ifdef SIGILL
131 case UVWASI_SIGILL: return SIGILL;
132 #endif
133 #ifdef SIGINT
134 case UVWASI_SIGINT: return SIGINT;
135 #endif
136 #ifdef SIGKILL
137 case UVWASI_SIGKILL: return SIGKILL;
138 #endif
139 #ifdef SIGPIPE
140 case UVWASI_SIGPIPE: return SIGPIPE;
141 #endif
142 #ifdef SIGQUIT
143 case UVWASI_SIGQUIT: return SIGQUIT;
144 #endif
145 #ifdef SIGSEGV
146 case UVWASI_SIGSEGV: return SIGSEGV;
147 #endif
148 #ifdef SIGSTOP
149 case UVWASI_SIGSTOP: return SIGSTOP;
150 #endif
151 #ifdef SIGSYS
152 case UVWASI_SIGSYS: return SIGSYS;
153 #endif
154 #ifdef SIGTERM
155 case UVWASI_SIGTERM: return SIGTERM;
156 #endif
157 #ifdef SIGTRAP
158 case UVWASI_SIGTRAP: return SIGTRAP;
159 #endif
160 #ifdef SIGTSTP
161 case UVWASI_SIGTSTP: return SIGTSTP;
162 #endif
163 #ifdef SIGTTIN
164 case UVWASI_SIGTTIN: return SIGTTIN;
165 #endif
166 #ifdef SIGTTOU
167 case UVWASI_SIGTTOU: return SIGTTOU;
168 #endif
169 #ifdef SIGURG
170 case UVWASI_SIGURG: return SIGURG;
171 #endif
172 #ifdef SIGUSR1
173 case UVWASI_SIGUSR1: return SIGUSR1;
174 #endif
175 #ifdef SIGUSR2
176 case UVWASI_SIGUSR2: return SIGUSR2;
177 #endif
178 #ifdef SIGVTALRM
179 case UVWASI_SIGVTALRM: return SIGVTALRM;
180 #endif
181 #ifdef SIGXCPU
182 case UVWASI_SIGXCPU: return SIGXCPU;
183 #endif
184 #ifdef SIGXFSZ
185 case UVWASI_SIGXFSZ: return SIGXFSZ;
186 #endif
187 default: return -1;
188 }
189 }
190
191
uvwasi__timespec_to_timestamp(const uv_timespec_t * ts)192 uvwasi_timestamp_t uvwasi__timespec_to_timestamp(const uv_timespec_t* ts) {
193 /* TODO(cjihrig): Handle overflow. */
194 return (uvwasi_timestamp_t) ts->tv_sec * NANOS_PER_SEC + ts->tv_nsec;
195 }
196
197
uvwasi__stat_to_filetype(const uv_stat_t * stat)198 uvwasi_filetype_t uvwasi__stat_to_filetype(const uv_stat_t* stat) {
199 uint64_t mode;
200
201 mode = stat->st_mode;
202
203 if (S_ISREG(mode))
204 return UVWASI_FILETYPE_REGULAR_FILE;
205
206 if (S_ISDIR(mode))
207 return UVWASI_FILETYPE_DIRECTORY;
208
209 if (S_ISCHR(mode))
210 return UVWASI_FILETYPE_CHARACTER_DEVICE;
211
212 if (S_ISLNK(mode))
213 return UVWASI_FILETYPE_SYMBOLIC_LINK;
214
215 #ifdef S_ISSOCK
216 if (S_ISSOCK(mode))
217 return UVWASI_FILETYPE_SOCKET_STREAM;
218 #endif /* S_ISSOCK */
219
220 #ifdef S_ISFIFO
221 if (S_ISFIFO(mode))
222 return UVWASI_FILETYPE_SOCKET_STREAM;
223 #endif /* S_ISFIFO */
224
225 #ifdef S_ISBLK
226 if (S_ISBLK(mode))
227 return UVWASI_FILETYPE_BLOCK_DEVICE;
228 #endif /* S_ISBLK */
229
230 return UVWASI_FILETYPE_UNKNOWN;
231 }
232
233
uvwasi__stat_to_filestat(const uv_stat_t * stat,uvwasi_filestat_t * fs)234 void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs) {
235 fs->st_dev = stat->st_dev;
236 fs->st_ino = stat->st_ino;
237 fs->st_nlink = stat->st_nlink;
238 fs->st_size = stat->st_size;
239 fs->st_filetype = uvwasi__stat_to_filetype(stat);
240 fs->st_atim = uvwasi__timespec_to_timestamp(&stat->st_atim);
241 fs->st_mtim = uvwasi__timespec_to_timestamp(&stat->st_mtim);
242 fs->st_ctim = uvwasi__timespec_to_timestamp(&stat->st_ctim);
243 }
244
245
uvwasi__get_filetype_by_fd(uv_file fd,uvwasi_filetype_t * type)246 uvwasi_errno_t uvwasi__get_filetype_by_fd(uv_file fd, uvwasi_filetype_t* type) {
247 uv_fs_t req;
248 int r;
249
250 r = uv_fs_fstat(NULL, &req, fd, NULL);
251 if (r != 0) {
252 uv_fs_req_cleanup(&req);
253
254 /* Windows can't stat a TTY. */
255 if (uv_guess_handle(fd) == UV_TTY) {
256 *type = UVWASI_FILETYPE_CHARACTER_DEVICE;
257 return UVWASI_ESUCCESS;
258 }
259
260 *type = UVWASI_FILETYPE_UNKNOWN;
261 return uvwasi__translate_uv_error(r);
262 }
263
264 *type = uvwasi__stat_to_filetype(&req.statbuf);
265 uv_fs_req_cleanup(&req);
266
267 if (*type == UVWASI_FILETYPE_SOCKET_STREAM &&
268 uv_guess_handle(fd) == UV_UDP) {
269 *type = UVWASI_FILETYPE_SOCKET_DGRAM;
270 }
271
272 return UVWASI_ESUCCESS;
273 }
274