2019-02-13 23:32:07 +00:00
[![Build Status ](https://travis-ci.org/falk-werner/fuse-wsfs.svg?branch=master )](https://travis-ci.org/falk-werner/fuse-wsfs)
2019-02-12 19:38:45 +00:00
[![Codacy Badge ](https://api.codacy.com/project/badge/Grade/d6c20d37bb3a456a9c0ee224001081b2 )](https://www.codacy.com/app/falk.werner/fuse-wsfs?utm_source=github.com& utm_medium=referral& utm_content=falk-werner/fuse-wsfs& utm_campaign=Badge_Grade)
2019-01-27 01:10:39 +00:00
# fuse-wsfs
2019-01-27 11:32:02 +00:00
fuse-wsfs combines libwebsockets and libfuse. It allows ot attach a remote filesystem via websockets.
2019-02-13 18:43:29 +00:00
## Contents
2019-02-12 20:43:50 +00:00
2019-02-13 18:43:29 +00:00
- [Workflow and API ](#Workflow-and-API )
- [Build and run ](#Build-and-run )
- [Dependencies ](#Dependencies )
2019-01-27 11:32:02 +00:00
2019-02-13 18:43:29 +00:00
## Workflow and API
2019-02-10 19:05:36 +00:00
+---------------------+ +-------------+ +------+
| Filesystem Provider | | wsfs daemon | | user |
| (e.g. Webbrowser) | | | | |
+----------+----------+ +------+------+ +---+--+
| | |
| +-+-+ |
| | +--+ |
| | | | fuse_mount |
| | +< - + |
| | | |
| | +--+ |
| | | | start ws |
| | +< - + |
| +-+-+ |
| | |
+-+-+ connect +-+-+ |
| |--------------->| | |
+-+-+ +-+-+ |
| | |
| +-+-+ ls +-+-+
+-+-+ readdir | |< ------------ + |
| |< --------------- + | | |
| | | | | |
| | readdir_resp | | | |
| +--------------->| | [., ..] | |
+-+-+ | +------------>| |
| +-+-+ +-+-+
| | |
With fuse-wsfs it is possible to implement remote filesystems based on websockets.
A reference implementation of such a daemon is provided within the examples. The picture above describes the workflow:
2019-02-13 18:43:29 +00:00
- The websocket filesystem daemon (*wsfs daemon*) mounts a filesystem on startup.
It starts the websocket server and waits for incoming connections.
2019-02-14 23:00:44 +00:00
2019-02-13 18:43:29 +00:00
- A remote filesystem provider connects to wsfs daemon via websocket protocol.
The example includes such a provider implemented in HTML and JavaScript.
2019-02-14 23:00:44 +00:00
2019-02-13 18:43:29 +00:00
- Whenever the user makes filesystem requests, such as *ls* , the request is redirected via wsfs daemon to the connected filesystem provider
2019-02-10 19:05:36 +00:00
Currently all requests are initiated by wsfs daemon and responded by filesystem provider. This may change in future, e.g. when authentication is supported.
2019-02-13 18:43:29 +00:00
### Requests, responses and notifications
2019-02-10 19:05:36 +00:00
There are three types of messages, used for communication between wsfs daemon and filesystem provider. All message types are encoded in [JSON ](https://www.json.org/ ) and strongly inspired by [JSON-RPC ](https://www.jsonrpc.org/ ).
2019-02-13 18:43:29 +00:00
#### Request
2019-02-10 19:05:36 +00:00
A request is used by a sender to invoke a method on the receiver. The sender awaits a response from the receiver. Since requests and responses can be sendet or answered in any order, an id is provided in each request to identify it.
{
"method": < method_name > ,
"params": < params > ,
"id" : < id >
}
| Item | Data type | Description |
| ----------- |:---------:| --------------------------------- |
| method_name | string | name of the method to invoke |
| params | array | method specific parameters |
| id | integer | id, which is repeated in response |
2019-02-13 18:43:29 +00:00
#### Response
2019-02-10 19:05:36 +00:00
A response is used to answer a prior request. There are two kinds of responses:
2019-02-13 18:43:29 +00:00
##### Successful Results
2019-02-10 19:05:36 +00:00
{
"result": < result > ,
"id": < id >
}
| Item | Data type | Description |
| ----------- |:---------:| ----------------------- |
| result | any | request specific result |
| id | integer | id, same as request |
2019-02-13 18:43:29 +00:00
##### Error notifications
2019-02-10 19:05:36 +00:00
{
"error": {
"code": < code >
},
"id": < id >
}
| Item | Data type | Description |
| ----------- |:---------:| ------------------- |
| code | integer | error code |
| id | integer | id, same as request |
2019-02-13 18:43:29 +00:00
##### Error codes
2019-02-10 19:05:36 +00:00
| Symbolic name | Code | Description |
| ------------------ | ---------:| ---------------------- |
| GOOD | 0 | no error |
| BAD | 1 | generic error |
| BAD_NOTIMPLEMENTED | 2 | method not implemented |
| BAD_TIMEOUT | 3 | timeout occured |
| BAD_BUSY | 4 | resource busy |
| BAD_FORMAT | 5 | invalid formt |
| BAD_NOENTRY | 101 | invalid entry |
| BAD_NOACCESS | 102 | access not allowed |
2019-02-13 18:43:29 +00:00
#### Notification
2019-02-10 19:05:36 +00:00
Notfications are used to inform a receiver about something. Unlike requests, notifications are not answered. Therefore, an id is not supplied.
{
"method": < method_name > ,
"params": < params >
}
| Item | Data type | Description |
| ----------- |:---------:| --------------------------------- |
| method_name | string | name of the method to invoke |
| params | array | method specific parameters |
2019-02-13 18:43:29 +00:00
### Requests
2019-02-10 19:05:36 +00:00
2019-02-13 18:43:29 +00:00
#### lookup
2019-02-10 19:05:36 +00:00
Retrieve information about a filesystem entry by name.
wsfs daemon: {"method": "lookup", "params": [< parent > , < name > ], "id": < id > }
fs provider: {"result": {
"inode": < inode > ,
"mode" : < mode > ,
"type" : < type > ,
"size" : < size > ,
"atime": < atime > ,
"mtime": < mtime > ,
"ctime": < ctime >
}, "id": < id > }
| Item | Data type | Description |
| ----------- | --------------- | ------------------------------------------- |
| parent | integer | inode of parent directory (1 = root) |
| name | string | name of the filesystem object to look up |
| inode | integer | inode of the filesystem object |
| mode | integer | unix file mode |
| type | "file" or "dir" | type of filesystem object |
| size | integer | required for files; file size in bytes |
| atime | integer | optional; unix time of last access |
| mtime | integer | optional; unix time of last modification |
| ctime | intefer | optional; unix time of last metadata change |
2019-02-13 18:43:29 +00:00
#### getattr
2019-02-10 19:05:36 +00:00
Get file attributes.
wsfs daemon: {"method": "getattr", "params": [< inode > ], "id": < id > }
fs provider: {"result": {
"mode" : < mode > ,
"type" : < type > ,
"size" : < size > ,
"atime": < atime > ,
"mtime": < mtime > ,
"ctime": < ctime >
}, "id": < id > }
| Item | Data type | Description |
| ----------- | --------------- | ------------------------------------------- |
| inode | integer | inode of the filesystem object |
| mode | integer | unix file mode |
| type | "file" or "dir" | type of filesystem object |
| size | integer | required for files; file size in bytes |
| atime | integer | optional; unix time of last access |
| mtime | integer | optional; unix time of last modification |
| ctime | intefer | optional; unix time of last metadata change |
2019-02-13 18:43:29 +00:00
#### readdir
2019-02-10 19:05:36 +00:00
Read directory contents.
Result is an array of name-inode pairs for each entry. The generic entries
"." and ".." should also be provided.
wsfs daemon: {"method": "readdir", "params": [< dir_inode > ], "id": < id > }
fs provider: {"result": [
{"name": < name > , "inode": < inode > },
...
], "id": < id > }
| Item | Data type | Description |
| ----------- | --------------- | ------------------------------ |
| dir_inode | integer | inode of the directory to read |
| name | integer | name of the entry |
| inode | integer | inode of the entry |
2019-02-13 18:43:29 +00:00
#### open
2019-02-10 19:05:36 +00:00
Open a file.
wsfs daemon: {"method": "readdir", "params": [< inode > , < flags > ], "id": < id > }
fs provider: {"result": {"handle": < handle > }, "id": < id > }
| Item | Data type | Description |
| ----------- | ----------| ----------------------------- |
| inode | integer | inode of the file |
| flags | integer | access mode flags (see below) |
| handle | integer | handle of the file |
2019-02-13 18:43:29 +00:00
##### Flags
2019-02-10 19:05:36 +00:00
| Symbolic name | Code | Description |
| --------------| ---------:| --------------------------- |
| O_ACCMODE | 0x003 | access mode mask |
| O_RDONLY | 0x000 | open for reading only |
| O_WRONLY | 0x001 | open for writing only |
| O_RDWR | 0x002 | open for reading an writing |
| O_CREAT | 0x040 | create (a new) file |
| O_EXCL | 0x080 | open file exclusivly |
| O_TRUNK | 0x200 | open file to trunkate |
| O_APPEND | 0x400 | open file to append |
2019-02-13 18:43:29 +00:00
#### close
2019-02-10 19:05:36 +00:00
Informs filesystem provider, that a file is closed.
Since `close` is a notification, it cannot fail.
wsfs daemon: {"method": "close", "params": [< inode > , < handle > , < flags > ], "id": < id > }
| Item | Data type | Description |
| ----------- | ----------| ---------------------------- |
| inode | integer | inode of the file |
| handle | integer | handle of the file |
| flags | integer | access mode flags (see open) |
2019-02-13 18:43:29 +00:00
#### read
2019-02-10 19:05:36 +00:00
Read from an open file.
wsfs daemon: {"method": "close", "params": [< inode > , < handle > , < offset > , < length > ], "id": < id > }
fs provider: {"result": {
"data": < data > ,
"format": < format > ,
"count": < count >
}, "id": < id > }
| Item | Data type | Description |
| ----------- | ----------| ----------------------------- |
| inode | integer | inode of the file |
| handle | integer | handle of the file |
| offset | integer | Offet to start read operation |
| length | integer | Max. number of bytes to read |
| data | integer | handle of the file |
| format | string | Encoding of data (see below) |
| count | integer | Actual number of bytes read |
2019-02-13 18:43:29 +00:00
##### Format
2019-02-10 19:05:36 +00:00
2019-02-10 21:18:22 +00:00
| Format | Description |
| ---------- | -------------------------------------------------------- |
| "identiy" | Use data as is; note that JSON strings are UTF-8 encoded |
| "base64" | data is base64 encoded |
2019-02-10 19:05:36 +00:00
2019-02-13 18:43:29 +00:00
## Build and run
2019-01-27 11:32:02 +00:00
2019-02-10 10:48:25 +00:00
To install dependencies, see below.
2019-01-27 11:32:02 +00:00
cd fuse-wsfs
2019-02-15 15:16:24 +00:00
mkdir .build
cd .build
cmake ..
2019-01-27 11:32:02 +00:00
mkdir test
2019-02-16 15:28:14 +00:00
./wsfsd -m test --document_root=../exmaple/daemon/www --port=4711
2019-01-27 11:32:02 +00:00
2019-02-15 15:16:24 +00:00
### Build options
By default, unit tests and example application are enabled. You can disable them using the following cmake options:
2019-02-16 07:41:24 +00:00
- **WITHOUT_TESTS** : disable tests
`cmake -DWITHOUT_TESTS=ON ..`
2019-02-15 15:16:24 +00:00
2019-02-16 07:41:24 +00:00
- **WITHOUT_EXAMPLE** : disable example
`cmake -DWITHOUD_EXAMPLE=ON ..`
2019-02-15 15:16:24 +00:00
2019-02-13 18:43:29 +00:00
## Dependencies
2019-01-27 11:32:02 +00:00
2019-02-13 18:43:29 +00:00
- [libfuse3 ](https://github.com/libfuse/libfuse/ )
- [libwebsockets ](https://libwebsockets.org/ )
- [Jansson ](https://jansson.readthedocs.io )
- [GoogleTest ](https://github.com/google/googletest ) *(optional)*
2019-01-27 11:32:02 +00:00
2019-02-13 18:43:29 +00:00
### Installation
2019-02-10 10:48:25 +00:00
2019-02-13 18:43:29 +00:00
#### libfuse
2019-02-10 10:48:25 +00:00
wget -O fuse-3.1.1.tar.gz https://github.com/libfuse/libfuse/archive/fuse-3.1.1.tar.gz
tar -xf fuse-3.1.1.tar.gz
cd libfuse-fuse-3.1.1
./makeconf.sh
./configure
make
sudo make install
2019-02-13 18:43:29 +00:00
#### libwebsockets
2019-02-10 10:48:25 +00:00
wget -O libwebsockets-3.1.0.tar.gz https://github.com/warmcat/libwebsockets/archive/v3.1.0.tar.gz
tar -xf libwebsockets-3.1.0.tar.gz
cd libwebsockets-3.1.0
mkdir .build
cd .build
cmake ..
make
sudo make install
2019-02-13 18:43:29 +00:00
#### Jansson
2019-02-10 10:48:25 +00:00
On many systems, libjansson can installed via apt:
sudo apt install libjansson-dev
Otherwise, it can be installed from source:
wget -O libjansson-2.12.tar.gz https://github.com/akheron/jansson/archive/v2.12.tar.gz
tar -xf libjansson-2.12.tar.gz
cd jansson-2.12
mkdir .build
cd .build
cmake ..
make
sudo make install
2019-02-13 18:43:29 +00:00
#### GoogleTest
2019-02-10 10:48:25 +00:00
Installation of GoogleTest is optional fuse-wsfs library, but required to compile tests.
wget -O gtest-1.8.1.tar.gz https://github.com/google/googletest/archive/release-1.8.1.tar.gz
tar -xf gtest-1.8.1.tar.gz
cd googletest-release-1.8.1
mkdir .build
cd .build
cmake ..
make
sudo make install