Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update wfslib (few refactors and gcc-14 update) #37

Merged
merged 5 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ jobs:
configure_preset: "static"
build_preset: "static-release"
release_name: "linux-x86-64"
cc: "gcc-13"
cxx: "g++-13"
cc: "gcc-14"
cxx: "g++-14"

- platform: windows-latest
configure_preset: "windows-static"
Expand Down Expand Up @@ -58,7 +58,12 @@ jobs:
vcpkgJsonGlob: "vcpkg.json"

- name: Install requirements
run: sudo apt install libfuse-dev gcc-13 g++-13
run: |
# Temporary until gcc-14 is officialy released and available on the runner
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ noble main universe"
sudo apt update
sudo apt install gcc-14 g++-14
sudo apt install libfuse-dev
if: matrix.platform == 'ubuntu-latest'

- name: Install requirements (MacOS)
Expand Down Expand Up @@ -90,7 +95,7 @@ jobs:
shell: bash
if: matrix.cc != ''

- name: Run cmake
- name: Build
uses: lukka/run-cmake@v10
with:
configurePreset: ${{matrix.configure_preset}}
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.18)

project(wfs-tools)

option(BUILD_TESTS "Build the unit tests" OFF)
if(BUILD_TESTS)
enable_testing()
endif()

add_subdirectory(wfslib)

add_subdirectory(wfs-extract)
Expand Down
34 changes: 33 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
"CMAKE_MODULE_PATH": "${sourceDir}/cmake"
"CMAKE_MODULE_PATH": "${sourceDir}/cmake",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
Expand All @@ -35,6 +36,15 @@
"cacheVariables": {
"VCPKG_TARGET_TRIPLET": "$env{Platform}-windows-static"
}
},
{
"name": "tests",
"inherits": [
"default"
],
"cacheVariables": {
"BUILD_TESTS": "ON"
}
}
],
"buildPresets": [
Expand All @@ -57,6 +67,28 @@
"name": "windows-static-release",
"configurePreset": "windows-static",
"configuration": "Release"
},
{
"name": "debug-tests",
"configurePreset": "tests",
"configuration": "Debug"
},
{
"name": "release-tests",
"configurePreset": "tests",
"configuration": "Release"
}
],
"testPresets": [
{
"name": "run-debug-tests",
"configurePreset": "tests",
"configuration": "Debug"
},
{
"name": "run-release-tests",
"configurePreset": "tests",
"configuration": "Release"
}
]
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ sudo wfs-fuse /dev/sdb /mnt --otp otp.bin --seeprom seeprom.bin -o default_permi

## Build
Requirements:
* Visual Studio 2022 17.4+ / GCC 13+ / LLVM 17+
* Visual Studio 2022 17.4+ / GCC 14+ / LLVM 17+
* CMake 3.20+
* Ninja

