• 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 
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