From a7ab34ebbce60f2af159f9010a2e3629756af3d1 Mon Sep 17 00:00:00 2001 From: human Date: Thu, 7 Jan 2021 16:31:52 +0200 Subject: fix truncating in defineFile() - in the C part: enable FUSE_CAP_ATOMIC_O_TRUNC so that open() will get called with O_TRUNC in flags instead of truncate() being called separately - this also prevents truncate() from calling setData() with an empty string when a file is opened with O_TRUNC - in defineFile()->open(): if O_TRUNC is used, don't call getData() but start with an empty file as if it had just been truncated - in defineFile()->write()/truncate(): correct buffer resizing/copying --- extension/background.js | 22 ++++++++++++++++------ fs/tabfs.c | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/extension/background.js b/extension/background.js index 179a2b8..127f4f9 100644 --- a/extension/background.js +++ b/extension/background.js @@ -19,6 +19,9 @@ const unix = { S_IFREG: 0100000, // regular S_IFLNK: 0120000, // symbolic link S_IFSOCK: 0140000, // socket + + // Open flags + O_TRUNC: 01000, } class UnixError extends Error { @@ -110,6 +113,7 @@ const Cache = { return handle; }, getObjectForHandle(handle) { return this.store[handle]; }, + setObjectForHandle(handle, object) { this.store[handle] = object; }, removeObjectForHandle(handle) { delete this.store[handle]; } }; function toUtf8Array(stringOrArray) { @@ -141,7 +145,10 @@ const defineFile = (getData, setData) => ({ // We call getData() once when the file is opened, then cache that // data for all subsequent reads from that application. - async open({path}) { return { fh: Cache.storeObject(toUtf8Array(await getData(path))) }; }, + async open({path, flags}) { + const data = !(flags & unix.O_TRUNC) ? await getData(path) : ""; + return { fh: Cache.storeObject(toUtf8Array(data)) }; + }, async read({path, fh, size, offset}) { return { buf: String.fromCharCode(...Cache.getObjectForHandle(fh).slice(offset, offset + size)) } }, @@ -150,9 +157,11 @@ const defineFile = (getData, setData) => ({ const bufarr = stringToUtf8Array(buf); if (offset + bufarr.length > arr.length) { const newArr = new Uint8Array(offset + bufarr.length); - newArr.set(arr); arr = newArr; + newArr.set(arr.slice(0, Math.min(offset, arr.length))); + arr = newArr; + Cache.setObjectForHandle(fh, arr); } - for (let i = 0; i < bufarr.length; i++) { arr[offset + i] = bufarr[i]; } + arr.set(bufarr, offset); // I guess caller should override write() if they want to actually // patch and not just re-set the whole string (for example, // if they want to hot-reload just one function the user modified) @@ -165,11 +174,12 @@ const defineFile = (getData, setData) => ({ // (but `echo hi > foo.txt`, the main thing I care about, uses // O_TRUNC which thankfully doesn't do that) let arr = toUtf8Array(await getData(path)); - if (size > arr.length) { + if (size !== arr.length) { const newArr = new Uint8Array(size); - newArr.set(arr); arr = newArr; + newArr.set(arr.slice(0, Math.min(size, arr.length))); + arr = newArr; } - await setData(path, utf8ArrayToString(arr.slice(0, size))); return {}; + await setData(path, utf8ArrayToString(arr)); return {}; } }); diff --git a/fs/tabfs.c b/fs/tabfs.c index 8c28dab..0eab91c 100644 --- a/fs/tabfs.c +++ b/fs/tabfs.c @@ -423,6 +423,20 @@ static int tabfs_create(const char *path, mode_t mode, struct fuse_file_info *fi return 0; } +#define want_capability(conn, flag) \ + do { \ + if (conn->capable & flag) { \ + conn->want |= flag; \ + } else { \ + eprintln("warning: " #flag " not supported"); \ + } \ + } while (0) + +static void *tabfs_init(struct fuse_conn_info *conn) { + want_capability(conn, FUSE_CAP_ATOMIC_O_TRUNC); + return NULL; +} + static const struct fuse_operations tabfs_oper = { .getattr = tabfs_getattr, .readlink = tabfs_readlink, @@ -441,6 +455,8 @@ static const struct fuse_operations tabfs_oper = { .mkdir = tabfs_mkdir, .create = tabfs_create, + + .init = tabfs_init, }; int main(int argc, char **argv) { -- cgit v1.2.3 From 8b0e106ebdce0020a3b7863061feb6a3eabe0c3f Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Tue, 12 Jan 2021 00:15:25 -0800 Subject: test: add test for #40 --- test/test.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test.c b/test/test.c index d16c724..aaff360 100644 --- a/test/test.c +++ b/test/test.c @@ -13,7 +13,7 @@ int file_contents_equal(char* path, char* contents) { // hehe: https://twitter.com/ianh_/status/1340450349065244675 setenv("path", path, 1); setenv("contents", contents, 1); - return system("[ \"$contents\" == \"$(cat \"$path\")\" ]") == 0; + return system("bash -c '[ \"$contents\" == \"$(cat \"$path\")\" ]'") == 0; } char* expand(char* phrase) { // expand path with wildcard @@ -77,7 +77,11 @@ int main() { assert(strcmp(hi, "hi") == 0); fclose(console); } - + + // try to shorten the URL (#40) + assert(system("echo about:blank > ../fs/mnt/tabs/last-focused/url.txt") == 0); + assert(file_contents_equal("../fs/mnt/tabs/last-focused/url.txt", "about:blank")); + assert(system("echo remove > ../fs/mnt/tabs/last-focused/control") == 0); } -- cgit v1.2.3