summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2021-04-06 13:48:48 -0700
committerOmar Rizwan <omar@omar.website>2021-04-06 13:48:48 -0700
commitb948c235b83e43441faeed257cfdffa2008326d9 (patch)
treed98da8af43b0a5a41bf04fb968a705b91fa410aa
parent8fbfa9a7c96b1de1e3e8416cb0bfc2b27c0b235d (diff)
downloadTabFS-b948c235b83e43441faeed257cfdffa2008326d9.tar.gz
TabFS-b948c235b83e43441faeed257cfdffa2008326d9.zip
fs,extension: Make truncate work on cached file content.
We now remember the path of each cached file, so when someone truncates that path, we can truncate all open instances of it in cache. Important when someone pipes to stomp a file / opens with O_TRUNC (which FUSE disaggregates into an open() and then a truncate() call). Gets rid of the need for FUSE_CAP_ATOMIC_O_TRUNC, which never worked on macOS anyway. Fixes #40.
-rw-r--r--extension/background.js30
-rw-r--r--fs/tabfs.c16
-rw-r--r--test/test.c6
3 files changed, 19 insertions, 33 deletions
diff --git a/extension/background.js b/extension/background.js
index 2a59630..6f4d108 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -17,9 +17,6 @@ const unix = {
S_IFREG: 0100000, // regular
S_IFLNK: 0120000, // symbolic link
S_IFSOCK: 0140000, // socket
-
- // Open flags
- O_TRUNC: 01000,
}
class UnixError extends Error {
constructor(error) { super(); this.name = "UnixError"; this.error = error; }
@@ -74,14 +71,21 @@ const defineFile = (function() {
// whole new conversation with the browser and regenerating the
// content -- important for taking a screenshot, for instance)
store: {}, nextHandle: 0,
- storeObject(object) {
+ storeObject(path, object) {
const handle = ++this.nextHandle;
- this.store[handle] = object;
+ this.store[handle] = {path, object};
return handle;
},
- getObjectForHandle(handle) { return this.store[handle]; },
- setObjectForHandle(handle, object) { this.store[handle] = object; },
- removeObjectForHandle(handle) { delete this.store[handle]; }
+ getObjectForHandle(handle) { return this.store[handle].object; },
+ setObjectForHandle(handle, object) { this.store[handle].object = object; },
+ removeObjectForHandle(handle) { delete this.store[handle]; },
+ setObjectForPath(path, object) {
+ for (let storedObject of Object.values(this.store)) {
+ if (storedObject.path === path) {
+ storedObject.object = object;
+ }
+ }
+ }
};
function toUtf8Array(stringOrArray) {
@@ -110,11 +114,11 @@ const defineFile = (function() {
// We call getData() once when the file is opened, then cache that
// data for all subsequent reads from that application.
async open(req) {
- const data = !(req.flags & unix.O_TRUNC) ? await getData(req) : "";
- return { fh: Cache.storeObject(toUtf8Array(data)) };
+ const data = await getData(req);
+ return { fh: Cache.storeObject(req.path, toUtf8Array(data)) };
},
async read({fh, size, offset}) {
- return { buf: String.fromCharCode(...Cache.getObjectForHandle(fh).slice(offset, offset + size)) }
+ return { buf: String.fromCharCode(...Cache.getObjectForHandle(fh).slice(offset, offset + size)) };
},
async write(req) {
const {fh, offset, buf} = req;
@@ -135,15 +139,13 @@ const defineFile = (function() {
async release({fh}) { Cache.removeObjectForHandle(fh); return {}; },
async truncate(req) {
- // TODO: weird case if they truncate while the file is open
- // (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(req));
if (req.size !== arr.length) {
const newArr = new Uint8Array(req.size);
newArr.set(arr.slice(0, Math.min(req.size, arr.length)));
arr = newArr;
}
+ Cache.setObjectForPath(req.path, arr);
await setData(req, utf8ArrayToString(arr)); return {};
}
});
diff --git a/fs/tabfs.c b/fs/tabfs.c
index a7936eb..c74becf 100644
--- a/fs/tabfs.c
+++ b/fs/tabfs.c
@@ -423,20 +423,6 @@ static int tabfs_mknod(const char *path, mode_t mode, dev_t rdev) {
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,
@@ -455,8 +441,6 @@ static const struct fuse_operations tabfs_oper = {
.mkdir = tabfs_mkdir,
.mknod = tabfs_mknod,
-
- .init = tabfs_init,
};
int main(int argc, char **argv) {
diff --git a/test/test.c b/test/test.c
index 4ad3dd3..b463f89 100644
--- a/test/test.c
+++ b/test/test.c
@@ -79,9 +79,9 @@ int main() {
fclose(result);
}
- // 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")); */
+ // try to truncate & stomp 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);
}