From c5cf13e1b7890a0a9bbcbd6352649fe2a0a13d46 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Sun, 19 Apr 2026 23:07:17 -0500 Subject: [PATCH] Change html to dark mode by default and stat in vfs --- .gitea/workflows/tag.yaml | 23 +- .onedev-buildspec.yml | 52 -- CMakeLists.txt | 79 +-- Dockerfile | 5 - Dockerfile.run | 3 - Packaging/Linux/PKGBUILD | 20 +- Packaging/Linux/build-arch.sh | 4 +- Packaging/Linux/build-ubuntu-jammy.sh | 46 -- Packaging/Linux/build-ubuntu-plucky.sh | 57 -- Packaging/Linux/make-control.sh | 8 - Packaging/Linux/push-ubuntu-jammy.sh | 22 - Packaging/Linux/push-ubuntu-plucky.sh | 27 - Packaging/Linux/version.sh | 1 - apps/tanonydrop.cpp | 15 +- cmake/sources.cmake | 60 ++ .../portable-json-creator/docker-compose.yml | 4 +- examples/runevent.cpp | 22 - examples/timer.cpp | 17 + examples/webserverex.cpp | 39 +- include/TessesFramework/Common.hpp | 127 ++-- .../TessesFramework/Filesystem/LocalFS.hpp | 32 +- .../Filesystem/MemoryFilesystem.hpp | 100 --- .../Filesystem/MountableFilesystem.hpp | 24 +- .../Filesystem/NullFilesystem.hpp | 13 +- .../Filesystem/SubdirFilesystem.hpp | 18 +- include/TessesFramework/Filesystem/TempFS.hpp | 20 +- include/TessesFramework/Filesystem/VFS.hpp | 152 +++- include/TessesFramework/Http/HttpServer.hpp | 26 +- include/TessesFramework/TessesFramework.hpp | 3 +- pkgconfig/CMakeLists.txt | 4 +- src/Filesystem/LocalFS.cpp | 118 +-- src/Filesystem/MemoryFilesystem.cpp | 669 ------------------ src/Filesystem/MountableFilesystem.cpp | 311 +++----- src/Filesystem/NullFilesystem.cpp | 29 +- src/Filesystem/SubdirFilesystem.cpp | 68 +- src/Filesystem/TempFS.cpp | 84 +-- src/Filesystem/VFS.cpp | 182 ++++- src/Http/FileServer.cpp | 18 +- src/Http/HttpServer.cpp | 259 +++---- src/TF_Init.cpp | 305 +++++--- 40 files changed, 1110 insertions(+), 1956 deletions(-) delete mode 100644 .onedev-buildspec.yml delete mode 100644 Dockerfile delete mode 100644 Dockerfile.run delete mode 100644 Packaging/Linux/build-ubuntu-jammy.sh delete mode 100644 Packaging/Linux/build-ubuntu-plucky.sh delete mode 100644 Packaging/Linux/make-control.sh delete mode 100644 Packaging/Linux/push-ubuntu-jammy.sh delete mode 100644 Packaging/Linux/push-ubuntu-plucky.sh delete mode 100644 Packaging/Linux/version.sh create mode 100644 cmake/sources.cmake delete mode 100644 examples/runevent.cpp create mode 100644 examples/timer.cpp delete mode 100644 include/TessesFramework/Filesystem/MemoryFilesystem.hpp delete mode 100644 src/Filesystem/MemoryFilesystem.cpp diff --git a/.gitea/workflows/tag.yaml b/.gitea/workflows/tag.yaml index 73192cf..11cc1f1 100644 --- a/.gitea/workflows/tag.yaml +++ b/.gitea/workflows/tag.yaml @@ -2,7 +2,7 @@ name: Build and Deploy on Tag on: push: tags: - - 'v*' + - "v*" env: GITEA_AUTH: ${{ secrets.MY_GITEA_AUTH }} @@ -20,24 +20,3 @@ jobs: - run: chown build:build /home/build/PKGBUILD - run: chown build:build /home/build/build-arch.sh - run: su build -c /home/build/build-arch.sh - build-jammy: - runs-on: deb-builder-jammy - steps: - - uses: actions/checkout@v4 - - name: Build for jammy, noble - run: | - bash build-ubuntu-jammy.sh - bash push-ubuntu-jammy.sh - working-directory: ./Packaging/Linux - build-plucky: - runs-on: deb-builder-plucky - steps: - - uses: actions/checkout@v4 - - name: Build for plucky, resolute - run: | - bash build-ubuntu-plucky.sh - bash push-ubuntu-plucky.sh - working-directory: ./Packaging/Linux - - uses: akkuman/gitea-release-action@v1 - env: - NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18 diff --git a/.onedev-buildspec.yml b/.onedev-buildspec.yml deleted file mode 100644 index bf24d70..0000000 --- a/.onedev-buildspec.yml +++ /dev/null @@ -1,52 +0,0 @@ -version: 43 -jobs: -- name: Build for x86_64 - steps: - - type: CheckoutStep - name: Checkout - cloneCredential: - type: DefaultCredential - withLfs: true - withSubmodules: false - condition: SUCCESSFUL - optional: false - - type: CommandStep - name: Execute build - runInContainer: true - image: onedev.site.tesses.net/dependencies/dependencies:latest - interpreter: - type: DefaultInterpreter - commands: | - mkdir build - cd build - cmake -S .. -B . -DTESSESFRAMEWORK_FETCHCONTENT=OFF - make -j12 - make install DESTDIR=out - useTTY: true - condition: SUCCESSFUL - optional: false - - type: BuildImageStep - name: Build Docker Image - dockerfile: Dockerfile.run - output: - type: RegistryOutput - tags: onedev.site.tesses.net/tesses-framework/tesses-framework:latest onedev.site.tesses.net/tesses-framework/tesses-framework:@commit_hash@ git.tesseslanguage.com/tesses50/tesses-framework:latest git.tesseslanguage.com/tesses50/tesses-framework:@commit_hash@ - registryLogins: - - registryUrl: '@server_url@' - userName: '@job_token@' - passwordSecret: dockersecret - - registryUrl: git.tesseslanguage.com - userName: tesses50 - passwordSecret: GITEA_AUTH - platforms: linux/amd64 - condition: SUCCESSFUL - optional: false - triggers: - - type: BranchUpdateTrigger - branches: master - userMatch: anyone - projects: tesses-framework - retryCondition: never - maxRetries: 3 - retryDelay: 30 - timeout: 14400 diff --git a/CMakeLists.txt b/CMakeLists.txt index 2543117..21bb950 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,68 +7,7 @@ set(TESSESFRAMEWORK_PATCH_VERSION 2) project(TessesFramework VERSION ${TESSESFRAMEWORK_MAJOR_VERSION}.${TESSESFRAMEWORK_MINOR_VERSION}.${TESSESFRAMEWORK_PATCH_VERSION}) set(CMAKE_CXX_STANDARD 17) - -list(APPEND TESSESFRAMEWORK_SOURCE -src/Random.cpp -src/Date/Date.cpp -src/Http/FileServer.cpp -src/Http/MountableServer.cpp -src/Http/RouteServer.cpp -src/Http/CallbackServer.cpp -src/Http/HttpServer.cpp -src/Http/HttpUtils.cpp -src/Http/HttpClient.cpp -src/Http/HttpStream.cpp -src/Http/ContentDisposition.cpp -src/Http/WebSocket.cpp -src/Http/ChangeableServer.cpp -src/Http/BasicAuthServer.cpp -src/Http/CGIServer.cpp -src/Mail/Smtp.cpp -src/Serialization/Json.cpp -src/Serialization/SQLite.cpp -src/Serialization/BitConverter.cpp -src/Serialization/Bencode.cpp -src/Platform/Environment.cpp -src/Platform/Process.cpp -src/Streams/FileStream.cpp -src/Streams/MemoryStream.cpp -src/Streams/NetworkStream.cpp -src/Streams/Stream.cpp -src/Streams/BufferedStream.cpp -src/Streams/ByteReader.cpp -src/Streams/ByteWriter.cpp -src/Streams/PtyStream.cpp -src/Text/StringConverter.cpp -src/Text/HeaderGenerator.cpp -src/TextStreams/StreamReader.cpp -src/TextStreams/StreamWriter.cpp -src/TextStreams/TextReader.cpp -src/TextStreams/TextWriter.cpp -src/TextStreams/StdIOReader.cpp -src/TextStreams/StdIOWriter.cpp -src/TextStreams/StringReader.cpp -src/TextStreams/StringWriter.cpp -src/Threading/Thread.cpp -src/Threading/Mutex.cpp -src/Threading/ThreadPool.cpp -src/Filesystem/VFS.cpp -src/Filesystem/LocalFS.cpp -src/Filesystem/MemoryFilesystem.cpp -src/Filesystem/SubdirFilesystem.cpp -src/Filesystem/NullFilesystem.cpp -src/Filesystem/MountableFilesystem.cpp -src/Filesystem/FSHelpers.cpp -src/Filesystem/TempFS.cpp -src/Crypto/MbedTLS/ClientTLSStream.cpp -src/Crypto/MbedTLS/Crypto.cpp -src/Args.cpp -src/TF_Init.cpp -src/HiddenField.cpp -src/Uuid.cpp -src/BitTorrent/TorrentFile.cpp -src/BitTorrent/TorrentStream.cpp -) +include(cmake/sources.cmake) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) @@ -82,7 +21,7 @@ option(TESSESFRAMEWORK_ENABLE_PROCESS "Enable process api" ON) option(TESSESFRAMEWORK_ENABLE_RPATH "Enable RPATH" ON) if(TESSESFRAMEWORK_ENABLE_SQLITE) -list(APPEND TESSESFRAMEWORK_SOURCE +list(APPEND TESSESFRAMEWORK_SOURCE src/Serialization/sqlite/sqlite3-mod.c src/Serialization/sqlite/vfs.c ) @@ -145,12 +84,12 @@ endif() FetchContent_Declare( mbedtls URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.4.tar.bz2 - + ) FetchContent_MakeAvailable(mbedtls) else() -set(MBEDTLS_DIR "" CACHE PATH "Mbed tls directory") +find_package(MbedTLS REQUIRED) endif() endif() @@ -280,7 +219,7 @@ if(TESSESFRAMEWORK_FETCHCONTENT) target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m) else() -target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto) +target_link_libraries(tessesframework_shared PUBLIC MbedTLS::mbedcrypto MbedTLS::mbedtls MbedTLS::mbedx509) endif() endif() @@ -300,7 +239,7 @@ endif() if(TESSESFRAMEWORK_INSTALL_DEVELOPMENT) -install(TARGETS ${TessesFrameworkLibs} +install(TARGETS ${TessesFrameworkLibs} EXPORT TessesFrameworkTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -329,6 +268,8 @@ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework) endif() if(TESSESFRAMEWORK_ENABLE_EXAMPLES) + add_executable(timer examples/timer.cpp) + target_link_libraries(timer PUBLIC tessesframework) add_executable(copyfile examples/copyfile.cpp) target_link_libraries(copyfile PUBLIC tessesframework) @@ -351,8 +292,6 @@ if(TESSESFRAMEWORK_ENABLE_EXAMPLES) add_executable(wsecho examples/wsecho.cpp) target_link_libraries(wsecho PUBLIC tessesframework) - add_executable(runevent examples/runevent.cpp) - target_link_libraries(runevent PUBLIC tessesframework) add_executable(tests examples/tests.cpp) target_link_libraries(tests PUBLIC tessesframework) @@ -434,4 +373,4 @@ set(CPACK_PACKAGE_VERSION_MINOR "${TessesFramework_VERSION_MINOR}") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmbedtls-dev (>= 2.28.8)") include(CPack) -add_subdirectory(pkgconfig) \ No newline at end of file +add_subdirectory(pkgconfig) diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 54ca02d..0000000 --- a/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM ubuntu:noble - -RUN apt update && apt install -y cmake g++ gcc libmbedtls-dev build-essential git ca-certificates - -RUN mkdir /src && cd /src && git clone https://onedev.site.tesses.net/tesses-framework . && mkdir build && cd build && cmake -S .. -B . && make -j12 && make install && cd / && rm -r /src diff --git a/Dockerfile.run b/Dockerfile.run deleted file mode 100644 index 9263f16..0000000 --- a/Dockerfile.run +++ /dev/null @@ -1,3 +0,0 @@ -FROM onedev.site.tesses.net/dependencies/dependencies:latest -COPY build/out / - diff --git a/Packaging/Linux/PKGBUILD b/Packaging/Linux/PKGBUILD index ef5f5f5..0988598 100644 --- a/Packaging/Linux/PKGBUILD +++ b/Packaging/Linux/PKGBUILD @@ -1,16 +1,16 @@ # Maintainer: Mike Nolan -pkgname=tesses-framework # '-bzr', '-git', '-hg' or '-svn' -pkgver=0.0.2 +pkgname=tessesframework # '-bzr', '-git', '-hg' or '-svn' +pkgver=0.0.3 pkgrel=1 pkgdesc="" arch=('x86_64' 'powerpc') -url="https://onedev.site.tesses.net/tesses-framework" +url="https://git.tesses.org/tessesframework" license=('MIT') groups=() depends=('mbedtls') makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion' install= -source=('tesses-framework::git+https://onedev.site.tesses.net/tesses-framework') +source=('tessesframework::git+https://git.tesses.org/tesses-framework') noextract=() sha256sums=('SKIP') if [[ -z "$CMAKE_TOOLCHAIN" ]]; then @@ -22,22 +22,21 @@ fi prepare() { cd "$srcdir/${pkgname}" - wget https://downloads.tesses.net/ShellPackage.crvm } build() { cd "$srcdir/${pkgname}" mkdir build - + if [[ -z "$CMAKE_TOOLCHAIN" ]]; then - cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo + cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release else - cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN" + cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN" fi - + cd build make -j`nproc` - + } @@ -47,4 +46,3 @@ package() { cd "$srcdir/${pkgname}/build" make install DESTDIR="$pkgdir/" } - diff --git a/Packaging/Linux/build-arch.sh b/Packaging/Linux/build-arch.sh index f47c5db..0d58a63 100644 --- a/Packaging/Linux/build-arch.sh +++ b/Packaging/Linux/build-arch.sh @@ -6,7 +6,7 @@ cp ../PKGBUILD . makepkg curl --user tesses50:$GITEA_AUTH \ --upload-file *.pkg.tar.zst \ - https://git.tesseslanguage.com/api/packages/tesses50/arch/core + https://git.tesses.org/api/packages/tesses50/arch/core cd .. mkdir powerpc cd powerpc @@ -14,4 +14,4 @@ cp ../PKGBUILD . CARCH=powerpc CMAKE_TOOLCHAIN=/opt/cross/ppc/toolchain.cmake makepkg curl --user tesses50:$GITEA_AUTH \ --upload-file *.pkg.tar.zst \ - https://git.tesseslanguage.com/api/packages/tesses50/arch/core + https://git.tesses.org/api/packages/tesses50/arch/core diff --git a/Packaging/Linux/build-ubuntu-jammy.sh b/Packaging/Linux/build-ubuntu-jammy.sh deleted file mode 100644 index e38414d..0000000 --- a/Packaging/Linux/build-ubuntu-jammy.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -source ./version.sh -mkdir -p build/jammy -cd build/jammy -mkdir build-amd64 -cmake -S ../../../../ -B build-amd64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -cd build-amd64 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_amd64 -mkdir -p ../tessesframework_$DEB_VERSION\_amd64/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_amd64/DEBIAN/control amd64 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_amd64 - -# ARM64 -mkdir build-arm64 -cmake -S ../../../../ -B build-arm64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/arm64.cmake -cd build-arm64 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_arm64 -mkdir -p ../tessesframework_$DEB_VERSION\_arm64/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_arm64/DEBIAN/control arm64 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_arm64 - -# RISCV64 -mkdir build-riscv64 -cmake -S ../../../../ -B build-riscv64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/riscv64.cmake -cd build-riscv64 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_riscv64 -mkdir -p ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN/control riscv64 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_riscv64 - -# ARMHF -mkdir build-armhf -cmake -S ../../../../ -B build-armhf -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/armhf.cmake -cd build-armhf -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_armhf -mkdir -p ../tessesframework_$DEB_VERSION\_armhf/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_armhf/DEBIAN/control armhf -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_armhf \ No newline at end of file diff --git a/Packaging/Linux/build-ubuntu-plucky.sh b/Packaging/Linux/build-ubuntu-plucky.sh deleted file mode 100644 index 64284e4..0000000 --- a/Packaging/Linux/build-ubuntu-plucky.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -source ./version.sh -mkdir -p build/plucky -cd build/plucky -mkdir build-amd64 -cmake -S ../../../../ -B build-amd64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -cd build-amd64 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_amd64 -mkdir -p ../tessesframework_$DEB_VERSION\_amd64/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_amd64/DEBIAN/control amd64 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_amd64 - -# ARM64 -mkdir build-arm64 -cmake -S ../../../../ -B build-arm64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/arm64.cmake -cd build-arm64 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_arm64 -mkdir -p ../tessesframework_$DEB_VERSION\_arm64/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_arm64/DEBIAN/control arm64 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_arm64 - -# RISCV64 -mkdir build-riscv64 -cmake -S ../../../../ -B build-riscv64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/riscv64.cmake -cd build-riscv64 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_riscv64 -mkdir -p ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN/control riscv64 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_riscv64 - -# ARMHF -mkdir build-armhf -cmake -S ../../../../ -B build-armhf -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/armhf.cmake -cd build-armhf -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_armhf -mkdir -p ../tessesframework_$DEB_VERSION\_armhf/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_armhf/DEBIAN/control armhf -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_armhf - -# I386 -mkdir build-i386 -cmake -S ../../../../ -B build-i386 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/i386.cmake -cd build-i386 -make -j`nproc` -make install DESTDIR=../tessesframework_$DEB_VERSION\_i386 -mkdir -p ../tessesframework_$DEB_VERSION\_i386/DEBIAN -bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_i386/DEBIAN/control i386 -cd ../ -dpkg-deb --build tessesframework_$DEB_VERSION\_i386 \ No newline at end of file diff --git a/Packaging/Linux/make-control.sh b/Packaging/Linux/make-control.sh deleted file mode 100644 index 7b51694..0000000 --- a/Packaging/Linux/make-control.sh +++ /dev/null @@ -1,8 +0,0 @@ -echo "Package: tessesframework" > "$1" -echo "Version: $DEB_VERSION" >> "$1" -echo "Architecture: $2" >> "$1" -echo "Essential: no" >> "$1" -echo "Priority: optional" >> "$1" -echo "Depends: libmbedtls-dev" >> "$1" -echo "Maintainer: Mike Nolan" >> "$1" -echo "Description: A cross platform wrapper library" >> "$1" \ No newline at end of file diff --git a/Packaging/Linux/push-ubuntu-jammy.sh b/Packaging/Linux/push-ubuntu-jammy.sh deleted file mode 100644 index e9ceb15..0000000 --- a/Packaging/Linux/push-ubuntu-jammy.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -source ./version.sh -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/amd64 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/arm64 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/riscv64 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/armhf -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/jammy/tessesframework_$DEB_VERSION\_amd64.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/jammy/tessesframework_$DEB_VERSION\_arm64.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/jammy/tessesframework_$DEB_VERSION\_riscv64.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/jammy/tessesframework_$DEB_VERSION\_armhf.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload \ No newline at end of file diff --git a/Packaging/Linux/push-ubuntu-plucky.sh b/Packaging/Linux/push-ubuntu-plucky.sh deleted file mode 100644 index 71054b1..0000000 --- a/Packaging/Linux/push-ubuntu-plucky.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -source ./version.sh -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/amd64 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/arm64 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/i386 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/riscv64 -curl --user tesses50:$GITEA_AUTH -X DELETE \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/armhf -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/plucky/tessesframework_$DEB_VERSION\_amd64.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/plucky/tessesframework_$DEB_VERSION\_arm64.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/plucky/tessesframework_$DEB_VERSION\_i386.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/plucky/tessesframework_$DEB_VERSION\_riscv64.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload -curl --user tesses50:$GITEA_AUTH \ - --upload-file build/plucky/tessesframework_$DEB_VERSION\_armhf.deb \ - https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload \ No newline at end of file diff --git a/Packaging/Linux/version.sh b/Packaging/Linux/version.sh deleted file mode 100644 index 06565cf..0000000 --- a/Packaging/Linux/version.sh +++ /dev/null @@ -1 +0,0 @@ -export DEB_VERSION=0.0.2 \ No newline at end of file diff --git a/apps/tanonydrop.cpp b/apps/tanonydrop.cpp index 6f1604f..915fc01 100644 --- a/apps/tanonydrop.cpp +++ b/apps/tanonydrop.cpp @@ -21,9 +21,9 @@ int main(int argc, char** argv) .SendText( "" "" - "AnonyDump" + "AnonyDrop" "" - "

AnonyDump

" + "

AnonyDrop

" "Files" "
" "" @@ -43,19 +43,18 @@ int main(int argc, char** argv) if(name != "file") return nullptr; VFSPath path("/"+filename); auto strm = vfs->OpenFile(path,"wb"); - + return strm; }); ctx.WithMimeType("text/html") .SendText( "" "" - "AnonyDump - Uploaded successfully" + "AnonyDrop - Uploaded successfully" "" "

Uploaded successfully

" "Back" - - "
" + "" "" ); @@ -71,7 +70,7 @@ int main(int argc, char** argv) "" "

Error: Must contain multipart and POST

" "Back" - + "" "" "" @@ -91,4 +90,4 @@ int main(int argc, char** argv) TF_Quit(); return 0; -} \ No newline at end of file +} diff --git a/cmake/sources.cmake b/cmake/sources.cmake new file mode 100644 index 0000000..fafa569 --- /dev/null +++ b/cmake/sources.cmake @@ -0,0 +1,60 @@ +list(APPEND TESSESFRAMEWORK_SOURCE +src/Random.cpp +src/Date/Date.cpp +src/Http/FileServer.cpp +src/Http/MountableServer.cpp +src/Http/RouteServer.cpp +src/Http/CallbackServer.cpp +src/Http/HttpServer.cpp +src/Http/HttpUtils.cpp +src/Http/HttpClient.cpp +src/Http/HttpStream.cpp +src/Http/ContentDisposition.cpp +src/Http/WebSocket.cpp +src/Http/ChangeableServer.cpp +src/Http/BasicAuthServer.cpp +src/Http/CGIServer.cpp +src/Mail/Smtp.cpp +src/Serialization/Json.cpp +src/Serialization/SQLite.cpp +src/Serialization/BitConverter.cpp +src/Serialization/Bencode.cpp +src/Platform/Environment.cpp +src/Platform/Process.cpp +src/Streams/FileStream.cpp +src/Streams/MemoryStream.cpp +src/Streams/NetworkStream.cpp +src/Streams/Stream.cpp +src/Streams/BufferedStream.cpp +src/Streams/ByteReader.cpp +src/Streams/ByteWriter.cpp +src/Streams/PtyStream.cpp +src/Text/StringConverter.cpp +src/Text/HeaderGenerator.cpp +src/TextStreams/StreamReader.cpp +src/TextStreams/StreamWriter.cpp +src/TextStreams/TextReader.cpp +src/TextStreams/TextWriter.cpp +src/TextStreams/StdIOReader.cpp +src/TextStreams/StdIOWriter.cpp +src/TextStreams/StringReader.cpp +src/TextStreams/StringWriter.cpp +src/Threading/Thread.cpp +src/Threading/Mutex.cpp +src/Threading/ThreadPool.cpp +src/Filesystem/VFS.cpp +src/Filesystem/LocalFS.cpp +src/Filesystem/SubdirFilesystem.cpp +src/Filesystem/NullFilesystem.cpp +src/Filesystem/MountableFilesystem.cpp +src/Filesystem/FSHelpers.cpp +src/Filesystem/TempFS.cpp +src/Crypto/MbedTLS/ClientTLSStream.cpp +src/Crypto/MbedTLS/Crypto.cpp +src/Args.cpp +src/TF_Init.cpp +src/HiddenField.cpp +src/Uuid.cpp +src/BitTorrent/TorrentFile.cpp +src/BitTorrent/TorrentStream.cpp +) diff --git a/docker-compose/portable-json-creator/docker-compose.yml b/docker-compose/portable-json-creator/docker-compose.yml index 2917c48..cd28232 100644 --- a/docker-compose/portable-json-creator/docker-compose.yml +++ b/docker-compose/portable-json-creator/docker-compose.yml @@ -1,5 +1,5 @@ services: portable-json: - image: onedev.site.tesses.net/tesses-framework/portable-json-creator:latest + image: git.tesses.org/tesses50/portable-json-creator:latest ports: - - "4999:4999" \ No newline at end of file + - "4999:4999" diff --git a/examples/runevent.cpp b/examples/runevent.cpp deleted file mode 100644 index 1efb605..0000000 --- a/examples/runevent.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "TessesFramework/TessesFramework.hpp" -using namespace Tesses::Framework; -int main(int argc, char** argv) -{ - TF_Init(); - auto event = std::make_shared>([](uint64_t n)->void { - std::cout << n << std::endl; - }); - OnItteraton += event; - - - auto event2 = std::make_shared>([&event](uint64_t n)->void{ - if(n == 10000) OnItteraton -= event; - }); - OnItteraton += event2; - - - TF_RunEventLoop(); - - return 0; - -} \ No newline at end of file diff --git a/examples/timer.cpp b/examples/timer.cpp new file mode 100644 index 0000000..50a7665 --- /dev/null +++ b/examples/timer.cpp @@ -0,0 +1,17 @@ +#include "TessesFramework/Common.hpp" +#include "TessesFramework/TessesFramework.hpp" + + +int main(int argc, char** argv) +{ + using namespace Tesses::Framework; + TF_Init(); + + auto timer = TF_Timer([]()->void { + std::cout << "Hi, I am a timer" << std::endl; + }); + + TF_RunEventLoop(); + + TF_Quit(); +} \ No newline at end of file diff --git a/examples/webserverex.cpp b/examples/webserverex.cpp index c79b342..536023e 100644 --- a/examples/webserverex.cpp +++ b/examples/webserverex.cpp @@ -1,5 +1,8 @@ #include "TessesFramework/TessesFramework.hpp" +#include +#include #include +#include using namespace Tesses::Framework; using namespace Tesses::Framework::Http; using namespace Tesses::Framework::Streams; @@ -26,7 +29,7 @@ class MyWebServer : public IHttpServer { if(ctx.path == "/") { std::shared_ptr fs = std::make_shared("index.html","rb"); - + ctx .WithMimeType("text/html") .SendStream(fs); @@ -62,7 +65,7 @@ class MyWebServer : public IHttpServer { for(size_t i=0;i<10000; i++) { writer.WriteLine("
  • " + std::to_string(i) + "
  • "); - + } writer.WriteLine(""); @@ -75,7 +78,7 @@ class MyWebServer : public IHttpServer { { std::shared_ptr fs = std::make_shared("main.js","rb"); - + ctx .WithMimeType("text/js") .SendStream(fs); @@ -92,10 +95,10 @@ class MyWebServer : public IHttpServer { Johnny* data = ctx.GetServerContentData("mytag"); data->text = "Demi Lovato"; } - + return false; } - + }; class MyOtherWebServer : public IHttpServer { @@ -115,10 +118,30 @@ class MyOtherWebServer : public IHttpServer .WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false) .SendText(name + " is cool."); //do something with q - + return true; } } + else if(ctx.path == "/status") + { + int64_t num; + if(ctx.queryParams.TryGetFirstInt("code", num)) + { + ctx.statusCode = (StatusCode)num; + } + + ctx.SendErrorPage(true); + return true; + } + else if(ctx.path == "/error") + { + throw std::runtime_error("This is a error"); + } + else if(ctx.path == "/error-debug") + { + ctx.WithDebug(true); + throw std::runtime_error("Platform is " + Tesses::Framework::Platform::Environment::GetPlatform()); + } else if(ctx.path == "/mymount/steve") { Johnny* data = ctx.GetServerContentData("mytag"); @@ -131,7 +154,7 @@ class MyOtherWebServer : public IHttpServer ctx.WithMimeType("text/html").SendText(txt); return true; } - + return false; } }; @@ -172,4 +195,4 @@ int main(int argc, char** argv) server.StartAccepting(); TF_RunEventLoop(); std::cout << "Closing server" << std::endl; -} \ No newline at end of file +} diff --git a/include/TessesFramework/Common.hpp b/include/TessesFramework/Common.hpp index 05b13e7..facc3c3 100644 --- a/include/TessesFramework/Common.hpp +++ b/include/TessesFramework/Common.hpp @@ -1,8 +1,11 @@ #pragma once +#include #include #include #include +#include +#include #include #include #include @@ -15,83 +18,55 @@ namespace Tesses::Framework { - template - class Event { - public: - virtual void Invoke(TArgs... args)=0; - virtual ~Event() - {} - }; - template - class FunctionalEvent : public Event { - std::function cb; - public: - FunctionalEvent(std::function cb) - { - this->cb = cb; - } - void Invoke(TArgs... args) - { - this->cb(args...); - } - }; - - template - class EventList : public Event { - Threading::Mutex mtx; - std::vector>> items; - public: - void operator+=(std::shared_ptr> event) - { - mtx.Lock(); - for(std::shared_ptr>& item : this->items) - { - if(item.get() == event.get()) { - mtx.Unlock(); - return; - } - } - this->items.push_back(event); - mtx.Unlock(); - } - void operator-=(std::shared_ptr> event) - { - mtx.Lock(); - for(auto i = this->items.begin(); i != this->items.end(); i++) - { - if(i->get() == event.get()) - { - this->items.erase(i); - mtx.Unlock(); - return; - } - } - mtx.Unlock(); - } - void Invoke(TArgs... args) - { - mtx.Lock(); - for(auto& item : this->items) - { - item->Invoke(args...); - } - mtx.Unlock(); - } - void Remove(std::function>)> cb) - { - for(auto index = this->items.begin(); index != this->items.end(); index++) - { - if(cb(*index)) - { - this->items.erase(index); - index--; - } - } - } - }; - - extern EventList OnItteraton; + std::optional TF_GetCommandName(); + class TF_Timer_Handle; + //Used for internal purposes, don't use unless you want to run timer events on another thread + + class TF_Timer_Handler { + private: + std::vector> handles; + public: + void Update(); + + + static std::shared_ptr Make(std::shared_ptr handler); + friend class TF_Timer_Handle; + }; + + class TF_Timer_Handle { + + private: + std::shared_ptr timerHandler; + std::function cb; + std::chrono::milliseconds interval; + std::chrono::time_point last; + bool enabled; + TF_Timer_Handle() = delete; + + TF_Timer_Handle(std::shared_ptr timerHandler); + + public: + + void SetCallback(std::function cb); + + int64_t GetIntervalMilliseconds(); + std::chrono::duration GetIntervalDuration(); + + void SetIntervalFromMilliseconds(int64_t ms); + + void SetIntervalFromDuration(std::chrono::milliseconds dur); + + + void SetEnabled(bool enabled); + bool GetEnabled(); + friend class TF_Timer_Handler; + }; + + + std::shared_ptr TF_Timer(); + std::shared_ptr TF_Timer(std::function cb, int64_t interval=1000, bool enabled=true); + std::shared_ptr TF_Timer(std::function cb, std::chrono::milliseconds interval, bool enabled=true); void TF_Init(); void TF_InitWithConsole(); diff --git a/include/TessesFramework/Filesystem/LocalFS.hpp b/include/TessesFramework/Filesystem/LocalFS.hpp index 38e8b9b..b9cc6ab 100644 --- a/include/TessesFramework/Filesystem/LocalFS.hpp +++ b/include/TessesFramework/Filesystem/LocalFS.hpp @@ -1,50 +1,46 @@ #pragma once #include "VFS.hpp" #include "VFSFix.hpp" - + namespace Tesses::Framework::Filesystem { class LocalFilesystem : public VFS { public: - + std::shared_ptr OpenFile(VFSPath path, std::string mode); - + void CreateDirectory(VFSPath path); void DeleteDirectory(VFSPath path); - bool RegularFileExists(VFSPath path); - bool SymlinkExists(VFSPath path); - bool CharacterDeviceExists(VFSPath path); - bool BlockDeviceExists(VFSPath path); - bool SocketFileExists(VFSPath path); - bool FIFOFileExists(VFSPath path); - bool DirectoryExists(VFSPath path); - + + void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); VFSPathEnumerator EnumeratePaths(VFSPath path); void CreateHardlink(VFSPath existingFile, VFSPath newName); - + void MoveFile(VFSPath src, VFSPath dest); - + void MoveDirectory(VFSPath src, VFSPath dest); VFSPath ReadLink(VFSPath path); std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); - - void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); - void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); + void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); + bool Stat(VFSPath path, StatData& stat); bool StatVFS(VFSPath path, StatVFSData& vfsData); void Chmod(VFSPath path, uint32_t mode); + void Chown(VFSPath path, uint32_t uid, uint32_t gid); void Lock(VFSPath path); void Unlock(VFSPath path); + FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mod); + protected: std::shared_ptr CreateWatcher(std::shared_ptr vfs, VFSPath path); - }; + }; extern std::shared_ptr LocalFS; -} \ No newline at end of file +} diff --git a/include/TessesFramework/Filesystem/MemoryFilesystem.hpp b/include/TessesFramework/Filesystem/MemoryFilesystem.hpp deleted file mode 100644 index 16627e8..0000000 --- a/include/TessesFramework/Filesystem/MemoryFilesystem.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once -#include "VFS.hpp" -#include "VFSFix.hpp" -#include "../Threading/Mutex.hpp" -#include -namespace Tesses::Framework::Filesystem -{ - class MemoryEntry { - public: - std::string name; - virtual ~MemoryEntry(); - }; - class MemoryFileData { - public: - MemoryFileData(); - Date::DateTime lastWrite; - - bool canAccess; - size_t readers; - std::vector file; - }; - - class MemoryFile : public MemoryEntry - { - public: - std::shared_ptr data; - ~MemoryFile(); - }; - - class MemoryDirectory : public MemoryEntry - { - public: - MemoryDirectory(); - Date::DateTime lastWrite; - std::vector entries; - ~MemoryDirectory(); - }; - - class MemorySymlink : public MemoryEntry - { - public: - Date::DateTime lastWrite; - VFSPath linkedTo; - }; - - class MemoryFilesystemStream : public Streams::Stream - { - public: - std::shared_ptr mtx; - std::shared_ptr data; - bool canRead; - bool canWrite; - bool canSeek; - int64_t pos; - MemoryFilesystemStream(std::shared_ptr mtx, std::shared_ptr data,bool canRead, bool canWrite, bool canSeek); - size_t Read(uint8_t* buff, size_t sz); - size_t Write(const uint8_t* buff, size_t sz); - bool CanRead(); - bool CanWrite(); - bool CanSeek(); - int64_t GetPosition(); - void Flush(); - void Seek(int64_t pos, Streams::SeekOrigin whence); - ~MemoryFilesystemStream(); - }; - - - class MemoryFilesystem : public VFS - { - std::shared_ptr mtx; - MemoryDirectory root; - - MemoryEntry* GetEntry(VFSPath path,bool followSymlink); - public: - MemoryFilesystem(); - std::shared_ptr OpenFile(VFSPath path, std::string mode); - - void CreateDirectory(VFSPath path); - void DeleteDirectory(VFSPath path); - bool RegularFileExists(VFSPath path); - bool SymlinkExists(VFSPath path); - bool DirectoryExists(VFSPath path); - - void DeleteFile(VFSPath path); - void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); - VFSPathEnumerator EnumeratePaths(VFSPath path); - void CreateHardlink(VFSPath existingFile, VFSPath newName); - - void MoveFile(VFSPath src, VFSPath dest); - - void MoveDirectory(VFSPath src, VFSPath dest); - VFSPath ReadLink(VFSPath path); - std::string VFSPathToSystem(VFSPath path); - VFSPath SystemToVFSPath(std::string path); - void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); - void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); - - ~MemoryFilesystem(); - }; -}; \ No newline at end of file diff --git a/include/TessesFramework/Filesystem/MountableFilesystem.hpp b/include/TessesFramework/Filesystem/MountableFilesystem.hpp index 03dafe9..31ee049 100644 --- a/include/TessesFramework/Filesystem/MountableFilesystem.hpp +++ b/include/TessesFramework/Filesystem/MountableFilesystem.hpp @@ -1,7 +1,7 @@ #pragma once #include "VFS.hpp" #include "VFSFix.hpp" - + namespace Tesses::Framework::Filesystem { class MountableDirectory { @@ -19,10 +19,10 @@ namespace Tesses::Framework::Filesystem std::shared_ptr root; std::vector directories; - + void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr& vfs); - + public: MountableFilesystem(); MountableFilesystem(std::shared_ptr root); @@ -31,15 +31,7 @@ namespace Tesses::Framework::Filesystem std::shared_ptr OpenFile(VFSPath path, std::string mode); void CreateDirectory(VFSPath path); void DeleteDirectory(VFSPath path); - bool SpecialFileExists(VFSPath path); - bool FileExists(VFSPath path); - bool RegularFileExists(VFSPath path); - bool SymlinkExists(VFSPath path); - bool CharacterDeviceExists(VFSPath path); - bool BlockDeviceExists(VFSPath path); - bool SocketFileExists(VFSPath path); - bool FIFOFileExists(VFSPath path); - bool DirectoryExists(VFSPath path); + bool Stat(VFSPath path, StatData& data); void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); VFSPathEnumerator EnumeratePaths(VFSPath path); @@ -50,14 +42,18 @@ namespace Tesses::Framework::Filesystem std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); ~MountableFilesystem(); - void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); bool StatVFS(VFSPath path, StatVFSData& vfsData); void Chmod(VFSPath path, uint32_t mode); + void Chown(VFSPath path, uint32_t uid, uint32_t gid); + FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode); + void Lock(VFSPath path); void Unlock(VFSPath path); + + }; -} \ No newline at end of file +} diff --git a/include/TessesFramework/Filesystem/NullFilesystem.hpp b/include/TessesFramework/Filesystem/NullFilesystem.hpp index f963139..ab30c88 100644 --- a/include/TessesFramework/Filesystem/NullFilesystem.hpp +++ b/include/TessesFramework/Filesystem/NullFilesystem.hpp @@ -1,21 +1,16 @@ #pragma once #include "VFS.hpp" #include "VFSFix.hpp" - + namespace Tesses::Framework::Filesystem { class NullFilesystem : public VFS { - public: + public: std::shared_ptr OpenFile(VFSPath path, std::string mode); - void CreateDirectory(VFSPath path); - void DeleteDirectory(VFSPath path); - bool RegularFileExists(VFSPath path); - bool DirectoryExists(VFSPath path); - void DeleteFile(VFSPath path); VFSPathEnumerator EnumeratePaths(VFSPath path); - void MoveFile(VFSPath src, VFSPath dest); + bool Stat(VFSPath path, StatData& data); std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); }; -} \ No newline at end of file +} diff --git a/include/TessesFramework/Filesystem/SubdirFilesystem.hpp b/include/TessesFramework/Filesystem/SubdirFilesystem.hpp index 3a14e40..bbf6db0 100644 --- a/include/TessesFramework/Filesystem/SubdirFilesystem.hpp +++ b/include/TessesFramework/Filesystem/SubdirFilesystem.hpp @@ -1,7 +1,7 @@ #pragma once #include "VFS.hpp" #include "VFSFix.hpp" - + namespace Tesses::Framework::Filesystem { class SubdirFilesystem : public VFS @@ -15,15 +15,6 @@ namespace Tesses::Framework::Filesystem std::shared_ptr OpenFile(VFSPath path, std::string mode); void CreateDirectory(VFSPath path); void DeleteDirectory(VFSPath path); - bool SpecialFileExists(VFSPath path); - bool FileExists(VFSPath path); - bool RegularFileExists(VFSPath path); - bool SymlinkExists(VFSPath path); - bool CharacterDeviceExists(VFSPath path); - bool BlockDeviceExists(VFSPath path); - bool SocketFileExists(VFSPath path); - bool FIFOFileExists(VFSPath path); - bool DirectoryExists(VFSPath path); void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); VFSPathEnumerator EnumeratePaths(VFSPath path); @@ -35,13 +26,14 @@ namespace Tesses::Framework::Filesystem std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); ~SubdirFilesystem(); - void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); bool StatVFS(VFSPath path, StatVFSData& vfsData); + bool Stat(VFSPath path, StatData& data); + void Chown(VFSPath path, uint32_t uid, uint32_t gid); void Chmod(VFSPath path, uint32_t mode); - + FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode); void Lock(VFSPath path); void Unlock(VFSPath path); }; -} \ No newline at end of file +} diff --git a/include/TessesFramework/Filesystem/TempFS.hpp b/include/TessesFramework/Filesystem/TempFS.hpp index f4527e3..3bd8c5e 100644 --- a/include/TessesFramework/Filesystem/TempFS.hpp +++ b/include/TessesFramework/Filesystem/TempFS.hpp @@ -2,7 +2,7 @@ #include "../Common.hpp" #include "VFS.hpp" #include "VFSFix.hpp" -namespace Tesses::Framework::Filesystem +namespace Tesses::Framework::Filesystem { void UniqueString(std::string& text); @@ -20,15 +20,6 @@ namespace Tesses::Framework::Filesystem std::shared_ptr OpenFile(VFSPath path, std::string mode); void CreateDirectory(VFSPath path); void DeleteDirectory(VFSPath path); - bool SpecialFileExists(VFSPath path); - bool FileExists(VFSPath path); - bool RegularFileExists(VFSPath path); - bool SymlinkExists(VFSPath path); - bool CharacterDeviceExists(VFSPath path); - bool BlockDeviceExists(VFSPath path); - bool SocketFileExists(VFSPath path); - bool FIFOFileExists(VFSPath path); - bool DirectoryExists(VFSPath path); void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); VFSPathEnumerator EnumeratePaths(VFSPath path); @@ -39,16 +30,19 @@ namespace Tesses::Framework::Filesystem VFSPath ReadLink(VFSPath path); std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); - - void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); + void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); bool StatVFS(VFSPath path, StatVFSData& vfsData); + bool Stat(VFSPath path, StatData& data); void Chmod(VFSPath path, uint32_t mode); + + void Chown(VFSPath path, uint32_t uid, uint32_t gid); + FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode); void Close(); void Lock(VFSPath path); void Unlock(VFSPath path); ~TempFS(); }; -} \ No newline at end of file +} diff --git a/include/TessesFramework/Filesystem/VFS.hpp b/include/TessesFramework/Filesystem/VFS.hpp index 755caed..c7b4aff 100644 --- a/include/TessesFramework/Filesystem/VFS.hpp +++ b/include/TessesFramework/Filesystem/VFS.hpp @@ -1,16 +1,18 @@ #pragma once #include "../Common.hpp" #include "../Streams/Stream.hpp" +#include +#include #include #include #include "../Date/Date.hpp" #include "VFSFix.hpp" - + namespace Tesses::Framework::Filesystem { - class StatVFSData { - public: + struct StatVFSData { + uint64_t BlockSize; uint64_t FragmentSize; uint64_t Blocks; @@ -23,12 +25,94 @@ namespace Tesses::Framework::Filesystem uint64_t Flags; uint64_t MaxNameLength; }; + + constexpr uint32_t MODE_USER_READ = 0400; + constexpr uint32_t MODE_USER_WRITE = 0200; + constexpr uint32_t MODE_USER_EXEC = 0100; + + constexpr uint32_t MODE_GROUP_READ = (MODE_USER_READ >> 3); + constexpr uint32_t MODE_GROUP_WRITE = (MODE_USER_WRITE >> 3); + constexpr uint32_t MODE_GROUP_EXEC = (MODE_USER_EXEC >> 3); + + constexpr uint32_t MODE_OTHER_READ = (MODE_GROUP_READ >> 3); + constexpr uint32_t MODE_OTHER_WRITE = (MODE_GROUP_WRITE >> 3); + constexpr uint32_t MODE_OTHER_EXEC = (MODE_GROUP_EXEC >> 3); + + constexpr uint32_t MODE_REGULAR = 0100000; + constexpr uint32_t MODE_DIRECTORY = 0040000; + constexpr uint32_t MODE_CHAR_DEVICE = 0020000; + constexpr uint32_t MODE_BLOCK_DEVICE = 0060000; + constexpr uint32_t MODE_SOCKET = 0140000; + constexpr uint32_t MODE_FIFO = 0010000; + constexpr uint32_t MODE_SYMLINK = 0120000; + + + struct StatData { + uint64_t Device; + uint64_t Inode; + uint32_t Mode; + uint64_t HardLinks; + uint32_t UserId; + uint32_t GroupId; + uint64_t DeviceId; + uint64_t Size; + uint64_t BlockSize; + uint64_t BlockCount; + Date::DateTime LastAccess; + Date::DateTime LastModified; + Date::DateTime LastStatus; + + bool IsRegularFile() + { + return (Mode & MODE_REGULAR) > 0; + } + bool IsDirectory() + { + return (Mode & MODE_DIRECTORY) > 0; + } + + bool IsCharDevice() + { + return (Mode & MODE_CHAR_DEVICE) > 0; + } + + bool IsBlockDevice() + { + return (Mode & MODE_BLOCK_DEVICE) > 0; + } + + bool IsSocket() + { + return (Mode & MODE_SOCKET) > 0; + } + bool IsFIFO() + { + return (Mode & MODE_FIFO) > 0; + } + + bool IsSymlink() + { + return (Mode & MODE_SYMLINK) > 0; + } + + bool IsSpecial() + { + if(IsRegularFile()) return false; + if(IsDirectory()) return false; + return true; + } + + std::string ToSizeString(bool usesBin=true) + { + return TF_FileSize(this->Size, usesBin); + } + }; class VFSPath { public: static VFSPath CurrentDirectoryAsRelative(); bool relative; static std::vector SplitPath(std::string path); - std::vector path; + std::vector path; VFSPath(); explicit VFSPath(const char* path) : VFSPath(std::string(path)) {} @@ -36,7 +120,7 @@ namespace Tesses::Framework::Filesystem VFSPath(std::string path); VFSPath(VFSPath p, std::string subent); VFSPath(VFSPath p, VFSPath p2); - + //does not check for ? static VFSPath ParseUriPath(std::string path); @@ -52,7 +136,7 @@ namespace Tesses::Framework::Filesystem static VFSPath GetAbsoluteCurrentDirectory(); static void SetAbsoluteCurrentDirectory(VFSPath path); VFSPath MakeAbsolute() const; - + VFSPath MakeAbsolute(VFSPath curDir) const; VFSPath MakeRelative() const; VFSPath MakeRelative(VFSPath toMakeRelativeTo) const; @@ -98,10 +182,10 @@ namespace Tesses::Framework::Filesystem VFSPathEnumeratorItterator& operator++(); VFSPathEnumeratorItterator& operator++(int); - + VFSPath& operator*(); VFSPath* operator->(); - + bool operator!=(VFSPathEnumeratorItterator right); bool operator==(VFSPathEnumeratorItterator right); }; @@ -185,48 +269,60 @@ namespace Tesses::Framework::Filesystem std::shared_ptr GetFilesystem(); const VFSPath& GetPath(); virtual ~FSWatcher() = default; - - static std::shared_ptr Create(std::shared_ptr vfs, VFSPath path); + + static std::shared_ptr Create(std::shared_ptr vfs, VFSPath path); + }; + + enum class FIFOCreationResult { + Success=0, + Exists = 1, + ReadOnlyFS = 2, + Denied = 3, + OutOfInodes = 4, + UnknownError = 5, + Unsupported = 255 }; class VFS { public: - + virtual std::shared_ptr OpenFile(VFSPath path, std::string mode)=0; - virtual void CreateDirectory(VFSPath path)=0; - virtual void DeleteDirectory(VFSPath path)=0; - virtual bool RegularFileExists(VFSPath path)=0; - virtual bool SymlinkExists(VFSPath path); - virtual bool CharacterDeviceExists(VFSPath path); - virtual bool BlockDeviceExists(VFSPath path); - virtual bool SocketFileExists(VFSPath path); - virtual bool FIFOFileExists(VFSPath path); - virtual bool FileExists(VFSPath path); - virtual bool SpecialFileExists(VFSPath path); + virtual void CreateDirectory(VFSPath path); + virtual void DeleteDirectory(VFSPath path); + bool DirectoryExists(VFSPath path); + bool RegularFileExists(VFSPath path); + bool SymlinkExists(VFSPath path); + bool CharacterDeviceExists(VFSPath path); + bool BlockDeviceExists(VFSPath path); + bool SocketFileExists(VFSPath path); + bool FIFOFileExists(VFSPath path); + bool FileExists(VFSPath path); + bool SpecialFileExists(VFSPath path); virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); virtual void CreateHardlink(VFSPath existingFile, VFSPath newName); - virtual bool DirectoryExists(VFSPath path)=0; - virtual void DeleteFile(VFSPath path)=0; + virtual void DeleteFile(VFSPath path); virtual void DeleteDirectoryRecurse(VFSPath path); virtual VFSPathEnumerator EnumeratePaths(VFSPath path) = 0; - virtual void MoveFile(VFSPath src, VFSPath dest)=0; + virtual void MoveFile(VFSPath src, VFSPath dest); virtual void MoveDirectory(VFSPath src, VFSPath dest); virtual VFSPath ReadLink(VFSPath path); virtual std::string VFSPathToSystem(VFSPath path)=0; virtual VFSPath SystemToVFSPath(std::string path)=0; - virtual void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); + void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); virtual void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); + virtual bool Stat(VFSPath path, StatData& data) = 0; virtual bool StatVFS(VFSPath path, StatVFSData& data); virtual void Chmod(VFSPath path, uint32_t mode); + virtual void Chown(VFSPath path, uint32_t userId, uint32_t groupId); virtual void Lock(VFSPath path); virtual void Unlock(VFSPath path); - - + virtual FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode); + virtual ~VFS(); virtual void Close(); @@ -236,7 +332,6 @@ namespace Tesses::Framework::Filesystem friend class FSWatcher; }; - namespace Literals { @@ -246,4 +341,3 @@ namespace Tesses::Framework::Filesystem } } } - diff --git a/include/TessesFramework/Http/HttpServer.hpp b/include/TessesFramework/Http/HttpServer.hpp index 6b9f14e..bc1714b 100644 --- a/include/TessesFramework/Http/HttpServer.hpp +++ b/include/TessesFramework/Http/HttpServer.hpp @@ -6,6 +6,7 @@ #include "../Date/Date.hpp" #include #include "WebSocket.hpp" +#include namespace Tesses::Framework::Http { class ServerContextData { @@ -13,12 +14,14 @@ namespace Tesses::Framework::Http virtual ~ServerContextData(); }; - + class ServerContext { bool sent; + bool debug; std::shared_ptr strm; std::map data; + std::queue> headerhandlers; public: HttpDictionary requestHeaders; HttpDictionary responseHeaders; @@ -34,7 +37,7 @@ namespace Tesses::Framework::Http uint16_t serverPort; std::string version; bool encrypted; - ServerContext(std::shared_ptr strm); + ServerContext(std::shared_ptr strm, bool debug=false); ~ServerContext(); std::shared_ptr GetStream(); std::string GetOriginalPathWithQuery(); @@ -53,6 +56,7 @@ namespace Tesses::Framework::Http void SendException(std::exception& ex); std::shared_ptr OpenResponseStream(); std::shared_ptr OpenRequestStream(); + ServerContext& WithStatusCode(StatusCode code); ServerContext& WithLastModified(Date::DateTime time); ServerContext& WithHeader(std::string key, std::string value); ServerContext& WithSingleHeader(std::string key, std::string value); @@ -61,6 +65,9 @@ namespace Tesses::Framework::Http ServerContext& WriteHeaders(); ServerContext& WithLocationHeader(std::string url); ServerContext& WithLocationHeader(std::string url,StatusCode sc); + ServerContext& WithHeaderIntercepter(std::function cb); + ServerContext& WithDebug(bool debug=true); + bool Debug(); void StartWebSocketSession(std::function,std::function,std::function)> onOpen, std::function onReceive, std::function onClose); void StartWebSocketSession(std::shared_ptr connection); std::string GetServerRoot(); @@ -68,7 +75,7 @@ namespace Tesses::Framework::Http void SendRedirect(std::string url); void SendRedirect(std::string url, StatusCode sc); - + template T* GetServerContentData(std::string tag) { @@ -95,14 +102,15 @@ namespace Tesses::Framework::Http bool showIPs; bool showARTL; - + bool debug; + public: - HttpServer(std::shared_ptr tcpServer, std::shared_ptr http, bool showIPs=true); - HttpServer(uint16_t port, std::shared_ptr http, bool showIPs=true); - HttpServer(std::string unixPath, std::shared_ptr http); + HttpServer(std::shared_ptr tcpServer, std::shared_ptr http, bool showIPs=true, bool debug=false); + HttpServer(uint16_t port, std::shared_ptr http, bool showIPs=true, bool debug=false); + HttpServer(std::string unixPath, std::shared_ptr http, bool debug=false); uint16_t GetPort(); void StartAccepting(); - static void Process(std::shared_ptr strm, std::shared_ptr server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted); + static void Process(std::shared_ptr strm, std::shared_ptr server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted, bool debug=false); ~HttpServer(); }; -} \ No newline at end of file +} diff --git a/include/TessesFramework/TessesFramework.hpp b/include/TessesFramework/TessesFramework.hpp index d796abf..667c2fd 100644 --- a/include/TessesFramework/TessesFramework.hpp +++ b/include/TessesFramework/TessesFramework.hpp @@ -31,7 +31,6 @@ #include "Filesystem/SubdirFilesystem.hpp" #include "Filesystem/NullFilesystem.hpp" #include "Filesystem/MountableFilesystem.hpp" -#include "Filesystem/MemoryFilesystem.hpp" #include "Filesystem/FSHelpers.hpp" #include "Crypto/ClientTLSStream.hpp" #include "Crypto/Crypto.hpp" @@ -46,4 +45,4 @@ #include "Serialization/BitConverter.hpp" #include "Args.hpp" #include "BitTorrent/TorrentFile.hpp" -#include "Random.hpp" \ No newline at end of file +#include "Random.hpp" diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index 40847b9..b41ab4e 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -2,7 +2,7 @@ set(PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") set(PKGCONFIG_PROJECT_DESCRIPTION "A cross platform wrapper library") -set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://onedev.site.tesses.net/tesses-framework") +set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://git.tesses.org/tessesframework") if(TESSESFRAMEWORK_ENABLE_MBED) set(PKGCONFIG_DEPS "Requires: mbedtls") @@ -22,4 +22,4 @@ configure_file(tessesframework.pc.in tessesframework.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tessesframework.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -endif() \ No newline at end of file +endif() diff --git a/src/Filesystem/LocalFS.cpp b/src/Filesystem/LocalFS.cpp index e56d403..1270913 100644 --- a/src/Filesystem/LocalFS.cpp +++ b/src/Filesystem/LocalFS.cpp @@ -1,7 +1,10 @@ #include "TessesFramework/Filesystem/LocalFS.hpp" #include "TessesFramework/Streams/FileStream.hpp" +#include +#include #include #include +#include #if defined(_WIN32) #include #include "TessesFramework/Filesystem/VFSFix.hpp" @@ -27,16 +30,31 @@ namespace Tesses::Framework::Filesystem pft->dwHighDateTime = time_value.HighPart; } #endif - void LocalFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) + bool LocalFilesystem::Stat(VFSPath path, StatData& sfs) { std::string s = VFSPathToSystem(path); struct stat st; if(stat(s.c_str(),&st) == 0) { - lastAccess = Date::DateTime((int64_t)st.st_atime); - lastWrite = Date::DateTime((int64_t)st.st_mtime); + + sfs.Device = (uint64_t)st.st_dev; + sfs.Inode = (uint64_t)st.st_ino; + sfs.Mode = (uint32_t)st.st_mode; + sfs.HardLinks = (uint64_t)st.st_nlink; + sfs.UserId = (uint32_t)st.st_uid; + sfs.GroupId = (uint32_t)st.st_gid; + sfs.DeviceId = (uint64_t)st.st_rdev; + sfs.Size = (uint64_t)st.st_size; + sfs.BlockSize = (uint64_t)st.st_blksize; + sfs.BlockCount = (uint64_t)st.st_blocks; + sfs.LastAccess = Date::DateTime((int64_t)st.st_atime); + sfs.LastModified = Date::DateTime((int64_t)st.st_mtime); + sfs.LastStatus = Date::DateTime((int64_t)st.st_ctime); + return true; } + return false; } + void LocalFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) { std::string s = VFSPathToSystem(path); @@ -44,7 +62,7 @@ namespace Tesses::Framework::Filesystem #if defined(_WIN32) FILETIME lastWriteF; FILETIME lastAccessF; - + TimetToFileTime((time_t)lastWrite.ToEpoch(),&lastWriteF); TimetToFileTime((time_t)lastAccess.ToEpoch(),&lastAccessF); HANDLE hFile = CreateFileA( @@ -96,34 +114,6 @@ namespace Tesses::Framework::Filesystem { std::filesystem::create_directories(VFSPathToSystem(path)); } - bool LocalFilesystem::DirectoryExists(VFSPath path) - { - return std::filesystem::is_directory(VFSPathToSystem(path)); - } - bool LocalFilesystem::RegularFileExists(VFSPath path) - { - return std::filesystem::is_regular_file(VFSPathToSystem(path)); - } - bool LocalFilesystem::SymlinkExists(VFSPath path) - { - return std::filesystem::is_symlink(VFSPathToSystem(path)); - } - bool LocalFilesystem::BlockDeviceExists(VFSPath path) - { - return std::filesystem::is_block_file(VFSPathToSystem(path)); - } - bool LocalFilesystem::CharacterDeviceExists(VFSPath path) - { - return std::filesystem::is_character_file(VFSPathToSystem(path)); - } - bool LocalFilesystem::SocketFileExists(VFSPath path) - { - return std::filesystem::is_socket(VFSPathToSystem(path)); - } - bool LocalFilesystem::FIFOFileExists(VFSPath path) - { - return std::filesystem::is_fifo(VFSPathToSystem(path)); - } void LocalFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) { if(std::filesystem::is_directory(VFSPathToSystem(existingFile))) @@ -182,10 +172,13 @@ namespace Tesses::Framework::Filesystem } return p; } - + VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path) { - auto dir = new std::filesystem::directory_iterator(VFSPathToSystem(path)); + std::filesystem::path sysPath = VFSPathToSystem(path); + if(!std::filesystem::is_directory(sysPath)) return VFSPathEnumerator(); + + auto dir = new std::filesystem::directory_iterator(sysPath); return VFSPathEnumerator([dir,path](VFSPath& path0)->bool { std::filesystem::directory_iterator& ittr = *dir; if(ittr != std::filesystem::directory_iterator()) @@ -236,8 +229,47 @@ namespace Tesses::Framework::Filesystem chmod(pathStr.c_str(), (mode_t)mode); #endif } + void LocalFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid) + { + auto pathStr = this->VFSPathToSystem(path); + #if defined(_WIN32) + + #else + chown(pathStr.c_str(), (uid_t)uid, (gid_t)gid); + #endif + } + + + FIFOCreationResult LocalFilesystem::CreateFIFO(VFSPath path, uint32_t mod) + { + auto pathStr = this->VFSPathToSystem(path); + #if defined(_WIN32) + return FIFOCreationResult::Unsupported; + #else + int res = mkfifo(pathStr.c_str(), (mode_t)mod); + if(res == 0) return FIFOCreationResult::Success; + else if(res == -1) + { + switch(res) + { + case EEXIST: + return FIFOCreationResult::Exists; + case ENOTSUP: + return FIFOCreationResult::Unsupported; + case EACCES: + return FIFOCreationResult::Denied; + case ENOSPC: + return FIFOCreationResult::OutOfInodes; + case EROFS: + return FIFOCreationResult::ReadOnlyFS; + } + } + + return FIFOCreationResult::UnknownError; + #endif + } + - void LocalFilesystem::Lock(VFSPath path) { auto p2 = VFSPathToSystem(path); @@ -275,7 +307,7 @@ namespace Tesses::Framework::Filesystem lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveOld) != 0) ? IN_MOVED_FROM : 0; lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveNew) != 0) ? IN_MOVED_TO : 0; lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Opened) != 0) ? IN_OPEN : 0; - + return lflags; } static FSWatcherEventType from_linux_mask(uint32_t lflags) @@ -293,7 +325,7 @@ namespace Tesses::Framework::Filesystem flags |= ((lflags & IN_MOVED_FROM) != 0) ? (uint32_t)FSWatcherEventType::MoveOld : 0; flags |= ((lflags & IN_MOVED_TO) != 0) ? (uint32_t)FSWatcherEventType::MoveNew : 0; flags |= ((lflags & IN_OPEN) != 0) ? (uint32_t)FSWatcherEventType::Opened : 0; - + return (FSWatcherEventType)flags; } public: @@ -303,7 +335,7 @@ namespace Tesses::Framework::Filesystem } protected: - + void SetEnabledImpl(bool enabled) { if(enabled) @@ -325,7 +357,7 @@ namespace Tesses::Framework::Filesystem __attribute__ ((aligned(__alignof__(struct inotify_event)))); const struct inotify_event *event; ssize_t size; - + bool fail=false; FSWatcherEvent evt; @@ -397,12 +429,12 @@ namespace Tesses::Framework::Filesystem close(fd); return; } - } + } } } } } - + close(fd); }); @@ -420,8 +452,8 @@ namespace Tesses::Framework::Filesystem } }; #endif - - + + std::shared_ptr LocalFilesystem::CreateWatcher(std::shared_ptr vfs, VFSPath path) { diff --git a/src/Filesystem/MemoryFilesystem.cpp b/src/Filesystem/MemoryFilesystem.cpp deleted file mode 100644 index 64ac995..0000000 --- a/src/Filesystem/MemoryFilesystem.cpp +++ /dev/null @@ -1,669 +0,0 @@ -#include "TessesFramework/Filesystem/MemoryFilesystem.hpp" -#include - -namespace Tesses::Framework::Filesystem -{ - - MemoryFilesystemStream::MemoryFilesystemStream(std::shared_ptr mtx, std::shared_ptr data,bool canRead, bool canWrite, bool canSeek) - { - this->mtx = mtx; - this->data = data; - this->canRead = canRead; - this->canWrite = canWrite; - this->canSeek = canSeek; - this->pos=0; - } - size_t MemoryFilesystemStream::Read(uint8_t* buff, size_t sz) - { - if(!this->canRead) return 0; - if(this->pos >= this->data->file.size()) return 0; - - size_t toRead = std::min(sz, (size_t)(this->data->file.size()-this->pos)); - - memcpy(buff, this->data->file.data() + this->pos, toRead); - - this->pos += toRead; - return toRead; - } - size_t MemoryFilesystemStream::Write(const uint8_t* buff, size_t sz) - { - if(!this->canWrite) return 0; - if(this->canSeek) - { - - if(this->pos > this->data->file.size()) - { - this->data->file.resize(this->pos+sz); - } - this->data->file.insert(this->data->file.begin()+this->pos, buff, buff+sz); - this->pos+=sz; - - } - else - { - this->data->file.insert(this->data->file.end(), buff, buff+sz); - } - return sz; - } - bool MemoryFilesystemStream::CanRead() - { - return canRead; - } - bool MemoryFilesystemStream::CanWrite() - { - return canWrite; - } - bool MemoryFilesystemStream::CanSeek() - { - return canSeek; - } - int64_t MemoryFilesystemStream::GetPosition() - { - if(!this->canSeek) return (int64_t)this->data->file.size(); - return pos; - } - void MemoryFilesystemStream::Flush() - { - //its already flushed - } - void MemoryFilesystemStream::Seek(int64_t pos, Streams::SeekOrigin whence) - { - if(canSeek) return; - switch(whence) - { - case Streams::SeekOrigin::Begin: - this->pos = (size_t)pos; - break; - case Streams::SeekOrigin::Current: - this->pos += (size_t)pos; - break; - case Streams::SeekOrigin::End: - this->pos = (size_t)(this->data->file.size() + pos); - break; - } - } - MemoryFilesystemStream::~MemoryFilesystemStream() - { - mtx->Lock(); - if(this->canWrite) this->data->canAccess=true; - this->data->readers--; - mtx->Unlock(); - } - - MemoryEntry* MemoryFilesystem::GetEntry(VFSPath path,bool followSymlink) - { - if(path.relative) return nullptr; - if(path.path.empty()) return &this->root; - - auto entry = GetEntry(path.GetParent(),true); - if(entry == nullptr) return nullptr; - - auto dir = dynamic_cast(entry); - if(dir != nullptr) - { - for(auto item : dir->entries) - { - if(item->name == path.GetFileName()) - { - auto link = dynamic_cast(item); - if(followSymlink && link != nullptr) - { - item = GetEntry(link->linkedTo,true); - } - return item; - } - } - } - return nullptr; - } - - std::shared_ptr MemoryFilesystem::OpenFile(VFSPath path, std::string mode) - { - bool canRead=false; - bool canWrite=false; - bool canSeek=true; - bool mustExist=false; - bool truncate=false; - - - if(mode.size() >= 1) - { - if(mode[0] == 'r') - { - canRead = true; - mustExist=true; - } - else if(mode[0] == 'w') - { - canWrite = true; - truncate=true; - } - else if(mode[0] == 'a') - { - canSeek = false; - canWrite = true; - } - } - - if(((mode.size() >= 2 && mode[1] == '+') || (mode.size() >= 2 && mode[1] == 'b' && mode[2] == '+'))) - { - canRead = true; - canWrite = true; - } - - mtx->Lock(); - if(mustExist) - { - auto file = GetEntry(path,true); - - if(file == nullptr) - { - mtx->Unlock(); - return nullptr; - } - - auto f = dynamic_cast(file); - if(f == nullptr) - { - mtx->Unlock(); - return nullptr; - } - if(!f->data->canAccess) - { - mtx->Unlock(); - return nullptr; - } - if(canWrite && f->data->readers > 0) - { - mtx->Unlock(); - return nullptr; - } - f->data->readers++; - if(canWrite) f->data->canAccess=false; - - mtx->Unlock(); - return std::make_shared(mtx,f->data,canRead,canWrite,canSeek); - } - else - { - auto file = dynamic_cast(GetEntry(path,true)); - - - if(file != nullptr) - { - if(!file->data->canAccess) - { - mtx->Unlock(); - return nullptr; - } - if(file->data->readers > 0) - { - mtx->Unlock(); - return nullptr; - } - file->data->canAccess=false; - file->data->readers++; - if(truncate) {file->data->file.clear(); file->data->lastWrite=Date::DateTime::NowUTC();} - mtx->Unlock(); - return std::make_shared(mtx,file->data,canRead,canWrite,canSeek); - - } - - - auto dir = GetEntry(path.GetParent(),true); - - if(dir == nullptr) - { - mtx->Unlock(); - return nullptr; - } - - auto myDir = dynamic_cast(dir); - - - if(myDir == nullptr) - { - mtx->Unlock(); - return nullptr; - } - - MemoryFile* thefile=nullptr; - - for(auto f : myDir->entries) - { - if(f->name == path.GetFileName()) - { - auto symlink = dynamic_cast(f); - while(symlink != nullptr) - { - auto ent = GetEntry(symlink->name,false); - auto sym = dynamic_cast(f); - if(sym != nullptr) - symlink = sym; - else - { - auto myDir0 = dynamic_cast(GetEntry(symlink->linkedTo.GetParent(),true)); - if(myDir0 != nullptr) - { - for(auto f2 : myDir0->entries) - { - if(f2->name == symlink->linkedTo.GetFileName()) - { - auto myFile = dynamic_cast(f2); - if(myFile != nullptr) - { - thefile = myFile; - break; - } - else - { - mtx->Unlock(); - return nullptr; - } - } - - } - myDir = myDir0; - } - else - { - mtx->Unlock(); - return nullptr; - } - break; - } - } - break; - } - } - if(thefile == nullptr) - { - - MemoryFile* f = new MemoryFile(); - f->name = path.GetFileName(); - f->data = std::make_shared(); - f->data->canAccess=false; - f->data->readers++; - - myDir->entries.push_back(f); - - mtx->Unlock(); - return std::make_shared(mtx,f->data,canRead,canWrite,canSeek); - } - if(thefile != nullptr) - { - if(!thefile->data->canAccess) - { - mtx->Unlock(); - return nullptr; - } - if(thefile->data->readers > 0) - { - mtx->Unlock(); - return nullptr; - } - thefile->data->canAccess=false; - thefile->data->readers++; - if(truncate) {thefile->data->file.clear(); thefile->data->lastWrite=Date::DateTime::NowUTC();} - mtx->Unlock(); - return std::make_shared(mtx,thefile->data,canRead,canWrite,canSeek); - } - } - - mtx->Unlock(); - return nullptr; - } - - void MemoryFilesystem::CreateDirectory(VFSPath path) - { - if(path.relative) return; - if(path.path.empty()) return; - mtx->Lock(); - MemoryDirectory* dir=&root; - for(auto part : path.path) - { - bool have=false; - for(auto dirent : dir->entries) - { - if(dirent->name == part) - { - auto symlink = dynamic_cast(dirent); - if(symlink != nullptr) - { - dirent = GetEntry(symlink->linkedTo,true); - } - auto dirdirent = dynamic_cast(dirent); - if(dirdirent != nullptr) - { - dir = dirdirent; - have=true; - break; - } - else - { - mtx->Unlock(); - return; - } - } - } - if(!have) - { - MemoryDirectory* dir2 = new MemoryDirectory(); - dir2->name = part; - - dir2->lastWrite=Date::DateTime::NowUTC(); - - dir->entries.push_back(dir2); - dir->lastWrite=Date::DateTime::NowUTC(); - - dir=dir2; - } - } - mtx->Unlock(); - } - - void MemoryFilesystem::DeleteFile(VFSPath path) - { - if(path.relative || path.path.empty()) return; - mtx->Lock(); - MemoryDirectory* dir=&root; - if(path.path.size() > 1) - { - dir = dynamic_cast(GetEntry(path.GetParent(),true)); - } - if(dir == nullptr) - { - mtx->Unlock(); - return; - } - std::string fname = path.GetFileName(); - for(auto index = dir->entries.begin(); index < dir->entries.end(); index++) - { - auto item = *index; - if(item->name == fname) - { - auto p = dynamic_cast(item); - if(p == nullptr) - { - delete item; - dir->entries.erase(index); - - dir->lastWrite=Date::DateTime::NowUTC(); - } - break; - } - } - mtx->Unlock(); - } - - bool MemoryFilesystem::RegularFileExists(VFSPath path) - { - - if(path.relative) return false; - if(path.path.empty()) return false; - mtx->Lock(); - auto f = GetEntry(path,false); - mtx->Unlock(); - return dynamic_cast(f) != nullptr; - } - bool MemoryFilesystem::SymlinkExists(VFSPath path) - { - - if(path.relative) return false; - if(path.path.empty()) return false; - mtx->Lock(); - auto f = GetEntry(path,false); - mtx->Unlock(); - return dynamic_cast(f) != nullptr; - } - bool MemoryFilesystem::DirectoryExists(VFSPath path) - { - if(path.relative) return false; - if(path.path.empty()) return true; - mtx->Lock(); - auto f = GetEntry(path,false); - mtx->Unlock(); - return dynamic_cast(f) != nullptr; - } - - void MemoryFilesystem::DeleteDirectory(VFSPath path) - { - if(path.relative || path.path.empty()) return; - mtx->Lock(); - MemoryDirectory* dir=&root; - if(path.path.size() > 1) - { - dir = dynamic_cast(GetEntry(path.GetParent(),true)); - } - if(dir == nullptr) - { - mtx->Unlock(); - return; - } - std::string fname = path.GetFileName(); - for(auto index = dir->entries.begin(); index < dir->entries.end(); index++) - { - auto item = *index; - if(item->name == fname) - { - auto p = dynamic_cast(item); - if(p != nullptr) - { - delete item; - dir->entries.erase(index); - dir->lastWrite=Date::DateTime::NowUTC(); - } - break; - } - } - mtx->Unlock(); - } - - void MemoryFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) - { - if(existingFile.relative || symlinkFile.relative || symlinkFile.path.empty()) return; - mtx->Lock(); - MemoryDirectory* dir=&root; - if(symlinkFile.path.size() > 1) - { - dir = dynamic_cast(GetEntry(symlinkFile.GetParent(),true)); - } - if(dir == nullptr) - { - mtx->Unlock(); - return; - } - std::string fname = symlinkFile.GetFileName(); - for(auto index = dir->entries.begin(); index < dir->entries.end(); index++) - { - auto item = *index; - if(item->name == fname) - { - auto p = dynamic_cast(item); - if(p != nullptr) - { - p->linkedTo = existingFile; - p->lastWrite = Date::DateTime::NowUTC(); - } - mtx->Unlock(); - return; - } - } - MemorySymlink* symlink = new MemorySymlink(); - symlink->name = fname; - symlink->linkedTo = existingFile; - symlink->lastWrite = Date::DateTime::NowUTC(); - dir->entries.push_back(symlink); - dir->lastWrite = Date::DateTime::NowUTC(); - - mtx->Unlock(); - } - VFSPathEnumerator MemoryFilesystem::EnumeratePaths(VFSPath path) - { - std::pair>* paths=new std::pair>(); - paths->first=0; - mtx->Lock(); - auto dir = dynamic_cast(GetEntry(path,true)); - if(dir != nullptr) - { - for(auto item : dir->entries) paths->second.push_back(item->name); - } - mtx->Unlock(); - - return VFSPathEnumerator([paths,path](VFSPath& _path)->bool{ - if(paths->first < paths->second.size()) - { - _path = path / paths->second[paths->first++]; - return true; - } - return false; - },[paths]()->void{ - delete paths; - }); - } - - - void MemoryFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName) - { - mtx->Lock(); - auto existing = dynamic_cast(GetEntry(existingFile,true)); - if(existing == nullptr) - { - mtx->Unlock(); - return; - } - MemoryDirectory* dir=&root; - if(newName.path.size() > 1) - { - dir = dynamic_cast(GetEntry(newName.GetParent(),true)); - } - if(dir == nullptr) - { - mtx->Unlock(); - return; - } - - std::string fname = newName.GetFileName(); - for(auto index = dir->entries.begin(); index < dir->entries.end(); index++) - { - auto item = *index; - if(item->name == fname) - { - - mtx->Unlock(); - return; - } - } - - MemoryFile* memFile = new MemoryFile(); - memFile->name = fname; - memFile->data = existing->data; - dir->entries.push_back(memFile); - dir->lastWrite=Date::DateTime::NowUTC(); - - mtx->Unlock(); - } - void MemoryFilesystem::MoveFile(VFSPath src, VFSPath dest) - { - DeleteFile(dest); - CreateHardlink(src,dest); - DeleteFile(src); - } - void MemoryFilesystem::MoveDirectory(VFSPath src, VFSPath dest) - { - CreateDirectory(dest); - for(auto ent : EnumeratePaths(src)) - { - VFSPath destPath = dest / ent.GetFileName(); - if(FileExists(ent)) MoveFile(ent,destPath); - if(DirectoryExists(ent)) MoveDirectory(ent,destPath); - - } - DeleteDirectory(src); - } - - VFSPath MemoryFilesystem::ReadLink(VFSPath p) - { - mtx->Lock(); - VFSPath p2; - auto symlink = dynamic_cast(GetEntry(p,false)); - if(symlink != nullptr) - { - p2 = symlink->linkedTo; - } - mtx->Unlock(); - return p2; - } - std::string MemoryFilesystem::VFSPathToSystem(VFSPath path) - { - return path.ToString(); - } - VFSPath MemoryFilesystem::SystemToVFSPath(std::string path) - { - return path; - } - void MemoryFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) - { - - mtx->Lock(); - auto node = GetEntry(path,false); - auto dir = dynamic_cast(node); - - auto file = dynamic_cast(node); - - auto sym = dynamic_cast(node); - - if(dir != nullptr) lastWrite = dir->lastWrite; - if(file != nullptr) lastWrite = file->data->lastWrite; - if(sym != nullptr) lastWrite = sym->lastWrite; - mtx->Unlock(); - lastAccess = lastWrite; - } - void MemoryFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) - { - mtx->Lock(); - auto node = GetEntry(path,false); - auto dir = dynamic_cast(node); - - auto file = dynamic_cast(node); - - auto sym = dynamic_cast(node); - - if(dir != nullptr) dir->lastWrite = lastWrite; - if(file != nullptr) file->data->lastWrite = lastWrite; - if(sym != nullptr) sym->lastWrite = lastWrite; - mtx->Unlock(); - } - MemoryFilesystem::~MemoryFilesystem() - { - - } - MemoryFilesystem::MemoryFilesystem() - { - mtx = std::make_shared(); - } - - MemoryEntry::~MemoryEntry() - { - - } - MemoryFile::~MemoryFile() - { - - } - MemoryDirectory::MemoryDirectory() - { - this->lastWrite = Date::DateTime::NowUTC(); - } - MemoryDirectory::~MemoryDirectory() - { - for(auto item : this->entries) delete item; - } - MemoryFileData::MemoryFileData() - { - this->lastWrite = Date::DateTime::NowUTC(); - this->canAccess=true; - this->readers=0; - - } -} diff --git a/src/Filesystem/MountableFilesystem.cpp b/src/Filesystem/MountableFilesystem.cpp index 618311a..3546d2e 100644 --- a/src/Filesystem/MountableFilesystem.cpp +++ b/src/Filesystem/MountableFilesystem.cpp @@ -24,7 +24,7 @@ namespace Tesses::Framework::Filesystem - void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr& vfs) + void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr& vfs) { if(srcPath.path.empty()) return; for(auto item : this->directories) @@ -38,8 +38,8 @@ namespace Tesses::Framework::Filesystem srcPath1.relative=false; destPath = srcPath1; destRoot = VFSPath(VFSPath(),item->name); - - + + } VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end())); srcPath2.relative=false; @@ -49,9 +49,9 @@ namespace Tesses::Framework::Filesystem } } - - - void MountableDirectory::GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr& vfs) + + + void MountableDirectory::GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr& vfs) { if(srcPath.path.empty()) return; for(auto item : this->dirs) @@ -61,13 +61,13 @@ namespace Tesses::Framework::Filesystem if(item->vfs != nullptr) { vfs = item->vfs; - + VFSPath srcPath1(std::vector(srcPath.path.begin()+1,srcPath.path.end())); srcPath1.relative=false; destPath = srcPath1; destRoot = curDir; - + } VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end())); srcPath2.relative=false; @@ -83,7 +83,7 @@ namespace Tesses::Framework::Filesystem VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) return VFSPath(destRoot,vfs->ReadLink(destPath)); @@ -96,24 +96,65 @@ namespace Tesses::Framework::Filesystem VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) return vfs->StatVFS(destPath,data); return false; } + + bool MountableFilesystem::Stat(VFSPath path, StatData& data) + { + path = path.CollapseRelativeParents(); + VFSPath destRoot; + VFSPath destPath = path; + std::shared_ptr vfs = root; + + GetFS(path, destRoot, destPath, vfs); + if(vfs != nullptr) + return vfs->Stat(destPath,data); + return false; + } + + void MountableFilesystem::Chmod(VFSPath path, uint32_t mode) { path = path.CollapseRelativeParents(); VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) vfs->Chmod(destPath,mode); } - + + void MountableFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid) + { + path = path.CollapseRelativeParents(); + VFSPath destRoot; + VFSPath destPath = path; + std::shared_ptr vfs = root; + + GetFS(path, destRoot, destPath, vfs); + if(vfs != nullptr) + vfs->Chown(destPath,uid, gid); + } + + + FIFOCreationResult MountableFilesystem::CreateFIFO(VFSPath path, uint32_t mod) + { + path = path.CollapseRelativeParents(); + VFSPath destRoot; + VFSPath destPath = path; + std::shared_ptr vfs = root; + + GetFS(path, destRoot, destPath, vfs); + if(vfs != nullptr) + return vfs->CreateFIFO(destPath,mod); + return FIFOCreationResult::UnknownError; + } + std::shared_ptr MountableFilesystem::OpenFile(VFSPath path, std::string mode) { @@ -121,7 +162,7 @@ namespace Tesses::Framework::Filesystem VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) @@ -131,238 +172,92 @@ namespace Tesses::Framework::Filesystem void MountableFilesystem::CreateDirectory(VFSPath path) { path = path.CollapseRelativeParents(); - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(destPath.path.empty()) return; if(vfs != nullptr) vfs->CreateDirectory(destPath); - + } - + void MountableFilesystem::DeleteDirectory(VFSPath path) { path = path.CollapseRelativeParents(); - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(destPath.path.empty()) return; if(vfs != nullptr) vfs->DeleteDirectory(destPath); - - } - bool MountableFilesystem::SpecialFileExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->SpecialFileExists(destPath); - return false; - } - - bool MountableFilesystem::FileExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->FileExists(destPath); - return false; - } - bool MountableFilesystem::RegularFileExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->RegularFileExists(destPath); - return false; - } - - bool MountableFilesystem::SymlinkExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->SymlinkExists(destPath); - return false; - } - bool MountableFilesystem::CharacterDeviceExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->CharacterDeviceExists(destPath); - return false; - } - bool MountableFilesystem::BlockDeviceExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->BlockDeviceExists(destPath); - return false; - } - - bool MountableFilesystem::SocketFileExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->SocketFileExists(destPath); - return false; - } - - - bool MountableFilesystem::FIFOFileExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - return vfs->FIFOFileExists(destPath); - return false; } - bool MountableFilesystem::DirectoryExists(VFSPath path) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - if(destPath.path.empty()) return true; - if(vfs != nullptr) - return vfs->DirectoryExists(destPath); - return false; - } void MountableFilesystem::DeleteFile(VFSPath path) { path = path.CollapseRelativeParents(); - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) vfs->DeleteFile(destPath); - + } void MountableFilesystem::Lock(VFSPath path) { path = path.CollapseRelativeParents(); - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) vfs->Lock(destPath); - + } void MountableFilesystem::Unlock(VFSPath path) { path = path.CollapseRelativeParents(); - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) vfs->Unlock(destPath); - - } - void MountableFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) - { - path = path.CollapseRelativeParents(); - - VFSPath destRoot; - VFSPath destPath = path; - std::shared_ptr vfs = root; - - GetFS(path, destRoot, destPath, vfs); - - if(vfs != nullptr) - vfs->GetDate(destPath,lastWrite,lastAccess); } void MountableFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) { path = path.CollapseRelativeParents(); - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); if(vfs != nullptr) @@ -372,17 +267,17 @@ namespace Tesses::Framework::Filesystem { existingFile = existingFile.CollapseRelativeParents(); symlinkFile = existingFile.CollapseRelativeParents(); - + VFSPath existingDestRoot; VFSPath existingDestPath = existingFile; std::shared_ptr existingVFS = root; VFSPath symlinkDestRoot; VFSPath symlinkDestPath = symlinkFile; std::shared_ptr symlinkVFS = root; - + GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS); GetFS(symlinkFile, symlinkDestRoot, symlinkDestPath, symlinkVFS); - + if(existingVFS != nullptr && existingVFS == symlinkVFS) existingVFS->CreateSymlink(existingDestPath, symlinkDestPath); } @@ -391,17 +286,17 @@ namespace Tesses::Framework::Filesystem { src = src.CollapseRelativeParents(); dest = dest.CollapseRelativeParents(); - + VFSPath srcDestRoot; VFSPath srcDestPath = src; std::shared_ptr srcVFS = root; VFSPath destDestRoot; VFSPath destDestPath = dest; std::shared_ptr destVFS = root; - + GetFS(src, srcDestRoot, srcDestPath, srcVFS); GetFS(dest, destDestRoot, destDestPath, destVFS); - + if(srcVFS != nullptr && srcVFS == destVFS) srcVFS->MoveDirectory(srcDestPath, destDestPath); } @@ -409,17 +304,17 @@ namespace Tesses::Framework::Filesystem { src = src.CollapseRelativeParents(); dest = dest.CollapseRelativeParents(); - + VFSPath srcDestRoot; VFSPath srcDestPath = src; std::shared_ptr srcVFS = root; VFSPath destDestRoot; VFSPath destDestPath = dest; std::shared_ptr destVFS = root; - + GetFS(src, srcDestRoot, srcDestPath, srcVFS); GetFS(dest, destDestRoot, destDestPath, destVFS); - + if(srcVFS != nullptr && srcVFS == destVFS) srcVFS->MoveFile(srcDestPath, destDestPath); } @@ -427,17 +322,17 @@ namespace Tesses::Framework::Filesystem { existingFile = existingFile.CollapseRelativeParents(); newName = existingFile.CollapseRelativeParents(); - + VFSPath existingDestRoot; VFSPath existingDestPath = existingFile; std::shared_ptr existingVFS = root; VFSPath newNameRoot; VFSPath newNamePath = newName; std::shared_ptr newNameVFS = root; - + GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS); GetFS(newName, newNameRoot, newNamePath, newNameVFS); - + if(existingVFS != nullptr && existingVFS == newNameVFS) existingVFS->CreateHardlink(existingDestPath, newNamePath); } @@ -449,17 +344,17 @@ namespace Tesses::Framework::Filesystem }; VFSPathEnumerator MountableFilesystem::EnumeratePaths(VFSPath path) { - + path = path.CollapseRelativeParents(); bool mydirs = path.path.empty(); std::vector* dirs = &this->directories; - + if(!path.path.empty()) for(auto p : path.path) { mydirs=true; bool hasSet=false; - + for(auto itm : *dirs) { if(itm->name == p) @@ -476,13 +371,13 @@ namespace Tesses::Framework::Filesystem break; } } - + VFSPath destRoot; VFSPath destPath = path; std::shared_ptr vfs = root; - + GetFS(path, destRoot, destPath, vfs); - + MountableEnumerationState* state = new MountableEnumerationState(); state->dirs = *dirs; @@ -493,11 +388,11 @@ namespace Tesses::Framework::Filesystem state->enumerator = nullptr; return VFSPathEnumerator([state,path](VFSPath& path0)->bool{ - + while(state->enumerator != nullptr && state->enumerator->MoveNext()) { auto fname = state->enumerator->Current.GetFileName(); - + bool mustContinue=false; for(auto item : state->dirs) { @@ -527,11 +422,11 @@ namespace Tesses::Framework::Filesystem delete state; }); } - + void MountableFilesystem::Mount(VFSPath path, std::shared_ptr fs) { path = path.CollapseRelativeParents(); - + if(path.path.empty()) { return; @@ -557,12 +452,12 @@ namespace Tesses::Framework::Filesystem dir->name = *index; dir->owns=false; dir->vfs=NULL; - + fsLs->push_back(dir); fsLs = &(dir->dirs); } } - + needToCreate=true; std::string lastDir = path.GetFileName(); @@ -571,7 +466,7 @@ namespace Tesses::Framework::Filesystem if(item->name == lastDir) { needToCreate=false; - + item->vfs = fs; break; } @@ -581,7 +476,7 @@ namespace Tesses::Framework::Filesystem { MountableDirectory* dir = new MountableDirectory(); dir->name = lastDir; - + dir->vfs=fs; fsLs->push_back(dir); } @@ -590,11 +485,11 @@ namespace Tesses::Framework::Filesystem static bool myumount(MountableDirectory* dir,VFSPath path) { - if(path.path.empty()) + if(path.path.empty()) { dir->vfs = nullptr; } - + if(dir->dirs.empty()) { delete dir; @@ -608,8 +503,8 @@ namespace Tesses::Framework::Filesystem { VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end())); - - + + if(myumount(item,srcPath2)) { dir->dirs.erase(index); @@ -629,14 +524,14 @@ namespace Tesses::Framework::Filesystem void MountableFilesystem::Unmount(VFSPath path) { path = path.CollapseRelativeParents(); - + for(auto index = this->directories.begin(); index < this->directories.end(); index++) { auto item = *index; if(!path.path.empty() && path.path.front() == item->name) { VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end())); - + if(myumount(item,srcPath2)) { this->directories.erase(index); @@ -654,4 +549,4 @@ namespace Tesses::Framework::Filesystem { return VFSPath(path); } -} \ No newline at end of file +} diff --git a/src/Filesystem/NullFilesystem.cpp b/src/Filesystem/NullFilesystem.cpp index 75ed930..5e9c4b1 100644 --- a/src/Filesystem/NullFilesystem.cpp +++ b/src/Filesystem/NullFilesystem.cpp @@ -6,33 +6,11 @@ namespace Tesses::Framework::Filesystem { return nullptr; } - void NullFilesystem::CreateDirectory(VFSPath path) - { - } - void NullFilesystem::DeleteDirectory(VFSPath path) - { - } - bool NullFilesystem::RegularFileExists(VFSPath path) - { - return false; - } - bool NullFilesystem::DirectoryExists(VFSPath path) - { - return false; - } - void NullFilesystem::DeleteFile(VFSPath path) - { - - } VFSPathEnumerator NullFilesystem::EnumeratePaths(VFSPath path) { return VFSPathEnumerator(); - } - void NullFilesystem::MoveFile(VFSPath src, VFSPath dest) - { - } std::string NullFilesystem::VFSPathToSystem(VFSPath path) { @@ -42,4 +20,9 @@ namespace Tesses::Framework::Filesystem { return VFSPath(path); } -} \ No newline at end of file + + bool NullFilesystem::Stat(VFSPath path, StatData& data) + { + return false; + } +} diff --git a/src/Filesystem/SubdirFilesystem.cpp b/src/Filesystem/SubdirFilesystem.cpp index 589628b..39af1f2 100644 --- a/src/Filesystem/SubdirFilesystem.cpp +++ b/src/Filesystem/SubdirFilesystem.cpp @@ -13,7 +13,7 @@ namespace Tesses::Framework::Filesystem // /a/b/c VFSPath newPath; newPath.relative=false; - + if(path.path.size() >= this->path.path.size()) { newPath.path.reserve(path.path.size()-this->path.path.size()); @@ -41,7 +41,7 @@ namespace Tesses::Framework::Filesystem } else this->path = path; - + } std::shared_ptr SubdirFilesystem::OpenFile(VFSPath path, std::string mode) { @@ -55,34 +55,6 @@ namespace Tesses::Framework::Filesystem { this->parent->DeleteDirectory(ToParent(path)); } - bool SubdirFilesystem::RegularFileExists(VFSPath path) - { - return this->parent->RegularFileExists(ToParent(path)); - } - bool SubdirFilesystem::SymlinkExists(VFSPath path) - { - return this->parent->SymlinkExists(ToParent(path)); - } - bool SubdirFilesystem::CharacterDeviceExists(VFSPath path) - { - return this->parent->CharacterDeviceExists(ToParent(path)); - } - bool SubdirFilesystem::BlockDeviceExists(VFSPath path) - { - return this->parent->BlockDeviceExists(ToParent(path)); - } - bool SubdirFilesystem::SocketFileExists(VFSPath path) - { - return this->parent->SocketFileExists(ToParent(path)); - } - bool SubdirFilesystem::FIFOFileExists(VFSPath path) - { - return this->parent->FIFOFileExists(ToParent(path)); - } - bool SubdirFilesystem::DirectoryExists(VFSPath path) - { - return this->parent->DirectoryExists(ToParent(path)); - } void SubdirFilesystem::DeleteFile(VFSPath path) { this->parent->DeleteFile(ToParent(path)); @@ -116,15 +88,12 @@ namespace Tesses::Framework::Filesystem delete enumerator; }); } - void SubdirFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) - { - this->parent->GetDate(ToParent(path),lastWrite,lastAccess); - } + void SubdirFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) { this->parent->SetDate(ToParent(path),lastWrite,lastAccess); } - + void SubdirFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName) { this->parent->CreateHardlink(ToParent(existingFile),ToParent(newName)); @@ -142,34 +111,39 @@ namespace Tesses::Framework::Filesystem return this->parent->VFSPathToSystem(ToParent(path)); } VFSPath SubdirFilesystem::SystemToVFSPath(std::string path) - { + { return FromParent(this->parent->SystemToVFSPath(path)); } void SubdirFilesystem::DeleteDirectoryRecurse(VFSPath path) { this->parent->DeleteDirectoryRecurse(ToParent(path)); } - bool SubdirFilesystem::SpecialFileExists(VFSPath path) - { - return this->parent->SpecialFileExists(ToParent(path)); - } - bool SubdirFilesystem::FileExists(VFSPath path) - { - return this->parent->FileExists(ToParent(path)); - } - + + SubdirFilesystem::~SubdirFilesystem() { - + } bool SubdirFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData) { return this->parent->StatVFS(ToParent(path), vfsData); } - + bool SubdirFilesystem::Stat(VFSPath path, StatData& data) + { + return this->parent->Stat(ToParent(path), data); + } void SubdirFilesystem::Chmod(VFSPath path, uint32_t mode) { return this->parent->Chmod(ToParent(path), mode); } + void SubdirFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid) + { + return this->parent->Chown(ToParent(path), uid, gid); + } + + FIFOCreationResult SubdirFilesystem::CreateFIFO(VFSPath path, uint32_t mod) + { + return this->parent->CreateFIFO(path, mod); + } } diff --git a/src/Filesystem/TempFS.cpp b/src/Filesystem/TempFS.cpp index c271127..d5ce8e2 100644 --- a/src/Filesystem/TempFS.cpp +++ b/src/Filesystem/TempFS.cpp @@ -7,12 +7,12 @@ namespace Tesses::Framework::Filesystem { Tesses::Framework::Threading::Mutex umtx; int64_t uidx=0; void UniqueString(std::string& text) - { + { umtx.Lock(); text += std::to_string((int64_t)time(NULL)); text += "_"; text += std::to_string(uidx); - + uidx++; umtx.Unlock(); @@ -54,56 +54,7 @@ namespace Tesses::Framework::Filesystem { if(this->vfs == nullptr) return; this->vfs->DeleteDirectory(path); } - bool TempFS::SpecialFileExists(VFSPath path) - { - if(this->vfs == nullptr) return false; - return this->vfs->SpecialFileExists(path); - } - bool TempFS::FileExists(VFSPath path) - { - - if(this->vfs == nullptr) return false; - return this->vfs->FileExists(path); - } - bool TempFS::RegularFileExists(VFSPath path) - { - - if(this->vfs == nullptr) return false; - return this->vfs->RegularFileExists(path); - } - bool TempFS::SymlinkExists(VFSPath path) - { - - if(this->vfs == nullptr) return false; - return this->vfs->SymlinkExists(path); - } - bool TempFS::CharacterDeviceExists(VFSPath path) - { - - if(this->vfs == nullptr) return false; - return this->vfs->CharacterDeviceExists(path); - } - bool TempFS::BlockDeviceExists(VFSPath path) - { - if(this->vfs == nullptr) return false; - return this->vfs->BlockDeviceExists(path); - } - bool TempFS::SocketFileExists(VFSPath path) - { - if(this->vfs == nullptr) return false; - return this->vfs->SocketFileExists(path); - } - bool TempFS::FIFOFileExists(VFSPath path) - { - if(this->vfs == nullptr) return false; - return this->vfs->FIFOFileExists(path); - } - bool TempFS::DirectoryExists(VFSPath path) - { - if(this->vfs == nullptr) return false; - return this->vfs->DirectoryExists(path); - } void TempFS::DeleteFile(VFSPath path) { if(this->vfs == nullptr) return; @@ -126,7 +77,7 @@ namespace Tesses::Framework::Filesystem { } VFSPathEnumerator TempFS::EnumeratePaths(VFSPath path) { - + if(this->vfs == nullptr) return VFSPathEnumerator(); return this->vfs->EnumeratePaths(path); @@ -172,13 +123,7 @@ namespace Tesses::Framework::Filesystem { if(this->vfs == nullptr) return VFSPath(); return this->vfs->SystemToVFSPath(path); } - - void TempFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) - { - if(this->vfs == nullptr) return; - this->vfs->GetDate(path,lastWrite,lastAccess); - } void TempFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) { @@ -187,10 +132,16 @@ namespace Tesses::Framework::Filesystem { } bool TempFS::StatVFS(VFSPath path, StatVFSData& vfsData) { - + if(this->vfs == nullptr) return false; return this->vfs->StatVFS(path, vfsData); } + bool TempFS::Stat(VFSPath path, StatData& data) + { + + if(this->vfs == nullptr) return false; + return this->vfs->Stat(path, data); + } void TempFS::Chmod(VFSPath path, uint32_t mode) { @@ -198,6 +149,17 @@ namespace Tesses::Framework::Filesystem { if(this->vfs == nullptr) return; this->vfs->Chmod(path,mode); } + void TempFS::Chown(VFSPath path, uint32_t uid, uint32_t gid) + { + + if(this->vfs == nullptr) return; + this->vfs->Chown(path,uid, gid); + } + FIFOCreationResult TempFS::CreateFIFO(VFSPath path, uint32_t mod) + { + if(this->vfs == nullptr) return FIFOCreationResult::UnknownError; + return this->vfs->CreateFIFO(path, mod); + } void TempFS::Close() { @@ -218,5 +180,5 @@ namespace Tesses::Framework::Filesystem { this->parent->DeleteDirectoryRecurse(p); } - -} \ No newline at end of file + +} diff --git a/src/Filesystem/VFS.cpp b/src/Filesystem/VFS.cpp index 60e0cc9..6f7a34b 100644 --- a/src/Filesystem/VFS.cpp +++ b/src/Filesystem/VFS.cpp @@ -1,6 +1,7 @@ #include "TessesFramework/Filesystem/VFS.hpp" #include "TessesFramework/Http/HttpUtils.hpp" #include "TessesFramework/Filesystem/LocalFS.hpp" +#include namespace Tesses::Framework::Filesystem { VFSPathEnumeratorItterator::VFSPathEnumeratorItterator() @@ -21,12 +22,12 @@ namespace Tesses::Framework::Filesystem enumerator->MoveNext(); return *this; } - - + + VFSPath& VFSPathEnumeratorItterator::operator*() { std::filesystem::directory_iterator i; - + if(enumerator != nullptr) return enumerator->Current; return this->e; @@ -46,7 +47,7 @@ namespace Tesses::Framework::Filesystem if(right.enumerator == nullptr) { auto r = !enumerator->IsDone(); - + return r; } return true; @@ -88,7 +89,7 @@ namespace Tesses::Framework::Filesystem } bool VFSPathEnumerator::IsDone() { - + if(this->data) { return data->eof; @@ -132,7 +133,7 @@ namespace Tesses::Framework::Filesystem { mid.append(p.path.back()); } - + if(!p2.path.empty()) { mid.append(p2.path.front()); @@ -169,7 +170,7 @@ namespace Tesses::Framework::Filesystem for(size_t i = 0; i < p.path.size(); i++) if(p.path[i] != p2.path[i]) return true; return false; - + } bool operator==(std::string p,VFSPath p2) { @@ -216,13 +217,98 @@ namespace Tesses::Framework::Filesystem { return MakeRelative(GetAbsoluteCurrentDirectory()); } + FIFOCreationResult VFS::CreateFIFO(VFSPath path, uint32_t mode) + { + return FIFOCreationResult::Unsupported; + } + bool VFS::DirectoryExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsDirectory(); + } + return false; + } + bool VFS::RegularFileExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsRegularFile(); + } + return false; + } + bool VFS::SymlinkExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsSymlink(); + } + return false; + } + bool VFS::CharacterDeviceExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsCharDevice(); + } + return false; + } + bool VFS::BlockDeviceExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsBlockDevice(); + } + return false; + } + bool VFS::SocketFileExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsSocket(); + } + return false; + } + bool VFS::FIFOFileExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsFIFO(); + } + return false; + } + bool VFS::FileExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return !data.IsDirectory(); + } + return false; + } + bool VFS::SpecialFileExists(VFSPath path) + { + StatData data; + if(this->Stat(path, data)) + { + return data.IsSpecial(); + } + return false; + } VFSPath VFSPath::MakeRelative(VFSPath toMakeRelativeTo) const { if(this->relative) return *this; - - - + + + size_t i; size_t len = std::min(toMakeRelativeTo.path.size(),this->path.size()); for(i = 0; i < len; i++) @@ -239,7 +325,7 @@ namespace Tesses::Framework::Filesystem } std::vector parts(this->path.begin()+i, this->path.end()); - + if(i < toMakeRelativeTo.path.size()) { for(; i < toMakeRelativeTo.path.size();i++) @@ -264,7 +350,7 @@ namespace Tesses::Framework::Filesystem parts.erase(parts.end()-1); } } - else if(item == ".") + else if(item == ".") { //do nothing but don't emit this } @@ -284,7 +370,7 @@ namespace Tesses::Framework::Filesystem path.relative=true; return path; } - + std::vector VFSPath::SplitPath(std::string path) { std::vector parts; @@ -386,7 +472,7 @@ namespace Tesses::Framework::Filesystem str = str.substr(0,index); } if(ext.empty()) return; - if(ext[0] != '.') + if(ext[0] != '.') { str += '.'; str += ext; @@ -400,7 +486,7 @@ namespace Tesses::Framework::Filesystem { ChangeExtension({}); } - + VFSPath::VFSPath(std::string str) { this->path = SplitPath(str); @@ -418,13 +504,21 @@ namespace Tesses::Framework::Filesystem if(!firstPartPath.empty() && firstPartPath.back() == ':') this->relative=false; } } + } + void VFS::CreateDirectory(VFSPath path) + { + + } + void VFS::DeleteDirectory(VFSPath path) + { + } VFSPath::VFSPath(VFSPath p1, VFSPath p2) { this->relative = p1.relative; this->path.insert(this->path.end(),p1.path.begin(),p1.path.end()); this->path.insert(this->path.end(),p2.path.begin(),p2.path.end()); - } + } VFSPath::VFSPath(VFSPath p1, std::string subpath) : VFSPath(p1, VFSPath(subpath)) { @@ -462,20 +556,30 @@ namespace Tesses::Framework::Filesystem } return p; } + void VFS::DeleteFile(VFSPath path) + { + } + void VFS::MoveFile(VFSPath src, VFSPath dest) + { + { + auto srcStrm = this->OpenFile(src, "rb"); + if(!srcStrm->CanRead()) return; + auto destStrm = this->OpenFile(dest, "wb"); + if(!destStrm->CanWrite()) return; + srcStrm->CopyTo(destStrm); + } + + VFS::DeleteFile(src); + } VFS::~VFS() { } - bool VFS::FIFOFileExists(VFSPath path) {return false;} - bool VFS::SocketFileExists(VFSPath path) {return false;} - bool VFS::CharacterDeviceExists(VFSPath path) {return false;} - bool VFS::BlockDeviceExists(VFSPath path) {return false;} - bool VFS::SymlinkExists(VFSPath path) {return false;} void VFS::MoveDirectory(VFSPath src, VFSPath dest) { - + for(auto item : EnumeratePaths(src)) { if(DirectoryExists(item)) @@ -488,7 +592,7 @@ namespace Tesses::Framework::Filesystem } } - DeleteDirectory(src); + DeleteDirectory(src); } void VFS::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) { @@ -496,22 +600,14 @@ namespace Tesses::Framework::Filesystem } void VFS::CreateHardlink(VFSPath existingFile, VFSPath newName) { - - } - - bool VFS::SpecialFileExists(VFSPath path) - { - return SymlinkExists(path) || BlockDeviceExists(path) || CharacterDeviceExists(path) || SocketFileExists(path) || FIFOFileExists(path); - } - bool VFS::FileExists(VFSPath path) - { - return RegularFileExists(path) || SpecialFileExists(path); + } + void VFS::DeleteDirectoryRecurse(VFSPath path) { if(!DirectoryExists(path)) return; - + for(auto item : EnumeratePaths(path)) { if(DirectoryExists(item)) @@ -527,7 +623,12 @@ namespace Tesses::Framework::Filesystem } void VFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) { - + StatData data; + if(Stat(path, data)) + { + lastWrite = data.LastModified; + lastAccess = data.LastAccess; + } } void VFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) { @@ -550,9 +651,12 @@ namespace Tesses::Framework::Filesystem } void VFS::Chmod(VFSPath path, uint32_t mode) { + } + void VFS::Chown(VFSPath path, uint32_t uid, uint32_t gid) { + } void VFS::Close() { - + } void VFS::Lock(VFSPath path) { @@ -560,7 +664,7 @@ namespace Tesses::Framework::Filesystem } void VFS::Unlock(VFSPath path) { - + } @@ -599,7 +703,7 @@ namespace Tesses::Framework::Filesystem { } - + std::shared_ptr FSWatcher::Create(std::shared_ptr vfs, VFSPath path) { return vfs->CreateWatcher(vfs,path); @@ -671,4 +775,4 @@ namespace Tesses::Framework::Filesystem return ""; } -} \ No newline at end of file +} diff --git a/src/Http/FileServer.cpp b/src/Http/FileServer.cpp index ad94f7e..fb4d47f 100644 --- a/src/Http/FileServer.cpp +++ b/src/Http/FileServer.cpp @@ -24,7 +24,7 @@ namespace Tesses::Framework::Http } FileServer::FileServer(std::shared_ptr fs, bool allowListing,bool spa) : FileServer(fs,allowListing,spa,{"index.html","default.html","index.htm","default.htm"}) { - + } FileServer::FileServer(std::shared_ptr fs, bool allowListing, bool spa, std::vector defaultNames) { @@ -44,7 +44,7 @@ namespace Tesses::Framework::Http this->vfs->GetDate(path,lw,la); ctx.WithLastModified(lw).WithMimeType(HttpUtils::MimeType(path.GetFileName())).SendStream(strm); retVal = true; - + } return retVal; } @@ -52,8 +52,8 @@ namespace Tesses::Framework::Http bool FileServer::Handle(ServerContext& ctx) { auto path = ((VFSPath)HttpUtils::UrlPathDecode(ctx.path)).CollapseRelativeParents(); - - + + if(this->vfs->DirectoryExists(path)) { TF_LOG("Directory exists"); @@ -73,10 +73,10 @@ namespace Tesses::Framework::Http std::string p = HttpUtils::HtmlEncode(ctx.originalPath); std::string html = "Index of "; html.append(p); - html.append("

    Index of "); + html.append("

    Index of "); html.append(p); html.append("


    ../\r\n");
    -                
    +
     
                     for(auto item : vfs->EnumeratePaths(path))
                     {
    @@ -103,7 +103,7 @@ namespace Tesses::Framework::Http
                     }
     
                     html.append("

    "); - + ctx.WithMimeType("text/html").SendText(html); return true; } @@ -126,6 +126,6 @@ namespace Tesses::Framework::Http } FileServer::~FileServer() { - + } -} \ No newline at end of file +} diff --git a/src/Http/HttpServer.cpp b/src/Http/HttpServer.cpp index bf7bd22..30b4358 100644 --- a/src/Http/HttpServer.cpp +++ b/src/Http/HttpServer.cpp @@ -13,6 +13,7 @@ #include "TessesFramework/Filesystem/VFSFix.hpp" #include "TessesFramework/Filesystem/VFS.hpp" +#include #include using FileStream = Tesses::Framework::Streams::FileStream; using Stream = Tesses::Framework::Streams::Stream; @@ -26,7 +27,7 @@ using namespace Tesses::Framework::TextStreams; namespace Tesses::Framework::Http { - class WSServer + class WSServer { public: Threading::Mutex mtx; @@ -43,9 +44,9 @@ namespace Tesses::Framework::Http uint8_t firstByte= finField | 0x8; strm->WriteByte(firstByte); strm->WriteByte(0); - + this->strm = nullptr; - mtx.Unlock(); + mtx.Unlock(); this->conn->OnClose(true); } void write_len_bytes(uint64_t len) @@ -84,7 +85,7 @@ namespace Tesses::Framework::Http { uint8_t buff[8]; if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0; - + uint64_t v = 0; v |= (uint64_t)buff[0] << 56; v |= (uint64_t)buff[1] << 48; @@ -100,7 +101,7 @@ namespace Tesses::Framework::Http { uint8_t buff[2]; if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0; - + uint16_t v = 0; v |= (uint16_t)buff[0] << 8; v |= (uint16_t)buff[1]; @@ -110,7 +111,7 @@ namespace Tesses::Framework::Http { while(!hasInit); mtx.Lock(); - + uint8_t opcode = msg->isBinary ? 0x2 : 0x1; size_t lengthLastByte = msg->data.size() % 4096; @@ -123,21 +124,21 @@ namespace Tesses::Framework::Http uint8_t finField = fin ? 0b10000000 : 0; uint8_t opcode2 = i == 0 ? opcode : 0; uint8_t firstByte = finField | (opcode2 & 0xF); - + size_t len = std::min((size_t)4096,msg->data.size()- offset); - + strm->WriteByte(firstByte); write_len_bytes((uint64_t)len); strm->WriteBlock(msg->data.data() + offset,len); offset += len; - } + } mtx.Unlock(); } void ping_send(std::vector& pData) { - + mtx.Lock(); - + uint8_t finField = 0b10000000 ; uint8_t firstByte= finField | 0x9; strm->WriteByte(firstByte); @@ -148,7 +149,7 @@ namespace Tesses::Framework::Http void pong_send(std::vector& pData) { mtx.Lock(); - + uint8_t finField = 0b10000000 ; uint8_t firstByte= finField | 0xA; strm->WriteByte(firstByte); @@ -158,7 +159,7 @@ namespace Tesses::Framework::Http } bool read_packet(uint8_t len,std::vector& data) { - + uint8_t realLen=len & 127; bool masked=(len & 0b10000000) > 0; uint64_t reallen2 = realLen >= 126 ? realLen > 126 ? get_long() : get_short() : realLen; @@ -180,7 +181,7 @@ namespace Tesses::Framework::Http } return true; } - + WSServer(ServerContext* ctx,std::shared_ptr conn) { this->ctx = ctx; @@ -188,7 +189,7 @@ namespace Tesses::Framework::Http this->strm = this->ctx->GetStream(); this->hasInit=false; - + } void Start() { @@ -198,7 +199,7 @@ namespace Tesses::Framework::Http { key.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); auto res = Crypto::Sha1::ComputeHash((const uint8_t*)key.c_str(),key.size()); - + if(res.empty()) return; key = Crypto::Base64_Encode(res); @@ -206,7 +207,7 @@ namespace Tesses::Framework::Http return; } - + if(!ctx->requestHeaders.AnyEquals("Upgrade","websocket")) { @@ -221,7 +222,7 @@ namespace Tesses::Framework::Http ctx->responseHeaders.SetValue("Connection","Upgrade"); ctx->responseHeaders.SetValue("Upgrade","websocket"); ctx->responseHeaders.SetValue("Sec-WebSocket-Accept",key); - + ctx->WriteHeaders(); bool hasMessage =false; @@ -232,11 +233,11 @@ namespace Tesses::Framework::Http while( !strm->EndOfStream()) { - + uint8_t frame_start[2]; if( strm->ReadBlock(frame_start,2) != 2) return; - - + + uint8_t opcode = frame_start[0] & 0xF; bool fin = (frame_start[0] & 0b10000000) > 0; switch(opcode) @@ -250,7 +251,7 @@ namespace Tesses::Framework::Http hasMessage=true; message.data = {}; message.isBinary = opcode == 0x2; - + read_packet(frame_start[1], message.data); break; case 0x8: @@ -280,7 +281,7 @@ namespace Tesses::Framework::Http } this->conn->OnClose(false); } - }; + }; /* static int _header_field(multipart_parser* p, const char *at, size_t length) { @@ -362,7 +363,7 @@ namespace Tesses::Framework::Http strm2->CopyTo(strm); } } - + std::string ServerContext::ReadString() { if(strm == nullptr) return {}; @@ -390,7 +391,7 @@ namespace Tesses::Framework::Http { bool hasMore=true; uint8_t* checkBuffer = new uint8_t[boundary.size()]; - + int b; size_t i = 0; size_t i2 = 0; @@ -429,21 +430,21 @@ namespace Tesses::Framework::Http { dest->Write(buffer, sizeof(buffer)); offsetInMem=0; - + } buffer[offsetInMem++] = checkBuffer[idx]; - + idx++; } i = 0; - + if(offsetInMem >= sizeof(buffer)) { dest->Write(buffer, sizeof(buffer)); offsetInMem=0; - + } buffer[offsetInMem++] = (uint8_t)b; @@ -455,7 +456,7 @@ namespace Tesses::Framework::Http dest->Write(buffer,offsetInMem); } delete[] checkBuffer; - + return hasMore; } @@ -466,7 +467,7 @@ namespace Tesses::Framework::Http std::string line; while(reader.ReadLineHttp(line)) { - auto v = HttpUtils::SplitString(line,": ", 2); + auto v = HttpUtils::SplitString(line,": ", 2); if(v.size() == 2) req.AddValue(v[0],v[1]); line.clear(); @@ -475,7 +476,7 @@ namespace Tesses::Framework::Http std::string cd0; ContentDisposition cd1; std::string ct; - + if(!req.TryGetFirst("Content-Type",ct)) ct = "application/octet-stream"; if(req.TryGetFirst("Content-Disposition", cd0) && ContentDisposition::TryParse(cd0,cd1)) @@ -494,10 +495,10 @@ namespace Tesses::Framework::Http } else { - auto strm = cb(ct, cd1.filename, cd1.fieldName); + auto strm = cb(ct, cd1.filename, cd1.fieldName); if(strm == nullptr) strm = std::make_shared(); bool retVal = parseUntillBoundaryEnd(ctx->GetStream(),strm,boundary); - + return retVal; } } @@ -521,9 +522,9 @@ namespace Tesses::Framework::Http parseUntillBoundaryEnd(this->strm,nullStrm, ct); while(parseSection(this, ct, cb)); - } + } - HttpServer::HttpServer(std::shared_ptr tcpServer, std::shared_ptr http, bool showIPs) + HttpServer::HttpServer(std::shared_ptr tcpServer, std::shared_ptr http, bool showIPs, bool debug) { this->server = tcpServer; this->http = http; @@ -531,19 +532,20 @@ namespace Tesses::Framework::Http this->showIPs = showIPs; this->thrd=nullptr; this->showARTL = showIPs; + this->debug = debug; } - - - HttpServer::HttpServer(uint16_t port, std::shared_ptr http, bool showIPs) : HttpServer(std::make_shared(port,10),http,showIPs) + + + HttpServer::HttpServer(uint16_t port, std::shared_ptr http, bool showIPs, bool debug) : HttpServer(std::make_shared(port,10),http,showIPs, debug) { - + } - - HttpServer::HttpServer(std::string unixPath, std::shared_ptr http) : HttpServer(std::make_shared(unixPath,10),http,false) + + HttpServer::HttpServer(std::string unixPath, std::shared_ptr http, bool debug) : HttpServer(std::make_shared(unixPath,10),http,false, debug) { this->showARTL=true; } - + uint16_t HttpServer::GetPort() { @@ -557,7 +559,7 @@ namespace Tesses::Framework::Http int64_t length = -1; if(!this->responseHeaders.TryGetFirstInt("Content-Length",length)) length = -1; - + if(this->version == "HTTP/1.1" && length == -1) this->responseHeaders.SetValue("Transfer-Encoding","chunked"); @@ -584,27 +586,29 @@ namespace Tesses::Framework::Http auto serverPort = this->server->GetPort(); auto http = this->http; TF_LOG("Before Creating Thread"); - thrd = new Threading::Thread([svr,http,serverPort]()->void { + bool debug = this->debug; + thrd = new Threading::Thread([svr,http,serverPort,debug]()->void { while(TF_IsRunning()) { TF_LOG("after TF_IsRunning"); std::string ip; uint16_t port; auto sock =svr->GetStream(ip,port); - + TF_LOG("New Host IP: " + ip + ":" + std::to_string(port)); - - if(sock == nullptr) + + if(sock == nullptr) { std::cout << "STREAM ERROR" << std::endl; return; } TF_LOG("Before entering socket thread"); - Threading::Thread thrd2([sock,http,ip,port,serverPort]()->void { + + Threading::Thread thrd2([sock,http,ip,port,serverPort,debug]()->void { TF_LOG("In thread to process"); - HttpServer::Process(sock,http,ip,port,serverPort,false); + HttpServer::Process(sock,http,ip,port,serverPort,false, debug); TF_LOG("In thread after process"); - + }); TF_LOG("Before attach"); thrd2.Detach(); @@ -614,7 +618,7 @@ namespace Tesses::Framework::Http if(this->showIPs) { TF_LOG("Before printing interfaces"); - + StdOut() << "\x1B[34mInterfaces:" << NewLine(); for(auto _ip : NetworkStream::GetIPs()) { @@ -623,15 +627,15 @@ namespace Tesses::Framework::Http << "\x1B[35mhttp://" << _ip.second << ":" << (uint64_t)this->GetPort() << "/" << NewLine(); } - - + + } if(this->showARTL) { if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl; StdOut() << "\x1B[31mAlmost Ready to Listen\x1B[39m" << NewLine(); } - + TF_LOG("After printing interfaces"); } HttpServer::~HttpServer() @@ -644,18 +648,20 @@ namespace Tesses::Framework::Http this->thrd->Join(); delete this->thrd; } - + } IHttpServer::~IHttpServer() { - + } - ServerContext::ServerContext(std::shared_ptr strm) + ServerContext::ServerContext(std::shared_ptr strm, bool debug) { this->statusCode = OK; this->strm = strm; + this->debug = debug; this->sent = false; this->queryParams.SetCaseSensitive(true); + this->pathArguments.SetCaseSensitive(true); this->responseHeaders.AddValue("Server","TessesFrameworkWebServer"); } std::shared_ptr ServerContext::GetStream() @@ -677,7 +683,7 @@ namespace Tesses::Framework::Http void ServerContext::SendText(std::string text) { std::shared_ptr strm=std::make_shared(false); - + auto& buff= strm->GetBuffer(); buff.insert(buff.end(),text.begin(),text.end()); SendStream(strm); @@ -685,11 +691,13 @@ namespace Tesses::Framework::Http void ServerContext::SendErrorPage(bool showPath) { if(sent) return; - std::string errorHtml = showPath ? ("File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

    " + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

    " + HttpUtils::HtmlEncode(this->originalPath) + "

    ") : ""; + std::string errorHtml = showPath ? ("File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

    " + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

    " + HttpUtils::HtmlEncode(this->originalPath) + "

    ") : ( + "" + std::to_string(this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

    " + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

    " + ); WithMimeType("text/html").SendText(errorHtml); } - + ServerContext::~ServerContext() { for(auto item : this->data) @@ -699,7 +707,7 @@ namespace Tesses::Framework::Http } ServerContextData::~ServerContextData() { - + } void ServerContext::SendStream(std::shared_ptr strm) { @@ -722,7 +730,7 @@ namespace Tesses::Framework::Http return; } res = HttpUtils::SplitString(res[1],", ",2); - if(res.size() != 1) + if(res.size() != 1) { this->statusCode = BadRequest; this->WriteHeaders(); @@ -764,7 +772,7 @@ namespace Tesses::Framework::Http if(end == -1) { - end = len-1; + end = len-1; } if(end > len-1) @@ -796,7 +804,7 @@ namespace Tesses::Framework::Http uint8_t buffer[1024]; size_t read=0; - + do { read = sizeof(buffer); myLen = (end - begin)+1; @@ -809,7 +817,7 @@ namespace Tesses::Framework::Http begin += read; } while(read > 0 && !this->strm->EndOfStream()); } - + } else { @@ -833,19 +841,19 @@ namespace Tesses::Framework::Http } else { - + auto chunkedStream = this->OpenResponseStream(); if(method != "HEAD") strm->CopyTo(chunkedStream); - - + + } } ServerContext& ServerContext::WithHeader(std::string key, std::string value) { this->responseHeaders.AddValue(key, value); - return *this; + return *this; } ServerContext& ServerContext::WithSingleHeader(std::string key, std::string value) { @@ -900,24 +908,40 @@ namespace Tesses::Framework::Http statusCode = StatusCode::BadRequest; SendErrorPage(false); } + ServerContext& ServerContext::WithStatusCode(StatusCode code) + { + this->statusCode = code; + return *this; + } void ServerContext::SendException(std::exception& ex) { - /* - - - - - Internal Server Error at / - - -

    Internal Server Error at /

    -

    what(): std::exception

    - -*/ - this->WithMimeType("text/html").SendText(" Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "

    Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "

    what(): " + HttpUtils::HtmlEncode(ex.what()) + "

    "); + if(this->debug) + { + + this->WithMimeType("text/html").WithStatusCode(StatusCode::InternalServerError).SendText(" Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "

    Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "

    what(): " + HttpUtils::HtmlEncode(ex.what()) + "

    "); + } + else { + this->WithStatusCode(StatusCode::InternalServerError).SendErrorPage(true); + } } + + ServerContext& ServerContext::WithHeaderIntercepter(std::function cb) + { + this->headerhandlers.push(cb); + return *this; + } + ServerContext& ServerContext::WriteHeaders() { + if(this->sent) return *this; + while(!this->headerhandlers.empty()) + { + auto header = this->headerhandlers.front(); + this->headerhandlers.pop(); + if(header(*this)) { + break; + } + } if(this->sent) return *this; this->sent = true; @@ -933,22 +957,20 @@ namespace Tesses::Framework::Http } } writer.WriteLine(); - + return *this; } - void HttpServer::Process(std::shared_ptr strm, std::shared_ptr server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted) + void HttpServer::Process(std::shared_ptr strm, std::shared_ptr server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted, bool debug) { TF_LOG("In process"); - while(true) - { - std::shared_ptr bStrm = std::make_shared(strm); - StreamReader reader(bStrm); - ServerContext ctx(bStrm); - ctx.ip = ip; - ctx.port = port; - ctx.encrypted = encrypted; - ctx.serverPort = serverPort; - try{ + std::shared_ptr bStrm = std::make_shared(strm); + StreamReader reader(bStrm); + ServerContext ctx(bStrm); + ctx.ip = ip; + ctx.port = port; + ctx.encrypted = encrypted; + ctx.serverPort = serverPort; + try{ bool firstLine = true; std::string line; while(reader.ReadLineHttp(line)) @@ -987,9 +1009,9 @@ namespace Tesses::Framework::Http ctx.WithMimeType("text/plain").SendText("Header line is not 2 elements"); return; } - + ctx.requestHeaders.AddValue(v[0],v[1]); - + } line.clear(); firstLine=false; @@ -1009,12 +1031,15 @@ namespace Tesses::Framework::Http delete[] buffer; HttpUtils::QueryParamsDecode(ctx.queryParams, query); } - - if(!server->Handle(ctx)) + + if(!server->Handle(ctx)) { - ctx.SendNotFound(); + if((int)ctx.statusCode < 400) + ctx.SendNotFound(); + else + ctx.SendErrorPage(true); } - } + } catch(std::exception& ex) { @@ -1033,26 +1058,23 @@ namespace Tesses::Framework::Http catch(...) { std::runtime_error ex("An unknown error occurred"); - ctx.SendException(ex); + ctx.SendException(ex); } - if(ctx.version != "HTTP/1.1" ) return; - std::string connection; - if(ctx.requestHeaders.TryGetFirst("Connection", connection)) - { - if(HttpUtils::ToLower(connection) != "keep-alive") return; - } - if(ctx.responseHeaders.TryGetFirst("Connection", connection)) - { - if(HttpUtils::ToLower(connection) != "keep-alive") return; - } - if(bStrm->EndOfStream()) { - return; - } - } + } + + bool ServerContext::Debug() + { + return this->debug; + } + + ServerContext& ServerContext::WithDebug(bool debug) + { + this->debug = debug; + return *this; } WebSocketConnection::~WebSocketConnection() @@ -1064,7 +1086,7 @@ namespace Tesses::Framework::Http std::shared_ptr wsc = std::make_shared(onOpen,onReceive,onClose); StartWebSocketSession(wsc); } - + void ServerContext::StartWebSocketSession(std::shared_ptr connection) { WSServer svr(this,connection); @@ -1080,7 +1102,7 @@ namespace Tesses::Framework::Http } }); - + svr.Start(); thrd.Join(); } @@ -1105,4 +1127,3 @@ namespace Tesses::Framework::Http } - diff --git a/src/TF_Init.cpp b/src/TF_Init.cpp index 6643a6c..da59df8 100644 --- a/src/TF_Init.cpp +++ b/src/TF_Init.cpp @@ -6,11 +6,15 @@ #include "TessesFramework/Filesystem/FSHelpers.hpp" #include "TessesFramework/Serialization/Json.hpp" #include +#include #include +#include #include +#include #include +#include -#if defined(TESSESFRAMEWORK_ENABLE_SQLITE) +#if defined(TESSESFRAMEWORK_ENABLE_SQLITE) extern "C" { #include "Serialization/sqlite/sqlite3.h" } @@ -52,8 +56,6 @@ static GXRModeObj *rmode = NULL; namespace Tesses::Framework { - - EventList OnItteraton; #if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__)) namespace Threading { @@ -64,13 +66,14 @@ namespace Tesses::Framework volatile static bool isRunningSig=true; volatile static std::atomic isRunning; volatile static std::atomic gaming_console_events=true; - + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + Threading::Mutex timers_mtx; Threading::Mutex invokings_mtx; std::queue> invokings; #endif - + void TF_Invoke(std::function cb) { @@ -86,7 +89,7 @@ namespace Tesses::Framework void TF_ConnectToSelf(uint16_t port) { Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false); - + } bool TF_IsRunning() { @@ -106,16 +109,142 @@ namespace Tesses::Framework } #if defined(__SWITCH__) bool initedConsole=false; - PadState default_pad; + PadState default_pad; #endif uint64_t ittr=0; + + + static std::shared_ptr timer_handler = std::make_shared(); + + std::shared_ptr TF_Timer_Handler::Make(std::shared_ptr handler) + { + auto timer = new TF_Timer_Handle(handler); + std::shared_ptr handle(timer); + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Lock(); + #endif + handler->handles.push_back(handle); + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Unlock(); + #endif + return handle; + } + + + std::shared_ptr TF_Timer() + { + return TF_Timer_Handler::Make(timer_handler); + } + std::shared_ptr TF_Timer(std::function cb, int64_t interval, bool enabled) + { + auto handle = TF_Timer(); + handle->SetCallback(cb); + handle->SetIntervalFromMilliseconds(interval); + + handle->SetEnabled(enabled); + return handle; + } + std::shared_ptr TF_Timer(std::function cb, std::chrono::duration interval, bool enabled) + { + auto handle = TF_Timer(); + handle->SetCallback(cb); + handle->SetIntervalFromDuration(interval); + + handle->SetEnabled(enabled); + return handle; + } + + void TF_Timer_Handler::Update() + { + std::chrono::time_point cur = std::chrono::time_point_cast(std::chrono::steady_clock::now()); + std::vector> cbs; + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Lock(); + #endif + + for(auto index = this->handles.begin(); index != this->handles.end(); index++) + { + if(index->expired()) + { + this->handles.erase(index); + index--; + } + else { + auto handle = index->lock(); + if(handle && handle->enabled && (handle->last + handle->interval) <= cur && handle->cb) + { + handle->last = cur; + cbs.push_back(handle->cb); + } + } + } + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Unlock(); + #endif + for(auto item : cbs) + { + item(); + } + } + void TF_Timer_Handle::SetCallback(std::function cb) + { + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Lock(); + #endif + this->cb = cb; + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Unlock(); + #endif + } + TF_Timer_Handle::TF_Timer_Handle(std::shared_ptr handler) : timerHandler(handler) + { + + } + void TF_Timer_Handle::SetEnabled(bool enabled) + { + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Lock(); + #endif + this->enabled = enabled; + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Unlock(); + #endif + } + bool TF_Timer_Handle::GetEnabled() + { + return this->enabled; + } + void TF_Timer_Handle::SetIntervalFromDuration(std::chrono::milliseconds ms) + { + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Lock(); + #endif + this->interval = ms; + #if defined(TESSESFRAMEWORK_ENABLE_THREADING) + timers_mtx.Unlock(); + #endif + } + void TF_Timer_Handle::SetIntervalFromMilliseconds(int64_t ms) + { + SetIntervalFromDuration(std::chrono::milliseconds(ms)); + } + std::chrono::duration TF_Timer_Handle::GetIntervalDuration() + { + return this->interval; + } + int64_t TF_Timer_Handle::GetIntervalMilliseconds() + { + return this->interval.count(); + } + + + + void TF_RunEventLoopItteration() { - - OnItteraton.Invoke(ittr++); #if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__)) Tesses::Framework::Threading::LookForFinishedThreads(); - + #endif #if defined(TESSESFRAMEWORK_ENABLE_THREADING) invokings_mtx.Lock(); @@ -125,10 +254,10 @@ namespace Tesses::Framework { invokes.front()(); invokes.pop(); - + } #endif - + if(!isRunningSig) isRunning=false; #if defined(GEKKO) if(gaming_console_events) @@ -140,7 +269,7 @@ namespace Tesses::Framework if(gaming_console_events) { if(!appletMainLoop()) isRunning=false; - + padUpdate(&default_pad); u64 kDown = padGetButtonsDown(&default_pad); @@ -163,7 +292,9 @@ namespace Tesses::Framework isRunning = false; } #endif - + + + timer_handler->Update(); } void TF_SetIsRunning(bool _isRunning) @@ -200,7 +331,7 @@ namespace Tesses::Framework signal(SIGINT, _sigInt); signal(SIGTERM, _sigInt); #endif - + isRunning=true; #if defined(_WIN32) WSADATA wsaData; @@ -230,9 +361,9 @@ if (iResult != 0) { // Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller) #else signal(SIGPIPE,SIG_IGN); - + #endif - + } bool TF_GetConsoleEventsEnabled() { @@ -332,7 +463,7 @@ if (iResult != 0) { } std::optional _argv0=std::nullopt; - + void TF_AllowPortable(std::string argv0) { @@ -346,7 +477,7 @@ if (iResult != 0) { auto portable=dir / "portable.json"; if(LocalFS->FileExists(portable)) { - + std::string portable_str; Helpers::ReadAllText(LocalFS,portable, portable_str); auto jsonObj=Json::Decode(portable_str); @@ -403,7 +534,7 @@ if (iResult != 0) { { if(paf_data) portable_config.user = LocalFS->SystemToVFSPath(*paf_data) / "TF_User"; - } + } else if(portable_str == "documents") { if(paf_documents) @@ -416,7 +547,7 @@ if (iResult != 0) { { if(portable_config.user) portable_config.desktop = *(portable_config.user) / "Desktop"; - } + } else if(portable_str == "documents") { if(paf_documents) @@ -429,7 +560,7 @@ if (iResult != 0) { { if(portable_config.user) portable_config.downloads = *(portable_config.user) / "Downloads"; - } + } else if(portable_str == "documents") { if(paf_documents) @@ -466,21 +597,21 @@ if (iResult != 0) { { if(dict2.TryGetValueAsType("user",portable_str)) { - if(portable_str != "system") + if(portable_str != "system") { auto userDir = dir / portable_str; portable_config.user = userDir.CollapseRelativeParents(); - + } } - + if(dict2.TryGetValueAsType("documents", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -490,7 +621,7 @@ if (iResult != 0) { portable_config.documents = *(portable_config.user) / "Documents"; } } - else + else { auto userDir = dir / portable_str; portable_config.documents = userDir.CollapseRelativeParents(); @@ -500,7 +631,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("downloads", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -510,7 +641,7 @@ if (iResult != 0) { portable_config.downloads = *(portable_config.user) / "Downloads"; } } - else + else { auto userDir = dir / portable_str; portable_config.downloads = userDir.CollapseRelativeParents(); @@ -520,7 +651,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("desktop", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -530,7 +661,7 @@ if (iResult != 0) { portable_config.desktop = *(portable_config.user) / "Desktop"; } } - else + else { auto userDir = dir / portable_str; portable_config.desktop = userDir.CollapseRelativeParents(); @@ -540,7 +671,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("pictures", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -550,7 +681,7 @@ if (iResult != 0) { portable_config.pictures = *(portable_config.user) / "Pictures"; } } - else + else { auto userDir = dir / portable_str; portable_config.pictures = userDir.CollapseRelativeParents(); @@ -560,7 +691,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("videos", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -570,7 +701,7 @@ if (iResult != 0) { portable_config.videos = *(portable_config.user) / "Videos"; } } - else + else { auto userDir = dir / portable_str; portable_config.videos = userDir.CollapseRelativeParents(); @@ -580,7 +711,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("music", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -590,7 +721,7 @@ if (iResult != 0) { portable_config.music = *(portable_config.user) / "Music"; } } - else + else { auto userDir = dir / portable_str; portable_config.music = userDir.CollapseRelativeParents(); @@ -600,7 +731,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("config", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -610,7 +741,7 @@ if (iResult != 0) { portable_config.config = *(portable_config.user) / "Config"; } } - else + else { auto userDir = dir / portable_str; portable_config.config = userDir.CollapseRelativeParents(); @@ -620,7 +751,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("cache", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -630,7 +761,7 @@ if (iResult != 0) { portable_config.cache = *(portable_config.user) / "Cache"; } } - else + else { auto userDir = dir / portable_str; portable_config.cache = userDir.CollapseRelativeParents(); @@ -640,7 +771,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("data", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -650,7 +781,7 @@ if (iResult != 0) { portable_config.data = *(portable_config.user) / "Data"; } } - else + else { auto userDir = dir / portable_str; portable_config.data = userDir.CollapseRelativeParents(); @@ -660,7 +791,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("state", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -670,7 +801,7 @@ if (iResult != 0) { portable_config.state = *(portable_config.user) / "State"; } } - else + else { auto userDir = dir / portable_str; portable_config.state = userDir.CollapseRelativeParents(); @@ -680,7 +811,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("temp", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -690,7 +821,7 @@ if (iResult != 0) { portable_config.temp = *(portable_config.user) / "Temp"; } } - else + else { auto userDir = dir / portable_str; portable_config.temp = userDir.CollapseRelativeParents(); @@ -698,40 +829,40 @@ if (iResult != 0) { } } } - - - - - - - - - - - - - - + + + + + + + + + + + + + + } else if(portable_str == "absolute") { if(dict2.TryGetValueAsType("user",portable_str)) { - if(portable_str != "system") + if(portable_str != "system") { VFSPath userDir = portable_str; portable_config.user = userDir.CollapseRelativeParents(); - + } } - + if(dict2.TryGetValueAsType("documents", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -741,7 +872,7 @@ if (iResult != 0) { portable_config.documents = *(portable_config.user) / "Documents"; } } - else + else { VFSPath userDir = portable_str; portable_config.documents = userDir.CollapseRelativeParents(); @@ -751,7 +882,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("downloads", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -761,7 +892,7 @@ if (iResult != 0) { portable_config.downloads = *(portable_config.user) / "Downloads"; } } - else + else { VFSPath userDir = portable_str; portable_config.downloads = userDir.CollapseRelativeParents(); @@ -771,7 +902,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("desktop", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -781,7 +912,7 @@ if (iResult != 0) { portable_config.desktop = *(portable_config.user) / "Desktop"; } } - else + else { VFSPath userDir = portable_str; portable_config.desktop = userDir.CollapseRelativeParents(); @@ -791,7 +922,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("pictures", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -801,7 +932,7 @@ if (iResult != 0) { portable_config.pictures = *(portable_config.user) / "Pictures"; } } - else + else { VFSPath userDir = portable_str; portable_config.pictures = userDir.CollapseRelativeParents(); @@ -811,7 +942,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("videos", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -821,7 +952,7 @@ if (iResult != 0) { portable_config.videos = *(portable_config.user) / "Videos"; } } - else + else { VFSPath userDir = portable_str; portable_config.videos = userDir.CollapseRelativeParents(); @@ -831,7 +962,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("music", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -841,7 +972,7 @@ if (iResult != 0) { portable_config.music = *(portable_config.user) / "Music"; } } - else + else { VFSPath userDir = portable_str; portable_config.music = userDir.CollapseRelativeParents(); @@ -851,7 +982,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("config", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -861,7 +992,7 @@ if (iResult != 0) { portable_config.config = *(portable_config.user) / "Config"; } } - else + else { VFSPath userDir = portable_str; portable_config.config = userDir.CollapseRelativeParents(); @@ -871,7 +1002,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("cache", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -881,7 +1012,7 @@ if (iResult != 0) { portable_config.cache = *(portable_config.user) / "Cache"; } } - else + else { VFSPath userDir = portable_str; portable_config.cache = userDir.CollapseRelativeParents(); @@ -891,7 +1022,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("data", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -901,7 +1032,7 @@ if (iResult != 0) { portable_config.data = *(portable_config.user) / "Data"; } } - else + else { VFSPath userDir = portable_str; portable_config.data = userDir.CollapseRelativeParents(); @@ -911,7 +1042,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("state", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -921,7 +1052,7 @@ if (iResult != 0) { portable_config.state = *(portable_config.user) / "State"; } } - else + else { VFSPath userDir = portable_str; portable_config.state = userDir.CollapseRelativeParents(); @@ -931,7 +1062,7 @@ if (iResult != 0) { } if(dict2.TryGetValueAsType("temp", portable_str)) { - + if(portable_str != "system") { if(portable_str == "default") @@ -941,7 +1072,7 @@ if (iResult != 0) { portable_config.temp = *(portable_config.user) / "Temp"; } } - else + else { VFSPath userDir = portable_str; portable_config.temp = userDir.CollapseRelativeParents(); @@ -949,7 +1080,7 @@ if (iResult != 0) { } } } - + } } }