Bug Summary

File:out/../deps/uvwasi/src/uvwasi.c
Warning:line 93, column 20
The left operand of '/' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

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