diff --git a/src/wasi/WASI.cpp b/src/wasi/WASI.cpp index c154b29af..e097c0799 100644 --- a/src/wasi/WASI.cpp +++ b/src/wasi/WASI.cpp @@ -308,6 +308,24 @@ void WASI::fd_renumber(ExecutionState& state, Value* argv, Value* result, Instan result[0] = Value(uvwasi_fd_renumber(WASI::g_uvwasi, from, to)); } +void WASI::fd_filestat_set_times(ExecutionState& state, Value* argv, Value* result, Instance* instance) +{ + uint32_t fd = argv[0].asI32(); + uint64_t st_atim = argv[1].asI64(); + uint64_t st_mtim = argv[2].asI64(); + uint32_t fst_flags = argv[3].asI32(); + + result[0] = Value(uvwasi_fd_filestat_set_times(WASI::g_uvwasi, fd, st_atim, st_mtim, fst_flags)); +} + +void WASI::sock_shutdown(ExecutionState& state, Value* argv, Value* result, Instance* instance) +{ + uint32_t sock = argv[0].asI32(); + uint32_t how = argv[1].asI32(); + + result[0] = Value(uvwasi_sock_shutdown(WASI::g_uvwasi, sock, how)); +} + void WASI::fd_fdstat_get(ExecutionState& state, Value* argv, Value* result, Instance* instance) { uint32_t fd = argv[0].asI32(); diff --git a/src/wasi/WASI.h b/src/wasi/WASI.h index 14235ac38..bfd0ac0eb 100644 --- a/src/wasi/WASI.h +++ b/src/wasi/WASI.h @@ -52,6 +52,7 @@ class WASI { F(fd_datasync, I32_RI32) \ F(fd_sync, I32_RI32) \ F(fd_renumber, I32I32_RI32) \ + F(fd_filestat_set_times, I32I64I64I32_RI32) \ F(fd_fdstat_get, I32I32_RI32) \ F(fd_fdstat_set_flags, I32I32_RI32) \ F(fd_prestat_get, I32I32_RI32) \ @@ -70,7 +71,8 @@ class WASI { F(poll_oneoff, I32I32I32I32_RI32) \ F(environ_get, I32I32_RI32) \ F(environ_sizes_get, I32I32_RI32) \ - F(sched_yield, RI32) + F(sched_yield, RI32) \ + F(sock_shutdown, I32I32_RI32) #define ERRORS(ERR) \ ERR(success, "no error") \ diff --git a/test/wasi/fd_filestat_set_times.wast b/test/wasi/fd_filestat_set_times.wast new file mode 100644 index 000000000..3c988dc42 --- /dev/null +++ b/test/wasi/fd_filestat_set_times.wast @@ -0,0 +1,66 @@ +(module + (import "wasi_snapshot_preview1" "path_open" + (func $path_open (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32))) + (import "wasi_snapshot_preview1" "fd_filestat_set_times" + (func $fd_filestat_set_times (param i32 i64 i64 i32) (result i32))) + (import "wasi_snapshot_preview1" "fd_close" + (func $fd_close (param i32) (result i32))) + + (memory 1) + (data (i32.const 300) "./write_to_this.txt") ;; 19 bytes, file path + + ;; Open file, call fd_filestat_set_times with ATIM_NOW|MTIM_NOW, close. + ;; Returns errno of fd_filestat_set_times. + (func (export "test_filestat_set_times") (result i32) + ;; --- path_open --- + i32.const 3 + i32.const 1 + i32.const 300 + i32.const 19 + i32.const 9 ;; oflags: creat|trunc + i64.const 8396864 ;; FD_WRITE(64) | PATH_OPEN(8192) | FD_FILESTAT_SET_TIMES(8388608) + i64.const 8396864 + i32.const 0 + i32.const 0 ;; store opened fd at memory[0] + call $path_open + i32.eqz + (if (then) (else i32.const 1 return)) ;; abort if open failed + + ;; --- fd_filestat_set_times: test target --- + i32.const 0 + i32.load ;; fd + i64.const 0 ;; atim (ignored: ATIM_NOW is set) + i64.const 0 ;; mtim (ignored: MTIM_NOW is set) + i32.const 10 ;; fst_flags: ATIM_NOW(2) | MTIM_NOW(8) = 10 + call $fd_filestat_set_times + ;; stash errno at memory[700] so we can close before returning + i32.const 700 + i32.store + + ;; --- fd_close --- + i32.const 0 + i32.load + call $fd_close + drop + + i32.const 700 + i32.load ;; return stashed errno + ) + + ;; Call fd_filestat_set_times with an invalid fd. Expects errno::badf (8). + (func (export "test_filestat_set_times_invalid_fd") (result i32) + i32.const 99 ;; non-existent fd + i64.const 0 + i64.const 0 + i32.const 0 + call $fd_filestat_set_times + ) + + (export "memory" (memory 0)) +) + +;; Valid fd: fd_filestat_set_times should succeed (errno::success = 0) +(assert_return (invoke "test_filestat_set_times") (i32.const 0)) + +;; Invalid fd: should return errno::badf (8) +(assert_return (invoke "test_filestat_set_times_invalid_fd") (i32.const 8)) diff --git a/test/wasi/sock_shutdown.wast b/test/wasi/sock_shutdown.wast new file mode 100644 index 000000000..694fff59b --- /dev/null +++ b/test/wasi/sock_shutdown.wast @@ -0,0 +1,30 @@ +(module + (import "wasi_snapshot_preview1" "sock_shutdown" + (func $sock_shutdown (param i32 i32) (result i32))) + + (memory 1) + + ;; Call sock_shutdown with an invalid fd and how=SHUT_WR(2). + ;; uvwasi proceeds to fd lookup -> fd not found -> errno::badf (8). + (func (export "test_sock_shutdown_invalid_fd") (result i32) + i32.const 99 ;; non-existent fd + i32.const 2 ;; how: SHUT_WR (the only supported flag) + call $sock_shutdown + ) + + ;; Call sock_shutdown with how=SHUT_RD(1). + ;; SHUT_RD is defined but not implemented in uvwasi: (how & ~SHUT_WR) fires -> errno::notsup (58). + (func (export "test_sock_shutdown_notsup") (result i32) + i32.const 0 ;; fd (irrelevant: flag check fires first) + i32.const 1 ;; how: SHUT_RD (defined but not implemented in uvwasi) + call $sock_shutdown + ) + + (export "memory" (memory 0)) +) + +;; Invalid fd with valid how: errno::badf (8) +(assert_return (invoke "test_sock_shutdown_invalid_fd") (i32.const 8)) + +;; Unsupported how flag (SHUT_RD): errno::notsup (58) +(assert_return (invoke "test_sock_shutdown_notsup") (i32.const 58))