Skip to content

Commit

Permalink
Add windows support using winfsp
Browse files Browse the repository at this point in the history
  • Loading branch information
averne committed Feb 24, 2021
1 parent 4ccc61b commit ab6badb
Show file tree
Hide file tree
Showing 23 changed files with 299 additions and 103 deletions.
22 changes: 0 additions & 22 deletions .github/workflows/bindings.yml

This file was deleted.

106 changes: 106 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
on: [push, pull_request]

jobs:
main:
strategy:
fail-fast: false
matrix:
job_name: ['linux', 'windows']

include:
- job_name: linux
os: ubuntu-latest
shell: bash {0}

- job_name: windows
os: windows-latest
shell: msys2 {0}

defaults:
run:
shell: ${{ matrix.shell }}

name: main - ${{ matrix.job_name }}
runs-on: ${{ matrix.os }}

steps:
- uses: msys2/setup-msys2@v2
if: matrix.os == 'windows-latest'
with:
path-type: inherit
msystem: MINGW64
update: true
install: mingw-w64-x86_64-gcc mingw-w64-x86_64-make

- run: choco install -y winfsp
if: matrix.os == 'windows-latest'
shell: powershell

- run: |
sudo apt install -y libfuse-dev libgcrypt-dev libre2-dev gcc-10 g++-10
echo CC=gcc-10 >> $GITHUB_ENV
echo CXX=g++-10 >> $GITHUB_ENV
if: matrix.os == 'ubuntu-latest'
- uses: actions/checkout@v1

- uses: actions/setup-python@v1
with:
python-version: '3.x'

- run: pip install meson ninja

- run: meson setup build

- run: meson compile -C build -v

- uses: actions/upload-artifact@v1
if: failure()
with:
name: compile-log
path: build/meson-logs/meson-log.txt

bindings:
strategy:
fail-fast: false
matrix:
job_name: ['linux', 'windows']

include:
- job_name: linux
os: ubuntu-latest
shell: bash {0}

- job_name: windows
os: windows-latest
shell: msys2 {0}

defaults:
run:
shell: ${{ matrix.shell }}

name: bindings - ${{ matrix.job_name }}
runs-on: ${{ matrix.os }}

steps:
- uses: msys2/setup-msys2@v2
if: matrix.os == 'windows-latest'
with:
msystem: MINGW64
update: true
install: mingw-w64-x86_64-gcc mingw-w64-x86_64-python mingw-w64-x86_64-python-setuptools mingw-w64-x86_64-libgcrypt

- run: |
sudo apt install -y libgcrypt-dev gcc-10 g++-10
echo CC=gcc-10 >> $GITHUB_ENV
echo CXX=g++-10 >> $GITHUB_ENV
if: matrix.os == 'ubuntu-latest'
- uses: actions/setup-python@v1
if: matrix.os == 'ubuntu-latest'
with:
python-version: '3.x'

- uses: actions/checkout@v1

