Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement basic support for JSaddle special device #9

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 93 additions & 9 deletions fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ if(typeof exports !== 'undefined'){
var bfs = BrowserFS.BFSRequire('fs');
var bfs_utils = BrowserFS.BFSRequire('bfs_utils');

// Sub-worker, collecting incoming messages from JS side jsaddle
var jsaddleListener = new Worker('jsaddle_listener.js');

// SharedArrayBuffer to communicate between wasm and jsaddleListener workers
// Just for incoming messages/SYS_read
// The write can happen via non-blocking postMessage
//
// The wasm worker is supposed to read one incoming message at a time
// So this buffer will contain only one message at a time.

// First UInt (32 bits), indicate buffer data size
// Followed by data
var jsaddleMsgSharedBuf = new SharedArrayBuffer(1024*1024);
var jsaddleMsgBufArray = new Uint8Array(jsaddleMsgSharedBuf);
var jsaddleMsgBufArray32 = new Uint32Array(jsaddleMsgSharedBuf);

var JSADDLE_INOUT_FD = 4;
var JSADDLE_INOUT_DEV = "/dev/jsaddle_inout";

// Certain directories are required by POSIX (and musl). In case there is an
// in memory filesystem under root we need to take care to create these manually.
Expand Down Expand Up @@ -96,28 +114,79 @@ function catchApiError(f) {
}

var fs = {

initFsJSaddle: function (jsaddleChannelPort) {
jsaddleListener.postMessage(
{type: 'init'
, jsaddleMsgBufArray32: jsaddleMsgBufArray32
, jsaddleMsgBufArray: jsaddleMsgBufArray
, jsaddleChannelPort: jsaddleChannelPort}
, [jsaddleChannelPort]);
},

openat: function (dirfd, pathname, flags, mode) {
if (dirfd !== AT_FDCWD) {
utils.warn('openat: TODO: dirfd other than AT_FDCWD, ignoring');
if (pathname == JSADDLE_INOUT_DEV) {
// FIXME set a valid value here
JSADDLE_INOUT_FD = 4;
return JSADDLE_INOUT_FD;
} else {
if (dirfd !== AT_FDCWD) {
utils.warn('openat: TODO: dirfd other than AT_FDCWD, ignoring');
}
return catchApiError(() => bfs.openSync(pathname, flagsToString(flags), mode));
}
return catchApiError(() => bfs.openSync(pathname, flagsToString(flags), mode));
},

creat: function (pathname, mode) {
return this.openat(AT_FDCWD, pathname, O_CREAT|O_WRONLY|O_TRUNC, mode);
},

read: function (fd, buf, offset, count) {
var b = bfs_utils.uint8Array2Buffer(buf);
return catchApiError(() => bfs.readSync(fd, b, offset, count, null));
if (fd === JSADDLE_INOUT_FD) {
var bytes_read = 0;
var bytes_available = jsaddleMsgBufArray32[0];
if (bytes_available > 0) {
if (bytes_available > count) {
var i = count;
bytes_read = i;
while (i--) buf[offset + i] = jsaddleMsgBufArray[i + 4];

// Shift the remaining contents, and set size
var target = 4;
var start = count + 4 + 1;
var len = bytes_available - count;
jsaddleMsgBufArray.copyWithin(target, start, len);
jsaddleMsgBufArray32[0] = len;
} else {
var i = bytes_available;
bytes_read = bytes_available;
while (i--) buf[offset + i] = jsaddleMsgBufArray[i + 4];
//buf[offset + bytes_available + 1] = 0;

// Set remaining bytes to 0
jsaddleMsgBufArray32[0] = 0;
// Tell jsaddle listener that buffer has been read
jsaddleListener.postMessage({type: 'read'});
}
}
return bytes_read;
} else {
var b = bfs_utils.uint8Array2Buffer(buf);
return catchApiError(() => bfs.readSync(fd, b, offset, count, null));
}
},

write: function (fd, buf, offset, count) {
// stdout is handled specially here, we may have a more robust solution
// in the future that does not assume stdout is connected to console
if (fd === 1) {
// stdout and stderr are handled specially here, we may have a more robust solution
// in the future that does not assume they are connected to console
if ((fd === 1) || (fd === 2)) {
utils.stdout__write(utils.bufToStr(buf, offset, offset + count));
return count;
} else if (fd === JSADDLE_INOUT_FD) {
var a = new Uint8Array(buf.slice(offset, offset + count));
var b = a.buffer;
jsaddleListener.postMessage({type: 'write', buf: b}, [b]);
return count;
} else {
var b = bfs_utils.uint8Array2Buffer(buf);
return catchApiError(() => bfs.writeSync(fd, b, offset, count, null));
Expand Down Expand Up @@ -198,9 +267,24 @@ var fs = {

ftruncate: function (fd, length) {
return catchApiError(() => bfs.ftruncate(fd, length));
},

fstat64: function (fd, statbuf_) {
if (fd === JSADDLE_INOUT_FD) {
// Set device type in st_mode field
// S_IFCHR 0020000 character device (octal)
// sizeof (st_dev) 8
// sizeof (st_ino) 8
// sizeof (st_mode) 4
st_mode_ptr = (statbuf_ + 16) / 4;
heap_uint32[st_mode_ptr] = 8192;
return 0;
} else {
throw "SYS_fstat64 NYI";
}
}
};

if(typeof exports !== 'undefined'){
if (typeof exports !== 'undefined'){
module.exports = fs;
}
Loading