Class: Dewasm::Pozeiden::WasmModule::Rt::WASI
- Inherits:
-
Object
- Object
- Dewasm::Pozeiden::WasmModule::Rt::WASI
- Defined in:
- lib/dewasm/pozeiden/wasm_module.rb
Defined Under Namespace
Classes: WasiDir
Constant Summary collapse
- ERRNO_SUCCESS =
0- ERRNO_BADF =
8- ERRNO_INVAL =
28- ERRNO_IO =
29- ERRNO_NOSYS =
52- ERRNO_NOTSUP =
58- ERRNO_SPIPE =
70- ERRNO_NOTCAPABLE =
NOTCAPABLE lives in this always-bundled prelude, not errno_fs, because the per-fd rights model raises it from the stdio-core fd_* units too, not only from the path_* units that pull in errno_fs.
76- ERRNO_ACCES =
Filesystem-only errno codes: kept out of the always-bundled wasi/class prelude so a stdio-only WASI module (no path* / fs-only fd_* imports) doesn't carry them.
2- ERRNO_EXIST =
20- ERRNO_ISDIR =
31- ERRNO_LOOP =
32- ERRNO_NAMETOOLONG =
37- ERRNO_NOENT =
44- ERRNO_NOTDIR =
54- ERRNO_NOTEMPTY =
55- ERRNO_PERM =
63- FS_ERRNO =
One SystemCallError-to-WASI-errno table shared by every filesystem syscall, so the same host error never maps to different codes depending on which syscall raised it.
{ Errno::EACCES => ERRNO_ACCES, Errno::EBADF => ERRNO_BADF, Errno::EEXIST => ERRNO_EXIST, Errno::EINVAL => ERRNO_INVAL, Errno::EISDIR => ERRNO_ISDIR, Errno::ELOOP => ERRNO_LOOP, Errno::ENAMETOOLONG => ERRNO_NAMETOOLONG, Errno::ENOENT => ERRNO_NOENT, Errno::ENOTDIR => ERRNO_NOTDIR, Errno::ENOTEMPTY => ERRNO_NOTEMPTY, Errno::EPERM => ERRNO_PERM, Errno::ESPIPE => ERRNO_SPIPE, }.freeze
- RIGHT_FD_DATASYNC =
WASI p1 rights bits and the per-filetype masks used to grant and enforce capabilities. Kept in its own unit so every rights-aware syscall can require it without pulling extra filesystem code. The
@fd_metamap (fd => [base, inheriting, fdflags]) that these operate on is seeded in wasi/_class. 1 << 0
- RIGHT_FD_READ =
1 << 1
- RIGHT_FD_SEEK =
1 << 2
- RIGHT_FD_FDSTAT_SET_FLAGS =
1 << 3
- RIGHT_FD_SYNC =
1 << 4
- RIGHT_FD_TELL =
1 << 5
- RIGHT_FD_WRITE =
1 << 6
- RIGHT_FD_ADVISE =
1 << 7
- RIGHT_FD_ALLOCATE =
1 << 8
- RIGHT_PATH_CREATE_DIRECTORY =
1 << 9
- RIGHT_PATH_CREATE_FILE =
1 << 10
- RIGHT_PATH_LINK_SOURCE =
1 << 11
- RIGHT_PATH_LINK_TARGET =
1 << 12
- RIGHT_PATH_OPEN =
1 << 13
- RIGHT_FD_READDIR =
1 << 14
- RIGHT_PATH_READLINK =
1 << 15
- RIGHT_PATH_RENAME_SOURCE =
1 << 16
- RIGHT_PATH_RENAME_TARGET =
1 << 17
- RIGHT_PATH_FILESTAT_GET =
1 << 18
- RIGHT_PATH_FILESTAT_SET_SIZE =
1 << 19
- RIGHT_PATH_FILESTAT_SET_TIMES =
1 << 20
- RIGHT_FD_FILESTAT_GET =
1 << 21
- RIGHT_FD_FILESTAT_SET_SIZE =
1 << 22
- RIGHT_FD_FILESTAT_SET_TIMES =
1 << 23
- RIGHT_PATH_SYMLINK =
1 << 24
- RIGHT_PATH_REMOVE_DIRECTORY =
1 << 25
- RIGHT_PATH_UNLINK_FILE =
1 << 26
- RIGHT_POLL_FD_READWRITE =
1 << 27
- FILE_BASE_RIGHTS =
Rights a regular-file fd may carry, and the two directory masks. A directory fd's base is narrowed to DIR_BASE_RIGHTS (so a requested FD_SEEK or FD_WRITE is dropped rather than granted), and its inheriting rights add the file rights it may pass to children (DIR_INHERITING_RIGHTS). These mirror the fixed masks wasi-common applies at path_open.
RIGHT_FD_DATASYNC | RIGHT_FD_READ | RIGHT_FD_SEEK | RIGHT_FD_FDSTAT_SET_FLAGS | RIGHT_FD_SYNC | RIGHT_FD_TELL | RIGHT_FD_WRITE | RIGHT_FD_ADVISE | RIGHT_FD_ALLOCATE | RIGHT_FD_FILESTAT_GET | RIGHT_FD_FILESTAT_SET_SIZE | RIGHT_FD_FILESTAT_SET_TIMES | RIGHT_POLL_FD_READWRITE
- DIR_BASE_RIGHTS =
RIGHT_PATH_CREATE_DIRECTORY | RIGHT_PATH_CREATE_FILE | RIGHT_PATH_LINK_SOURCE | RIGHT_PATH_LINK_TARGET | RIGHT_PATH_OPEN | RIGHT_FD_READDIR | RIGHT_PATH_READLINK | RIGHT_PATH_RENAME_SOURCE | RIGHT_PATH_RENAME_TARGET | RIGHT_PATH_FILESTAT_GET | RIGHT_PATH_FILESTAT_SET_SIZE | RIGHT_PATH_FILESTAT_SET_TIMES | RIGHT_FD_FILESTAT_GET | RIGHT_FD_FILESTAT_SET_TIMES | RIGHT_PATH_SYMLINK | RIGHT_PATH_REMOVE_DIRECTORY | RIGHT_PATH_UNLINK_FILE
- DIR_INHERITING_RIGHTS =
DIR_BASE_RIGHTS | FILE_BASE_RIGHTS
Instance Attribute Summary collapse
-
#memory ⇒ Object
readonly
Returns the value of attribute memory.
Instance Method Summary collapse
- #attach(instance) ⇒ Object
-
#import(name) ⇒ Object
Import-provider protocol: a custom WASI runtime replaces this class wholesale by implementing these two methods.
-
#initialize(args: [], env: {}, preopens: {}) ⇒ WASI
constructor
A new instance of WASI.
- #wasi_clock_res_get(_id, out_ptr) ⇒ Object
- #wasi_clock_time_get(id, _precision, out_ptr) ⇒ Object
- #wasi_environ_get(environ_ptr, buf_ptr) ⇒ Object
- #wasi_environ_sizes_get(count_ptr, buf_size_ptr) ⇒ Object
- #wasi_fd_close(fd) ⇒ Object
- #wasi_fd_fdstat_get(fd, out_ptr) ⇒ Object
- #wasi_fd_filestat_get(fd, buf_ptr) ⇒ Object
- #wasi_fd_filestat_set_size(fd, size) ⇒ Object
- #wasi_fd_pwrite(fd, iovs_ptr, iovs_len, offset, nwritten_ptr) ⇒ Object
- #wasi_fd_read(fd, iovs_ptr, iovs_len, nread_ptr) ⇒ Object
- #wasi_fd_readdir(fd, buf_ptr, buf_len, cookie, bufused_ptr) ⇒ Object
- #wasi_fd_seek(fd, offset, whence, out_ptr) ⇒ Object
- #wasi_fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) ⇒ Object
- #wasi_path_create_directory(dirfd, path_ptr, path_len) ⇒ Object
- #wasi_path_filestat_get(dirfd, flags, path_ptr, path_len, buf_ptr) ⇒ Object
- #wasi_path_remove_directory(dirfd, path_ptr, path_len) ⇒ Object
- #wasi_path_unlink_file(dirfd, path_ptr, path_len) ⇒ Object
- #wasi_random_get(buf_ptr, len) ⇒ Object
- #write_string_list(strings, list_ptr, buf_ptr) ⇒ Object
Constructor Details
#initialize(args: [], env: {}, preopens: {}) ⇒ WASI
Returns a new instance of WASI.
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 454 def initialize(args: [], env: {}, preopens: {}) @args = args.map(&:to_s) @env = env.map { |k, v| "#{k}=#{v}" } @fds = { 0 => $stdin, 1 => $stdout, 2 => $stderr } # Per-fd capability metadata: fd => [rights_base, rights_inheriting, fdflags]. stdio is seeded all-rights (it is never rights-tested and must stay readable/writable); preopens likewise, so a real embedder keeps unrestricted access and path_open derives the narrowed rights from them. @fd_meta = { 0 => [Rt::M64, Rt::M64, 0], 1 => [Rt::M64, Rt::M64, 0], 2 => [Rt::M64, Rt::M64, 0], } # The stdio special-cases (SPIPE on seek/tell/pread/pwrite, no close) # key on the objects captured here, in lockstep with the fd table, not on whatever the globals point at when a syscall runs. @std_ios = [$stdin, $stdout, $stderr].freeze next_fd = 3 preopens.each do |guest, host| # The host path must resolve, but need not be a directory: a single-file preopen (e.g. "/dev/null" for the zeroperl reactor's init probe) is accepted: the guest resolves it as the preopen root itself. real = begin File.realpath(host) rescue SystemCallError => e raise ArgumentError, "preopen #{guest.inspect} => #{host.inspect}: #{e.}" end @fds[next_fd] = WasiDir.new(real, guest, nil) # A preopen is a directory, so its base is the directory-rights set # (no FD_WRITE etc.); its inheriting rights carry the full file-rights set so guest-opened files under it get real read/write capability. # root_directory() in the testsuite reopens the preopen with exactly these, so seeding all-of-M64 here would wrongly hand a directory the write right and make that reopen fail EISDIR. @fd_meta[next_fd] = [DIR_BASE_RIGHTS, DIR_INHERITING_RIGHTS, 0] next_fd += 1 end @next_fd = next_fd $stdout.binmode $stderr.binmode $stdin.binmode end |
Instance Attribute Details
#memory ⇒ Object (readonly)
Returns the value of attribute memory.
452 453 454 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 452 def memory @memory end |
Instance Method Details
#attach(instance) ⇒ Object
494 495 496 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 494 def attach(instance) @memory = instance.memory end |
#import(name) ⇒ Object
Import-provider protocol: a custom WASI runtime replaces this class wholesale by implementing these two methods.
489 490 491 492 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 489 def import(name) meth = :"wasi_#{name}" respond_to?(meth) ? method(meth) : nil end |
#wasi_clock_res_get(_id, out_ptr) ⇒ Object
498 499 500 501 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 498 def wasi_clock_res_get(_id, out_ptr) @memory.i64_store(out_ptr, 1) ERRNO_SUCCESS end |
#wasi_clock_time_get(id, _precision, out_ptr) ⇒ Object
503 504 505 506 507 508 509 510 511 512 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 503 def wasi_clock_time_get(id, _precision, out_ptr) ns = case id when 0 then Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) when 1, 2, 3 then Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) else return ERRNO_INVAL end @memory.i64_store(out_ptr, Rt.m64(ns)) ERRNO_SUCCESS end |
#wasi_environ_get(environ_ptr, buf_ptr) ⇒ Object
514 515 516 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 514 def wasi_environ_get(environ_ptr, buf_ptr) write_string_list(@env, environ_ptr, buf_ptr) end |
#wasi_environ_sizes_get(count_ptr, buf_size_ptr) ⇒ Object
518 519 520 521 522 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 518 def wasi_environ_sizes_get(count_ptr, buf_size_ptr) @memory.i32_store(count_ptr, @env.size) @memory.i32_store(buf_size_ptr, @env.sum { |e| e.bytesize + 1 }) ERRNO_SUCCESS end |
#wasi_fd_close(fd) ⇒ Object
557 558 559 560 561 562 563 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 557 def wasi_fd_close(fd) io = @fds.delete(fd) return ERRNO_BADF unless io return ERRNO_SUCCESS if io.is_a?(WasiDir) # no real OS handle to close io.close unless @std_ios.include?(io) ERRNO_SUCCESS end |
#wasi_fd_fdstat_get(fd, out_ptr) ⇒ Object
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 565 def wasi_fd_fdstat_get(fd, out_ptr) io = @fds[fd] return ERRNO_BADF unless io filetype = if io.is_a?(WasiDir) 3 # directory else io.respond_to?(:tty?) && io.tty? ? 2 : 4 # char device / regular file end base, inheriting, fdflags = @fd_meta[fd] || [Rt::M64, Rt::M64, 0] @memory.fill(out_ptr, 0, 24) @memory.i32_store8(out_ptr, filetype) @memory.i32_store16(out_ptr + 2, fdflags) @memory.i64_store(out_ptr + 8, base) @memory.i64_store(out_ptr + 16, inheriting) ERRNO_SUCCESS end |
#wasi_fd_filestat_get(fd, buf_ptr) ⇒ Object
583 584 585 586 587 588 589 590 591 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 583 def wasi_fd_filestat_get(fd, buf_ptr) entry = @fds[fd] return ERRNO_BADF unless entry stat = entry.is_a?(WasiDir) ? File.stat(entry.host_path) : entry.stat @memory.init(buf_ptr, pack_filestat(stat), 0, 64) ERRNO_SUCCESS rescue SystemCallError ERRNO_IO end |
#wasi_fd_filestat_set_size(fd, size) ⇒ Object
593 594 595 596 597 598 599 600 601 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 593 def wasi_fd_filestat_set_size(fd, size) io = @fds[fd] return ERRNO_BADF if io.nil? || io.is_a?(WasiDir) return ERRNO_NOTCAPABLE unless fd_has_right?(fd, RIGHT_FD_FILESTAT_SET_SIZE) io.truncate(size) ERRNO_SUCCESS rescue SystemCallError ERRNO_IO end |
#wasi_fd_pwrite(fd, iovs_ptr, iovs_len, offset, nwritten_ptr) ⇒ Object
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 603 def wasi_fd_pwrite(fd, iovs_ptr, iovs_len, offset, nwritten_ptr) io = @fds[fd] return ERRNO_BADF if io.nil? || io.is_a?(WasiDir) return ERRNO_SPIPE if @std_ios.include?(io) return ERRNO_NOTCAPABLE unless fd_has_right?(fd, RIGHT_FD_WRITE) written = 0 iovs_len.times do |i| ptr = @memory.i32_load(iovs_ptr + i * 8) len = @memory.i32_load(iovs_ptr + i * 8 + 4) chunk = @memory.read_string(ptr, len) n = io.pwrite(chunk, offset + written) written += n # IO#pwrite is a single pwrite(2), which may write short; stop so the reported nwritten stays contiguous. break if n < chunk.bytesize end @memory.i32_store(nwritten_ptr, written) ERRNO_SUCCESS rescue SystemCallError ERRNO_IO end |
#wasi_fd_read(fd, iovs_ptr, iovs_len, nread_ptr) ⇒ Object
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 624 def wasi_fd_read(fd, iovs_ptr, iovs_len, nread_ptr) io = @fds[fd] return ERRNO_BADF if io.nil? || io.is_a?(WasiDir) return ERRNO_NOTCAPABLE unless fd_has_right?(fd, RIGHT_FD_READ) stdin = @std_ios[0].equal?(io) nread = 0 iovs_len.times do |i| ptr = @memory.i32_load(iovs_ptr + i * 8) len = @memory.i32_load(iovs_ptr + i * 8 + 4) next if len == 0 # stdin may be an interactive tty (the QuickJS REPL under a pty): a buffered # IO#read(len) blocks until the full len arrives or EOF, deadlocking a line-buffered terminal that never sends EOF. readpartial returns as soon as any bytes are available (the WASI short-read semantics wasmtime uses), while poll_oneoff's IO.select already did the waiting. # Files keep #read. if stdin begin chunk = io.readpartial(len) rescue EOFError break end else chunk = io.read(len) break if chunk.nil? end @memory.init(ptr, chunk, 0, chunk.bytesize) nread += chunk.bytesize break if chunk.bytesize < len end @memory.i32_store(nread_ptr, nread) ERRNO_SUCCESS rescue SystemCallError ERRNO_IO end |
#wasi_fd_readdir(fd, buf_ptr, buf_len, cookie, bufused_ptr) ⇒ Object
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 657 def wasi_fd_readdir(fd, buf_ptr, buf_len, , bufused_ptr) entry = @fds[fd] return ERRNO_BADF unless entry.is_a?(WasiDir) return ERRNO_NOTCAPABLE unless fd_has_right?(fd, RIGHT_FD_READDIR) # cookie 0 starts a fresh scan, so re-snapshot the listing (a directory mutated between two full readdirs must show the new state); cookie > 0 continues the snapshot taken when this scan began. entry.entries = readdir_entries(entry.host_path) if .zero? || entry.entries.nil? entries = entry.entries out = +"".b i = while i < entries.size && out.bytesize < buf_len name, filetype, ino = entries[i] # dirent: d_next (u64, resume cookie) + d_ino (u64) + d_namlen (u32) + d_type (u8) + 3 pad, followed immediately by the (unpadded) name. out << [i + 1, ino, name.bytesize, filetype].pack("Q<Q<L<Cx3") << name.b i += 1 end # A dirent may be legally truncated at the tail once buf_len runs out. out = out.byteslice(0, buf_len) if out.bytesize > buf_len @memory.init(buf_ptr, out, 0, out.bytesize) @memory.i32_store(bufused_ptr, out.bytesize) ERRNO_SUCCESS rescue SystemCallError ERRNO_IO end |
#wasi_fd_seek(fd, offset, whence, out_ptr) ⇒ Object
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 695 def wasi_fd_seek(fd, offset, whence, out_ptr) io = @fds[fd] return ERRNO_BADF if io.nil? || io.is_a?(WasiDir) return ERRNO_SPIPE if @std_ios.include?(io) return ERRNO_NOTCAPABLE unless fd_has_right?(fd, RIGHT_FD_SEEK) mode = [IO::SEEK_SET, IO::SEEK_CUR, IO::SEEK_END][whence] return ERRNO_INVAL unless mode io.seek(Rt.s64(offset), mode) @memory.i64_store(out_ptr, Rt.m64(io.tell)) ERRNO_SUCCESS rescue Errno::EINVAL # Seeking before byte 0 raises EINVAL; surface it precisely rather than folding it into the generic ERRNO_IO. ERRNO_INVAL rescue SystemCallError ERRNO_IO end |
#wasi_fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) ⇒ Object
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 712 def wasi_fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) io = @fds[fd] return ERRNO_BADF if io.nil? || io.is_a?(WasiDir) return ERRNO_NOTCAPABLE unless fd_has_right?(fd, RIGHT_FD_WRITE) # APPEND is implemented here rather than via O_APPEND (so fd_fdstat_set_flags can turn it off): seek to end before writing. io.seek(0, IO::SEEK_END) if (@fd_meta[fd][2] & 0x1) != 0 written = 0 iovs_len.times do |i| ptr = @memory.i32_load(iovs_ptr + i * 8) len = @memory.i32_load(iovs_ptr + i * 8 + 4) written += io.write(@memory.read_string(ptr, len)) end io.flush @memory.i32_store(nwritten_ptr, written) ERRNO_SUCCESS rescue SystemCallError ERRNO_IO end |
#wasi_path_create_directory(dirfd, path_ptr, path_len) ⇒ Object
743 744 745 746 747 748 749 750 751 752 753 754 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 743 def wasi_path_create_directory(dirfd, path_ptr, path_len) rel = @memory.read_string(path_ptr, path_len) # Strip a trailing slash: mkdir names a directory anyway, and EEXIST is wasmtime's answer for mkdir("file/") where the hosts split. rel = rel.sub(%r{(.)/+\z}, '\1') # mkdir(2) never follows a trailing symlink (an existing one is EEXIST). host_path, err = resolve_path(dirfd, rel, follow_last: false) return err if err Dir.mkdir(host_path) ERRNO_SUCCESS rescue SystemCallError => e fs_errno(e) end |
#wasi_path_filestat_get(dirfd, flags, path_ptr, path_len, buf_ptr) ⇒ Object
756 757 758 759 760 761 762 763 764 765 766 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 756 def wasi_path_filestat_get(dirfd, flags, path_ptr, path_len, buf_ptr) rel = @memory.read_string(path_ptr, path_len) symlink_follow = flags & 0x1 != 0 # lookupflags::SYMLINK_FOLLOW host_path, err = resolve_path(dirfd, rel, follow_last: symlink_follow) return err if err stat = symlink_follow ? File.stat(host_path) : File.lstat(host_path) @memory.init(buf_ptr, pack_filestat(stat), 0, 64) ERRNO_SUCCESS rescue SystemCallError => e fs_errno(e) end |
#wasi_path_remove_directory(dirfd, path_ptr, path_len) ⇒ Object
768 769 770 771 772 773 774 775 776 777 778 779 780 781 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 768 def wasi_path_remove_directory(dirfd, path_ptr, path_len) rel = @memory.read_string(path_ptr, path_len) # rmdir(2) never follows a trailing symlink. host_path, err = resolve_path(dirfd, rel, follow_last: false) return err if err # rmdir through a trailing slash on an existing directory is EINVAL per wasmtime; other shapes come from the host call. if host_path.end_with?("/") && File.directory?(host_path.delete_suffix("/")) return ERRNO_INVAL end Dir.rmdir(host_path) ERRNO_SUCCESS rescue SystemCallError => e fs_errno(e) end |
#wasi_path_unlink_file(dirfd, path_ptr, path_len) ⇒ Object
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 783 def wasi_path_unlink_file(dirfd, path_ptr, path_len) rel = @memory.read_string(path_ptr, path_len) # unlink(2) never follows a trailing symlink: it removes the link. host_path, err = resolve_path(dirfd, rel, follow_last: false) return err if err # A slash-suffixed non-directory is ENOTDIR, missing is ENOENT; a real directory falls through to File.unlink (host EPERM/EISDIR). # Probe the slash-stripped path: stat on "file/" fails ENOTDIR, reads as missing. if host_path.end_with?("/") = host_path.delete_suffix("/") unless File.directory?() return File.exist?() || File.symlink?() ? ERRNO_NOTDIR : ERRNO_NOENT end end File.unlink(host_path) ERRNO_SUCCESS rescue SystemCallError => e fs_errno(e) end |
#wasi_random_get(buf_ptr, len) ⇒ Object
804 805 806 807 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 804 def wasi_random_get(buf_ptr, len) @memory.init(buf_ptr, SecureRandom.bytes(len), 0, len) ERRNO_SUCCESS end |
#write_string_list(strings, list_ptr, buf_ptr) ⇒ Object
956 957 958 959 960 961 962 963 964 |
# File 'lib/dewasm/pozeiden/wasm_module.rb', line 956 def write_string_list(strings, list_ptr, buf_ptr) strings.each_with_index do |s, i| @memory.i32_store(list_ptr + i * 4, buf_ptr) @memory.init(buf_ptr, s, 0, s.bytesize) @memory.i32_store8(buf_ptr + s.bytesize, 0) buf_ptr += s.bytesize + 1 end ERRNO_SUCCESS end |