wardite 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Steepfile +1 -0
- data/exe/wardite +3 -25
- data/lib/wardite/cli/cli.rb +135 -0
- data/lib/wardite/value.rb +1 -1
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi/consts.rb +7 -0
- data/lib/wardite/wasi/dirent_cache.rb +87 -0
- data/lib/wardite/wasi/preopens.rb +17 -0
- data/lib/wardite/wasi.rb +457 -17
- data/lib/wardite.rb +8 -1
- data/rbs_collection.lock.yaml +204 -0
- data/rbs_collection.yaml +18 -0
- data/sig/bundler.rbs +3 -0
- data/sig/generated/wardite/cli/cli.rbs +52 -0
- data/sig/generated/wardite/wasi/consts.rbs +10 -0
- data/sig/generated/wardite/wasi/dirent_cache.rbs +42 -0
- data/sig/generated/wardite/wasi/preopens.rbs +15 -0
- data/sig/generated/wardite/wasi.rbs +102 -2
- data/sig/generated/wardite.rbs +5 -1
- metadata +11 -2
data/lib/wardite/wasi.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require "wardite/wasm_module"
|
4
4
|
require "wardite/wasi/consts"
|
5
|
+
require "wardite/wasi/preopens"
|
6
|
+
require "wardite/wasi/dirent_cache"
|
5
7
|
require "securerandom"
|
6
8
|
require "fcntl"
|
7
9
|
|
@@ -10,18 +12,136 @@ module Wardite
|
|
10
12
|
include ValueHelper
|
11
13
|
include WasmModule
|
12
14
|
|
13
|
-
attr_accessor :fd_table #:
|
15
|
+
attr_accessor :fd_table #: Hash[Integer, (IO|File|::Wardite::Wasi::PreopenedDir)]
|
16
|
+
attr_accessor :fd_count #: Integer
|
14
17
|
attr_accessor :argv #: Array[String]
|
18
|
+
attr_accessor :mapdir #: Hash[String, String]
|
19
|
+
attr_accessor :dirent_cache #: Hash[Integer, ::Wardite::Wasi::DirentCache]
|
15
20
|
|
16
21
|
# @rbs argv: Array[String]
|
22
|
+
# @rbs mapdir: Hash[String, String]
|
17
23
|
# @rbs return: void
|
18
|
-
def initialize(argv: [])
|
19
|
-
@fd_table =
|
20
|
-
STDIN,
|
21
|
-
STDOUT,
|
22
|
-
STDERR,
|
23
|
-
|
24
|
+
def initialize(argv: [], mapdir: {})
|
25
|
+
@fd_table = {
|
26
|
+
0 => STDIN,
|
27
|
+
1 => STDOUT,
|
28
|
+
2 => STDERR,
|
29
|
+
}
|
30
|
+
@fd_count = 3
|
24
31
|
@argv = argv
|
32
|
+
@mapdir = mapdir
|
33
|
+
|
34
|
+
@dirent_cache = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
# @rbs file: IO|File|::Wardite::Wasi::PreopenedDir
|
38
|
+
# @rbs return: Integer
|
39
|
+
def set_fd(file)
|
40
|
+
fd = @fd_count
|
41
|
+
@fd_table[fd] = file
|
42
|
+
@fd_count += 1
|
43
|
+
fd
|
44
|
+
end
|
45
|
+
|
46
|
+
# @rbs path: String
|
47
|
+
# @rbs guest_path: String
|
48
|
+
# @rbs return: void
|
49
|
+
def set_preopened_dir(path, guest_path)
|
50
|
+
fd = @fd_count
|
51
|
+
set_fd(::Wardite::Wasi::PreopenedDir.new(path, guest_path, fd))
|
52
|
+
end
|
53
|
+
|
54
|
+
# @rbs orig_path: String
|
55
|
+
# @rbs return: String
|
56
|
+
def resolv_path(orig_path)
|
57
|
+
@mapdir.each do |k, v|
|
58
|
+
if orig_path.start_with?(k)
|
59
|
+
return v + orig_path[k.size..-1].to_s
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
return orig_path
|
64
|
+
end
|
65
|
+
|
66
|
+
# @rbs atfd: Integer
|
67
|
+
# @rbs target: String
|
68
|
+
# @rbs return: String
|
69
|
+
def get_path_at(atfd, target)
|
70
|
+
target = resolv_path(target)
|
71
|
+
|
72
|
+
at = @fd_table[atfd]
|
73
|
+
pwd = case at
|
74
|
+
when Wasi::PreopenedDir
|
75
|
+
at.guest_path
|
76
|
+
when File
|
77
|
+
Dir.fchdir(at.fileno) do
|
78
|
+
Dir.pwd
|
79
|
+
end
|
80
|
+
else
|
81
|
+
raise ArgumentError, "invalid fd: #{atfd}"
|
82
|
+
end
|
83
|
+
|
84
|
+
ret = File.expand_path(target, pwd)
|
85
|
+
ret
|
86
|
+
end
|
87
|
+
|
88
|
+
# @rbs dirflags: Integer
|
89
|
+
# @rbs oflags: Integer
|
90
|
+
# @rbs fdflags: Integer
|
91
|
+
# @rbs rights: Integer
|
92
|
+
def interpret_open_flags(dirflags, oflags, fdflags, rights)
|
93
|
+
open_flags = 0
|
94
|
+
if dirflags & Wasi::LOOKUP_SYMLINK_FOLLOW == 0
|
95
|
+
open_flags |= File::Constants::NOFOLLOW
|
96
|
+
end
|
97
|
+
if oflags & Wasi::O_DIRECTORY != 0
|
98
|
+
# open_flags |= File::Constants::DIRECTORY
|
99
|
+
$stderr.puts "O_DIRECTORY is not supported, ignore" if ENV["WARDITE_TRACE"]
|
100
|
+
elsif oflags & Wasi::O_EXCL != 0
|
101
|
+
open_flags |= File::Constants::EXCL
|
102
|
+
end
|
103
|
+
|
104
|
+
default_mode = File::Constants::RDONLY
|
105
|
+
if oflags & Wasi::O_TRUNC != 0
|
106
|
+
open_flags |= File::Constants::TRUNC
|
107
|
+
default_mode = File::Constants::RDWR
|
108
|
+
end
|
109
|
+
if oflags & Wasi::O_CREAT != 0
|
110
|
+
open_flags |= File::Constants::CREAT
|
111
|
+
default_mode = File::Constants::RDWR
|
112
|
+
end
|
113
|
+
if fdflags & Wasi::FD_NONBLOCK != 0
|
114
|
+
open_flags |= File::Constants::NONBLOCK
|
115
|
+
end
|
116
|
+
if fdflags & Wasi::FD_APPEND != 0
|
117
|
+
open_flags |= File::Constants::APPEND
|
118
|
+
default_mode = File::Constants::RDWR
|
119
|
+
end
|
120
|
+
if fdflags & Wasi::FD_DSYNC != 0
|
121
|
+
open_flags |= File::Constants::DSYNC
|
122
|
+
end
|
123
|
+
if fdflags & Wasi::FD_RSYNC != 0
|
124
|
+
open_flags |= File::Constants::RSYNC
|
125
|
+
end
|
126
|
+
if fdflags & Wasi::FD_SYNC != 0
|
127
|
+
open_flags |= File::Constants::SYNC
|
128
|
+
end
|
129
|
+
|
130
|
+
r = Wasi::RIGHT_FD_READ
|
131
|
+
w = Wasi::RIGHT_FD_WRITE
|
132
|
+
rw = r | w
|
133
|
+
case
|
134
|
+
when (rights & rw) == rw
|
135
|
+
open_flags |= File::Constants::RDWR
|
136
|
+
when (rights & w) == w
|
137
|
+
open_flags |= File::Constants::WRONLY
|
138
|
+
when (rights & r) == r
|
139
|
+
open_flags |= File::Constants::RDONLY
|
140
|
+
else
|
141
|
+
open_flags |= default_mode
|
142
|
+
end
|
143
|
+
|
144
|
+
open_flags
|
25
145
|
end
|
26
146
|
|
27
147
|
# @rbs store: Store
|
@@ -137,17 +257,216 @@ module Wardite
|
|
137
257
|
0
|
138
258
|
end
|
139
259
|
|
260
|
+
# @rbs store: Store
|
261
|
+
# @rbs args: Array[wasmValue]
|
262
|
+
# @rbs return: Object
|
263
|
+
def path_create_directory(store, args)
|
264
|
+
fd = args[0].value.to_i
|
265
|
+
path = args[1].value.to_i
|
266
|
+
path_len = args[2].value.to_i
|
267
|
+
path_str = store.memories[0].data[path...(path+path_len)]
|
268
|
+
if !path_str
|
269
|
+
return Wasi::ENOENT
|
270
|
+
end
|
271
|
+
|
272
|
+
target = get_path_at(fd, path_str)
|
273
|
+
Dir.mkdir(target, 0700)
|
274
|
+
0
|
275
|
+
# TODO; rescue EBADF, ENOTDIR
|
276
|
+
end
|
277
|
+
|
278
|
+
# @rbs store: Store
|
279
|
+
# @rbs args: Array[wasmValue]
|
280
|
+
# @rbs return: Object
|
281
|
+
def path_filestat_get(store, args)
|
282
|
+
fd = args[0].value.to_i
|
283
|
+
flags = args[1].value.to_i
|
284
|
+
path = args[2].value.to_i
|
285
|
+
path_len = args[3].value.to_i
|
286
|
+
target = get_path_at(fd, store.memories[0].data[path...(path+path_len)].to_s)
|
287
|
+
|
288
|
+
stat = File.stat(target)
|
289
|
+
memory = store.memories[0]
|
290
|
+
binformat = [
|
291
|
+
stat.dev, stat.ino, Wasi.to_ftype(stat.ftype), stat.nlink,
|
292
|
+
stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i
|
293
|
+
].pack("Q8")
|
294
|
+
memory.data[flags...(flags+binformat.size)] = binformat
|
295
|
+
0
|
296
|
+
rescue Errno::ENOENT
|
297
|
+
return Wasi::ENOENT
|
298
|
+
end
|
299
|
+
|
300
|
+
# @rbs store: Store
|
301
|
+
# @rbs args: Array[wasmValue]
|
302
|
+
# @rbs return: Object
|
303
|
+
def path_filestat_set_times(store, args)
|
304
|
+
fd = args[0].value.to_i
|
305
|
+
# TODO: flags support
|
306
|
+
_flags = args[1].value.to_i
|
307
|
+
path = args[2].value.to_i
|
308
|
+
path_len = args[3].value.to_i
|
309
|
+
atim = args[4].value.to_i # nanoseconds
|
310
|
+
mtim = args[5].value.to_i # nanoseconds
|
311
|
+
target = get_path_at(fd, store.memories[0].data[path...(path+path_len)].to_s)
|
312
|
+
|
313
|
+
atime = Time.at(atim.to_f / 1_000_000_000)
|
314
|
+
mtime = Time.at(mtim.to_f / 1_000_000_000)
|
315
|
+
File.utime(atime, mtime, target)
|
316
|
+
0
|
317
|
+
end
|
318
|
+
|
319
|
+
# @rbs store: Store
|
320
|
+
# @rbs args: Array[wasmValue]
|
321
|
+
# @rbs return: Object
|
322
|
+
def path_link(store, args)
|
323
|
+
old_fd = args[0].value.to_i
|
324
|
+
old_path = args[1].value.to_i
|
325
|
+
old_path_len = args[2].value.to_i
|
326
|
+
old_name = get_path_at(old_fd, store.memories[0].data[old_path...(old_path+old_path_len)].to_s)
|
327
|
+
|
328
|
+
new_fd = args[3].value.to_i
|
329
|
+
new_path = args[4].value.to_i
|
330
|
+
new_path_len = args[5].value.to_i
|
331
|
+
new_name = get_path_at(new_fd, store.memories[0].data[new_path...(new_path+new_path_len)].to_s)
|
332
|
+
|
333
|
+
File.link(old_name, new_name)
|
334
|
+
0
|
335
|
+
end
|
336
|
+
|
337
|
+
# @rbs store: Store
|
338
|
+
# @rbs args: Array[wasmValue]
|
339
|
+
# @rbs return: Object
|
340
|
+
def path_open(store, args)
|
341
|
+
dirfd = args[0].value.to_i
|
342
|
+
dirflags = args[1].value.to_i
|
343
|
+
path = args[2].value.to_i
|
344
|
+
path_len = args[3].value.to_i
|
345
|
+
oflags = args[4].value.to_i
|
346
|
+
fs_rights_base = args[5].value.to_i
|
347
|
+
_fs_rights_inheriting = args[6].value.to_i
|
348
|
+
fs_flags = args[7].value.to_i
|
349
|
+
fd_off = args[8].value.to_i
|
350
|
+
|
351
|
+
path_name = get_path_at(dirfd, store.memories[0].data[path...(path+path_len)].to_s)
|
352
|
+
open_flags = interpret_open_flags(dirflags, oflags, fs_flags, fs_rights_base)
|
353
|
+
is_dir = (oflags & Wasi::O_DIRECTORY) != 0
|
354
|
+
if is_dir && (oflags & Wasi::O_CREAT) != 0
|
355
|
+
return Wasi::EINVAL
|
356
|
+
end
|
357
|
+
|
358
|
+
file = File.open(path_name, open_flags, 0600)
|
359
|
+
fd = set_fd file
|
360
|
+
|
361
|
+
memory = store.memories[0]
|
362
|
+
memory.data[fd_off...(fd_off+4)] = [fd].pack("I!")
|
363
|
+
0
|
364
|
+
rescue Errno::ENOENT
|
365
|
+
return Wasi::ENOENT
|
366
|
+
end
|
367
|
+
|
368
|
+
# @rbs store: Store
|
369
|
+
# @rbs args: Array[wasmValue]
|
370
|
+
# @rbs return: Object
|
371
|
+
def path_readlink(store, args)
|
372
|
+
fd = args[0].value.to_i
|
373
|
+
path = args[1].value.to_i
|
374
|
+
path_len = args[2].value.to_i
|
375
|
+
buf = args[3].value.to_i
|
376
|
+
buf_len = args[4].value.to_i
|
377
|
+
result_buf = args[5].value.to_i
|
378
|
+
|
379
|
+
if buf_len <= 0 || path_len <= 0
|
380
|
+
return Wasi::EINVAL
|
381
|
+
end
|
382
|
+
target = get_path_at(fd, store.memories[0].data[path...(path+path_len)].to_s)
|
383
|
+
|
384
|
+
link_target = File.readlink(target)
|
385
|
+
if link_target.size > buf_len
|
386
|
+
return Wasi::ENAMETOOLONG
|
387
|
+
end
|
388
|
+
|
389
|
+
memory = store.memories[0]
|
390
|
+
memory.data[buf...(buf+link_target.size)] = link_target
|
391
|
+
memory.data[result_buf...(result_buf+4)] = [link_target.size].pack("I!")
|
392
|
+
0
|
393
|
+
end
|
394
|
+
|
395
|
+
# @rbs store: Store
|
396
|
+
# @rbs args: Array[wasmValue]
|
397
|
+
# @rbs return: Object
|
398
|
+
def path_remove_directory(store, args)
|
399
|
+
fd = args[0].value.to_i
|
400
|
+
path = args[1].value.to_i
|
401
|
+
path_len = args[2].value.to_i
|
402
|
+
path_str = store.memories[0].data[path...(path+path_len)].to_s
|
403
|
+
target = get_path_at(fd, path_str)
|
404
|
+
|
405
|
+
Dir.rmdir(target)
|
406
|
+
0
|
407
|
+
end
|
408
|
+
|
409
|
+
# @rbs store: Store
|
410
|
+
# @rbs args: Array[wasmValue]
|
411
|
+
# @rbs return: Object
|
412
|
+
def path_rename(store, args)
|
413
|
+
fd = args[0].value.to_i
|
414
|
+
old_path = args[1].value.to_i
|
415
|
+
old_path_len = args[2].value.to_i
|
416
|
+
|
417
|
+
new_fd = args[3].value.to_i
|
418
|
+
new_path = args[4].value.to_i
|
419
|
+
new_path_len = args[5].value.to_i
|
420
|
+
|
421
|
+
old_target = get_path_at(fd, store.memories[0].data[old_path...(old_path+old_path_len)].to_s)
|
422
|
+
new_target = get_path_at(new_fd, store.memories[0].data[new_path...(new_path+new_path_len)].to_s)
|
423
|
+
|
424
|
+
File.rename(old_target, new_target)
|
425
|
+
0
|
426
|
+
end
|
427
|
+
|
428
|
+
# @rbs store: Store
|
429
|
+
# @rbs args: Array[wasmValue]
|
430
|
+
# @rbs return: Object
|
431
|
+
def path_symlink(store, args)
|
432
|
+
old_path = args[0].value.to_i
|
433
|
+
old_path_len = args[1].value.to_i
|
434
|
+
old_name = store.memories[0].data[old_path...(old_path+old_path_len)].to_s
|
435
|
+
|
436
|
+
fd = args[2].value.to_i
|
437
|
+
new_path = args[3].value.to_i
|
438
|
+
new_path_len = args[4].value.to_i
|
439
|
+
new_name = get_path_at(fd, store.memories[0].data[new_path...(new_path+new_path_len)].to_s)
|
440
|
+
|
441
|
+
File.symlink(old_name, new_name)
|
442
|
+
0
|
443
|
+
end
|
444
|
+
|
445
|
+
# @rbs store: Store
|
446
|
+
# @rbs args: Array[wasmValue]
|
447
|
+
# @rbs return: Object
|
448
|
+
def path_unlink_file(store, args)
|
449
|
+
fd = args[0].value.to_i
|
450
|
+
path = args[1].value.to_i
|
451
|
+
path_len = args[2].value.to_i
|
452
|
+
path_str = store.memories[0].data[path...(path+path_len)].to_s
|
453
|
+
target = get_path_at(fd, path_str)
|
454
|
+
|
455
|
+
File.unlink(target)
|
456
|
+
0
|
457
|
+
end
|
458
|
+
|
140
459
|
# @rbs store: Store
|
141
460
|
# @rbs args: Array[wasmValue]
|
142
461
|
# @rbs return: Object
|
143
462
|
def fd_prestat_get(store, args)
|
144
463
|
fd = args[0].value.to_i
|
145
464
|
prestat_offset = args[1].value.to_i
|
146
|
-
if fd >=
|
465
|
+
if fd >= fd_count
|
147
466
|
return Wasi::EBADF
|
148
467
|
end
|
149
468
|
file = @fd_table[fd]
|
150
|
-
if !file.is_a?(
|
469
|
+
if !file.is_a?(Wasi::PreopenedDir)
|
151
470
|
return Wasi::EBADF
|
152
471
|
end
|
153
472
|
name = file.path
|
@@ -158,6 +477,31 @@ module Wardite
|
|
158
477
|
0
|
159
478
|
end
|
160
479
|
|
480
|
+
# @rbs store: Store
|
481
|
+
# @rbs args: Array[wasmValue]
|
482
|
+
# @rbs return: Object
|
483
|
+
def fd_prestat_dir_name(store, args)
|
484
|
+
fd = args[0].value.to_i
|
485
|
+
path = args[1].value.to_i
|
486
|
+
path_len = args[2].value.to_i
|
487
|
+
if fd >= fd_count
|
488
|
+
return Wasi::EBADF
|
489
|
+
end
|
490
|
+
file = @fd_table[fd]
|
491
|
+
if !file.is_a?(Wasi::PreopenedDir)
|
492
|
+
return Wasi::EBADF
|
493
|
+
end
|
494
|
+
name = file.path
|
495
|
+
if name.size > path_len
|
496
|
+
return Wasi::ENAMETOOLONG
|
497
|
+
end
|
498
|
+
name += ("\0" * (path_len - name.size))
|
499
|
+
|
500
|
+
memory = store.memories[0]
|
501
|
+
memory.data[path...(path+name.size)] = name
|
502
|
+
0
|
503
|
+
end
|
504
|
+
|
161
505
|
# @rbs store: Store
|
162
506
|
# @rbs args: Array[wasmValue]
|
163
507
|
# @rbs return: Object
|
@@ -174,7 +518,7 @@ module Wardite
|
|
174
518
|
raise Wardite::ArgumentError, "args too short"
|
175
519
|
end
|
176
520
|
file = self.fd_table[fd]
|
177
|
-
return Wasi::EBADF if !file
|
521
|
+
return Wasi::EBADF if !file || file.is_a?(Wasi::PreopenedDir)
|
178
522
|
memory = store.memories[0]
|
179
523
|
nwritten = 0
|
180
524
|
iovs_len.times do
|
@@ -207,7 +551,7 @@ module Wardite
|
|
207
551
|
raise Wardite::ArgumentError, "args too short"
|
208
552
|
end
|
209
553
|
file = self.fd_table[fd]
|
210
|
-
return Wasi::EBADF if !file
|
554
|
+
return Wasi::EBADF if !file || file.is_a?(Wasi::PreopenedDir)
|
211
555
|
memory = store.memories[0]
|
212
556
|
nread = 0
|
213
557
|
|
@@ -218,10 +562,10 @@ module Wardite
|
|
218
562
|
iovs += 4
|
219
563
|
buf = file.read(slen)
|
220
564
|
if !buf
|
221
|
-
|
565
|
+
break 0
|
222
566
|
end
|
223
|
-
memory.data[start...(start+
|
224
|
-
nread +=
|
567
|
+
memory.data[start...(start+buf.size)] = buf
|
568
|
+
nread += buf.size
|
225
569
|
end
|
226
570
|
|
227
571
|
memory.data[rp...(rp+4)] = [nread].pack("I!")
|
@@ -234,12 +578,16 @@ module Wardite
|
|
234
578
|
def fd_fdstat_get(store, args)
|
235
579
|
fd = args[0].value.to_i
|
236
580
|
fdstat_offset = args[1].value.to_i
|
237
|
-
if fd >=
|
581
|
+
if fd >= fd_count
|
238
582
|
return Wasi::EBADF
|
239
583
|
end
|
240
584
|
file = @fd_table[fd]
|
241
585
|
fdflags = 0
|
242
|
-
if file
|
586
|
+
if !file
|
587
|
+
return Wasi::EBADF
|
588
|
+
elsif file.is_a?(Wasi::PreopenedDir)
|
589
|
+
file = File.open(file.guest_path) # reopen directory
|
590
|
+
elsif file.is_a?(IO) && !file.is_a?(File)
|
243
591
|
fdflags |= Wasi::FD_APPEND
|
244
592
|
else
|
245
593
|
if (Fcntl::O_APPEND & file.fcntl(Fcntl::F_GETFL, 0)) != 0
|
@@ -282,10 +630,14 @@ module Wardite
|
|
282
630
|
def fd_filestat_get(store, args)
|
283
631
|
fd = args[0].value.to_i
|
284
632
|
filestat_offset = args[1].value.to_i
|
285
|
-
if fd >=
|
633
|
+
if fd >= fd_count
|
286
634
|
return Wasi::EBADF
|
287
635
|
end
|
288
636
|
file = @fd_table[fd]
|
637
|
+
if !file || file.is_a?(Wasi::PreopenedDir)
|
638
|
+
return Wasi::EBADF
|
639
|
+
end
|
640
|
+
|
289
641
|
stat = file.stat #: File::Stat
|
290
642
|
memory = store.memories[0]
|
291
643
|
binformat = [stat.dev, stat.ino, Wasi.to_ftype(stat.ftype), stat.nlink, stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i].pack("Q8")
|
@@ -293,6 +645,94 @@ module Wardite
|
|
293
645
|
0
|
294
646
|
end
|
295
647
|
|
648
|
+
# @rbs store: Store
|
649
|
+
# @rbs args: Array[wasmValue]
|
650
|
+
# @rbs return: Object
|
651
|
+
def fd_readdir(store, args)
|
652
|
+
fd = args[0].value.to_i
|
653
|
+
buf = args[1].value.to_i
|
654
|
+
buf_len = args[2].value.to_i
|
655
|
+
cookie = args[3].value.to_i
|
656
|
+
result_buf_used = args[4].value.to_i
|
657
|
+
|
658
|
+
if buf_len < 24 # when smaller than Dirent header size: Q! Q! I! I!
|
659
|
+
return Wasi::EINVAL
|
660
|
+
end
|
661
|
+
|
662
|
+
memory = store.memories[0]
|
663
|
+
|
664
|
+
if dirent_cache[fd]&.eof
|
665
|
+
dirent_cache.delete(fd)
|
666
|
+
end
|
667
|
+
dir = @fd_table[fd]
|
668
|
+
if dir.is_a?(Wasi::PreopenedDir) || (dir.is_a?(File) && dir.stat.ftype == "directory")
|
669
|
+
dirent_cache[fd] ||= Wasi::DirentCache.new(dir.path)
|
670
|
+
else
|
671
|
+
return Wasi::EBADF
|
672
|
+
end
|
673
|
+
|
674
|
+
dirent = dirent_cache[fd]
|
675
|
+
bindata, is_truncated = dirent.fetch_entries_binary(buf_len, cookie)
|
676
|
+
|
677
|
+
bufused = bindata.size
|
678
|
+
# bufused == buf_len means more dirents exist
|
679
|
+
if is_truncated
|
680
|
+
bufused = buf_len
|
681
|
+
memory.data[buf...(buf+buf_len)] = bindata + "\0" * (buf_len - bindata.size)
|
682
|
+
else
|
683
|
+
dirent.eof = true
|
684
|
+
memory.data[buf...(buf+bindata.size)] = bindata
|
685
|
+
end
|
686
|
+
|
687
|
+
memory.data[result_buf_used...(result_buf_used+4)] = [bufused].pack("I!")
|
688
|
+
0
|
689
|
+
end
|
690
|
+
|
691
|
+
# @rbs store: Store
|
692
|
+
# @rbs args: Array[wasmValue]
|
693
|
+
def fd_tell(store, args)
|
694
|
+
fd = args[0].value.to_i
|
695
|
+
result_buf = args[1].value.to_i
|
696
|
+
if fd >= fd_count
|
697
|
+
return Wasi::EBADF
|
698
|
+
end
|
699
|
+
file = @fd_table[fd]
|
700
|
+
if !file || file.is_a?(Wasi::PreopenedDir)
|
701
|
+
return Wasi::EBADF
|
702
|
+
end
|
703
|
+
|
704
|
+
memory = store.memories[0]
|
705
|
+
memory.data[result_buf...(result_buf+4)] = [file.tell].pack("I!")
|
706
|
+
0
|
707
|
+
rescue Errno::EBADF
|
708
|
+
return Wasi::EBADF
|
709
|
+
end
|
710
|
+
|
711
|
+
# @rbs store: Store
|
712
|
+
# @rbs args: Array[wasmValue]
|
713
|
+
# @rbs return: Object
|
714
|
+
def fd_close(store, args)
|
715
|
+
fd = args[0].value.to_i
|
716
|
+
if fd >= fd_count
|
717
|
+
return Wasi::EBADF
|
718
|
+
end
|
719
|
+
file = @fd_table[fd]
|
720
|
+
if !file
|
721
|
+
return Wasi::EBADF
|
722
|
+
end
|
723
|
+
if file.is_a?(Wasi::PreopenedDir)
|
724
|
+
# do nothing for preopened dir...?
|
725
|
+
$stderr.puts "close preopened dir?: #{file.guest_path}"
|
726
|
+
@fd_table.delete(fd)
|
727
|
+
return 0
|
728
|
+
end
|
729
|
+
file.close
|
730
|
+
@fd_table.delete(fd)
|
731
|
+
0
|
732
|
+
rescue Errno::EBADF
|
733
|
+
return Wasi::EBADF
|
734
|
+
end
|
735
|
+
|
296
736
|
# @rbs store: Store
|
297
737
|
# @rbs args: Array[wasmValue]
|
298
738
|
# @rbs return: Object
|
data/lib/wardite.rb
CHANGED
@@ -38,7 +38,7 @@ module Wardite
|
|
38
38
|
|
39
39
|
attr_reader :import_object #: Hash[Symbol, wasmModule]
|
40
40
|
|
41
|
-
attr_accessor :wasi #: WasiSnapshotPreview1?
|
41
|
+
attr_accessor :wasi #: ::Wardite::WasiSnapshotPreview1?
|
42
42
|
|
43
43
|
# @rbs import_object: Hash[Symbol, wasmModuleSrc]
|
44
44
|
# @rbs &blk: (Instance) -> void
|
@@ -354,6 +354,7 @@ module Wardite
|
|
354
354
|
# @rbs external_function: ExternalFunction
|
355
355
|
# @rbs return: wasmValue|nil
|
356
356
|
def invoke_external(external_function)
|
357
|
+
$stderr.puts "[trace] call external function: #{external_function.name}" if ENV["WARDITE_TRACE"]
|
357
358
|
local_start = stack.size - external_function.callsig.size
|
358
359
|
args = stack[local_start..]
|
359
360
|
if !args
|
@@ -803,6 +804,12 @@ module Wardite
|
|
803
804
|
def respond_to? name
|
804
805
|
callable?(name) || super
|
805
806
|
end
|
807
|
+
|
808
|
+
# @rbs args: Array[Object]
|
809
|
+
# @rbs return: Object?
|
810
|
+
def _start(*args)
|
811
|
+
call(:_start, args)
|
812
|
+
end
|
806
813
|
end
|
807
814
|
|
808
815
|
class Type
|