Compare commits
15 Commits
Author | SHA1 | Date |
---|---|---|
Matéo Duparc | 35a2198ac9 | |
Matéo Duparc | 267fb40fe7 | |
Matéo Duparc | f03d39433c | |
Matéo Duparc | 9c19680b55 | |
Matéo Duparc | fb593c468c | |
Matéo Duparc | ac2b8a615b | |
Matéo Duparc | f89ac70d59 | |
Matéo Duparc | 6cd6d9ef5d | |
Matéo Duparc | 412df2e7be | |
Matéo Duparc | e9f000353b | |
Matéo Duparc | 03fffc44a5 | |
Matéo Duparc | 56c7d96bbf | |
Matéo Duparc | e6d735dbab | |
Matéo Duparc | 3866607d68 | |
Matéo Duparc | 3df8023b21 |
|
@ -42,8 +42,5 @@ if(MSVC)
|
|||
add_definitions(/bigobj)
|
||||
endif()
|
||||
|
||||
# Hardcoded version. Don't forget to change this when merging upstream!
|
||||
set(GIT_VERSION "0.11.4-libcryfs")
|
||||
|
||||
add_subdirectory(vendor EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
Version 0.11.4
|
||||
Version 0.12.0 (unreleased)
|
||||
---------------
|
||||
* Fixed build issue with GCC 13 (see https://github.com/cryfs/cryfs/pull/448 )
|
||||
* Fixed build issue with Python 3.12 (see https://github.com/cryfs/cryfs/issues/459 )
|
||||
|
||||
Version 0.11.3
|
||||
---------------
|
||||
* Fixed build issue on systems with libfmt 9.0 (see https://github.com/cryfs/cryfs/issues/432 )
|
||||
* Fixed build issue on Apple Silicon Macs (see https://github.com/cryfs/homebrew-tap/issues/10 )
|
||||
* Fixed build issue on systems that only have `python3` but no `python` executable (see https://github.com/cryfs/homebrew-tap/issues/12 )
|
||||
* Updated to DokanY 1.3.0.1000
|
||||
|
||||
Version 0.11.2
|
||||
---------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
libcryfs is a re-design of the original [CryFS](https://github.com/cryfs/cryfs) code to work as a library. Volumes are not mounted with [FUSE](https://www.kernel.org/doc/html/latest/filesystems/fuse.html) but rather opened in memory and accessed through API calls. What's the purpose ?
|
||||
libcryfs is a re-desing of the original [CryFS](https://github.com/cryfs/cryfs) code to work as a library. Volumes are not mounted with [FUSE](https://www.kernel.org/doc/html/latest/filesystems/fuse.html) but rather opened in memory and accessed through API calls. What the purpose ?
|
||||
- Allow the use of CryFS on platforms where FUSE is not available (such as Android)
|
||||
- Reduce attack surface by restricting volumes access to only one process rather than one user
|
||||
|
||||
|
@ -14,7 +14,6 @@ Here is what has been modified from the original project:
|
|||
- sh scripts, `cpack`, `doc`, `test` and `vendor/googletest` deleted
|
||||
- Main program `cryfs-cli` removed
|
||||
- boost build configured with [Boost-for-Android](https://github.com/moritz-wundke/Boost-for-Android)
|
||||
- Automatic version detection removed
|
||||
- Interactive mode removed (including any writes to stdout)
|
||||
- Logging output redirected to logcat
|
||||
- JNI API created in `src/jni`
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#pragma once
|
||||
#ifndef CPPUTILS_SIZEDDATA_H
|
||||
#define CPPUTILS_SIZEDDATA_H
|
||||
|
||||
struct SizedData {
|
||||
unsigned char* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -4,7 +4,6 @@
|
|||
#include <thread>
|
||||
#include <cpp-utils/macros.h>
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace cpputils {
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <cpp-utils/io/DontEchoStdinToStdoutRAII.h>
|
||||
#include <cryfs/impl/filesystem/CryDevice.h>
|
||||
#include <cryfs/impl/config/CryConfigLoader.h>
|
||||
#include <cryfs/impl/config/CryDirectKeyProvider.h>
|
||||
#include <cryfs/impl/config/CryPresetPasswordBasedKeyProvider.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
|
@ -90,9 +89,9 @@ namespace cryfs_cli {
|
|||
basedirMetadata.save();
|
||||
}
|
||||
|
||||
CryConfigLoader::ConfigLoadResult Cli::_loadOrCreateConfig(const ProgramOptions &options, const LocalStateDir& localStateDir, Credentials credentials) {
|
||||
CryConfigLoader::ConfigLoadResult Cli::_loadOrCreateConfig(const ProgramOptions &options, const LocalStateDir& localStateDir, unique_ptr<string> password) {
|
||||
auto configFile = _determineConfigFile(options);
|
||||
auto config = _loadOrCreateConfigFile(std::move(configFile), localStateDir, credentials, options.cipher(), options.blocksizeBytes(), options.allowFilesystemUpgrade(), options.missingBlockIsIntegrityViolation(), options.allowReplacedFilesystem());
|
||||
auto config = _loadOrCreateConfigFile(std::move(configFile), localStateDir, std::move(password), options.cipher(), options.blocksizeBytes(), options.allowFilesystemUpgrade(), options.missingBlockIsIntegrityViolation(), options.allowReplacedFilesystem());
|
||||
if (config.is_left()) {
|
||||
switch(config.left()) {
|
||||
case CryConfigFile::LoadError::DecryptionFailed:
|
||||
|
@ -105,30 +104,24 @@ namespace cryfs_cli {
|
|||
return std::move(config.right());
|
||||
}
|
||||
|
||||
unique_ref<CryKeyProvider> Cli::_createKeyProvider(Credentials credentials) {
|
||||
if (credentials.password == none) {
|
||||
return make_unique_ref<CryDirectKeyProvider>(credentials.givenHash);
|
||||
} else {
|
||||
return make_unique_ref<CryPresetPasswordBasedKeyProvider>(
|
||||
*credentials.password,
|
||||
make_unique_ref<SCrypt>(_scryptSettings),
|
||||
credentials.returnedHash
|
||||
);
|
||||
}
|
||||
either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, LocalStateDir localStateDir, unique_ptr<string> password, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem) {
|
||||
// TODO Instead of passing in _askPasswordXXX functions to KeyProvider, only pass in console and move logic to the key provider,
|
||||
// for example by having a separate CryPasswordBasedKeyProvider / CryNoninteractivePasswordBasedKeyProvider.
|
||||
auto keyProvider = make_unique_ref<CryPresetPasswordBasedKeyProvider>(
|
||||
*password.get(),
|
||||
make_unique_ref<SCrypt>(_scryptSettings)
|
||||
);
|
||||
return CryConfigLoader(_keyGenerator, std::move(keyProvider), std::move(localStateDir), cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
||||
}
|
||||
|
||||
either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, LocalStateDir localStateDir, Credentials credentials, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem) {
|
||||
return CryConfigLoader(_keyGenerator, _createKeyProvider(credentials), std::move(localStateDir), cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
||||
}
|
||||
|
||||
fspp::fuse::Fuse* Cli::initFilesystem(const ProgramOptions &options, Credentials credentials) {
|
||||
fspp::fuse::Fuse* Cli::initFilesystem(const ProgramOptions &options, unique_ptr<string> password) {
|
||||
cpputils::showBacktraceOnCrash();
|
||||
cpputils::set_thread_name("cryfs");
|
||||
try {
|
||||
_sanityChecks(options);
|
||||
LocalStateDir localStateDir(options.localStateDir());
|
||||
auto blockStore = make_unique_ref<OnDiskBlockStore2>(options.baseDir());
|
||||
auto config = _loadOrCreateConfig(options, localStateDir, credentials);
|
||||
auto config = _loadOrCreateConfig(options, localStateDir, std::move(password));
|
||||
fspp::fuse::Fuse* fuse = nullptr;
|
||||
|
||||
auto onIntegrityViolation = [&fuse] () {
|
||||
|
@ -152,12 +145,14 @@ namespace cryfs_cli {
|
|||
return make_shared<fspp::FilesystemImpl>(std::move(*_device));
|
||||
};
|
||||
|
||||
fuse = new fspp::fuse::Fuse(initFilesystem);
|
||||
fuse = new fspp::fuse::Fuse(initFilesystem, "cryfs", "cryfs@" + options.baseDir().string());
|
||||
|
||||
fuse->init();
|
||||
return fuse;
|
||||
} catch (const CryfsException &e) {
|
||||
throw; // CryfsException is only thrown if setup goes wrong. Throw it through so that we get the correct process exit code.
|
||||
if (e.what() != string()) {
|
||||
LOG(ERR, "Error {}: {}", static_cast<int>(e.errorCode()), e.what());
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG(ERR, "Crashed: {}", e.what());
|
||||
} catch (...) {
|
||||
|
|
|
@ -5,13 +5,11 @@
|
|||
#include <fspp/fuse/Fuse.h>
|
||||
#include "program_options/ProgramOptions.h"
|
||||
#include <cryfs/impl/config/CryConfigFile.h>
|
||||
#include <cryfs/impl/config/CryKeyProvider.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <cpp-utils/tempfile/TempFile.h>
|
||||
#include <cpp-utils/io/Console.h>
|
||||
#include <cpp-utils/random/RandomGenerator.h>
|
||||
#include <cpp-utils/network/HttpClient.h>
|
||||
#include <cpp-utils/SizedData.h>
|
||||
#include <cryfs/impl/filesystem/CryDevice.h>
|
||||
#include "CallAfterTimeout.h"
|
||||
#include <cryfs/impl/config/CryConfigLoader.h>
|
||||
|
@ -20,20 +18,16 @@
|
|||
namespace cryfs_cli {
|
||||
class Cli final {
|
||||
public:
|
||||
struct Credentials {
|
||||
boost::optional<string> password;
|
||||
SizedData givenHash;
|
||||
SizedData* returnedHash;
|
||||
};
|
||||
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings& scryptSettings);
|
||||
fspp::fuse::Fuse* initFilesystem(const program_options::ProgramOptions &options, Credentials credentials);
|
||||
fspp::fuse::Fuse* initFilesystem(const program_options::ProgramOptions &options, std::unique_ptr<string> password);
|
||||
|
||||
private:
|
||||
cryfs::CryConfigLoader::ConfigLoadResult _loadOrCreateConfig(const program_options::ProgramOptions &options, const cryfs::LocalStateDir& localStateDir, Credentials credentials);
|
||||
void _checkForUpdates(cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
||||
cryfs::CryConfigLoader::ConfigLoadResult _loadOrCreateConfig(const program_options::ProgramOptions &options, const cryfs::LocalStateDir& localStateDir, std::unique_ptr<string> password);
|
||||
void _checkConfigIntegrity(const boost::filesystem::path& basedir, const cryfs::LocalStateDir& localStateDir, const cryfs::CryConfigFile& config, bool allowReplacedFilesystem);
|
||||
cpputils::unique_ref<cryfs::CryKeyProvider> _createKeyProvider(Credentials credentials);
|
||||
cpputils::either<cryfs::CryConfigFile::LoadError, cryfs::CryConfigLoader::ConfigLoadResult> _loadOrCreateConfigFile(boost::filesystem::path configFilePath, cryfs::LocalStateDir localStateDir, Credentials credentials, const boost::optional<std::string> &cipher, const boost::optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const boost::optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem);
|
||||
cpputils::either<cryfs::CryConfigFile::LoadError, cryfs::CryConfigLoader::ConfigLoadResult> _loadOrCreateConfigFile(boost::filesystem::path configFilePath, cryfs::LocalStateDir localStateDir, std::unique_ptr<string> password, const boost::optional<std::string> &cipher, const boost::optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const boost::optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem);
|
||||
boost::filesystem::path _determineConfigFile(const program_options::ProgramOptions &options);
|
||||
void _initLogfile();
|
||||
void _sanityChecks(const program_options::ProgramOptions &options);
|
||||
void _checkDirAccessible(const boost::filesystem::path &dir, const std::string &name, bool createMissingDir, cryfs::ErrorCode errorCode);
|
||||
void _sanityCheckFilesystem(cryfs::CryDevice *device);
|
||||
|
|
|
@ -19,7 +19,6 @@ set(LIB_SOURCES
|
|||
impl/config/CryKeyProvider.cpp
|
||||
impl/config/CryPasswordBasedKeyProvider.cpp
|
||||
impl/config/CryPresetPasswordBasedKeyProvider.cpp
|
||||
impl/config/CryDirectKeyProvider.cpp
|
||||
impl/filesystem/CryOpenFile.cpp
|
||||
impl/filesystem/fsblobstore/utils/DirEntry.cpp
|
||||
impl/filesystem/fsblobstore/utils/DirEntryList.cpp
|
||||
|
|
|
@ -93,6 +93,8 @@ void CryConfigLoader::_checkMissingBlocksAreIntegrityViolations(CryConfigFile *c
|
|||
auto exclusiveClientId = configFile->config()->ExclusiveClientId();
|
||||
if (exclusiveClientId != none && *exclusiveClientId != myClientId) {
|
||||
throw CryfsException("File system is in single-client mode and can only be used from the client that created it.", ErrorCode::SingleClientFileSystem);
|
||||
configFile->config()->SetExclusiveClientId(none);
|
||||
configFile->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,15 +110,6 @@ either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> CryConfigLoa
|
|||
}
|
||||
}
|
||||
|
||||
boost::optional<CryConfigFile::LoadError> CryConfigLoader::changeEncryptionKey(bf::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, unique_ref<CryKeyProvider> newKeyProvider) {
|
||||
auto config = _loadConfig(filename, allowFilesystemUpgrade, allowReplacedFilesystem, CryConfigFile::Access::ReadWrite);
|
||||
if (config.is_left()) {
|
||||
return config.left();
|
||||
}
|
||||
CryConfigFile(filename, *config.right().configFile->config(), CryConfigEncryptorFactory::deriveNewKey(newKeyProvider.get()), CryConfigFile::Access::ReadWrite).save();
|
||||
return none;
|
||||
}
|
||||
|
||||
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(bf::path filename, bool allowReplacedFilesystem) {
|
||||
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine, allowReplacedFilesystem);
|
||||
auto result = CryConfigFile::create(std::move(filename), config.config, _keyProvider.get());
|
||||
|
|
|
@ -26,7 +26,6 @@ public:
|
|||
|
||||
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> loadOrCreate(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem);
|
||||
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> load(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, CryConfigFile::Access access);
|
||||
boost::optional<CryConfigFile::LoadError> changeEncryptionKey(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, cpputils::unique_ref<CryKeyProvider> newKeyProvider);
|
||||
|
||||
private:
|
||||
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> _loadConfig(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, CryConfigFile::Access access);
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#include "CryDirectKeyProvider.h"
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryDirectKeyProvider::CryDirectKeyProvider(SizedData encryptionKey) : _encryptionKey(encryptionKey) {}
|
||||
|
||||
cpputils::EncryptionKey CryDirectKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) {
|
||||
ASSERT(_encryptionKey.size == keySize, "CryDirectKeyProvider: Invalid key size requested");
|
||||
cpputils::EncryptionKey encryptionKey = cpputils::EncryptionKey::Null(_encryptionKey.size);
|
||||
memcpy(encryptionKey.data(), _encryptionKey.data, _encryptionKey.size);
|
||||
return encryptionKey;
|
||||
}
|
||||
|
||||
CryKeyProvider::KeyResult CryDirectKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
||||
throw std::logic_error("CryDirectKeyProvider can't be used for new filesystems");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
#ifndef CRYFS_CRYDIRECTKEYPROVIDER_H
|
||||
#define CRYFS_CRYDIRECTKEYPROVIDER_H
|
||||
|
||||
#include "CryKeyProvider.h"
|
||||
#include <cpp-utils/SizedData.h>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class CryDirectKeyProvider final : public CryKeyProvider {
|
||||
public:
|
||||
explicit CryDirectKeyProvider(SizedData encryptionKey);
|
||||
|
||||
cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override;
|
||||
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||
|
||||
private:
|
||||
SizedData _encryptionKey;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryDirectKeyProvider);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,26 +8,15 @@ using cpputils::Data;
|
|||
|
||||
namespace cryfs {
|
||||
|
||||
CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref<PasswordBasedKDF> kdf, SizedData* returnedHash)
|
||||
: _password(std::move(password)), _kdf(std::move(kdf)), _returnedHash(returnedHash) {}
|
||||
|
||||
void CryPresetPasswordBasedKeyProvider::saveEncryptionKey(EncryptionKey encryptionKey) {
|
||||
if (_returnedHash != nullptr) {
|
||||
_returnedHash->size = encryptionKey.binaryLength();
|
||||
_returnedHash->data = new unsigned char[_returnedHash->size];
|
||||
memcpy(_returnedHash->data, encryptionKey.data(), _returnedHash->size);
|
||||
}
|
||||
}
|
||||
CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref<PasswordBasedKDF> kdf)
|
||||
: _password(std::move(password)), _kdf(std::move(kdf)) {}
|
||||
|
||||
EncryptionKey CryPresetPasswordBasedKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const Data& kdfParameters) {
|
||||
EncryptionKey encryptionKey = _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
||||
saveEncryptionKey(encryptionKey);
|
||||
return encryptionKey;
|
||||
return _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
||||
}
|
||||
|
||||
CryPresetPasswordBasedKeyProvider::KeyResult CryPresetPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
||||
auto keyResult = _kdf->deriveNewKey(keySize, _password);
|
||||
saveEncryptionKey(keyResult.key);
|
||||
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,27 +5,19 @@
|
|||
#include "CryKeyProvider.h"
|
||||
#include <functional>
|
||||
#include <cpp-utils/crypto/kdf/PasswordBasedKDF.h>
|
||||
#include <cpp-utils/SizedData.h>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class CryPresetPasswordBasedKeyProvider final : public CryKeyProvider {
|
||||
public:
|
||||
explicit CryPresetPasswordBasedKeyProvider(
|
||||
std::string password,
|
||||
cpputils::unique_ref<cpputils::PasswordBasedKDF> kdf,
|
||||
SizedData* returnedHash
|
||||
);
|
||||
explicit CryPresetPasswordBasedKeyProvider(std::string password, cpputils::unique_ref<cpputils::PasswordBasedKDF> kdf);
|
||||
|
||||
cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override;
|
||||
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||
|
||||
private:
|
||||
void saveEncryptionKey(cpputils::EncryptionKey encryptionKey);
|
||||
|
||||
std::string _password;
|
||||
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
|
||||
SizedData* _returnedHash;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryPresetPasswordBasedKeyProvider);
|
||||
};
|
||||
|
|
|
@ -58,8 +58,16 @@ public:
|
|||
// Remove the following line, if you don't want to output each fuse operation on the console
|
||||
//#define FSPP_LOG 1
|
||||
|
||||
Fuse::Fuse(std::function<shared_ptr<Filesystem> ()> init)
|
||||
:_init(std::move(init)), _fs(make_shared<InvalidFilesystem>()), _running(false) {
|
||||
Fuse::~Fuse() {
|
||||
for(char *arg : _argv) {
|
||||
delete[] arg;
|
||||
arg = nullptr;
|
||||
}
|
||||
_argv.clear();
|
||||
}
|
||||
|
||||
Fuse::Fuse(std::function<shared_ptr<Filesystem> ()> init, std::string fstype, boost::optional<std::string> fsname)
|
||||
:_init(std::move(init)), _fs(make_shared<InvalidFilesystem>()), _running(false), _fstype(std::move(fstype)), _fsname(std::move(fsname)) {
|
||||
ASSERT(static_cast<bool>(_init), "Invalid init given");
|
||||
}
|
||||
|
||||
|
@ -190,14 +198,14 @@ int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
|
|||
int Fuse::mkdir(const bf::path &path, ::mode_t mode) {
|
||||
ThreadNameForDebugging _threadName("mkdir");
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG, "mkdir({}, {})", path.string(), mode);
|
||||
LOG(DEBUG, "mkdir({}, {})", path, mode);
|
||||
#endif
|
||||
try {
|
||||
ASSERT(is_valid_fspp_path(path), "has to be an absolute path");
|
||||
// DokanY seems to call mkdir("/"). Ignore that
|
||||
if ("/" == path) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG, "mkdir({}, {}): ignored", path.string(), mode);
|
||||
LOG(DEBUG, "mkdir({}, {}): ignored", path, mode);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -344,7 +352,7 @@ int Fuse::rename(const bf::path &from, const bf::path &to) {
|
|||
//TODO
|
||||
int Fuse::link(const bf::path &from, const bf::path &to) {
|
||||
ThreadNameForDebugging _threadName("link");
|
||||
LOG(WARN, "NOT IMPLEMENTED: link({}, {})", from.string(), to.string());
|
||||
LOG(WARN, "NOT IMPLEMENTED: link({}, {})", from, to);
|
||||
//auto real_from = _impl->RootDir() / from;
|
||||
//auto real_to = _impl->RootDir() / to;
|
||||
//int retstat = ::link(real_from.string().c_str(), real_to.string().c_str());
|
||||
|
|
|
@ -25,7 +25,8 @@ class Filesystem;
|
|||
|
||||
class Fuse final {
|
||||
public:
|
||||
explicit Fuse(std::function<std::shared_ptr<Filesystem> ()> init);
|
||||
explicit Fuse(std::function<std::shared_ptr<Filesystem> ()> init, std::string fstype, boost::optional<std::string> fsname);
|
||||
~Fuse();
|
||||
|
||||
bool running() const;
|
||||
void stop();
|
||||
|
@ -70,7 +71,10 @@ private:
|
|||
|
||||
std::function<std::shared_ptr<Filesystem> ()> _init;
|
||||
std::shared_ptr<Filesystem> _fs;
|
||||
std::vector<char*> _argv;
|
||||
std::atomic<bool> _running;
|
||||
std::string _fstype;
|
||||
boost::optional<std::string> _fsname;
|
||||
boost::optional<Context> _context;
|
||||
::uid_t uid;
|
||||
::gid_t gid;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
project (gitversion)
|
||||
|
||||
include(gitversion.cmake)
|
||||
get_git_version(GIT_VERSION)
|
||||
|
||||
set(SOURCES
|
||||
gitversion.cpp
|
||||
versionstring.cpp
|
||||
|
@ -9,9 +12,6 @@ set(SOURCES
|
|||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC boost)
|
||||
if (NOT DEFINED GIT_VERSION)
|
||||
message(FATAL_ERROR "GIT_VERSION not defined")
|
||||
endif()
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE GIT_VERSION_STRING="${GIT_VERSION}")
|
||||
target_add_boost(${PROJECT_NAME})
|
||||
target_enable_style_warnings(${PROJECT_NAME})
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
include versioneer.py
|
||||
include _version_source.py
|
||||
include _version.py
|
|
@ -0,0 +1,487 @@
|
|||
|
||||
# This file helps to compute a version number in source trees obtained from
|
||||
# git-archive tarball (such as those provided by githubs download-from-tag
|
||||
# feature). Distribution tarballs (built by setup.py sdist) and build
|
||||
# directories (produced by setup.py build) will contain a much shorter file
|
||||
# that just contains the computed version number.
|
||||
|
||||
# This file is released into the public domain. Generated by
|
||||
# versioneer-0.15+dev (https://github.com/warner/python-versioneer)
|
||||
|
||||
"""Git implementation of _version.py."""
|
||||
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def get_keywords():
|
||||
"""Get the keywords needed to look up the version information."""
|
||||
# these strings will be replaced by git during git-archive.
|
||||
# setup.py/versioneer.py will grep for the variable names, so they must
|
||||
# each be defined on a line of their own. _version.py will just call
|
||||
# get_keywords().
|
||||
git_refnames = "$Format:%d$"
|
||||
git_full = "$Format:%H$"
|
||||
keywords = {"refnames": git_refnames, "full": git_full}
|
||||
return keywords
|
||||
|
||||
|
||||
class VersioneerConfig:
|
||||
|
||||
"""Container for Versioneer configuration parameters."""
|
||||
|
||||
|
||||
def get_config():
|
||||
"""Create, populate and return the VersioneerConfig() object."""
|
||||
# these strings are filled in when 'setup.py versioneer' creates
|
||||
# _version.py
|
||||
cfg = VersioneerConfig()
|
||||
cfg.VCS = "git"
|
||||
cfg.style = "pep440"
|
||||
cfg.tag_prefix = ""
|
||||
cfg.parentdir_prefix = "cryfs-"
|
||||
cfg.versionfile_source = "_version.py"
|
||||
cfg.verbose = False
|
||||
return cfg
|
||||
|
||||
|
||||
class NotThisMethod(Exception):
|
||||
|
||||
"""Exception raised if a method is not valid for the current scenario."""
|
||||
|
||||
|
||||
LONG_VERSION_PY = {}
|
||||
HANDLERS = {}
|
||||
|
||||
|
||||
def register_vcs_handler(vcs, method): # decorator
|
||||
"""Decorator to mark a method as the handler for a particular VCS."""
|
||||
def decorate(f):
|
||||
"""Store f in HANDLERS[vcs][method]."""
|
||||
if vcs not in HANDLERS:
|
||||
HANDLERS[vcs] = {}
|
||||
HANDLERS[vcs][method] = f
|
||||
return f
|
||||
return decorate
|
||||
|
||||
|
||||
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
|
||||
"""Call the given command(s)."""
|
||||
assert isinstance(commands, list)
|
||||
p = None
|
||||
for c in commands:
|
||||
try:
|
||||
dispcmd = str([c] + args)
|
||||
# remember shell=False, so use git.cmd on windows, not just git
|
||||
p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
|
||||
stderr=(subprocess.PIPE if hide_stderr
|
||||
else None))
|
||||
break
|
||||
except EnvironmentError:
|
||||
e = sys.exc_info()[1]
|
||||
if e.errno == errno.ENOENT:
|
||||
continue
|
||||
if verbose:
|
||||
print("unable to run %s" % dispcmd)
|
||||
print(e)
|
||||
return None
|
||||
else:
|
||||
if verbose:
|
||||
print("unable to find command, tried %s" % (commands,))
|
||||
return None
|
||||
stdout = p.communicate()[0].strip()
|
||||
if sys.version_info[0] >= 3:
|
||||
stdout = stdout.decode()
|
||||
if p.returncode != 0:
|
||||
if verbose:
|
||||
print("unable to run %s (error)" % dispcmd)
|
||||
return None
|
||||
return stdout
|
||||
|
||||
|
||||
def versions_from_parentdir(parentdir_prefix, root, verbose):
|
||||
"""Try to determine the version from the parent directory name.
|
||||
|
||||
Source tarballs conventionally unpack into a directory that includes
|
||||
both the project name and a version string.
|
||||
"""
|
||||
# -- (MESSMER) CHANGED FOLLOWING LINE TO LOOK IN ../.. instead of . --
|
||||
dirname = os.path.basename(os.path.abspath(os.path.join(os.path.join(root, '..'), '..')))
|
||||
if not dirname.startswith(parentdir_prefix):
|
||||
if verbose:
|
||||
print("guessing rootdir is '%s', but '%s' doesn't start with "
|
||||
"prefix '%s'" % (root, dirname, parentdir_prefix))
|
||||
raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
|
||||
return {"version": dirname[len(parentdir_prefix):],
|
||||
"full-revisionid": None,
|
||||
"dirty": False, "error": None}
|
||||
|
||||
|
||||
@register_vcs_handler("git", "get_keywords")
|
||||
def git_get_keywords(versionfile_abs):
|
||||
"""Extract version information from the given file."""
|
||||
# the code embedded in _version.py can just fetch the value of these
|
||||
# keywords. When used from setup.py, we don't want to import _version.py,
|
||||
# so we do it with a regexp instead. This function is not used from
|
||||
# _version.py.
|
||||
keywords = {}
|
||||
try:
|
||||
f = open(versionfile_abs, "r")
|
||||
for line in f.readlines():
|
||||
if line.strip().startswith("git_refnames ="):
|
||||
mo = re.search(r'=\s*"(.*)"', line)
|
||||
if mo:
|
||||
keywords["refnames"] = mo.group(1)
|
||||
if line.strip().startswith("git_full ="):
|
||||
mo = re.search(r'=\s*"(.*)"', line)
|
||||
if mo:
|
||||
keywords["full"] = mo.group(1)
|
||||
f.close()
|
||||
except EnvironmentError:
|
||||
pass
|
||||
return keywords
|
||||
|
||||
|
||||
@register_vcs_handler("git", "keywords")
|
||||
def git_versions_from_keywords(keywords, tag_prefix, verbose):
|
||||
"""Get version information from git keywords."""
|
||||
if not keywords:
|
||||
raise NotThisMethod("no keywords at all, weird")
|
||||
refnames = keywords["refnames"].strip()
|
||||
if refnames.startswith("$Format"):
|
||||
if verbose:
|
||||
print("keywords are unexpanded, not using")
|
||||
raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
|
||||
refs = set([r.strip() for r in refnames.strip("()").split(",")])
|
||||
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
|
||||
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
|
||||
TAG = "tag: "
|
||||
tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
|
||||
if not tags:
|
||||
# Either we're using git < 1.8.3, or there really are no tags. We use
|
||||
# a heuristic: assume all version tags have a digit. The old git %d
|
||||
# expansion behaves like git log --decorate=short and strips out the
|
||||
# refs/heads/ and refs/tags/ prefixes that would let us distinguish
|
||||
# between branches and tags. By ignoring refnames without digits, we
|
||||
# filter out many common branch names like "release" and
|
||||
# "stabilization", as well as "HEAD" and "master".
|
||||
tags = set([r for r in refs if re.search(r'\d', r)])
|
||||
if verbose:
|
||||
print("discarding '%s', no digits" % ",".join(refs-tags))
|
||||
if verbose:
|
||||
print("likely tags: %s" % ",".join(sorted(tags)))
|
||||
for ref in sorted(tags):
|
||||
# sorting will prefer e.g. "2.0" over "2.0rc1"
|
||||
if ref.startswith(tag_prefix):
|
||||
r = ref[len(tag_prefix):]
|
||||
if verbose:
|
||||
print("picking %s" % r)
|
||||
return {"version": r,
|
||||
"full-revisionid": keywords["full"].strip(),
|
||||
"dirty": False, "error": None
|
||||
}
|
||||
# no suitable tags, so version is "0+unknown", but full hex is still there
|
||||
if verbose:
|
||||
print("no suitable tags, using unknown + full revision id")
|
||||
return {"version": "0+unknown",
|
||||
"full-revisionid": keywords["full"].strip(),
|
||||
"dirty": False, "error": "no suitable tags"}
|
||||
|
||||
|
||||
@register_vcs_handler("git", "pieces_from_vcs")
|
||||
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
|
||||
"""Get version from 'git describe' in the root of the source tree.
|
||||
|
||||
This only gets called if the git-archive 'subst' keywords were *not*
|
||||
expanded, and _version.py hasn't already been rewritten with a short
|
||||
version string, meaning we're inside a checked out source tree.
|
||||
"""
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %s" % root)
|
||||
raise NotThisMethod("no .git directory")
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
# if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
|
||||
# if there isn't one, this yields HEX[-dirty] (no NUM)
|
||||
describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
|
||||
"--always", "--long",
|
||||
"--match", "%s*" % tag_prefix],
|
||||
cwd=root)
|
||||
# --long was added in git-1.5.5
|
||||
if describe_out is None:
|
||||
raise NotThisMethod("'git describe' failed")
|
||||
describe_out = describe_out.strip()
|
||||
full_out = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
|
||||
if full_out is None:
|
||||
raise NotThisMethod("'git rev-parse' failed")
|
||||
full_out = full_out.strip()
|
||||
|
||||
pieces = {}
|
||||
pieces["long"] = full_out
|
||||
pieces["short"] = full_out[:7] # maybe improved later
|
||||
pieces["error"] = None
|
||||
|
||||
# parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
|
||||
# TAG might have hyphens.
|
||||
git_describe = describe_out
|
||||
|
||||
# look for -dirty suffix
|
||||
dirty = git_describe.endswith("-dirty")
|
||||
pieces["dirty"] = dirty
|
||||
if dirty:
|
||||
git_describe = git_describe[:git_describe.rindex("-dirty")]
|
||||
|
||||
# now we have TAG-NUM-gHEX or HEX
|
||||
|
||||
if "-" in git_describe:
|
||||
# TAG-NUM-gHEX
|
||||
mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
|
||||
if not mo:
|
||||
# unparseable. Maybe git-describe is misbehaving?
|
||||
pieces["error"] = ("unable to parse git-describe output: '%s'"
|
||||
% describe_out)
|
||||
return pieces
|
||||
|
||||
# tag
|
||||
full_tag = mo.group(1)
|
||||
if not full_tag.startswith(tag_prefix):
|
||||
if verbose:
|
||||
fmt = "tag '%s' doesn't start with prefix '%s'"
|
||||
print(fmt % (full_tag, tag_prefix))
|
||||
pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
|
||||
% (full_tag, tag_prefix))
|
||||
return pieces
|
||||
pieces["closest-tag"] = full_tag[len(tag_prefix):]
|
||||
|
||||
# distance: number of commits since tag
|
||||
pieces["distance"] = int(mo.group(2))
|
||||
|
||||
# commit: short hex revision ID
|
||||
pieces["short"] = mo.group(3)
|
||||
|
||||
else:
|
||||
# HEX: no tags
|
||||
pieces["closest-tag"] = None
|
||||
count_out = run_command(GITS, ["rev-list", "HEAD", "--count"],
|
||||
cwd=root)
|
||||
pieces["distance"] = int(count_out) # total number of commits
|
||||
|
||||
return pieces
|
||||
|
||||
|
||||
def plus_or_dot(pieces):
|
||||
"""Return a + if we don't already have one, else return a ."""
|
||||
if "+" in pieces.get("closest-tag", ""):
|
||||
return "."
|
||||
return "+"
|
||||
|
||||
|
||||
def render_pep440(pieces):
|
||||
"""Build up version string, with post-release "local version identifier".
|
||||
|
||||
Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
|
||||
get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
|
||||
|
||||
Exceptions:
|
||||
1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
|
||||
"""
|
||||
if pieces["closest-tag"]:
|
||||
rendered = pieces["closest-tag"]
|
||||
if pieces["distance"] or pieces["dirty"]:
|
||||
rendered += plus_or_dot(pieces)
|
||||
rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
|
||||
if pieces["dirty"]:
|
||||
rendered += ".dirty"
|
||||
else:
|
||||
# exception #1
|
||||
rendered = "0+untagged.%d.g%s" % (pieces["distance"],
|
||||
pieces["short"])
|
||||
if pieces["dirty"]:
|
||||
rendered += ".dirty"
|
||||
return rendered
|
||||
|
||||
|
||||
def render_pep440_pre(pieces):
|
||||
"""TAG[.post.devDISTANCE] -- No -dirty.
|
||||
|
||||
Exceptions:
|
||||
1: no tags. 0.post.devDISTANCE
|
||||
"""
|
||||
if pieces["closest-tag"]:
|
||||
rendered = pieces["closest-tag"]
|
||||
if pieces["distance"]:
|
||||
rendered += ".post.dev%d" % pieces["distance"]
|
||||
else:
|
||||
# exception #1
|
||||
rendered = "0.post.dev%d" % pieces["distance"]
|
||||
return rendered
|
||||
|
||||
|
||||
def render_pep440_post(pieces):
|
||||
"""TAG[.postDISTANCE[.dev0]+gHEX] .
|
||||
|
||||
The ".dev0" means dirty. Note that .dev0 sorts backwards
|
||||
(a dirty tree will appear "older" than the corresponding clean one),
|
||||
but you shouldn't be releasing software with -dirty anyways.
|
||||
|
||||
Exceptions:
|
||||
1: no tags. 0.postDISTANCE[.dev0]
|
||||
"""
|
||||
if pieces["closest-tag"]:
|
||||
rendered = pieces["closest-tag"]
|
||||
if pieces["distance"] or pieces["dirty"]:
|
||||
rendered += ".post%d" % pieces["distance"]
|
||||
if pieces["dirty"]:
|
||||
rendered += ".dev0"
|
||||
rendered += plus_or_dot(pieces)
|
||||
rendered += "g%s" % pieces["short"]
|
||||
else:
|
||||
# exception #1
|
||||
rendered = "0.post%d" % pieces["distance"]
|
||||
if pieces["dirty"]:
|
||||
rendered += ".dev0"
|
||||
rendered += "+g%s" % pieces["short"]
|
||||
return rendered
|
||||
|
||||
|
||||
def render_pep440_old(pieces):
|
||||
"""TAG[.postDISTANCE[.dev0]] .
|
||||
|
||||
The ".dev0" means dirty.
|
||||
|
||||
Eexceptions:
|
||||
1: no tags. 0.postDISTANCE[.dev0]
|
||||
"""
|
||||
if pieces["closest-tag"]:
|
||||
rendered = pieces["closest-tag"]
|
||||
if pieces["distance"] or pieces["dirty"]:
|
||||
rendered += ".post%d" % pieces["distance"]
|
||||
if pieces["dirty"]:
|
||||
rendered += ".dev0"
|
||||
else:
|
||||
# exception #1
|
||||
rendered = "0.post%d" % pieces["distance"]
|
||||
if pieces["dirty"]:
|
||||
rendered += ".dev0"
|
||||
return rendered
|
||||
|
||||
|
||||
def render_git_describe(pieces):
|
||||
"""TAG[-DISTANCE-gHEX][-dirty].
|
||||
|
||||
Like 'git describe --tags --dirty --always'.
|
||||
|
||||
Exceptions:
|
||||
1: no tags. HEX[-dirty] (note: no 'g' prefix)
|
||||
"""
|
||||
if pieces["closest-tag"]:
|
||||
rendered = pieces["closest-tag"]
|
||||
if pieces["distance"]:
|
||||
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
|
||||
else:
|
||||
# exception #1
|
||||
rendered = pieces["short"]
|
||||
if pieces["dirty"]:
|
||||
rendered += "-dirty"
|
||||
return rendered
|
||||
|
||||
|
||||
def render_git_describe_long(pieces):
|
||||
"""TAG-DISTANCE-gHEX[-dirty].
|
||||
|
||||
Like 'git describe --tags --dirty --always -long'.
|
||||
The distance/hash is unconditional.
|
||||
|
||||
Exceptions:
|
||||
1: no tags. HEX[-dirty] (note: no 'g' prefix)
|
||||
"""
|
||||
if pieces["closest-tag"]:
|
||||
rendered = pieces["closest-tag"]
|
||||
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
|
||||
else:
|
||||
# exception #1
|
||||
rendered = pieces["short"]
|
||||
if pieces["dirty"]:
|
||||
rendered += "-dirty"
|
||||
return rendered
|
||||
|
||||
|
||||
def render(pieces, style):
|
||||
"""Render the given version pieces into the requested style."""
|
||||
if pieces["error"]:
|
||||
return {"version": "unknown",
|
||||
"full-revisionid": pieces.get("long"),
|
||||
"dirty": None,
|
||||
"error": pieces["error"]}
|
||||
|
||||
if not style or style == "default":
|
||||
style = "pep440" # the default
|
||||
|
||||
if style == "pep440":
|
||||
rendered = render_pep440(pieces)
|
||||
elif style == "pep440-pre":
|
||||
rendered = render_pep440_pre(pieces)
|
||||
elif style == "pep440-post":
|
||||
rendered = render_pep440_post(pieces)
|
||||
elif style == "pep440-old":
|
||||
rendered = render_pep440_old(pieces)
|
||||
elif style == "git-describe":
|
||||
rendered = render_git_describe(pieces)
|
||||
elif style == "git-describe-long":
|
||||
rendered = render_git_describe_long(pieces)
|
||||
else:
|
||||
raise ValueError("unknown style '%s'" % style)
|
||||
|
||||
return {"version": rendered, "full-revisionid": pieces["long"],
|
||||
"dirty": pieces["dirty"], "error": None}
|
||||
|
||||
|
||||
def get_versions():
|
||||
"""Get version information or return default if unable to do so."""
|
||||
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
|
||||
# __file__, we can work backwards from there to the root. Some
|
||||
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
|
||||
# case we can only use expanded keywords.
|
||||
|
||||
cfg = get_config()
|
||||
verbose = cfg.verbose
|
||||
|
||||
try:
|
||||
return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
|
||||
verbose)
|
||||
except NotThisMethod:
|
||||
pass
|
||||
|
||||
try:
|
||||
root = os.path.realpath(__file__)
|
||||
# versionfile_source is the relative path from the top of the source
|
||||
# tree (where the .git directory might live) to this file. Invert
|
||||
# this to find the root from __file__.
|
||||
for i in cfg.versionfile_source.split('/'):
|
||||
root = os.path.dirname(root)
|
||||
except NameError:
|
||||
return {"version": "0+unknown", "full-revisionid": None,
|
||||
"dirty": None,
|
||||
"error": "unable to find root of source tree"}
|
||||
|
||||
try:
|
||||
pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
|
||||
return render(pieces, cfg.style)
|
||||
except NotThisMethod:
|
||||
pass
|
||||
|
||||
try:
|
||||
if cfg.parentdir_prefix:
|
||||
return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
|
||||
except NotThisMethod:
|
||||
pass
|
||||
|
||||
return {"version": "0+unknown", "full-revisionid": None,
|
||||
"dirty": None,
|
||||
"error": "unable to compute version"}
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import versioneer
|
||||
|
||||
print(versioneer.get_version())
|
|
@ -0,0 +1,18 @@
|
|||
set(DIR_OF_GITVERSION_TOOL "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "DIR_OF_GITVERSION_TOOL")
|
||||
|
||||
function (get_git_version OUTPUT_VARIABLE)
|
||||
EXECUTE_PROCESS(COMMAND python3 ${DIR_OF_GITVERSION_TOOL}/getversion.py
|
||||
WORKING_DIRECTORY ${DIR_OF_GITVERSION_TOOL}
|
||||
OUTPUT_VARIABLE VERSION
|
||||
ERROR_VARIABLE error
|
||||
RESULT_VARIABLE result)
|
||||
STRING(STRIP "${VERSION}" STRIPPED_VERSION)
|
||||
SET(${OUTPUT_VARIABLE} "${STRIPPED_VERSION}" CACHE INTERNAL "${OUTPUT_VARIABLE}")
|
||||
MESSAGE(STATUS "Building version ${${OUTPUT_VARIABLE}}")
|
||||
IF(NOT ${result} EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR "Error running versioneer. Return code is: ${result}, error message is: ${error}")
|
||||
ENDIF()
|
||||
IF("${STRIPPED_VERSION}" STREQUAL "0+unknown")
|
||||
MESSAGE(FATAL_ERROR "Unable to find git version information. Please build directly from a git repository (i.e. after git clone).")
|
||||
ENDIF()
|
||||
endfunction(get_git_version)
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
# See the docstring in versioneer.py for instructions. Note that you must
|
||||
# re-run 'versioneer.py setup' after changing this section, and commit the
|
||||
# resulting files.
|
||||
|
||||
[versioneer]
|
||||
VCS = git
|
||||
style = pep440
|
||||
versionfile_source = _version.py
|
||||
versionfile_build = None
|
||||
tag_prefix =
|
||||
parentdir_prefix = cryfs-
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from setuptools import setup
|
||||
import versioneer
|
||||
|
||||
setup(name='git-version',
|
||||
version=versioneer.get_version(),
|
||||
cmdclass=versioneer.get_cmdclass(),
|
||||
description='Make git version information (e.g. git tag name, git commit id, ...) available to C++ source files.',
|
||||
author='Sebastian Messmer',
|
||||
author_email='messmer@cryfs.org',
|
||||
license='LGPLv3'
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,10 @@
|
|||
#include <jni.h>
|
||||
|
||||
jlong cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword,
|
||||
jbyteArray jgivenHash, jobject returnedHash, jboolean createBaseDir,
|
||||
jstring jcipher, jobject jerrorCode);
|
||||
jboolean cryfs_change_encryption_key(JNIEnv *env,
|
||||
jstring jbaseDir, jstring jlocalStateDir,
|
||||
jbyteArray jcurrentPassword, jbyteArray jgivenHash,
|
||||
jbyteArray jnewPassword, jobject jreturnedHash);
|
||||
jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword, jboolean createBaseDir, jstring jcipher);
|
||||
jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode);
|
||||
jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flags);
|
||||
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray buffer, jlong dstOffset, jlong length);
|
||||
jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray buffer, jlong srcOffset, jlong length);
|
||||
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset);
|
||||
jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong offset, jbyteArray jbuffer, jint size);
|
||||
jint cryfs_truncate(JNIEnv* env, jlong fusePtr, jstring jpath, jlong size);
|
||||
jint cryfs_unlink(JNIEnv* env, jlong fusePtr, jstring jpath);
|
||||
jint cryfs_release(jlong fusePtr, jlong fileHandle);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include <jni.h>
|
||||
#include <cryfs-cli/Cli.h>
|
||||
#include <fspp/fuse/Fuse.h>
|
||||
#include <cryfs/impl/CryfsException.h>
|
||||
#include <cryfs/impl/config/CryKeyProvider.h>
|
||||
#include <cryfs/impl/config/CryDirectKeyProvider.h>
|
||||
#include <cryfs/impl/config/CryPresetPasswordBasedKeyProvider.h>
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
using boost::none;
|
||||
using cpputils::Random;
|
||||
using cpputils::SCrypt;
|
||||
|
@ -15,21 +13,7 @@ using fspp::fuse::Fuse;
|
|||
|
||||
std::set<jlong> validFusePtrs;
|
||||
|
||||
jfieldID getValueField(JNIEnv* env, jobject object) {
|
||||
return env->GetFieldID(env->GetObjectClass(object), "value", "Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
void setReturnedPasswordHash(JNIEnv* env, jobject jreturnedHash, const SizedData& returnedHash) {
|
||||
jbyteArray jpasswordHash = env->NewByteArray(returnedHash.size);
|
||||
env->SetByteArrayRegion(jpasswordHash, 0, returnedHash.size, reinterpret_cast<const jbyte*>(returnedHash.data));
|
||||
delete[] returnedHash.data;
|
||||
env->SetObjectField(jreturnedHash, getValueField(env, jreturnedHash), jpasswordHash);
|
||||
}
|
||||
|
||||
extern "C" jlong
|
||||
cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword,
|
||||
jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir,
|
||||
jstring jcipher, jobject jerrorCode) {
|
||||
extern "C" jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword, jboolean createBaseDir, jstring jcipher) {
|
||||
const char* baseDir = env->GetStringUTFChars(jbaseDir, NULL);
|
||||
const char* localStateDir = env->GetStringUTFChars(jlocalStateDir, NULL);
|
||||
boost::optional<string> cipher = none;
|
||||
|
@ -38,44 +22,16 @@ cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpa
|
|||
cipher = boost::optional<string>(cipherName);
|
||||
env->ReleaseStringUTFChars(jcipher, cipherName);
|
||||
}
|
||||
auto &keyGenerator = Random::OSRandom();
|
||||
auto &keyGenerator = Random::OSRandom();
|
||||
ProgramOptions options = ProgramOptions(baseDir, none, localStateDir, false, false, createBaseDir, cipher, none, false, none);
|
||||
char* password = reinterpret_cast<char*>(env->GetByteArrayElements(jpassword, NULL));
|
||||
|
||||
Fuse* fuse = Cli(keyGenerator, SCrypt::DefaultSettings).initFilesystem(options, make_unique<string>(password));
|
||||
|
||||
env->ReleaseByteArrayElements(jpassword, reinterpret_cast<jbyte*>(password), 0);
|
||||
env->ReleaseStringUTFChars(jbaseDir, baseDir);
|
||||
env->ReleaseStringUTFChars(jlocalStateDir, localStateDir);
|
||||
struct SizedData returnedHash;
|
||||
struct Cli::Credentials credentials;
|
||||
credentials.returnedHash = nullptr;
|
||||
if (jpassword == NULL) {
|
||||
credentials.password = none;
|
||||
credentials.givenHash.data = reinterpret_cast<unsigned char*>(env->GetByteArrayElements(jgivenHash, NULL));
|
||||
credentials.givenHash.size = env->GetArrayLength(jgivenHash);
|
||||
} else {
|
||||
jbyte* password = env->GetByteArrayElements(jpassword, NULL);
|
||||
credentials.password = string(reinterpret_cast<const char*>(password), env->GetArrayLength(jpassword));
|
||||
env->ReleaseByteArrayElements(jpassword, password, 0);
|
||||
if (jreturnedHash != NULL) {
|
||||
credentials.returnedHash = &returnedHash;
|
||||
}
|
||||
}
|
||||
|
||||
Fuse* fuse = 0;
|
||||
try {
|
||||
fuse = Cli(keyGenerator, SCrypt::DefaultSettings).initFilesystem(options, credentials);
|
||||
} catch (const cryfs::CryfsException &e) {
|
||||
int errorCode = static_cast<int>(e.errorCode());
|
||||
if (e.what() != string()) {
|
||||
LOG(cpputils::logging::ERR, "Error {}: {}", errorCode, e.what());
|
||||
}
|
||||
jclass integerClass = env->FindClass("java/lang/Integer");
|
||||
jobject integer = env->NewObject(integerClass, env->GetMethodID(integerClass, "<init>", "(I)V"), errorCode);
|
||||
env->SetObjectField(jerrorCode, getValueField(env, jerrorCode), integer);
|
||||
}
|
||||
if (jpassword == NULL) {
|
||||
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(credentials.givenHash.data), 0);
|
||||
}
|
||||
if (credentials.returnedHash != nullptr) {
|
||||
setReturnedPasswordHash(env, jreturnedHash, returnedHash);
|
||||
}
|
||||
jlong fusePtr = reinterpret_cast<jlong>(fuse);
|
||||
if (fusePtr != 0) {
|
||||
validFusePtrs.insert(fusePtr);
|
||||
|
@ -83,55 +39,6 @@ cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpa
|
|||
return fusePtr;
|
||||
}
|
||||
|
||||
extern "C" jboolean cryfs_change_encryption_key(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDir,
|
||||
jbyteArray jcurrentPassword, jbyteArray jgivenHash,
|
||||
jbyteArray jnewPassword, jobject jreturnedHash) {
|
||||
using namespace cryfs;
|
||||
|
||||
const char* baseDir = env->GetStringUTFChars(jbaseDir, NULL);
|
||||
const char* localStateDir = env->GetStringUTFChars(jlocalStateDir, NULL);
|
||||
|
||||
struct SizedData givenHash;
|
||||
std::unique_ptr<CryKeyProvider> currentKeyProvider;
|
||||
if (jcurrentPassword == NULL) {
|
||||
givenHash.data = reinterpret_cast<unsigned char*>(env->GetByteArrayElements(jgivenHash, NULL));
|
||||
givenHash.size = env->GetArrayLength(jgivenHash);
|
||||
currentKeyProvider = std::make_unique<CryDirectKeyProvider>(givenHash);
|
||||
} else {
|
||||
jbyte* currentPassword = env->GetByteArrayElements(jcurrentPassword, NULL);
|
||||
currentKeyProvider = std::make_unique<CryPresetPasswordBasedKeyProvider>(
|
||||
string(reinterpret_cast<const char*>(currentPassword), env->GetArrayLength(jcurrentPassword)),
|
||||
cpputils::make_unique_ref<SCrypt>(SCrypt::DefaultSettings),
|
||||
nullptr
|
||||
);
|
||||
env->ReleaseByteArrayElements(jcurrentPassword, currentPassword, 0);
|
||||
}
|
||||
struct SizedData returnedHash = {nullptr, 0};
|
||||
jbyte* newPassword = env->GetByteArrayElements(jnewPassword, NULL);
|
||||
cpputils::unique_ref<CryKeyProvider> newKeyProvider = cpputils::make_unique_ref<CryPresetPasswordBasedKeyProvider>(
|
||||
string(reinterpret_cast<const char*>(newPassword), env->GetArrayLength(jnewPassword)),
|
||||
cpputils::make_unique_ref<SCrypt>(SCrypt::DefaultSettings),
|
||||
jreturnedHash == NULL ? nullptr : &returnedHash
|
||||
);
|
||||
env->ReleaseByteArrayElements(jnewPassword, newPassword, 0);
|
||||
CryConfigLoader configLoader = CryConfigLoader(
|
||||
Random::OSRandom(), std::move(*cpputils::nullcheck(std::move(currentKeyProvider))),
|
||||
LocalStateDir(localStateDir), none, none, none
|
||||
);
|
||||
env->ReleaseStringUTFChars(jlocalStateDir, localStateDir);
|
||||
|
||||
auto result = configLoader.changeEncryptionKey(boost::filesystem::path(baseDir) / "cryfs.config", false, false, std::move(newKeyProvider));
|
||||
|
||||
if (jcurrentPassword == NULL) {
|
||||
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(givenHash.data), 0);
|
||||
}
|
||||
env->ReleaseStringUTFChars(jbaseDir, baseDir);
|
||||
if (returnedHash.data != nullptr) {
|
||||
setReturnedPasswordHash(env, jreturnedHash, returnedHash);
|
||||
}
|
||||
return result == none;
|
||||
}
|
||||
|
||||
extern "C" jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode) {
|
||||
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
|
||||
const char* path = env->GetStringUTFChars(jpath, NULL);
|
||||
|
@ -162,21 +69,22 @@ extern "C" jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flag
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray jbuffer, jlong dstOffset, jlong length) {
|
||||
extern "C" jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset) {
|
||||
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
|
||||
const jsize size = env->GetArrayLength(jbuffer);
|
||||
char* buff = reinterpret_cast<char*>(env->GetByteArrayElements(jbuffer, NULL));
|
||||
|
||||
int result = fuse->read(buff+dstOffset, length, fileOffset, fileHandle);
|
||||
int result = fuse->read(buff, size, offset, fileHandle);
|
||||
|
||||
env->ReleaseByteArrayElements(jbuffer, reinterpret_cast<jbyte*>(buff), 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray jbuffer, jlong srcOffset, jlong length) {
|
||||
extern "C" jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong offset, jbyteArray jbuffer, jint size) {
|
||||
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
|
||||
char* buff = reinterpret_cast<char*>(env->GetByteArrayElements(jbuffer, NULL));
|
||||
|
||||
int result = fuse->write(buff+srcOffset, length, fileOffset, fileHandle);
|
||||
int result = fuse->write(buff, size, offset, fileHandle);
|
||||
|
||||
env->ReleaseByteArrayElements(jbuffer, reinterpret_cast<jbyte*>(buff), 0);
|
||||
return result;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c6012c576e30ff6000ddab0988d59bad849200ce
|
||||
Subproject commit 0e12fbd30cb70b668a117c0913a303acfdaae04f
|
|
@ -1146,7 +1146,7 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.1" AND USE_OPENMP)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
# If OpenMP wasn't found, try if we can find it in the default Homebrew location (Intel Macs)
|
||||
# If OpenMP wasn't found, try if we can find it in the default Homebrew location
|
||||
if((NOT OPENMP_FOUND) AND (NOT OPENMP_CXX_FOUND) AND EXISTS "/usr/local/opt/libomp/lib/libomp.dylib")
|
||||
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I/usr/local/opt/libomp/include")
|
||||
set(OpenMP_CXX_LIB_NAMES omp)
|
||||
|
@ -1154,23 +1154,9 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.1" AND USE_OPENMP)
|
|||
|
||||
find_package(OpenMP)
|
||||
if (OPENMP_FOUND OR OPENMP_CXX_FOUND)
|
||||
message(STATUS "OpenMP: Found libomp in homebrew default location for Intel Macs.")
|
||||
message(STATUS "OpenMP: Found libomp in homebrew default location.")
|
||||
else()
|
||||
message(FATAL_ERROR "OpenMP: Didn't find libomp. Tried homebrew default location for Intel Macs but also didn't find it.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If OpenMP wasn't found, try if we can find it in the default Homebrew location (Apple Silicon Macs)
|
||||
if((NOT OPENMP_FOUND) AND (NOT OPENMP_CXX_FOUND) AND EXISTS "/opt/homebrew/opt/libomp/lib/libomp.dylib")
|
||||
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I/opt/homebrew/opt/libomp/include")
|
||||
set(OpenMP_CXX_LIB_NAMES omp)
|
||||
set(OpenMP_omp_LIBRARY /opt/homebrew/opt/libomp/lib/libomp.dylib)
|
||||
|
||||
find_package(OpenMP)
|
||||
if (OPENMP_FOUND OR OPENMP_CXX_FOUND)
|
||||
message(STATUS "OpenMP: Found libomp in homebrew default location for Apple Silicon Macs.")
|
||||
else()
|
||||
message(FATAL_ERROR "OpenMP: Didn't find libomp. Tried homebrew default location for Apple Silicon Macs but also didn't find it.")
|
||||
message(FATAL_ERROR "OpenMP: Didn't find libomp. Tried homebrew default location but also didn't find it.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7e635fca68d014934b4af8a1cf874f63989352b7
|
||||
Subproject commit a26e174b367a60a51f0be83a81d6d066330cdd8f
|
Loading…
Reference in New Issue