diff --git a/.circleci/config.yml b/.circleci/config.yml index a86492ca6aea7..fe281d58e84eb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -718,6 +718,7 @@ jobs: wasm2js3.test_memorygrowth_2 wasm2js2.test_pthread_proxying wasmfs.test_hello_world + wasmfs.test_pipe_select wasmfs.test_unistd_links* wasmfs.test_atexit_standalone wasmfs.test_emscripten_get_now diff --git a/src/lib/libpipefs.js b/src/lib/libpipefs.js index 7de0c8817f5f2..c99ffb7bc29b6 100644 --- a/src/lib/libpipefs.js +++ b/src/lib/libpipefs.js @@ -117,7 +117,16 @@ addToLibrary({ dup(stream) { stream.node.pipe.refcnt++; }, - ioctl(stream, request, varargs) { + ioctl(stream, request, argp) { + if (request == {{{ cDefs.FIONREAD }}}) { + var pipe = stream.node.pipe; + var currentLength = 0; + for (var bucket of pipe.buckets) { + currentLength += bucket.offset - bucket.roffset; + } + {{{ makeSetValue('argp', 0, 'currentLength', 'i32') }}}; + return 0; + } return {{{ cDefs.EINVAL }}}; }, fsync(stream) { diff --git a/system/lib/wasmfs/syscalls.cpp b/system/lib/wasmfs/syscalls.cpp index 664e757a5b645..b3f655b937127 100644 --- a/system/lib/wasmfs/syscalls.cpp +++ b/system/lib/wasmfs/syscalls.cpp @@ -1306,7 +1306,28 @@ int __syscall_ioctl(int fd, int request, ...) { if (!openFile) { return -EBADF; } - if (!isTTY(openFile->locked().getFile())) { + + va_list args; + va_start(args, request); + void* argp = va_arg(args, void*); + va_end(args); + + auto openHandle = openFile->locked(); + auto file = openHandle.getFile(); + + if (request == FIONREAD) { + off_t size = file->locked().getSize(); + if (size < 0) { + return (int)size; + } + if (file->isSeekable()) { + size -= openHandle.getPosition(); + } + *static_cast(argp) = static_cast(size); + return 0; + } + + if (!isTTY(file)) { return -ENOTTY; } // TODO: Full TTY support. For now this is limited, and matches the old FS. diff --git a/test/codesize/test_codesize_hello_dylink_all.json b/test/codesize/test_codesize_hello_dylink_all.json index e71cc8742f260..18cf6afca2277 100644 --- a/test/codesize/test_codesize_hello_dylink_all.json +++ b/test/codesize/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { - "a.out.js": 244260, + "a.out.js": 244350, "a.out.nodebug.wasm": 577664, - "total": 821924, + "total": 822014, "sent": [ "IMG_Init", "IMG_Load", diff --git a/test/core/test_pipe_select.c b/test/core/test_pipe_select.c index 54cfaa5417bfb..8a895bfde49af 100644 --- a/test/core/test_pipe_select.c +++ b/test/core/test_pipe_select.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -7,18 +8,34 @@ int pipe_a[2]; +int get_available(int fd) { + int avail = 0; + assert(ioctl(fd, FIONREAD, &avail) == 0); + printf("FIONREAD %d -> %d\n", fd, avail); + return avail; +} + int main() { fd_set readfds; const char *t = "test\n"; assert(pipe(pipe_a) == 0); + assert(get_available(pipe_a[0]) == 0); + assert(get_available(pipe_a[1]) == 0); + FD_ZERO(&readfds); FD_SET(pipe_a[0], &readfds); write(pipe_a[1], t, strlen(t)); assert(select(pipe_a[0] + 1, &readfds, NULL, NULL, NULL) == 1); assert(FD_ISSET(pipe_a[0], &readfds)); - close(pipe_a[0]); close(pipe_a[1]); + // Slightly strange behavior here that we can use FIONREAD + // on either the read or the write end of the pipe and get + // the same result, but this matches linux. + assert(get_available(pipe_a[0]) == strlen(t)); + assert(get_available(pipe_a[1]) == strlen(t)); + close(pipe_a[0]); + close(pipe_a[1]); return 0; }