xref: /third_party/node/deps/uvwasi/src/uv_mapping.c (revision 1cb0ef41)
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
32uvwasi_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
111int 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
196uvwasi_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
202uvwasi_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
238void 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
250uvwasi_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