- run: python setup.py build
30 changes: 0 additions & 30 deletions .github/workflows/main.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"compileCommands": "build/compile_commands.json",
"includePath": [
"${workspaceRoot}/include",
"/usr/include/python3.8/"
"/usr/include/python3.9/"
],
"compilerPath": "/bin/gcc",
"cStandard": "gnu11",
Expand Down
24 changes: 24 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@
}
]
},
{
"name": "Debug (gdb) (windows)",
"type": "cppdbg",
"request": "launch",
"preLaunchTask": "predebug",
"externalConsole": false,
"program": "${workspaceRoot}/build/fuse-nx.exe",
"cwd": "${workspaceRoot}",
"args": [
"mount",
"-r",
"${workspaceRoot}/data/test.xci",
"${workspaceRoot}/data/test",
],
"MIMode": "gdb",
"miDebuggerPath": "C:\\msys64\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "Attach (gdb)",
"type": "cppdbg",
Expand Down
10 changes: 8 additions & 2 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
{
"label": "all",
"type": "shell",
"command": "LANG=en meson compile -j$(nproc)",
"command": "meson compile",
"options": {
"cwd": "build"
"cwd": "build",
"env": {
"LANG": "en",
}
},
"presentation": {
"reveal": "always",
Expand Down Expand Up @@ -58,6 +61,9 @@
"label": "unmount",
"type": "shell",
"command": "fusermount -u data/test || :",
"windows": {
"command": "[void]"
},
"presentation": {
"panel": "shared",
"reveal": "never"
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Mount Nintendo Switch archive as filesystems, and find/extract files from them.
<img src="https://user-images.githubusercontent.com/45773016/94306398-2e388780-ff73-11ea-8595-fc8425afd7a7.png" height="250" />
<img src="https://user-images.githubusercontent.com/45773016/94306638-a69f4880-ff73-11ea-984d-3fc893990064.png" height="250" />
<img src="https://user-images.githubusercontent.com/45773016/94306437-3db7d080-ff73-11ea-97f8-228ea32f3739.png" height="250" />
<img src="https://user-images.githubusercontent.com/45773016/109013087-07fa4d80-76b3-11eb-94ab-082af0c92214.png" height="250" />
</p>

## Supported formats
Expand All @@ -23,7 +24,9 @@ Refer to the built-in help (`-h`/`--help`). You can find help on a specific subc

### Windows

Windows is supported via WSL. To access the filesystem through the explorer, you will need to pass the `-o allow_other` flag to FUSE, and add `user_allow_other` to `/etc/fuse.conf`.
Windows is supported via:
- [WinFsp](http://www.secfs.net/winfsp/rel/): make sure that `winfsp-x64.dll` (found in `C:\Program Files (x86)\WinFsp\bin` after installing) is present in the same directory as the executable;
- WSL: To access the filesystem through the explorer, you will need to pass the `-o allow_other` flag to FUSE when mounting, and add `user_allow_other` to `/etc/fuse.conf`.

## Project layout

Expand Down
2 changes: 1 addition & 1 deletion include/fnx/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class FileBase {

class File final: public FileBase {
public:
File(const std::string_view &path, const char *mode = "r") {
File(const std::string_view &path, const char *mode = "rb") {
this->open(path, mode);
}

Expand Down
41 changes: 38 additions & 3 deletions lib/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@
// You should have received a copy of the GNU General Public License
// along with Fuse-Nx. If not, see <http://www.gnu.org/licenses/>.

#include <cstring>
#include <cinttypes>

#include <fnx/io.hpp>

#ifdef __MINGW32__
# define fseek fseeko64
#endif

namespace fnx::io {

bool File::open(const std::string_view &path, const char *mode) {
Expand All @@ -34,18 +41,46 @@ std::uint64_t File::update_size() {
}

std::size_t File::read(void *dest, std::uint64_t size) {
#ifdef __MINGW32__
_lock_file(this->fp.get());
#else
flockfile(this->fp.get());
FNX_SCOPEGUARD([this] { funlockfile(this->fp.get()); });
#endif

FNX_SCOPEGUARD([this] {
#ifdef __MINGW32__
_unlock_file(this->fp.get());
#else
funlockfile(this->fp.get());
#endif
});

if (auto rc = fseek(this->fp.get(), this->pos, SEEK_SET); rc != 0)
std::fprintf(stderr, "Failed to seek in %s: %d (%d -> %s)\n", this->path.c_str(), rc, errno, std::strerror(errno));

std::fseek(this->fp.get(), this->pos, SEEK_SET);
auto read = std::fread(dest, 1, size, this->fp.get());
if (read != size)
std::fprintf(stderr, "Failed to read %s at %#" PRIx64 " (expected %#" PRIx64 ", got %#" PRIx64 "): %d (%s), %d (%s)\n",
this->path.c_str(), this->pos, size, read, std::ferror(this->fp.get()), std::strerror(std::ferror(this->fp.get())),
errno, std::strerror(errno));
this->pos += read;
return read;
}

std::size_t File::write(const void *src, std::uint64_t size) {
#ifdef __MINGW32__
_lock_file(this->fp.get());
#else
flockfile(this->fp.get());
FNX_SCOPEGUARD([this] { funlockfile(this->fp.get()); });
#endif

FNX_SCOPEGUARD([this] {
#ifdef __MINGW32__
_unlock_file(this->fp.get());
#else
funlockfile(this->fp.get());
#endif
});

auto written = std::fwrite(src, 1, size, this->fp.get());
this->pos += written;
Expand Down
2 changes: 1 addition & 1 deletion lib/nca.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
// along with Fuse-Nx. If not, see <http://www.gnu.org/licenses/>.

#include <cstdlib>
#include <cinttypes>
#include <algorithm>
#include <array>
#include <cinttypes>

#include <fnx/crypto.hpp>

Expand Down
21 changes: 17 additions & 4 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,22 @@ else
exe_deps += crypto_dep
endif

if get_option('fuse').enabled()
exe_deps += dependency('fuse')
if host_machine.system() == 'windows'
exe_deps += declare_dependency(include_directories: include_directories('C:/Program Files (x86)/WinFsp/inc/fuse'))
exe_deps += meson.get_compiler('cpp').find_library('winfsp-x64', dirs: 'C:/Program Files (x86)/WinFsp/lib', static: true)
else
exe_deps += dependency('fuse', required: true)
add_project_arguments('-DFUSE_USE_VERSION=26', language: ['c', 'cpp'])
endif

cli11 = subproject('CLI11')
exe_deps += cli11.get_variable('CLI11_dep')
exe_deps += dependency('re2', fallback: ['re2', 're2_dep'])

if host_machine.system() == 'windows'
exe_deps += meson.get_compiler('cpp').find_library('Shlwapi', required: true)
endif

lib_inc = include_directories('include')
lib_src = []
subdir('lib')
Expand All @@ -51,15 +58,21 @@ subdir('src')

fnx_lib = library('fnx',
lib_src,
include_directories: lib_inc
include_directories: lib_inc,
dependencies: crypto_dep,
)

exe_ldargs = ['-Wl,--gc-sections']
if host_machine.system() == 'windows'
exe_ldargs += ['-static', '-static-libgcc']
endif

executable('fuse-nx',
exe_src,
include_directories: lib_inc,
dependencies: exe_deps,
link_with: fnx_lib,
cpp_args: '-std=gnu++20', # re2 pkg-config overrides the standard version to c++11
link_args: '-Wl,--gc-sections',
link_args: exe_ldargs,
install: true,
)
3 changes: 2 additions & 1 deletion src/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
#include <filesystem>

#include "vfs.hpp"
#include "utils.hpp"

namespace fnx {

struct Context {
Context(const std::filesystem::path &container): container(container) {
this->filesys = std::make_unique<FileSystem>(container);
if (auto dir = this->filesys->get_folder("/"); !dir) {
std::fprintf(stderr, "Unrecognized file type for \"%s\"\n", container.c_str());
std::fprintf(stderr, "Unrecognized file type for \"%s\"\n", PATHSTR(container).c_str());
std::exit(EXIT_FAILURE);
}
}
Expand Down
Loading

0 comments on commit ab6badb

Please sign in to comment.