mirror of
https://github.com/osnr/TabFS.git
synced 2024-06-17 05:05:00 +02:00
open/read work on url file!!!
Use string keys for opcodes to simplify the code.
This commit is contained in:
parent
b6f46e166d
commit
528467a55b
|
@ -1,14 +1,5 @@
|
||||||
const ws = new WebSocket("ws://localhost:8888");
|
const ws = new WebSocket("ws://localhost:8888");
|
||||||
|
|
||||||
const ops = {
|
|
||||||
NONE: 0,
|
|
||||||
|
|
||||||
GETATTR: 1,
|
|
||||||
OPEN: 2,
|
|
||||||
READDIR: 3,
|
|
||||||
READ: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
const unix = {
|
const unix = {
|
||||||
EPERM: 1,
|
EPERM: 1,
|
||||||
ENOENT: 2,
|
ENOENT: 2,
|
||||||
|
@ -34,10 +25,51 @@ function UnixError(error) {
|
||||||
}
|
}
|
||||||
UnixError.prototype = Error.prototype;
|
UnixError.prototype = Error.prototype;
|
||||||
|
|
||||||
|
function getTab(id) {
|
||||||
|
return new Promise((resolve, reject) => chrome.tabs.get(id, resolve));
|
||||||
|
}
|
||||||
function queryTabs() {
|
function queryTabs() {
|
||||||
return new Promise((resolve, reject) => chrome.tabs.query({}, resolve));
|
return new Promise((resolve, reject) => chrome.tabs.query({}, resolve));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendDebuggerCommand(tab, method, commandParams) {
|
||||||
|
return new Promise(resolve => chrome.debugger.sendCommand({tabId: id}, method, commandParams, resolve));
|
||||||
|
}
|
||||||
|
|
||||||
|
const fhManager = (function() {
|
||||||
|
const handles = {};
|
||||||
|
let nextFh = 0;
|
||||||
|
return {
|
||||||
|
allocate(obj) { // -> fh
|
||||||
|
const fh = nextFh++;
|
||||||
|
handles[fh] = obj;
|
||||||
|
return fh;
|
||||||
|
},
|
||||||
|
ref(fh) {
|
||||||
|
if (!handles[fh]) throw new UnixError(unix.EIO);
|
||||||
|
return handles[fh];
|
||||||
|
},
|
||||||
|
free(fh) {
|
||||||
|
delete handles[fh];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// tabs/by-id/ID/title
|
||||||
|
// tabs/by-id/ID/url
|
||||||
|
// tabs/by-id/ID/console
|
||||||
|
// tabs/by-id/ID/mem (?)
|
||||||
|
// tabs/by-id/ID/cpu (?)
|
||||||
|
// tabs/by-id/ID/screenshot.png
|
||||||
|
// tabs/by-id/ID/printed.pdf
|
||||||
|
// tabs/by-id/ID/control
|
||||||
|
// tabs/by-id/ID/sources/
|
||||||
|
|
||||||
|
function pathComponent(path, i) {
|
||||||
|
const components = path.split('/');
|
||||||
|
return components[i >= 0 ? i : components.length + i];
|
||||||
|
}
|
||||||
|
|
||||||
const router = {
|
const router = {
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"by-id": {
|
"by-id": {
|
||||||
|
@ -47,13 +79,34 @@ const router = {
|
||||||
},
|
},
|
||||||
|
|
||||||
"*": {
|
"*": {
|
||||||
|
"url": {
|
||||||
async getattr() {
|
async getattr() {
|
||||||
return {
|
return {
|
||||||
st_mode: unix.S_IFREG | 0444,
|
st_mode: unix.S_IFREG | 0444,
|
||||||
st_nlink: 1,
|
st_nlink: 1,
|
||||||
st_size: 10 // FIXME
|
st_size: 100 // FIXME
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
async open(path) {
|
||||||
|
return fhManager.allocate(await getTab(parseInt(pathComponent(path, -2))));
|
||||||
|
},
|
||||||
|
async read(path, fh, size, offset) {
|
||||||
|
const tab = fhManager.ref(fh);
|
||||||
|
return tab.url.substr(offset, size);
|
||||||
|
},
|
||||||
|
async release(path, fh) {
|
||||||
|
fhManager.free(fh);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
/* "title": fileFromProperty('title'),
|
||||||
|
* "sources": folderFromResource(
|
||||||
|
* (tab, path) => new Promise(resolve => chrome.debugger.attach(
|
||||||
|
* { tabId: tab.id }, "1-3", resolve)),
|
||||||
|
* {
|
||||||
|
* readdir() {
|
||||||
|
|
||||||
|
* }
|
||||||
|
* }*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +126,7 @@ function findRoute(path) {
|
||||||
async function getattr(path) {
|
async function getattr(path) {
|
||||||
let route = findRoute(path);
|
let route = findRoute(path);
|
||||||
if (route.getattr) {
|
if (route.getattr) {
|
||||||
return route.getattr();
|
return route.getattr(path);
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
st_mode: unix.S_IFDIR | 0755,
|
st_mode: unix.S_IFDIR | 0755,
|
||||||
|
@ -84,39 +137,62 @@ async function getattr(path) {
|
||||||
|
|
||||||
async function readdir(path) {
|
async function readdir(path) {
|
||||||
let route = findRoute(path);
|
let route = findRoute(path);
|
||||||
if (route.readdir) {
|
if (route.readdir) return route.readdir(path);
|
||||||
return route.readdir();
|
|
||||||
}
|
|
||||||
return Object.keys(route);
|
return Object.keys(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function open(path) {
|
||||||
|
let route = findRoute(path);
|
||||||
|
if (route.open) return route.open(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function read(path, fh, size, offset) {
|
||||||
|
let route = findRoute(path);
|
||||||
|
if (route.read) return route.read(path, fh, size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function release(path, fh) {
|
||||||
|
let route = findRoute(path);
|
||||||
|
if (route.read) return route.release(path, fh);
|
||||||
|
}
|
||||||
|
|
||||||
ws.onmessage = async function(event) {
|
ws.onmessage = async function(event) {
|
||||||
const req = JSON.parse(event.data);
|
const req = JSON.parse(event.data);
|
||||||
console.log('req', Object.entries(ops).find(([op, opcode]) => opcode === req.op)[0], req);
|
|
||||||
|
|
||||||
let response = { op: req.op, error: unix.EIO };
|
let response = { op: req.op, error: unix.EIO };
|
||||||
try {
|
try {
|
||||||
if (req.op === ops.GETATTR) {
|
if (req.op === 'getattr') {
|
||||||
response = {
|
response = {
|
||||||
op: ops.GETATTR,
|
op: 'getattr',
|
||||||
st_mode: 0,
|
st_mode: 0,
|
||||||
st_nlink: 0,
|
st_nlink: 0,
|
||||||
st_size: 0,
|
st_size: 0,
|
||||||
...(await getattr(req.path))
|
...(await getattr(req.path))
|
||||||
};
|
};
|
||||||
} else if (req.op === ops.OPEN) {
|
} else if (req.op === 'open') {
|
||||||
throw new UnixError(unix.EIO);
|
|
||||||
|
|
||||||
} else if (req.op === ops.READDIR) {
|
|
||||||
response = {
|
response = {
|
||||||
op: ops.READDIR,
|
op: 'open',
|
||||||
|
fh: await open(req.path)
|
||||||
|
};
|
||||||
|
|
||||||
|
} else if (req.op === 'readdir') {
|
||||||
|
response = {
|
||||||
|
op: 'readdir',
|
||||||
entries: [".", "..", ...(await readdir(req.path))]
|
entries: [".", "..", ...(await readdir(req.path))]
|
||||||
};
|
};
|
||||||
|
|
||||||
} else if (req.op === ops.READ) {
|
} else if (req.op === 'read') {
|
||||||
|
const buf = await read(req.path, req.fh, req.size, req.offset)
|
||||||
response = {
|
response = {
|
||||||
op: ops.READ,
|
op: 'read',
|
||||||
buf: await read(req.path)
|
buf,
|
||||||
|
size: buf.length
|
||||||
|
};
|
||||||
|
|
||||||
|
} else if (req.op === 'release') {
|
||||||
|
await release(req.path, req.fh);
|
||||||
|
response = {
|
||||||
|
op: 'release'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +203,5 @@ ws.onmessage = async function(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('response', Object.entries(ops).find(([op, opcode]) => opcode === response.op)[0], response);
|
|
||||||
ws.send(JSON.stringify(response));
|
ws.send(JSON.stringify(response));
|
||||||
};
|
};
|
||||||
|
|
61
fs/hello.c
61
fs/hello.c
|
@ -20,15 +20,6 @@ struct wby_con *con = NULL;
|
||||||
pthread_mutex_t request_data_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t request_data_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
char *request_data = NULL;
|
char *request_data = NULL;
|
||||||
|
|
||||||
enum opcode {
|
|
||||||
NONE = 0,
|
|
||||||
|
|
||||||
GETATTR,
|
|
||||||
OPEN,
|
|
||||||
READDIR,
|
|
||||||
READ
|
|
||||||
};
|
|
||||||
|
|
||||||
pthread_cond_t response_cv = PTHREAD_COND_INITIALIZER;
|
pthread_cond_t response_cv = PTHREAD_COND_INITIALIZER;
|
||||||
pthread_mutex_t response_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t response_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
cJSON *response = NULL;
|
cJSON *response = NULL;
|
||||||
|
@ -88,7 +79,7 @@ static cJSON *await_response() {
|
||||||
if (disconnected) { ret = -EIO; goto done; } \
|
if (disconnected) { ret = -EIO; goto done; } \
|
||||||
\
|
\
|
||||||
req = cJSON_CreateObject(); \
|
req = cJSON_CreateObject(); \
|
||||||
cJSON_AddNumberToObject(req, "op", (int) op); \
|
cJSON_AddStringToObject(req, "op", op); \
|
||||||
req_body \
|
req_body \
|
||||||
\
|
\
|
||||||
dispatch_send_req(req); \
|
dispatch_send_req(req); \
|
||||||
|
@ -101,9 +92,9 @@ static cJSON *await_response() {
|
||||||
if (ret != 0) goto done; \
|
if (ret != 0) goto done; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
ret = -1; \
|
||||||
resp_handler \
|
resp_handler \
|
||||||
\
|
\
|
||||||
ret = 0; \
|
|
||||||
done: \
|
done: \
|
||||||
if (req != NULL) cJSON_Delete(req); \
|
if (req != NULL) cJSON_Delete(req); \
|
||||||
if (resp != NULL) cJSON_Delete(resp); \
|
if (resp != NULL) cJSON_Delete(resp); \
|
||||||
|
@ -121,25 +112,29 @@ hello_getattr(const char *path, struct stat *stbuf)
|
||||||
memset(stbuf, 0, sizeof(struct stat));
|
memset(stbuf, 0, sizeof(struct stat));
|
||||||
printf("\n\ngetattr(%s)\n", path);
|
printf("\n\ngetattr(%s)\n", path);
|
||||||
|
|
||||||
MAKE_REQ(GETATTR, {
|
MAKE_REQ("getattr", {
|
||||||
cJSON_AddStringToObject(req, "path", path);
|
cJSON_AddStringToObject(req, "path", path);
|
||||||
}, {
|
}, {
|
||||||
JSON_GET_PROP_INT(stbuf->st_mode, "st_mode");
|
JSON_GET_PROP_INT(stbuf->st_mode, "st_mode");
|
||||||
JSON_GET_PROP_INT(stbuf->st_nlink, "st_nlink");
|
JSON_GET_PROP_INT(stbuf->st_nlink, "st_nlink");
|
||||||
JSON_GET_PROP_INT(stbuf->st_size, "st_size");
|
JSON_GET_PROP_INT(stbuf->st_size, "st_size");
|
||||||
printf("returning re getattr(%s)\n", path);
|
printf("returning re getattr(%s)\n", path);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hello_open(const char *path, struct fuse_file_info *fi)
|
hello_open(const char *path, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
MAKE_REQ(OPEN, {
|
MAKE_REQ("open", {
|
||||||
cJSON_AddStringToObject(req, "path", path);
|
cJSON_AddStringToObject(req, "path", path);
|
||||||
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
||||||
}, {
|
}, {
|
||||||
cJSON *fh_item = cJSON_GetObjectItemCaseSensitive(resp, "fh");
|
cJSON *fh_item = cJSON_GetObjectItemCaseSensitive(resp, "fh");
|
||||||
if (fh_item) fi->fh = fh_item->valueint;
|
if (fh_item) fi->fh = fh_item->valueint;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,8 +144,8 @@ hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||||
{
|
{
|
||||||
printf("\n\nreaddir(%s)\n", path);
|
printf("\n\nreaddir(%s)\n", path);
|
||||||
|
|
||||||
// send {op: READDIR, path} to the websocket handler
|
// send {op: "readdir", path} to the websocket handler
|
||||||
MAKE_REQ(READDIR, {
|
MAKE_REQ("readdir", {
|
||||||
cJSON_AddStringToObject(req, "path", path);
|
cJSON_AddStringToObject(req, "path", path);
|
||||||
}, {
|
}, {
|
||||||
cJSON *entries = cJSON_GetObjectItemCaseSensitive(resp, "entries");
|
cJSON *entries = cJSON_GetObjectItemCaseSensitive(resp, "entries");
|
||||||
|
@ -159,6 +154,8 @@ hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||||
filler(buf, cJSON_GetStringValue(entry), NULL, 0);
|
filler(buf, cJSON_GetStringValue(entry), NULL, 0);
|
||||||
printf("entry: [%s]\n", cJSON_GetStringValue(entry));
|
printf("entry: [%s]\n", cJSON_GetStringValue(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +163,7 @@ static int
|
||||||
hello_read(const char *path, char *buf, size_t size, off_t offset,
|
hello_read(const char *path, char *buf, size_t size, off_t offset,
|
||||||
struct fuse_file_info *fi)
|
struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
MAKE_REQ(OPEN, {
|
MAKE_REQ("read", {
|
||||||
cJSON_AddStringToObject(req, "path", path);
|
cJSON_AddStringToObject(req, "path", path);
|
||||||
cJSON_AddNumberToObject(req, "size", size);
|
cJSON_AddNumberToObject(req, "size", size);
|
||||||
cJSON_AddNumberToObject(req, "offset", offset);
|
cJSON_AddNumberToObject(req, "offset", offset);
|
||||||
|
@ -174,27 +171,35 @@ hello_read(const char *path, char *buf, size_t size, off_t offset,
|
||||||
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||||
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
||||||
}, {
|
}, {
|
||||||
|
size_t resp_size;
|
||||||
|
JSON_GET_PROP_INT(resp_size, "size");
|
||||||
|
size = resp_size < size ? resp_size : size;
|
||||||
|
|
||||||
|
cJSON *resp_buf_item = cJSON_GetObjectItemCaseSensitive(resp, "buf");
|
||||||
|
char *resp_buf = cJSON_GetStringValue(resp_buf_item);
|
||||||
|
size_t resp_buf_len = strlen(resp_buf);
|
||||||
|
size = resp_buf_len < size ? resp_buf_len : size;
|
||||||
|
|
||||||
|
memcpy(buf, resp_buf, size);
|
||||||
|
|
||||||
|
ret = size;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(path, file_path) != 0)
|
static int hello_release(const char *path, struct fuse_file_info *fi) {
|
||||||
return -ENOENT;
|
MAKE_REQ("release", {
|
||||||
|
cJSON_AddStringToObject(req, "path", path);
|
||||||
if (offset >= file_size) /* Trying to read past the end of file. */
|
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||||
return 0;
|
}, {
|
||||||
|
ret = 0;
|
||||||
if (offset + size > file_size) /* Trim the read to the file size. */
|
});
|
||||||
size = file_size - offset;
|
|
||||||
|
|
||||||
memcpy(buf, file_content + offset, size); /* Provide the content. */
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fuse_operations hello_filesystem_operations = {
|
static struct fuse_operations hello_filesystem_operations = {
|
||||||
.getattr = hello_getattr, /* To provide size, permissions, etc. */
|
.getattr = hello_getattr, /* To provide size, permissions, etc. */
|
||||||
.open = hello_open, /* To enforce read-only access. */
|
.open = hello_open, /* To enforce read-only access. */
|
||||||
.read = hello_read, /* To provide file content. */
|
.read = hello_read, /* To provide file content. */
|
||||||
|
.release = hello_release,
|
||||||
.readdir = hello_readdir, /* To provide directory listing. */
|
.readdir = hello_readdir, /* To provide directory listing. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue