mirror of
https://github.com/falk-werner/webfuse-provider
synced 2026-03-02 04:09:18 +00:00
moved code to examples
This commit is contained in:
4
examples/.gitignore
vendored
Normal file
4
examples/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/build/
|
||||
/.vscode/
|
||||
/subprojects/*
|
||||
!/subprojects/*.wrap
|
||||
31
examples/.travis.yml
Normal file
31
examples/.travis.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
dist: bionic
|
||||
|
||||
language: c
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
packages:
|
||||
- build-essential
|
||||
- cmake
|
||||
- pkgconf
|
||||
- wget
|
||||
- ca-certificates
|
||||
- python3
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
- python3-wheel
|
||||
- ninja-build
|
||||
|
||||
before_install:
|
||||
- sudo pip3 install --system meson
|
||||
|
||||
before_script:
|
||||
- meson build
|
||||
|
||||
script:
|
||||
- cd build
|
||||
- ninja
|
||||
165
examples/LICENSE
Normal file
165
examples/LICENSE
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
22
examples/README.md
Normal file
22
examples/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
[](https://travis-ci.org/falk-werner/webfuse-provider)
|
||||
|
||||
# webfuse-provider
|
||||
|
||||
Reference implementation of webfuse provider
|
||||
|
||||
## Build and run
|
||||
|
||||
To install dependecies, see below.
|
||||
|
||||
meson build
|
||||
cd build
|
||||
ninja
|
||||
./webfuse-provider
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [webfuse](https://github.com/falk-werner/webfuse)
|
||||
- [libwebsockets](https://libwebsockets.org/)
|
||||
- [jansson](https://github.com/akheron/jansson)
|
||||
|
||||
All dependencies are bundled using meson wrap files.
|
||||
15
examples/meson.build
Normal file
15
examples/meson.build
Normal file
@@ -0,0 +1,15 @@
|
||||
project('webfuse-provider', version: '0.1.0', license: 'LGPL-3.0+')
|
||||
|
||||
|
||||
webfuse_provider_dep = dependency('webfuse_provider', version: '>=0.3.0',
|
||||
fallback: ['webfuse', 'webfuse_provider_dep'], default_options: ['without_adapter=true'])
|
||||
|
||||
executable('webfuse-provider',
|
||||
'src/main.c',
|
||||
dependencies: [webfuse_provider_dep])
|
||||
|
||||
executable('static-filesystem-provider',
|
||||
'src/static_filesystem/static_filesystem.c',
|
||||
'src/static_filesystem/path.c',
|
||||
'src/static_filesystem/main.c',
|
||||
dependencies: [webfuse_provider_dep])
|
||||
383
examples/src/main.c
Normal file
383
examples/src/main.c
Normal file
@@ -0,0 +1,383 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "webfuse_provider.h"
|
||||
|
||||
struct config
|
||||
{
|
||||
char * url;
|
||||
struct wfp_client_config * client_config;
|
||||
bool show_help;
|
||||
};
|
||||
|
||||
enum fs_entry_type
|
||||
{
|
||||
FS_FILE,
|
||||
FS_DIR
|
||||
};
|
||||
|
||||
struct fs_entry
|
||||
{
|
||||
ino_t parent;
|
||||
ino_t inode;
|
||||
char const * name;
|
||||
int mode;
|
||||
enum fs_entry_type type;
|
||||
size_t content_length;
|
||||
char const * content;
|
||||
};
|
||||
|
||||
struct fs
|
||||
{
|
||||
struct fs_entry const * entries;
|
||||
};
|
||||
|
||||
static void show_help()
|
||||
{
|
||||
printf(
|
||||
"webfuse-provider, Copyright (c) 2019, webfuse authors <https://github.com/falk-werner/webfuse>\n"
|
||||
"Example for websocket file system provider\n"
|
||||
"\n"
|
||||
"Usage: webfuse-provider -u <url> [-k <key_path>] [-c <cert_path>]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"\t-u, --url URL of webfuse server (required)\n"
|
||||
"\t-k, --key_path Path to private key of provider (default: not set, TLS disabled)\n"
|
||||
"\t-c, --cert_path Path to certificate of provider (defautl: not set, TLS disabled)\n"
|
||||
"\t-h, --help prints this message\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"\twebfuse-provider -u ws://localhost:8080/\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int parse_arguments(
|
||||
int argc,
|
||||
char* argv[],
|
||||
struct config * config)
|
||||
{
|
||||
static struct option const options[] =
|
||||
{
|
||||
{"url", required_argument, NULL, 'u'},
|
||||
{"key_path", required_argument, NULL, 'k'},
|
||||
{"cert_path", required_argument, NULL, 'c'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
int result = EXIT_SUCCESS;
|
||||
bool finished = false;
|
||||
while (!finished)
|
||||
{
|
||||
int option_index = 0;
|
||||
int const c = getopt_long(argc, argv, "u:k:c:h", options, &option_index);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case -1:
|
||||
finished = true;
|
||||
break;
|
||||
case 'h':
|
||||
config->show_help = true;
|
||||
finished = true;
|
||||
break;
|
||||
case 'u':
|
||||
free(config->url);
|
||||
config->url = strdup(optarg);
|
||||
break;
|
||||
case 'k':
|
||||
wfp_client_config_set_keypath(config->client_config, optarg);
|
||||
break;
|
||||
case 'c':
|
||||
wfp_client_config_set_certpath(config->client_config, optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "error: unknown argument\n");
|
||||
finished = true;
|
||||
result = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == config->url)
|
||||
{
|
||||
fprintf(stderr, "error: missing required argument \"-u\"\n");
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (result != EXIT_SUCCESS)
|
||||
{
|
||||
config->show_help = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct fs_entry const * fs_getentry(
|
||||
struct fs * fs,
|
||||
ino_t inode)
|
||||
{
|
||||
for (size_t i = 0; 0 != fs->entries[i].inode; i++)
|
||||
{
|
||||
struct fs_entry const * entry = &fs->entries[i];
|
||||
if (inode == entry->inode)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fs_entry const * fs_getentry_byname(
|
||||
struct fs * fs,
|
||||
ino_t parent,
|
||||
char const * name)
|
||||
{
|
||||
for( size_t i = 0; 0 != fs->entries[i].inode; i++)
|
||||
{
|
||||
struct fs_entry const * entry = &fs->entries[i];
|
||||
if ((parent == entry->parent) && (0 == strcmp(name, entry->name)))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fs_stat(
|
||||
struct fs_entry const * entry,
|
||||
struct stat * stat)
|
||||
{
|
||||
memset(stat, 0, sizeof(struct stat));
|
||||
|
||||
stat->st_ino = entry->inode;
|
||||
stat->st_mode = entry->mode;
|
||||
|
||||
if (FS_DIR == entry->type)
|
||||
{
|
||||
stat->st_mode |= S_IFDIR;
|
||||
}
|
||||
|
||||
if (FS_FILE == entry->type)
|
||||
{
|
||||
stat->st_mode |= S_IFREG;
|
||||
stat->st_size = entry->content_length;
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_lookup(
|
||||
struct wfp_request * request,
|
||||
ino_t parent,
|
||||
char const * name,
|
||||
void * user_data)
|
||||
{
|
||||
struct fs * fs = (struct fs*) user_data;
|
||||
struct fs_entry const * entry = fs_getentry_byname(fs, parent, name);
|
||||
if (NULL != entry)
|
||||
{
|
||||
struct stat stat;
|
||||
fs_stat(entry, &stat);
|
||||
|
||||
wfp_respond_lookup(request, &stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fs_getattr(
|
||||
struct wfp_request * request,
|
||||
ino_t inode,
|
||||
void * user_data)
|
||||
{
|
||||
struct fs * fs = (struct fs*) user_data;
|
||||
struct fs_entry const * entry = fs_getentry(fs, inode);
|
||||
|
||||
if (NULL != entry)
|
||||
{
|
||||
struct stat stat;
|
||||
fs_stat(entry, &stat);
|
||||
|
||||
wfp_respond_getattr(request, &stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_readdir(
|
||||
struct wfp_request * request,
|
||||
ino_t directory,
|
||||
void * user_data)
|
||||
{
|
||||
struct fs * fs = (struct fs*) user_data;
|
||||
|
||||
struct fs_entry const * dir = fs_getentry(fs, directory);
|
||||
if ((NULL != dir) && (FS_DIR == dir->type))
|
||||
{
|
||||
struct wfp_dirbuffer * buffer = wfp_dirbuffer_create();
|
||||
wfp_dirbuffer_add(buffer, ".", dir->inode);
|
||||
wfp_dirbuffer_add(buffer, "..", dir->inode);
|
||||
|
||||
for(size_t i = 0; 0 != fs->entries[i].inode; i++)
|
||||
{
|
||||
struct fs_entry const * entry = &fs->entries[i];
|
||||
if (directory == entry->parent)
|
||||
{
|
||||
wfp_dirbuffer_add(buffer, entry->name, entry->inode);
|
||||
}
|
||||
}
|
||||
|
||||
wfp_respond_readdir(request, buffer);
|
||||
wfp_dirbuffer_dispose(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_open(
|
||||
struct wfp_request * request,
|
||||
ino_t inode,
|
||||
int flags,
|
||||
void * user_data)
|
||||
{
|
||||
struct fs * fs = (struct fs*) user_data;
|
||||
|
||||
struct fs_entry const * entry = fs_getentry(fs, inode);
|
||||
if ((NULL != entry) && (FS_FILE == entry->type))
|
||||
{
|
||||
if (O_RDONLY == (flags & O_ACCMODE))
|
||||
{
|
||||
wfp_respond_open(request, 0U);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t min(size_t const a, size_t const b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static void fs_read(
|
||||
struct wfp_request * request,
|
||||
ino_t inode,
|
||||
uint32_t handle,
|
||||
size_t offset,
|
||||
size_t length,
|
||||
void * user_data)
|
||||
{
|
||||
(void) handle;
|
||||
|
||||
struct fs * fs = (struct fs*) user_data;
|
||||
struct fs_entry const * entry = fs_getentry(fs, inode);
|
||||
if ((NULL != entry) && (FS_FILE == entry->type))
|
||||
{
|
||||
if (entry->content_length > offset)
|
||||
{
|
||||
size_t const remaining = entry->content_length - offset;
|
||||
size_t const count = min(remaining, length);
|
||||
|
||||
wfp_respond_read(request, &entry->content[offset], count);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static volatile bool shutdown_requested = false;
|
||||
|
||||
static void on_interrupt(int signal_id)
|
||||
{
|
||||
(void) signal_id;
|
||||
shutdown_requested = true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
struct config config;
|
||||
config.url = NULL;
|
||||
config.show_help = false;
|
||||
config.client_config = wfp_client_config_create();
|
||||
int result = parse_arguments(argc, argv, &config);
|
||||
|
||||
if (EXIT_SUCCESS == result)
|
||||
{
|
||||
static struct fs_entry const entries[]=
|
||||
{
|
||||
{.parent = 0, .inode = 1, .name = "<root>", .mode = 0555, .type = FS_DIR},
|
||||
{
|
||||
.parent = 1,
|
||||
.inode = 2,
|
||||
.name = "hello.txt",
|
||||
.mode = 0444,
|
||||
.type = FS_FILE,
|
||||
.content="hello, world!",
|
||||
.content_length = 13,
|
||||
},
|
||||
{.parent = 0, .inode = 0, .name = NULL}
|
||||
};
|
||||
|
||||
struct fs fs =
|
||||
{
|
||||
.entries = entries
|
||||
};
|
||||
|
||||
signal(SIGINT, &on_interrupt);
|
||||
|
||||
wfp_client_config_set_userdata(config.client_config, &fs);
|
||||
wfp_client_config_set_onlookup(config.client_config, &fs_lookup);
|
||||
wfp_client_config_set_ongetattr(config.client_config, &fs_getattr);
|
||||
wfp_client_config_set_onreaddir(config.client_config, &fs_readdir);
|
||||
wfp_client_config_set_onopen(config.client_config, &fs_open);
|
||||
wfp_client_config_set_onread(config.client_config, &fs_read);
|
||||
|
||||
struct wfp_client * client = wfp_client_create(config.client_config);
|
||||
wfp_client_connect(client, config.url);
|
||||
|
||||
while (!shutdown_requested)
|
||||
{
|
||||
wfp_client_service(client);
|
||||
}
|
||||
|
||||
wfp_client_dispose(client);
|
||||
}
|
||||
|
||||
if (config.show_help)
|
||||
{
|
||||
show_help();
|
||||
}
|
||||
|
||||
free(config.url);
|
||||
wfp_client_config_dispose(config.client_config);
|
||||
return result;
|
||||
}
|
||||
108
examples/src/static_filesystem/main.c
Normal file
108
examples/src/static_filesystem/main.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "webfuse_provider.h"
|
||||
#include "static_filesystem.h"
|
||||
|
||||
struct args
|
||||
{
|
||||
char const * url;
|
||||
bool show_help;
|
||||
};
|
||||
|
||||
static int
|
||||
parse_args(
|
||||
struct args * args,
|
||||
int argc,
|
||||
char * argv[])
|
||||
{
|
||||
int result = EXIT_FAILURE;
|
||||
args->show_help = true;
|
||||
args->url = NULL;
|
||||
|
||||
if (2 == argc)
|
||||
{
|
||||
result = EXIT_SUCCESS;
|
||||
|
||||
char const * url = argv[1];
|
||||
if ((0 != strcmp(url, "-h")) && (0 != strcmp(url, "--help")))
|
||||
{
|
||||
args->show_help = false;
|
||||
args->url = url;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "error: missing argument\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static volatile bool shutdown_requested = false;
|
||||
|
||||
static void on_interrupt(int signal_id)
|
||||
{
|
||||
(void) signal_id;
|
||||
shutdown_requested = true;
|
||||
}
|
||||
|
||||
static void print_usage()
|
||||
{
|
||||
printf(
|
||||
"static-filesystem-provider Copyright (c) 2019, webfuse authors <https://github.com/falk-werner/webfuse>\n"
|
||||
"Example of webfuse static filesystem provider\n"
|
||||
"\n"
|
||||
"Usage: static-filesystem-provider <url>\n"
|
||||
"\n"
|
||||
"Arguments:\n"
|
||||
"\t<url> URL of webfuse server (required)\n"
|
||||
"\t-h, --help prints this message\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"\tstatic-filesystem-provider ws://localhost:8080/\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
signal(SIGINT, &on_interrupt);
|
||||
|
||||
struct args args;
|
||||
int result = parse_args(&args, argc, argv);
|
||||
if ((EXIT_SUCCESS == result) && (!args.show_help))
|
||||
{
|
||||
struct wfp_client_config * config = wfp_client_config_create();
|
||||
|
||||
struct static_filesystem * fs = static_filesystem_create(config);
|
||||
static_filesystem_add_text(fs, "brummni/hello_world.txt", 0444, "Hello, World!\n");
|
||||
static_filesystem_add_text(fs, "brummni/hello_bob.txt", 0444, "Hello, Bob!\n");
|
||||
static_filesystem_add_text(fs, "brummni/hello_bob.txt", 0444, "Hello, Alice!\n");
|
||||
static_filesystem_add_text(fs, "bla/hello_world.txt", 0444, "Hello, World!\n");
|
||||
static_filesystem_add_text(fs, "foo.txt", 0444, "foo\n");
|
||||
static_filesystem_add_text(fs, "bar.txt", 0444, "bar\n");
|
||||
|
||||
struct wfp_client * client = wfp_client_create(config);
|
||||
wfp_client_connect(client, args.url);
|
||||
|
||||
while (!shutdown_requested)
|
||||
{
|
||||
wfp_client_service(client);
|
||||
}
|
||||
|
||||
wfp_client_dispose(client);
|
||||
static_filesystem_dispose(fs);
|
||||
wfp_client_config_dispose(config);
|
||||
}
|
||||
|
||||
if (args.show_help)
|
||||
{
|
||||
print_usage();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
116
examples/src/static_filesystem/path.c
Normal file
116
examples/src/static_filesystem/path.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "path.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PATH_DEFAULT_CAPACITY (8)
|
||||
|
||||
struct path
|
||||
{
|
||||
char * * elements;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
static void
|
||||
path_add(
|
||||
struct path * path,
|
||||
char const * element,
|
||||
size_t element_size)
|
||||
{
|
||||
if (0 < element_size)
|
||||
{
|
||||
if (path->count >= path->capacity)
|
||||
{
|
||||
size_t new_capacity = 2 * path->capacity;
|
||||
size_t new_size = sizeof(char*) * new_capacity;
|
||||
|
||||
char * * elements = realloc(path->elements, new_size);
|
||||
if (NULL != elements)
|
||||
{
|
||||
path->elements = elements;
|
||||
path->capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
if (path->count < path->capacity)
|
||||
{
|
||||
path->elements[path->count] = strndup(element, element_size);
|
||||
path->count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct path *
|
||||
path_create(
|
||||
char const * value)
|
||||
{
|
||||
struct path * path = malloc(sizeof(struct path));
|
||||
if (NULL != path)
|
||||
{
|
||||
path->elements = malloc(sizeof(char*) * PATH_DEFAULT_CAPACITY);
|
||||
path->capacity = PATH_DEFAULT_CAPACITY;
|
||||
path->count = 0;
|
||||
|
||||
char const * remainder = value;
|
||||
char const * pos = strchr(remainder, '/');
|
||||
while (NULL != pos)
|
||||
{
|
||||
path_add(path, remainder, (pos - remainder));
|
||||
remainder = pos + 1;
|
||||
pos = strchr(remainder, '/');
|
||||
}
|
||||
|
||||
path_add(path, remainder, strlen(remainder));
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void
|
||||
path_dispose(
|
||||
struct path * path)
|
||||
{
|
||||
for(size_t i = 0; i < path->count; i++)
|
||||
{
|
||||
free(path->elements[i]);
|
||||
}
|
||||
|
||||
free(path->elements);
|
||||
free(path);
|
||||
(void) path;
|
||||
}
|
||||
|
||||
size_t
|
||||
path_element_count(
|
||||
struct path * path)
|
||||
{
|
||||
return path->count;
|
||||
}
|
||||
|
||||
char const *
|
||||
path_get_element(
|
||||
struct path * path,
|
||||
size_t i)
|
||||
{
|
||||
char const * result = NULL;
|
||||
if (i < path->count)
|
||||
{
|
||||
result = path->elements[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char const *
|
||||
path_get_filename(
|
||||
struct path * path)
|
||||
{
|
||||
char const * result = NULL;
|
||||
|
||||
if (0 < path->count)
|
||||
{
|
||||
result = path->elements[path->count - 1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
43
examples/src/static_filesystem/path.h
Normal file
43
examples/src/static_filesystem/path.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef PATH_H
|
||||
#define PATH_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stddef.h>
|
||||
#else
|
||||
#include <cstddef>
|
||||
using ::std::size_t;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct path;
|
||||
|
||||
extern struct path *
|
||||
path_create(
|
||||
char const * value);
|
||||
|
||||
extern void
|
||||
path_dispose(
|
||||
struct path * path);
|
||||
|
||||
extern size_t
|
||||
path_element_count(
|
||||
struct path * path);
|
||||
|
||||
extern char const *
|
||||
path_get_element(
|
||||
struct path * path,
|
||||
size_t i);
|
||||
|
||||
extern char const *
|
||||
path_get_filename(
|
||||
struct path * path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
500
examples/src/static_filesystem/static_filesystem.c
Normal file
500
examples/src/static_filesystem/static_filesystem.c
Normal file
@@ -0,0 +1,500 @@
|
||||
#include "static_filesystem.h"
|
||||
|
||||
#include "webfuse/provider/client_config.h"
|
||||
#include "webfuse/provider/dirbuffer.h"
|
||||
#include "webfuse/provider/operation/error.h"
|
||||
|
||||
#include "path.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define STATIC_FILESYSTEM_DEFAULT_CAPACITY (16)
|
||||
#define STATIC_FILSYSTEM_INODE_ROOT (1)
|
||||
#define STATIC_FILESYSTEM_MAX_READ_SIZE (4 * 1024)
|
||||
|
||||
struct static_filesystem_entry
|
||||
{
|
||||
size_t inode;
|
||||
size_t parent;
|
||||
char * name;
|
||||
bool is_file;
|
||||
int mode;
|
||||
size_t size;
|
||||
char * content;
|
||||
static_filesystem_read_fn * read;
|
||||
static_filesystem_get_info_fn * get_info;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
struct static_filesystem
|
||||
{
|
||||
struct static_filesystem_entry * entries;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
static struct static_filesystem_entry *
|
||||
static_filesystem_get_entry(
|
||||
struct static_filesystem * filesystem,
|
||||
size_t inode)
|
||||
{
|
||||
struct static_filesystem_entry * entry = NULL;
|
||||
|
||||
if ((0 < inode) && (inode <= filesystem->size))
|
||||
{
|
||||
entry = &filesystem->entries[inode - 1];
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static struct static_filesystem_entry *
|
||||
static_filesystem_get_entry_by_name(
|
||||
struct static_filesystem * filesystem,
|
||||
size_t parent,
|
||||
char const * name)
|
||||
{
|
||||
struct static_filesystem_entry * entry = NULL;
|
||||
for(size_t i = 0; i < filesystem->size; i++)
|
||||
{
|
||||
struct static_filesystem_entry * current = &filesystem->entries[i];
|
||||
if ((parent == current->parent) && (0 == strcmp(name, current->name)))
|
||||
{
|
||||
entry = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static struct static_filesystem_entry *
|
||||
static_filesystem_add_entry(
|
||||
struct static_filesystem * filesystem)
|
||||
{
|
||||
struct static_filesystem_entry * entry = NULL;
|
||||
|
||||
if (filesystem->size >= filesystem->capacity)
|
||||
{
|
||||
struct static_filesystem_entry * entries;
|
||||
|
||||
size_t new_capacity = 2 * filesystem->capacity;
|
||||
size_t new_size = new_capacity * sizeof(struct static_filesystem_entry);
|
||||
entries = realloc(filesystem->entries, new_size);
|
||||
|
||||
if (NULL != entries)
|
||||
{
|
||||
filesystem->entries = entries;
|
||||
filesystem->capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
if (filesystem->size < filesystem->capacity)
|
||||
{
|
||||
entry = &filesystem->entries[filesystem->size];
|
||||
entry->inode = filesystem->size + 1;
|
||||
filesystem->size++;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static size_t
|
||||
static_filesystem_entry_read(
|
||||
size_t offset,
|
||||
char * buffer,
|
||||
size_t buffer_size,
|
||||
void * user_data)
|
||||
{
|
||||
size_t result = 0;
|
||||
struct static_filesystem_entry * entry = user_data;
|
||||
if (offset < entry->size)
|
||||
{
|
||||
size_t remaining = (entry->size - offset);
|
||||
result = (buffer_size < remaining) ? buffer_size : remaining;
|
||||
memcpy(buffer, entry->content, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
static_filesystem_entry_get_info(
|
||||
void * user_data,
|
||||
int * result_mode,
|
||||
size_t * result_size)
|
||||
{
|
||||
struct static_filesystem_entry * entry = user_data;
|
||||
*result_mode = entry->mode;
|
||||
*result_size = entry->size;
|
||||
}
|
||||
|
||||
static size_t
|
||||
static_filesystem_file_read(
|
||||
size_t offset,
|
||||
char * buffer,
|
||||
size_t buffer_size,
|
||||
void * user_data)
|
||||
{
|
||||
size_t result = 0;
|
||||
struct static_filesystem_entry * entry = user_data;
|
||||
char const * filename = entry->content;
|
||||
|
||||
FILE * file = fopen(filename, "rb");
|
||||
if (NULL != file)
|
||||
{
|
||||
fseek(file, offset, SEEK_SET);
|
||||
result = fread(buffer, buffer_size, 1, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
static_filesystem_file_get_info(
|
||||
void * user_data,
|
||||
int * result_mode,
|
||||
size_t * result_size)
|
||||
{
|
||||
struct static_filesystem_entry * entry = user_data;
|
||||
char const * filename = entry->content;
|
||||
|
||||
struct stat buffer;
|
||||
stat(filename, &buffer);
|
||||
|
||||
*result_mode = (int) (buffer.st_mode & 0777);
|
||||
*result_size = (size_t) buffer.st_size;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
static_filesystem_add_dir(
|
||||
struct static_filesystem * filesystem,
|
||||
size_t parent,
|
||||
char const * name
|
||||
)
|
||||
{
|
||||
struct static_filesystem_entry * entry = static_filesystem_get_entry_by_name(filesystem, parent, name);
|
||||
if (NULL == entry)
|
||||
{
|
||||
entry = static_filesystem_add_entry(filesystem);
|
||||
entry->parent = parent;
|
||||
entry->is_file = false;
|
||||
entry->mode = 0555;
|
||||
entry->name = strdup(name);
|
||||
entry->user_data = entry;
|
||||
entry->read = &static_filesystem_entry_read;
|
||||
entry->get_info = &static_filesystem_entry_get_info;
|
||||
entry->size = 0;
|
||||
entry->content = NULL;
|
||||
}
|
||||
|
||||
return entry->inode;
|
||||
}
|
||||
|
||||
static size_t
|
||||
static_filesystem_make_parent(
|
||||
struct static_filesystem * filesystem,
|
||||
struct path * path)
|
||||
{
|
||||
size_t result = STATIC_FILSYSTEM_INODE_ROOT;
|
||||
|
||||
size_t count = path_element_count(path);
|
||||
if (0 < count)
|
||||
{
|
||||
for(size_t i = 0; i < (count - 1); i++)
|
||||
{
|
||||
char const * name = path_get_element(path, i);
|
||||
result = static_filesystem_add_dir(filesystem, result, name);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
static_filesystem_stat(
|
||||
struct static_filesystem_entry * entry,
|
||||
struct stat * stat
|
||||
)
|
||||
{
|
||||
memset(stat, 0, sizeof(struct stat));
|
||||
|
||||
int mode;
|
||||
size_t size;
|
||||
entry->get_info(entry->user_data, &mode, &size);
|
||||
|
||||
stat->st_ino = entry->inode;
|
||||
stat->st_size = entry->size;
|
||||
stat->st_mode = entry->mode & 0777;
|
||||
stat->st_mode |= (entry->is_file) ? S_IFREG: S_IFDIR;
|
||||
}
|
||||
|
||||
static void static_filesystem_lookup(
|
||||
struct wfp_request * request,
|
||||
ino_t parent,
|
||||
char const * name,
|
||||
void * user_data)
|
||||
{
|
||||
struct static_filesystem * filesystem = user_data;
|
||||
struct static_filesystem_entry * entry = static_filesystem_get_entry_by_name(filesystem, parent, name);
|
||||
|
||||
if (NULL != entry)
|
||||
{
|
||||
struct stat stat;
|
||||
static_filesystem_stat(entry, &stat);
|
||||
wfp_respond_lookup(request, &stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void static_filesystem_getattr(
|
||||
struct wfp_request * request,
|
||||
ino_t inode,
|
||||
void * user_data)
|
||||
{
|
||||
struct static_filesystem * filesystem = user_data;
|
||||
struct static_filesystem_entry * entry = static_filesystem_get_entry(filesystem, inode);
|
||||
|
||||
if (NULL != entry)
|
||||
{
|
||||
struct stat stat;
|
||||
static_filesystem_stat(entry, &stat);
|
||||
wfp_respond_getattr(request, &stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static void static_filesystem_readdir(
|
||||
struct wfp_request * request,
|
||||
ino_t directory,
|
||||
void * user_data)
|
||||
{
|
||||
struct static_filesystem * filesystem = user_data;
|
||||
struct static_filesystem_entry * dir = static_filesystem_get_entry(filesystem, directory);
|
||||
|
||||
if ((NULL != dir) && (!dir->is_file))
|
||||
{
|
||||
struct wfp_dirbuffer * buffer = wfp_dirbuffer_create();
|
||||
wfp_dirbuffer_add(buffer, ".", dir->inode);
|
||||
wfp_dirbuffer_add(buffer, "..", dir->inode);
|
||||
|
||||
for(size_t i = 0; i < filesystem->size; i++)
|
||||
{
|
||||
struct static_filesystem_entry const * entry = &filesystem->entries[i];
|
||||
if (directory == entry->parent)
|
||||
{
|
||||
wfp_dirbuffer_add(buffer, entry->name, entry->inode);
|
||||
}
|
||||
}
|
||||
|
||||
wfp_respond_readdir(request, buffer);
|
||||
wfp_dirbuffer_dispose(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static void static_filesystem_open(
|
||||
struct wfp_request * request,
|
||||
ino_t inode,
|
||||
int flags,
|
||||
void * user_data)
|
||||
{
|
||||
struct static_filesystem * filesystem = user_data;
|
||||
struct static_filesystem_entry * entry = static_filesystem_get_entry(filesystem, inode);
|
||||
|
||||
if ((NULL != entry) && (entry->is_file))
|
||||
{
|
||||
if (O_RDONLY == (flags & O_ACCMODE))
|
||||
{
|
||||
wfp_respond_open(request, 0U);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
static void static_filesystem_read(
|
||||
struct wfp_request * request,
|
||||
ino_t inode,
|
||||
uint32_t handle,
|
||||
size_t offset,
|
||||
size_t length,
|
||||
void * user_data)
|
||||
{
|
||||
(void) handle;
|
||||
|
||||
struct static_filesystem * filesystem = user_data;
|
||||
struct static_filesystem_entry * entry = static_filesystem_get_entry(filesystem, inode);
|
||||
|
||||
if ((NULL != entry) && (entry->is_file))
|
||||
{
|
||||
char buffer[STATIC_FILESYSTEM_MAX_READ_SIZE];
|
||||
size_t max_size = (length < STATIC_FILESYSTEM_MAX_READ_SIZE) ? length : STATIC_FILESYSTEM_MAX_READ_SIZE;
|
||||
|
||||
size_t count = entry->read(offset, buffer, max_size, entry->user_data);
|
||||
wfp_respond_read(request, buffer, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfp_respond_error(request, WF_BAD_NOENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct static_filesystem *
|
||||
static_filesystem_create(
|
||||
struct wfp_client_config * config)
|
||||
{
|
||||
(void) config;
|
||||
|
||||
struct static_filesystem * filesystem = malloc(sizeof(struct static_filesystem));
|
||||
if (NULL != filesystem)
|
||||
{
|
||||
filesystem->entries = malloc(sizeof(struct static_filesystem_entry) * STATIC_FILESYSTEM_DEFAULT_CAPACITY);
|
||||
filesystem->size = 0;
|
||||
filesystem->capacity = STATIC_FILESYSTEM_DEFAULT_CAPACITY;
|
||||
|
||||
static_filesystem_add_dir(filesystem, 0, "<root>");
|
||||
|
||||
wfp_client_config_set_userdata(config, filesystem);
|
||||
wfp_client_config_set_onlookup(config, &static_filesystem_lookup);
|
||||
wfp_client_config_set_ongetattr(config, &static_filesystem_getattr);
|
||||
wfp_client_config_set_onreaddir(config, &static_filesystem_readdir);
|
||||
wfp_client_config_set_onopen(config, &static_filesystem_open);
|
||||
wfp_client_config_set_onread(config, &static_filesystem_read);
|
||||
}
|
||||
|
||||
return filesystem;
|
||||
}
|
||||
|
||||
void
|
||||
static_filesystem_dispose(
|
||||
struct static_filesystem * filesystem)
|
||||
{
|
||||
for(size_t i = 0; i < filesystem->size; i++)
|
||||
{
|
||||
struct static_filesystem_entry * entry = &filesystem->entries[i];
|
||||
free(entry->name);
|
||||
free(entry->content);
|
||||
}
|
||||
|
||||
free(filesystem->entries);
|
||||
free(filesystem);
|
||||
}
|
||||
|
||||
void
|
||||
static_filesystem_add(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
int mode,
|
||||
char const * content,
|
||||
size_t length)
|
||||
{
|
||||
struct path * path_ = path_create(path);
|
||||
if (NULL != path_)
|
||||
{
|
||||
size_t parent = static_filesystem_make_parent(filesystem, path_);
|
||||
struct static_filesystem_entry * entry = static_filesystem_add_entry(filesystem);
|
||||
entry->parent = parent;
|
||||
entry->is_file = true;
|
||||
entry->name = strdup(path_get_filename(path_));
|
||||
entry->mode = mode;
|
||||
entry->size = length;
|
||||
entry->get_info = &static_filesystem_entry_get_info;
|
||||
entry->read = &static_filesystem_entry_read;
|
||||
entry->user_data = entry;
|
||||
|
||||
entry->content = malloc(length);
|
||||
memcpy(entry->content, content, length);
|
||||
|
||||
path_dispose(path_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static_filesystem_add_text(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
int mode,
|
||||
char const * content)
|
||||
{
|
||||
size_t length = strlen(content);
|
||||
static_filesystem_add(filesystem, path, mode, content, length);
|
||||
}
|
||||
|
||||
void
|
||||
static_filesystem_add_file(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
char const * filename)
|
||||
{
|
||||
struct path * path_ = path_create(path);
|
||||
if (NULL != path_)
|
||||
{
|
||||
size_t parent = static_filesystem_make_parent(filesystem, path_);
|
||||
struct static_filesystem_entry * entry = static_filesystem_add_entry(filesystem);
|
||||
entry->parent = parent;
|
||||
entry->is_file = true;
|
||||
entry->mode = 0;
|
||||
entry->content = strdup(filename);
|
||||
entry->size = 0;
|
||||
entry->name = strdup(path_get_filename(path_));
|
||||
entry->get_info = &static_filesystem_file_get_info;
|
||||
entry->read = &static_filesystem_file_read;
|
||||
entry->user_data = entry;
|
||||
|
||||
path_dispose(path_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static_filesystem_add_generic(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
static_filesystem_read_fn * read,
|
||||
static_filesystem_get_info_fn * get_info,
|
||||
void * user_data)
|
||||
{
|
||||
struct path * path_ = path_create(path);
|
||||
if (NULL != path_)
|
||||
{
|
||||
size_t parent = static_filesystem_make_parent(filesystem, path_);
|
||||
struct static_filesystem_entry * entry = static_filesystem_add_entry(filesystem);
|
||||
entry->parent = parent;
|
||||
entry->is_file = true;
|
||||
entry->mode = 0;
|
||||
entry->content = NULL;
|
||||
entry->size = 0;
|
||||
entry->name = strdup(path_get_filename(path_));
|
||||
entry->get_info = get_info;
|
||||
entry->read = read;
|
||||
entry->user_data = user_data;
|
||||
|
||||
path_dispose(path_);
|
||||
}
|
||||
}
|
||||
73
examples/src/static_filesystem/static_filesystem.h
Normal file
73
examples/src/static_filesystem/static_filesystem.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef STATIC_FILESYSTEM_H
|
||||
#define STATIC_FILESYSTEM_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stddef.h>
|
||||
#else
|
||||
#include <cstddef>
|
||||
using ::std::size_t;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wfp_client_config;
|
||||
struct wfp_static_filesystem;
|
||||
|
||||
typedef size_t
|
||||
static_filesystem_read_fn(
|
||||
size_t offset,
|
||||
char * buffer,
|
||||
size_t buffer_size,
|
||||
void * user_data);
|
||||
|
||||
typedef void
|
||||
static_filesystem_get_info_fn(
|
||||
void * user_data,
|
||||
int * result_mode,
|
||||
size_t * result_size);
|
||||
|
||||
extern struct static_filesystem *
|
||||
static_filesystem_create(
|
||||
struct wfp_client_config * config);
|
||||
|
||||
extern void
|
||||
static_filesystem_dispose(
|
||||
struct static_filesystem * filesystem);
|
||||
|
||||
extern void
|
||||
static_filesystem_add(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
int mode,
|
||||
char const * content,
|
||||
size_t length);
|
||||
|
||||
extern void
|
||||
static_filesystem_add_text(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
int mode,
|
||||
char const * content);
|
||||
|
||||
extern void
|
||||
static_filesystem_add_file(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
char const * filename);
|
||||
|
||||
extern void
|
||||
static_filesystem_add_generic(
|
||||
struct static_filesystem * filesystem,
|
||||
char const * path,
|
||||
static_filesystem_read_fn * read,
|
||||
static_filesystem_get_info_fn * get_info,
|
||||
void * user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
10
examples/subprojects/jansson.wrap
Normal file
10
examples/subprojects/jansson.wrap
Normal file
@@ -0,0 +1,10 @@
|
||||
[wrap-file]
|
||||
directory = jansson-2.11
|
||||
|
||||
source_url = http://www.digip.org/jansson/releases/jansson-2.11.tar.bz2
|
||||
source_filename = jansson-2.11.tar.bz2
|
||||
source_hash = 783132e2fc970feefc2fa54199ef65ee020bd8e0e991a78ea44b8586353a0947
|
||||
|
||||
patch_url = https://wrapdb.mesonbuild.com/v1/projects/jansson/2.11/3/get_zip
|
||||
patch_filename = jansson-2.11-3-wrap.zip
|
||||
patch_hash = 0bcac510994890048d42658c674e33dd7d88715fc1e3bf49d10012f57b0e0020
|
||||
6
examples/subprojects/libwebsockets.wrap
Normal file
6
examples/subprojects/libwebsockets.wrap
Normal file
@@ -0,0 +1,6 @@
|
||||
[wrap-file]
|
||||
directory = libwebsockets-4.0.13
|
||||
|
||||
source_url = https://github.com/warmcat/libwebsockets/archive/v4.0.13.zip
|
||||
source_filename = v4.0.13.zip
|
||||
source_hash = 0914ea3fdec496daf6b6a5c00f7ba1b52eb8cc3d55b66685df92920b232fd7a5
|
||||
6
examples/subprojects/webfuse.wrap
Normal file
6
examples/subprojects/webfuse.wrap
Normal file
@@ -0,0 +1,6 @@
|
||||
[wrap-file]
|
||||
directory = webfuse-0.3.1
|
||||
|
||||
source_url = https://github.com/falk-werner/webfuse/archive/v0.3.1.tar.gz
|
||||
source_filename = v0.3.1.tar.gz
|
||||
source_hash = 46624b5f29e8f87dd1aebfce3b13ca87e766bc59546b6e5f49665d2f8c555d62
|
||||
Reference in New Issue
Block a user