From acbcbc1d97f0a808a645bb491447d842e029d4d8 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 5 Feb 2023 11:37:19 +0100 Subject: [PATCH] add javascript example --- example/provider/javascript/index.html | 22 +++- example/provider/javascript/js/filesystem.js | 104 ++++++++++++++++++ example/provider/javascript/js/startup.js | 33 +++++- .../javascript/js/static_filesystem.js | 41 ------- .../javascript/js/webfuse/basefilesystem.js | 36 ++++-- .../javascript/js/webfuse/messagereader.js | 1 - .../javascript/js/webfuse/messagewriter.js | 1 - .../javascript/js/webfuse/openflags.js | 28 +++++ .../provider/javascript/js/webfuse/webfuse.js | 20 ++-- example/provider/javascript/style.css | 28 +++++ 10 files changed, 244 insertions(+), 70 deletions(-) create mode 100644 example/provider/javascript/js/filesystem.js delete mode 100644 example/provider/javascript/js/static_filesystem.js create mode 100644 example/provider/javascript/js/webfuse/openflags.js create mode 100644 example/provider/javascript/style.css diff --git a/example/provider/javascript/index.html b/example/provider/javascript/index.html index 8570de9..588f949 100644 --- a/example/provider/javascript/index.html +++ b/example/provider/javascript/index.html @@ -3,15 +3,35 @@ Webfuse Example + -

Webfuse

+

Webfuse Example

+ +

+ This example provides a single file "README.md", which + contents can be altered below. +

+ +

Connection

+

+ + +

+ disconnected +

+ +

README.md

+

+

