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