mirror of
https://github.com/vgough/encfs.git
synced 2024-11-24 00:43:41 +01:00
Cygwin support (#499)
This commit is contained in:
commit
a220c395f4
@ -1,3 +1,5 @@
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||
|
||||
# 3.0.2 preferred, but we can often get by with 2.8.
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} LESS 3.0.2)
|
||||
@ -73,16 +75,27 @@ if (APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32 OR APPLE)
|
||||
if (CYGWIN OR WIN32 OR APPLE)
|
||||
set(DEFAULT_CASE_INSENSITIVE TRUE)
|
||||
else()
|
||||
set(DEFAULT_CASE_INSENSITIVE FALSE)
|
||||
endif()
|
||||
|
||||
if (CYGWIN)
|
||||
find_program(PKILL NAMES "pkill")
|
||||
if(NOT PKILL)
|
||||
message(FATAL_ERROR "pkill not found, please install procps-ng package.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for FUSE.
|
||||
find_package (FUSE REQUIRED)
|
||||
include_directories (SYSTEM ${FUSE_INCLUDE_DIR})
|
||||
add_definitions (-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=29)
|
||||
if (CYGWIN)
|
||||
# Cygwin build is intended to use WinFsp
|
||||
add_definitions(-DCYGFUSE)
|
||||
endif()
|
||||
|
||||
# Check for OpenSSL.
|
||||
find_package (OpenSSL REQUIRED)
|
||||
@ -92,8 +105,10 @@ find_program (POD2MAN pod2man)
|
||||
|
||||
# Check for include files and stdlib properties.
|
||||
include (CheckIncludeFileCXX)
|
||||
check_include_file_cxx (attr/xattr.h HAVE_ATTR_XATTR_H)
|
||||
check_include_file_cxx (sys/xattr.h HAVE_SYS_XATTR_H)
|
||||
if (NOT CYGWIN)
|
||||
check_include_file_cxx (attr/xattr.h HAVE_ATTR_XATTR_H)
|
||||
check_include_file_cxx (sys/xattr.h HAVE_SYS_XATTR_H)
|
||||
endif()
|
||||
|
||||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE LANGUAGE CXX)
|
||||
|
@ -81,7 +81,10 @@ How about a nice email instead?
|
||||
|
||||
## Windows
|
||||
|
||||
A Windows port exists and is maintained by JetWhiz in the GitHub
|
||||
EncFS works on Cygwin, see [the wiki](https://github.com/vgough/encfs/wiki)
|
||||
for additional info.
|
||||
|
||||
A Windows port also exists and is maintained by JetWhiz in the GitHub
|
||||
[jetwhiz/encfs4win](https://github.com/jetwhiz/encfs4win) repository.
|
||||
|
||||
## FAQ
|
||||
|
@ -171,6 +171,15 @@ void EncFS_Context::eraseNode(const char *path,
|
||||
Lock lock(contextMutex);
|
||||
|
||||
auto it = openFiles.find(std::string(path));
|
||||
#ifdef __CYGWIN__
|
||||
// When renaming a file, Windows first opens it, renames it and then closes it
|
||||
// Filenode may have then been renamed too
|
||||
if (it == openFiles.end()) {
|
||||
RLOG(WARNING) << "Filenode to erase not found, file has certainly be renamed: "
|
||||
<< path;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
rAssert(it != openFiles.end());
|
||||
auto &list = it->second;
|
||||
|
||||
|
@ -599,11 +599,26 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
|
||||
if (renameOp) {
|
||||
renameOp->undo();
|
||||
}
|
||||
} else if (preserve_mtime) {
|
||||
struct utimbuf ut;
|
||||
ut.actime = st.st_atime;
|
||||
ut.modtime = st.st_mtime;
|
||||
::utime(toCName.c_str(), &ut);
|
||||
}
|
||||
else {
|
||||
#ifdef __CYGWIN__
|
||||
// When renaming a file, Windows first opens it, renames it and then closes it
|
||||
// We then must decrease the target openFiles count
|
||||
// We could recreate the source so that close will not (silently) fails,
|
||||
// however it will update modification time of the file, so break what we do below.
|
||||
// Let's simply warn in eraseNode().
|
||||
if (!isDirectory(toCName.c_str())) {
|
||||
std::shared_ptr<FileNode> toNode = findOrCreate(toPlaintext);
|
||||
ctx->eraseNode(toPlaintext, toNode);
|
||||
//ctx->putNode(fromPlaintext, toNode);
|
||||
}
|
||||
#endif
|
||||
if (preserve_mtime) {
|
||||
struct utimbuf ut;
|
||||
ut.actime = st.st_atime;
|
||||
ut.modtime = st.st_mtime;
|
||||
::utime(toCName.c_str(), &ut);
|
||||
}
|
||||
}
|
||||
} catch (encfs::Error &err) {
|
||||
// exception from renameNode, just show the error and continue..
|
||||
@ -739,7 +754,9 @@ int DirNode::unlink(const char *plaintextName) {
|
||||
|
||||
Lock _lock(mutex);
|
||||
|
||||
int res = 0;
|
||||
// Windows does not allow deleting opened files, so no need to check
|
||||
// There is this "issue" however : https://github.com/billziss-gh/winfsp/issues/157
|
||||
#ifndef __CYGWIN__
|
||||
if ((ctx != nullptr) && ctx->lookupNode(plaintextName)) {
|
||||
// If FUSE is running with "hard_remove" option where it doesn't
|
||||
// hide open files for us, then we can't allow an unlink of an open
|
||||
@ -747,14 +764,16 @@ int DirNode::unlink(const char *plaintextName) {
|
||||
RLOG(WARNING) << "Refusing to unlink open file: " << cyName
|
||||
<< ", hard_remove option "
|
||||
"is probably in effect";
|
||||
res = -EBUSY;
|
||||
} else {
|
||||
string fullName = rootDir + cyName;
|
||||
res = ::unlink(fullName.c_str());
|
||||
if (res == -1) {
|
||||
res = -errno;
|
||||
VLOG(1) << "unlink error: " << strerror(-res);
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
int res = 0;
|
||||
string fullName = rootDir + cyName;
|
||||
res = ::unlink(fullName.c_str());
|
||||
if (res == -1) {
|
||||
res = -errno;
|
||||
VLOG(1) << "unlink error: " << strerror(-res);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -6,6 +6,13 @@
|
||||
#include "easylogging++.h"
|
||||
#include <stdexcept>
|
||||
|
||||
// Cygwin / WinFsp does not support EBADMSG yet
|
||||
// https://github.com/billziss-gh/winfsp/issues/156
|
||||
#ifdef __CYGWIN__
|
||||
#undef EBADMSG
|
||||
#define EBADMSG EINVAL
|
||||
#endif
|
||||
|
||||
namespace encfs {
|
||||
|
||||
class Error : public std::runtime_error {
|
||||
|
@ -1089,7 +1089,7 @@ RootPtr createV6Config(EncFS_Context *ctx,
|
||||
alg = findCipherAlgorithm("AES", keySize);
|
||||
|
||||
// If case-insensitive system, opt for Block32 filename encoding
|
||||
#if defined(__APPLE__) || defined(WIN32)
|
||||
#if defined(DEFAULT_CASE_INSENSITIVE)
|
||||
nameIOIface = BlockNameIO::CurrentInterface(true);
|
||||
#else
|
||||
nameIOIface = BlockNameIO::CurrentInterface();
|
||||
@ -1739,6 +1739,14 @@ void unmountFS(const char *mountPoint) {
|
||||
// fuse_unmount does not work on Mac OS, see #428
|
||||
unmount(mountPoint, MNT_FORCE);
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
if(fork() == 0)
|
||||
{
|
||||
execl("/usr/bin/pkill", "/usr/bin/pkill", "-f", string("(^|/)encfs .*/.* ").append(mountPoint).append("?( |$)").c_str(), (char *)0);
|
||||
}
|
||||
int status;
|
||||
wait(&status);
|
||||
#endif
|
||||
}
|
||||
|
||||
int remountFS(EncFS_Context *ctx) {
|
||||
|
@ -72,6 +72,7 @@ enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };
|
||||
struct EncFS_Opts {
|
||||
std::string rootDir;
|
||||
std::string mountPoint; // where to make filesystem visible
|
||||
std::string cygDrive; // Cygwin mount drive
|
||||
bool createIfNotFound; // create filesystem if not found
|
||||
bool idleTracking; // turn on idle monitoring of filesystem
|
||||
bool mountOnDemand; // mounting on-demand
|
||||
|
@ -167,6 +167,13 @@ static int withFileNode(const char *opName, const char *path,
|
||||
if (fi != nullptr && fi->fh != 0) {
|
||||
auto node = ctx->lookupFuseFh(fi->fh);
|
||||
if (node == nullptr) {
|
||||
#ifdef __CYGWIN__
|
||||
if (strcmp(opName, "flush") == 0) {
|
||||
RLOG(WARNING) << "Filenode to flush not found, file has certainly be renamed: "
|
||||
<< path;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
auto msg = "fh=" + std::to_string(fi->fh) + " not found in fuseFhMap";
|
||||
throw Error(msg.c_str());
|
||||
}
|
||||
|
@ -649,6 +649,8 @@ Support, bug reports... : B<https://github.com/vgough/encfs>.
|
||||
|
||||
Mailing list : none.
|
||||
|
||||
Cygwin : B<https://github.com/vgough/encfs/wiki>.
|
||||
|
||||
Windows port : B<https://github.com/jetwhiz/encfs4win>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
@ -380,6 +380,11 @@ static bool processArgs(int argc, char *argv[],
|
||||
/* Disable kernel dentry cache
|
||||
* Fallout unknown, disabling for safety */
|
||||
PUSHARG("-oentry_timeout=0");
|
||||
#ifdef __CYGWIN__
|
||||
// Should be enforced due to attr_timeout=0, but does not seem to work correctly
|
||||
// https://github.com/billziss-gh/winfsp/issues/155
|
||||
PUSHARG("-oFileInfoTimeout=0");
|
||||
#endif
|
||||
break;
|
||||
case 'm':
|
||||
out->opts->mountOnDemand = true;
|
||||
@ -542,18 +547,38 @@ static bool processArgs(int argc, char *argv[],
|
||||
if (!isDirectory(out->opts->rootDir.c_str()) &&
|
||||
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(),
|
||||
0700)) {
|
||||
cerr << _("Unable to locate root directory, aborting.");
|
||||
cerr << _("Unable to locate root directory, aborting.") << endl;
|
||||
return false;
|
||||
}
|
||||
#ifdef __CYGWIN__
|
||||
if (isDirectory(out->opts->mountPoint.c_str())) {
|
||||
cerr << _("Mount point must not exist before mouting, aborting.") << endl;
|
||||
return false;
|
||||
}
|
||||
if ((strncmp(out->opts->mountPoint.c_str(), "/cygdrive/", 10) != 0) ||
|
||||
(out->opts->mountPoint.length() != 12)) {
|
||||
cerr << _("A drive is prefered for mouting, ")
|
||||
<< _("so a path like /cygdrive/x should rather be used. ")
|
||||
<< _("Mounting anyway.") << endl;
|
||||
}
|
||||
#else
|
||||
if (!isDirectory(out->opts->mountPoint.c_str()) &&
|
||||
!userAllowMkdir(out->opts->annotate ? 2 : 0,
|
||||
out->opts->mountPoint.c_str(), 0700)) {
|
||||
cerr << _("Unable to locate mount point, aborting.");
|
||||
cerr << _("Unable to locate mount point, aborting.") << endl;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fill in mount path for fuse
|
||||
out->fuseArgv[1] = out->opts->mountPoint.c_str();
|
||||
#ifdef __CYGWIN__
|
||||
if ((strncmp(out->opts->mountPoint.c_str(), "/cygdrive/", 10) == 0) &&
|
||||
(out->opts->mountPoint.length() == 12)) {
|
||||
out->opts->cygDrive = out->opts->mountPoint.substr(10,1).append(":");
|
||||
out->fuseArgv[1] = out->opts->cygDrive.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -107,6 +107,10 @@ sub newWorkingDir
|
||||
|
||||
our $raw = "$workingDir/raw";
|
||||
our $crypt = "$workingDir/crypt";
|
||||
if ($^O eq "cygwin")
|
||||
{
|
||||
$crypt = "/cygdrive/x";
|
||||
}
|
||||
}
|
||||
|
||||
# Test Corruption
|
||||
@ -124,7 +128,8 @@ sub corruption
|
||||
ok( open(IN, "< $crypt/corrupt"), "open corrupted file");
|
||||
my $content;
|
||||
$result = read(IN, $content, 20);
|
||||
ok($!{EBADMSG} && (! defined $result), "corrupted file with MAC returns read error: $!");
|
||||
# Cygwin returns EINVAL for now
|
||||
ok(($!{EBADMSG} || $!{EINVAL}) && (! defined $result), "corrupted file with MAC returns read error: $!");
|
||||
}
|
||||
|
||||
# Test internal modification
|
||||
@ -363,7 +368,10 @@ sub mount
|
||||
|
||||
# When these fail, the rest of the tests makes no sense
|
||||
mkdir($raw) || BAIL_OUT("Could not create $raw: $!");
|
||||
mkdir($crypt) || BAIL_OUT("Could not create $crypt: $!");
|
||||
if ($^O ne "cygwin")
|
||||
{
|
||||
mkdir($crypt) || BAIL_OUT("Could not create $crypt: $!");
|
||||
}
|
||||
|
||||
delete $ENV{"ENCFS6_CONFIG"};
|
||||
remount($args);
|
||||
@ -425,8 +433,15 @@ sub create_unmount_remount
|
||||
{
|
||||
my $crypt = "$workingDir/create_remount.crypt";
|
||||
my $mnt = "$workingDir/create_remount.mnt";
|
||||
if ($^O eq "cygwin")
|
||||
{
|
||||
$mnt = "/cygdrive/y";
|
||||
}
|
||||
mkdir($crypt) || BAIL_OUT($!);
|
||||
mkdir($mnt) || BAIL_OUT($!);
|
||||
if ($^O ne "cygwin")
|
||||
{
|
||||
mkdir($mnt) || BAIL_OUT($!);
|
||||
}
|
||||
|
||||
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
||||
ok( $? == 0, "encfs command returns 0") || return;
|
||||
@ -472,8 +487,15 @@ sub checkWriteError
|
||||
else {
|
||||
my $crypt = "$workingDir/checkWriteError.crypt";
|
||||
my $mnt = "$workingDir/checkWriteError.mnt";
|
||||
if ($^O eq "cygwin")
|
||||
{
|
||||
$mnt = "/cygdrive/z";
|
||||
}
|
||||
mkdir($crypt) || BAIL_OUT($!);
|
||||
mkdir($mnt) || BAIL_OUT($!);
|
||||
if ($^O ne "cygwin")
|
||||
{
|
||||
mkdir($mnt) || BAIL_OUT($!);
|
||||
}
|
||||
system("$sudo_cmd mount -t tmpfs -o size=1m tmpfs $crypt");
|
||||
ok( $? == 0, "mount command returns 0") || return;
|
||||
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
||||
|
@ -49,9 +49,23 @@ sub newWorkingDir
|
||||
our $plain = "$workingDir/plain";
|
||||
mkdir($plain);
|
||||
our $ciphertext = "$workingDir/ciphertext";
|
||||
mkdir($ciphertext);
|
||||
if ($^O ne "cygwin")
|
||||
{
|
||||
mkdir($ciphertext);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ciphertext = "/cygdrive/x";
|
||||
}
|
||||
our $decrypted = "$workingDir/decrypted";
|
||||
mkdir($decrypted);
|
||||
if ($^O ne "cygwin")
|
||||
{
|
||||
mkdir($decrypted);
|
||||
}
|
||||
else
|
||||
{
|
||||
$decrypted = "/cygdrive/y";
|
||||
}
|
||||
}
|
||||
|
||||
# Helper function
|
||||
@ -231,7 +245,14 @@ encfsctl_cat_test();
|
||||
symlink_test("/"); # absolute
|
||||
symlink_test("foo"); # relative
|
||||
symlink_test("/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/15/17/18"); # long
|
||||
symlink_test("!§\$%&/()\\<>#+="); # special characters
|
||||
if ($^O ne "cygwin")
|
||||
{
|
||||
symlink_test("!§\$%&/()\\<>#+="); # special characters
|
||||
}
|
||||
else
|
||||
{
|
||||
symlink_test("!§\$%&/()//<>#+="); # special characters but without \ which is not Windows compliant
|
||||
} # Absolute symlinks may failed on Windows : https://github.com/billziss-gh/winfsp/issues/153
|
||||
symlink_test("$plain/foo");
|
||||
writesDenied();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user