\ No newline at end of file diff --git a/example/provider/javascript/js/filesystem.js b/example/provider/javascript/js/filesystem.js new file mode 100644 index 0000000..d571d5c --- /dev/null +++ b/example/provider/javascript/js/filesystem.js @@ -0,0 +1,104 @@ + +import { BaseFileSystem, ERRNO, Mode, AccessMode, OpenFlags } from "./webfuse/webfuse.js" + +class FileSystem extends BaseFileSystem { + + constructor(tokenProvider, stateListener, files) { + super(); + + this.tokenProvider = tokenProvider; + this.stateListener = stateListener + this.files = new Map(); + for(const file of files) { + this.files.set("/" + file.name, file); + } + } + + access(path, mode) { + // we do not allow write or execute + if ((mode & AccessMode.W_OK) || (mode & AccessMode.X_OK)) { + return ERRNO.EACCES; + } + + if ((path = "/") || (this.files.has(path))) { + return 0; + } + + return ERRNO.ENOENT; + } + + getattr(path) { + if (path == "/") { + return { + nlink: 2, + mode: Mode.DIR | 0o555 + }; + } + else if (this.files.has(path)) { + const file = this.files.get(path); + const contents = file.contents(); + return { + nlink: 1, + mode: Mode.REG | 0o444, + size: contents.length + }; + } + + return ERRNO.ENOENT; + } + + readdir(path) { + if (path == "/") { + const list = []; + for(const file of this.files.values()) { + list.push(file.name); + } + return list; + } + + return ERRNO.ENOENT; + } + + open(path, flags) { + if (this.files.has(path)) { + const accessMode = flags & OpenFlags.ACCESS_MODE; + if (accessMode == OpenFlags.RDONLY) { + return [0, 0]; + } + else { + return [ERRNO.EPERM, 0]; + } + } + + return [ERRNO.ENOENT, 0]; + } + + read(path, size, offset, fd) { + if (this.files.has(path)) { + const file = this.files.get(path); + const contents = file.contents(); + if (offset < contents.length) { + const available = contents.length - offset; + const length = (size < available) ? size : available; + const data = contents.slice(offset, offset + length); + return data; + } + + return []; + } + else { + return ERRNO.EBADF; + } + } + + getcreds() { + const token = this.tokenProvider(); + return token; + } + + connectionstatechanged(state) { + this.stateListener(state); + } +} + +export { FileSystem } diff --git a/example/provider/javascript/js/startup.js b/example/provider/javascript/js/startup.js index 8189e5b..576224e 100644 --- a/example/provider/javascript/js/startup.js +++ b/example/provider/javascript/js/startup.js @@ -1,19 +1,40 @@ import { Webfuse } from "./webfuse/webfuse.js"; -import { StaticFileSystem } from "./static_filesystem.js"; +import { FileSystem } from "./filesystem.js"; + + +function encode(value) { + const encoder = new TextEncoder('utf-8'); + return encoder.encode(value); +} + +function get_contents() { + const contentTextArea = document.querySelector("#contents"); + const contents = contentTextArea.value; + return encode(contents); +} + +function get_token() { + const tokenTextfield = document.querySelector('#token'); + const token = tokenTextfield.value; + return token; +} + +function update_state(state) { + const stateTextField = document.querySelector("#state"); + stateTextField.textContent = (state == "connected") ? "connected" : "disconnected"; +} let webfuse = null; -const filesystem = new StaticFileSystem(new Map([ - ["/foo", "foo"], - ["/bar", "foo"] -])); +const filesystem = new FileSystem(get_token, update_state, [ + {name: "README.md", contents: get_contents } +]); function onConnectButtonClicked() { if (webfuse) { webfuse.close(); } const urlTextfield = document.querySelector('#url'); const url = urlTextfield.value; - console.log(url); webfuse = new Webfuse(url, filesystem); } diff --git a/example/provider/javascript/js/static_filesystem.js b/example/provider/javascript/js/static_filesystem.js deleted file mode 100644 index 02a81a5..0000000 --- a/example/provider/javascript/js/static_filesystem.js +++ /dev/null @@ -1,41 +0,0 @@ - -import { BaseFileSystem, ERRNO, Mode } from "./webfuse/webfuse.js" - -class StaticFileSystem extends BaseFileSystem { - - constructor(files) { - super(); - this.files = files; - } - - getattr(path) { - console.log("getattr", path); - - if (path == "/") { - return { - nlink: 2, - mode: Mode.DIR | 0o555 - }; - } - else if (this.files.has(path)) { - const contents = this.files.get(path); - return { - nlink: 1, - mode: Mode.REG | 0o444, - size: contents.length - } - } - - return ERRNO.ENOENT; - } - - readdir(path) { - if (path == "/") { - return ["foo", "bar"] - } - - return ERRNO.ENOENT; - } -} - -export { StaticFileSystem } diff --git a/example/provider/javascript/js/webfuse/basefilesystem.js b/example/provider/javascript/js/webfuse/basefilesystem.js index 1f987df..1a68d87 100644 --- a/example/provider/javascript/js/webfuse/basefilesystem.js +++ b/example/provider/javascript/js/webfuse/basefilesystem.js @@ -27,15 +27,19 @@ class BaseFileSystem { } chmod(path, mode) { - return ERRNO.ENOENT; + return ERRNO.EPERM; } chown(path, uid, gid) { - return ERRNO.ENOENT; + return ERRNO.EPERM; } truncate(path, size, fd) { - return ERRNO.ENOENT; + return ERRNO.EPERM; + } + + fsync(path, isDataSync, fd) { + return 0; } open(path, flags) { @@ -43,31 +47,31 @@ class BaseFileSystem { } mknod(path, mode, rdev) { - return ERRNO.ENOENT; + return ERRNO.EPERM; } create(path, mode) { - return [ERNNO.ENOEND, 0]; + return [ERRNO.EPERM, 0]; } release(path, fd) { - return ERRNO.ENOENT; + return 0; } unlink(path) { - return ERRNO.ENOENT; + return ERRNO.EPERM; } read(path, size, offset, fd) { - return ERRNO.ENOENT; + return ERRNO.EBADF; } write(path, data, offset, fd) { - return ERRNO.ENOENT; + return ERRNO.EBADF; } mkdir(path, mode) { - return ERRNO.ENOENT; + return ERRNO.EPERM; } readdir(path) { @@ -75,16 +79,24 @@ class BaseFileSystem { } rmdir(path) { - return ERRNO.ENOENT; + return ERRNO.EPERM; } statfs(path) { - return ERRNO.ENOENT; + return ERRNO.ENOSYS; + } + + utimens(path, atime, mtime) { + return ERRNO.ENOSYS; } getcreds() { return ""; } + + connectionstatechanged(state) { + // pass + } } export { BaseFileSystem } diff --git a/example/provider/javascript/js/webfuse/messagereader.js b/example/provider/javascript/js/webfuse/messagereader.js index f58958a..737564a 100644 --- a/example/provider/javascript/js/webfuse/messagereader.js +++ b/example/provider/javascript/js/webfuse/messagereader.js @@ -1,7 +1,6 @@ class MessageReader { constructor(data) { - // console.log(new Uint8Array(data)); this.raw = data; this.data = new DataView(data); this.pos = 0; diff --git a/example/provider/javascript/js/webfuse/messagewriter.js b/example/provider/javascript/js/webfuse/messagewriter.js index ec1f504..3c5a9f9 100644 --- a/example/provider/javascript/js/webfuse/messagewriter.js +++ b/example/provider/javascript/js/webfuse/messagewriter.js @@ -67,7 +67,6 @@ class MessageWriter { } get_data() { - // console.log(this.data) return new Uint8Array(this.data); } diff --git a/example/provider/javascript/js/webfuse/openflags.js b/example/provider/javascript/js/webfuse/openflags.js new file mode 100644 index 0000000..b63badf --- /dev/null +++ b/example/provider/javascript/js/webfuse/openflags.js @@ -0,0 +1,28 @@ + +const OpenFlags = { + ACCESS_MODE: 0x03, + RDONLY : 0o00, + WRONLY : 0o01, + RDWR : 0o02, + + APPEND : 0o00002000, + ASYNC : 0o00020000, + CLOEXEC : 0o02000000, + CREAT : 0o00000100, + DIRECT : 0o00040000, + DIRECTORY : 0o00200000, + DSYNC : 0o00010000, + EXCL : 0o00000200, + LARGEFILE : 0o00100000, + NOATIME : 0o01000000, + NOCTTY : 0o00000400, + NOFOLLOW : 0o00400000, + NONBLOCK : 0o00004000, + NDELAY : 0o00004000, + PATH : 0o10000000, + SYNC : 0o04010000, + TMPFILE : 0o20200000, + TRUNC : 0o00001000 +}; + +export { OpenFlags } \ No newline at end of file diff --git a/example/provider/javascript/js/webfuse/webfuse.js b/example/provider/javascript/js/webfuse/webfuse.js index 1c53751..c8e49de 100644 --- a/example/provider/javascript/js/webfuse/webfuse.js +++ b/example/provider/javascript/js/webfuse/webfuse.js @@ -2,6 +2,7 @@ import { MessageWriter } from "./messagewriter.js"; import { MessageReader } from "./messagereader.js"; import { ERRNO } from "./errno.js"; import { AccessMode } from "./accessmode.js"; +import { OpenFlags } from "./openflags.js"; import { BaseFileSystem } from "./basefilesystem.js"; @@ -20,7 +21,7 @@ const Mode = { function fs_access(reader, writer, filesystem) { const path = reader.read_str(); const mode = reader.read_u8(); - result = filesystem.access(path, mode); + const result = filesystem.access(path, mode); writer.write_i32(result); } @@ -156,7 +157,7 @@ function fs_read(reader, writer, filesystem) { const fd = reader.read_u64(); const result = filesystem.read(path, size, offset, fd); if (typeof(result) != "number") { - writer.write_i32(0); + writer.write_i32(result.length); writer.write_bytes(result); } else { @@ -259,10 +260,9 @@ const commands = new Map([ class Webfuse { constructor(url, filesystem) { - console.log('webfuse: ctor') - this.ws = new WebSocket(url, ["webfuse2"]); this.ws.binaryType = 'arraybuffer'; + this.ws.addEventListener('open', (event) => this.on_connected(event)); this.ws.addEventListener('close', (event) => this.on_closed(event)); this.ws.addEventListener('error', (event) => this.on_error(event)); this.ws.addEventListener('message', (event) => this.on_message(event)); @@ -285,21 +285,25 @@ class Webfuse { command(reader, writer, this.filesystem); } else { - console.error(`unknow message type: ${message_type}`); + console.warn(`unknow message type: ${message_type}`); } this.ws.send(writer.get_data()); } + on_connected(event) { + this.filesystem.connectionstatechanged("connected"); + } + on_error(event) { - console.log('error', event); + console.info("connection error"); this.ws.close(); } on_closed(event) { - console.log('closed', event); + this.filesystem.connectionstatechanged("closed"); } } -export { Webfuse, BaseFileSystem, ERRNO, Mode, AccessMode } +export { Webfuse, BaseFileSystem, ERRNO, Mode, AccessMode, OpenFlags } diff --git a/example/provider/javascript/style.css b/example/provider/javascript/style.css new file mode 100644 index 0000000..52ee0d5 --- /dev/null +++ b/example/provider/javascript/style.css @@ -0,0 +1,28 @@ +html, body { + background-color: #c0c0c0; +} + +h1 { + background-color: black; + color: white; +} + +label { + display: inline-block; + width: 150px; +} + +input { + width: 150px; +} + +#stats { + display: inline-block; + text-align: right; + width: 150px; +} + +textarea { + width: 300px; + height: 300px; +} \ No newline at end of file