Expand Down
1 change: 1 addition & 0 deletions vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"boost-dynamic-bitset",
"boost-iostreams",
"boost-program-options",
"catch2",
"cryptopp"
]
}
8 changes: 4 additions & 4 deletions wfs-extract/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ void dumpdir(const std::filesystem::path& target,
auto item = throw_if_error(item_or_error);
if (verbose)
std::cout << "Dumping /" << npath.generic_string() << std::endl;
if (item->IsDirectory()) {
if (item->is_directory()) {
dumpdir(target, std::dynamic_pointer_cast<Directory>(item), npath, verbose);
} else if (item->IsFile()) {
} else if (item->is_file()) {
auto file = std::dynamic_pointer_cast<File>(item);
std::ofstream output_file((target / npath).string(), std::ios::binary | std::ios::out);
size_t to_read = file->Size();
Expand Down Expand Up @@ -151,7 +151,7 @@ int main(int argc, char* argv[]) {

// Recovery mode
if (dump_usr_dir) {
auto wfs_with_usr_dir = Recovery::OpenUsrDirectoryWithoutWfsHeader(device, key);
auto wfs_with_usr_dir = Recovery::OpenUsrDirectoryWithoutWfsDeviceHeader(device, key);
if (!wfs_with_usr_dir.has_value()) {
if (wfs_with_usr_dir.error() == WfsError::kInvalidWfsVersion) {
std::cerr
Expand Down Expand Up @@ -192,7 +192,7 @@ int main(int argc, char* argv[]) {
throw WfsException(*detection_result);
return 1;
}
auto dir = Wfs(device, key).GetDirectory(dump_path);
auto dir = throw_if_error(WfsDevice::Open(device, key))->GetDirectory(dump_path);
if (!dir) {
std::cerr << "Error: Didn't find directory " << dump_path << " in wfs" << std::endl;
return 1;
Expand Down
2 changes: 1 addition & 1 deletion wfs-file-injector/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ int main(int argc, char* argv[]) {
throw WfsException(*detection_result);
return 1;
}
auto file = Wfs(device, key).GetFile(inject_path);
auto file = throw_if_error(WfsDevice::Open(device, key))->GetFile(inject_path);
if (!file) {
std::cerr << "Error: Didn't find file " << inject_path << " in wfs" << std::endl;
return 1;
Expand Down
24 changes: 12 additions & 12 deletions wfs-fuse/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <mutex>
#include <string>

static std::shared_ptr<Wfs> wfs;
static std::shared_ptr<WfsDevice> wfs_device;

struct locked_stream {
std::unique_ptr<File::stream> stream;
Expand All @@ -21,17 +21,17 @@ struct locked_stream {
static int wfs_getattr(const char* path, struct stat* stbuf) {
memset(stbuf, 0, sizeof(struct stat));

auto item = wfs->GetObject(path);
auto item = wfs_device->GetObject(path);
if (!item)
return -ENOENT;
if (item->IsDirectory()) {
if (item->is_directory()) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2 + std::dynamic_pointer_cast<Directory>(item)->Size();
} else if (item->IsLink()) {
} else if (item->is_link()) {
stbuf->st_mode = S_IFLNK | 0777;
stbuf->st_nlink = 1;
stbuf->st_size = 0; // TODO
} else if (item->IsFile()) {
} else if (item->is_file()) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = std::dynamic_pointer_cast<File>(item)->Size();
Expand All @@ -47,8 +47,8 @@ static int wfs_readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_
(void)offset;
(void)fi;

auto item = wfs->GetObject(path);
if (!item || !item->IsDirectory())
auto item = wfs_device->GetObject(path);
if (!item || !item->is_directory())
return -ENOENT;

filler(buf, ".", NULL, 0);
Expand All @@ -62,8 +62,8 @@ static int wfs_readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_
}

static int wfs_open(const char* path, struct fuse_file_info* fi) {
auto item = wfs->GetObject(path);
if (!item->IsFile())
auto item = wfs_device->GetObject(path);
if (!item->is_file())
return -ENOENT;

if ((fi->flags & O_ACCMODE) != O_RDONLY)
Expand Down Expand Up @@ -96,8 +96,8 @@ static int wfs_read(const char* path, char* buf, size_t size, off_t offset, stru

int wfs_readlink(const char* path, [[maybe_unused]] char* buf, [[maybe_unused]] size_t size) {
// TODO
auto item = wfs->GetObject(path);
if (!item || !item->IsLink())
auto item = wfs_device->GetObject(path);
if (!item || !item->is_link())
return -ENOENT;

// TODO
Expand Down Expand Up @@ -229,7 +229,7 @@ int main(int argc, char* argv[]) {
throw WfsException(*detection_result);
return 1;
}
wfs.reset(new Wfs(device, key));
wfs_device = throw_if_error(WfsDevice::Open(device, key));
} catch (std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
Expand Down
43 changes: 21 additions & 22 deletions wfs-info/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,29 @@
#include <vector>

#include <wfslib/wfslib.h>
#include "../../wfslib/src/area.h" // TOOD: Public header?
#include "../../wfslib/src/free_blocks_tree.h" // TOOD: Public header?
#include "../../wfslib/src/free_blocks_tree.h" // TOOD: Public header?
#include "../../wfslib/src/quota_area.h" // TOOD: Public header?
#include "../../wfslib/src/transactions_area.h" // TOOD: Public header?

std::string inline prettify_path(const std::filesystem::path& path) {
return "/" + path.generic_string();
}

void dumpArea(int depth, const std::filesystem::path& path, const std::shared_ptr<Area>& area) {
void quotaInfo(int depth, const std::filesystem::path& path, const std::shared_ptr<QuotaArea>& quota) {
std::string padding(depth, '\t');
std::cout << std::format("{}Area {} [0x{:08x}-0x{:08x}]:\n", padding, prettify_path(path), area->BlockNumber(),
area->AbsoluteBlockNumber(area->BlocksCount()));
std::cout << std::format("{}Area {} [0x{:08x}-0x{:08x}]:\n", padding, prettify_path(path),
quota->device_block_number(), quota->to_area_block_number(quota->blocks_count()));

padding += '\t';
std::shared_ptr<FreeBlocksAllocator> allocator = throw_if_error(area->GetFreeBlocksAllocator());
std::shared_ptr<FreeBlocksAllocator> allocator = throw_if_error(quota->GetFreeBlocksAllocator());
FreeBlocksTree tree(allocator.get());
auto* allocator_header = EPTree(allocator.get()).extra_header();

std::cout << std::format("{}Free blocks: 0x{:08x}\n", padding, allocator_header->free_blocks_count.value());
std::cout << std::format("{}Free metadata blocks: 0x{:08x}\n", padding,
allocator_header->free_metadata_blocks_count.value());
quota->to_device_block_number(allocator_header->free_blocks_cache_count.value()));
std::cout << std::format("{}Free metadata block: 0x{:08x}\n", padding,
area->AbsoluteBlockNumber(allocator_header->free_metadata_block.value()));

if (depth == 0) {
auto transactions_area = throw_if_error(area->GetTransactionsArea1());
std::cout << std::format("{}Transactions area [0x{:08x}-0x{:08x}]\n", padding, transactions_area->BlockNumber(),
transactions_area->AbsoluteBlockNumber(transactions_area->BlocksCount()));
}
quota->to_device_block_number(allocator_header->free_blocks_cache_count.value()));

std::vector<FreeBlocksRangeInfo> ranges;
for (const auto& extent : tree) {
Expand All @@ -55,22 +50,22 @@ void dumpArea(int depth, const std::filesystem::path& path, const std::shared_pt
std::cout << std::format("{}Free ranges:\n", padding);
padding += '\t';
for (const auto& range : ranges) {
std::cout << std::format("{}[0x{:08x}-0x{:08x}]\n", padding, area->AbsoluteBlockNumber(range.block_number),
area->AbsoluteBlockNumber(range.block_number + range.blocks_count));
std::cout << std::format("{}[0x{:08x}-0x{:08x}]\n", padding, quota->to_device_block_number(range.block_number),
quota->to_device_block_number(range.block_number + range.blocks_count));
}
}

void dumpdir(int depth, const std::shared_ptr<Directory>& dir, const std::filesystem::path& path) {
if (dir->IsQuota()) {
dumpArea(depth, path, dir->area());
void dirInfo(int depth, const std::shared_ptr<Directory>& dir, const std::filesystem::path& path) {
if (dir->is_quota()) {
quotaInfo(depth, path, dir->quota());
depth += 1;
}
for (auto [name, item_or_error] : *dir) {
auto const npath = path / name;
try {
auto item = throw_if_error(item_or_error);
if (item->IsDirectory())
dumpdir(depth, std::dynamic_pointer_cast<Directory>(item), npath);
if (item->is_directory())
dirInfo(depth, std::dynamic_pointer_cast<Directory>(item), npath);
} catch (const WfsException& e) {
std::cout << std::format("Error: Failed to dump {} ({})\n", prettify_path(npath), e.what());
}
Expand Down Expand Up @@ -156,8 +151,12 @@ int main(int argc, char* argv[]) {
throw WfsException(*detection_result);
return 1;
}
auto wfs_device = throw_if_error(WfsDevice::Open(device, key));
std::cout << "Allocator state:" << std::endl;
dumpdir(0, throw_if_error(Wfs(device, key).GetRootArea()->GetRootDirectory()), {});
auto transactions_area = throw_if_error(wfs_device->GetTransactionsArea());
std::cout << std::format("Transactions area [0x{:08x}-0x{:08x}]\n", transactions_area->device_block_number(),
transactions_area->to_device_blocks_count(transactions_area->blocks_count()));
dirInfo(0, throw_if_error(wfs_device->GetRootDirectory()), {});
std::cout << "Done!" << std::endl;
} catch (std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
Expand Down
Loading