• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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