1 #include <stdlib.h>
2 #include <string.h>
3
4 #ifndef _WIN32
5 # include <sched.h>
6 # include <sys/types.h>
7 # include <unistd.h>
8 # include <dirent.h>
9 # include <time.h>
10 #else
11 # include <io.h>
12 #endif /* _WIN32 */
13
14 #define UVWASI__READDIR_NUM_ENTRIES 1
15
16 #if !defined(_WIN32) && !defined(__ANDROID__)
17 # define UVWASI_FD_READDIR_SUPPORTED 1
18 #endif
19
20 #include "uvwasi.h"
21 #include "uvwasi_alloc.h"
22 #include "uv.h"
23 #include "uv_mapping.h"
24 #include "fd_table.h"
25 #include "clocks.h"
26 #include "path_resolver.h"
27 #include "poll_oneoff.h"
28 #include "wasi_rights.h"
29 #include "wasi_serdes.h"
30 #include "debug.h"
31
32 /* IBMi PASE does not support posix_fadvise() */
33 #ifdef __PASE__
34 # undef POSIX_FADV_NORMAL
35 #endif
36
37 #define VALIDATE_FSTFLAGS_OR_RETURN(flags) \
38 do { \
39 if ((flags) & ~(UVWASI_FILESTAT_SET_ATIM | \
40 UVWASI_FILESTAT_SET_ATIM_NOW | \
41 UVWASI_FILESTAT_SET_MTIM | \
42 UVWASI_FILESTAT_SET_MTIM_NOW)) { \
43 return UVWASI_EINVAL; \
44 } \
45 } while (0)
46
uvwasi__get_filestat_set_times(uvwasi_timestamp_t * st_atim,uvwasi_timestamp_t * st_mtim,uvwasi_fstflags_t fst_flags,uv_file * fd,char * path)47 static uvwasi_errno_t uvwasi__get_filestat_set_times(
48 uvwasi_timestamp_t* st_atim,
49 uvwasi_timestamp_t* st_mtim,
50 uvwasi_fstflags_t fst_flags,
51 uv_file* fd,
52 char* path
53 ) {
54 uvwasi_filestat_t stat;
55 uvwasi_timestamp_t now;
56 uvwasi_errno_t err;
57 uv_fs_t req;
58 int r;
59
60 /* Check if either value requires the current time. */
61 if ((fst_flags &
62 (UVWASI_FILESTAT_SET_ATIM_NOW | UVWASI_FILESTAT_SET_MTIM_NOW)) != 0) {
63 err = uvwasi__clock_gettime_realtime(&now);
64 if (err != UVWASI_ESUCCESS)
65 return err;
66 }
67
68 /* Check if either value is omitted. libuv doesn't have an 'omitted' option,
69 so get the current stats for the file. This approach isn't perfect, but it
70 will do until libuv can get better support here. */
71 if ((fst_flags &
72 (UVWASI_FILESTAT_SET_ATIM | UVWASI_FILESTAT_SET_ATIM_NOW)) == 0 ||
73 (fst_flags &
74 (UVWASI_FILESTAT_SET_MTIM | UVWASI_FILESTAT_SET_MTIM_NOW)) == 0) {
75
76 if (fd != NULL)
77 r = uv_fs_fstat(NULL, &req, *fd, NULL);
78 else
79 r = uv_fs_lstat(NULL, &req, path, NULL);
80
81 if (r != 0) {
82 uv_fs_req_cleanup(&req);
83 return uvwasi__translate_uv_error(r);
84 }
85
86 uvwasi__stat_to_filestat(&req.statbuf, &stat);
87 uv_fs_req_cleanup(&req);
88 }
89
90 /* Choose the provided time or 'now' and convert WASI timestamps from
91 nanoseconds to seconds due to libuv. */
92 if ((fst_flags & UVWASI_FILESTAT_SET_ATIM_NOW) != 0)
93 *st_atim = now / NANOS_PER_SEC;
94 else if ((fst_flags & UVWASI_FILESTAT_SET_ATIM) != 0)
95 *st_atim = *st_atim / NANOS_PER_SEC;
96 else
97 *st_atim = stat.st_atim / NANOS_PER_SEC;
98
99 if ((fst_flags & UVWASI_FILESTAT_SET_MTIM_NOW) != 0)
100 *st_mtim = now / NANOS_PER_SEC;
101 else if ((fst_flags & UVWASI_FILESTAT_SET_MTIM) != 0)
102 *st_mtim = *st_mtim / NANOS_PER_SEC;
103 else
104 *st_mtim = stat.st_mtim / NANOS_PER_SEC;
105
106 return UVWASI_ESUCCESS;
107 }
108
default_malloc(size_t size,void * mem_user_data)109 static void* default_malloc(size_t size, void* mem_user_data) {
110 return malloc(size);
111 }
112
default_free(void * ptr,void * mem_user_data)113 static void default_free(void* ptr, void* mem_user_data) {
114 free(ptr);
115 }
116
default_calloc(size_t nmemb,size_t size,void * mem_user_data)117 static void* default_calloc(size_t nmemb, size_t size, void* mem_user_data) {
118 return calloc(nmemb, size);
119 }
120
default_realloc(void * ptr,size_t size,void * mem_user_data)121 static void* default_realloc(void* ptr, size_t size, void* mem_user_data) {
122 return realloc(ptr, size);
123 }
124
uvwasi__malloc(const uvwasi_t * uvwasi,size_t size)125 void* uvwasi__malloc(const uvwasi_t* uvwasi, size_t size) {
126 return uvwasi->allocator->malloc(size, uvwasi->allocator->mem_user_data);
127 }
128
uvwasi__free(const uvwasi_t * uvwasi,void * ptr)129 void uvwasi__free(const uvwasi_t* uvwasi, void* ptr) {
130 uvwasi->allocator->free(ptr, uvwasi->allocator->mem_user_data);
131 }
132
uvwasi__calloc(const uvwasi_t * uvwasi,size_t nmemb,size_t size)133 void* uvwasi__calloc(const uvwasi_t* uvwasi, size_t nmemb, size_t size) {
134 return uvwasi->allocator->calloc(nmemb,
135 size,
136 uvwasi->allocator->mem_user_data);
137 }
138
uvwasi__realloc(const uvwasi_t * uvwasi,void * ptr,size_t size)139 void* uvwasi__realloc(const uvwasi_t* uvwasi, void* ptr, size_t size) {
140 return uvwasi->allocator->realloc(ptr,
141 size,
142 uvwasi->allocator->mem_user_data);
143 }
144
145 static const uvwasi_mem_t default_allocator = {
146 NULL,
147 default_malloc,
148 default_free,
149 default_calloc,
150 default_realloc,
151 };
152
153
uvwasi__lseek(uv_file fd,uvwasi_filedelta_t offset,uvwasi_whence_t whence,uvwasi_filesize_t * newoffset)154 static uvwasi_errno_t uvwasi__lseek(uv_file fd,
155 uvwasi_filedelta_t offset,
156 uvwasi_whence_t whence,
157 uvwasi_filesize_t* newoffset) {
158 int real_whence;
159
160 if (whence == UVWASI_WHENCE_CUR)
161 real_whence = SEEK_CUR;
162 else if (whence == UVWASI_WHENCE_END)
163 real_whence = SEEK_END;
164 else if (whence == UVWASI_WHENCE_SET)
165 real_whence = SEEK_SET;
166 else
167 return UVWASI_EINVAL;
168
169 #ifdef _WIN32
170 int64_t r;
171
172 r = _lseeki64(fd, offset, real_whence);
173 if (-1L == r)
174 return uvwasi__translate_uv_error(uv_translate_sys_error(errno));
175 #else
176 off_t r;
177
178 r = lseek(fd, offset, real_whence);
179 if ((off_t) -1 == r)
180 return uvwasi__translate_uv_error(uv_translate_sys_error(errno));
181 #endif /* _WIN32 */
182
183 *newoffset = r;
184 return UVWASI_ESUCCESS;
185 }
186
187
uvwasi__setup_iovs(const uvwasi_t * uvwasi,uv_buf_t ** buffers,const uvwasi_iovec_t * iovs,uvwasi_size_t iovs_len)188 static uvwasi_errno_t uvwasi__setup_iovs(const uvwasi_t* uvwasi,
189 uv_buf_t** buffers,
190 const uvwasi_iovec_t* iovs,
191 uvwasi_size_t iovs_len) {
192 uv_buf_t* bufs;
193 uvwasi_size_t i;
194
195 if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len)
196 return UVWASI_ENOMEM;
197
198 bufs = uvwasi__malloc(uvwasi, iovs_len * sizeof(*bufs));
199 if (bufs == NULL)
200 return UVWASI_ENOMEM;
201
202 for (i = 0; i < iovs_len; ++i)
203 bufs[i] = uv_buf_init(iovs[i].buf, iovs[i].buf_len);
204
205 *buffers = bufs;
206 return UVWASI_ESUCCESS;
207 }
208
209
uvwasi__setup_ciovs(const uvwasi_t * uvwasi,uv_buf_t ** buffers,const uvwasi_ciovec_t * iovs,uvwasi_size_t iovs_len)210 static uvwasi_errno_t uvwasi__setup_ciovs(const uvwasi_t* uvwasi,
211 uv_buf_t** buffers,
212 const uvwasi_ciovec_t* iovs,
213 uvwasi_size_t iovs_len) {
214 uv_buf_t* bufs;
215 uvwasi_size_t i;
216
217 if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len)
218 return UVWASI_ENOMEM;
219
220 bufs = uvwasi__malloc(uvwasi, iovs_len * sizeof(*bufs));
221 if (bufs == NULL)
222 return UVWASI_ENOMEM;
223
224 for (i = 0; i < iovs_len; ++i)
225 bufs[i] = uv_buf_init((char*)iovs[i].buf, iovs[i].buf_len);
226
227 *buffers = bufs;
228 return UVWASI_ESUCCESS;
229 }
230
231
uvwasi_init(uvwasi_t * uvwasi,uvwasi_options_t * options)232 uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) {
233 uv_fs_t realpath_req;
234 uv_fs_t open_req;
235 uvwasi_errno_t err;
236 uvwasi_size_t args_size;
237 uvwasi_size_t size;
238 uvwasi_size_t offset;
239 uvwasi_size_t env_count;
240 uvwasi_size_t env_buf_size;
241 uvwasi_size_t i;
242 int r;
243
244 if (uvwasi == NULL || options == NULL || options->fd_table_size == 0)
245 return UVWASI_EINVAL;
246
247 uvwasi->allocator = options->allocator;
248 if (uvwasi->allocator == NULL)
249 uvwasi->allocator = &default_allocator;
250
251 uvwasi->argv_buf = NULL;
252 uvwasi->argv = NULL;
253 uvwasi->env_buf = NULL;
254 uvwasi->env = NULL;
255 uvwasi->fds = NULL;
256
257 args_size = 0;
258 for (i = 0; i < options->argc; ++i)
259 args_size += strlen(options->argv[i]) + 1;
260
261 uvwasi->argc = options->argc;
262 uvwasi->argv_buf_size = args_size;
263
264 if (args_size > 0) {
265 uvwasi->argv_buf = uvwasi__malloc(uvwasi, args_size);
266 if (uvwasi->argv_buf == NULL) {
267 err = UVWASI_ENOMEM;
268 goto exit;
269 }
270
271 uvwasi->argv = uvwasi__calloc(uvwasi, options->argc, sizeof(char*));
272 if (uvwasi->argv == NULL) {
273 err = UVWASI_ENOMEM;
274 goto exit;
275 }
276
277 offset = 0;
278 for (i = 0; i < options->argc; ++i) {
279 size = strlen(options->argv[i]) + 1;
280 memcpy(uvwasi->argv_buf + offset, options->argv[i], size);
281 uvwasi->argv[i] = uvwasi->argv_buf + offset;
282 offset += size;
283 }
284 }
285
286 env_count = 0;
287 env_buf_size = 0;
288 if (options->envp != NULL) {
289 while (options->envp[env_count] != NULL) {
290 env_buf_size += strlen(options->envp[env_count]) + 1;
291 env_count++;
292 }
293 }
294
295 uvwasi->envc = env_count;
296 uvwasi->env_buf_size = env_buf_size;
297
298 if (env_buf_size > 0) {
299 uvwasi->env_buf = uvwasi__malloc(uvwasi, env_buf_size);
300 if (uvwasi->env_buf == NULL) {
301 err = UVWASI_ENOMEM;
302 goto exit;
303 }
304
305 uvwasi->env = uvwasi__calloc(uvwasi, env_count, sizeof(char*));
306 if (uvwasi->env == NULL) {
307 err = UVWASI_ENOMEM;
308 goto exit;
309 }
310
311 offset = 0;
312 for (i = 0; i < env_count; ++i) {
313 size = strlen(options->envp[i]) + 1;
314 memcpy(uvwasi->env_buf + offset, options->envp[i], size);
315 uvwasi->env[i] = uvwasi->env_buf + offset;
316 offset += size;
317 }
318 }
319
320 for (i = 0; i < options->preopenc; ++i) {
321 if (options->preopens[i].real_path == NULL ||
322 options->preopens[i].mapped_path == NULL) {
323 err = UVWASI_EINVAL;
324 goto exit;
325 }
326 }
327
328 err = uvwasi_fd_table_init(uvwasi, options);
329 if (err != UVWASI_ESUCCESS)
330 goto exit;
331
332 for (i = 0; i < options->preopenc; ++i) {
333 r = uv_fs_realpath(NULL,
334 &realpath_req,
335 options->preopens[i].real_path,
336 NULL);
337 if (r != 0) {
338 err = uvwasi__translate_uv_error(r);
339 uv_fs_req_cleanup(&realpath_req);
340 goto exit;
341 }
342
343 r = uv_fs_open(NULL, &open_req, realpath_req.ptr, 0, 0666, NULL);
344 if (r < 0) {
345 err = uvwasi__translate_uv_error(r);
346 uv_fs_req_cleanup(&realpath_req);
347 uv_fs_req_cleanup(&open_req);
348 goto exit;
349 }
350
351 err = uvwasi_fd_table_insert_preopen(uvwasi,
352 uvwasi->fds,
353 open_req.result,
354 options->preopens[i].mapped_path,
355 realpath_req.ptr);
356 uv_fs_req_cleanup(&realpath_req);
357 uv_fs_req_cleanup(&open_req);
358
359 if (err != UVWASI_ESUCCESS)
360 goto exit;
361 }
362
363 return UVWASI_ESUCCESS;
364
365 exit:
366 uvwasi_destroy(uvwasi);
367 return err;
368 }
369
370
uvwasi_destroy(uvwasi_t * uvwasi)371 void uvwasi_destroy(uvwasi_t* uvwasi) {
372 if (uvwasi == NULL)
373 return;
374
375 uvwasi_fd_table_free(uvwasi, uvwasi->fds);
376 uvwasi__free(uvwasi, uvwasi->argv_buf);
377 uvwasi__free(uvwasi, uvwasi->argv);
378 uvwasi__free(uvwasi, uvwasi->env_buf);
379 uvwasi__free(uvwasi, uvwasi->env);
380 uvwasi->fds = NULL;
381 uvwasi->argv_buf = NULL;
382 uvwasi->argv = NULL;
383 uvwasi->env_buf = NULL;
384 uvwasi->env = NULL;
385 }
386
387
uvwasi_options_init(uvwasi_options_t * options)388 void uvwasi_options_init(uvwasi_options_t* options) {
389 if (options == NULL)
390 return;
391
392 options->in = 0;
393 options->out = 1;
394 options->err = 2;
395 options->fd_table_size = 3;
396 options->argc = 0;
397 options->argv = NULL;
398 options->envp = NULL;
399 options->preopenc = 0;
400 options->preopens = NULL;
401 options->allocator = NULL;
402 }
403
404
uvwasi_embedder_remap_fd(uvwasi_t * uvwasi,const uvwasi_fd_t fd,uv_file new_host_fd)405 uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi,
406 const uvwasi_fd_t fd,
407 uv_file new_host_fd) {
408 struct uvwasi_fd_wrap_t* wrap;
409 uvwasi_errno_t err;
410
411 if (uvwasi == NULL)
412 return UVWASI_EINVAL;
413
414 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0);
415 if (err != UVWASI_ESUCCESS)
416 return err;
417
418 wrap->fd = new_host_fd;
419 uv_mutex_unlock(&wrap->mutex);
420 return UVWASI_ESUCCESS;
421 }
422
423
uvwasi_args_get(uvwasi_t * uvwasi,char ** argv,char * argv_buf)424 uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf) {
425 uvwasi_size_t i;
426
427 UVWASI_DEBUG("uvwasi_args_get(uvwasi=%p, argv=%p, argv_buf=%p)\n",
428 uvwasi,
429 argv,
430 argv_buf);
431
432 if (uvwasi == NULL || argv == NULL || argv_buf == NULL)
433 return UVWASI_EINVAL;
434
435 for (i = 0; i < uvwasi->argc; ++i) {
436 argv[i] = argv_buf + (uvwasi->argv[i] - uvwasi->argv_buf);
437 }
438
439 memcpy(argv_buf, uvwasi->argv_buf, uvwasi->argv_buf_size);
440 return UVWASI_ESUCCESS;
441 }
442
443
uvwasi_args_sizes_get(uvwasi_t * uvwasi,uvwasi_size_t * argc,uvwasi_size_t * argv_buf_size)444 uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi,
445 uvwasi_size_t* argc,
446 uvwasi_size_t* argv_buf_size) {
447 UVWASI_DEBUG("uvwasi_args_sizes_get(uvwasi=%p, argc=%p, argv_buf_size=%p)\n",
448 uvwasi,
449 argc,
450 argv_buf_size);
451
452 if (uvwasi == NULL || argc == NULL || argv_buf_size == NULL)
453 return UVWASI_EINVAL;
454
455 *argc = uvwasi->argc;
456 *argv_buf_size = uvwasi->argv_buf_size;
457 return UVWASI_ESUCCESS;
458 }
459
460
uvwasi_clock_res_get(uvwasi_t * uvwasi,uvwasi_clockid_t clock_id,uvwasi_timestamp_t * resolution)461 uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi,
462 uvwasi_clockid_t clock_id,
463 uvwasi_timestamp_t* resolution) {
464 UVWASI_DEBUG("uvwasi_clock_res_get(uvwasi=%p, clock_id=%d, resolution=%p)\n",
465 uvwasi,
466 clock_id,
467 resolution);
468
469 if (uvwasi == NULL || resolution == NULL)
470 return UVWASI_EINVAL;
471
472 switch (clock_id) {
473 case UVWASI_CLOCK_MONOTONIC:
474 case UVWASI_CLOCK_REALTIME:
475 *resolution = 1; /* Nanosecond precision. */
476 return UVWASI_ESUCCESS;
477 case UVWASI_CLOCK_PROCESS_CPUTIME_ID:
478 return uvwasi__clock_getres_process_cputime(resolution);
479 case UVWASI_CLOCK_THREAD_CPUTIME_ID:
480 return uvwasi__clock_getres_thread_cputime(resolution);
481 default:
482 return UVWASI_EINVAL;
483 }
484 }
485
486
uvwasi_clock_time_get(uvwasi_t * uvwasi,uvwasi_clockid_t clock_id,uvwasi_timestamp_t precision,uvwasi_timestamp_t * time)487 uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi,
488 uvwasi_clockid_t clock_id,
489 uvwasi_timestamp_t precision,
490 uvwasi_timestamp_t* time) {
491 UVWASI_DEBUG("uvwasi_clock_time_get(uvwasi=%p, clock_id=%d, "
492 "precision=%"PRIu64", time=%p)\n",
493 uvwasi,
494 clock_id,
495 precision,
496 time);
497
498 if (uvwasi == NULL || time == NULL)
499 return UVWASI_EINVAL;
500
501 switch (clock_id) {
502 case UVWASI_CLOCK_MONOTONIC:
503 *time = uv_hrtime();
504 return UVWASI_ESUCCESS;
505 case UVWASI_CLOCK_REALTIME:
506 return uvwasi__clock_gettime_realtime(time);
507 case UVWASI_CLOCK_PROCESS_CPUTIME_ID:
508 return uvwasi__clock_gettime_process_cputime(time);
509 case UVWASI_CLOCK_THREAD_CPUTIME_ID:
510 return uvwasi__clock_gettime_thread_cputime(time);
511 default:
512 return UVWASI_EINVAL;
513 }
514 }
515
516
uvwasi_environ_get(uvwasi_t * uvwasi,char ** environment,char * environ_buf)517 uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi,
518 char** environment,
519 char* environ_buf) {
520 uvwasi_size_t i;
521
522 UVWASI_DEBUG("uvwasi_environ_get(uvwasi=%p, environment=%p, "
523 "environ_buf=%p)\n",
524 uvwasi,
525 environment,
526 environ_buf);
527
528 if (uvwasi == NULL || environment == NULL || environ_buf == NULL)
529 return UVWASI_EINVAL;
530
531 for (i = 0; i < uvwasi->envc; ++i) {
532 environment[i] = environ_buf + (uvwasi->env[i] - uvwasi->env_buf);
533 }
534
535 memcpy(environ_buf, uvwasi->env_buf, uvwasi->env_buf_size);
536 return UVWASI_ESUCCESS;
537 }
538
539
uvwasi_environ_sizes_get(uvwasi_t * uvwasi,uvwasi_size_t * environ_count,uvwasi_size_t * environ_buf_size)540 uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi,
541 uvwasi_size_t* environ_count,
542 uvwasi_size_t* environ_buf_size) {
543 UVWASI_DEBUG("uvwasi_environ_sizes_get(uvwasi=%p, environ_count=%p, "
544 "environ_buf_size=%p)\n",
545 uvwasi,
546 environ_count,
547 environ_buf_size);
548
549 if (uvwasi == NULL || environ_count == NULL || environ_buf_size == NULL)
550 return UVWASI_EINVAL;
551
552 *environ_count = uvwasi->envc;
553 *environ_buf_size = uvwasi->env_buf_size;
554 return UVWASI_ESUCCESS;
555 }
556
557
uvwasi_fd_advise(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_filesize_t offset,uvwasi_filesize_t len,uvwasi_advice_t advice)558 uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi,
559 uvwasi_fd_t fd,
560 uvwasi_filesize_t offset,
561 uvwasi_filesize_t len,
562 uvwasi_advice_t advice) {
563 struct uvwasi_fd_wrap_t* wrap;
564 uvwasi_errno_t err;
565 #ifdef POSIX_FADV_NORMAL
566 int mapped_advice;
567 int r;
568 #endif /* POSIX_FADV_NORMAL */
569
570 UVWASI_DEBUG("uvwasi_fd_advise(uvwasi=%p, fd=%d, offset=%"PRIu64", "
571 "len=%"PRIu64", advice=%d)\n",
572 uvwasi,
573 fd,
574 offset,
575 len,
576 advice);
577
578 if (uvwasi == NULL)
579 return UVWASI_EINVAL;
580
581 switch (advice) {
582 case UVWASI_ADVICE_DONTNEED:
583 #ifdef POSIX_FADV_NORMAL
584 mapped_advice = POSIX_FADV_DONTNEED;
585 #endif /* POSIX_FADV_NORMAL */
586 break;
587 case UVWASI_ADVICE_NOREUSE:
588 #ifdef POSIX_FADV_NORMAL
589 mapped_advice = POSIX_FADV_NOREUSE;
590 #endif /* POSIX_FADV_NORMAL */
591 break;
592 case UVWASI_ADVICE_NORMAL:
593 #ifdef POSIX_FADV_NORMAL
594 mapped_advice = POSIX_FADV_NORMAL;
595 #endif /* POSIX_FADV_NORMAL */
596 break;
597 case UVWASI_ADVICE_RANDOM:
598 #ifdef POSIX_FADV_NORMAL
599 mapped_advice = POSIX_FADV_RANDOM;
600 #endif /* POSIX_FADV_NORMAL */
601 break;
602 case UVWASI_ADVICE_SEQUENTIAL:
603 #ifdef POSIX_FADV_NORMAL
604 mapped_advice = POSIX_FADV_SEQUENTIAL;
605 #endif /* POSIX_FADV_NORMAL */
606 break;
607 case UVWASI_ADVICE_WILLNEED:
608 #ifdef POSIX_FADV_NORMAL
609 mapped_advice = POSIX_FADV_WILLNEED;
610 #endif /* POSIX_FADV_NORMAL */
611 break;
612 default:
613 return UVWASI_EINVAL;
614 }
615
616 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ADVISE, 0);
617 if (err != UVWASI_ESUCCESS)
618 return err;
619
620 err = UVWASI_ESUCCESS;
621
622 #ifdef POSIX_FADV_NORMAL
623 r = posix_fadvise(wrap->fd, offset, len, mapped_advice);
624 if (r != 0)
625 err = uvwasi__translate_uv_error(uv_translate_sys_error(r));
626 #endif /* POSIX_FADV_NORMAL */
627 uv_mutex_unlock(&wrap->mutex);
628 return err;
629 }
630
631
uvwasi_fd_allocate(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_filesize_t offset,uvwasi_filesize_t len)632 uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi,
633 uvwasi_fd_t fd,
634 uvwasi_filesize_t offset,
635 uvwasi_filesize_t len) {
636 #if !defined(__POSIX__)
637 uv_fs_t req;
638 uint64_t st_size;
639 #endif /* !__POSIX__ */
640 struct uvwasi_fd_wrap_t* wrap;
641 uvwasi_errno_t err;
642 int r;
643
644 UVWASI_DEBUG("uvwasi_fd_allocate(uvwasi=%p, fd=%d, offset=%"PRIu64", "
645 "len=%"PRIu64")\n",
646 uvwasi,
647 fd,
648 offset,
649 len);
650
651 if (uvwasi == NULL)
652 return UVWASI_EINVAL;
653
654 err = uvwasi_fd_table_get(uvwasi->fds,
655 fd,
656 &wrap,
657 UVWASI_RIGHT_FD_ALLOCATE,
658 0);
659 if (err != UVWASI_ESUCCESS)
660 return err;
661
662 /* Try to use posix_fallocate(). If that's not an option, fall back to the
663 race condition prone combination of fstat() + ftruncate(). */
664 #if defined(__POSIX__)
665 r = posix_fallocate(wrap->fd, offset, len);
666 if (r != 0) {
667 err = uvwasi__translate_uv_error(uv_translate_sys_error(r));
668 goto exit;
669 }
670 #else
671 r = uv_fs_fstat(NULL, &req, wrap->fd, NULL);
672 st_size = req.statbuf.st_size;
673 uv_fs_req_cleanup(&req);
674 if (r != 0) {
675 err = uvwasi__translate_uv_error(r);
676 goto exit;
677 }
678
679 if (st_size < offset + len) {
680 r = uv_fs_ftruncate(NULL, &req, wrap->fd, offset + len, NULL);
681 if (r != 0) {
682 err = uvwasi__translate_uv_error(r);
683 goto exit;
684 }
685 }
686 #endif /* __POSIX__ */
687
688 err = UVWASI_ESUCCESS;
689 exit:
690 uv_mutex_unlock(&wrap->mutex);
691 return err;
692 }
693
694
uvwasi_fd_close(uvwasi_t * uvwasi,uvwasi_fd_t fd)695 uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
696 struct uvwasi_fd_wrap_t* wrap;
697 uvwasi_errno_t err;
698 uv_fs_t req;
699 int r;
700
701 UVWASI_DEBUG("uvwasi_fd_close(uvwasi=%p, fd=%d)\n", uvwasi, fd);
702
703 if (uvwasi == NULL)
704 return UVWASI_EINVAL;
705
706 uvwasi_fd_table_lock(uvwasi->fds);
707
708 err = uvwasi_fd_table_get_nolock(uvwasi->fds, fd, &wrap, 0, 0);
709 if (err != UVWASI_ESUCCESS)
710 goto exit;
711
712 r = uv_fs_close(NULL, &req, wrap->fd, NULL);
713 uv_mutex_unlock(&wrap->mutex);
714 uv_fs_req_cleanup(&req);
715
716 if (r != 0) {
717 err = uvwasi__translate_uv_error(r);
718 goto exit;
719 }
720
721 err = uvwasi_fd_table_remove_nolock(uvwasi, uvwasi->fds, fd);
722
723 exit:
724 uvwasi_fd_table_unlock(uvwasi->fds);
725 return err;
726 }
727
728
uvwasi_fd_datasync(uvwasi_t * uvwasi,uvwasi_fd_t fd)729 uvwasi_errno_t uvwasi_fd_datasync(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
730 struct uvwasi_fd_wrap_t* wrap;
731 uvwasi_errno_t err;
732 uv_fs_t req;
733 int r;
734
735 UVWASI_DEBUG("uvwasi_fd_datasync(uvwasi=%p, fd=%d)\n", uvwasi, fd);
736
737 if (uvwasi == NULL)
738 return UVWASI_EINVAL;
739
740 err = uvwasi_fd_table_get(uvwasi->fds,
741 fd,
742 &wrap,
743 UVWASI_RIGHT_FD_DATASYNC,
744 0);
745 if (err != UVWASI_ESUCCESS)
746 return err;
747
748 r = uv_fs_fdatasync(NULL, &req, wrap->fd, NULL);
749 uv_mutex_unlock(&wrap->mutex);
750 uv_fs_req_cleanup(&req);
751
752 if (r != 0)
753 return uvwasi__translate_uv_error(r);
754
755 return UVWASI_ESUCCESS;
756 }
757
758
uvwasi_fd_fdstat_get(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_fdstat_t * buf)759 uvwasi_errno_t uvwasi_fd_fdstat_get(uvwasi_t* uvwasi,
760 uvwasi_fd_t fd,
761 uvwasi_fdstat_t* buf) {
762 struct uvwasi_fd_wrap_t* wrap;
763 uvwasi_errno_t err;
764 #ifndef _WIN32
765 int r;
766 #endif
767
768 UVWASI_DEBUG("uvwasi_fd_fdstat_get(uvwasi=%p, fd=%d, buf=%p)\n",
769 uvwasi,
770 fd,
771 buf);
772
773 if (uvwasi == NULL || buf == NULL)
774 return UVWASI_EINVAL;
775
776 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0);
777 if (err != UVWASI_ESUCCESS)
778 return err;
779
780 buf->fs_filetype = wrap->type;
781 buf->fs_rights_base = wrap->rights_base;
782 buf->fs_rights_inheriting = wrap->rights_inheriting;
783 #ifdef _WIN32
784 buf->fs_flags = 0; /* TODO(cjihrig): Missing Windows support. */
785 #else
786 r = fcntl(wrap->fd, F_GETFL);
787 if (r < 0) {
788 err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
789 uv_mutex_unlock(&wrap->mutex);
790 return err;
791 }
792 buf->fs_flags = r;
793 #endif /* _WIN32 */
794
795 uv_mutex_unlock(&wrap->mutex);
796 return UVWASI_ESUCCESS;
797 }
798
799
uvwasi_fd_fdstat_set_flags(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_fdflags_t flags)800 uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi,
801 uvwasi_fd_t fd,
802 uvwasi_fdflags_t flags) {
803 #ifdef _WIN32
804 UVWASI_DEBUG("uvwasi_fd_fdstat_set_flags(uvwasi=%p, fd=%d, flags=%d)\n",
805 uvwasi,
806 fd,
807 flags);
808
809 /* TODO(cjihrig): Windows is not supported. */
810 return UVWASI_ENOSYS;
811 #else
812 struct uvwasi_fd_wrap_t* wrap;
813 uvwasi_errno_t err;
814 int mapped_flags;
815 int r;
816
817 UVWASI_DEBUG("uvwasi_fd_fdstat_set_flags(uvwasi=%p, fd=%d, flags=%d)\n",
818 uvwasi,
819 fd,
820 flags);
821
822 if (uvwasi == NULL)
823 return UVWASI_EINVAL;
824
825 err = uvwasi_fd_table_get(uvwasi->fds,
826 fd,
827 &wrap,
828 UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS,
829 0);
830 if (err != UVWASI_ESUCCESS)
831 return err;
832
833 mapped_flags = 0;
834
835 if ((flags & UVWASI_FDFLAG_APPEND) == UVWASI_FDFLAG_APPEND)
836 mapped_flags |= O_APPEND;
837
838 if ((flags & UVWASI_FDFLAG_DSYNC) == UVWASI_FDFLAG_DSYNC)
839 #ifdef O_DSYNC
840 mapped_flags |= O_DSYNC;
841 #else
842 mapped_flags |= O_SYNC;
843 #endif /* O_DSYNC */
844
845 if ((flags & UVWASI_FDFLAG_NONBLOCK) == UVWASI_FDFLAG_NONBLOCK)
846 mapped_flags |= O_NONBLOCK;
847
848 if ((flags & UVWASI_FDFLAG_RSYNC) == UVWASI_FDFLAG_RSYNC)
849 #ifdef O_RSYNC
850 mapped_flags |= O_RSYNC;
851 #else
852 mapped_flags |= O_SYNC;
853 #endif /* O_RSYNC */
854
855 if ((flags & UVWASI_FDFLAG_SYNC) == UVWASI_FDFLAG_SYNC)
856 mapped_flags |= O_SYNC;
857
858 r = fcntl(wrap->fd, F_SETFL, mapped_flags);
859 if (r < 0)
860 err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
861 else
862 err = UVWASI_ESUCCESS;
863
864 uv_mutex_unlock(&wrap->mutex);
865 return err;
866 #endif /* _WIN32 */
867 }
868
869
uvwasi_fd_fdstat_set_rights(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_rights_t fs_rights_base,uvwasi_rights_t fs_rights_inheriting)870 uvwasi_errno_t uvwasi_fd_fdstat_set_rights(uvwasi_t* uvwasi,
871 uvwasi_fd_t fd,
872 uvwasi_rights_t fs_rights_base,
873 uvwasi_rights_t fs_rights_inheriting
874 ) {
875 struct uvwasi_fd_wrap_t* wrap;
876 uvwasi_errno_t err;
877
878 UVWASI_DEBUG("uvwasi_fd_fdstat_set_rights(uvwasi=%p, fd=%d, "
879 "fs_rights_base=%"PRIu64", fs_rights_inheriting=%"PRIu64")\n",
880 uvwasi,
881 fd,
882 fs_rights_base,
883 fs_rights_inheriting);
884
885 if (uvwasi == NULL)
886 return UVWASI_EINVAL;
887
888 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0);
889 if (err != UVWASI_ESUCCESS)
890 return err;
891
892 /* Check for attempts to add new permissions. */
893 if ((fs_rights_base | wrap->rights_base) > wrap->rights_base) {
894 err = UVWASI_ENOTCAPABLE;
895 goto exit;
896 }
897
898 if ((fs_rights_inheriting | wrap->rights_inheriting) >
899 wrap->rights_inheriting) {
900 err = UVWASI_ENOTCAPABLE;
901 goto exit;
902 }
903
904 wrap->rights_base = fs_rights_base;
905 wrap->rights_inheriting = fs_rights_inheriting;
906 err = UVWASI_ESUCCESS;
907 exit:
908 uv_mutex_unlock(&wrap->mutex);
909 return err;
910 }
911
912
uvwasi_fd_filestat_get(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_filestat_t * buf)913 uvwasi_errno_t uvwasi_fd_filestat_get(uvwasi_t* uvwasi,
914 uvwasi_fd_t fd,
915 uvwasi_filestat_t* buf) {
916 struct uvwasi_fd_wrap_t* wrap;
917 uv_fs_t req;
918 uvwasi_errno_t err;
919 int r;
920
921 UVWASI_DEBUG("uvwasi_fd_filestat_get(uvwasi=%p, fd=%d, buf=%p)\n",
922 uvwasi,
923 fd,
924 buf);
925
926 if (uvwasi == NULL || buf == NULL)
927 return UVWASI_EINVAL;
928
929 err = uvwasi_fd_table_get(uvwasi->fds,
930 fd,
931 &wrap,
932 UVWASI_RIGHT_FD_FILESTAT_GET,
933 0);
934 if (err != UVWASI_ESUCCESS)
935 return err;
936
937 r = uv_fs_fstat(NULL, &req, wrap->fd, NULL);
938 if (r != 0) {
939 err = uvwasi__translate_uv_error(r);
940 goto exit;
941 }
942
943 uvwasi__stat_to_filestat(&req.statbuf, buf);
944 err = UVWASI_ESUCCESS;
945 exit:
946 uv_mutex_unlock(&wrap->mutex);
947 uv_fs_req_cleanup(&req);
948 return err;
949 }
950
951
uvwasi_fd_filestat_set_size(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_filesize_t st_size)952 uvwasi_errno_t uvwasi_fd_filestat_set_size(uvwasi_t* uvwasi,
953 uvwasi_fd_t fd,
954 uvwasi_filesize_t st_size) {
955 /* TODO(cjihrig): uv_fs_ftruncate() takes an int64_t. st_size is uint64_t. */
956 struct uvwasi_fd_wrap_t* wrap;
957 uv_fs_t req;
958 uvwasi_errno_t err;
959 int r;
960
961 UVWASI_DEBUG("uvwasi_fd_filestat_set_size(uvwasi=%p, fd=%d, "
962 "st_size=%"PRIu64")\n",
963 uvwasi,
964 fd,
965 st_size);
966
967 if (uvwasi == NULL)
968 return UVWASI_EINVAL;
969
970 err = uvwasi_fd_table_get(uvwasi->fds,
971 fd,
972 &wrap,
973 UVWASI_RIGHT_FD_FILESTAT_SET_SIZE,
974 0);
975 if (err != UVWASI_ESUCCESS)
976 return err;
977
978 r = uv_fs_ftruncate(NULL, &req, wrap->fd, st_size, NULL);
979 uv_mutex_unlock(&wrap->mutex);
980 uv_fs_req_cleanup(&req);
981
982 if (r != 0)
983 return uvwasi__translate_uv_error(r);
984
985 return UVWASI_ESUCCESS;
986 }
987
988
uvwasi_fd_filestat_set_times(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_timestamp_t st_atim,uvwasi_timestamp_t st_mtim,uvwasi_fstflags_t fst_flags)989 uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi,
990 uvwasi_fd_t fd,
991 uvwasi_timestamp_t st_atim,
992 uvwasi_timestamp_t st_mtim,
993 uvwasi_fstflags_t fst_flags) {
994 struct uvwasi_fd_wrap_t* wrap;
995 uvwasi_timestamp_t atim;
996 uvwasi_timestamp_t mtim;
997 uv_fs_t req;
998 uvwasi_errno_t err;
999 int r;
1000
1001 UVWASI_DEBUG("uvwasi_fd_filestat_set_times(uvwasi=%p, fd=%d, "
1002 "st_atim=%"PRIu64", st_mtim=%"PRIu64", fst_flags=%d)\n",
1003 uvwasi,
1004 fd,
1005 st_atim,
1006 st_mtim,
1007 fst_flags);
1008
1009 if (uvwasi == NULL)
1010 return UVWASI_EINVAL;
1011
1012 VALIDATE_FSTFLAGS_OR_RETURN(fst_flags);
1013
1014 err = uvwasi_fd_table_get(uvwasi->fds,
1015 fd,
1016 &wrap,
1017 UVWASI_RIGHT_FD_FILESTAT_SET_TIMES,
1018 0);
1019 if (err != UVWASI_ESUCCESS)
1020 return err;
1021
1022 atim = st_atim;
1023 mtim = st_mtim;
1024 err = uvwasi__get_filestat_set_times(&atim,
1025 &mtim,
1026 fst_flags,
1027 &wrap->fd,
1028 NULL);
1029 if (err != UVWASI_ESUCCESS) {
1030 uv_mutex_unlock(&wrap->mutex);
1031 return err;
1032 }
1033
1034 /* libuv does not currently support nanosecond precision. */
1035 r = uv_fs_futime(NULL, &req, wrap->fd, atim, mtim, NULL);
1036 uv_mutex_unlock(&wrap->mutex);
1037 uv_fs_req_cleanup(&req);
1038
1039 if (r != 0)
1040 return uvwasi__translate_uv_error(r);
1041
1042 return UVWASI_ESUCCESS;
1043 }
1044
1045
uvwasi_fd_pread(uvwasi_t * uvwasi,uvwasi_fd_t fd,const uvwasi_iovec_t * iovs,uvwasi_size_t iovs_len,uvwasi_filesize_t offset,uvwasi_size_t * nread)1046 uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi,
1047 uvwasi_fd_t fd,
1048 const uvwasi_iovec_t* iovs,
1049 uvwasi_size_t iovs_len,
1050 uvwasi_filesize_t offset,
1051 uvwasi_size_t* nread) {
1052 struct uvwasi_fd_wrap_t* wrap;
1053 uv_buf_t* bufs;
1054 uv_fs_t req;
1055 uvwasi_errno_t err;
1056 size_t uvread;
1057 int r;
1058
1059 UVWASI_DEBUG("uvwasi_fd_pread(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%d, "
1060 "offset=%"PRIu64", nread=%p)\n",
1061 uvwasi,
1062 fd,
1063 iovs,
1064 iovs_len,
1065 offset,
1066 nread);
1067
1068 if (uvwasi == NULL || iovs == NULL || nread == NULL)
1069 return UVWASI_EINVAL;
1070
1071 err = uvwasi_fd_table_get(uvwasi->fds,
1072 fd,
1073 &wrap,
1074 UVWASI_RIGHT_FD_READ | UVWASI_RIGHT_FD_SEEK,
1075 0);
1076 if (err != UVWASI_ESUCCESS)
1077 return err;
1078
1079 err = uvwasi__setup_iovs(uvwasi, &bufs, iovs, iovs_len);
1080 if (err != UVWASI_ESUCCESS) {
1081 uv_mutex_unlock(&wrap->mutex);
1082 return err;
1083 }
1084
1085 r = uv_fs_read(NULL, &req, wrap->fd, bufs, iovs_len, offset, NULL);
1086 uv_mutex_unlock(&wrap->mutex);
1087 uvread = req.result;
1088 uv_fs_req_cleanup(&req);
1089 uvwasi__free(uvwasi, bufs);
1090
1091 if (r < 0)
1092 return uvwasi__translate_uv_error(r);
1093
1094 *nread = (uvwasi_size_t) uvread;
1095 return UVWASI_ESUCCESS;
1096 }
1097
1098
uvwasi_fd_prestat_get(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_prestat_t * buf)1099 uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi,
1100 uvwasi_fd_t fd,
1101 uvwasi_prestat_t* buf) {
1102 struct uvwasi_fd_wrap_t* wrap;
1103 uvwasi_errno_t err;
1104
1105 UVWASI_DEBUG("uvwasi_fd_prestat_get(uvwasi=%p, fd=%d, buf=%p)\n",
1106 uvwasi,
1107 fd,
1108 buf);
1109
1110 if (uvwasi == NULL || buf == NULL)
1111 return UVWASI_EINVAL;
1112
1113 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0);
1114 if (err != UVWASI_ESUCCESS)
1115 return err;
1116 if (wrap->preopen != 1) {
1117 err = UVWASI_EINVAL;
1118 goto exit;
1119 }
1120
1121 buf->pr_type = UVWASI_PREOPENTYPE_DIR;
1122 buf->u.dir.pr_name_len = strlen(wrap->path) + 1;
1123 err = UVWASI_ESUCCESS;
1124 exit:
1125 uv_mutex_unlock(&wrap->mutex);
1126 return err;
1127 }
1128
1129
uvwasi_fd_prestat_dir_name(uvwasi_t * uvwasi,uvwasi_fd_t fd,char * path,uvwasi_size_t path_len)1130 uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi,
1131 uvwasi_fd_t fd,
1132 char* path,
1133 uvwasi_size_t path_len) {
1134 struct uvwasi_fd_wrap_t* wrap;
1135 uvwasi_errno_t err;
1136 size_t size;
1137
1138 UVWASI_DEBUG("uvwasi_fd_prestat_dir_name(uvwasi=%p, fd=%d, path=%p, "
1139 "path_len=%d)\n",
1140 uvwasi,
1141 fd,
1142 path,
1143 path_len);
1144
1145 if (uvwasi == NULL || path == NULL)
1146 return UVWASI_EINVAL;
1147
1148 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0);
1149 if (err != UVWASI_ESUCCESS)
1150 return err;
1151 if (wrap->preopen != 1) {
1152 err = UVWASI_EBADF;
1153 goto exit;
1154 }
1155
1156 size = strlen(wrap->path) + 1;
1157 if (size > (size_t) path_len) {
1158 err = UVWASI_ENOBUFS;
1159 goto exit;
1160 }
1161
1162 memcpy(path, wrap->path, size);
1163 err = UVWASI_ESUCCESS;
1164 exit:
1165 uv_mutex_unlock(&wrap->mutex);
1166 return err;
1167 }
1168
1169
uvwasi_fd_pwrite(uvwasi_t * uvwasi,uvwasi_fd_t fd,const uvwasi_ciovec_t * iovs,uvwasi_size_t iovs_len,uvwasi_filesize_t offset,uvwasi_size_t * nwritten)1170 uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi,
1171 uvwasi_fd_t fd,
1172 const uvwasi_ciovec_t* iovs,
1173 uvwasi_size_t iovs_len,
1174 uvwasi_filesize_t offset,
1175 uvwasi_size_t* nwritten) {
1176 struct uvwasi_fd_wrap_t* wrap;
1177 uv_buf_t* bufs;
1178 uv_fs_t req;
1179 uvwasi_errno_t err;
1180 size_t uvwritten;
1181 int r;
1182
1183 UVWASI_DEBUG("uvwasi_fd_pwrite(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%d, "
1184 "offset=%"PRIu64", nwritten=%p)\n",
1185 uvwasi,
1186 fd,
1187 iovs,
1188 iovs_len,
1189 offset,
1190 nwritten);
1191
1192 if (uvwasi == NULL || iovs == NULL || nwritten == NULL)
1193 return UVWASI_EINVAL;
1194
1195 err = uvwasi_fd_table_get(uvwasi->fds,
1196 fd,
1197 &wrap,
1198 UVWASI_RIGHT_FD_WRITE | UVWASI_RIGHT_FD_SEEK,
1199 0);
1200 if (err != UVWASI_ESUCCESS)
1201 return err;
1202
1203 err = uvwasi__setup_ciovs(uvwasi, &bufs, iovs, iovs_len);
1204 if (err != UVWASI_ESUCCESS) {
1205 uv_mutex_unlock(&wrap->mutex);
1206 return err;
1207 }
1208
1209 r = uv_fs_write(NULL, &req, wrap->fd, bufs, iovs_len, offset, NULL);
1210 uv_mutex_unlock(&wrap->mutex);
1211 uvwritten = req.result;
1212 uv_fs_req_cleanup(&req);
1213 uvwasi__free(uvwasi, bufs);
1214
1215 if (r < 0)
1216 return uvwasi__translate_uv_error(r);
1217
1218 *nwritten = (uvwasi_size_t) uvwritten;
1219 return UVWASI_ESUCCESS;
1220 }
1221
1222
uvwasi_fd_read(uvwasi_t * uvwasi,uvwasi_fd_t fd,const uvwasi_iovec_t * iovs,uvwasi_size_t iovs_len,uvwasi_size_t * nread)1223 uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi,
1224 uvwasi_fd_t fd,
1225 const uvwasi_iovec_t* iovs,
1226 uvwasi_size_t iovs_len,
1227 uvwasi_size_t* nread) {
1228 struct uvwasi_fd_wrap_t* wrap;
1229 uv_buf_t* bufs;
1230 uv_fs_t req;
1231 uvwasi_errno_t err;
1232 size_t uvread;
1233 int r;
1234
1235 UVWASI_DEBUG("uvwasi_fd_read(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%d, "
1236 "nread=%p)\n",
1237 uvwasi,
1238 fd,
1239 iovs,
1240 iovs_len,
1241 nread);
1242
1243 if (uvwasi == NULL || iovs == NULL || nread == NULL)
1244 return UVWASI_EINVAL;
1245
1246 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ, 0);
1247 if (err != UVWASI_ESUCCESS)
1248 return err;
1249
1250 err = uvwasi__setup_iovs(uvwasi, &bufs, iovs, iovs_len);
1251 if (err != UVWASI_ESUCCESS) {
1252 uv_mutex_unlock(&wrap->mutex);
1253 return err;
1254 }
1255
1256 r = uv_fs_read(NULL, &req, wrap->fd, bufs, iovs_len, -1, NULL);
1257 uv_mutex_unlock(&wrap->mutex);
1258 uvread = req.result;
1259 uv_fs_req_cleanup(&req);
1260 uvwasi__free(uvwasi, bufs);
1261
1262 if (r < 0)
1263 return uvwasi__translate_uv_error(r);
1264
1265 *nread = (uvwasi_size_t) uvread;
1266 return UVWASI_ESUCCESS;
1267 }
1268
1269
uvwasi_fd_readdir(uvwasi_t * uvwasi,uvwasi_fd_t fd,void * buf,uvwasi_size_t buf_len,uvwasi_dircookie_t cookie,uvwasi_size_t * bufused)1270 uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1271 uvwasi_fd_t fd,
1272 void* buf,
1273 uvwasi_size_t buf_len,
1274 uvwasi_dircookie_t cookie,
1275 uvwasi_size_t* bufused) {
1276 #if defined(UVWASI_FD_READDIR_SUPPORTED)
1277 /* TODO(cjihrig): Avoid opening and closing the directory on each call. */
1278 struct uvwasi_fd_wrap_t* wrap;
1279 uvwasi_dirent_t dirent;
1280 uv_dirent_t dirents[UVWASI__READDIR_NUM_ENTRIES];
1281 uv_dir_t* dir;
1282 uv_fs_t req;
1283 uvwasi_errno_t err;
1284 size_t name_len;
1285 size_t available;
1286 size_t size_to_cp;
1287 long tell;
1288 int i;
1289 int r;
1290 #endif /* defined(UVWASI_FD_READDIR_SUPPORTED) */
1291
1292 UVWASI_DEBUG("uvwasi_fd_readdir(uvwasi=%p, fd=%d, buf=%p, buf_len=%d, "
1293 "cookie=%"PRIu64", bufused=%p)\n",
1294 uvwasi,
1295 fd,
1296 buf,
1297 buf_len,
1298 cookie,
1299 bufused);
1300
1301 if (uvwasi == NULL || buf == NULL || bufused == NULL)
1302 return UVWASI_EINVAL;
1303
1304 #if defined(UVWASI_FD_READDIR_SUPPORTED)
1305 err = uvwasi_fd_table_get(uvwasi->fds,
1306 fd,
1307 &wrap,
1308 UVWASI_RIGHT_FD_READDIR,
1309 0);
1310 if (err != UVWASI_ESUCCESS)
1311 return err;
1312
1313 /* Open the directory. */
1314 r = uv_fs_opendir(NULL, &req, wrap->real_path, NULL);
1315 if (r != 0) {
1316 uv_mutex_unlock(&wrap->mutex);
1317 return uvwasi__translate_uv_error(r);
1318 }
1319
1320 /* Setup for reading the directory. */
1321 dir = req.ptr;
1322 dir->dirents = dirents;
1323 dir->nentries = UVWASI__READDIR_NUM_ENTRIES;
1324 uv_fs_req_cleanup(&req);
1325
1326 /* Seek to the proper location in the directory. */
1327 if (cookie != UVWASI_DIRCOOKIE_START)
1328 seekdir(dir->dir, cookie);
1329
1330 /* Read the directory entries into the provided buffer. */
1331 err = UVWASI_ESUCCESS;
1332 *bufused = 0;
1333 while (0 != (r = uv_fs_readdir(NULL, &req, dir, NULL))) {
1334 if (r < 0) {
1335 err = uvwasi__translate_uv_error(r);
1336 uv_fs_req_cleanup(&req);
1337 goto exit;
1338 }
1339
1340 available = 0;
1341
1342 for (i = 0; i < r; i++) {
1343 tell = telldir(dir->dir);
1344 if (tell < 0) {
1345 err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
1346 uv_fs_req_cleanup(&req);
1347 goto exit;
1348 }
1349
1350 name_len = strlen(dirents[i].name);
1351 dirent.d_next = (uvwasi_dircookie_t) tell;
1352 /* TODO(cjihrig): libuv doesn't provide d_ino, and d_type is not
1353 supported on all platforms. Use stat()? */
1354 dirent.d_ino = 0;
1355 dirent.d_namlen = name_len;
1356
1357 switch (dirents[i].type) {
1358 case UV_DIRENT_FILE:
1359 dirent.d_type = UVWASI_FILETYPE_REGULAR_FILE;
1360 break;
1361 case UV_DIRENT_DIR:
1362 dirent.d_type = UVWASI_FILETYPE_DIRECTORY;
1363 break;
1364 case UV_DIRENT_SOCKET:
1365 dirent.d_type = UVWASI_FILETYPE_SOCKET_STREAM;
1366 break;
1367 case UV_DIRENT_LINK:
1368 dirent.d_type = UVWASI_FILETYPE_SYMBOLIC_LINK;
1369 break;
1370 case UV_DIRENT_CHAR:
1371 dirent.d_type = UVWASI_FILETYPE_CHARACTER_DEVICE;
1372 break;
1373 case UV_DIRENT_BLOCK:
1374 dirent.d_type = UVWASI_FILETYPE_BLOCK_DEVICE;
1375 break;
1376 case UV_DIRENT_FIFO:
1377 case UV_DIRENT_UNKNOWN:
1378 default:
1379 dirent.d_type = UVWASI_FILETYPE_UNKNOWN;
1380 break;
1381 }
1382
1383 /* Write dirent to the buffer if it will fit. */
1384 if (UVWASI_SERDES_SIZE_dirent_t + *bufused > buf_len)
1385 break;
1386
1387 uvwasi_serdes_write_dirent_t(buf, *bufused, &dirent);
1388 *bufused += UVWASI_SERDES_SIZE_dirent_t;
1389 available = buf_len - *bufused;
1390
1391 /* Write as much of the entry name to the buffer as possible. */
1392 size_to_cp = name_len > available ? available : name_len;
1393 memcpy((char*)buf + *bufused, dirents[i].name, size_to_cp);
1394 *bufused += size_to_cp;
1395 available = buf_len - *bufused;
1396 }
1397
1398 uv_fs_req_cleanup(&req);
1399
1400 if (available == 0)
1401 break;
1402 }
1403
1404 exit:
1405 /* Close the directory. */
1406 r = uv_fs_closedir(NULL, &req, dir, NULL);
1407 uv_mutex_unlock(&wrap->mutex);
1408 uv_fs_req_cleanup(&req);
1409 if (r != 0)
1410 return uvwasi__translate_uv_error(r);
1411
1412 return err;
1413 #else
1414 /* TODO(cjihrig): Need a solution for Windows and Android. */
1415 return UVWASI_ENOSYS;
1416 #endif /* defined(UVWASI_FD_READDIR_SUPPORTED) */
1417 }
1418
1419
uvwasi_fd_renumber(uvwasi_t * uvwasi,uvwasi_fd_t from,uvwasi_fd_t to)1420 uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi,
1421 uvwasi_fd_t from,
1422 uvwasi_fd_t to) {
1423 UVWASI_DEBUG("uvwasi_fd_renumber(uvwasi=%p, from=%d, to=%d)\n",
1424 uvwasi,
1425 from,
1426 to);
1427
1428 if (uvwasi == NULL)
1429 return UVWASI_EINVAL;
1430
1431 return uvwasi_fd_table_renumber(uvwasi, uvwasi->fds, to, from);
1432 }
1433
1434
uvwasi_fd_seek(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_filedelta_t offset,uvwasi_whence_t whence,uvwasi_filesize_t * newoffset)1435 uvwasi_errno_t uvwasi_fd_seek(uvwasi_t* uvwasi,
1436 uvwasi_fd_t fd,
1437 uvwasi_filedelta_t offset,
1438 uvwasi_whence_t whence,
1439 uvwasi_filesize_t* newoffset) {
1440 struct uvwasi_fd_wrap_t* wrap;
1441 uvwasi_errno_t err;
1442
1443 UVWASI_DEBUG("uvwasi_fd_seek(uvwasi=%p, fd=%d, offset=%"PRId64", "
1444 "whence=%d, newoffset=%p)\n",
1445 uvwasi,
1446 fd,
1447 offset,
1448 whence,
1449 newoffset);
1450
1451 if (uvwasi == NULL || newoffset == NULL)
1452 return UVWASI_EINVAL;
1453
1454 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SEEK, 0);
1455 if (err != UVWASI_ESUCCESS)
1456 return err;
1457
1458 err = uvwasi__lseek(wrap->fd, offset, whence, newoffset);
1459 uv_mutex_unlock(&wrap->mutex);
1460 return err;
1461 }
1462
1463
uvwasi_fd_sync(uvwasi_t * uvwasi,uvwasi_fd_t fd)1464 uvwasi_errno_t uvwasi_fd_sync(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
1465 struct uvwasi_fd_wrap_t* wrap;
1466 uv_fs_t req;
1467 uvwasi_errno_t err;
1468 int r;
1469
1470 UVWASI_DEBUG("uvwasi_fd_sync(uvwasi=%p, fd=%d)\n", uvwasi, fd);
1471
1472 if (uvwasi == NULL)
1473 return UVWASI_EINVAL;
1474
1475 err = uvwasi_fd_table_get(uvwasi->fds,
1476 fd,
1477 &wrap,
1478 UVWASI_RIGHT_FD_SYNC,
1479 0);
1480 if (err != UVWASI_ESUCCESS)
1481 return err;
1482
1483 r = uv_fs_fsync(NULL, &req, wrap->fd, NULL);
1484 uv_mutex_unlock(&wrap->mutex);
1485 uv_fs_req_cleanup(&req);
1486
1487 if (r != 0)
1488 return uvwasi__translate_uv_error(r);
1489
1490 return UVWASI_ESUCCESS;
1491 }
1492
1493
uvwasi_fd_tell(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_filesize_t * offset)1494 uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi,
1495 uvwasi_fd_t fd,
1496 uvwasi_filesize_t* offset) {
1497 struct uvwasi_fd_wrap_t* wrap;
1498 uvwasi_errno_t err;
1499
1500 UVWASI_DEBUG("uvwasi_fd_tell(uvwasi=%p, fd=%d, offset=%p)\n",
1501 uvwasi,
1502 fd,
1503 offset);
1504
1505 if (uvwasi == NULL || offset == NULL)
1506 return UVWASI_EINVAL;
1507
1508 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_TELL, 0);
1509 if (err != UVWASI_ESUCCESS)
1510 return err;
1511
1512 err = uvwasi__lseek(wrap->fd, 0, UVWASI_WHENCE_CUR, offset);
1513 uv_mutex_unlock(&wrap->mutex);
1514 return err;
1515 }
1516
1517
uvwasi_fd_write(uvwasi_t * uvwasi,uvwasi_fd_t fd,const uvwasi_ciovec_t * iovs,uvwasi_size_t iovs_len,uvwasi_size_t * nwritten)1518 uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi,
1519 uvwasi_fd_t fd,
1520 const uvwasi_ciovec_t* iovs,
1521 uvwasi_size_t iovs_len,
1522 uvwasi_size_t* nwritten) {
1523 struct uvwasi_fd_wrap_t* wrap;
1524 uv_buf_t* bufs;
1525 uv_fs_t req;
1526 uvwasi_errno_t err;
1527 size_t uvwritten;
1528 int r;
1529
1530 UVWASI_DEBUG("uvwasi_fd_write(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%d, "
1531 "nwritten=%p)\n",
1532 uvwasi,
1533 fd,
1534 iovs,
1535 iovs_len,
1536 nwritten);
1537
1538 if (uvwasi == NULL || iovs == NULL || nwritten == NULL)
1539 return UVWASI_EINVAL;
1540
1541 err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE, 0);
1542 if (err != UVWASI_ESUCCESS)
1543 return err;
1544
1545 err = uvwasi__setup_ciovs(uvwasi, &bufs, iovs, iovs_len);
1546 if (err != UVWASI_ESUCCESS) {
1547 uv_mutex_unlock(&wrap->mutex);
1548 return err;
1549 }
1550
1551 r = uv_fs_write(NULL, &req, wrap->fd, bufs, iovs_len, -1, NULL);
1552 uv_mutex_unlock(&wrap->mutex);
1553 uvwritten = req.result;
1554 uv_fs_req_cleanup(&req);
1555 uvwasi__free(uvwasi, bufs);
1556
1557 if (r < 0)
1558 return uvwasi__translate_uv_error(r);
1559
1560 *nwritten = (uvwasi_size_t) uvwritten;
1561 return UVWASI_ESUCCESS;
1562 }
1563
1564
uvwasi_path_create_directory(uvwasi_t * uvwasi,uvwasi_fd_t fd,const char * path,uvwasi_size_t path_len)1565 uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi,
1566 uvwasi_fd_t fd,
1567 const char* path,
1568 uvwasi_size_t path_len) {
1569 char* resolved_path;
1570 struct uvwasi_fd_wrap_t* wrap;
1571 uv_fs_t req;
1572 uvwasi_errno_t err;
1573 int r;
1574
1575 UVWASI_DEBUG("uvwasi_path_create_directory(uvwasi=%p, fd=%d, path='%s', "
1576 "path_len=%d)\n",
1577 uvwasi,
1578 fd,
1579 path,
1580 path_len);
1581
1582 if (uvwasi == NULL || path == NULL)
1583 return UVWASI_EINVAL;
1584
1585 err = uvwasi_fd_table_get(uvwasi->fds,
1586 fd,
1587 &wrap,
1588 UVWASI_RIGHT_PATH_CREATE_DIRECTORY,
1589 0);
1590 if (err != UVWASI_ESUCCESS)
1591 return err;
1592
1593 err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0);
1594 if (err != UVWASI_ESUCCESS)
1595 goto exit;
1596
1597 r = uv_fs_mkdir(NULL, &req, resolved_path, 0777, NULL);
1598 uv_fs_req_cleanup(&req);
1599 uvwasi__free(uvwasi, resolved_path);
1600
1601 if (r != 0) {
1602 err = uvwasi__translate_uv_error(r);
1603 goto exit;
1604 }
1605
1606 err = UVWASI_ESUCCESS;
1607 exit:
1608 uv_mutex_unlock(&wrap->mutex);
1609 return err;
1610 }
1611
1612
uvwasi_path_filestat_get(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_lookupflags_t flags,const char * path,uvwasi_size_t path_len,uvwasi_filestat_t * buf)1613 uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi,
1614 uvwasi_fd_t fd,
1615 uvwasi_lookupflags_t flags,
1616 const char* path,
1617 uvwasi_size_t path_len,
1618 uvwasi_filestat_t* buf) {
1619 char* resolved_path;
1620 struct uvwasi_fd_wrap_t* wrap;
1621 uv_fs_t req;
1622 uvwasi_errno_t err;
1623 int r;
1624
1625 UVWASI_DEBUG("uvwasi_path_filestat_get(uvwasi=%p, fd=%d, flags=%d, "
1626 "path='%s', path_len=%d, buf=%p)\n",
1627 uvwasi,
1628 fd,
1629 flags,
1630 path,
1631 path_len,
1632 buf);
1633
1634 if (uvwasi == NULL || path == NULL || buf == NULL)
1635 return UVWASI_EINVAL;
1636
1637 err = uvwasi_fd_table_get(uvwasi->fds,
1638 fd,
1639 &wrap,
1640 UVWASI_RIGHT_PATH_FILESTAT_GET,
1641 0);
1642 if (err != UVWASI_ESUCCESS)
1643 return err;
1644
1645 err = uvwasi__resolve_path(uvwasi,
1646 wrap,
1647 path,
1648 path_len,
1649 &resolved_path,
1650 flags);
1651 if (err != UVWASI_ESUCCESS)
1652 goto exit;
1653
1654 r = uv_fs_lstat(NULL, &req, resolved_path, NULL);
1655 uvwasi__free(uvwasi, resolved_path);
1656 if (r != 0) {
1657 uv_fs_req_cleanup(&req);
1658 err = uvwasi__translate_uv_error(r);
1659 goto exit;
1660 }
1661
1662 uvwasi__stat_to_filestat(&req.statbuf, buf);
1663 uv_fs_req_cleanup(&req);
1664 err = UVWASI_ESUCCESS;
1665 exit:
1666 uv_mutex_unlock(&wrap->mutex);
1667 return err;
1668 }
1669
1670
uvwasi_path_filestat_set_times(uvwasi_t * uvwasi,uvwasi_fd_t fd,uvwasi_lookupflags_t flags,const char * path,uvwasi_size_t path_len,uvwasi_timestamp_t st_atim,uvwasi_timestamp_t st_mtim,uvwasi_fstflags_t fst_flags)1671 uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi,
1672 uvwasi_fd_t fd,
1673 uvwasi_lookupflags_t flags,
1674 const char* path,
1675 uvwasi_size_t path_len,
1676 uvwasi_timestamp_t st_atim,
1677 uvwasi_timestamp_t st_mtim,
1678 uvwasi_fstflags_t fst_flags) {
1679 char* resolved_path;
1680 struct uvwasi_fd_wrap_t* wrap;
1681 uvwasi_timestamp_t atim;
1682 uvwasi_timestamp_t mtim;
1683 uv_fs_t req;
1684 uvwasi_errno_t err;
1685 int r;
1686
1687 UVWASI_DEBUG("uvwasi_path_filestat_set_times(uvwasi=%p, fd=%d, "
1688 "flags=%d, path='%s', path_len=%d, "
1689 "st_atim=%"PRIu64", st_mtim=%"PRIu64", fst_flags=%d)\n",
1690 uvwasi,
1691 fd,
1692 flags,
1693 path,
1694 path_len,
1695 st_atim,
1696 st_mtim,
1697 fst_flags);
1698
1699 if (uvwasi == NULL || path == NULL)
1700 return UVWASI_EINVAL;
1701
1702 VALIDATE_FSTFLAGS_OR_RETURN(fst_flags);
1703
1704 err = uvwasi_fd_table_get(uvwasi->fds,
1705 fd,
1706 &wrap,
1707 UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES,
1708 0);
1709 if (err != UVWASI_ESUCCESS)
1710 return err;
1711
1712 err = uvwasi__resolve_path(uvwasi,
1713 wrap,
1714 path,
1715 path_len,
1716 &resolved_path,
1717 flags);
1718 if (err != UVWASI_ESUCCESS)
1719 goto exit;
1720
1721 atim = st_atim;
1722 mtim = st_mtim;
1723 err = uvwasi__get_filestat_set_times(&atim,
1724 &mtim,
1725 fst_flags,
1726 NULL,
1727 resolved_path);
1728 if (err != UVWASI_ESUCCESS) {
1729 uvwasi__free(uvwasi, resolved_path);
1730 goto exit;
1731 }
1732
1733 /* libuv does not currently support nanosecond precision. */
1734 r = uv_fs_lutime(NULL, &req, resolved_path, atim, mtim, NULL);
1735 uvwasi__free(uvwasi, resolved_path);
1736 uv_fs_req_cleanup(&req);
1737
1738 if (r != 0) {
1739 err = uvwasi__translate_uv_error(r);
1740 goto exit;
1741 }
1742
1743 err = UVWASI_ESUCCESS;
1744 exit:
1745 uv_mutex_unlock(&wrap->mutex);
1746 return err;
1747 }
1748
1749
uvwasi_path_link(uvwasi_t * uvwasi,uvwasi_fd_t old_fd,uvwasi_lookupflags_t old_flags,const char * old_path,uvwasi_size_t old_path_len,uvwasi_fd_t new_fd,const char * new_path,uvwasi_size_t new_path_len)1750 uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi,
1751 uvwasi_fd_t old_fd,
1752 uvwasi_lookupflags_t old_flags,
1753 const char* old_path,
1754 uvwasi_size_t old_path_len,
1755 uvwasi_fd_t new_fd,
1756 const char* new_path,
1757 uvwasi_size_t new_path_len) {
1758 char* resolved_old_path;
1759 char* resolved_new_path;
1760 struct uvwasi_fd_wrap_t* old_wrap;
1761 struct uvwasi_fd_wrap_t* new_wrap;
1762 uvwasi_errno_t err;
1763 uv_fs_t req;
1764 int r;
1765
1766 UVWASI_DEBUG("uvwasi_path_link(uvwasi=%p, old_fd=%d, old_flags=%d, "
1767 "old_path='%s', old_path_len=%d, new_fd=%d, new_path='%s', "
1768 "new_path_len=%d)\n",
1769 uvwasi,
1770 old_fd,
1771 old_flags,
1772 old_path,
1773 old_path_len,
1774 new_fd,
1775 new_path,
1776 new_path_len);
1777
1778 if (uvwasi == NULL || old_path == NULL || new_path == NULL)
1779 return UVWASI_EINVAL;
1780
1781 uvwasi_fd_table_lock(uvwasi->fds);
1782
1783 if (old_fd == new_fd) {
1784 err = uvwasi_fd_table_get_nolock(uvwasi->fds,
1785 old_fd,
1786 &old_wrap,
1787 UVWASI_RIGHT_PATH_LINK_SOURCE |
1788 UVWASI_RIGHT_PATH_LINK_TARGET,
1789 0);
1790 new_wrap = old_wrap;
1791 } else {
1792 err = uvwasi_fd_table_get_nolock(uvwasi->fds,
1793 old_fd,
1794 &old_wrap,
1795 UVWASI_RIGHT_PATH_LINK_SOURCE,
1796 0);
1797 if (err != UVWASI_ESUCCESS) {
1798 uvwasi_fd_table_unlock(uvwasi->fds);
1799 return err;
1800 }
1801
1802 err = uvwasi_fd_table_get_nolock(uvwasi->fds,
1803 new_fd,
1804 &new_wrap,
1805 UVWASI_RIGHT_PATH_LINK_TARGET,
1806 0);
1807 if (err != UVWASI_ESUCCESS)
1808 uv_mutex_unlock(&old_wrap->mutex);
1809 }
1810
1811 uvwasi_fd_table_unlock(uvwasi->fds);
1812
1813 if (err != UVWASI_ESUCCESS)
1814 return err;
1815
1816 resolved_old_path = NULL;
1817 resolved_new_path = NULL;
1818
1819 err = uvwasi__resolve_path(uvwasi,
1820 old_wrap,
1821 old_path,
1822 old_path_len,
1823 &resolved_old_path,
1824 old_flags);
1825 if (err != UVWASI_ESUCCESS)
1826 goto exit;
1827
1828 err = uvwasi__resolve_path(uvwasi,
1829 new_wrap,
1830 new_path,
1831 new_path_len,
1832 &resolved_new_path,
1833 0);
1834 if (err != UVWASI_ESUCCESS)
1835 goto exit;
1836
1837 r = uv_fs_link(NULL, &req, resolved_old_path, resolved_new_path, NULL);
1838 uv_fs_req_cleanup(&req);
1839 if (r != 0) {
1840 err = uvwasi__translate_uv_error(r);
1841 goto exit;
1842 }
1843
1844 err = UVWASI_ESUCCESS;
1845 exit:
1846 uv_mutex_unlock(&new_wrap->mutex);
1847 if (old_fd != new_fd)
1848 uv_mutex_unlock(&old_wrap->mutex);
1849
1850 uvwasi__free(uvwasi, resolved_old_path);
1851 uvwasi__free(uvwasi, resolved_new_path);
1852 return err;
1853 }
1854
1855
uvwasi_path_open(uvwasi_t * uvwasi,uvwasi_fd_t dirfd,uvwasi_lookupflags_t dirflags,const char * path,uvwasi_size_t path_len,uvwasi_oflags_t o_flags,uvwasi_rights_t fs_rights_base,uvwasi_rights_t fs_rights_inheriting,uvwasi_fdflags_t fs_flags,uvwasi_fd_t * fd)1856 uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
1857 uvwasi_fd_t dirfd,
1858 uvwasi_lookupflags_t dirflags,
1859 const char* path,
1860 uvwasi_size_t path_len,
1861 uvwasi_oflags_t o_flags,
1862 uvwasi_rights_t fs_rights_base,
1863 uvwasi_rights_t fs_rights_inheriting,
1864 uvwasi_fdflags_t fs_flags,
1865 uvwasi_fd_t* fd) {
1866 char* resolved_path;
1867 uvwasi_rights_t needed_inheriting;
1868 uvwasi_rights_t needed_base;
1869 uvwasi_rights_t max_base;
1870 uvwasi_rights_t max_inheriting;
1871 struct uvwasi_fd_wrap_t* dirfd_wrap;
1872 struct uvwasi_fd_wrap_t *wrap;
1873 uvwasi_filetype_t filetype;
1874 uvwasi_errno_t err;
1875 uv_fs_t req;
1876 int flags;
1877 int read;
1878 int write;
1879 int r;
1880
1881 UVWASI_DEBUG("uvwasi_path_open(uvwasi=%p, dirfd=%d, dirflags=%d, path='%s', "
1882 "path_len=%d, o_flags=%d, fs_rights_base=%"PRIu64", "
1883 "fs_rights_inheriting=%"PRIu64", fs_flags=%d, fd=%p)\n",
1884 uvwasi,
1885 dirfd,
1886 dirflags,
1887 path,
1888 path_len,
1889 o_flags,
1890 fs_rights_base,
1891 fs_rights_inheriting,
1892 fs_flags,
1893 fd);
1894
1895 if (uvwasi == NULL || path == NULL || fd == NULL)
1896 return UVWASI_EINVAL;
1897
1898 read = 0 != (fs_rights_base & (UVWASI_RIGHT_FD_READ |
1899 UVWASI_RIGHT_FD_READDIR));
1900 write = 0 != (fs_rights_base & (UVWASI_RIGHT_FD_DATASYNC |
1901 UVWASI_RIGHT_FD_WRITE |
1902 UVWASI_RIGHT_FD_ALLOCATE |
1903 UVWASI_RIGHT_FD_FILESTAT_SET_SIZE));
1904 flags = write ? read ? UV_FS_O_RDWR : UV_FS_O_WRONLY : UV_FS_O_RDONLY;
1905 needed_base = UVWASI_RIGHT_PATH_OPEN;
1906 needed_inheriting = fs_rights_base | fs_rights_inheriting;
1907
1908 if ((o_flags & UVWASI_O_CREAT) != 0) {
1909 flags |= UV_FS_O_CREAT;
1910 needed_base |= UVWASI_RIGHT_PATH_CREATE_FILE;
1911 }
1912 if ((o_flags & UVWASI_O_DIRECTORY) != 0)
1913 flags |= UV_FS_O_DIRECTORY;
1914 if ((o_flags & UVWASI_O_EXCL) != 0)
1915 flags |= UV_FS_O_EXCL;
1916 if ((o_flags & UVWASI_O_TRUNC) != 0) {
1917 flags |= UV_FS_O_TRUNC;
1918 needed_base |= UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE;
1919 }
1920
1921 if ((fs_flags & UVWASI_FDFLAG_APPEND) != 0)
1922 flags |= UV_FS_O_APPEND;
1923 if ((fs_flags & UVWASI_FDFLAG_DSYNC) != 0) {
1924 flags |= UV_FS_O_DSYNC;
1925 needed_inheriting |= UVWASI_RIGHT_FD_DATASYNC;
1926 }
1927 if ((fs_flags & UVWASI_FDFLAG_NONBLOCK) != 0)
1928 flags |= UV_FS_O_NONBLOCK;
1929 if ((fs_flags & UVWASI_FDFLAG_RSYNC) != 0) {
1930 #ifdef O_RSYNC
1931 flags |= O_RSYNC; /* libuv has no UV_FS_O_RSYNC. */
1932 #else
1933 flags |= UV_FS_O_SYNC;
1934 #endif
1935 needed_inheriting |= UVWASI_RIGHT_FD_SYNC;
1936 }
1937 if ((fs_flags & UVWASI_FDFLAG_SYNC) != 0) {
1938 flags |= UV_FS_O_SYNC;
1939 needed_inheriting |= UVWASI_RIGHT_FD_SYNC;
1940 }
1941 if (write && (flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC)) == 0)
1942 needed_inheriting |= UVWASI_RIGHT_FD_SEEK;
1943
1944 err = uvwasi_fd_table_get(uvwasi->fds,
1945 dirfd,
1946 &dirfd_wrap,
1947 needed_base,
1948 needed_inheriting);
1949 if (err != UVWASI_ESUCCESS)
1950 return err;
1951
1952 err = uvwasi__resolve_path(uvwasi,
1953 dirfd_wrap,
1954 path,
1955 path_len,
1956 &resolved_path,
1957 dirflags);
1958 if (err != UVWASI_ESUCCESS) {
1959 uv_mutex_unlock(&dirfd_wrap->mutex);
1960 return err;
1961 }
1962
1963 r = uv_fs_open(NULL, &req, resolved_path, flags, 0666, NULL);
1964 uv_mutex_unlock(&dirfd_wrap->mutex);
1965 uv_fs_req_cleanup(&req);
1966
1967 if (r < 0) {
1968 uvwasi__free(uvwasi, resolved_path);
1969 return uvwasi__translate_uv_error(r);
1970 }
1971
1972 /* Not all platforms support UV_FS_O_DIRECTORY, so get the file type and check
1973 it here. */
1974 err = uvwasi__get_filetype_by_fd(r, &filetype);
1975 if (err != UVWASI_ESUCCESS)
1976 goto close_file_and_error_exit;
1977
1978 if ((o_flags & UVWASI_O_DIRECTORY) != 0 &&
1979 filetype != UVWASI_FILETYPE_DIRECTORY) {
1980 err = UVWASI_ENOTDIR;
1981 goto close_file_and_error_exit;
1982 }
1983
1984 err = uvwasi__get_rights(r, flags, filetype, &max_base, &max_inheriting);
1985 if (err != UVWASI_ESUCCESS)
1986 goto close_file_and_error_exit;
1987
1988 err = uvwasi_fd_table_insert(uvwasi,
1989 uvwasi->fds,
1990 r,
1991 resolved_path,
1992 resolved_path,
1993 filetype,
1994 fs_rights_base & max_base,
1995 fs_rights_inheriting & max_inheriting,
1996 0,
1997 &wrap);
1998 if (err != UVWASI_ESUCCESS)
1999 goto close_file_and_error_exit;
2000
2001 *fd = wrap->id;
2002 uv_mutex_unlock(&wrap->mutex);
2003 uvwasi__free(uvwasi, resolved_path);
2004 return UVWASI_ESUCCESS;
2005
2006 close_file_and_error_exit:
2007 uv_fs_close(NULL, &req, r, NULL);
2008 uv_fs_req_cleanup(&req);
2009 uvwasi__free(uvwasi, resolved_path);
2010 return err;
2011 }
2012
2013
uvwasi_path_readlink(uvwasi_t * uvwasi,uvwasi_fd_t fd,const char * path,uvwasi_size_t path_len,char * buf,uvwasi_size_t buf_len,uvwasi_size_t * bufused)2014 uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi,
2015 uvwasi_fd_t fd,
2016 const char* path,
2017 uvwasi_size_t path_len,
2018 char* buf,
2019 uvwasi_size_t buf_len,
2020 uvwasi_size_t* bufused) {
2021 char* resolved_path;
2022 struct uvwasi_fd_wrap_t* wrap;
2023 uvwasi_errno_t err;
2024 uv_fs_t req;
2025 size_t len;
2026 int r;
2027
2028 UVWASI_DEBUG("uvwasi_path_readlink(uvwasi=%p, fd=%d, path='%s', path_len=%d, "
2029 "buf=%p, buf_len=%d, bufused=%p)\n",
2030 uvwasi,
2031 fd,
2032 path,
2033 path_len,
2034 buf,
2035 buf_len,
2036 bufused);
2037
2038 if (uvwasi == NULL || path == NULL || buf == NULL || bufused == NULL)
2039 return UVWASI_EINVAL;
2040
2041 err = uvwasi_fd_table_get(uvwasi->fds,
2042 fd,
2043 &wrap,
2044 UVWASI_RIGHT_PATH_READLINK,
2045 0);
2046 if (err != UVWASI_ESUCCESS)
2047 return err;
2048
2049 err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0);
2050 if (err != UVWASI_ESUCCESS) {
2051 uv_mutex_unlock(&wrap->mutex);
2052 return err;
2053 }
2054
2055 r = uv_fs_readlink(NULL, &req, resolved_path, NULL);
2056 uv_mutex_unlock(&wrap->mutex);
2057 uvwasi__free(uvwasi, resolved_path);
2058 if (r != 0) {
2059 uv_fs_req_cleanup(&req);
2060 return uvwasi__translate_uv_error(r);
2061 }
2062
2063 len = strnlen(req.ptr, buf_len);
2064 if (len >= buf_len) {
2065 uv_fs_req_cleanup(&req);
2066 return UVWASI_ENOBUFS;
2067 }
2068
2069 memcpy(buf, req.ptr, len);
2070 buf[len] = '\0';
2071 *bufused = len + 1;
2072 uv_fs_req_cleanup(&req);
2073 return UVWASI_ESUCCESS;
2074 }
2075
2076
uvwasi_path_remove_directory(uvwasi_t * uvwasi,uvwasi_fd_t fd,const char * path,uvwasi_size_t path_len)2077 uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi,
2078 uvwasi_fd_t fd,
2079 const char* path,
2080 uvwasi_size_t path_len) {
2081 char* resolved_path;
2082 struct uvwasi_fd_wrap_t* wrap;
2083 uv_fs_t req;
2084 uvwasi_errno_t err;
2085 int r;
2086
2087 UVWASI_DEBUG("uvwasi_path_remove_directory(uvwasi=%p, fd=%d, path='%s', "
2088 "path_len=%d)\n",
2089 uvwasi,
2090 fd,
2091 path,
2092 path_len);
2093
2094 if (uvwasi == NULL || path == NULL)
2095 return UVWASI_EINVAL;
2096
2097 err = uvwasi_fd_table_get(uvwasi->fds,
2098 fd,
2099 &wrap,
2100 UVWASI_RIGHT_PATH_REMOVE_DIRECTORY,
2101 0);
2102 if (err != UVWASI_ESUCCESS)
2103 return err;
2104
2105 err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0);
2106 if (err != UVWASI_ESUCCESS) {
2107 uv_mutex_unlock(&wrap->mutex);
2108 return err;
2109 }
2110
2111 r = uv_fs_rmdir(NULL, &req, resolved_path, NULL);
2112 uv_mutex_unlock(&wrap->mutex);
2113 uvwasi__free(uvwasi, resolved_path);
2114 uv_fs_req_cleanup(&req);
2115
2116 if (r != 0)
2117 return uvwasi__translate_uv_error(r);
2118
2119 return UVWASI_ESUCCESS;
2120 }
2121
2122
uvwasi_path_rename(uvwasi_t * uvwasi,uvwasi_fd_t old_fd,const char * old_path,uvwasi_size_t old_path_len,uvwasi_fd_t new_fd,const char * new_path,uvwasi_size_t new_path_len)2123 uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi,
2124 uvwasi_fd_t old_fd,
2125 const char* old_path,
2126 uvwasi_size_t old_path_len,
2127 uvwasi_fd_t new_fd,
2128 const char* new_path,
2129 uvwasi_size_t new_path_len) {
2130 char* resolved_old_path;
2131 char* resolved_new_path;
2132 struct uvwasi_fd_wrap_t* old_wrap;
2133 struct uvwasi_fd_wrap_t* new_wrap;
2134 uvwasi_errno_t err;
2135 uv_fs_t req;
2136 int r;
2137
2138 UVWASI_DEBUG("uvwasi_path_rename(uvwasi=%p, old_fd=%d, old_path='%s', "
2139 "old_path_len=%d, new_fd=%d, new_path='%s', new_path_len=%d)\n",
2140 uvwasi,
2141 old_fd,
2142 old_path,
2143 old_path_len,
2144 new_fd,
2145 new_path,
2146 new_path_len);
2147
2148 if (uvwasi == NULL || old_path == NULL || new_path == NULL)
2149 return UVWASI_EINVAL;
2150
2151 uvwasi_fd_table_lock(uvwasi->fds);
2152
2153 if (old_fd == new_fd) {
2154 err = uvwasi_fd_table_get_nolock(uvwasi->fds,
2155 old_fd,
2156 &old_wrap,
2157 UVWASI_RIGHT_PATH_RENAME_SOURCE |
2158 UVWASI_RIGHT_PATH_RENAME_TARGET,
2159 0);
2160 new_wrap = old_wrap;
2161 } else {
2162 err = uvwasi_fd_table_get_nolock(uvwasi->fds,
2163 old_fd,
2164 &old_wrap,
2165 UVWASI_RIGHT_PATH_RENAME_SOURCE,
2166 0);
2167 if (err != UVWASI_ESUCCESS) {
2168 uvwasi_fd_table_unlock(uvwasi->fds);
2169 return err;
2170 }
2171
2172 err = uvwasi_fd_table_get_nolock(uvwasi->fds,
2173 new_fd,
2174 &new_wrap,
2175 UVWASI_RIGHT_PATH_RENAME_TARGET,
2176 0);
2177 if (err != UVWASI_ESUCCESS)
2178 uv_mutex_unlock(&old_wrap->mutex);
2179 }
2180
2181 uvwasi_fd_table_unlock(uvwasi->fds);
2182
2183 if (err != UVWASI_ESUCCESS)
2184 return err;
2185
2186 resolved_old_path = NULL;
2187 resolved_new_path = NULL;
2188
2189 err = uvwasi__resolve_path(uvwasi,
2190 old_wrap,
2191 old_path,
2192 old_path_len,
2193 &resolved_old_path,
2194 0);
2195 if (err != UVWASI_ESUCCESS)
2196 goto exit;
2197
2198 err = uvwasi__resolve_path(uvwasi,
2199 new_wrap,
2200 new_path,
2201 new_path_len,
2202 &resolved_new_path,
2203 0);
2204 if (err != UVWASI_ESUCCESS)
2205 goto exit;
2206
2207 r = uv_fs_rename(NULL, &req, resolved_old_path, resolved_new_path, NULL);
2208 uv_fs_req_cleanup(&req);
2209 if (r != 0) {
2210 err = uvwasi__translate_uv_error(r);
2211 goto exit;
2212 }
2213
2214 err = UVWASI_ESUCCESS;
2215 exit:
2216 uv_mutex_unlock(&new_wrap->mutex);
2217 if (old_fd != new_fd)
2218 uv_mutex_unlock(&old_wrap->mutex);
2219
2220 uvwasi__free(uvwasi, resolved_old_path);
2221 uvwasi__free(uvwasi, resolved_new_path);
2222 return err;
2223 }
2224
2225
uvwasi_path_symlink(uvwasi_t * uvwasi,const char * old_path,uvwasi_size_t old_path_len,uvwasi_fd_t fd,const char * new_path,uvwasi_size_t new_path_len)2226 uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi,
2227 const char* old_path,
2228 uvwasi_size_t old_path_len,
2229 uvwasi_fd_t fd,
2230 const char* new_path,
2231 uvwasi_size_t new_path_len) {
2232 char* resolved_new_path;
2233 struct uvwasi_fd_wrap_t* wrap;
2234 uvwasi_errno_t err;
2235 uv_fs_t req;
2236 int r;
2237
2238 UVWASI_DEBUG("uvwasi_path_symlink(uvwasi=%p, old_path='%s', old_path_len=%d, "
2239 "fd=%d, new_path='%s', new_path_len=%d)\n",
2240 uvwasi,
2241 old_path,
2242 old_path_len,
2243 fd,
2244 new_path,
2245 new_path_len);
2246
2247 if (uvwasi == NULL || old_path == NULL || new_path == NULL)
2248 return UVWASI_EINVAL;
2249
2250 err = uvwasi_fd_table_get(uvwasi->fds,
2251 fd,
2252 &wrap,
2253 UVWASI_RIGHT_PATH_SYMLINK,
2254 0);
2255 if (err != UVWASI_ESUCCESS)
2256 return err;
2257
2258 err = uvwasi__resolve_path(uvwasi,
2259 wrap,
2260 new_path,
2261 new_path_len,
2262 &resolved_new_path,
2263 0);
2264 if (err != UVWASI_ESUCCESS) {
2265 uv_mutex_unlock(&wrap->mutex);
2266 return err;
2267 }
2268
2269 /* Windows support may require setting the flags option. */
2270 r = uv_fs_symlink(NULL, &req, old_path, resolved_new_path, 0, NULL);
2271 uv_mutex_unlock(&wrap->mutex);
2272 uvwasi__free(uvwasi, resolved_new_path);
2273 uv_fs_req_cleanup(&req);
2274 if (r != 0)
2275 return uvwasi__translate_uv_error(r);
2276
2277 return UVWASI_ESUCCESS;
2278 }
2279
2280
uvwasi_path_unlink_file(uvwasi_t * uvwasi,uvwasi_fd_t fd,const char * path,uvwasi_size_t path_len)2281 uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi,
2282 uvwasi_fd_t fd,
2283 const char* path,
2284 uvwasi_size_t path_len) {
2285 char* resolved_path;
2286 struct uvwasi_fd_wrap_t* wrap;
2287 uv_fs_t req;
2288 uvwasi_errno_t err;
2289 int r;
2290
2291 UVWASI_DEBUG("uvwasi_path_unlink_file(uvwasi=%p, fd=%d, path='%s', "
2292 "path_len=%d)\n",
2293 uvwasi,
2294 fd,
2295 path,
2296 path_len);
2297
2298 if (uvwasi == NULL || path == NULL)
2299 return UVWASI_EINVAL;
2300
2301 err = uvwasi_fd_table_get(uvwasi->fds,
2302 fd,
2303 &wrap,
2304 UVWASI_RIGHT_PATH_UNLINK_FILE,
2305 0);
2306 if (err != UVWASI_ESUCCESS)
2307 return err;
2308
2309 err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0);
2310 if (err != UVWASI_ESUCCESS) {
2311 uv_mutex_unlock(&wrap->mutex);
2312 return err;
2313 }
2314
2315 r = uv_fs_unlink(NULL, &req, resolved_path, NULL);
2316 uv_mutex_unlock(&wrap->mutex);
2317 uvwasi__free(uvwasi, resolved_path);
2318 uv_fs_req_cleanup(&req);
2319
2320 if (r != 0)
2321 return uvwasi__translate_uv_error(r);
2322
2323 return UVWASI_ESUCCESS;
2324 }
2325
2326
uvwasi_poll_oneoff(uvwasi_t * uvwasi,const uvwasi_subscription_t * in,uvwasi_event_t * out,uvwasi_size_t nsubscriptions,uvwasi_size_t * nevents)2327 uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi,
2328 const uvwasi_subscription_t* in,
2329 uvwasi_event_t* out,
2330 uvwasi_size_t nsubscriptions,
2331 uvwasi_size_t* nevents) {
2332 struct uvwasi_poll_oneoff_state_t state;
2333 struct uvwasi__poll_fdevent_t* fdevent;
2334 uvwasi_userdata_t timer_userdata;
2335 uvwasi_timestamp_t min_timeout;
2336 uvwasi_timestamp_t cur_timeout;
2337 uvwasi_timestamp_t now;
2338 uvwasi_subscription_t sub;
2339 uvwasi_event_t* event;
2340 uvwasi_errno_t err;
2341 int has_timeout;
2342 uvwasi_size_t i;
2343
2344 UVWASI_DEBUG("uvwasi_poll_oneoff(uvwasi=%p, in=%p, out=%p, "
2345 "nsubscriptions=%d, nevents=%p)\n",
2346 uvwasi,
2347 in,
2348 out,
2349 nsubscriptions,
2350 nevents);
2351
2352 if (uvwasi == NULL || in == NULL || out == NULL ||
2353 nsubscriptions == 0 || nevents == NULL) {
2354 return UVWASI_EINVAL;
2355 }
2356
2357 *nevents = 0;
2358 err = uvwasi__poll_oneoff_state_init(uvwasi, &state, nsubscriptions);
2359 if (err != UVWASI_ESUCCESS)
2360 return err;
2361
2362 timer_userdata = 0;
2363 has_timeout = 0;
2364 min_timeout = 0;
2365
2366 for (i = 0; i < nsubscriptions; i++) {
2367 sub = in[i];
2368
2369 switch (sub.type) {
2370 case UVWASI_EVENTTYPE_CLOCK:
2371 if (sub.u.clock.flags == UVWASI_SUBSCRIPTION_CLOCK_ABSTIME) {
2372 /* Convert absolute time to relative delay. */
2373 err = uvwasi__clock_gettime_realtime(&now);
2374 if (err != UVWASI_ESUCCESS)
2375 goto exit;
2376
2377 cur_timeout = sub.u.clock.timeout - now;
2378 } else {
2379 cur_timeout = sub.u.clock.timeout;
2380 }
2381
2382 if (has_timeout == 0 || cur_timeout < min_timeout) {
2383 min_timeout = cur_timeout;
2384 timer_userdata = sub.userdata;
2385 has_timeout = 1;
2386 }
2387
2388 break;
2389 case UVWASI_EVENTTYPE_FD_READ:
2390 case UVWASI_EVENTTYPE_FD_WRITE:
2391 err = uvwasi__poll_oneoff_state_add_fdevent(&state, &sub);
2392 if (err != UVWASI_ESUCCESS)
2393 goto exit;
2394
2395 break;
2396 default:
2397 err = UVWASI_EINVAL;
2398 goto exit;
2399 }
2400 }
2401
2402 if (has_timeout == 1) {
2403 err = uvwasi__poll_oneoff_state_set_timer(&state, min_timeout);
2404 if (err != UVWASI_ESUCCESS)
2405 goto exit;
2406 }
2407
2408 /* Handle poll() errors, then timeouts, then happy path. */
2409 err = uvwasi__poll_oneoff_run(&state);
2410 if (err != UVWASI_ESUCCESS) {
2411 goto exit;
2412 } else if (state.result == 0) {
2413 event = &out[0];
2414 event->userdata = timer_userdata;
2415 event->error = UVWASI_ESUCCESS;
2416 event->type = UVWASI_EVENTTYPE_CLOCK;
2417 *nevents = 1;
2418 } else {
2419 for (i = 0; i < state.fdevent_cnt; i++) {
2420 fdevent = &state.fdevents[i];
2421 event = &out[*nevents];
2422
2423 event->userdata = fdevent->userdata;
2424 event->error = fdevent->error;
2425 event->type = fdevent->type;
2426 event->u.fd_readwrite.nbytes = 0;
2427 event->u.fd_readwrite.flags = 0;
2428
2429 if (fdevent->error != UVWASI_ESUCCESS)
2430 ;
2431 else if ((fdevent->revents & UV_DISCONNECT) != 0)
2432 event->u.fd_readwrite.flags = UVWASI_EVENT_FD_READWRITE_HANGUP;
2433 else if ((fdevent->revents & (UV_READABLE | UV_WRITABLE)) != 0)
2434 ; /* TODO(cjihrig): Set nbytes if type is UVWASI_EVENTTYPE_FD_READ. */
2435 else
2436 continue;
2437
2438 *nevents = *nevents + 1;
2439 }
2440 }
2441
2442 err = UVWASI_ESUCCESS;
2443
2444 exit:
2445 uvwasi__poll_oneoff_state_cleanup(&state);
2446 return err;
2447 }
2448
2449
uvwasi_proc_exit(uvwasi_t * uvwasi,uvwasi_exitcode_t rval)2450 uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval) {
2451 UVWASI_DEBUG("uvwasi_proc_exit(uvwasi=%p, rval=%d)\n", uvwasi, rval);
2452 exit(rval);
2453 return UVWASI_ESUCCESS; /* This doesn't happen. */
2454 }
2455
2456
uvwasi_proc_raise(uvwasi_t * uvwasi,uvwasi_signal_t sig)2457 uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig) {
2458 int r;
2459
2460 UVWASI_DEBUG("uvwasi_proc_raise(uvwasi=%p, sig=%d)\n", uvwasi, sig);
2461
2462 if (uvwasi == NULL)
2463 return UVWASI_EINVAL;
2464
2465 r = uvwasi__translate_to_uv_signal(sig);
2466 if (r == -1)
2467 return UVWASI_ENOSYS;
2468
2469 r = uv_kill(uv_os_getpid(), r);
2470 if (r != 0)
2471 return uvwasi__translate_uv_error(r);
2472
2473 return UVWASI_ESUCCESS;
2474 }
2475
2476
uvwasi_random_get(uvwasi_t * uvwasi,void * buf,uvwasi_size_t buf_len)2477 uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi,
2478 void* buf,
2479 uvwasi_size_t buf_len) {
2480 int r;
2481
2482 UVWASI_DEBUG("uvwasi_random_get(uvwasi=%p, buf=%p, buf_len=%d)\n",
2483 uvwasi,
2484 buf,
2485 buf_len);
2486
2487 if (uvwasi == NULL || buf == NULL)
2488 return UVWASI_EINVAL;
2489
2490 r = uv_random(NULL, NULL, buf, buf_len, 0, NULL);
2491 if (r != 0)
2492 return uvwasi__translate_uv_error(r);
2493
2494 return UVWASI_ESUCCESS;
2495 }
2496
2497
uvwasi_sched_yield(uvwasi_t * uvwasi)2498 uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) {
2499 UVWASI_DEBUG("uvwasi_sched_yield(uvwasi=%p)\n", uvwasi);
2500
2501 if (uvwasi == NULL)
2502 return UVWASI_EINVAL;
2503
2504 #ifndef _WIN32
2505 if (0 != sched_yield())
2506 return uvwasi__translate_uv_error(uv_translate_sys_error(errno));
2507 #else
2508 SwitchToThread();
2509 #endif /* _WIN32 */
2510
2511 return UVWASI_ESUCCESS;
2512 }
2513
2514
uvwasi_sock_recv(uvwasi_t * uvwasi,uvwasi_fd_t sock,const uvwasi_iovec_t * ri_data,uvwasi_size_t ri_data_len,uvwasi_riflags_t ri_flags,uvwasi_size_t * ro_datalen,uvwasi_roflags_t * ro_flags)2515 uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi,
2516 uvwasi_fd_t sock,
2517 const uvwasi_iovec_t* ri_data,
2518 uvwasi_size_t ri_data_len,
2519 uvwasi_riflags_t ri_flags,
2520 uvwasi_size_t* ro_datalen,
2521 uvwasi_roflags_t* ro_flags) {
2522 /* TODO(cjihrig): Waiting to implement, pending
2523 https://github.com/WebAssembly/WASI/issues/4 */
2524 UVWASI_DEBUG("uvwasi_sock_recv(uvwasi=%p, unimplemented)\n", uvwasi);
2525 return UVWASI_ENOTSUP;
2526 }
2527
2528
uvwasi_sock_send(uvwasi_t * uvwasi,uvwasi_fd_t sock,const uvwasi_ciovec_t * si_data,uvwasi_size_t si_data_len,uvwasi_siflags_t si_flags,uvwasi_size_t * so_datalen)2529 uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi,
2530 uvwasi_fd_t sock,
2531 const uvwasi_ciovec_t* si_data,
2532 uvwasi_size_t si_data_len,
2533 uvwasi_siflags_t si_flags,
2534 uvwasi_size_t* so_datalen) {
2535 /* TODO(cjihrig): Waiting to implement, pending
2536 https://github.com/WebAssembly/WASI/issues/4 */
2537 UVWASI_DEBUG("uvwasi_sock_send(uvwasi=%p, unimplemented)\n", uvwasi);
2538 return UVWASI_ENOTSUP;
2539 }
2540
2541
uvwasi_sock_shutdown(uvwasi_t * uvwasi,uvwasi_fd_t sock,uvwasi_sdflags_t how)2542 uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi,
2543 uvwasi_fd_t sock,
2544 uvwasi_sdflags_t how) {
2545 /* TODO(cjihrig): Waiting to implement, pending
2546 https://github.com/WebAssembly/WASI/issues/4 */
2547 UVWASI_DEBUG("uvwasi_sock_shutdown(uvwasi=%p, unimplemented)\n", uvwasi);
2548 return UVWASI_ENOTSUP;
2549 }
2550
2551
uvwasi_embedder_err_code_to_string(uvwasi_errno_t code)2552 const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code) {
2553 switch (code) {
2554 #define V(errcode) case errcode: return #errcode;
2555 V(UVWASI_E2BIG)
2556 V(UVWASI_EACCES)
2557 V(UVWASI_EADDRINUSE)
2558 V(UVWASI_EADDRNOTAVAIL)
2559 V(UVWASI_EAFNOSUPPORT)
2560 V(UVWASI_EAGAIN)
2561 V(UVWASI_EALREADY)
2562 V(UVWASI_EBADF)
2563 V(UVWASI_EBADMSG)
2564 V(UVWASI_EBUSY)
2565 V(UVWASI_ECANCELED)
2566 V(UVWASI_ECHILD)
2567 V(UVWASI_ECONNABORTED)
2568 V(UVWASI_ECONNREFUSED)
2569 V(UVWASI_ECONNRESET)
2570 V(UVWASI_EDEADLK)
2571 V(UVWASI_EDESTADDRREQ)
2572 V(UVWASI_EDOM)
2573 V(UVWASI_EDQUOT)
2574 V(UVWASI_EEXIST)
2575 V(UVWASI_EFAULT)
2576 V(UVWASI_EFBIG)
2577 V(UVWASI_EHOSTUNREACH)
2578 V(UVWASI_EIDRM)
2579 V(UVWASI_EILSEQ)
2580 V(UVWASI_EINPROGRESS)
2581 V(UVWASI_EINTR)
2582 V(UVWASI_EINVAL)
2583 V(UVWASI_EIO)
2584 V(UVWASI_EISCONN)
2585 V(UVWASI_EISDIR)
2586 V(UVWASI_ELOOP)
2587 V(UVWASI_EMFILE)
2588 V(UVWASI_EMLINK)
2589 V(UVWASI_EMSGSIZE)
2590 V(UVWASI_EMULTIHOP)
2591 V(UVWASI_ENAMETOOLONG)
2592 V(UVWASI_ENETDOWN)
2593 V(UVWASI_ENETRESET)
2594 V(UVWASI_ENETUNREACH)
2595 V(UVWASI_ENFILE)
2596 V(UVWASI_ENOBUFS)
2597 V(UVWASI_ENODEV)
2598 V(UVWASI_ENOENT)
2599 V(UVWASI_ENOEXEC)
2600 V(UVWASI_ENOLCK)
2601 V(UVWASI_ENOLINK)
2602 V(UVWASI_ENOMEM)
2603 V(UVWASI_ENOMSG)
2604 V(UVWASI_ENOPROTOOPT)
2605 V(UVWASI_ENOSPC)
2606 V(UVWASI_ENOSYS)
2607 V(UVWASI_ENOTCONN)
2608 V(UVWASI_ENOTDIR)
2609 V(UVWASI_ENOTEMPTY)
2610 V(UVWASI_ENOTRECOVERABLE)
2611 V(UVWASI_ENOTSOCK)
2612 V(UVWASI_ENOTSUP)
2613 V(UVWASI_ENOTTY)
2614 V(UVWASI_ENXIO)
2615 V(UVWASI_EOVERFLOW)
2616 V(UVWASI_EOWNERDEAD)
2617 V(UVWASI_EPERM)
2618 V(UVWASI_EPIPE)
2619 V(UVWASI_EPROTO)
2620 V(UVWASI_EPROTONOSUPPORT)
2621 V(UVWASI_EPROTOTYPE)
2622 V(UVWASI_ERANGE)
2623 V(UVWASI_EROFS)
2624 V(UVWASI_ESPIPE)
2625 V(UVWASI_ESRCH)
2626 V(UVWASI_ESTALE)
2627 V(UVWASI_ETIMEDOUT)
2628 V(UVWASI_ETXTBSY)
2629 V(UVWASI_EXDEV)
2630 V(UVWASI_ENOTCAPABLE)
2631 V(UVWASI_ESUCCESS)
2632 #undef V
2633 default:
2634 return "UVWASI_UNKNOWN_ERROR";
2635 }
2636 }
2637