Skip to content

Commit

Permalink
Merge branch 'fuse'
Browse files Browse the repository at this point in the history
  • Loading branch information
Talv committed Jul 31, 2019
2 parents d43b155 + 0dc9961 commit f1f271a
Show file tree
Hide file tree
Showing 12 changed files with 596 additions and 15 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change Log

## [2.1.0] - 2019-07-31

* Added basic support for mounting CASC as filesystem visible to the OS using [FUSE](https://github.com/libfuse/libfuse).
* Linux will work out of the box.
* MacOS is likely to work but hasn't been tested.
* Under Windows app is compiled against `dokanfuse` wrapper library. In order for it to work `Dokany` must be installed on the system.

## [2.0.0] - 2019-07-26

* Refactored entire codebase..
Expand Down
20 changes: 19 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 2.6)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${STORMEXTRACT_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${STORMEXTRACT_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${STORMEXTRACT_BINARY_DIR}/bin")
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

set(default_build_type "RelWithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
Expand All @@ -15,10 +16,16 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

# compile flags
set(CMAKE_CXX_FLAGS "-std=c++11")
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
set(FUSE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=27")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FUSE_REQUIRED_FLAGS}")

# modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/CMakeModules")

if (NOT EXISTS "${STORMEXTRACT_SOURCE_DIR}/CascLib/CMakeLists.txt")
message(FATAL_ERROR
Expand All @@ -38,6 +45,14 @@ endif()
add_subdirectory(CascLib)
add_subdirectory(plog)

# FUSE
find_package(FUSE REQUIRED)
if(NOT FUSE_FOUND)
message(FATAL_ERROR "Failed to find fuse")
else()
include_directories(${FUSE_INCLUDE_DIR})
endif()

include_directories("${STORMEXTRACT_SOURCE_DIR}/include/"
"${STORMEXTRACT_SOURCE_DIR}/CascLib/src/"
"${STORMEXTRACT_SOURCE_DIR}/cxxopts/include/"
Expand All @@ -47,12 +62,15 @@ include_directories("${STORMEXTRACT_SOURCE_DIR}/include/"
set(SRC_FILES
src/util.cc
src/storage.cc
src/cascfuse.cc
src/stormex.cc
)

add_executable(stormex ${SRC_FILES})

target_link_libraries(stormex plog)
target_link_libraries(stormex
${FUSE_LIBRARIES}
)

if(WIN32)
target_link_libraries(stormex casc_static)
Expand Down
41 changes: 41 additions & 0 deletions CMakeModules/FindFUSE.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Find the FUSE includes and library
#
# FUSE_INCLUDE_DIR - where to find fuse.h, etc.
# FUSE_LIBRARIES - List of libraries when using FUSE.
# FUSE_FOUND - True if FUSE lib is found.

# check if already in cache, be silent
IF (FUSE_INCLUDE_DIR)
SET (FUSE_FIND_QUIETLY TRUE)
ENDIF (FUSE_INCLUDE_DIR)

SET(DOKANY_DIR "C:\\Program Files\\Dokan\\Dokan Library-1.3.0")

# find includes
FIND_PATH (FUSE_INCLUDE_DIR fuse.h
/usr/local/include/osxfuse
/usr/local/include
/usr/include
"${DOKANY_DIR}\\include"
)

# find lib
if(APPLE)
SET(FUSE_NAMES libosxfuse.dylib fuse)
elseif (WIN32)
SET(FUSE_NAMES dokanfuse1)
else()
SET(FUSE_NAMES fuse)
endif(APPLE)

FIND_LIBRARY(FUSE_LIBRARIES
NAMES ${FUSE_NAMES}
PATHS /lib64 /lib /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib "${DOKANY_DIR}\\lib"
)

include (FindPackageHandleStandardArgs)
find_package_handle_standard_args ("FUSE" DEFAULT_MSG
FUSE_INCLUDE_DIR FUSE_LIBRARIES)

mark_as_advanced (FUSE_INCLUDE_DIR FUSE_LIBRARIES)

41 changes: 39 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,15 @@ Usage:
-x, --extract-all Extract all files matching search filters.
-X, --extract-file [FILE...] Extract file(s) matching exactly.
-o, --outdir [PATH] Output directory for extracted files.
(default: ./)
(default: .)
-p, --stdout Pipe content of a file(s) to stdout instead
writing it to the filesystem.
-P, --progress Notify about progress during extraction.
-n, --dry-run Simulate extraction process without writing
any data to the filesystem.
Mount options:
-m, --mount [MOUNTPOINT] Mount CASC as a filesystem
```

### Examples
Expand All @@ -103,7 +106,7 @@ stormex '/mnt/s1/BnetGameLib/StarCraft II' -ld | sort -h

```sh
stormex '/mnt/s1/BnetGameLib/StarCraft II' \
-I '\/(DocumentInfo|Objects|Regions|Triggers)$' \
-I '\\(DocumentInfo|Objects|Regions|Triggers)$' \
-I '\.(fx|xml|txt|json|galaxy|SC2Style|SC2Hotkeys|SC2Lib|TriggerLib|SC2Interface|SC2Locale|SC2Components|SC2Layout)$' \
-E '(dede|eses|esmx|frfr|itit|kokr|plpl|ptbr|ruru|zhcn|zhtw)\.sc2data' \
-E '(PreloadAssetDB|TextureReductionValues)\.txt$' \
Expand All @@ -122,6 +125,40 @@ stormex -S '/mnt/s1/BnetGameLib/StarCraft II' -X 'mods/core.sc2mod/base.sc2data/
stormex -S '/mnt/s1/BnetGameLib/StarCraft II' -X 'mods/core.sc2mod/base.sc2data/EditorData/Images/EditorLogo.dds' -p | magick dds: png: | display png:
```

#### Mount as FUSE filesystem

```sh
mkdir -p cascfs
stormex -v -S '/mnt/s1/BnetGameLib/StarCraft II' -m ./cascfs
```

Result:

```sh
$ ls -l ./cascfs
dr-xr-xr-- - root 1 Jan 1970 campaigns
dr-xr-xr-- - root 1 Jan 1970 CKEY
.r-xr-xr-- 17M root 1 Jan 1970 DOWNLOAD
.r-xr-xr-- 41M root 1 Jan 1970 ENCODING
.r-xr-xr-- 59k root 1 Jan 1970 INSTALL
dr-xr-xr-- - root 1 Jan 1970 mods
.r-xr-xr-- 20M root 1 Jan 1970 ROOT
dr-xr-xr-- - root 1 Jan 1970 versions.osxarchive
dr-xr-xr-- - root 1 Jan 1970 versions.winarchive
```

##### Windows support via Dokany

[Dokany](https://github.com/dokan-dev) provides a FUSE wrapper for Windows. You've to install [Dokany's system driver](https://github.com/dokan-dev/dokany/wiki/Installation) in order for this feature to work.

As `[MOUNTPOINT]` argument provide a free drive letter. In following example CASC will be mounted at `S:\`.

```sh
stormex.exe -v -S X:\shared\SC2.4.8.4.73286 -m S
```

[![](https://i.imgur.com/1y7zCTL.png)](https://i.imgur.com/1y7zCTL.png)

## Credits

* Powered by [CascLib](https://github.com/ladislav-zezula/CascLib)
5 changes: 5 additions & 0 deletions include/cascfuse.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include "storage.hpp"

int cascfs_mount(const std::string& mountPoint, HANDLE hStorage);
2 changes: 1 addition & 1 deletion include/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "mplog/ColorConsoleAppenderStderr.h"
// #include "plog/Formatters/FuncMessageFormatter.h"

static const std::string stormexVersion = "2.0.1";
static const std::string stormexVersion = "2.1.0";

static plog::ColorConsoleAppenderStdErr<plog::TxtFormatter> consoleAppender;
// static plog::ColorConsoleAppender<plog::FuncMessageFormatter> consoleAppender;
Expand Down
4 changes: 3 additions & 1 deletion include/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ class StorageExplorer {
HANDLE m_hStorage = nullptr;

public:
const HANDLE& getHandle() { return m_hStorage; }
HANDLE getHandle() { return m_hStorage; }

~StorageExplorer();

/**
* @brief Open CASC
Expand Down
5 changes: 4 additions & 1 deletion include/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ int ensureDirExists(std::string strDestName);
std::string formatFileSize(size_t size);

/// Try to find in the Haystack the Needle - ignore case
bool findStringIC(const std::string& strHaystack, const std::string& strNeedle);
bool stringFindIC(const std::string& strHaystack, const std::string& strNeedle);
bool stringEqualIC(const std::string& str1, const std::string& str2);
void stringToLower(std::string& str);
std::string stringToLowerCopy(std::string str);

#endif // __UTIL_HPP__
Loading

0 comments on commit f1f271a

Please sign in to comment.