mirror of
https://github.com/vgough/encfs.git
synced 2025-06-24 14:02:13 +02: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.
|
# 3.0.2 preferred, but we can often get by with 2.8.
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} LESS 3.0.2)
|
if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} LESS 3.0.2)
|
||||||
@ -73,16 +75,27 @@ if (APPLE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32 OR APPLE)
|
if (CYGWIN OR WIN32 OR APPLE)
|
||||||
set(DEFAULT_CASE_INSENSITIVE TRUE)
|
set(DEFAULT_CASE_INSENSITIVE TRUE)
|
||||||
else()
|
else()
|
||||||
set(DEFAULT_CASE_INSENSITIVE FALSE)
|
set(DEFAULT_CASE_INSENSITIVE FALSE)
|
||||||
endif()
|
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.
|
# Check for FUSE.
|
||||||
find_package (FUSE REQUIRED)
|
find_package (FUSE REQUIRED)
|
||||||
include_directories (SYSTEM ${FUSE_INCLUDE_DIR})
|
include_directories (SYSTEM ${FUSE_INCLUDE_DIR})
|
||||||
add_definitions (-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=29)
|
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.
|
# Check for OpenSSL.
|
||||||
find_package (OpenSSL REQUIRED)
|
find_package (OpenSSL REQUIRED)
|
||||||
@ -92,8 +105,10 @@ find_program (POD2MAN pod2man)
|
|||||||
|
|
||||||
# Check for include files and stdlib properties.
|
# Check for include files and stdlib properties.
|
||||||
include (CheckIncludeFileCXX)
|
include (CheckIncludeFileCXX)
|
||||||
check_include_file_cxx (attr/xattr.h HAVE_ATTR_XATTR_H)
|
if (NOT CYGWIN)
|
||||||
check_include_file_cxx (sys/xattr.h HAVE_SYS_XATTR_H)
|
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)
|
include(CheckStructHasMember)
|
||||||
check_struct_has_member("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE LANGUAGE CXX)
|
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
|
## 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.
|
[jetwhiz/encfs4win](https://github.com/jetwhiz/encfs4win) repository.
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
@ -171,6 +171,15 @@ void EncFS_Context::eraseNode(const char *path,
|
|||||||
Lock lock(contextMutex);
|
Lock lock(contextMutex);
|
||||||
|
|
||||||
auto it = openFiles.find(std::string(path));
|
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());
|
rAssert(it != openFiles.end());
|
||||||
auto &list = it->second;
|
auto &list = it->second;
|
||||||
|
|
||||||
|
@ -599,11 +599,26 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
|
|||||||
if (renameOp) {
|
if (renameOp) {
|
||||||
renameOp->undo();
|
renameOp->undo();
|
||||||
}
|
}
|
||||||
} else if (preserve_mtime) {
|
}
|
||||||
struct utimbuf ut;
|
else {
|
||||||
ut.actime = st.st_atime;
|
#ifdef __CYGWIN__
|
||||||
ut.modtime = st.st_mtime;
|
// When renaming a file, Windows first opens it, renames it and then closes it
|
||||||
::utime(toCName.c_str(), &ut);
|
// 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) {
|
} catch (encfs::Error &err) {
|
||||||
// exception from renameNode, just show the error and continue..
|
// exception from renameNode, just show the error and continue..
|
||||||
@ -739,7 +754,9 @@ int DirNode::unlink(const char *plaintextName) {
|
|||||||
|
|
||||||
Lock _lock(mutex);
|
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 ((ctx != nullptr) && ctx->lookupNode(plaintextName)) {
|
||||||
// If FUSE is running with "hard_remove" option where it doesn't
|
// 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
|
// 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
|
RLOG(WARNING) << "Refusing to unlink open file: " << cyName
|
||||||
<< ", hard_remove option "
|
<< ", hard_remove option "
|
||||||
"is probably in effect";
|
"is probably in effect";
|
||||||
res = -EBUSY;
|
return -EBUSY;
|
||||||
} else {
|
}
|
||||||
string fullName = rootDir + cyName;
|
#endif
|
||||||
res = ::unlink(fullName.c_str());
|
|
||||||
if (res == -1) {
|
int res = 0;
|
||||||
res = -errno;
|
string fullName = rootDir + cyName;
|
||||||
VLOG(1) << "unlink error: " << strerror(-res);
|
res = ::unlink(fullName.c_str());
|
||||||
}
|
if (res == -1) {
|
||||||
|
res = -errno;
|
||||||
|
VLOG(1) << "unlink error: " << strerror(-res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -6,6 +6,13 @@
|
|||||||
#include "easylogging++.h"
|
#include "easylogging++.h"
|
||||||
#include <stdexcept>
|
#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 {
|
namespace encfs {
|
||||||
|
|
||||||
class Error : public std::runtime_error {
|
class Error : public std::runtime_error {
|
||||||
|
@ -1089,7 +1089,7 @@ RootPtr createV6Config(EncFS_Context *ctx,
|
|||||||
alg = findCipherAlgorithm("AES", keySize);
|
alg = findCipherAlgorithm("AES", keySize);
|
||||||
|
|
||||||
// If case-insensitive system, opt for Block32 filename encoding
|
// If case-insensitive system, opt for Block32 filename encoding
|
||||||
#if defined(__APPLE__) || defined(WIN32)
|
#if defined(DEFAULT_CASE_INSENSITIVE)
|
||||||
nameIOIface = BlockNameIO::CurrentInterface(true);
|
nameIOIface = BlockNameIO::CurrentInterface(true);
|
||||||
#else
|
#else
|
||||||
nameIOIface = BlockNameIO::CurrentInterface();
|
nameIOIface = BlockNameIO::CurrentInterface();
|
||||||
@ -1739,6 +1739,14 @@ void unmountFS(const char *mountPoint) {
|
|||||||
// fuse_unmount does not work on Mac OS, see #428
|
// fuse_unmount does not work on Mac OS, see #428
|
||||||
unmount(mountPoint, MNT_FORCE);
|
unmount(mountPoint, MNT_FORCE);
|
||||||
#endif
|
#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) {
|
int remountFS(EncFS_Context *ctx) {
|
||||||
|
@ -72,6 +72,7 @@ enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };
|
|||||||
struct EncFS_Opts {
|
struct EncFS_Opts {
|
||||||
std::string rootDir;
|
std::string rootDir;
|
||||||
std::string mountPoint; // where to make filesystem visible
|
std::string mountPoint; // where to make filesystem visible
|
||||||
|
std::string cygDrive; // Cygwin mount drive
|
||||||
bool createIfNotFound; // create filesystem if not found
|
bool createIfNotFound; // create filesystem if not found
|
||||||
bool idleTracking; // turn on idle monitoring of filesystem
|
bool idleTracking; // turn on idle monitoring of filesystem
|
||||||
bool mountOnDemand; // mounting on-demand
|
bool mountOnDemand; // mounting on-demand
|
||||||
|
@ -167,6 +167,13 @@ static int withFileNode(const char *opName, const char *path,
|
|||||||
if (fi != nullptr && fi->fh != 0) {
|
if (fi != nullptr && fi->fh != 0) {
|
||||||
auto node = ctx->lookupFuseFh(fi->fh);
|
auto node = ctx->lookupFuseFh(fi->fh);
|
||||||
if (node == nullptr) {
|
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";
|
auto msg = "fh=" + std::to_string(fi->fh) + " not found in fuseFhMap";
|
||||||
throw Error(msg.c_str());
|
throw Error(msg.c_str());
|
||||||
}
|
}
|
||||||
|
@ -649,6 +649,8 @@ Support, bug reports... : B<https://github.com/vgough/encfs>.
|
|||||||
|
|
||||||
Mailing list : none.
|
Mailing list : none.
|
||||||
|
|
||||||
|
Cygwin : B<https://github.com/vgough/encfs/wiki>.
|
||||||
|
|
||||||
Windows port : B<https://github.com/jetwhiz/encfs4win>.
|
Windows port : B<https://github.com/jetwhiz/encfs4win>.
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
@ -380,6 +380,11 @@ static bool processArgs(int argc, char *argv[],
|
|||||||
/* Disable kernel dentry cache
|
/* Disable kernel dentry cache
|
||||||
* Fallout unknown, disabling for safety */
|
* Fallout unknown, disabling for safety */
|
||||||
PUSHARG("-oentry_timeout=0");
|
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;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
out->opts->mountOnDemand = true;
|
out->opts->mountOnDemand = true;
|
||||||
@ -542,18 +547,38 @@ static bool processArgs(int argc, char *argv[],
|
|||||||
if (!isDirectory(out->opts->rootDir.c_str()) &&
|
if (!isDirectory(out->opts->rootDir.c_str()) &&
|
||||||
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(),
|
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(),
|
||||||
0700)) {
|
0700)) {
|
||||||
cerr << _("Unable to locate root directory, aborting.");
|
cerr << _("Unable to locate root directory, aborting.") << endl;
|
||||||
return false;
|
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()) &&
|
if (!isDirectory(out->opts->mountPoint.c_str()) &&
|
||||||
!userAllowMkdir(out->opts->annotate ? 2 : 0,
|
!userAllowMkdir(out->opts->annotate ? 2 : 0,
|
||||||
out->opts->mountPoint.c_str(), 0700)) {
|
out->opts->mountPoint.c_str(), 0700)) {
|
||||||
cerr << _("Unable to locate mount point, aborting.");
|
cerr << _("Unable to locate mount point, aborting.") << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// fill in mount path for fuse
|
// fill in mount path for fuse
|
||||||
out->fuseArgv[1] = out->opts->mountPoint.c_str();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,10 @@ sub newWorkingDir
|
|||||||
|
|
||||||
our $raw = "$workingDir/raw";
|
our $raw = "$workingDir/raw";
|
||||||
our $crypt = "$workingDir/crypt";
|
our $crypt = "$workingDir/crypt";
|
||||||
|
if ($^O eq "cygwin")
|
||||||
|
{
|
||||||
|
$crypt = "/cygdrive/x";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test Corruption
|
# Test Corruption
|
||||||
@ -124,7 +128,8 @@ sub corruption
|
|||||||
ok( open(IN, "< $crypt/corrupt"), "open corrupted file");
|
ok( open(IN, "< $crypt/corrupt"), "open corrupted file");
|
||||||
my $content;
|
my $content;
|
||||||
$result = read(IN, $content, 20);
|
$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
|
# Test internal modification
|
||||||
@ -363,7 +368,10 @@ sub mount
|
|||||||
|
|
||||||
# When these fail, the rest of the tests makes no sense
|
# When these fail, the rest of the tests makes no sense
|
||||||
mkdir($raw) || BAIL_OUT("Could not create $raw: $!");
|
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"};
|
delete $ENV{"ENCFS6_CONFIG"};
|
||||||
remount($args);
|
remount($args);
|
||||||
@ -425,8 +433,15 @@ sub create_unmount_remount
|
|||||||
{
|
{
|
||||||
my $crypt = "$workingDir/create_remount.crypt";
|
my $crypt = "$workingDir/create_remount.crypt";
|
||||||
my $mnt = "$workingDir/create_remount.mnt";
|
my $mnt = "$workingDir/create_remount.mnt";
|
||||||
|
if ($^O eq "cygwin")
|
||||||
|
{
|
||||||
|
$mnt = "/cygdrive/y";
|
||||||
|
}
|
||||||
mkdir($crypt) || BAIL_OUT($!);
|
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");
|
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
||||||
ok( $? == 0, "encfs command returns 0") || return;
|
ok( $? == 0, "encfs command returns 0") || return;
|
||||||
@ -472,8 +487,15 @@ sub checkWriteError
|
|||||||
else {
|
else {
|
||||||
my $crypt = "$workingDir/checkWriteError.crypt";
|
my $crypt = "$workingDir/checkWriteError.crypt";
|
||||||
my $mnt = "$workingDir/checkWriteError.mnt";
|
my $mnt = "$workingDir/checkWriteError.mnt";
|
||||||
|
if ($^O eq "cygwin")
|
||||||
|
{
|
||||||
|
$mnt = "/cygdrive/z";
|
||||||
|
}
|
||||||
mkdir($crypt) || BAIL_OUT($!);
|
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");
|
system("$sudo_cmd mount -t tmpfs -o size=1m tmpfs $crypt");
|
||||||
ok( $? == 0, "mount command returns 0") || return;
|
ok( $? == 0, "mount command returns 0") || return;
|
||||||
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
||||||
|
@ -49,9 +49,23 @@ sub newWorkingDir
|
|||||||
our $plain = "$workingDir/plain";
|
our $plain = "$workingDir/plain";
|
||||||
mkdir($plain);
|
mkdir($plain);
|
||||||
our $ciphertext = "$workingDir/ciphertext";
|
our $ciphertext = "$workingDir/ciphertext";
|
||||||
mkdir($ciphertext);
|
if ($^O ne "cygwin")
|
||||||
|
{
|
||||||
|
mkdir($ciphertext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ciphertext = "/cygdrive/x";
|
||||||
|
}
|
||||||
our $decrypted = "$workingDir/decrypted";
|
our $decrypted = "$workingDir/decrypted";
|
||||||
mkdir($decrypted);
|
if ($^O ne "cygwin")
|
||||||
|
{
|
||||||
|
mkdir($decrypted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$decrypted = "/cygdrive/y";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helper function
|
# Helper function
|
||||||
@ -231,7 +245,14 @@ encfsctl_cat_test();
|
|||||||
symlink_test("/"); # absolute
|
symlink_test("/"); # absolute
|
||||||
symlink_test("foo"); # relative
|
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("/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");
|
symlink_test("$plain/foo");
|
||||||
writesDenied();
|
writesDenied();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user