commit
76a0469f40
@ -1,348 +1,63 @@
|
||||
cmake_minimum_required (VERSION 3.10)
|
||||
project(webfuse VERSION 0.2.0 DESCRIPTION "Websocket filesystem based on libfuse")
|
||||
project(webfuse VERSION 0.3.0 DESCRIPTION "Websocket filesystem based on libfuse")
|
||||
|
||||
option(WITHOUT_TESTS "disable unit tests" OFF)
|
||||
option(WITHOUT_EXAMPLE "disable example" OFF)
|
||||
option(WITHOUT_TESTS "disable unit tests" OFF)
|
||||
option(WITHOUT_ADAPTER "disable adapter library" OFF)
|
||||
option(WITHOUT_PROVIDER "disable provider library" OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(coverage)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(FUSE3 REQUIRED fuse3)
|
||||
pkg_check_modules(LWS REQUIRED libwebsockets)
|
||||
pkg_check_modules(JANSSON REQUIRED jansson)
|
||||
pkg_check_modules(UUID REQUIRED uuid)
|
||||
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(C_WARNINGS -Wall -Wextra)
|
||||
set(C_WARNINGS -Wall -Wextra -Werror)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
|
||||
add_definitions(
|
||||
-pg
|
||||
--coverage
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs")
|
||||
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
"include"
|
||||
${FUSE3_INCLUDE_DIRS}
|
||||
${LWS_INCLUDE_DIRS}
|
||||
${JANSSON_INCLUDE_DIRS}
|
||||
${UUID_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(EXTRA_LIBS
|
||||
${EXTRA_LIBS}
|
||||
${FUSE3_LIBRARIES}
|
||||
${LWS_LIBRARIES}
|
||||
${JANSSON_LIBRARIES}
|
||||
${UUID_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
|
||||
add_compile_options(
|
||||
${C_WARNINGS}
|
||||
${FUSE3_CFLAGS_OTHER}
|
||||
${LWS_CFLAGS_OTHER}
|
||||
${JANSSON_CFLAGS_OTHER}
|
||||
${UUID_CFLAGS_OTHER}
|
||||
"-pthread"
|
||||
)
|
||||
|
||||
# libwebfuse-core
|
||||
|
||||
add_library(webfuse-core STATIC
|
||||
lib/webfuse/core/slist.c
|
||||
lib/webfuse/core/message.c
|
||||
lib/webfuse/core/message_queue.c
|
||||
lib/webfuse/core/status.c
|
||||
lib/webfuse/core/string.c
|
||||
lib/webfuse/core/path.c
|
||||
lib/webfuse/core/lws_log.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-core PROPERTIES OUTPUT_NAME webfuse-core)
|
||||
target_include_directories(webfuse-core PUBLIC lib)
|
||||
set_target_properties(webfuse-core PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
|
||||
install(DIRECTORY include/webfuse/core DESTINATION include/webfuse)
|
||||
|
||||
|
||||
# libwebfuse-adapter
|
||||
|
||||
add_library(webfuse-adapter-static STATIC
|
||||
lib/webfuse/adapter/api.c
|
||||
lib/webfuse/adapter/impl/filesystem.c
|
||||
lib/webfuse/adapter/impl/server.c
|
||||
lib/webfuse/adapter/impl/server_config.c
|
||||
lib/webfuse/adapter/impl/server_protocol.c
|
||||
lib/webfuse/adapter/impl/session.c
|
||||
lib/webfuse/adapter/impl/session_manager.c
|
||||
lib/webfuse/adapter/impl/authenticator.c
|
||||
lib/webfuse/adapter/impl/authenticators.c
|
||||
lib/webfuse/adapter/impl/credentials.c
|
||||
lib/webfuse/adapter/impl/operations.c
|
||||
lib/webfuse/adapter/impl/time/timepoint.c
|
||||
lib/webfuse/adapter/impl/time/timer.c
|
||||
lib/webfuse/adapter/impl/time/timeout_manager.c
|
||||
lib/webfuse/adapter/impl/operation/lookup.c
|
||||
lib/webfuse/adapter/impl/operation/getattr.c
|
||||
lib/webfuse/adapter/impl/operation/readdir.c
|
||||
lib/webfuse/adapter/impl/operation/open.c
|
||||
lib/webfuse/adapter/impl/operation/close.c
|
||||
lib/webfuse/adapter/impl/operation/read.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/proxy.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/server.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/method.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/request.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/response.c
|
||||
lib/webfuse/adapter/impl/jsonrpc/util.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-adapter-static PROPERTIES OUTPUT_NAME webfuse-adapter)
|
||||
set_target_properties(webfuse-adapter-static PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
target_include_directories(webfuse-adapter-static PUBLIC lib)
|
||||
|
||||
add_library(webfuse-adapter SHARED
|
||||
lib/webfuse/adapter/api.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-adapter PROPERTIES VERSION ${PROJECT_VERSION})
|
||||
set_target_properties(webfuse-adapter PROPERTIES SOVERSION 0)
|
||||
set_target_properties(webfuse-adapter PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(webfuse-adapter PROPERTIES COMPILE_DEFINITIONS "WF_API=WF_EXPORT")
|
||||
|
||||
target_link_libraries(webfuse-adapter PRIVATE webfuse-adapter-static webfuse-core)
|
||||
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/libwebfuse-adapter.pc"
|
||||
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
|
||||
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${exec_prefix}/lib${LIB_SUFFIX}
|
||||
includedir=\${prefix}/include
|
||||
Name: libwebfuse
|
||||
Description: Websockets filesystem server library
|
||||
Version: ${PROJECT_VERSION}
|
||||
|
||||
Libs: -L\${libdir} -lwebfuse-adapter -l${FUSE3_LIBRARIES} -l${LWS_LIBRARIES} -l${JANSSON_LIBRARIES}
|
||||
Cflags: -I\${includedir}"
|
||||
)
|
||||
|
||||
install(TARGETS webfuse-adapter DESTINATION lib${LIB_SUFFIX})
|
||||
install(FILES include/webfuse_adapter.h DESTINATION include)
|
||||
install(DIRECTORY include/webfuse/adapter DESTINATION include/webfuse)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/libwebfuse-adapter.pc" DESTINATION lib${LIB_SUFFIX}/pkgconfig)
|
||||
|
||||
#libwebfuse-provider
|
||||
|
||||
add_library(webfuse-provider-static STATIC
|
||||
lib/webfuse/provider/api.c
|
||||
lib/webfuse/provider/impl/url.c
|
||||
lib/webfuse/provider/impl/client.c
|
||||
lib/webfuse/provider/impl/client_config.c
|
||||
lib/webfuse/provider/impl/client_protocol.c
|
||||
lib/webfuse/provider/impl/provider.c
|
||||
lib/webfuse/provider/impl/request.c
|
||||
lib/webfuse/provider/impl/dirbuffer.c
|
||||
lib/webfuse/provider/impl/operation/lookup.c
|
||||
lib/webfuse/provider/impl/operation/getattr.c
|
||||
lib/webfuse/provider/impl/operation/readdir.c
|
||||
lib/webfuse/provider/impl/operation/open.c
|
||||
lib/webfuse/provider/impl/operation/close.c
|
||||
lib/webfuse/provider/impl/operation/read.c
|
||||
lib/webfuse/provider/impl/static_filesystem.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-provider-static PROPERTIES OUTPUT_NAME webfuse-provider)
|
||||
set_target_properties(webfuse-provider-static PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
target_include_directories(webfuse-provider-static PUBLIC lib)
|
||||
|
||||
add_library(webfuse-provider SHARED
|
||||
lib/webfuse/provider/api.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-provider PROPERTIES VERSION ${PROJECT_VERSION})
|
||||
set_target_properties(webfuse-provider PROPERTIES SOVERSION 0)
|
||||
set_target_properties(webfuse-provider PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(webfuse-provider PROPERTIES COMPILE_DEFINITIONS "WFP_API=WFP_EXPORT")
|
||||
|
||||
target_include_directories(webfuse-provider PUBLIC lib)
|
||||
target_link_libraries(webfuse-provider PRIVATE webfuse-provider-static webfuse-core)
|
||||
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/libwebfuse-provider.pc"
|
||||
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${exec_prefix}/lib${LIB_SUFFIX}
|
||||
includedir=\${prefix}/include
|
||||
Name: libwebfuse-provider
|
||||
Description: Provider library for websockets filesystem
|
||||
Version: ${PROJECT_VERSION}
|
||||
|
||||
Libs: -L\${libdir} -lwebfuse-provider -l${LWS_LIBRARIES} -l${JANSSON_LIBRARIES}
|
||||
Cflags: -I\${includedir}"
|
||||
)
|
||||
|
||||
install(TARGETS webfuse-provider DESTINATION lib${LIB_SUFFIX})
|
||||
install(FILES include/webfuse_provider.h DESTINATION include)
|
||||
install(DIRECTORY include/webfuse/provider DESTINATION include/webfuse)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/libwebfuse-provider.pc" DESTINATION lib${LIB_SUFFIX}/pkgconfig)
|
||||
|
||||
|
||||
# examples
|
||||
|
||||
pkg_check_modules(OPENSSL REQUIRED openssl)
|
||||
include(webfuse_core)
|
||||
include(webfuse_adapter)
|
||||
include(webfuse_provider)
|
||||
include(unit_tests)
|
||||
|
||||
if(NOT WITHOUT_EXAMPLE)
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
||||
set(CPACK_DESCRIPTION "Websocket filesystem based on libfuse")
|
||||
#set(CPACK_COMPONENTS_ALL libraries)
|
||||
set(CPACK_DEB_COMPONENT_INSTALL ON)
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Falk Werner")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
|
||||
# libuserdb
|
||||
set(CPACK_DEBIAN_LIBRARIES_FILE_NAME "webfuse_${PROJECT_VERSION}_${CMAKE_SYSTEM_NAME}.deb")
|
||||
set(CPACK_DEBIAN_LIBRARIES_PACKAGE_NAME "webfuse")
|
||||
|
||||
add_library(userdb STATIC
|
||||
example/lib/userdb/src/userdb.c
|
||||
)
|
||||
|
||||
target_include_directories(userdb PUBLIC
|
||||
example/lib/userdb/include
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${JANSSON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_compile_options(userdb PUBLIC ${OPENSSL_CFLAGS_OTHER})
|
||||
|
||||
# daemon
|
||||
|
||||
add_executable(webfused
|
||||
example/daemon/main.c
|
||||
)
|
||||
|
||||
target_link_libraries(webfused PUBLIC webfuse-adapter userdb ${OPENSSL_LIBRARIES} ${EXTRA_LIBS})
|
||||
target_compile_options(webfused PUBLIC ${OPENSSL_CFLAGS_OTHER})
|
||||
|
||||
# provider
|
||||
|
||||
add_executable(webfuse-provider-app
|
||||
example/provider/main.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-provider-app PROPERTIES OUTPUT_NAME webfuse-provider)
|
||||
|
||||
target_link_libraries(webfuse-provider-app PUBLIC webfuse-provider ${EXTRA_LIBS})
|
||||
target_include_directories(webfuse-provider-app PUBLIC ${EXTRA_INCLUDE_DIRS})
|
||||
|
||||
# static-filesystem-provider
|
||||
|
||||
add_executable(static-filesystem-provider
|
||||
example/provider/static_filesystem.c
|
||||
)
|
||||
|
||||
target_link_libraries(static-filesystem-provider PUBLIC webfuse-provider ${EXTRA_LIBS})
|
||||
target_include_directories(static-filesystem-provider PUBLIC ${EXTRA_INCLUDE_DIRS})
|
||||
target_compile_options(static-filesystem-provider PUBLIC ${EXTRA_CFLAGS})
|
||||
|
||||
# webfuse-passwd
|
||||
|
||||
add_executable(webfuse-passwd
|
||||
example/passwd/main.c
|
||||
)
|
||||
|
||||
target_link_libraries(webfuse-passwd PUBLIC
|
||||
userdb
|
||||
${OPENSSL_LIBRARIES}
|
||||
${JANSSON_LIBRARIES}
|
||||
)
|
||||
|
||||
target_include_directories(webfuse-passwd PUBLIC
|
||||
example/passwd
|
||||
example/lib/userdb/include
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${JANSSON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_compile_options(webfuse-passwd PUBLIC ${OPENSSL_CFLAGS_OTHER})
|
||||
|
||||
|
||||
endif(NOT WITHOUT_EXAMPLE)
|
||||
|
||||
# tests
|
||||
|
||||
if(NOT WITHOUT_TESTS)
|
||||
|
||||
include (CTest)
|
||||
|
||||
pkg_check_modules(GTEST gtest_main)
|
||||
include(GoogleTest)
|
||||
pkg_check_modules(GMOCK gmock)
|
||||
|
||||
add_executable(alltests
|
||||
test/msleep.cc
|
||||
test/die_if.cc
|
||||
test/mock_authenticator.cc
|
||||
test/mock_request.cc
|
||||
test/core/test_container_of.cc
|
||||
test/core/test_string.cc
|
||||
test/core/test_slist.cc
|
||||
test/core/test_path.cc
|
||||
test/core/test_status.cc
|
||||
test/core/test_message.cc
|
||||
test/core/test_message_queue.cc
|
||||
test/adapter/test_response_parser.cc
|
||||
test/adapter/test_server.cc
|
||||
test/adapter/test_timepoint.cc
|
||||
test/adapter/test_timer.cc
|
||||
test/adapter/test_credentials.cc
|
||||
test/adapter/test_authenticator.cc
|
||||
test/adapter/test_authenticators.cc
|
||||
test/adapter/test_fuse_req.cc
|
||||
test/adapter/jsonrpc/test_util.cc
|
||||
test/adapter/jsonrpc/test_is_request.cc
|
||||
test/adapter/jsonrpc/test_request.cc
|
||||
test/adapter/jsonrpc/test_is_response.cc
|
||||
test/adapter/jsonrpc/test_response.cc
|
||||
test/adapter/jsonrpc/test_server.cc
|
||||
test/adapter/jsonrpc/test_proxy.cc
|
||||
test/provider/test_url.cc
|
||||
test/provider/test_static_filesystem.cc
|
||||
test/integration/test_integration.cc
|
||||
test/integration/server.cc
|
||||
test/integration/provider.cc
|
||||
)
|
||||
|
||||
target_link_libraries(alltests PUBLIC webfuse-adapter-static webfuse-provider-static webfuse-core ${EXTRA_LIBS} ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES})
|
||||
target_include_directories(alltests PUBLIC test lib ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS})
|
||||
target_compile_options(alltests PUBLIC ${GMOCK_CFLAGS} ${GTEST_CFLAGS})
|
||||
|
||||
enable_testing()
|
||||
gtest_discover_tests(alltests TEST_PREFIX alltests:)
|
||||
|
||||
add_custom_target(coverage
|
||||
./alltests
|
||||
COMMAND mkdir -p coverage
|
||||
COMMAND lcov --capture --directory . --output-file coverage/lcov.info
|
||||
COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info
|
||||
COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info
|
||||
)
|
||||
add_dependencies(coverage alltests)
|
||||
|
||||
add_custom_target(coverage-report
|
||||
COMMAND genhtml coverage/lcov.info --output-directory coverage/report
|
||||
)
|
||||
add_dependencies(coverage-report coverage)
|
||||
set(CPACK_DEBIAN_HEADERS_FILE_NAME "webfuse-dev_${PROJECT_VERSION}_${CMAKE_SYSTEM_NAME}.deb")
|
||||
set(CPACK_DEBIAN_HEADERS_PACKAGE_NAME "webfuse-dev")
|
||||
set(CPACK_DEBIAN_HEADERS_PACKAGE_DEPENDS "webfuse")
|
||||
|
||||
endif(NOT WITHOUT_TESTS)
|
||||
include(CPack)
|
@ -0,0 +1,333 @@
|
||||
# Doxyfile 1.8.13
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "webfuse"
|
||||
PROJECT_NUMBER = 0.3.0
|
||||
PROJECT_BRIEF = "Websocket filesystem based on libfuse"
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = "doc/api"
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = README.md \
|
||||
doc/build.md doc/protocol.md doc/api.md \
|
||||
include
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = NO
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_OPTIONS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX = wf_ wfp_
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
@ -0,0 +1,30 @@
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
"${CMAKE_C_FLAGS_DEBUG} -pg --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds"
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -pg --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE
|
||||
)
|
||||
|
||||
mark_as_advanced(
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
)
|
@ -0,0 +1,136 @@
|
||||
if(NOT WITHOUT_TESTS AND NOT WITHOUT_ADAPTER AND NOT WITHOUT_PROVIDER)
|
||||
|
||||
set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1")
|
||||
include (CTest)
|
||||
|
||||
add_executable(fs_check
|
||||
test/webfuse/tests/integration/fs_check.c
|
||||
)
|
||||
|
||||
pkg_check_modules(GTEST gtest_main)
|
||||
include(GoogleTest)
|
||||
pkg_check_modules(GMOCK gmock)
|
||||
|
||||
add_executable(alltests
|
||||
test/webfuse/tests/core/jsonrpc/mock_timer_callback.cc
|
||||
test/webfuse/tests/core/jsonrpc/mock_timer.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_is_request.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_request.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_is_response.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_response.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_server.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_proxy.cc
|
||||
test/webfuse/tests/core/jsonrpc/test_response_parser.cc
|
||||
test/webfuse/tests/core/timer/test_timepoint.cc
|
||||
test/webfuse/tests/core/timer/test_timer.cc
|
||||
test/webfuse/utils/tempdir.cc
|
||||
test/webfuse/utils/file_utils.cc
|
||||
test/webfuse/utils/timeout_watcher.cc
|
||||
test/webfuse/utils/path.c
|
||||
test/webfuse/utils/static_filesystem.c
|
||||
test/webfuse/utils/ws_server.cc
|
||||
test/webfuse/mocks/fake_invokation_context.cc
|
||||
test/webfuse/mocks/mock_authenticator.cc
|
||||
test/webfuse/mocks/mock_request.cc
|
||||
test/webfuse/mocks/mock_provider_client.cc
|
||||
test/webfuse/mocks/mock_provider.cc
|
||||
test/webfuse/mocks/mock_fuse.cc
|
||||
test/webfuse/mocks/mock_operation_context.cc
|
||||
test/webfuse/mocks/mock_jsonrpc_proxy.cc
|
||||
test/webfuse//tests/core/test_util.cc
|
||||
test/webfuse/tests/core/test_container_of.cc
|
||||
test/webfuse/tests/core/test_string.cc
|
||||
test/webfuse/tests/core/test_slist.cc
|
||||
test/webfuse/tests/core/test_base64.cc
|
||||
test/webfuse/tests/core/test_status.cc
|
||||
test/webfuse/tests/core/test_message.cc
|
||||
test/webfuse/tests/core/test_message_queue.cc
|
||||
test/webfuse/tests/adapter/test_server.cc
|
||||
test/webfuse/tests/adapter/test_server_config.cc
|
||||
test/webfuse/tests/adapter/test_credentials.cc
|
||||
test/webfuse/tests/adapter/test_authenticator.cc
|
||||
test/webfuse/tests/adapter/test_authenticators.cc
|
||||
test/webfuse/tests/adapter/test_mountpoint.cc
|
||||
test/webfuse/tests/adapter/test_fuse_req.cc
|
||||
test/webfuse/tests/adapter/operation/test_context.cc
|
||||
test/webfuse/tests/adapter/operation/test_open.cc
|
||||
test/webfuse/tests/adapter/operation/test_close.cc
|
||||
test/webfuse/tests/adapter/operation/test_read.cc
|
||||
test/webfuse/tests/adapter/operation/test_readdir.cc
|
||||
test/webfuse/tests/adapter/operation/test_getattr.cc
|
||||
test/webfuse/tests/adapter/operation/test_lookup.cc
|
||||
test/webfuse/tests/provider/test_url.cc
|
||||
test/webfuse/tests/provider/test_client_protocol.cc
|
||||
test/webfuse/tests/provider/operation/test_close.cc
|
||||
test/webfuse/tests/provider/operation/test_getattr.cc
|
||||
test/webfuse/tests/provider/operation/test_lookup.cc
|
||||
test/webfuse/tests/provider/operation/test_open.cc
|
||||
test/webfuse/tests/provider/operation/test_read.cc
|
||||
test/webfuse/tests/provider/operation/test_readdir.cc
|
||||
test/webfuse/tests/integration/test_lowlevel.cc
|
||||
test/webfuse/tests/integration/test_integration.cc
|
||||
test/webfuse/tests/integration/file.cc
|
||||
test/webfuse/tests/integration/server.cc
|
||||
test/webfuse/tests/integration/provider.cc
|
||||
)
|
||||
|
||||
target_link_libraries(alltests PUBLIC
|
||||
-Wl,--wrap=wf_timer_manager_create
|
||||
-Wl,--wrap=wf_timer_manager_dispose
|
||||
-Wl,--wrap=wf_timer_manager_check
|
||||
-Wl,--wrap=wf_timer_create
|
||||
-Wl,--wrap=wf_timer_dispose
|
||||
-Wl,--wrap=wf_timer_start
|
||||
-Wl,--wrap=wf_timer_cancel
|
||||
-Wl,--wrap=wf_impl_operation_context_get_proxy
|
||||
-Wl,--wrap=wf_jsonrpc_proxy_vinvoke
|
||||
-Wl,--wrap=wf_jsonrpc_proxy_vnotify
|
||||
-Wl,--wrap=fuse_req_userdata
|
||||
-Wl,--wrap=fuse_reply_open
|
||||
-Wl,--wrap=fuse_reply_err
|
||||
-Wl,--wrap=fuse_reply_buf
|
||||
-Wl,--wrap=fuse_reply_attr
|
||||
-Wl,--wrap=fuse_reply_entry
|
||||
-Wl,--wrap=fuse_req_ctx
|
||||
|
||||
webfuse-adapter-static
|
||||
webfuse-provider-static
|
||||
webfuse-core
|
||||
${FUSE3_LIBRARIES}
|
||||
${LWS_LIBRARIES}
|
||||
${JANSSON_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${GMOCK_LIBRARIES}
|
||||
${GTEST_LIBRARIES}
|
||||
)
|
||||
|
||||
target_include_directories(alltests PUBLIC test lib ${FUSE3_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS})
|
||||
target_compile_options(alltests PUBLIC ${FUSE3_CFLAGS_OTHER} ${GMOCK_CFLAGS} ${GTEST_CFLAGS})
|
||||
|
||||
add_custom_command(OUTPUT server-key.pem
|
||||
COMMAND openssl req -x509 -newkey rsa:4096 -keyout server-key.pem -out server-cert.pem -days 365 -nodes -batch -subj '/CN=localhost'
|
||||
COMMAND openssl req -x509 -newkey rsa:4096 -keyout client-key.pem -out client-cert.pem -days 365 -nodes -batch -subj '/CN=localhost'
|
||||
)
|
||||
|
||||
add_custom_target(gen-tls DEPENDS server-key.pem)
|
||||
add_dependencies(alltests gen-tls)
|
||||
|
||||
enable_testing()
|
||||
gtest_discover_tests(alltests TEST_PREFIX alltests:)
|
||||
|
||||
add_custom_target(coverage
|
||||
mkdir -p coverage
|
||||
COMMAND lcov --initial --capture --directory . --output-file coverage/lcov_base.info --rc lcov_branch_coverage=1
|
||||
COMMAND ./alltests
|
||||
COMMAND lcov --capture --directory . --output-file coverage/lcov.info --rc lcov_branch_coverage=1
|
||||
COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info --rc lcov_branch_coverage=1
|
||||
COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info --rc lcov_branch_coverage=1
|
||||
)
|
||||
add_dependencies(coverage alltests)
|
||||
|
||||
add_custom_target(coverage-report
|
||||
COMMAND genhtml --branch-coverage --highlight --legend coverage/lcov.info --output-directory coverage/report
|
||||
)
|
||||
add_dependencies(coverage-report coverage)
|
||||
|
||||
endif(NOT WITHOUT_TESTS AND NOT WITHOUT_ADAPTER AND NOT WITHOUT_PROVIDER)
|
@ -0,0 +1,79 @@
|
||||
if(NOT WITHOUT_ADAPTER)
|
||||
|
||||
pkg_check_modules(FUSE3 REQUIRED fuse3)
|
||||
|
||||
add_library(webfuse-adapter-static STATIC
|
||||
lib/webfuse/adapter/api.c
|
||||
lib/webfuse/adapter/impl/filesystem.c
|
||||
lib/webfuse/adapter/impl/server.c
|
||||
lib/webfuse/adapter/impl/server_config.c
|
||||
lib/webfuse/adapter/impl/server_protocol.c
|
||||
lib/webfuse/adapter/impl/session.c
|
||||
lib/webfuse/adapter/impl/session_manager.c
|
||||
lib/webfuse/adapter/impl/authenticator.c
|
||||
lib/webfuse/adapter/impl/authenticators.c
|
||||
lib/webfuse/adapter/impl/credentials.c
|
||||
lib/webfuse/adapter/impl/mountpoint.c
|
||||
lib/webfuse/adapter/impl/mountpoint_factory.c
|
||||
lib/webfuse/adapter/impl/operation/context.c
|
||||
lib/webfuse/adapter/impl/operation/lookup.c
|
||||
lib/webfuse/adapter/impl/operation/getattr.c
|
||||
lib/webfuse/adapter/impl/operation/readdir.c
|
||||
lib/webfuse/adapter/impl/operation/open.c
|
||||
lib/webfuse/adapter/impl/operation/close.c
|
||||
lib/webfuse/adapter/impl/operation/read.c
|
||||
)
|
||||
|
||||
target_include_directories(webfuse-adapter-static PRIVATE
|
||||
lib
|
||||
${FUSE3_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_compile_options(webfuse-adapter-static PUBLIC
|
||||
${FUSE3_CFLAGS_OTHER}
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-adapter-static PROPERTIES OUTPUT_NAME webfuse-adapter)
|
||||
set_target_properties(webfuse-adapter-static PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
|
||||
add_library(webfuse-adapter SHARED
|
||||
lib/webfuse/adapter/api.c
|
||||
)
|
||||
|
||||
target_include_directories(webfuse-adapter PRIVATE
|
||||
${FUSE3_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_compile_options(webfuse-adapter PUBLIC
|
||||
${FUSE3_CFLAGS_OTHER}
|
||||
)
|
||||
|
||||
|
||||
set_target_properties(webfuse-adapter PROPERTIES VERSION ${PROJECT_VERSION})
|
||||
set_target_properties(webfuse-adapter PROPERTIES SOVERSION 0)
|
||||
set_target_properties(webfuse-adapter PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(webfuse-adapter PROPERTIES COMPILE_DEFINITIONS "WF_API=WF_EXPORT")
|
||||
|
||||
target_link_libraries(webfuse-adapter PRIVATE webfuse-adapter-static webfuse-core)
|
||||
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/libwebfuse-adapter.pc"
|
||||
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
|
||||
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${exec_prefix}/lib${LIB_SUFFIX}
|
||||
includedir=\${prefix}/include
|
||||
Name: libwebfuse
|
||||
Description: Websockets filesystem server library
|
||||
Version: ${PROJECT_VERSION}
|
||||
|
||||
Libs: -L\${libdir} -lwebfuse-adapter -l${FUSE3_LIBRARIES} -l${LWS_LIBRARIES} -l${JANSSON_LIBRARIES}
|
||||
Cflags: -I\${includedir}"
|
||||
)
|
||||
|
||||
install(TARGETS webfuse-adapter DESTINATION lib${LIB_SUFFIX} COMPONENT libraries)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/libwebfuse-adapter.pc" DESTINATION lib${LIB_SUFFIX}/pkgconfig COMPONENT libraries)
|
||||
|
||||
install(FILES include/webfuse_adapter.h DESTINATION include COMPONENT headers)
|
||||
install(DIRECTORY include/webfuse/adapter DESTINATION include/webfuse COMPONENT headers)
|
||||
|
||||
endif(NOT WITHOUT_ADAPTER)
|
@ -0,0 +1,29 @@
|
||||
# libwebfuse-core
|
||||
|
||||
add_library(webfuse-core STATIC
|
||||
lib/webfuse/core/slist.c
|
||||
lib/webfuse/core/message.c
|
||||
lib/webfuse/core/message_queue.c
|
||||
lib/webfuse/core/status.c
|
||||
lib/webfuse/core/string.c
|
||||
lib/webfuse/core/base64.c
|
||||
lib/webfuse/core/lws_log.c
|
||||
lib/webfuse/core/json_util.c
|
||||
lib/webfuse/core/timer/manager.c
|
||||
lib/webfuse/core/timer/timepoint.c
|
||||
lib/webfuse/core/timer/timer.c
|
||||
lib/webfuse/core/jsonrpc/proxy.c
|
||||
lib/webfuse/core/jsonrpc/proxy_variadic.c
|
||||
lib/webfuse/core/jsonrpc/server.c
|
||||
lib/webfuse/core/jsonrpc/method.c
|
||||
lib/webfuse/core/jsonrpc/request.c
|
||||
lib/webfuse/core/jsonrpc/response.c
|
||||
lib/webfuse/core/jsonrpc/error.c
|
||||
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-core PROPERTIES OUTPUT_NAME webfuse-core)
|
||||
target_include_directories(webfuse-core PUBLIC lib lib/wf/jsonrpc/include)
|
||||
set_target_properties(webfuse-core PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
|
||||
install(DIRECTORY include/webfuse/core DESTINATION include/webfuse COMPONENT headers)
|
@ -0,0 +1,58 @@
|
||||
if(NOT WITHOUT_PROVIDER)
|
||||
|
||||
add_library(webfuse-provider-static STATIC
|
||||
lib/webfuse/provider/api.c
|
||||
lib/webfuse/provider/impl/url.c
|
||||
lib/webfuse/provider/impl/client.c
|
||||
lib/webfuse/provider/impl/client_config.c
|
||||
lib/webfuse/provider/impl/client_protocol.c
|
||||
lib/webfuse/provider/impl/provider.c
|
||||
lib/webfuse/provider/impl/request.c
|
||||
lib/webfuse/provider/impl/dirbuffer.c
|
||||
lib/webfuse/provider/impl/credentials.c
|
||||
lib/webfuse/provider/impl/operation/lookup.c
|
||||
lib/webfuse/provider/impl/operation/getattr.c
|
||||
lib/webfuse/provider/impl/operation/readdir.c
|
||||
lib/webfuse/provider/impl/operation/open.c
|
||||
lib/webfuse/provider/impl/operation/close.c
|
||||
lib/webfuse/provider/impl/operation/read.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-provider-static PROPERTIES OUTPUT_NAME webfuse-provider)
|
||||
set_target_properties(webfuse-provider-static PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
target_include_directories(webfuse-provider-static PRIVATE
|
||||
lib
|
||||
)
|
||||
|
||||
add_library(webfuse-provider SHARED
|
||||
lib/webfuse/provider/api.c
|
||||
)
|
||||
|
||||
set_target_properties(webfuse-provider PROPERTIES VERSION ${PROJECT_VERSION})
|
||||
set_target_properties(webfuse-provider PROPERTIES SOVERSION 0)
|
||||
set_target_properties(webfuse-provider PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(webfuse-provider PROPERTIES COMPILE_DEFINITIONS "WFP_API=WFP_EXPORT")
|
||||
|
||||
target_include_directories(webfuse-provider PUBLIC lib)
|
||||
target_link_libraries(webfuse-provider PRIVATE webfuse-provider-static webfuse-core)
|
||||
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/libwebfuse-provider.pc"
|
||||
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${exec_prefix}/lib${LIB_SUFFIX}
|
||||
includedir=\${prefix}/include
|
||||
Name: libwebfuse-provider
|
||||
Description: Provider library for websockets filesystem
|
||||
Version: ${PROJECT_VERSION}
|
||||
|
||||
Libs: -L\${libdir} -lwebfuse-provider -l${LWS_LIBRARIES} -l${JANSSON_LIBRARIES}
|
||||
Cflags: -I\${includedir}"
|
||||
)
|
||||
|
||||
install(TARGETS webfuse-provider DESTINATION lib${LIB_SUFFIX} COMPONENT libraries)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/libwebfuse-provider.pc" DESTINATION lib${LIB_SUFFIX}/pkgconfig COMPONENT libraries)
|
||||
|
||||
install(FILES include/webfuse_provider.h DESTINATION include COMPONENT headers)
|
||||
install(DIRECTORY include/webfuse/provider DESTINATION include/webfuse COMPONENT headers)
|
||||
|
||||
endif(NOT WITHOUT_PROVIDER)
|
@ -0,0 +1,12 @@
|
||||
ignore:
|
||||
- test
|
||||
- lib/wf/timer/test
|
||||
- lib/wf/jsonrpc/test
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: yes
|
||||
macro: yes
|
@ -0,0 +1,55 @@
|
||||
# Webfuse API introduction
|
||||
|
||||
This introduction provides a general overview to webfuse API.
|
||||
Please refer to the [build instructions](build.md) to generate API reference documentation.
|
||||
|
||||
## Contents
|
||||
|
||||
- [Authentication](#Authentication)
|
||||
|
||||
## Authentication
|
||||
|
||||
By default, webfuse daemon will redirect each filesystem call to the first connected provider without any authentication.
|
||||
This might be good for testing purposes or when an external authentication mechanism is used. In some use cases, explicit authentication is needed. Therefore, authentication can be enabled within webfuse daemon.
|
||||
|
||||
When authentication is enabled, filesystem calls are only redirected to a connected provider, after `authenticate`
|
||||
has succeeded.
|
||||
|
||||
![authenticate](authenticate.png)
|
||||
|
||||
### Enable authentication
|
||||
|
||||
Authentication is enabled, if one or more authenticators are registered via `wf_server_config`.
|
||||
|
||||
static bool authenticate(struct wf_credentials * creds, void * user_data)
|
||||
{
|
||||
char const * username = wf_credentials_get(creds, "username");
|
||||
char const * password = wf_credentials_get(creds, "password");
|
||||
|
||||
return ((NULL != username) && (0 == strcmp(username, "bob")) &&
|
||||
(NULL != password) && (0 == strcmp(password, "???")));
|
||||
}
|
||||
|
||||
wf_server_config * config = wf_server_config_create();
|
||||
wf_server_config_add_authenticator(config, "username", &authenticate, NULL);
|
||||
|
||||
wf_server * server = wf_server_create(config);
|
||||
//...
|
||||
|
||||
### Authenticator types and credentidals
|
||||
|
||||
Each authenticator is identified by a user defined string, called `type`. The type is provided by the `authenticate` request, so you can define different authenticators for different authentication types, e.g. username, certificate, token.
|
||||
|
||||
Actually, only one type is used: **username**
|
||||
**It is strongly recommended to prefix custom authenticator types with an underscore (`_`) to avoid name clashes.**
|
||||
|
||||
The `wf_credentials`struct represents a map to access credentials as key-value pairs, where both, key and value, are of type string.
|
||||
|
||||
#### username
|
||||
|
||||
The authenticator type **username** is used to authenticate via username and password. Valid credentials should contain two keys.
|
||||
|
||||
- **username** refers to the name of the user
|
||||
- **password** refers to the password of the user
|
||||
|
||||
**Note** that no further encryption is done, so this authenticator type should not be used over unencrypted websocket connections.
|
@ -0,0 +1,102 @@
|
||||
# Build Instructions
|
||||
|
||||
To install dependencies, see below.
|
||||
|
||||
cd webfuse
|
||||
mkdir .build
|
||||
cd .build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
## Build options
|
||||
|
||||
By default, unit tests are enabled. You can disable them using the following cmake options:
|
||||
|
||||
- **WITHOUT_TESTS**: disable tests
|
||||
`cmake -DWITHOUT_TESTS=ON ..`
|
||||
|
||||
Since webfuse consists of two libraries, it is possible to disable one of them
|
||||
in order to reduce build dependencies.
|
||||
*Note that unit tests are only available, when both libraries are built.*
|
||||
|
||||
- **WITHOUT_ADAPTER**: omit adapter library
|
||||
`cmake -DWITHOUT_ADAPTER=ON`
|
||||
|
||||
- **WIHTOU_PROVIDER**: omit provider library
|
||||
`cmake -DWITHOUT_PROVIDER=ON`
|
||||
|
||||
## Build using Meson (experimental)
|
||||
|
||||
_Note: Meson build support is experimental. Do not rely on it._
|
||||
|
||||
meson .build
|
||||
cd .build
|
||||
ninja build
|
||||
|
||||
_Note: Build options are not supported yet._
|
||||
|
||||
## Create API documentation
|
||||
|
||||
To create API documentation, you must install doxygen and dot first.
|
||||
After that, run doxygen in the project root directory.
|
||||
|
||||
doxygen
|
||||
|
||||
After that, you will find the API documentation in the doc/api subdirectory.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [libfuse3](https://github.com/libfuse/libfuse/)
|
||||
- [libwebsockets](https://libwebsockets.org/)
|
||||
- [Jansson](https://jansson.readthedocs.io)
|
||||
- [GoogleTest](https://github.com/google/googletest) *(optional)*
|
||||
|
||||
### Installation from source
|
||||
|
||||
#### libfuse
|
||||
|
||||
To install libfuse, meson is needed. Please refer to [meson quick guide](https://mesonbuild.com/Quick-guide.html) for setup instructions.
|
||||
|
||||
wget -O fuse-3.9.1.tar.gz https://github.com/libfuse/libfuse/archive/fuse-3.9.1.tar.gz
|
||||
tar -xf fuse-3.9.1.tar.gz
|
||||
cd libfuse-fuse-3.9.1
|
||||
mkdir .build
|
||||
cd .build
|
||||
meson ..
|
||||
ninja
|
||||
sudo ninja install
|
||||
|
||||
#### libwebsockets
|
||||
|
||||
wget -O libwebsockets-4.0.10.tar.gz https://github.com/warmcat/libwebsockets/archive/v4.0.10.tar.gz
|
||||
tar -xf libwebsockets-4.0.10.tar.gz
|
||||
cd libwebsockets-4.0.10
|
||||
mkdir .build
|
||||
cd .build
|
||||
cmake ..
|
||||
make
|
||||
sudo make install
|
||||
|
||||
#### Jansson
|
||||
|
||||
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
|
||||
|
||||
#### GoogleTest
|
||||
|
||||
Installation of GoogleTest is optional webfuse library, but required to compile tests.
|
||||
|
||||
wget -O gtest-1.10.0.tar.gz https://github.com/google/googletest/archive/release-1.10.0.tar.gz
|
||||
tar -xf gtest-1.10.0.tar.gz
|
||||
cd googletest-release-1.10.0
|
||||
mkdir .build
|
||||
cd .build
|
||||
cmake ..
|
||||
make
|
||||
sudo make install
|
Before Width: | Height: | Size: 5.2 KiB |
@ -1,16 +0,0 @@
|
||||
@startuml
|
||||
|
||||
salt
|
||||
{
|
||||
{T
|
||||
+ mount_point
|
||||
++ fwupdate
|
||||
+++ default -> 7c029f81-6bdf-4d3c-82dc-26f748164012
|
||||
+++ 7c029f81-6bdf-4d3c-82dc-26f748164012
|
||||
++++ update.raucb
|
||||
+++ f93de23b-4535-4a47-a287-a381b78a11b8
|
||||
++++ update.raucb
|
||||
}
|
||||
}
|
||||
|
||||
@enduml
|
@ -0,0 +1,253 @@
|
||||
# Webfuse Protocol
|
||||
|
||||
## Requests, responses and notifications
|
||||
|
||||
There are three types of messages, used for communication between webfuse 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/).
|
||||
|
||||
### Request
|
||||
|
||||
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 |
|
||||
|
||||
### Response
|
||||
|
||||
A response is used to answer a prior request. There are two kinds of responses:
|
||||
|
||||
#### Successful Results
|
||||
|
||||
{
|
||||
"result": <result>,
|
||||
"id": <id>
|
||||
}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- |:---------:| ----------------------- |
|
||||
| result | any | request specific result |
|
||||
| id | integer | id, same as request |
|
||||
|
||||
#### Error notifications
|
||||
|
||||
{
|
||||
"error": {
|
||||
"code": <code>
|
||||
},
|
||||
"id": <id>
|
||||
}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- |:---------:| ------------------- |
|
||||
| code | integer | error code |
|
||||
| id | integer | id, same as request |
|
||||
|
||||
#### Error codes
|
||||
|
||||
| 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_ACCESS_DENIED | 102 | access not allowed |
|
||||
|
||||
### Notification
|
||||
|
||||
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 |
|
||||
|
||||
## Requests (Adapter -> Provider)
|
||||
|
||||
### lookup
|
||||
|
||||
Retrieve information about a filesystem entry by name.
|
||||
|
||||
webfuse daemon: {"method": "lookup", "params": [<filesystem>, <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 |
|
||||
| ----------- | --------------- | ------------------------------------------- |
|
||||
| filesystem | string | name of the filesystem |
|
||||
| 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 |
|
||||
|
||||
### getattr
|
||||
|
||||
Get file attributes.
|
||||
|
||||
webfuse daemon: {"method": "getattr", "params": [<filesystem>, <inode>], "id": <id>}
|
||||
fs provider: {"result": {
|
||||
"mode" : <mode>,
|
||||
"type" : <type>,
|
||||
"size" : <size>,
|
||||
"atime": <atime>,
|
||||
"mtime": <mtime>,
|
||||
"ctime": <ctime>
|
||||
}, "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | --------------- | ------------------------------------------- |
|
||||
| filesystem | string | name of the filesystem |
|
||||
| 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 |
|
||||
|
||||
### readdir
|
||||
|
||||
Read directory contents.
|
||||
Result is an array of name-inode pairs for each entry. The generic entries
|
||||
"." and ".." should also be provided.
|
||||
|
||||
webfuse daemon: {"method": "readdir", "params": [<filesystem>, <dir_inode>], "id": <id>}
|
||||
fs provider: {"result": [
|
||||
{"name": <name>, "inode": <inode>},
|
||||
...
|
||||
], "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | --------------- | ------------------------------ |
|
||||
| filesystem | string | name of the filesystem |
|
||||
| dir_inode | integer | inode of the directory to read |
|
||||
| name | integer | name of the entry |
|
||||
| inode | integer | inode of the entry |
|
||||
|
||||
### open
|
||||
|
||||
Open a file.
|
||||
|
||||
webfuse daemon: {"method": "readdir", "params": [<filesystem>, <inode>, <flags>], "id": <id>}
|
||||
fs provider: {"result": {"handle": <handle>}, "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | ----------| ----------------------------- |
|
||||
| filesystem | string | name of the filesystem |
|
||||
| inode | integer | inode of the file |
|
||||
| flags | integer | access mode flags (see below) |
|
||||
| handle | integer | handle of the file |
|
||||
|
||||
#### Flags
|
||||
|
||||
| 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_TRUNC | 0x200 | open file to truncate |
|
||||
| O_APPEND | 0x400 | open file to append |
|
||||
|
||||
### close
|
||||
|
||||
Informs filesystem provider, that a file is closed.
|
||||
Since `close` is a notification, it cannot fail.
|
||||
|
||||
webfuse daemon: {"method": "close", "params": [<filesystem>, <inode>, <handle>, <flags>], "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | ----------| ---------------------------- |
|
||||
| filesystem | string | name of the filesystem |
|
||||
| inode | integer | inode of the file |
|
||||
| handle | integer | handle of the file |
|
||||
| flags | integer | access mode flags (see open) |
|
||||
|
||||
### read
|
||||
|
||||
Read from an open file.
|
||||
|
||||
webfuse daemon: {"method": "close", "params": [<filesystem>, <inode>, <handle>, <offset>, <length>], "id": <id>}
|
||||
fs provider: {"result": {
|
||||
"data": <data>,
|
||||
"format": <format>,
|
||||
"count": <count>
|
||||
}, "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | ----------| ----------------------------- |
|
||||
| filesystem | string | name of the filesystem |
|
||||
| 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 |
|
||||
|
||||
#### Format
|
||||
|
||||
| Format | Description |
|
||||
| ---------- | -------------------------------------------------------- |
|
||||
| "identiy" | Use data as is; note that JSON strings are UTF-8 encoded |
|
||||
| "base64" | data is base64 encoded |
|
||||
|
||||
## Requests (Provider -> Adapter)
|
||||
|
||||
### add_filesystem
|
||||
|
||||
Adds a filesystem.
|
||||
|
||||
fs provider: {"method": "add_filesystem", "params": [<name>], "id": <id>}
|
||||
webfuse daemon: {"result": {"id": <name>}, "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | ----------| ------------------------------- |
|
||||
| name | string | name and id of filesystem |
|
||||
|
||||
### authtenticate
|
||||
|
||||
Authenticate the provider.
|
||||
If authentication is enabled, a provider must be authenticated by the adapter before filesystems can be added.
|
||||
|
||||
fs provider: {"method": "authenticate", "params": [<type>, <credentials>], "id": <id>}
|
||||
webfuse daemon: {"result": {}, "id": <id>}
|
||||
|
||||
| Item | Data type | Description |
|
||||
| ----------- | ----------| ------------------------------- |
|
||||
| type | string | authentication type (see below) |
|
||||
| credentials | object | credentials to authenticate |
|
||||
|
||||
#### authentication types
|
||||
|
||||
- **username**: authenticate via username and password
|
||||
`{"username": <username>, "password": <password>}`
|
@ -1,196 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <webfuse_adapter.h>
|
||||
#include <userdb.h>
|
||||
|
||||
#define SERVICE_TIMEOUT (1 * 1000)
|
||||
|
||||
struct args
|
||||
{
|
||||
struct wf_server_config * config;
|
||||
char * passwd_path;
|
||||
bool show_help;
|
||||
};
|
||||
|
||||
static bool shutdown_requested = false;
|
||||
|
||||
static void show_help(void)
|
||||
{
|
||||
printf(
|
||||
"webfused, Copyright (c) 2019, webfuse authors <https://github.com/falk-werner/webfuse>\n"
|
||||
"Websocket file system daemon\n"
|
||||
"\n"
|
||||
"Usage: webfused [m <mount_point>] [-d <document_root] [-n <vhost_name>] [-p <port>]\n"
|
||||
" [-c <server_cert_path>] [-k <server_key_path>] [-P <passwd_path>]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"\t-m, --mount_point Path of mount point (required)\n"
|
||||
"\t-d, --document_root Path of www directory (default: not set, www disabled)\n"
|
||||
"\t-c, --server_cert_path Path of servers own certificate (default: not set, TLS disabled)\n"
|
||||
"\t-k, --server_key_path Path of servers private key (default: not set, TLS disabled)\n"
|
||||
"\t-n, --vhost_name Name of virtual host (default: \"localhost\")\n"
|
||||
"\t-p, --port Number of servers port (default: 8080)\n"
|
||||
"\t-P, --passwd_path Path to password file (default: not set, authentication disabled)\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static bool authenticate(struct wf_credentials * creds, void * user_data)
|
||||
{
|
||||
bool result = false;
|
||||
struct args * args = user_data;
|
||||
|
||||
char const * username = wf_credentials_get(creds, "username");
|
||||
char const * password = wf_credentials_get(creds, "password");
|
||||
if ((NULL != username) && (NULL != password))
|
||||
{
|
||||
struct userdb * db = userdb_create("");
|
||||
result = userdb_load(db, args->passwd_path);
|
||||
if (result)
|
||||
{
|
||||
result = userdb_check(db, username, password);
|
||||
}
|
||||
|
||||
userdb_dispose(db);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int parse_arguments(int argc, char * argv[], struct args * args)
|
||||
{
|
||||
static struct option const options[] =
|
||||
{
|
||||
{"mount_point", required_argument, NULL, 'm'},
|
||||
{"document_root", required_argument, NULL, 'd'},
|
||||
{"server_cert_path", required_argument, NULL, 'c'},
|
||||
{"server_key_path", required_argument, NULL, 'k'},
|
||||
{"vhost_name", required_argument, NULL, 'n'},
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"passwd_path", required_argument, NULL, 'P'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
bool result = EXIT_SUCCESS;
|
||||
bool finished = false;
|
||||
bool has_mountpoint = false;
|
||||
while ((!finished) && (EXIT_SUCCESS == result))
|
||||
{
|
||||
int option_index = 0;
|
||||
int const c = getopt_long(argc, argv, "m:d:c:k:n:p:P:h", options, &option_index);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case -1:
|
||||
finished = true;
|
||||
break;
|
||||
case 'h':
|
||||
args->show_help = true;
|
||||
finished = true;
|
||||
break;
|
||||
case 'm':
|
||||
wf_server_config_set_mountpoint(args->config, optarg);
|
||||
has_mountpoint = true;
|
||||
break;
|
||||
case 'd':
|
||||
wf_server_config_set_documentroot(args->config, optarg);
|
||||
break;
|
||||
case 'c':
|
||||
wf_server_config_set_certpath(args->config, optarg);
|
||||
break;
|
||||
case 'k':
|
||||
wf_server_config_set_keypath(args->config, optarg);
|
||||
break;
|
||||
case 'n':
|
||||
wf_server_config_set_vhostname(args->config, optarg);
|
||||
break;
|
||||
case 'p':
|
||||
wf_server_config_set_port(args->config, atoi(optarg));
|
||||
break;
|
||||
case 'P':
|
||||
free(args->passwd_path);
|
||||
args->passwd_path = strdup(optarg);
|
||||
wf_server_config_add_authenticator(args->config,
|
||||
"username",
|
||||
&authenticate,
|
||||
args);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "error: unknown argument\n");
|
||||
result = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((EXIT_SUCCESS == result) && (!args->show_help))
|
||||
{
|
||||
if (!has_mountpoint)
|
||||
{
|
||||
fprintf(stderr, "error: missing mount point\n");
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (EXIT_SUCCESS != result)
|
||||
{
|
||||
args->show_help = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void on_interrupt(int signal_id)
|
||||
{
|
||||
(void) signal_id;
|
||||
|
||||
shutdown_requested = true;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
struct args args;
|
||||
args.config = wf_server_config_create();
|
||||
wf_server_config_set_vhostname(args.config, "localhost");
|
||||
wf_server_config_set_port(args.config, 8080);
|
||||
args.passwd_path = NULL;
|
||||
args.show_help = false;
|
||||
|
||||
int result = parse_arguments(argc, argv, &args);
|
||||
|
||||
if (!args.show_help)
|
||||
{
|
||||
signal(SIGINT, on_interrupt);
|
||||
struct wf_server * server = wf_server_create(args.config);
|
||||
if (NULL != server)
|
||||
{
|
||||
while (!shutdown_requested)
|
||||
{
|
||||
wf_server_service(server, SERVICE_TIMEOUT);
|
||||
}
|
||||
|
||||
wf_server_dispose(server);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "fatal: unable start server\n");
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
show_help();
|
||||
}
|
||||
|
||||
free(args.passwd_path);
|
||||
wf_server_config_dispose(args.config);
|
||||
return result;
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>WebFuse Example</title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="style/main.css">
|
||||
<script type="module" src="js/startup.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="page">
|
||||
<div class="window">
|
||||
<div class="title">Connection</div>
|
||||
<div id="connection"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,287 +0,0 @@
|
||||
module.exports = {
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"accessor-pairs": "error",
|
||||
"array-bracket-newline": "error",
|
||||
"array-bracket-spacing": "error",
|
||||
"array-callback-return": "error",
|
||||
"array-element-newline": ["error", "consistent"],
|
||||
"arrow-body-style": "error",
|
||||
"arrow-parens": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"arrow-spacing": [
|
||||
"error",
|
||||
{
|
||||
"after": true,
|
||||
"before": true
|
||||
}
|
||||
],
|
||||
"block-scoped-var": "error",
|
||||
"block-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"brace-style": "off",
|
||||
"callback-return": "off",
|
||||
"camelcase": "error",
|
||||
"capitalized-comments": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"class-methods-use-this": "off",
|
||||
"comma-dangle": "error",
|
||||
"comma-spacing": [
|
||||
"error",
|
||||
{
|
||||
"after": true,
|
||||
"before": false
|
||||
}
|
||||
],
|
||||
"comma-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"complexity": "error",
|
||||
"computed-property-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"consistent-return": "error",
|
||||
"consistent-this": "error",
|
||||
"curly": "error",
|
||||
"default-case": "error",
|
||||
"dot-location": "error",
|
||||
"dot-notation": "error",
|
||||
"eol-last": "off",
|
||||
"eqeqeq": "off",
|
||||
"func-call-spacing": "error",
|
||||
"func-name-matching": "error",
|
||||
"func-names": "error",
|
||||
"func-style": [
|
||||
"error",
|
||||
"declaration"
|
||||
],
|
||||
"function-paren-newline": "error",
|
||||
"generator-star-spacing": "error",
|
||||
"global-require": "error",
|
||||
"guard-for-in": "error",
|
||||
"handle-callback-err": "error",
|
||||
"id-blacklist": "error",
|
||||
"id-length": "error",
|
||||
"id-match": "error",
|
||||
"implicit-arrow-linebreak": [
|
||||
"error",
|
||||
"beside"
|
||||
],
|
||||
"indent": "off",
|
||||
"indent-legacy": "off",
|
||||
"init-declarations": "off",
|
||||
"jsx-quotes": "error",
|
||||
"key-spacing": "off",
|
||||
"keyword-spacing": "off",
|
||||
"line-comment-position": "error",
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"lines-around-comment": "error",
|
||||
"lines-around-directive": "error",
|
||||
"lines-between-class-members": "off",
|
||||
"max-classes-per-file": "error",
|
||||
"max-depth": "error",
|
||||
"max-len": "off",
|
||||
"max-lines": "error",
|
||||
"max-lines-per-function": "off",
|
||||
"max-nested-callbacks": "error",
|
||||
"max-params": "off",
|
||||
"max-statements": "off",
|
||||
"max-statements-per-line": "off",
|
||||
"multiline-comment-style": "error",
|
||||
"new-cap": "error",
|
||||
"new-parens": "error",
|
||||
"newline-after-var": "off",
|
||||
"newline-before-return": "error",
|
||||
"newline-per-chained-call": "error",
|
||||
"no-alert": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"no-await-in-loop": "error",
|
||||
"no-bitwise": "off",
|
||||
"no-buffer-constructor": "error",
|
||||
"no-caller": "error",
|
||||
"no-catch-shadow": "error",
|
||||
"no-confusing-arrow": "error",
|
||||
"no-continue": "error",
|
||||
"no-div-regex": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-else-return": "off",
|
||||
"no-empty-function": "off",
|
||||
"no-eq-null": "error",
|
||||
"no-eval": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-extra-label": "error",
|
||||
"no-extra-parens": "off",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implicit-globals": "off",
|
||||
"no-implied-eval": "error",
|
||||
"no-inline-comments": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-iterator": "error",
|
||||
"no-label-var": "error",
|
||||
"no-labels": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-magic-numbers": "off",
|
||||
"no-misleading-character-class": "error",
|
||||
"no-mixed-operators": "error",
|
||||
"no-mixed-requires": "error",
|
||||
"no-multi-assign": "error",
|
||||
"no-multi-spaces": "off",
|
||||
"no-multi-str": "error",
|
||||
"no-multiple-empty-lines": "error",
|
||||
"no-native-reassign": "error",
|
||||
"no-negated-condition": "off",
|
||||
"no-negated-in-lhs": "error",
|
||||
"no-nested-ternary": "error",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-object": "error",
|
||||
"no-new-require": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "error",
|
||||
"no-path-concat": "error",
|
||||
"no-plusplus": "error",
|
||||
"no-process-env": "error",
|
||||
"no-process-exit": "error",
|
||||
"no-proto": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-restricted-globals": "error",
|
||||
"no-restricted-imports": "error",
|
||||
"no-restricted-modules": "error",
|
||||
"no-restricted-properties": "error",
|
||||
"no-restricted-syntax": "error",
|
||||
"no-return-assign": "error",
|
||||
"no-return-await": "error",
|
||||
"no-script-url": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-shadow": "off",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-spaced-func": "error",
|
||||
"no-sync": "error",
|
||||
"no-tabs": "off",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-ternary": "off",
|
||||
"no-throw-literal": "error",
|
||||
"no-trailing-spaces": "off",
|
||||
"no-undef-init": "error",
|
||||
"no-undefined": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-use-before-define": "error",
|
||||
"no-useless-call": "error",
|
||||
// "no-useless-catch": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-useless-rename": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-var": "error",
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"no-with": "error",
|
||||
"nonblock-statement-body-position": "error",
|
||||
"object-curly-newline": "error",
|
||||
"object-curly-spacing": "off",
|
||||
"object-shorthand": "off",
|
||||
"one-var": "off",
|
||||
"one-var-declaration-per-line": "error",
|
||||
"operator-assignment": "error",
|
||||
"operator-linebreak": "error",
|
||||
"padded-blocks": "off",
|
||||
"padding-line-between-statements": "error",
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": "off",
|
||||
"prefer-destructuring": "off",
|
||||
"prefer-numeric-literals": "off",
|
||||
"prefer-object-spread": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"prefer-reflect": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
"quote-props": "off",
|
||||
"quotes": "off",
|
||||
"radix": "error",
|
||||
"require-atomic-updates": "error",
|
||||
"require-await": "off",
|
||||
"require-jsdoc": "off",
|
||||
"require-unicode-regexp": "off",
|
||||
"rest-spread-spacing": "error",
|
||||
"semi": "error",
|
||||
"semi-spacing": "error",
|
||||
"semi-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"sort-imports": "error",
|
||||
"sort-keys": "off",
|
||||
"sort-vars": "error",
|
||||
"space-before-blocks": "error",
|
||||
"space-before-function-paren": "off",
|
||||
"space-in-parens": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"space-infix-ops": "error",
|
||||
"space-unary-ops": [
|
||||
"error",
|
||||
{
|
||||
"nonwords": false,
|
||||
"words": false
|
||||
}
|
||||
],
|
||||
"spaced-comment": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"strict": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"switch-colon-spacing": "error",
|
||||
"symbol-description": "error",
|
||||
"template-curly-spacing": "error",
|
||||
"template-tag-spacing": "error",
|
||||
"unicode-bom": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"valid-jsdoc": "error",
|
||||
"vars-on-top": "error",
|
||||
"wrap-iife": "error",
|
||||
"wrap-regex": "error",
|
||||
"yield-star-spacing": "error",
|
||||
"yoda": "off"
|
||||
}
|
||||
};
|
@ -1,93 +0,0 @@
|
||||
export class ConnectionView {
|
||||
constructor(client, provider) {
|
||||
this._provider = provider;
|
||||
this._client = client;
|
||||
this._client.onopen = () => { this._onConnectionOpened(); };
|
||||
this._client.onclose = () => { this._onConnectionClosed(); };
|
||||
|
||||
this.element = document.createElement("div");
|
||||
|
||||
const connectBox = document.createElement("div");
|
||||
this.element.appendChild(connectBox);
|
||||
|
||||
const urlLabel = document.createElement("span");
|
||||
urlLabel.textContent = "URL:";
|
||||
connectBox.appendChild(urlLabel);
|
||||
|
||||
this.urlTextbox = document.createElement("input");
|
||||
this.urlTextbox.type = "text";
|
||||
this.urlTextbox.value = window.location.href.replace(/^http/, "ws");
|
||||
connectBox.appendChild(this.urlTextbox);
|
||||
|
||||
this.connectButton = document.createElement("input");
|
||||
this.connectButton.type = "button";
|
||||
this.connectButton.value = "connect";
|
||||
this.connectButton.addEventListener("click", () => { this._onConnectButtonClicked(); });
|
||||
connectBox.appendChild(this.connectButton);
|
||||
|
||||
|
||||
const authenticateBox = document.createElement("div");
|
||||
this.element.appendChild(authenticateBox);
|
||||
|
||||
const authLabel = document.createElement("span");
|
||||
authLabel.textContent = "use authentication:";
|
||||
authenticateBox.appendChild(authLabel);
|
||||
|
||||
this.authenticateCheckbox = document.createElement("input");
|
||||
this.authenticateCheckbox.type = "checkbox";
|
||||
authenticateBox.appendChild(this.authenticateCheckbox);
|
||||
|
||||
const usernameLabel = document.createElement("span");
|
||||
usernameLabel.textContent = "user:";
|
||||
authenticateBox.appendChild(usernameLabel);
|
||||
|
||||
this.usernameTextbox = document.createElement("input");
|
||||
this.usernameTextbox.type = "text";
|
||||
this.usernameTextbox.value = "bob";
|
||||
authenticateBox.appendChild(this.usernameTextbox);
|
||||
|
||||
const passwordLabel = document.createElement("span");
|
||||
passwordLabel.textContent = "user:";
|
||||
authenticateBox.appendChild(passwordLabel);
|
||||
|
||||
this.passwordTextbox = document.createElement("input");
|
||||
this.passwordTextbox.type = "password";
|
||||
this.passwordTextbox.value = "secret";
|
||||
authenticateBox.appendChild(this.passwordTextbox);
|
||||
}
|
||||
|
||||
_onConnectButtonClicked() {
|
||||
if (!this._client.isConnected()) {
|
||||
let url = this.urlTextbox.value;
|
||||
this._client.connectTo(url);
|
||||
}
|
||||
else {
|
||||
this._client.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
_onAuthenticateButtonClicked() {
|
||||
if (this._client.isConnected()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_onConnectionOpened() {
|
||||
if (this.authenticateCheckbox.checked) {
|
||||
const username = this.usernameTextbox.value;
|
||||
const password = this.passwordTextbox.value;
|
||||
|
||||
const promise = this._client.authenticate("username", { username, password });
|
||||
promise.then(() => { this._client.addProvider("test", this._provider); });
|
||||
} else {
|
||||
this._client.addProvider("test", this._provider);
|
||||
}
|
||||
|
||||
this.connectButton.value = "disconnect";
|
||||
}
|
||||
|
||||
_onConnectionClosed() {
|
||||
this.connectButton.value = "connect";
|
||||
}
|
||||
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
|
||||
|
||||
import { BadState } from "./webfuse/bad_state.js";
|
||||
import { FileMode } from "./webfuse/file_mode.js";
|
||||
import { Provider } from "./webfuse/provider.js";
|
||||
|
||||
export class FileSystemProvider extends Provider {
|
||||
constructor(root) {
|
||||
super();
|
||||
|
||||
this.root = root;
|
||||
this._inodes = { };
|
||||
|
||||
this._walk(this.root, (entry) => { this._inodes[entry.inode] = entry; });
|
||||
}
|
||||
|
||||
_walk(node, callback) {
|
||||
callback(node);
|
||||
|
||||
const entries = node.entries;
|
||||
if (entries) {
|
||||
for(let entry of Object.entries(entries)) {
|
||||
this._walk(entry[1], callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async lookup(parent, name) {
|
||||
const parentEntry = this._inodes[parent];
|
||||
const entry = (parentEntry && parentEntry.entries && parentEntry.entries[name]) || null;
|
||||
if (entry) {
|
||||
return {
|
||||
inode: entry.inode,
|
||||
mode: entry.mode || parseInt("755", 8),
|
||||
type: entry.type || "file",
|
||||
size: entry.size || (entry.contents && entry.contents.length) || 0,
|
||||
atime: entry.atime || 0,
|
||||
mtime: entry.mtime || 0,
|
||||
ctime: entry.ctime || 0
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.NO_ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getattr(inode) {
|
||||
let entry = this._inodes[inode];
|
||||
if (entry) {
|
||||
return {
|
||||
mode: entry.mode || parseInt("755", 8),
|
||||
type: entry.type || "file",
|
||||
size: entry.size || (entry.contents && entry.contents.length) || 0,
|
||||
atime: entry.atime || 0,
|
||||
mtime: entry.mtime || 0,
|
||||
ctime: entry.ctime || 0
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.NO_ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
async readdir(inode) {
|
||||
let entry = this._inodes[inode];
|
||||
|
||||
if ((entry) && ("dir" === entry.type)) {
|
||||
let result = [
|
||||
{name: ".", inode: entry.inode},
|
||||
{name: "..", inode: entry.inode}
|
||||
];
|
||||
for(let subdir of Object.entries(entry.entries)) {
|
||||
const name = subdir[0];
|
||||
const inode = subdir[1].inode;
|
||||
result.push({name, inode});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.NO_ENTRY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async open(inode, mode) {
|
||||
let entry = this._inodes[inode];
|
||||
|
||||
if (entry.type === "file") {
|
||||
if ((mode & FileMode.ACCESS_MODE) === FileMode.READONLY) {
|
||||
return {handle: 1337};
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.NO_ACCESS);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.NO_ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
close(_inode, _handle, _mode) {
|
||||
// do nothing
|
||||
return true;
|
||||
}
|
||||
|
||||
async read(inode, handle, offset, length) {
|
||||
let entry = this._inodes[inode];
|
||||
|
||||
if (entry.type === "file") {
|
||||
const end = Math.min(offset + length, entry.contents.length);
|
||||
const data = (offset < entry.contents.length) ? entry.contents.substring(offset, end) : "";
|
||||
|
||||
return data;
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.NO_ENTRY);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "webfuse-provider",
|
||||
"version": "0.2.0",
|
||||
"description": "Provider for websocket filesystem (webfuse)",
|
||||
"main": "startup.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Falk Werner",
|
||||
"license": "LGPL-3.0"
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
import { Client } from "./webfuse/client.js";
|
||||
import { ConnectionView } from "./connection_view.js";
|
||||
import { FileSystemProvider } from "./filesystem_provider.js";
|
||||
|
||||
|
||||
function mode(value) {
|
||||
return parseInt(value, 8);
|
||||
}
|
||||
|
||||
function startup() {
|
||||
const provider = new FileSystemProvider({
|
||||
inode: 1,
|
||||
mode: mode("0755"),
|
||||
type: "dir",
|
||||
entries: {
|
||||
"hello.txt" : { inode: 2, mode: mode("0444"), type: "file", contents: "Hello, World!"},
|
||||
"say_hello.sh": { inode: 3, mode: mode("0555"), type: "file", contents: "#!/bin/sh\necho hello\n"}
|
||||
}
|
||||
});
|
||||
const client = new Client();
|
||||
const connectionView = new ConnectionView(client, provider);
|
||||
document.getElementById('connection').appendChild(connectionView.element);
|
||||
}
|
||||
|
||||
window.onload = startup;
|
@ -1,15 +0,0 @@
|
||||
export class BadState extends Error {
|
||||
static get BAD() { return 1; }
|
||||
|
||||
static get NOT_IMPLEMENTED() { return 2; }
|
||||
static get TIMEOUT() { return 3; }
|
||||
static get FORMAT() { return 4; }
|
||||
|
||||
static get NO_ENTRY() { return 101; }
|
||||
static get NO_ACCESS() { return 102; }
|
||||
|
||||
constructor(code) {
|
||||
super("Bad State");
|
||||
this.code = code;
|
||||
}
|
||||
}
|
@ -1,223 +0,0 @@
|
||||
import { BadState } from "./bad_state.js";
|
||||
|
||||
export class Client {
|
||||
static get _PROTOCOL() { return "fs"; }
|
||||
|
||||
constructor(provider) {
|
||||
this._provider = { };
|
||||
this._pendingRequests = {};
|
||||
this._id = 0;
|
||||
this._ws = null;
|
||||
this.onopen = () => { };
|
||||
this.onclose = () => { };
|
||||
this.onerror = () => { };
|
||||
}
|
||||
|
||||
connectTo(url) {
|
||||
this.disconnect();
|
||||
|
||||
this._ws = new WebSocket(url, Client._PROTOCOL);
|
||||
this._ws.onopen = this.onopen;
|
||||
this._ws.onclose = this.onclose;
|
||||
this._ws.onerror = this.onerror;
|
||||
|
||||
this._ws.onmessage = (message) => {
|
||||
this._onmessage(message);
|
||||
};
|
||||
}
|
||||
|
||||
_invokeRequest(method, params) {
|
||||
this._id += 1;
|
||||
const id = this._id;
|
||||
const request = {method, params, id};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this._pendingRequests[id] = {resolve, reject};
|
||||
this._ws.send(JSON.stringify(request));
|
||||
});
|
||||
}
|
||||
|
||||
authenticate(type, credentials) {
|
||||
return this._invokeRequest("authenticate", [type, credentials]);
|
||||
}
|
||||
|
||||
addProvider(name, provider) {
|
||||
this._provider[name] = provider;
|
||||
const request = {
|
||||
"method": "add_filesystem",
|
||||
"params": [name],
|
||||
"id": 23
|
||||
};
|
||||
|
||||
this._ws.send(JSON.stringify(request));
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this._ws) {
|
||||
this._ws.close();
|
||||
this._ws = null;
|
||||
}
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return ((this._ws) && (this._ws.readyState === WebSocket.OPEN));
|
||||
}
|
||||
|
||||
_isRequest(request) {
|
||||
const method = request.method;
|
||||
|
||||
return (("string" === typeof(method)) && ("params" in request));
|
||||
}
|
||||
|
||||
_isResponse(response) {
|
||||
const id = response.id;
|
||||
|
||||
return (("number" === typeof(id)) && (("result" in response) || ("error" in response)));
|
||||
}
|
||||
|
||||
_removePendingRequest(id) {
|
||||
let result = null;
|
||||
|
||||
if (id in this._pendingRequests) {
|
||||
result = this._pendingRequests[id];
|
||||
Reflect.deleteProperty(this._pendingRequests, id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_onmessage(message) {
|
||||
try {
|
||||
const data = JSON.parse(message.data);
|
||||
|
||||
if (this._isRequest(data)) {
|
||||
const method = data.method;
|
||||
const id = data.id;
|
||||
const params = data.params;
|
||||
|
||||
if ("number" === typeof(id)) {
|
||||
this._invoke(method, params, id);
|
||||
}
|
||||
else {
|
||||
this._notify(method, params);
|
||||
}
|
||||
}
|
||||
else if (this._isResponse(data)) {
|
||||
const id = data.id;
|
||||
const result = data.result;
|
||||
const error = data.error;
|
||||
|
||||
const request = this._removePendingRequest(id);
|
||||
if (request) {
|
||||
if (result) {
|
||||
request.resolve(result);
|
||||
}
|
||||
else {
|
||||
request.reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (ex) {
|
||||
// swallow
|
||||
}
|
||||
}
|
||||
|
||||
_invoke(method, params, id) {
|
||||
this._invokeAsync(method, params).
|
||||
then((result) => {
|
||||
const response = { result, id };
|
||||
this._ws.send(JSON.stringify(response));
|
||||
}).
|
||||
catch((ex) => {
|
||||
const code = ex.code || BadState.BAD;
|
||||
const response = {error: {code}, id};
|
||||
this._ws.send(JSON.stringify(response));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async _invokeAsync(method, params) {
|
||||
switch(method)
|
||||
{
|
||||
case "lookup":
|
||||
return this._lookup(params);
|
||||
case "getattr":
|
||||
return this._getattr(params);
|
||||
case "readdir":
|
||||
return this._readdir(params);
|
||||
case "open":
|
||||
return this._open(params);
|
||||
case "read":
|
||||
return this._read(params);
|
||||
default:
|
||||
throw new BadState(BadState.NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
|
||||
_notify(method, params) {
|
||||
switch(method) {
|
||||
case 'close':
|
||||
this._close(params);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid method: "${method}"`);
|
||||
}
|
||||
}
|
||||
|
||||
_getProvider(name) {
|
||||
if (name in this._provider) {
|
||||
return this._provider[name];
|
||||
}
|
||||
else {
|
||||
throw new Error('Unknown provider');
|
||||
}
|
||||
}
|
||||
|
||||
async _lookup([providerName, parent, name]) {
|
||||
const provider = this._getProvider(providerName);
|
||||
|
||||
return provider.lookup(parent, name);
|
||||
}
|
||||
|
||||
async _getattr([providerName, inode]) {
|
||||
const provider = this._getProvider(providerName);
|
||||
|
||||
return provider.getattr(inode);
|
||||
}
|
||||
|
||||
async _readdir([providerName, inode]) {
|
||||
const provider = this._getProvider(providerName);
|
||||
|
||||
return provider.readdir(inode);
|
||||
}
|
||||
|
||||
async _open([providerName, inode, mode]) {
|
||||
const provider = this._getProvider(providerName);
|
||||
|
||||
return provider.open(inode, mode);
|
||||
}
|
||||
|
||||
_close([providerName, inode, handle, mode]) {
|
||||
const provider = this._getProvider(providerName);
|
||||
|
||||
provider.close(inode, handle, mode);
|
||||
}
|
||||
|
||||
async _read([providerName, inode, handle, offset, length]) {
|
||||
const provider = this._getProvider(providerName);
|
||||
const data = await provider.read(inode, handle, offset, length);
|
||||
|
||||
if ("string" === typeof(data)) {
|
||||
return {
|
||||
data: btoa(data),
|
||||
format: "base64",
|
||||
count: data.length
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new BadState(BadState.BAD);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
export class FileMode {
|
||||
static get ACCESS_MODE() { return 0x003; }
|
||||
static get READONLY() { return 0x000; }
|
||||
static get WRITEONLY() { return 0x001; }
|
||||
static get READWRITE() { return 0x002; }
|
||||
static get CREATE() { return 0x040; }
|
||||
static get EXCLUSIVE() { return 0x080; }
|
||||
static get TRUNKATE() { return 0x200; }
|
||||
static get APPEND() { return 0x400; }
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
|
||||
|
||||
import { BadState } from "./bad_state.js";
|
||||
|
||||
export class Provider {
|
||||
|
||||
async lookup(_parent, _name) {
|
||||
throw new BadState(BadState.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
async getattr(_inode) {
|
||||
throw new BadState(BadState.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
async readdir(_inode) {
|
||||
throw new BadState(BadState.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
async open(_inode, _mode) {
|
||||
throw new BadState(BadState.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
close(_inode, _handle, _mode) {
|
||||
// empty
|
||||
}
|
||||
|
||||
async read(_inode, _handle, _offset, _length) {
|
||||
throw new BadState(BadState.NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
html, body {
|
||||
font-family: monospace;
|
||||
background-color: #c0c0c0;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-left: 50px;
|
||||
margin-right: 50px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.window {
|
||||
border: 1px solid black;
|
||||
background-color: black;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin-bottom: 25px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.window .title {
|
||||
text-align: center;
|
||||
color: #dba329;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #dba329;
|
||||
}
|
||||
|
||||
.commands {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.content {
|
||||
column-count: 2;
|
||||
column-width: 50%;
|
||||
}
|
||||
|
||||
.content > div {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#connection {
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
#ifndef USERDB_H
|
||||
#define USERDB_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct userdb;
|
||||
|
||||
extern struct userdb * userdb_create(
|
||||
char const * pepper);
|
||||
|
||||
extern void userdb_dispose(struct userdb * db);
|
||||
|
||||
extern bool userdb_save(
|
||||
struct userdb * db,
|
||||
char const * filename);
|
||||
|
||||
extern bool userdb_load(
|
||||
struct userdb * db,
|
||||
char const * filename);
|
||||
|
||||
extern void userdb_add(
|
||||
struct userdb * db,
|
||||
char const * username,
|
||||
char const * password);
|
||||
|
||||
extern void userdb_remove(
|
||||
struct userdb * db,
|
||||
char const * user);
|
||||
|
||||
extern bool userdb_check(
|
||||
struct userdb * db,
|
||||
char const * username,
|
||||
char const * password);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,277 +0,0 @@
|
||||
#include "userdb.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#define USERDB_HASH_ALGORITHM "sha512"
|
||||
#define USERDB_MAJOR 1
|
||||
#define USERDB_MINOR 0
|
||||
|
||||
#define USERDB_SALT_SIZE 32
|
||||
|
||||
struct userdb
|
||||
{
|
||||
json_t * users;
|
||||
char * pepper;
|
||||
char * hash_algorithm;
|
||||
};
|
||||
|
||||
static bool is_compatible(json_t * meta)
|
||||
{
|
||||
bool result = false;
|
||||
if (json_is_object(meta))
|
||||
{
|
||||
json_t * type = json_object_get(meta, "type");
|
||||
json_t * major = json_object_get(meta, "major");
|
||||
json_t * minor = json_object_get(meta, "minor");
|
||||
json_t * hash_algorithm = json_object_get(meta, "hash_algorithm");
|
||||
|
||||
result = (
|
||||
json_is_string(type) &&
|
||||
(0 == strcmp(json_string_value(type), "wf-userdb")) &&
|
||||
json_is_integer(major) &&
|
||||
(USERDB_MAJOR == json_integer_value(major)) &&
|
||||
json_is_integer(minor) &&
|
||||
json_is_string(hash_algorithm)
|
||||
);
|
||||
|
||||
if (result)
|
||||
{
|
||||
char const * algorithm = json_string_value(hash_algorithm);
|
||||
result = (NULL != EVP_get_digestbyname(algorithm));
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static char hex_char(unsigned char value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 0x00: return '0';
|
||||
case 0x01: return '1';
|
||||
case 0x02: return '2';
|
||||
case 0x03: return '3';
|
||||
case 0x04: return '4';
|
||||
case 0x05: return '5';
|
||||
case 0x06: return '6';
|
||||
case 0x07: return '7';
|
||||
case 0x08: return '8';
|
||||
case 0x09: return '9';
|
||||
case 0x0a: return 'a';
|
||||
case 0x0b: return 'b';
|
||||
case 0x0c: return 'c';
|
||||
case 0x0d: return 'd';
|
||||
case 0x0e: return 'e';
|
||||
case 0x0f: return 'f';
|
||||
default: return '?';
|
||||
}
|
||||
}
|
||||
|
||||
static char * to_hex(unsigned char const * value, size_t length)
|
||||
{
|
||||
char * result = malloc((2 * length) + 1);
|
||||
if (NULL != result)
|
||||
{
|
||||
for (size_t i = 0, j = 0; i < length; i++, j+=2)
|
||||
{
|
||||
unsigned char high = (value[i] >> 4) & 0x0f;
|
||||
unsigned char low = value[i] & 0x0f;
|
||||
|
||||
result[j ] = hex_char(high);
|
||||
result[j + 1] = hex_char(low);
|
||||
}
|
||||
|
||||
result[2 * length] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char * generate_salt(void)
|
||||
{
|
||||
unsigned char buffer[USERDB_SALT_SIZE];
|
||||
int rc = RAND_bytes(buffer, USERDB_SALT_SIZE);
|
||||
if (1 != rc)
|
||||
{
|
||||
fprintf(stderr, "fatal: failed to generate salt (OpenSSL RAND_bytes failed)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return to_hex(buffer, USERDB_SALT_SIZE);
|
||||
}
|
||||
|
||||
static char * compute_hash(
|
||||
struct userdb * db,
|
||||
char const * password,
|
||||
char const * salt)
|
||||
{
|
||||
EVP_MD const * digest = EVP_get_digestbyname(db->hash_algorithm);
|
||||
if (NULL == digest)
|
||||
{
|
||||
fprintf(stderr, "error: hash algorithm %s not supported\n", db->hash_algorithm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * result = NULL;
|
||||
unsigned int hash_size = EVP_MD_size(digest);
|
||||
unsigned char * hash = malloc(hash_size);
|
||||
|
||||
if (NULL != hash)
|
||||
{
|
||||
EVP_MD_CTX * context = EVP_MD_CTX_new();
|
||||
EVP_DigestInit_ex(context, digest, NULL);
|
||||
EVP_DigestUpdate(context, password, strlen(password));
|
||||
EVP_DigestUpdate(context, salt, strlen(salt));
|
||||
EVP_DigestUpdate(context, db->pepper, strlen(db->pepper));
|
||||
EVP_DigestFinal_ex(context, hash, &hash_size);
|
||||
EVP_MD_CTX_free(context);
|
||||
|
||||
result = to_hex(hash, hash_size);
|
||||
free(hash);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct userdb * userdb_create(
|
||||
char const * pepper)
|
||||
{
|
||||
struct userdb * db = malloc(sizeof(struct userdb));
|
||||
if (NULL != db)
|
||||
{
|
||||
db->users = json_object();
|
||||
db->pepper = strdup(pepper);
|
||||
db->hash_algorithm = strdup(USERDB_HASH_ALGORITHM);
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
void userdb_dispose(
|
||||
struct userdb * db)
|
||||
{
|
||||
json_decref(db->users);
|
||||
free(db->pepper);
|
||||
free(db->hash_algorithm);
|
||||
free(db);
|
||||
}
|
||||
|
||||
bool userdb_save(
|
||||
struct userdb * db,
|
||||
char const * filename)
|
||||
{
|
||||
json_t * container = json_object();
|
||||
|
||||
json_t * meta = json_object();
|
||||
json_object_set_new(meta, "type", json_string("wf-userdb"));
|
||||
json_object_set_new(meta, "major", json_integer(USERDB_MAJOR));
|
||||
json_object_set_new(meta, "minor", json_integer(USERDB_MINOR));
|
||||
json_object_set_new(meta, "hash_algorithm", json_string(db->hash_algorithm));
|
||||
json_object_set_new(container, "meta", meta);
|
||||
|
||||
json_object_set(container, "users", db->users);
|
||||
|
||||
int result = json_dump_file(container, filename, JSON_INDENT(2));
|
||||
json_decref(container);
|
||||
|
||||
return (0 == result);
|
||||
}
|
||||
|
||||
|
||||
bool userdb_load(
|
||||
struct userdb * db,
|
||||
char const * filename)
|
||||
{
|
||||
bool result = false;
|
||||
json_t * container = json_load_file(filename, 0, NULL);
|
||||
if (NULL != container)
|
||||
{
|
||||
json_t * meta = json_object_get(container, "meta");
|
||||
json_t * users = json_object_get(container, "users");
|
||||
|
||||
if ((is_compatible(meta)) && (json_is_object(users))) {
|
||||
json_t * hash_algorithm = json_object_get(meta, "hash_algorithm");
|
||||
free(db->hash_algorithm);
|
||||
db->hash_algorithm = strdup(json_string_value(hash_algorithm));
|
||||
|
||||
json_decref(db->users);
|
||||
json_incref(users);
|
||||
db->users = users;
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
json_decref(container);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void userdb_add(
|
||||
struct userdb * db,
|
||||
char const * username,
|
||||
char const * password)
|
||||
{
|
||||
char * salt = generate_salt();
|
||||
char * hash = compute_hash(db, password, salt);
|
||||
|
||||
json_t * user = json_object();
|
||||
json_object_set_new(user, "password_hash", json_string(hash));
|
||||
json_object_set_new(user, "salt", json_string(salt));
|
||||
|
||||
json_object_set_new(db->users, username, user);
|
||||
|
||||
free(salt);
|
||||
free(hash);
|
||||
}
|
||||
|
||||
void userdb_remove(
|
||||
struct userdb * db,
|
||||
char const * user)
|
||||
{
|
||||
json_object_del(db->users, user);
|
||||
}
|
||||
|
||||
static char const * json_object_get_string(
|
||||
json_t * object,
|
||||
char const * key)
|
||||
{
|
||||
char const * result = NULL;
|
||||
|
||||
json_t * string_holder = json_object_get(object, key);
|
||||
if (json_is_string(string_holder))
|
||||
{
|
||||
result = json_string_value(string_holder);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool userdb_check(
|
||||
struct userdb * db,
|
||||
char const * username,
|
||||
char const * password)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
json_t * user = json_object_get(db->users, username);
|
||||
if (json_is_object(user))
|
||||
{
|
||||
char const * salt = json_object_get_string(user, "salt");
|
||||
char const * hash = json_object_get_string(user, "password_hash");
|
||||
|
||||
char * computed_hash = compute_hash(db, password, salt);
|
||||
|
||||
result = (0 == strcmp(computed_hash, hash));
|
||||
free(computed_hash);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -1,304 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <jansson.h>
|
||||
#include <userdb.h>
|
||||
|
||||
|
||||
struct args
|
||||
{
|
||||
char * file;
|
||||
char * command;
|
||||
char * username;
|
||||
char * password;
|
||||
char * pepper;
|
||||
bool show_help;
|
||||
};
|
||||
|
||||
typedef int command_invoke_fn(
|
||||
struct args * args);
|
||||
|
||||
struct command
|
||||
{
|
||||
char const * name;
|
||||
command_invoke_fn * invoke;
|
||||
};
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"webfuse-passwd, Copyright (c) 2019, webfuse authors <https://github.com/falk-werner/webfuse>\n"
|
||||
"Manage webfuse passwd file\n"
|
||||
"\n"
|
||||
"Usage: webfuse-passwd -f <file> -c <command> [-u <username>] [-p <password>] [-P <pepper>]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"\t-f, --file Path of wf passwd file\n"
|
||||
"\t-c, --command Command to execute\n"
|
||||
"\t-u, --username Name of user\n"
|
||||
"\t-p, --password Password of user\n"
|
||||
"\t-P, --pepper pepper\n"
|
||||
"\t-h, --help Shows this message\n"
|
||||
"\n"
|
||||
"Commands:\n"
|
||||
"\tcreate Creates an empty passwd file (or cleans an existing)\n"
|
||||
"\t Example: webfuse-passwd -f passwd.json -c create\n"
|
||||
"\tadd Adds or replaces a user\n"
|
||||
"\t Example: webfuse-passwd -f passwd.json -c add -u bob -p secret\n"
|
||||
"\tremove Removes a user\n"
|
||||
"\t Example: webfuse-passwd -f passwd.json -c remove -u bob\n"
|
||||
"\tcheck Checks password of a user\n"
|
||||
"\t Example: webfuse-passwd -f passwd.json -c check -u bob -p secret\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int parse_args(struct args * args, int argc, char * argv[])
|
||||
{
|
||||
static struct option const options[] =
|
||||
{
|
||||
{"file", required_argument, NULL, 'f'},
|
||||
{"command", required_argument, NULL, 'c'},
|
||||
{"username", required_argument, NULL, 'u'},
|
||||
{"password", required_argument, NULL, 'p'},
|
||||
{"Pepper", required_argument, NULL, 'P'},
|
||||
{"help", required_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
int result = EXIT_SUCCESS;
|
||||
bool finished = false;
|
||||
while ((!finished) && (EXIT_SUCCESS == result))
|
||||
{
|
||||
int option_index = 0;
|
||||
int const c = getopt_long(argc, argv, "f:c:u:p:P:h", options, &option_index);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case -1:
|
||||
finished = true;
|
||||
break;
|
||||
case 'h':
|
||||
args->show_help = true;
|
||||
finished = true;
|
||||
break;
|
||||
case 'f':
|
||||
free(args->file);
|
||||
args->file = strdup(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
free(args->command);
|
||||
args->command = strdup(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
free(args->username);
|
||||
args->username = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
free(args->password);
|
||||
args->password = strdup(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
free(args->pepper);
|
||||
args->pepper = strdup(optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "error: unknown argument\n");
|
||||
result = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((result == EXIT_SUCCESS) && (!args->show_help))
|
||||
{
|
||||
if (NULL == args->file)
|
||||
{
|
||||
fprintf(stderr, "error: missing file\n");
|
||||
args->show_help = true;
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
else if (NULL == args->command)
|
||||
{
|
||||
fprintf(stderr, "error: missing command\n");
|
||||
args->show_help = true;
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void args_init(struct args * args)
|
||||
{
|
||||
args->file = NULL;
|
||||
args->command = NULL;
|
||||
args->username = NULL;
|
||||
args->password = NULL;
|
||||
args->pepper = strdup("");
|
||||
args->show_help = false;
|
||||
}
|
||||
|
||||
static int create_passwd(struct args * args)
|
||||
{
|
||||
struct userdb * db = userdb_create(args->pepper);
|
||||
bool result = userdb_save(db, args->file);
|
||||
userdb_dispose(db);
|
||||
|
||||
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int add_user(struct args * args)
|
||||
{
|
||||
if (NULL == args->username)
|
||||
{
|
||||
fprintf(stderr, "error: missing username");
|
||||
args->show_help = true;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (NULL == args->password)
|
||||
{
|
||||
fprintf(stderr, "error: missing password");
|
||||
args->show_help = true;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct userdb * db = userdb_create(args->pepper);
|
||||
userdb_load(db, args->file);
|
||||
userdb_add(db, args->username, args->password);
|
||||
bool result = userdb_save(db, args->file);
|
||||
userdb_dispose(db);
|
||||
|
||||
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int remove_user(struct args * args)
|
||||
{
|
||||
if (NULL == args->username)
|
||||
{
|
||||
fprintf(stderr, "error: missing username");
|
||||
args->show_help = true;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct userdb * db = userdb_create(args->pepper);
|
||||
userdb_load(db, args->file);
|
||||
userdb_remove(db, args->username);
|
||||
bool result = userdb_save(db, args->file);
|
||||
userdb_dispose(db);
|
||||
|
||||
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int check_password(struct args * args)
|
||||
{
|
||||
if (NULL == args->username)
|
||||
{
|
||||
fprintf(stderr, "error: missing username");
|
||||
args->show_help = true;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (NULL == args->password)
|
||||
{
|
||||
fprintf(stderr, "error: missing password");
|
||||
args->show_help = true;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct userdb * db = userdb_create(args->pepper);
|
||||
userdb_load(db, args->file);
|
||||
bool result = userdb_check(db, args->username, args->password);
|
||||
userdb_dispose(db);
|
||||
|
||||
printf("%s\n", (result) ? "OK" : "FAILURE");
|
||||
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int invoke_invalid_command(struct args * args)
|
||||
{
|
||||
(void) args;
|
||||
|
||||
fprintf(stderr, "error: unknown command\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static struct command const commands[] =
|
||||
{
|
||||
{"create", &create_passwd},
|
||||
{"add", &add_user},
|
||||
{"remove", &remove_user},
|
||||
{"check", &check_password},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static struct command const invalid_command =
|
||||
{
|
||||
"<invalid>",
|
||||
&invoke_invalid_command
|
||||
};
|
||||
|
||||
static struct command const * get_command(char const * name)
|
||||
{
|
||||
for(size_t i = 0; NULL != commands[i].name; i++)
|
||||
{
|
||||
if (0 == strcmp(name, commands[i].name))
|
||||
{
|
||||
return &commands[i];
|
||||
}
|
||||
}
|
||||
|
||||
return &invalid_command;
|
||||
}
|
||||
|
||||
static void args_cleanup(struct args * args)
|
||||
{
|
||||
free(args->file);
|
||||
free(args->command);
|
||||
free(args->username);
|
||||
free(args->password);
|
||||
free(args->pepper);
|
||||
}
|
||||
|
||||
static void openssl_cleanup(void)
|
||||
{
|
||||
FIPS_mode_set(0);
|
||||
ENGINE_cleanup();
|
||||
CONF_modules_unload(1);
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
ERR_free_strings();
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
OPENSSL_init();
|
||||
OPENSSL_add_all_algorithms_conf();
|
||||
|
||||
struct args args;
|
||||
args_init(&args);
|
||||
int result = parse_args(&args, argc, argv);
|
||||
if ((EXIT_SUCCESS == result) && (!args.show_help))
|
||||
{
|
||||
struct command const * command = get_command(args.command);
|
||||
result = command->invoke(&args);
|
||||
}
|
||||
|
||||
if (args.show_help)
|
||||
{
|
||||
print_usage();
|
||||
}
|
||||
|
||||
args_cleanup(&args);
|
||||
openssl_cleanup();
|
||||
return result;
|
||||
}
|
@ -1,385 +0,0 @@
|
||||
#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"
|
||||
|
||||
#define SERVICE_TIMEOUT (1 * 1000)
|
||||
|
||||
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, SERVICE_TIMEOUT);
|
||||
}
|
||||
|
||||
wfp_client_dispose(client);
|
||||
}
|
||||
|
||||
if (config.show_help)
|
||||
{
|
||||
show_help();
|
||||
}
|
||||
|
||||
free(config.url);
|
||||
wfp_client_config_dispose(config.client_config);
|
||||
return result;
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "webfuse_provider.h"
|
||||
|
||||
#define SERVICE_TIMEOUT (1 * 1000)
|
||||
|
||||
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)
|
||||
{
|
||||
struct wfp_client_config * config = wfp_client_config_create();
|
||||
|
||||
struct wfp_static_filesystem * fs = wfp_static_filesystem_create(config);
|
||||
wfp_static_filesystem_add_text(fs, "hello.txt", 0444, "Hello, World!");
|
||||
|
||||
struct wfp_client * client = wfp_client_create(config);
|
||||
wfp_client_connect(client, args.url);
|
||||
|
||||
while (!shutdown_requested)
|
||||
{
|
||||
wfp_client_service(client, SERVICE_TIMEOUT);
|
||||
}
|
||||
|
||||
wfp_client_dispose(client);
|
||||
wfp_static_filesystem_dispose(fs);
|
||||
wfp_client_config_dispose(config);
|
||||
}
|
||||
|
||||
if (args.show_help)
|
||||
{
|
||||
print_usage();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file adapter/mountpoint.h
|
||||
/// \brief Mointpoint.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WF_ADAPTER_MOUNTPOINT_H
|
||||
#define WF_ADAPTER_MOUNTPOINT_H
|
||||
|
||||
#include <webfuse/adapter/api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \struct wf_mountpoint
|
||||
/// \brief Mointpoint.
|
||||
//------------------------------------------------------------------------------
|
||||
struct wf_mountpoint;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Disposes the user defined context of a mountpoint.
|
||||
///
|
||||
/// \param user_data user defined context of the mointpoint.
|
||||
///
|
||||
/// \see wf_mountpoint_set_userdata
|
||||
//------------------------------------------------------------------------------
|
||||
typedef void
|
||||
wf_mountpoint_userdata_dispose_fn(
|
||||
void * user_data);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Creates a mountpoint.
|
||||
///
|
||||
/// \param path local path of the mounpoint
|
||||
/// \return Newly created mountpoint.
|
||||
//------------------------------------------------------------------------------
|
||||
extern WF_API struct wf_mountpoint *
|
||||
wf_mountpoint_create(
|
||||
char const * path);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Disposes a mountpoint.
|
||||
///
|
||||
/// \param mountpoint pointer to the mountpoint
|
||||
//------------------------------------------------------------------------------
|
||||
extern WF_API void
|
||||
wf_mountpoint_dispose(
|
||||
struct wf_mountpoint * mountpoint);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Returns the local path of the mountpoint.
|
||||
///
|
||||
/// \param mountpoint pointer to the mountpoint
|
||||
/// \return local path of the mountpoint
|
||||
//------------------------------------------------------------------------------
|
||||
extern WF_API char const *
|
||||
wf_mountpoint_get_path(
|
||||
struct wf_mountpoint const * mountpoint);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Sets user data of the mointpoint.
|
||||
///
|
||||
/// \note This function is intended for custom mountpoint factories to
|
||||
/// annotate mountpoints with a user specified context.
|
||||
///
|
||||
/// \param mounpoint pointer to the mountpoint
|
||||
/// \param user_data user data
|
||||
/// \param dispose pointer to dipose function of user data or NULL,
|
||||
/// if there is no need to dispose user data
|
||||
//------------------------------------------------------------------------------
|
||||
extern WF_API void
|
||||
wf_mountpoint_set_userdata(
|
||||
struct wf_mountpoint * mointpoint,
|
||||
void * user_data,
|
||||
wf_mountpoint_userdata_dispose_fn * dispose);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,39 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file adapter/mountpoint_factory.h
|
||||
/// \brief Defines a factory function to create mointpoints.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WF_ADAPTER_MOUNTPOINT_FACTORY_H
|
||||
#define WF_ADAPTER_MOUNTPOINT_FACTORY_H
|
||||
|
||||
#include <webfuse/adapter/api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_mountpoint;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \brief Factory function to create mountpoints.
|
||||
///
|
||||
/// \param filesystem name the filesystem
|
||||
/// \param user_data context of the factory
|
||||
/// \return newly created mountpoint or NULL, on error
|
||||
///
|
||||
/// \see wf_server_config_set_mountpoint_factory
|
||||
/// \see wf_server_protocol_create
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct wf_mountpoint *
|
||||
wf_create_mountpoint_fn(
|
||||
char const * filesystem,
|
||||
void * user_data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,21 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file protocol_names.h
|
||||
/// \brief Names of websocket protocol.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef WF_PROTOCOL_NAMES_H
|
||||
#define WF_PROTOCOL_NAMES_H
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \def WF_PROTOCOL_NAME_ADAPTER_SERVER
|
||||
/// \brief Name of the websocket protocol an adapter server is running.
|
||||
//------------------------------------------------------------------------------
|
||||
#define WF_PROTOCOL_NAME_ADAPTER_SERVER ("webfuse-adapter-server")
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \def WF_PROTOCOL_NAME_PROVIDER_CLIENT
|
||||
/// \brief Name of the websocket protocol an provider client is running.
|
||||
//------------------------------------------------------------------------------
|
||||
#define WF_PROTOCOL_NAME_PROVIDER_CLIENT ("webfuse-provider-client")
|
||||
|
||||
#endif
|
@ -1,17 +1,23 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file status.h
|
||||
/// \brief Generic status code.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WF_STATUS_H
|
||||
#define WF_STATUS_H
|
||||
|
||||
#define WF_GOOD 0
|
||||
#define WF_BAD 1
|
||||
#define WF_GOOD 0 ///< Positive status code.
|
||||
#define WF_BAD 1 ///< Generic negative status code.
|
||||
|
||||
#define WF_BAD_NOTIMPLEMENTED 2
|
||||
#define WF_BAD_TIMEOUT 3
|
||||
#define WF_BAD_BUSY 4
|
||||
#define WF_BAD_FORMAT 5
|
||||
#define WF_BAD_NOTIMPLEMENTED 2 ///< The called function is not implemented (yet).
|
||||
#define WF_BAD_TIMEOUT 3 ///< A timeout occured.
|
||||
#define WF_BAD_BUSY 4 ///< Resource is busy, try again later.
|
||||
#define WF_BAD_FORMAT 5 ///< Invalid format.
|
||||
|
||||
#define WF_BAD_NOENTRY 101
|
||||
#define WF_BAD_ACCESS_DENIED 102
|
||||
#define WF_BAD_NOENTRY 101 ///< Entry not found.
|
||||
#define WF_BAD_ACCESS_DENIED 102 ///< Access is denied.
|
||||
|
||||
/// Status code.
|
||||
typedef int wf_status;
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,30 @@
|
||||
#ifndef WF_PROVIDER_CREDENTIALS_H
|
||||
#define WF_PROVIDER_CREDENTIALS_H
|
||||
|
||||
#include <webfuse/provider/api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wfp_credentials;
|
||||
|
||||
typedef void wfp_get_credentials_fn(
|
||||
struct wfp_credentials * credentials,
|
||||
void * user_data);
|
||||
|
||||
extern WFP_API void wfp_credentials_set_type(
|
||||
struct wfp_credentials * credentials,
|
||||
char const * type);
|
||||
|
||||
extern WFP_API void wfp_credentials_add(
|
||||
struct wfp_credentials * credentials,
|
||||
char const * key,
|
||||
char const * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,172 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Checks for dependencies and install them, if needed.
|
||||
#
|
||||
# A valid package description is defined as follows:
|
||||
# local <package>_name=<name>
|
||||
# local <package>_type=<type>
|
||||
# local <package>_archive=<archive>
|
||||
# local <package>_dir=<dir>
|
||||
# local <package>_url=<url>
|
||||
#
|
||||
# <package> - symbolid id of package
|
||||
# <name> - name of the package (used for pkg-config)
|
||||
# <type> - type of project ("cmake" or "autotools")
|
||||
# <archive> - archive file name
|
||||
# <dir> - dir of package sources
|
||||
# <url> - url of the project archive
|
||||
#
|
||||
# For examples, see below.
|
||||
#
|
||||
# Since <package>_ variables are not used directly, shellcheck will complain:
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
|
||||
#######################################
|
||||
# Installs a cmake package.
|
||||
#
|
||||
# Arguments:
|
||||
# package - name of package
|
||||
# Returns:
|
||||
# 0 on success, otherwise failure
|
||||
#######################################
|
||||
function install_cmake_package() {
|
||||
local package="$1"
|
||||
local archive="${package}_archive"
|
||||
local dir="${package}_dir"
|
||||
local url="${package}_url"
|
||||
|
||||
wget -O "${!archive}" "${!url}" && \
|
||||
tar -xf "${!archive}" && \
|
||||
cd "${!dir}" && \
|
||||
mkdir .build && \
|
||||
cd .build && \
|
||||
cmake .. && \
|
||||
make && \
|
||||
sudo make install && \
|
||||
cd .. && \
|
||||
cd ..
|
||||
|
||||
return "$?"
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Installs a autotools package.
|
||||
#
|
||||
# Arguments:
|
||||
# package - name of package
|
||||
# Returns:
|
||||
# 0 on success, otherwise failure
|
||||
#######################################
|
||||
function install_autotools_package() {
|
||||
local package="$1"
|
||||
local archive="${package}_archive"
|
||||
local dir="${package}_dir"
|
||||
local url="${package}_url"
|
||||
|
||||
wget -O "${!archive}" "${!url}" && \
|
||||
tar -xf "${!archive}" && \
|
||||
cd "${!dir}" && \
|
||||
./makeconf.sh && \
|
||||
./configure && \
|
||||
make && \
|
||||
sudo make install && \
|
||||
cd ..
|
||||
|
||||
return "$?"
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Checks, whether a package exists.
|
||||
#
|
||||
# Arguments:
|
||||
# package_name - name of package
|
||||
# Returns:
|
||||
# 0 if package exists, otherwise failure
|
||||
#######################################
|
||||
function package_exists() {
|
||||
local package_name="$1"
|
||||
|
||||
pkg-config --exists "${package_name}"
|
||||
return "$?"
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Installs a package, if it is not available.
|
||||
#
|
||||
# Arguments:
|
||||
# package - name of package
|
||||
# Returns:
|
||||
# 0 if package exists, otherwise failure
|
||||
#######################################
|
||||
function install_if_needed() {
|
||||
local package="$1"
|
||||
local package_name="${package}_name"
|
||||
local package_type="${package}_type"
|
||||
local result=0
|
||||
|
||||
package_exists "${!package_name}"
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
"install_${!package_type}_package" "$package"
|
||||
result="$?"
|
||||
fi
|
||||
|
||||
return "${result}"
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Main
|
||||
#
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# 0 on success, otherwise failure
|
||||
#######################################
|
||||
function main() {
|
||||
rm -rf .deps
|
||||
mkdir .deps
|
||||
cd .deps
|
||||
|
||||
local packages=(fuse3 lws jansson gtest)
|
||||
|
||||
local fuse3_name=fuse3
|
||||
local fuse3_type=autotools
|
||||
local fuse3_archive=fuse-3.1.1.tar.gz
|
||||
local fuse3_dir=libfuse-fuse-3.1.1
|
||||
local fuse3_url=https://github.com/libfuse/libfuse/archive/fuse-3.1.1.tar.gz
|
||||
|
||||
local lws_name=libwebsockets
|
||||
local lws_type=cmake
|
||||
local lws_archive=libwebsockets-3.1.0.tar.gz
|
||||
local lws_dir=libwebsockets-3.1.0
|
||||
local lws_url=https://github.com/warmcat/libwebsockets/archive/v3.1.0.tar.gz
|
||||
|
||||
local jansson_name=jansson
|
||||
local jansson_type=cmake
|
||||
local jansson_archive=libjansson-2.12.tar.gz
|
||||
local jansson_dir=jansson-2.12
|
||||
local jansson_url=https://github.com/akheron/jansson/archive/v2.12.tar.gz
|
||||
|
||||
local gtest_name=gtest_main
|
||||
local gtest_type=cmake
|
||||
local gtest_archive=gtest-1.8.1.tar.gz
|
||||
local gtest_dir=googletest-release-1.8.1
|
||||
local gtest_url=https://github.com/google/googletest/archive/release-1.8.1.tar.gz
|
||||
|
||||
local result=0
|
||||
local package=""
|
||||
for package in "${packages[@]}" ; do
|
||||
install_if_needed $package
|
||||
result="$?"
|
||||
|
||||
if [[ "${result}" -ne 0 ]] ; then
|
||||
cd ..
|
||||
return "${result}"
|
||||
fi
|
||||
done
|
||||
|
||||
cd ..
|
||||
return 0
|
||||
}
|
||||
|
||||
main "$@"
|
@ -1,27 +0,0 @@
|
||||
#include "webfuse/adapter/impl/jsonrpc/method.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
|
||||
char const * method_name,
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke,
|
||||
void * user_data)
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * method = malloc(sizeof(struct wf_impl_jsonrpc_method));
|
||||
if (NULL != method)
|
||||
{
|
||||
method->next = NULL;
|
||||
method->name = strdup(method_name);
|
||||
method->invoke = invoke;
|
||||
method->user_data = user_data;
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_method_dispose(
|
||||
struct wf_impl_jsonrpc_method * method)
|
||||
{
|
||||
free(method->name);
|
||||
free(method);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSONRPC_METHOD_H
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_METHOD_H
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_request;
|
||||
|
||||
typedef void wf_impl_jsonrpc_method_invoke_fn(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
char const * method_name,
|
||||
json_t * params,
|
||||
void * user_data);
|
||||
|
||||
struct wf_impl_jsonrpc_method
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * next;
|
||||
char * name;
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
extern struct wf_impl_jsonrpc_method * wf_impl_jsonrpc_method_create(
|
||||
char const * method_name,
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke,
|
||||
void * user_data);
|
||||
|
||||
extern void wf_impl_jsonrpc_method_dispose(
|
||||
struct wf_impl_jsonrpc_method * method);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -1,194 +0,0 @@
|
||||
#include "webfuse/adapter/impl/jsonrpc/proxy.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "webfuse/adapter/impl/jsonrpc/response.h"
|
||||
|
||||
static void wf_impl_jsonrpc_proxy_timeout(
|
||||
struct wf_impl_timer * timer)
|
||||
{
|
||||
struct wf_impl_jsonrpc_proxy * proxy = timer->user_data;
|
||||
|
||||
if (proxy->request.is_pending)
|
||||
{
|
||||
wf_impl_jsonrpc_proxy_finished_fn * finished = proxy->request.finished;
|
||||
void * user_data = proxy->request.user_data;
|
||||
|
||||
proxy->request.is_pending = false;
|
||||
proxy->request.id = 0;
|
||||
proxy->request.user_data = NULL;
|
||||
proxy->request.finished = NULL;
|
||||
wf_impl_timer_cancel(&proxy->request.timer);
|
||||
|
||||
finished(user_data, WF_BAD_TIMEOUT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static json_t * wf_impl_jsonrpc_request_create(
|
||||
char const * method,
|
||||
int id,
|
||||
char const * param_info,
|
||||
va_list args)
|
||||
{
|
||||
json_t * request = json_object();
|
||||
json_object_set_new(request, "method", json_string(method));
|
||||
json_t * params = json_array();
|
||||
|
||||
for (char const * param_type = param_info; '\0' != *param_type; param_type++)
|
||||
{
|
||||
switch(*param_type)
|
||||
{
|
||||
case 's':
|
||||
{
|
||||
char const * const value = va_arg(args, char const *);
|
||||
json_array_append_new(params, json_string(value));
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
{
|
||||
int const value = va_arg(args, int);
|
||||
json_array_append_new(params, json_integer(value));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "fatal: unknown param_type '%c'\n", *param_type);
|
||||
json_decref(params);
|
||||
json_decref(request);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
json_object_set_new(request, "params", params);
|
||||
if (0 != id)
|
||||
{
|
||||
json_object_set_new(request, "id", json_integer(id));
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_proxy_init(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
struct wf_impl_timeout_manager * timeout_manager,
|
||||
int timeout,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data)
|
||||
{
|
||||
proxy->send = send;
|
||||
proxy->timeout = timeout;
|
||||
proxy->user_data = user_data;
|
||||
proxy->request.is_pending = false;
|
||||
|
||||
wf_impl_timer_init(&proxy->request.timer, timeout_manager);
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_proxy_cleanup(
|
||||
struct wf_impl_jsonrpc_proxy * proxy)
|
||||
{
|
||||
if (proxy->request.is_pending)
|
||||
{
|
||||
void * user_data = proxy->request.user_data;
|
||||
wf_impl_jsonrpc_proxy_finished_fn * finished = proxy->request.finished;
|
||||
|
||||
proxy->request.is_pending = false;
|
||||
proxy->request.finished = NULL;
|
||||
proxy->request.user_data = NULL;
|
||||
proxy->request.id = 0;
|
||||
wf_impl_timer_cancel(&proxy->request.timer);
|
||||
|
||||
finished(user_data, WF_BAD, NULL);
|
||||
}
|
||||
|
||||
wf_impl_timer_cleanup(&proxy->request.timer);
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_proxy_invoke(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
wf_impl_jsonrpc_proxy_finished_fn * finished,
|
||||
void * user_data,
|
||||
char const * method_name,
|
||||
char const * param_info,
|
||||
...
|
||||
)
|
||||
{
|
||||
if (!proxy->request.is_pending)
|
||||
{
|
||||
proxy->request.is_pending = true;
|
||||
proxy->request.finished = finished;
|
||||
proxy->request.user_data = user_data;
|
||||
proxy->request.id = 42;
|
||||
wf_impl_timer_start(&proxy->request.timer, wf_impl_timepoint_in_msec(proxy->timeout),
|
||||
&wf_impl_jsonrpc_proxy_timeout, proxy);
|
||||
|
||||
va_list args;
|
||||
va_start(args, param_info);
|
||||
json_t * request = wf_impl_jsonrpc_request_create(method_name, proxy->request.id, param_info, args);
|
||||
va_end(args);
|
||||
|
||||
bool const is_send = ((NULL != request) && (proxy->send(request, proxy->user_data)));
|
||||
if (!is_send)
|
||||
{
|
||||
proxy->request.is_pending = false;
|
||||
proxy->request.finished = NULL;
|
||||
proxy->request.user_data = NULL;
|
||||
proxy->request.id = 0;
|
||||
wf_impl_timer_cancel(&proxy->request.timer);
|
||||
|
||||
finished(user_data, WF_BAD, NULL);
|
||||
|
||||
}
|
||||
|
||||
if (NULL != request)
|
||||
{
|
||||
json_decref(request);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
finished(user_data, WF_BAD_BUSY, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
extern void wf_impl_jsonrpc_proxy_notify(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
char const * method_name,
|
||||
char const * param_info,
|
||||
...
|
||||
)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, param_info);
|
||||
json_t * request = wf_impl_jsonrpc_request_create(method_name, 0, param_info, args);
|
||||
va_end(args);
|
||||
if (NULL != request)
|
||||
{
|
||||
proxy->send(request, proxy->user_data);
|
||||
json_decref(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wf_impl_jsonrpc_proxy_onresult(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
json_t * message)
|
||||
{
|
||||
struct wf_impl_jsonrpc_response response;
|
||||
wf_impl_jsonrpc_response_init(&response, message);
|
||||
|
||||
if ((proxy->request.is_pending) && (response.id == proxy->request.id))
|
||||
{
|
||||
wf_impl_jsonrpc_proxy_finished_fn * finished = proxy->request.finished;
|
||||
void * user_data = proxy->request.user_data;
|
||||
|
||||
proxy->request.is_pending = false;
|
||||
proxy->request.id = 0;
|
||||
proxy->request.user_data = NULL;
|
||||
proxy->request.finished = NULL;
|
||||
wf_impl_timer_cancel(&proxy->request.timer);
|
||||
|
||||
finished(user_data, response.status, response.result);
|
||||
}
|
||||
|
||||
wf_impl_jsonrpc_response_cleanup(&response);
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSONRPC_PROXY_H
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_PROXY_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
using std::size_t;
|
||||
#endif
|
||||
|
||||
#include <jansson.h>
|
||||
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
|
||||
#include "webfuse/adapter/impl/time/timeout_manager.h"
|
||||
#include "webfuse/adapter/impl/time/timer.h"
|
||||
#include "webfuse/core/status.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void wf_impl_jsonrpc_proxy_finished_fn(
|
||||
void * user_data,
|
||||
wf_status status,
|
||||
struct json_t const * result);
|
||||
|
||||
|
||||
struct wf_impl_jsonrpc_request
|
||||
{
|
||||
bool is_pending;
|
||||
wf_impl_jsonrpc_proxy_finished_fn * finished;
|
||||
void * user_data;
|
||||
int id;
|
||||
struct wf_impl_timer timer;
|
||||
};
|
||||
|
||||
struct wf_impl_jsonrpc_proxy
|
||||
{
|
||||
struct wf_impl_jsonrpc_request request;
|
||||
int timeout;
|
||||
wf_impl_jsonrpc_send_fn * send;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
extern void wf_impl_jsonrpc_proxy_init(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
struct wf_impl_timeout_manager * manager,
|
||||
int timeout,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data);
|
||||
|
||||
extern void wf_impl_jsonrpc_proxy_cleanup(
|
||||
struct wf_impl_jsonrpc_proxy * proxy);
|
||||
|
||||
extern void wf_impl_jsonrpc_proxy_invoke(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
wf_impl_jsonrpc_proxy_finished_fn * finished,
|
||||
void * user_data,
|
||||
char const * method_name,
|
||||
char const * param_info,
|
||||
...
|
||||
);
|
||||
|
||||
extern void wf_impl_jsonrpc_proxy_notify(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
char const * method_name,
|
||||
char const * param_info,
|
||||
...
|
||||
);
|
||||
|
||||
extern void wf_impl_jsonrpc_proxy_onresult(
|
||||
struct wf_impl_jsonrpc_proxy * proxy,
|
||||
json_t * message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -1,82 +0,0 @@
|
||||
#include "webfuse/adapter/impl/jsonrpc/request.h"
|
||||
#include "webfuse/core/status_intern.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct wf_impl_jsonrpc_request
|
||||
{
|
||||
int id;
|
||||
wf_impl_jsonrpc_send_fn * send;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
bool wf_impl_jsonrpc_is_request(
|
||||
json_t * message)
|
||||
{
|
||||
json_t * id = json_object_get(message, "id");
|
||||
json_t * method = json_object_get(message, "method");
|
||||
json_t * params = json_object_get(message, "params");
|
||||
|
||||
return (json_is_integer(id) && json_is_string(method) &&
|
||||
(json_is_array(params) || json_is_object(params)));
|
||||
}
|
||||
|
||||
|
||||
struct wf_impl_jsonrpc_request * wf_impl_jsonrpc_request_create(
|
||||
int id,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data)
|
||||
{
|
||||
struct wf_impl_jsonrpc_request * request = malloc(sizeof(struct wf_impl_jsonrpc_request));
|
||||
if (NULL != request)
|
||||
{
|
||||
request->id = id;
|
||||
request->send = send;
|
||||
request->user_data = user_data;
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_request_dispose(
|
||||
struct wf_impl_jsonrpc_request * request)
|
||||
{
|
||||
free(request);
|
||||
}
|
||||
|
||||
void * wf_impl_jsonrpc_request_get_userdata(
|
||||
struct wf_impl_jsonrpc_request * request)
|
||||
{
|
||||
return request->user_data;
|
||||
}
|
||||
|
||||
|
||||
void wf_impl_jsonrpc_respond(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
json_t * result)
|
||||
{
|
||||
json_t * response = json_object();
|
||||
json_object_set_new(response, "result", result);
|
||||
json_object_set_new(response, "id", json_integer(request->id));
|
||||
|
||||
request->send(response, request->user_data);
|
||||
json_decref(response);
|
||||
wf_impl_jsonrpc_request_dispose(request);
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_respond_error(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
wf_status status)
|
||||
{
|
||||
json_t * err = json_object();
|
||||
json_object_set_new(err, "code", json_integer(status));
|
||||
json_object_set_new(err, "message", json_string(wf_status_tostring(status)));
|
||||
|
||||
json_t * response = json_object();
|
||||
json_object_set_new(response, "error", err);
|
||||
json_object_set_new(response, "id", json_integer(request->id));
|
||||
|
||||
request->send(response, request->user_data);
|
||||
json_decref(response);
|
||||
wf_impl_jsonrpc_request_dispose(request);
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSONRPC_REQUEST_H
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_REQUEST_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
using std::size_t;
|
||||
#endif
|
||||
|
||||
#include <jansson.h>
|
||||
#include "webfuse/core/status.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_request;
|
||||
|
||||
extern bool wf_impl_jsonrpc_is_request(
|
||||
json_t * message);
|
||||
|
||||
extern struct wf_impl_jsonrpc_request * wf_impl_jsonrpc_request_create(
|
||||
int id,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data);
|
||||
|
||||
extern void wf_impl_jsonrpc_request_dispose(
|
||||
struct wf_impl_jsonrpc_request * request);
|
||||
|
||||
extern void * wf_impl_jsonrpc_request_get_userdata(
|
||||
struct wf_impl_jsonrpc_request * request);
|
||||
|
||||
extern void wf_impl_jsonrpc_respond(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
json_t * result);
|
||||
|
||||
extern void wf_impl_jsonrpc_respond_error(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
wf_status status);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,60 +0,0 @@
|
||||
#include "webfuse/adapter/impl/jsonrpc/response.h"
|
||||
|
||||
extern bool wf_impl_jsonrpc_is_response(
|
||||
json_t * message)
|
||||
{
|
||||
json_t * id = json_object_get(message, "id");
|
||||
json_t * err = json_object_get(message, "error");
|
||||
json_t * result = json_object_get(message, "result");
|
||||
|
||||
return (json_is_integer(id) &&
|
||||
(json_is_object(err) || (NULL != result)));
|
||||
}
|
||||
|
||||
|
||||
void wf_impl_jsonrpc_response_init(
|
||||
struct wf_impl_jsonrpc_response * result,
|
||||
json_t * response)
|
||||
{
|
||||
result->status = WF_BAD;
|
||||
result->id = -1;
|
||||
result->result = NULL;
|
||||
|
||||
json_t * id_holder = json_object_get(response, "id");
|
||||
if ((NULL == id_holder) || (!json_is_integer(id_holder)))
|
||||
{
|
||||
result->status = WF_BAD_FORMAT;
|
||||
return;
|
||||
}
|
||||
|
||||
result->status = WF_GOOD;
|
||||
result->id = json_integer_value(id_holder);
|
||||
result->result = json_object_get(response, "result");
|
||||
if (NULL != result->result)
|
||||
{
|
||||
json_incref(result->result);
|
||||
}
|
||||
else
|
||||
{
|
||||
result->status = WF_BAD_FORMAT;
|
||||
|
||||
json_t * error = json_object_get(response, "error");
|
||||
if (NULL != error)
|
||||
{
|
||||
json_t * error_code = json_object_get(error, "code");
|
||||
if ((NULL != error_code) && (json_is_integer(error_code)))
|
||||
{
|
||||
result->status = json_integer_value(error_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_response_cleanup(
|
||||
struct wf_impl_jsonrpc_response * response)
|
||||
{
|
||||
if (NULL != response->result)
|
||||
{
|
||||
json_decref(response->result);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSONRPC_RESPONSE_H
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_RESPONSE_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#else
|
||||
#include <cstddef>
|
||||
using std::size_t;
|
||||
#endif
|
||||
|
||||
#include <jansson.h>
|
||||
#include "webfuse/core/status.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_response
|
||||
{
|
||||
wf_status status;
|
||||
int id;
|
||||
json_t * result;
|
||||
};
|
||||
|
||||
extern bool wf_impl_jsonrpc_is_response(
|
||||
json_t * message);
|
||||
|
||||
extern void wf_impl_jsonrpc_response_init(
|
||||
struct wf_impl_jsonrpc_response * response,
|
||||
json_t * message);
|
||||
|
||||
extern void wf_impl_jsonrpc_response_cleanup(
|
||||
struct wf_impl_jsonrpc_response * response);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,95 +0,0 @@
|
||||
#include "webfuse/adapter/impl/jsonrpc/server.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/method.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/request.h"
|
||||
#include "webfuse/core/util.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void wf_impl_jsonrpc_server_init(
|
||||
struct wf_impl_jsonrpc_server * server)
|
||||
{
|
||||
server->methods = NULL;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_server_cleanup(
|
||||
struct wf_impl_jsonrpc_server * server)
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * current = server->methods;
|
||||
while (NULL != current)
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * next = current->next;
|
||||
wf_impl_jsonrpc_method_dispose(current);
|
||||
current = next;
|
||||
}
|
||||
server->methods = NULL;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_server_add(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * method_name,
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke,
|
||||
void * user_data)
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * method = wf_impl_jsonrpc_method_create(method_name, invoke, user_data);
|
||||
method->next = server->methods;
|
||||
server->methods = method;
|
||||
}
|
||||
|
||||
static void wf_impl_jsonrpc_server_invalid_method_invoke(
|
||||
struct wf_impl_jsonrpc_request * request,
|
||||
char const * WF_UNUSED_PARAM(method_name),
|
||||
json_t * WF_UNUSED_PARAM(params),
|
||||
void * WF_UNUSED_PARAM(user_data))
|
||||
{
|
||||
wf_impl_jsonrpc_respond_error(request, WF_BAD_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
static struct wf_impl_jsonrpc_method const wf_impl_jsonrpc_server_invalid_method =
|
||||
{
|
||||
.next = NULL,
|
||||
.name = "<invalid>",
|
||||
.invoke = &wf_impl_jsonrpc_server_invalid_method_invoke,
|
||||
.user_data = NULL
|
||||
};
|
||||
|
||||
static struct wf_impl_jsonrpc_method const * wf_impl_jsonrpc_server_get_method(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * method_name)
|
||||
{
|
||||
struct wf_impl_jsonrpc_method const * current = server->methods;
|
||||
while (NULL != current)
|
||||
{
|
||||
if (0 == strcmp(method_name, current->name))
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return &wf_impl_jsonrpc_server_invalid_method;
|
||||
}
|
||||
|
||||
void wf_impl_jsonrpc_server_process(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
json_t * request_data,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data)
|
||||
{
|
||||
json_t * method_holder = json_object_get(request_data, "method");
|
||||
json_t * params = json_object_get(request_data, "params");
|
||||
json_t * id_holder = json_object_get(request_data, "id");
|
||||
|
||||
if (json_is_string(method_holder) &&
|
||||
(json_is_array(params) || (json_is_object(params))) &&
|
||||
json_is_integer(id_holder))
|
||||
{
|
||||
char const * method_name = json_string_value(method_holder);
|
||||
int id = json_integer_value(id_holder);
|
||||
struct wf_impl_jsonrpc_request * request = wf_impl_jsonrpc_request_create(id, send, user_data);
|
||||
struct wf_impl_jsonrpc_method const * method = wf_impl_jsonrpc_server_get_method(server, method_name);
|
||||
|
||||
method->invoke(request, method_name, params, method->user_data);
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSONRPC_SERVER_H
|
||||
#define WF_ADAPTER_IMPL_JSONRPC_SERVER_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#include <cstdarg>
|
||||
#endif
|
||||
|
||||
#include <jansson.h>
|
||||
#include "webfuse/core/status.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/send_fn.h"
|
||||
#include "webfuse/adapter/impl/jsonrpc/method.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_jsonrpc_server
|
||||
{
|
||||
struct wf_impl_jsonrpc_method * methods;
|
||||
};
|
||||
|
||||
extern void wf_impl_jsonrpc_server_init(
|
||||
struct wf_impl_jsonrpc_server * server);
|
||||
|
||||
extern void wf_impl_jsonrpc_server_cleanup(
|
||||
struct wf_impl_jsonrpc_server * server);
|
||||
|
||||
extern void wf_impl_jsonrpc_server_add(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
char const * method_name,
|
||||
wf_impl_jsonrpc_method_invoke_fn * invoke,
|
||||
void * user_data);
|
||||
|
||||
extern void wf_impl_jsonrpc_server_process(
|
||||
struct wf_impl_jsonrpc_server * server,
|
||||
json_t * request,
|
||||
wf_impl_jsonrpc_send_fn * send,
|
||||
void * user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
#ifndef WF_ADAPTER_IMPL_JSON_UTIL_H
|
||||
#define WF_ADAPTER_IMPL_JSON_UTIL_H
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern int wf_impl_json_get_int(json_t const * object, char const * key, int default_value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
#include "webfuse/adapter/impl/mountpoint.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct wf_mountpoint
|
||||
{
|
||||
char * path;
|
||||
void * user_data;
|
||||
wf_mountpoint_userdata_dispose_fn * dispose;
|
||||
};
|
||||
|
||||
struct wf_mountpoint *
|
||||
wf_impl_mountpoint_create(
|
||||
char const * path)
|
||||
{
|
||||
struct wf_mountpoint * mountpoint = malloc(sizeof(struct wf_mountpoint));
|
||||
mountpoint->path = strdup(path);
|
||||
mountpoint->user_data = NULL;
|
||||
mountpoint->dispose = NULL;
|
||||
|
||||
return mountpoint;
|
||||
}
|
||||
|
||||
void
|
||||
wf_impl_mountpoint_dispose(
|
||||
struct wf_mountpoint * mountpoint)
|
||||
{
|
||||
if (NULL != mountpoint->dispose)
|
||||
{
|
||||
mountpoint->dispose(mountpoint->user_data);
|
||||
}
|
||||
|
||||
free(mountpoint->path);
|
||||
free(mountpoint);
|
||||
}
|
||||
|
||||
char const *
|
||||
wf_impl_mountpoint_get_path(
|
||||
struct wf_mountpoint const * mountpoint)
|
||||
{
|
||||
return mountpoint->path;
|
||||
}
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_set_userdata(
|
||||
struct wf_mountpoint * mountpoint,
|
||||
void * user_data,
|
||||
wf_mountpoint_userdata_dispose_fn * dispose)
|
||||
{
|
||||
mountpoint->user_data = user_data;
|
||||
mountpoint->dispose = dispose;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
#ifndef WF_IMPL_MOUNTPOINT_H
|
||||
#define WF_IMPL_MOUNTPOINT_H
|
||||
|
||||
#include "webfuse/adapter/mountpoint.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern struct wf_mountpoint *
|
||||
wf_impl_mountpoint_create(
|
||||
char const * path);
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_dispose(
|
||||
struct wf_mountpoint * mountpoint);
|
||||
|
||||
extern char const *
|
||||
wf_impl_mountpoint_get_path(
|
||||
struct wf_mountpoint const * mountpoint);
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_set_userdata(
|
||||
struct wf_mountpoint * mountpoint,
|
||||
void * user_data,
|
||||
wf_mountpoint_userdata_dispose_fn * dispose);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,54 @@
|
||||
#include "webfuse/adapter/impl/mountpoint_factory.h"
|
||||
#include <stddef.h>
|
||||
|
||||
void
|
||||
wf_impl_mountpoint_factory_init_default(
|
||||
struct wf_impl_mountpoint_factory * factory)
|
||||
{
|
||||
factory->create_mountpoint = NULL;
|
||||
factory->user_data = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wf_impl_mountpoint_factory_init(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
wf_create_mountpoint_fn * create_mountpoint,
|
||||
void * user_data)
|
||||
{
|
||||
factory->create_mountpoint = create_mountpoint;
|
||||
factory->user_data = user_data;
|
||||
}
|
||||
|
||||
void
|
||||
wf_impl_mountpoint_factory_clone(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
struct wf_impl_mountpoint_factory * other)
|
||||
{
|
||||
other->create_mountpoint = factory->create_mountpoint;
|
||||
other->user_data = factory->user_data;
|
||||
}
|
||||
|
||||
bool
|
||||
wf_impl_mountpoint_factory_isvalid(
|
||||
struct wf_impl_mountpoint_factory * factory)
|
||||
{
|
||||
return (NULL != factory->create_mountpoint);
|
||||
}
|
||||
|
||||
void
|
||||
wf_impl_mountpoint_factory_cleanup(
|
||||
struct wf_impl_mountpoint_factory * factory)
|
||||
{
|
||||
|
||||
factory->create_mountpoint = NULL;
|
||||
factory->user_data = NULL;
|
||||
}
|
||||
|
||||
struct wf_mountpoint *
|
||||
wf_impl_mountpoint_factory_create_mountpoint(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
char const * filesystem)
|
||||
{
|
||||
return factory->create_mountpoint(filesystem, factory->user_data);
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
#ifndef WF_ADAPTER_IMPL_MOUNTPOINT_FACTORY_H
|
||||
#define WF_ADAPTER_IMPL_MOUNTPOINT_FACTORY_H
|
||||
|
||||
#include "webfuse/adapter/mountpoint_factory.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_mountpoint_factory
|
||||
{
|
||||
wf_create_mountpoint_fn * create_mountpoint;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_factory_init_default(
|
||||
struct wf_impl_mountpoint_factory * factory);
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_factory_init(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
wf_create_mountpoint_fn * create_mountpoint,
|
||||
void * user_data);
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_factory_clone(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
struct wf_impl_mountpoint_factory * other);
|
||||
|
||||
extern bool
|
||||
wf_impl_mountpoint_factory_isvalid(
|
||||
struct wf_impl_mountpoint_factory * factory);
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_factory_init_from(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
struct wf_impl_mountpoint_factory * other);
|
||||
|
||||
extern void
|
||||
wf_impl_mountpoint_factory_cleanup(
|
||||
struct wf_impl_mountpoint_factory * factory);
|
||||
|
||||
extern struct wf_mountpoint *
|
||||
wf_impl_mountpoint_factory_create_mountpoint(
|
||||
struct wf_impl_mountpoint_factory * factory,
|
||||
char const * filesystem);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,20 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_CLOSE_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_CLOSE_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern void wf_impl_operation_close(
|
||||
fuse_req_t request,
|
||||
fuse_ino_t inode,
|
||||
struct fuse_file_info * file_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,18 @@
|
||||
#include "webfuse/adapter/impl/operation/context.h"
|
||||
#include "webfuse/adapter/impl/session_manager.h"
|
||||
#include "webfuse/adapter/impl/session.h"
|
||||
#include <stddef.h>
|
||||
|
||||
struct wf_jsonrpc_proxy * wf_impl_operation_context_get_proxy(
|
||||
struct wf_impl_operation_context * context)
|
||||
{
|
||||
struct wf_jsonrpc_proxy * proxy = NULL;
|
||||
|
||||
struct wf_impl_session * session = context->session;
|
||||
if (NULL != session)
|
||||
{
|
||||
proxy = session->rpc;
|
||||
}
|
||||
|
||||
return proxy;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_CONTEXT_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_CONTEXT_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct wf_impl_session;
|
||||
struct wf_jsonrpc_proxy;
|
||||
|
||||
struct wf_impl_operation_context
|
||||
{
|
||||
struct wf_impl_session * session;
|
||||
double timeout;
|
||||
char * name;
|
||||
};
|
||||
|
||||
extern struct wf_jsonrpc_proxy * wf_impl_operation_context_get_proxy(
|
||||
struct wf_impl_operation_context * context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,37 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_GETATTR_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_GETATTR_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
|
||||
#include <jansson.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_operation_getattr_context
|
||||
{
|
||||
fuse_req_t request;
|
||||
fuse_ino_t inode;
|
||||
double timeout;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
extern void wf_impl_operation_getattr_finished(
|
||||
void * user_data,
|
||||
json_t const * result,
|
||||
json_t const * error);
|
||||
|
||||
extern void wf_impl_operation_getattr (
|
||||
fuse_req_t request,
|
||||
fuse_ino_t inode,
|
||||
struct fuse_file_info *file_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,36 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_LOOKUP_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_LOOKUP_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
|
||||
#include <jansson.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_operation_lookup_context
|
||||
{
|
||||
fuse_req_t request;
|
||||
double timeout;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
extern void wf_impl_operation_lookup_finished(
|
||||
void * user_data,
|
||||
json_t const * result,
|
||||
json_t const * error);
|
||||
|
||||
extern void wf_impl_operation_lookup (
|
||||
fuse_req_t req,
|
||||
fuse_ino_t parent,
|
||||
char const * name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,26 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_OPEN_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_OPEN_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern void wf_impl_operation_open(
|
||||
fuse_req_t request,
|
||||
fuse_ino_t inode,
|
||||
struct fuse_file_info * file_info);
|
||||
|
||||
extern void wf_impl_operation_open_finished(
|
||||
void * user_data,
|
||||
json_t const * result,
|
||||
json_t const * error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,36 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_READ_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_READ_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
#include "webfuse/core/status.h"
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern void wf_impl_operation_read(
|
||||
fuse_req_t request,
|
||||
fuse_ino_t ino, size_t size, off_t off,
|
||||
struct fuse_file_info *fi);
|
||||
|
||||
extern char * wf_impl_fill_buffer(
|
||||
char const * data,
|
||||
size_t data_size,
|
||||
char const * format,
|
||||
size_t count,
|
||||
wf_status * status);
|
||||
|
||||
extern void wf_impl_operation_read_finished(
|
||||
void * user_data,
|
||||
json_t const * result,
|
||||
json_t const * error);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,35 @@
|
||||
#ifndef WF_ADAPTER_IMPL_OPERATION_READDIR_H
|
||||
#define WF_ADAPTER_IMPL_OPERATION_READDIR_H
|
||||
|
||||
#include "webfuse/adapter/impl/fuse_wrapper.h"
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wf_impl_operation_readdir_context
|
||||
{
|
||||
fuse_req_t request;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
};
|
||||
|
||||
extern void wf_impl_operation_readdir (
|
||||
fuse_req_t request,
|
||||
fuse_ino_t inode,
|
||||
size_t size,
|
||||
off_t offset,
|
||||
struct fuse_file_info *file_info);
|
||||
|
||||
extern void wf_impl_operation_readdir_finished(
|
||||
void * user_data,
|
||||
json_t const * result,
|
||||
json_t const * error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
#include "webfuse/adapter/impl/operations.h"
|
||||
#include "webfuse/adapter/impl/session_manager.h"
|
||||
#include "webfuse/adapter/impl/session.h"
|
||||
#include <stddef.h>
|
||||
|
||||
struct wf_impl_jsonrpc_proxy * wf_impl_operations_context_get_proxy(
|
||||
struct wf_impl_operations_context * context)
|
||||
{
|
||||
struct wf_impl_jsonrpc_proxy * proxy = NULL;
|
||||
|
||||
struct wf_impl_session * session = context->session;
|
||||
if (NULL != session)
|
||||
{
|
||||
proxy = &session->rpc;
|
||||
}
|
||||
|
||||
return proxy;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue