Skip to content

Commit baf621f

Browse files
committed
Use linux style pwrite
1 parent 04bdcda commit baf621f

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

example/wasi_httpbin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import pywasm
23
import socket
34

@@ -16,6 +17,7 @@
1617
wasi = pywasm.wasi.Preview1(['wasi_httpbin.wasm'], {}, {})
1718
wasi.fd.append(pywasm.wasi.Preview1.File(
1819
host_fd=client_socket.fileno(),
20+
host_flag=os.O_RDWR,
1921
host_name=client_socket.getsockname(),
2022
host_status=pywasm.wasi.Preview1.FILE_STATUS_OPENED,
2123
pipe=None,

pywasm/wasi.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import dataclasses
2+
import fcntl
23
import os
34
import platform
45
import pywasm.core
@@ -395,6 +396,7 @@ class Preview1:
395396
@dataclasses.dataclass
396397
class File:
397398
host_fd: int
399+
host_flag: int
398400
host_name: str
399401
host_status: int
400402
pipe: typing.Optional[typing.BinaryIO]
@@ -414,6 +416,7 @@ def __init__(self, args: typing.List[str], dirs: typing.Dict[str, str], envs: ty
414416
self.fd: typing.List[Preview1.File] = []
415417
self.fd.append(self.File(
416418
host_fd=sys.stdin.fileno(),
419+
host_flag=0,
417420
host_name=sys.stdin.name,
418421
host_status=self.FILE_STATUS_OPENED,
419422
pipe=None,
@@ -427,6 +430,7 @@ def __init__(self, args: typing.List[str], dirs: typing.Dict[str, str], envs: ty
427430
))
428431
self.fd.append(self.File(
429432
host_fd=sys.stdout.fileno(),
433+
host_flag=0,
430434
host_name=sys.stdout.name,
431435
host_status=self.FILE_STATUS_OPENED,
432436
pipe=None,
@@ -440,6 +444,7 @@ def __init__(self, args: typing.List[str], dirs: typing.Dict[str, str], envs: ty
440444
))
441445
self.fd.append(self.File(
442446
host_fd=sys.stderr.fileno(),
447+
host_flag=0,
443448
host_name=sys.stderr.name,
444449
host_status=self.FILE_STATUS_OPENED,
445450
pipe=None,
@@ -456,6 +461,7 @@ def __init__(self, args: typing.List[str], dirs: typing.Dict[str, str], envs: ty
456461
v = os.path.abspath(os.path.normpath(v))
457462
self.fd.append(self.File(
458463
host_fd=os.open(v, os.O_RDONLY | os.O_DIRECTORY),
464+
host_flag=os.O_RDONLY | os.O_DIRECTORY,
459465
host_name=v,
460466
host_status=self.FILE_STATUS_OPENED,
461467
pipe=None,
@@ -652,12 +658,17 @@ def fd_fdstat_set_flags(self, _: pywasm.core.Machine, args: typing.List[int]) ->
652658
if file.wasm_flag ^ args[1] | fyes != fyes:
653659
# Only support changing the NONBLOCK or APPEND flags.
654660
return [self.ERRNO_INVAL]
661+
file.host_flag &= ~os.O_APPEND
662+
file.host_flag &= ~os.O_NONBLOCK
655663
file.wasm_flag &= ~self.FDFLAGS_APPEND
656664
file.wasm_flag &= ~self.FDFLAGS_NONBLOCK
657665
if args[1] & self.FDFLAGS_APPEND:
666+
file.host_flag |= os.O_APPEND
658667
file.wasm_flag |= self.FDFLAGS_APPEND
659668
if args[1] & self.FDFLAGS_NONBLOCK:
669+
file.host_flag |= os.O_NONBLOCK
660670
file.wasm_flag |= self.FDFLAGS_NONBLOCK
671+
fcntl.fcntl(file.host_fd, fcntl.F_SETFL, file.host_flag)
661672
return [self.ERRNO_SUCCESS]
662673

663674
def fd_fdstat_set_rights(self, _: pywasm.core.Machine, args: typing.List[int]) -> typing.List[int]:
@@ -871,6 +882,7 @@ def fd_renumber(self, _: pywasm.core.Machine, args: typing.List[int]) -> typing.
871882
if dest.wasm_type != self.FILETYPE_CHARACTER_DEVICE:
872883
os.close(dest.host_fd)
873884
dest.host_fd = stem.host_fd
885+
dest.host_flag = stem.host_flag
874886
dest.host_name = stem.host_name
875887
dest.host_status = stem.host_status
876888
dest.pipe = stem.pipe
@@ -951,8 +963,6 @@ def fd_write(self, m: pywasm.core.Machine, args: typing.List[int]) -> typing.Lis
951963
elem = mems.get(elem_ptr, elem_len)
952964
iovs_ptr += 8
953965
data.extend(elem)
954-
if file.wasm_flag & self.FDFLAGS_APPEND:
955-
os.lseek(file.host_fd, 0, os.SEEK_END)
956966
size = [
957967
lambda: os.write(file.host_fd, data),
958968
lambda: file.pipe.write(data),
@@ -1171,6 +1181,8 @@ def path_open(self, m: pywasm.core.Machine, args: typing.List[int]) -> typing.Li
11711181
flag |= os.O_WRONLY
11721182
if args[5] & self.RIGHTS_FD_READ + self.RIGHTS_FD_WRITE == self.RIGHTS_FD_READ + self.RIGHTS_FD_WRITE:
11731183
flag |= os.O_RDWR
1184+
if args[7] & self.FDFLAGS_APPEND:
1185+
flag |= os.O_APPEND
11741186
wasm_fd = len(self.fd)
11751187
try:
11761188
host_fd = os.open(name, flag, 0o644, dir_fd=self.fd[args[0]].host_fd)
@@ -1217,6 +1229,7 @@ def path_open(self, m: pywasm.core.Machine, args: typing.List[int]) -> typing.Li
12171229
rights_root &= ~void
12181230
self.fd.append(Preview1.File(
12191231
host_fd=host_fd,
1232+
host_flag=flag,
12201233
host_name=host_name,
12211234
host_status=self.FILE_STATUS_OPENED,
12221235
pipe=None,

test/wasi.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ def cd(dst: str) -> typing.Generator[None, typing.Any, None]:
3434
case.extend(sorted(glob.glob('res/wasi-testsuite/tests/c/testsuite/*.wasm')))
3535
case.extend(sorted(glob.glob('res/wasi-testsuite/tests/rust/testsuite/*.wasm')))
3636
skip = [
37+
# POSIX requires that opening a file with the O_APPEND flag should have no affect on the location at which pwrite()
38+
# writes data. However, on Linux, if a file is opened with O_APPEND, pwrite() appends data to the end of the file,
39+
# regardless of the value of offset.
40+
#
41+
# See https://linux.die.net/man/2/pwrite.
42+
# See https://github.com/WebAssembly/wasi-testsuite/issues/111
43+
'res/wasi-testsuite/tests/c/testsuite/pwrite-with-append.wasm'
3744
]
3845
for wasm_path in case:
3946
if wasm_path in skip:

0 commit comments

Comments
 (0)